diff --git a/.dockerignore b/.dockerignore index 4b33ec5099..2e6259d23d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,7 +17,7 @@ TGS3.json cfg data SQL -tgui/node_modules +node_modules tgstation.dmb tgstation.int tgstation.rsc diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e14c5d1624..643b4d6e64 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -257,6 +257,12 @@ This prevents nesting levels from getting deeper then they need to be. * Please attempt to clean out any dirty variables that may be contained within items you alter through var-editing. For example, due to how DM functions, changing the `pixel_x` variable from 23 to 0 will leave a dirty record in the map's code of `pixel_x = 0`. Likewise this can happen when changing an item's icon to something else and then back. This can lead to some issues where an item's icon has changed within the code, but becomes broken on the map due to it still attempting to use the old entry. * Areas should not be var-edited on a map to change it's name or attributes. All areas of a single type and it's altered instances are considered the same area within the code, and editing their variables on a map can lead to issues with powernets and event subsystems which are difficult to debug. +### User Interfaces +* All new player-facing user interfaces must use TGUI. +* Raw HTML is permitted for admin and debug UIs. +* Documentation for TGUI can be found at: + * [tgui/README.md](../tgui/README.md) + * [tgui/tutorial-and-examples.md](../tgui/docs/tutorial-and-examples.md) ### Other Notes * Code should be modular where possible; if you are working on a new addition, then strongly consider putting it in its own file unless it makes sense to put it with similar ones (i.e. a new tool would go in the "tools.dm" file) @@ -337,7 +343,7 @@ for(var/obj/item/sword/S in bag_of_swords) if(!best_sword || S.damage > best_sword.damage) best_sword = S ``` -specifies a type for DM to filter by. +specifies a type for DM to filter by. With the previous example that's perfectly fine, we only want swords, but here the bag only contains swords? Is DM still going to try to filter because we gave it a type to filter by? YES, and here comes the inefficiency. Wherever a list (or other container, such as an atom (in which case you're technically accessing their special contents list, but that's irrelevant)) contains datums of the same datatype or subtypes of the datatype you require for your loop's body, you can circumvent DM's filtering and automatic ```istype()``` checks by writing the loop as such: @@ -374,7 +380,7 @@ mob ``` This does NOT mean that you can access it everywhere like a global var. Instead, it means that that var will only exist once for all instances of its type, in this case that var will only exist once for all mobs - it's shared across everything in its type. (Much more like the keyword `static` in other languages like PHP/C++/C#/Java) -Isn't that confusing? +Isn't that confusing? There is also an undocumented keyword called `static` that has the same behaviour as global but more correctly describes BYOND's behaviour. Therefore, we always use static instead of global where we need it, as it reduces suprise when reading BYOND code. @@ -394,6 +400,10 @@ There is no strict process when it comes to merging pull requests. Pull requests * Please explain why you are submitting the pull request, and how you think your change will be beneficial to the game. Failure to do so will be grounds for rejecting the PR. +* If your pull request is not finished make sure it is at least testable in a live environment. Pull requests that do not at least meet this requirement will be closed. You may request a maintainer reopen the pull request when you're ready, or make a new one. + +* While we have no issue helping contributors (and especially new contributors) bring reasonably sized contributions up to standards via the pull request review process, larger contributions are expected to pass a higher bar of completeness and code quality *before* you open a pull request. Maintainers may close such pull requests that are deemed to be substantially flawed. You should take some time to discuss with maintainers or other contributors on how to improve the changes. + ## Porting features/sprites/sounds/tools from other codebases If you are porting features/tools from other codebases, you must give them credit where it's due. Typically, crediting them in your pull request and the changelog is the recommended way of doing it. Take note of what license they use though, porting stuff from AGPLv3 and GPLv3 codebases are allowed. @@ -404,10 +414,17 @@ Regarding sprites & sounds, you must credit the artist and possibly the codebase Do not add any of the following in a Pull Request or risk getting the PR closed: * National Socialist Party of Germany content, National Socialist Party of Germany related content, or National Socialist Party of Germany references * Code where one line of code is split across mutiple lines (except for multiple, separate strings and comments; in those cases, existing longer lines must not be split up) -* Code adding, removing, or updating the availability of alien races/species/human mutants without prior approval. Pull requests attempting to add or remove features from said races/species/mutants require prior approval as well. Just because something isn't on this list doesn't mean that it's acceptable. Use common sense above all else. +## Content requiring prior approval +Certain types of changes may require prior approval from maintainers. This currently includes: + +* Code adding, removing, or updating the availability of alien races/species/human mutants. This includes pull requests attempting to add or remove features from said races/species/mutants. (Requires approval from at least one maintainer) +* Code adding, removing, or modifying the functionality of adult-oriented features (such as, but not limited to: vore, genitals, MKUltra, and more). This also includes pull requests attempting to add or remove these features outright. (Requires approval from at least half of the formal maintainer team) + +The above content requires approval from the specified amount of maintainers prior to PR creation. Seeking approval must be done via a @Maintainer ping in a relevant development/code or staff channel on the Discord, otherwise it will be considered insufficient. If a PR contains any of the above content, but the creator does not have sufficient approval prior to the PR's creation, then the PR may be closed by any maintainer, at any time, for any reason. + ## A word on Git Yes, we know that the files have a tonne of mixed Windows and Linux line endings. Attempts to fix this have been met with less than stellar success, and as such we have decided to give up caring until there comes a time when it matters. diff --git a/.github/workflows/autobuild_tgui.yml b/.github/workflows/autobuild_tgui.yml index b680139f74..226ea2b7ce 100644 --- a/.github/workflows/autobuild_tgui.yml +++ b/.github/workflows/autobuild_tgui.yml @@ -5,8 +5,8 @@ on: branches: - 'master' paths: - - 'tgui-next/**.js' - - 'tgui-next/**.scss' + - 'tgui/**.js' + - 'tgui/**.scss' jobs: build: @@ -23,7 +23,7 @@ jobs: node-version: '>=12.13' - name: Build TGUI run: bin/tgui --ci - working-directory: ./tgui-next + working-directory: ./tgui - name: Commit Artifacts run: | git config --local user.email "action@github.com" diff --git a/.travis.yml b/.travis.yml index 3082e1a18e..2214df3aee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ matrix: - tools/travis/check_filedirs.sh tgstation.dme - tools/travis/check_changelogs.sh - find . -name "*.php" -print0 | xargs -0 -n1 php -l - - find . -name "*.json" -not -path "./tgui/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py + - find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py - tools/travis/build_tgui.sh - tools/travis/check_grep.sh - python3 tools/travis/check_line_endings.py diff --git a/_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm b/_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm index bddadc7b0c..f1b0582ec3 100644 --- a/_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm +++ b/_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm @@ -2,156 +2,172 @@ "a" = ( /turf/template_noop, /area/template_noop) -"b" = ( -/turf/closed/wall/mineral/cult, -/area/ruin/unpowered) "c" = ( /obj/structure/healingfountain, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/purple, /area/ruin/unpowered) "d" = ( /obj/structure/fluff/divine/conduit, -/turf/open/floor/engine/cult, +/turf/open/floor/mineral/plasma, /area/ruin/unpowered) "e" = ( /obj/structure/sacrificealtar, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/purple, /area/ruin/unpowered) "f" = ( -/turf/open/floor/engine/cult, +/mob/living/simple_animal/butterfly, +/turf/open/floor/carpet/purple, /area/ruin/unpowered) "g" = ( /mob/living/simple_animal/butterfly, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/red, /area/ruin/unpowered) "h" = ( /obj/structure/fans/tiny/invisible, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/red, +/area/ruin/unpowered) +"u" = ( +/turf/open/floor/carpet/purple, +/area/ruin/unpowered) +"G" = ( +/turf/closed/wall/mineral/cult{ + sheet_amount = 0 + }, +/area/ruin/unpowered) +"J" = ( +/mob/living/simple_animal/butterfly, +/turf/open/floor/carpet/royalblack, +/area/ruin/unpowered) +"T" = ( +/turf/open/floor/carpet/royalblack, +/area/ruin/unpowered) +"U" = ( +/turf/open/floor/carpet/red, /area/ruin/unpowered) (1,1,1) = {" a -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b +G +G +G +G +G +G +G +G +G +G +G +G +G +G +G "} (2,1,1) = {" a -b +G d -f -f +U +T +T +T +J +T +T +T +T +T +T d -f -f -d -f -f -d -f -f -d -b +G "} (3,1,1) = {" -b -b +G +G e g -f -f +U +d g -f -f -f -f -g -f -g -f -b +U +d +U +U +d +U +U +u +G "} (4,1,1) = {" -b +G c f -f -f -f -f -f -f -f -f -f -f -f -f +U +T +u +T +T +u +T +T +u +T +T +T h "} (5,1,1) = {" -b -b +G +G e -f -f -f -f g -f -f -f -f -f -f -f -b +U +d +g +U +d +U +U +d +U +U +u +G "} (6,1,1) = {" a -b +G d -g -f +U +T +T +T +J +T +T +T +T +T +T d -f -f -d -f -f -d -f -g -d -b +G "} (7,1,1) = {" a -b -b -b -b -b -b -b -b -b -b -b -b -b -b -b +G +G +G +G +G +G +G +G +G +G +G +G +G +G +G "} diff --git a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm index d01e4f8da1..37a89ba2ff 100644 --- a/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm +++ b/_maps/RandomRuins/AnywhereRuins/golem_ship.dmm @@ -18,9 +18,7 @@ /obj/item/mining_scanner, /obj/item/flashlight/lantern, /obj/item/card/id/mining, -/obj/item/gps/mining{ - tracking = 0 - }, +/obj/item/gps/mining, /turf/open/floor/plating, /area/ruin/powered/golem_ship) "d" = ( @@ -34,9 +32,7 @@ /obj/item/mining_scanner, /obj/item/flashlight/lantern, /obj/item/card/id/mining, -/obj/item/gps/mining{ - tracking = 0 - }, +/obj/item/gps/mining, /turf/open/floor/plating, /area/ruin/powered/golem_ship) "e" = ( @@ -156,9 +152,7 @@ "x" = ( /obj/structure/table/wood, /obj/machinery/reagentgrinder, -/obj/item/gps/mining{ - tracking = 0 - }, +/obj/item/gps/mining, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) "z" = ( diff --git a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm index 969acdd871..23abc4b731 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_surface_mining_site.dmm @@ -16,7 +16,7 @@ /turf/open/floor/wood, /area/ruin/unpowered) "d" = ( -/turf/open/openspace/icemoon, +/turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors) "e" = ( /obj/item/clothing/suit/hooded/explorer, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm index a43e6129b7..7e9ce9db68 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_biodome_beach.dmm @@ -42,6 +42,10 @@ "ak" = ( /obj/structure/toilet, /obj/effect/turf_decal/sand, +/obj/item/reagent_containers/food/drinks/beer/light{ + pixel_x = 9 + }, +/obj/effect/decal/cleanable/vomit/old, /turf/open/floor/plating, /area/ruin/powered/beach) "al" = ( @@ -191,7 +195,9 @@ /turf/open/floor/plasteel, /area/ruin/powered/beach) "aM" = ( -/obj/structure/reagent_dispensers/beerkeg, +/obj/structure/reagent_dispensers/beerkeg{ + reagent_id = /datum/reagent/consumable/ethanol/beer/light + }, /turf/open/floor/wood, /area/ruin/powered/beach) "aN" = ( @@ -371,7 +377,7 @@ /turf/open/floor/plating/beach/sand, /area/ruin/powered/beach) "bP" = ( -/obj/item/reagent_containers/food/drinks/beer, +/obj/item/reagent_containers/food/drinks/beer/light, /turf/open/floor/plating/beach/sand, /area/ruin/powered/beach) "bQ" = ( @@ -463,6 +469,7 @@ /obj/item/storage/box/drinkingglasses, /obj/item/storage/box/beakers, /obj/item/storage/box/donkpockets, +/obj/item/soap, /turf/open/floor/plating, /area/ruin/powered/beach) "hY" = ( @@ -537,6 +544,14 @@ }, /turf/open/floor/pod/light, /area/ruin/powered/beach) +"rV" = ( +/obj/effect/turf_decal/sand, +/obj/item/reagent_containers/food/drinks/beer/light{ + pixel_y = -3; + pixel_x = -9 + }, +/turf/open/floor/plating, +/area/ruin/powered/beach) "sy" = ( /obj/effect/turf_decal/caution{ dir = 4 @@ -590,6 +605,11 @@ /obj/effect/turf_decal/sand, /turf/open/floor/pod/light, /area/ruin/powered/beach) +"Gu" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/beer/light, +/turf/open/floor/wood, +/area/ruin/powered/beach) "HC" = ( /obj/structure/rack, /obj/item/clothing/shoes/sandal, @@ -964,7 +984,7 @@ ar ar ar ar -ar +bP ar bR bT @@ -984,7 +1004,7 @@ as aw aC aC -aP +Gu aW aK Ga @@ -1108,7 +1128,7 @@ aa aa bW ak -au +rV aj aE aC diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm index 862c745f81..eab08815f3 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm @@ -188,13 +188,13 @@ /area/ruin/unpowered/xenonest) "aT" = ( /obj/structure/alien/weeds, -/obj/item/twohanded/required/chainsaw, +/obj/item/chainsaw, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/xenonest) "aU" = ( /obj/structure/alien/weeds, /obj/structure/bed/nest, -/obj/item/twohanded/fireaxe/boneaxe, +/obj/item/fireaxe/boneaxe, /obj/item/clothing/head/helmet/gladiator, /obj/item/clothing/mask/facehugger/impregnated, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, @@ -219,6 +219,7 @@ /obj/structure/alien/weeds, /obj/effect/decal/cleanable/blood/gibs, /mob/living/simple_animal/hostile/alien/drone, +/obj/structure/alien/weeds/node, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/xenonest) "aZ" = ( @@ -226,7 +227,7 @@ /area/ruin/unpowered/xenonest) "ba" = ( /obj/structure/stone_tile/slab, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bb" = ( /obj/structure/stone_tile/cracked{ @@ -240,7 +241,7 @@ dir = 8 }, /obj/item/flashlight/lantern, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bc" = ( /obj/structure/stone_tile/block, @@ -250,7 +251,7 @@ /obj/structure/stone_tile{ dir = 4 }, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bd" = ( /obj/structure/stone_tile/block, @@ -261,7 +262,7 @@ dir = 1 }, /obj/effect/decal/cleanable/blood/xeno, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "be" = ( /obj/structure/stone_tile/block, @@ -271,7 +272,7 @@ /obj/structure/stone_tile{ dir = 1 }, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bf" = ( /obj/structure/stone_tile, @@ -285,7 +286,7 @@ dir = 4 }, /obj/item/flashlight/lantern, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bg" = ( /obj/structure/alien/weeds, @@ -302,7 +303,7 @@ /obj/structure/stone_tile{ dir = 8 }, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bi" = ( /obj/structure/alien/weeds, @@ -335,11 +336,11 @@ dir = 1 }, /obj/structure/stone_tile, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bm" = ( /obj/structure/stone_tile/slab/cracked, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bn" = ( /obj/structure/stone_tile/block{ @@ -351,7 +352,7 @@ /obj/structure/stone_tile{ dir = 4 }, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bo" = ( /obj/structure/stone_tile/surrounding_tile{ @@ -382,7 +383,7 @@ dir = 1 }, /obj/effect/decal/cleanable/blood/xeno, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bs" = ( /obj/structure/stone_tile/block{ @@ -415,7 +416,7 @@ dir = 1 }, /obj/structure/stone_tile/cracked, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bw" = ( /obj/structure/stone_tile/cracked{ @@ -429,7 +430,7 @@ dir = 8 }, /obj/item/flashlight/lantern, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bx" = ( /obj/structure/stone_tile/block{ @@ -440,7 +441,7 @@ dir = 8 }, /obj/effect/decal/cleanable/blood/xeno, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "by" = ( /obj/structure/stone_tile/block{ @@ -450,7 +451,7 @@ /obj/structure/stone_tile/cracked{ dir = 8 }, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bz" = ( /obj/structure/stone_tile/block/cracked{ @@ -460,7 +461,7 @@ /obj/structure/stone_tile{ dir = 8 }, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bA" = ( /obj/structure/stone_tile/cracked{ @@ -474,7 +475,7 @@ }, /obj/structure/stone_tile, /obj/item/flashlight/lantern, -/turf/open/indestructible/boss/air, +/turf/open/indestructible/boss, /area/ruin/unpowered/xenonest) "bB" = ( /obj/structure/alien/weeds, @@ -535,6 +536,11 @@ /obj/effect/mob_spawn/alien/corpse/humanoid/queen, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/xenonest) +"wA" = ( +/obj/structure/alien/weeds, +/obj/structure/alien/weeds/node, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/xenonest) "yf" = ( /obj/structure/alien/weeds/node, /mob/living/simple_animal/hostile/alien/sentinel, @@ -551,6 +557,12 @@ /obj/effect/mob_spawn/alien/corpse/humanoid/drone, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/xenonest) +"QG" = ( +/obj/structure/alien/weeds, +/obj/structure/bed/nest, +/obj/structure/alien/weeds/node, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/xenonest) "Uh" = ( /obj/structure/alien/weeds, /obj/item/xenos_claw, @@ -683,7 +695,7 @@ ac ac aj ac -am +QG ac ac ac @@ -800,7 +812,7 @@ ac ac ac ac -ag +wA ag ag ar @@ -884,7 +896,7 @@ aa (7,1,1) = {" ab ac -ag +wA ag ag ag @@ -917,7 +929,7 @@ ac ac ZT ac -ag +wA ag ac ab @@ -1349,7 +1361,7 @@ ar lG ag ag -ag +wA ad ag ag @@ -1555,7 +1567,7 @@ ag ac aF ag -ag +ar ag ag ar @@ -1603,7 +1615,7 @@ ao ah ac ag -ag +wA ag ag pE @@ -1742,7 +1754,7 @@ ag ag ag ag -ac +aw ar ag bD @@ -1791,9 +1803,9 @@ ac ac ac ac +wA ag -ag -ac +aw ar ag bD @@ -1828,7 +1840,7 @@ ac ac ag Uh -ag +wA aZ be bo diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm index 60ae409ea2..527a328563 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_animal_hospital.dmm @@ -517,7 +517,7 @@ /turf/open/floor/plasteel, /area/ruin/powered/animal_hospital) "bt" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/plasteel, /area/ruin/powered/animal_hospital) "bu" = ( diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm index 80ad86e3c5..39ecc54ec7 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm @@ -724,7 +724,7 @@ /area/lavaland/surface/outdoors) "bP" = ( /obj/structure/stone_tile/block, -/obj/item/twohanded/spear, +/obj/item/spear, /obj/effect/mapping_helpers/no_lava, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) @@ -896,7 +896,7 @@ /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "ck" = ( -/obj/item/twohanded/spear, +/obj/item/spear, /obj/structure/stone_tile{ dir = 4 }, @@ -910,7 +910,7 @@ /obj/structure/stone_tile/cracked{ dir = 8 }, -/obj/item/twohanded/spear, +/obj/item/spear, /obj/effect/mapping_helpers/no_lava, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) @@ -1014,7 +1014,7 @@ /obj/structure/stone_tile/cracked{ dir = 1 }, -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) "cA" = ( @@ -1058,7 +1058,7 @@ dir = 1 }, /obj/structure/table/wood, -/obj/item/twohanded/spear, +/obj/item/spear, /obj/item/storage/belt, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) @@ -1100,7 +1100,7 @@ dir = 4 }, /obj/structure/table/wood, -/obj/item/twohanded/spear, +/obj/item/spear, /obj/item/scythe, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) @@ -1128,7 +1128,7 @@ dir = 4 }, /obj/structure/table/wood, -/obj/item/twohanded/spear, +/obj/item/spear, /obj/item/clothing/head/helmet/roman/legionnaire, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm index b71b6838b0..c7ae4c6eb4 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_biodome_winter.dmm @@ -203,6 +203,12 @@ /area/ruin/powered/snow_biodome) "aR" = ( /obj/structure/flora/tree/pine/xmas, +/obj/item/a_gift{ + pixel_y = -5 + }, +/obj/item/a_gift{ + pixel_x = 6 + }, /turf/open/floor/plating/asteroid/snow{ initial_gas_mix = "o2=22;n2=82;TEMP=180" }, @@ -295,6 +301,12 @@ }, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) +"gy" = ( +/obj/item/toy/snowball, +/turf/open/floor/plating/asteroid/snow{ + initial_gas_mix = "o2=22;n2=82;TEMP=180" + }, +/area/ruin/powered/snow_biodome) "gz" = ( /obj/structure/chair/stool, /turf/open/floor/pod/dark, @@ -316,6 +328,13 @@ }, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) +"rl" = ( +/obj/structure/flora/bush, +/obj/item/toy/snowball, +/turf/open/floor/plating/asteroid/snow{ + initial_gas_mix = "o2=22;n2=82;TEMP=180" + }, +/area/ruin/powered/snow_biodome) "tb" = ( /obj/effect/mapping_helpers/no_lava, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, @@ -361,13 +380,18 @@ /obj/structure/closet/secure_closet/freezer/fridge, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) +"IQ" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug, +/turf/open/floor/wood, +/area/ruin/powered/snow_biodome) "JZ" = ( /obj/structure/table, /obj/machinery/microwave, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) "KS" = ( -/obj/item/twohanded/required/chainsaw, +/obj/item/chainsaw, /obj/structure/closet, /obj/machinery/light/small{ dir = 4 @@ -380,6 +404,7 @@ /area/ruin/powered/snow_biodome) "Oj" = ( /obj/structure/table, +/obj/item/reagent_containers/food/drinks/mug, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) "PD" = ( @@ -407,6 +432,7 @@ "QK" = ( /obj/structure/table, /obj/item/storage/fancy/cigarettes/cigpack_carp, +/obj/item/reagent_containers/food/drinks/mug, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) "QN" = ( @@ -417,6 +443,13 @@ /obj/effect/decal/cleanable/oil, /turf/open/floor/pod/dark, /area/ruin/powered/snow_biodome) +"SL" = ( +/obj/structure/flora/grass/both, +/obj/item/toy/snowball, +/turf/open/floor/plating/asteroid/snow{ + initial_gas_mix = "o2=22;n2=82;TEMP=180" + }, +/area/ruin/powered/snow_biodome) "Ub" = ( /obj/structure/filingcabinet, /turf/open/floor/pod/dark, @@ -577,7 +610,7 @@ aB ak ak ak -aI +rl by ak ak @@ -740,7 +773,7 @@ aI az ak ak -ak +gy ak ak aI @@ -916,7 +949,7 @@ Wg ag ah as -aw +IQ aA aA at @@ -924,7 +957,7 @@ aM aP ak ak -aQ +SL ak ak az @@ -1077,7 +1110,7 @@ Wg an Wg ay -ak +gy ak ak ak @@ -1114,6 +1147,7 @@ aI ak ap ak +gy ak ak ak @@ -1121,8 +1155,7 @@ ak ak ak ak -ak -ak +gy ak aI ak @@ -1240,7 +1273,7 @@ ak ak az ak -ak +gy ak bB ak diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_envy.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_envy.dmm index df9620cb67..a14a8d3a13 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_envy.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_envy.dmm @@ -11,7 +11,7 @@ "d" = ( /turf/closed/wall/rust, /area/ruin/unpowered) -"e" = ( +"f" = ( /obj/structure/mirror{ desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!"; icon_state = "mirror_broke"; @@ -22,17 +22,6 @@ /obj/effect/decal/cleanable/blood, /turf/open/floor/plating, /area/ruin/unpowered) -"f" = ( -/obj/structure/mirror{ - desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!"; - icon_state = "mirror_broke"; - pixel_x = 28; - broken = 1 - }, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/ruin/unpowered) "g" = ( /obj/effect/decal/cleanable/blood/tracks, /obj/structure/mirror{ @@ -58,11 +47,12 @@ /obj/structure/mirror{ desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!"; icon_state = "mirror_broke"; - pixel_y = 28; + pixel_x = 28; broken = 1 }, -/obj/item/kitchen/knife/envy, -/turf/open/floor/plating, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, /area/ruin/unpowered) "l" = ( /obj/structure/mirror{ @@ -106,6 +96,16 @@ /obj/effect/mapping_helpers/no_lava, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) +"T" = ( +/obj/structure/mirror{ + desc = "This mirror has been shattered. It looks like the bad luck energies spilling from it are taking immediate effect on your surroundings!"; + icon_state = "mirror_broke"; + pixel_y = 28; + broken = 1 + }, +/obj/item/kitchen/knife/envy, +/turf/open/floor/plating, +/area/ruin/unpowered) (1,1,1) = {" a @@ -125,14 +125,8 @@ a a a a -a -a -a "} (2,1,1) = {" -a -a -c c c c @@ -167,9 +161,6 @@ d d d d -d -d -d c a "} @@ -178,16 +169,13 @@ c c d d -d -e +f g g g m m m -m -m o m j @@ -201,14 +189,11 @@ d d d d -d h h i i i -i -i h i i @@ -224,10 +209,7 @@ d d d d -d -k -i -i +T i i i @@ -245,12 +227,9 @@ d d d d -d i i i -j -i n i i @@ -266,8 +245,7 @@ c c d d -d -f +k j l l @@ -276,8 +254,6 @@ l l l l -l -l j d c @@ -299,9 +275,6 @@ d d d d -d -d -d c a "} @@ -322,8 +295,5 @@ c c c c -c -c -c a "} diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm index d587d19b97..70ffdc85cd 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_gluttony.dmm @@ -20,7 +20,7 @@ /turf/open/floor/plasteel/freezer, /area/ruin/powered/gluttony) "h" = ( -/obj/item/veilrender/vealrender, +/obj/item/trash/boritos, /turf/open/floor/plasteel/freezer, /area/ruin/powered/gluttony) "i" = ( @@ -65,6 +65,7 @@ /obj/machinery/light/small{ dir = 1 }, +/obj/item/trash/plate/alt, /turf/open/floor/plasteel/freezer, /area/ruin/powered/gluttony) "v" = ( @@ -84,6 +85,28 @@ }, /turf/open/floor/plasteel/freezer, /area/ruin/powered/gluttony) +"B" = ( +/obj/item/veilrender/vealrender, +/turf/open/floor/plasteel/freezer, +/area/ruin/powered/gluttony) +"E" = ( +/obj/machinery/light/small, +/obj/item/trash/cheesie, +/turf/open/floor/plasteel/freezer, +/area/ruin/powered/gluttony) +"G" = ( +/obj/item/trash/waffles, +/turf/open/floor/plasteel/freezer, +/area/ruin/powered/gluttony) +"L" = ( +/obj/machinery/light/small, +/obj/item/trash/plate/alt, +/turf/open/floor/plasteel/freezer, +/area/ruin/powered/gluttony) +"N" = ( +/obj/item/trash/cheesie, +/turf/open/floor/plasteel/freezer, +/area/ruin/powered/gluttony) "R" = ( /turf/closed/indestructible/riveted/uranium, /area/ruin/powered/gluttony) @@ -92,6 +115,10 @@ /obj/structure/fans/tiny/invisible, /turf/open/floor/plasteel/freezer, /area/ruin/powered/gluttony) +"Z" = ( +/obj/item/trash/plate/alt, +/turf/open/floor/plasteel/freezer, +/area/ruin/powered/gluttony) (1,1,1) = {" a @@ -191,7 +218,7 @@ b b c R -h +j i o R @@ -213,9 +240,9 @@ b b c R -i -i -v +h +G +L R c b @@ -258,7 +285,7 @@ c c R t -i +N m R c @@ -305,10 +332,10 @@ g g i p -i +G z l -i +Z R c b @@ -324,10 +351,10 @@ g g g g +B n i -i -i +h i i i @@ -346,12 +373,12 @@ r g g g -i +N g i l A -i +Z q R c @@ -368,7 +395,7 @@ R R R g -i +h v R R @@ -391,7 +418,7 @@ c R r i -i +q R c c @@ -435,7 +462,7 @@ c R j i -v +E R c b diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_greed.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_greed.dmm index df450b9803..671fdd54d6 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_greed.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_greed.dmm @@ -20,9 +20,7 @@ /area/ruin/powered/greed) "f" = ( /obj/structure/cursed_slot_machine, -/turf/open/floor/carpet{ - icon_state = "carpetsymbol" - }, +/turf/open/floor/carpet/black, /area/ruin/powered/greed) "g" = ( /obj/structure/table/wood/poker, @@ -41,11 +39,6 @@ icon_state = "carpetsymbol" }, /area/ruin/powered/greed) -"i" = ( -/turf/open/floor/carpet{ - icon_state = "carpetsymbol" - }, -/area/ruin/powered/greed) "j" = ( /obj/structure/table/wood/poker, /obj/item/coin/adamantine, @@ -57,28 +50,28 @@ /obj/machinery/computer/arcade/battle{ set_obj_flags = "EMAGGED" }, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/black, /area/ruin/powered/greed) "l" = ( /obj/item/coin/gold, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/black, /area/ruin/powered/greed) "m" = ( -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/black, /area/ruin/powered/greed) "n" = ( /obj/structure/table/wood/poker, /obj/item/stack/spacecash/c1000, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet, /area/ruin/powered/greed) "o" = ( /obj/item/storage/bag/money, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/black, /area/ruin/powered/greed) "p" = ( /obj/structure/table/wood/poker, /obj/item/stack/ore/gold, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet, /area/ruin/powered/greed) "q" = ( /obj/structure/table/wood/poker, @@ -88,19 +81,19 @@ brightness = 3; dir = 8 }, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet, /area/ruin/powered/greed) "r" = ( /obj/structure/table/wood/poker, /obj/item/stack/spacecash/c500, /obj/item/stack/spacecash/c100, /obj/item/stack/spacecash/c1000, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet, /area/ruin/powered/greed) "s" = ( /obj/structure/table/wood/poker, /obj/item/stack/spacecash/c200, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet, /area/ruin/powered/greed) "u" = ( /obj/structure/table/wood/poker, @@ -110,25 +103,30 @@ /obj/machinery/light/small{ dir = 4 }, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet, /area/ruin/powered/greed) "v" = ( /obj/item/coin/gold, /obj/machinery/light/small, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/black, /area/ruin/powered/greed) "w" = ( /obj/item/storage/bag/money, /obj/machinery/light/small, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/black, +/area/ruin/powered/greed) +"H" = ( +/turf/open/floor/carpet/purple, /area/ruin/powered/greed) "J" = ( /obj/machinery/door/airlock/gold, /obj/structure/fans/tiny/invisible, -/turf/open/floor/engine/cult, +/turf/open/floor/carpet/purple, /area/ruin/powered/greed) "W" = ( -/turf/closed/wall/mineral/cult, +/turf/closed/wall/mineral/cult{ + sheet_amount = 0 + }, /area/ruin/powered/greed) (1,1,1) = {" @@ -337,7 +335,7 @@ a c W f -i +m m l m @@ -345,7 +343,7 @@ o m m m -m +H J a a diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm index b66fbdf3d5..e582f6e9ce 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm @@ -21,6 +21,7 @@ "f" = ( /obj/structure/table/wood, /obj/item/storage/box/cups, +/obj/item/reagent_containers/food/snacks/lollipop, /turf/open/floor/wood{ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, @@ -181,11 +182,19 @@ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, /area/ruin/unpowered) +"B" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/trash/candy, +/turf/open/floor/wood{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered) "C" = ( /obj/structure/chair/wood/wings{ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/snacks/candy, /turf/open/floor/plating{ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, @@ -214,6 +223,7 @@ /area/ruin/unpowered) "G" = ( /obj/structure/table/wood, +/obj/item/reagent_containers/food/snacks/lollipop, /turf/open/floor/wood{ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, @@ -288,6 +298,35 @@ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, /area/ruin/unpowered) +"R" = ( +/obj/structure/table/wood, +/obj/effect/spawner/lootdrop/pizzaparty, +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/snacks/candy, +/turf/open/floor/wood{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered) +"V" = ( +/obj/item/reagent_containers/food/snacks/gumball, +/turf/open/floor/wood{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered) +"X" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/toy/snappop, +/turf/open/floor/wood{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered) +"Z" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/reagent_containers/food/snacks/gumball, +/turf/open/floor/wood{ + initial_gas_mix = "o2=14;n2=23;TEMP=300" + }, +/area/ruin/unpowered) (1,1,1) = {" a @@ -359,8 +398,8 @@ b c c e -h -h +B +Z e Q e @@ -397,8 +436,8 @@ b d f n -h -h +M +X c e M @@ -417,7 +456,7 @@ b d g o -h +B h C J @@ -435,7 +474,7 @@ b b b e -h +Z p q x @@ -461,7 +500,7 @@ r y E h -h +X c b b @@ -496,7 +535,7 @@ b b e e -h +X t A G @@ -515,12 +554,12 @@ b b b d -k +R h s s H -h +B O d b @@ -536,9 +575,9 @@ b b d k -h +M u -s +V s o n diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_pride.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_pride.dmm index cf4938f369..f42aef243a 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_pride.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_pride.dmm @@ -3,8 +3,8 @@ /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "b" = ( -/turf/closed/mineral/volcanic/lava_land_surface, -/area/lavaland/surface/outdoors) +/turf/closed/wall/mineral/diamond, +/area/ruin/powered/pride) "c" = ( /turf/open/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) @@ -23,6 +23,10 @@ "g" = ( /turf/open/floor/mineral/silver, /area/ruin/powered/pride) +"i" = ( +/obj/item/clothing/gloves/ring, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) "j" = ( /obj/structure/mirror{ pixel_x = -32 @@ -33,13 +37,8 @@ /turf/open/floor/mineral/silver, /area/ruin/powered/pride) "k" = ( -/obj/structure/mirror{ - pixel_x = 32 - }, -/obj/machinery/light/small{ - dir = 1 - }, -/turf/open/floor/mineral/silver, +/obj/structure/mirror/magic/pride, +/turf/closed/wall/mineral/diamond, /area/ruin/powered/pride) "l" = ( /obj/structure/mirror{ @@ -60,19 +59,65 @@ }, /turf/open/floor/mineral/silver, /area/ruin/powered/pride) +"o" = ( +/obj/structure/mirror{ + pixel_x = -32 + }, +/obj/item/lipstick/random, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) +"q" = ( +/obj/structure/mirror{ + pixel_x = -32 + }, +/obj/item/clothing/gloves/ring/silver, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) "r" = ( /obj/machinery/light/small, /turf/open/floor/mineral/silver, /area/ruin/powered/pride) +"u" = ( +/obj/structure/mirror{ + pixel_x = 32 + }, +/obj/item/lipstick/random, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) +"D" = ( +/obj/item/clothing/head/wig/random, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) "G" = ( -/turf/closed/wall/mineral/diamond, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface/outdoors) +"I" = ( +/obj/item/clothing/gloves/ring/silver, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) +"J" = ( +/obj/structure/mirror{ + pixel_x = 32 + }, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) +"L" = ( +/obj/item/lipstick/random, +/turf/open/floor/mineral/silver, /area/ruin/powered/pride) "O" = ( -/obj/structure/mirror/magic/pride, -/turf/closed/wall/mineral/diamond, +/obj/item/clothing/gloves/ring/diamond, +/turf/open/floor/mineral/silver, +/area/ruin/powered/pride) +"V" = ( +/obj/item/clothing/head/wig, +/turf/open/floor/mineral/silver, /area/ruin/powered/pride) "Y" = ( -/obj/machinery/door/airlock/diamond, +/obj/machinery/door/airlock/silver/glass, /turf/open/floor/mineral/silver{ blocks_air = 1 }, @@ -95,10 +140,6 @@ a a a a -a -a -a -a "} (2,1,1) = {" a @@ -116,91 +157,71 @@ c c c c -c -c -c -c a "} (3,1,1) = {" +G +c +c +b +b +b +b +b +b +b +b +b +b b -c -c -G -G -G -G -G -G -G -G -G -G -G -G -G -G -G c a "} (4,1,1) = {" c c -G -G -G +b +b j -e +q e l e e l e -e -l -e -e -G +o +b c a "} (5,1,1) = {" c -G -G -G -G -G -g -g -g -g -g +b +b g g g +L g +V g +L +i r -G +b a a "} (6,1,1) = {" c -G -G -G -G -G +b O g +k g g -g -g +I g g g @@ -212,77 +233,61 @@ a "} (7,1,1) = {" c -G -G -G -G -G -g -g -g -g -g -g +b +b g g +L +D g +L +i g +D r -G -c +b +a a "} (8,1,1) = {" c c -G -G -G -k +b +b +J f f m f f m +u f -f -m -f -f -G +b c a "} (9,1,1) = {" +G +c +c +b +b +b +b +b +b +b +b +b +b b -c -c -G -G -G -G -G -G -G -G -G -G -G -G -G -G -G c a "} (10,1,1) = {" -b -b -c -c -c -c +G +G c c c diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm index 3576cab5c7..aa56cce5ca 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_sloth.dmm @@ -641,4 +641,4 @@ a a a a -"} +"} \ No newline at end of file diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index dab9d0316b..e310f8a6da 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -5181,7 +5181,7 @@ /turf/open/floor/plating, /area/ruin/unpowered/syndicate_lava_base/arrivals) "mu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/decal/cleanable/dirt, diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm index 05155ee2a8..88b906b467 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm @@ -90,11 +90,11 @@ /obj/structure/stone_tile/surrounding_tile{ dir = 8 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "l" = ( /obj/structure/stone_tile/block/cracked, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "m" = ( /obj/structure/stone_tile/surrounding_tile/cracked, @@ -105,7 +105,7 @@ /obj/structure/stone_tile/surrounding_tile{ dir = 8 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "n" = ( /obj/structure/stone_tile/block/cracked{ @@ -136,14 +136,14 @@ }, /obj/structure/table/bronze, /obj/item/disk/design_disk/adv/knight_gear, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "q" = ( /obj/structure/table/bronze, /obj/item/stack/sheet/mineral/runite{ amount = 5 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "r" = ( /obj/structure/stone_tile/block{ @@ -153,7 +153,7 @@ /obj/item/stack/sheet/mineral/runite{ amount = 5 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "s" = ( /obj/structure/stone_tile/block{ @@ -186,13 +186,13 @@ /obj/structure/stone_tile/surrounding_tile{ dir = 1 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "v" = ( /obj/structure/stone_tile/block{ dir = 1 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "w" = ( /obj/structure/stone_tile/surrounding_tile/cracked{ @@ -205,7 +205,7 @@ /obj/structure/stone_tile/surrounding_tile{ dir = 4 }, -/turf/open/indestructible/necropolis, +/turf/open/indestructible/necropolis/air, /area/lavaland/surface/outdoors) "x" = ( /obj/structure/stone_tile/block{ diff --git a/_maps/RandomRuins/SpaceRuins/arcade.dmm b/_maps/RandomRuins/SpaceRuins/arcade.dmm index 771c33c55b..c68d3b224e 100644 --- a/_maps/RandomRuins/SpaceRuins/arcade.dmm +++ b/_maps/RandomRuins/SpaceRuins/arcade.dmm @@ -3,7 +3,7 @@ /turf/template_noop, /area/template_noop) "b" = ( -/turf/open/floor/plating/asteroid, +/turf/open/floor/plating/asteroid/airless, /area/ruin/powered) "c" = ( /turf/closed/mineral/random/high_chance, @@ -135,7 +135,7 @@ /area/ruin/powered) "F" = ( /obj/structure/closet/crate/trashcart, -/turf/open/floor/plating/asteroid, +/turf/open/floor/plating/asteroid/airless, /area/ruin/powered) "G" = ( /obj/structure/chair/sofa/right, @@ -151,7 +151,7 @@ /turf/open/floor/engine, /area/ruin/powered) "J" = ( -/obj/item/twohanded/dualsaber/toy, +/obj/item/dualsaber/toy, /turf/open/floor/light/colour_cycle/dancefloor_b, /area/ruin/powered) "K" = ( diff --git a/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm b/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm index e23beb3407..2a25a3b6e7 100644 --- a/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm +++ b/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm @@ -3,7 +3,7 @@ /turf/template_noop, /area/template_noop) "b" = ( -/turf/open/floor/plating/asteroid, +/turf/open/floor/plating/asteroid/airless, /area/ruin/powered) "c" = ( /turf/closed/mineral/random/high_chance, @@ -176,8 +176,8 @@ /obj/structure/table, /obj/effect/decal/cleanable/dirt, /obj/item/autosurgeon{ - name = "rusted autosurgeon"; desc = "A device that automatically inserts an implant or organ into the user without the hassle of extensive surgery. It has a slot to insert an organ of implant. But this rusted version looks like it could only manage one implant...."; + name = "rusted autosurgeon"; uses = 1 }, /turf/open/floor/plasteel, @@ -205,7 +205,7 @@ /obj/machinery/atmospherics/components/unary/outlet_injector/on/layer1{ dir = 4 }, -/turf/open/floor/plating/asteroid, +/turf/open/floor/plating/asteroid/airless, /area/ruin/powered) "K" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ diff --git a/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm b/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm index 1fb4e60aff..d440e2d15b 100644 --- a/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm +++ b/_maps/RandomRuins/SpaceRuins/cloning_facility.dmm @@ -69,7 +69,7 @@ /turf/open/floor/plasteel/white, /area/ruin/space/has_grav/powered/ancient_shuttle) "j" = ( -/obj/machinery/computer/prototype_cloning, +/obj/machinery/computer/cloning/prototype, /obj/machinery/light{ dir = 1 }, diff --git a/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm b/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm index a89d1422d2..d8677f11d8 100644 --- a/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm +++ b/_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm @@ -165,7 +165,7 @@ /turf/open/floor/plasteel/grimy, /area/ruin/space/has_grav/hilbertresearchfacility) "D" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/ruin/space/has_grav/hilbertresearchfacility) "E" = ( diff --git a/_maps/RandomRuins/SpaceRuins/listeningstation.dmm b/_maps/RandomRuins/SpaceRuins/listeningstation.dmm index b23f24b0e9..49646fbd71 100644 --- a/_maps/RandomRuins/SpaceRuins/listeningstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/listeningstation.dmm @@ -151,6 +151,7 @@ id_tag = "syndie_listeningpost_external"; req_access_txt = "150" }, +/obj/structure/fans/tiny, /turf/open/floor/plating, /area/ruin/space/has_grav/listeningstation) "aq" = ( diff --git a/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm b/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm index 0baac3252a..9ac2fed86f 100644 --- a/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm +++ b/_maps/RandomRuins/SpaceRuins/mrow_thats_right.dmm @@ -185,7 +185,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/powered/cat_man) "aF" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -294,7 +294,7 @@ /area/ruin/space/has_grav/powered/cat_man) "aV" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -552,7 +552,7 @@ /area/ruin/space/has_grav/powered/cat_man) "bF" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm index 343c79a895..8528099d30 100644 --- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm @@ -597,7 +597,7 @@ icon_state = "2-4" }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/effect/decal/cleanable/dirt, @@ -639,7 +639,7 @@ /turf/open/floor/plasteel, /area/ruin/space/has_grav/ancientstation) "bW" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/effect/decal/cleanable/dirt, @@ -858,7 +858,7 @@ /turf/open/floor/plasteel, /area/ruin/space/has_grav/ancientstation/deltacorridor) "cz" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/structure/cable{ @@ -918,7 +918,7 @@ /turf/open/floor/plasteel, /area/ruin/space/has_grav/ancientstation/deltacorridor) "cH" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/effect/decal/cleanable/dirt, @@ -1127,7 +1127,7 @@ /area/ruin/space/has_grav/ancientstation) "dn" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/machinery/light/small{ @@ -1179,7 +1179,7 @@ /area/ruin/space/has_grav/ancientstation/hydroponics) "ds" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/machinery/light/small{ @@ -3980,7 +3980,7 @@ icon_state = "1-4" }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/effect/decal/cleanable/dirt, @@ -4015,7 +4015,7 @@ /turf/open/floor/plasteel, /area/ruin/space/has_grav/ancientstation) "jJ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/structure/cable{ @@ -5010,7 +5010,7 @@ /turf/open/floor/plating, /area/ruin/space/has_grav/ancientstation) "PV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/effect/decal/cleanable/dirt, diff --git a/_maps/RandomRuins/SpaceRuins/spacediner.dmm b/_maps/RandomRuins/SpaceRuins/spacediner.dmm index 21670da9e4..16a6850130 100644 --- a/_maps/RandomRuins/SpaceRuins/spacediner.dmm +++ b/_maps/RandomRuins/SpaceRuins/spacediner.dmm @@ -932,7 +932,6 @@ /obj/machinery/airalarm/all_access{ dir = 1; icon_state = "alarm0"; - pixel_x = 0; pixel_y = -24 }, /turf/open/floor/plasteel/dark, diff --git a/_maps/RandomRuins/SpaceRuins/spacehermit.dmm b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm index dd7e700146..c95e0c7539 100644 --- a/_maps/RandomRuins/SpaceRuins/spacehermit.dmm +++ b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm @@ -5,9 +5,6 @@ "ab" = ( /turf/closed/mineral/random/low_chance, /area/ruin/unpowered) -"ac" = ( -/turf/open/floor/plating/asteroid, -/area/ruin/unpowered) "ad" = ( /obj/machinery/hydroponics/soil, /turf/open/floor/plating/asteroid, @@ -112,7 +109,7 @@ /turf/open/floor/plating/asteroid, /area/ruin/powered) "ax" = ( -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/plating/asteroid, /area/ruin/powered) "ay" = ( @@ -327,9 +324,6 @@ /obj/item/flashlight/lamp/bananalamp, /turf/open/floor/plating/asteroid, /area/ruin/powered) -"bt" = ( -/turf/closed/mineral/random/low_chance/earth_like, -/area/ruin/unpowered) "bC" = ( /obj/item/pickaxe/titanium, /turf/open/floor/plating/asteroid, @@ -396,7 +390,7 @@ aa aa aa aa -ac +aA aO aA aA @@ -2648,7 +2642,7 @@ aa aa aa aa -ac +aA aa aa aa @@ -2699,9 +2693,9 @@ aa aa aa aa -ac +aA ab -ac +aA aa aa "} @@ -2855,9 +2849,9 @@ aa aa aa aa -ac +aA ab -ac +aA aa aa "} @@ -2907,7 +2901,7 @@ aa aa aa aa -ac +aA aa aa aa @@ -2959,7 +2953,7 @@ aa aa aa aa -bt +ab aa aa aa diff --git a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm index 209feb82e3..3e5c80253d 100644 --- a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm +++ b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm @@ -148,7 +148,7 @@ /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_3) "aD" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /turf/open/floor/wood, @@ -189,7 +189,7 @@ /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_4) "aL" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/wood, @@ -230,7 +230,7 @@ /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_5) "aT" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/wood, @@ -271,7 +271,7 @@ /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_6) "bb" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /turf/open/floor/wood, @@ -1113,7 +1113,7 @@ /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_2) "dq" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/wood, @@ -1177,7 +1177,7 @@ /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_1) "dy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/wood, @@ -1453,7 +1453,7 @@ /area/ruin/space/has_grav/hotel/guestroom/room_2) "eu" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/wood, /area/ruin/space/has_grav/hotel/guestroom/room_2) "ev" = ( @@ -1855,7 +1855,7 @@ /turf/open/floor/plasteel, /area/ruin/space/has_grav/hotel/bar) "fI" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ @@ -2035,7 +2035,7 @@ }, /area/ruin/space/has_grav/hotel/dock) "gh" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/wood, @@ -2435,7 +2435,7 @@ /turf/open/floor/carpet, /area/ruin/space/has_grav/hotel) "hq" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /turf/open/floor/plasteel/dark, @@ -3013,7 +3013,7 @@ /turf/open/floor/plasteel, /area/ruin/space/has_grav/hotel/power) "iM" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/wood, /area/ruin/space/has_grav/hotel) "iN" = ( @@ -4817,7 +4817,7 @@ /turf/open/floor/plasteel/dark, /area/ruin/space/has_grav/hotel/pool) "mD" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-25" }, /obj/effect/turf_decal/tile/neutral{ diff --git a/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm b/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm index 794300cdb5..1bc497d4f9 100644 --- a/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm +++ b/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm @@ -44,7 +44,7 @@ /area/ruin/space/has_grav) "C" = ( /obj/effect/decal/remains/human, -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/mineral/titanium/blue, /area/ruin/space/has_grav) "F" = ( @@ -80,7 +80,7 @@ /obj/item/shard{ icon_state = "medium" }, -/turf/open/floor/plating/airless{ +/turf/open/floor/plating{ icon_state = "platingdmg2" }, /area/ruin/space/has_grav) diff --git a/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm b/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm index a9c5eab318..2d66300953 100644 --- a/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm +++ b/_maps/RandomRuins/StationRuins/Box/Engine/engine_teg.dmm @@ -71,8 +71,9 @@ /turf/closed/wall/r_wall, /area/engine/engineering) "di" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, /area/engine/engineering) "dl" = ( /obj/structure/cable{ @@ -304,12 +305,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, /turf/open/floor/plasteel, /area/engine/engineering) "kH" = ( @@ -523,6 +518,9 @@ /obj/machinery/light{ dir = 4 }, +/obj/structure/sign/warning/enginesafety{ + pixel_x = 32 + }, /turf/open/floor/plasteel, /area/engine/engineering) "qv" = ( @@ -543,7 +541,13 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/turf/open/floor/plasteel, /area/engine/engineering) "qN" = ( /obj/structure/table/reinforced, @@ -848,6 +852,10 @@ /obj/machinery/igniter{ id = "TEG_igniter" }, +/mob/living/carbon/monkey{ + name = "Mumkey Jones" + }, +/obj/item/clothing/head/hardhat/atmos, /turf/open/floor/engine/vacuum, /area/engine/engineering) "An" = ( @@ -882,14 +890,6 @@ /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 1 }, -/obj/machinery/camera{ - c_tag = "TEG - North Center"; - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel, /area/engine/engineering) "AX" = ( @@ -948,7 +948,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "BT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/engine/engineering) "BY" = ( @@ -1042,12 +1042,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"EI" = ( -/obj/effect/turf_decal/delivery, -/obj/structure/reagent_dispensers/fueltank, -/obj/machinery/atmospherics/pipe/simple/orange/visible, -/turf/open/floor/plasteel, -/area/engine/engineering) "EL" = ( /turf/closed/wall, /area/engine/engineering) @@ -1082,6 +1076,11 @@ /obj/structure/window/reinforced, /turf/open/floor/plasteel, /area/engine/engineering) +"Fs" = ( +/obj/structure/rack, +/obj/item/pipe_dispenser, +/turf/open/floor/plasteel, +/area/engine/engineering) "FG" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 10 @@ -1218,11 +1217,6 @@ /turf/open/floor/plasteel, /area/engine/engineering) "Jd" = ( -/obj/machinery/light, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, /obj/machinery/atmospherics/pipe/manifold/orange/visible, /turf/open/floor/plasteel, /area/engine/engineering) @@ -1312,15 +1306,6 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/light{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, /turf/open/floor/plasteel, /area/engine/engineering) "LD" = ( @@ -1372,6 +1357,7 @@ /obj/machinery/atmospherics/pipe/manifold/cyan/visible{ dir = 4 }, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/engineering) "Nz" = ( @@ -1429,12 +1415,10 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 4 }, -/obj/machinery/airalarm{ - dir = 1; - locked = 0; - pixel_y = -22 - }, /obj/machinery/light, +/obj/structure/sign/nanotrasen{ + pixel_y = -32 + }, /turf/open/floor/plasteel, /area/engine/engineering) "Pz" = ( @@ -1452,6 +1436,9 @@ /obj/machinery/light{ dir = 1 }, +/obj/structure/sign/warning/nosmoking{ + pixel_y = 30 + }, /turf/open/floor/plasteel, /area/engine/engineering) "PK" = ( @@ -1522,12 +1509,11 @@ /turf/open/space, /area/space/nearstation) "Rl" = ( -/obj/machinery/atmospherics/components/binary/pump{ - dir = 1 - }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/cyan/visible, +/obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/engineering) "Rz" = ( @@ -1602,7 +1588,13 @@ /turf/open/floor/plating, /area/engine/engineering) "TE" = ( -/obj/structure/closet/crate/internals, +/obj/structure/closet/crate{ + icon_state = "crateopen" + }, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 2; + name = "2maintenance loot spawner" + }, /turf/open/floor/plasteel, /area/engine/engineering) "TH" = ( @@ -1648,6 +1640,10 @@ dir = 4 }, /obj/effect/turf_decal/tile/yellow, +/obj/machinery/camera{ + c_tag = "TEG - North Center"; + dir = 8 + }, /turf/open/floor/plasteel, /area/engine/engineering) "Uq" = ( @@ -1671,18 +1667,15 @@ /area/engine/engineering) "UT" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, /turf/open/floor/plasteel, /area/engine/engineering) "UY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, +/obj/machinery/airalarm{ + pixel_y = 23 + }, /turf/open/floor/plasteel, /area/engine/engineering) "Vi" = ( @@ -1811,10 +1804,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 }, -/obj/structure/extinguisher_cabinet{ - dir = 4; - pixel_y = -27 - }, /turf/open/floor/plasteel, /area/engine/engineering) "YC" = ( @@ -1837,9 +1826,10 @@ /turf/open/floor/plasteel, /area/engine/engineering) "YP" = ( -/obj/structure/rack, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/item/pipe_dispenser, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel, /area/engine/engineering) "YQ" = ( @@ -1878,7 +1868,9 @@ /turf/open/floor/plasteel, /area/engine/engineering) "Zu" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/visible, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 6 + }, /obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/engineering) @@ -1887,13 +1879,6 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/sign/warning/securearea{ - pixel_y = -32 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel, /area/engine/engineering) "ZC" = ( @@ -2170,7 +2155,7 @@ iD MP MP MP -ij +MP yX qn qn @@ -2251,11 +2236,11 @@ ME QS uB Ok -Ok -Ok +di +di Ok Bz -Zu +lI Wc Ok zG @@ -2307,8 +2292,8 @@ iP wk go fF -EI -EI +UT +UT sn qc Nh @@ -2367,7 +2352,7 @@ KA KA Ok dZ -bO +Zu ev tl qb @@ -2477,7 +2462,7 @@ IP Zs sD Jd -EL +YP YG AX PK @@ -2505,7 +2490,7 @@ SX ou vG Zv -di +Xe qJ Lw Xe @@ -2595,7 +2580,7 @@ PK Dv Dv bO -YP +sH As yN yN @@ -2651,7 +2636,7 @@ eh zx XW ST -Ok +Fs MP tw tw diff --git a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm index 1bfb337d99..5bc10b30f0 100644 --- a/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm +++ b/_maps/RandomRuins/StationRuins/Lavaland/Mining_Station/Mining_Station_Public_01.dmm @@ -399,7 +399,7 @@ /turf/open/floor/plating, /area/mine/laborcamp/security) "hf" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/mine/living_quarters) "hm" = ( @@ -1565,7 +1565,7 @@ /turf/open/floor/plating, /area/mine/laborcamp) "zy" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/brown{ dir = 1 }, diff --git a/_maps/RandomZLevels/VR/murderdome.dmm b/_maps/RandomZLevels/VR/murderdome.dmm index 740f9fd09f..5b5cbbfcfe 100644 --- a/_maps/RandomZLevels/VR/murderdome.dmm +++ b/_maps/RandomZLevels/VR/murderdome.dmm @@ -232,7 +232,9 @@ /area/awaymission/vr/murderdome) "H" = ( /obj/machinery/telecomms/allinone, -/turf/open/indestructible, +/turf/open/indestructible{ + initial_gas_mix = "TEMP=2.7" + }, /area/awaymission/vr/murderdome) "R" = ( /obj/effect/spawner/structure/window/reinforced/indestructable, diff --git a/_maps/RandomZLevels/VR/syndicate_trainer.dmm b/_maps/RandomZLevels/VR/syndicate_trainer.dmm index 0a44006802..5b010e74d9 100644 --- a/_maps/RandomZLevels/VR/syndicate_trainer.dmm +++ b/_maps/RandomZLevels/VR/syndicate_trainer.dmm @@ -1370,7 +1370,7 @@ /turf/open/indestructible, /area/awaymission/centcomAway/general) "hW" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/indestructible, /area/awaymission/centcomAway/general) "hX" = ( @@ -1951,7 +1951,7 @@ "lv" = ( /obj/structure/rack, /obj/item/restraints/legcuffs/beartrap, -/obj/item/twohanded/fireaxe, +/obj/item/fireaxe, /turf/open/indestructible, /area/awaymission/centcomAway/thunderdome) "lw" = ( diff --git a/_maps/RandomZLevels/away_mission/Academy.dmm b/_maps/RandomZLevels/away_mission/Academy.dmm index de0b7cc430..37b0098fd2 100644 --- a/_maps/RandomZLevels/away_mission/Academy.dmm +++ b/_maps/RandomZLevels/away_mission/Academy.dmm @@ -6,8 +6,12 @@ /turf/closed/wall/r_wall, /area/awaymission/academy/headmaster) "ac" = ( -/mob/living/simple_animal/hostile/carp/ranged{ - faction = list("wizard") +/mob/living/simple_animal/hostile/carp{ + icon_dead = "magicarp_dead"; + icon_gib = "magicarp_gib"; + icon_living = "magicarp"; + icon_state = "magicarp"; + name = "bootleg magicarp" }, /turf/open/space, /area/space/nearstation) @@ -38,6 +42,7 @@ /obj/structure/chair/office/light{ dir = 1 }, +/mob/living/simple_animal/hostile/wizard, /turf/open/floor/carpet, /area/awaymission/academy/headmaster) "aj" = ( @@ -46,8 +51,6 @@ }, /obj/machinery/power/apc/unlocked{ dir = 1; - environ = 3; - equipment = 3; pixel_y = 32; req_access = null }, @@ -160,6 +163,7 @@ "aB" = ( /obj/structure/bed, /obj/item/bedsheet/purple, +/mob/living/simple_animal/hostile/wizard, /turf/open/floor/wood, /area/awaymission/academy/headmaster) "aC" = ( @@ -199,7 +203,7 @@ /area/awaymission/academy/headmaster) "aJ" = ( /obj/structure/destructible/cult/tome, -/obj/item/dice/d20/fate, +/obj/item/dice/d20/fate/one_use, /turf/open/floor/wood, /area/awaymission/academy/headmaster) "aK" = ( @@ -259,6 +263,7 @@ /area/awaymission/academy/headmaster) "aV" = ( /obj/structure/chair/office/dark, +/mob/living/simple_animal/hostile/wizard, /turf/open/floor/carpet, /area/awaymission/academy/headmaster) "aW" = ( @@ -315,6 +320,7 @@ /area/awaymission/academy/headmaster) "bg" = ( /obj/structure/table/wood, +/obj/item/flashlight/flashdark, /turf/open/floor/carpet, /area/awaymission/academy/headmaster) "bh" = ( @@ -348,6 +354,7 @@ /obj/structure/chair/office/dark{ dir = 1 }, +/mob/living/simple_animal/hostile/wizard, /turf/open/floor/carpet, /area/awaymission/academy/headmaster) "bm" = ( @@ -699,6 +706,7 @@ /turf/open/floor/plating, /area/awaymission/academy/headmaster) "cw" = ( +/obj/structure/trap/chill, /turf/open/floor/plating, /area/awaymission/academy/headmaster) "cx" = ( @@ -712,6 +720,7 @@ /area/awaymission/academy/headmaster) "cy" = ( /obj/structure/table, +/obj/item/disk/design_disk/adv/cleric_mace, /turf/open/floor/plasteel/showroomfloor, /area/awaymission/academy/headmaster) "cz" = ( @@ -929,7 +938,7 @@ /area/awaymission/academy/classrooms) "dg" = ( /obj/structure/table/wood, -/obj/item/gun/magic/wand/fireball, +/obj/item/gun/magic/wand/teleport, /turf/open/floor/wood, /area/awaymission/academy/classrooms) "dh" = ( @@ -1282,8 +1291,6 @@ }, /obj/machinery/power/apc/unlocked{ dir = 1; - environ = 3; - equipment = 3; pixel_y = 32; req_access = null }, @@ -1935,6 +1942,7 @@ /obj/structure/cable{ icon_state = "4-8" }, +/obj/structure/trap/damage, /turf/open/floor/plasteel/white/side{ dir = 1 }, @@ -2294,7 +2302,6 @@ "gH" = ( /obj/structure/table, /obj/item/paper/fluff/awaymissions/academy/grade/aplus, -/obj/item/gun/ballistic/shotgun/automatic/combat, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -2305,6 +2312,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/item/gun/ballistic/revolver/doublebarrel/improvised, /turf/open/floor/plasteel/dark, /area/awaymission/academy/classrooms) "gI" = ( @@ -2349,6 +2357,7 @@ /area/awaymission/academy/classrooms) "gM" = ( /obj/item/toy/beach_ball/holoball, +/obj/structure/trap/stun, /turf/open/floor/engine/cult, /area/awaymission/academy/academycellar) "gN" = ( @@ -2477,15 +2486,11 @@ /turf/open/floor/plasteel, /area/awaymission/academy/classrooms) "ha" = ( -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, +/turf/open/floor/plasteel/white/side, /area/awaymission/academy/classrooms) "hb" = ( /obj/structure/chair/stool, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, +/turf/open/floor/plasteel/white/side, /area/awaymission/academy/classrooms) "hc" = ( /turf/closed/wall/r_wall, @@ -2537,8 +2542,6 @@ }, /obj/machinery/power/apc/unlocked{ dir = 1; - environ = 3; - equipment = 3; pixel_y = 32; req_access = null }, @@ -2641,6 +2644,7 @@ /obj/structure/cable{ icon_state = "1-4" }, +/obj/structure/trap/damage, /turf/open/floor/plasteel, /area/awaymission/academy/academyaft) "hD" = ( @@ -2829,6 +2833,19 @@ }, /turf/open/floor/plasteel, /area/awaymission/academy/academyaft) +"ig" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/structure/trap/chill, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/academy/classrooms) "ih" = ( /obj/structure/rack, /obj/item/stack/sheet/mineral/plasma{ @@ -2853,23 +2870,17 @@ /turf/open/floor/plasteel, /area/awaymission/academy/academyaft) "il" = ( -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "im" = ( /obj/structure/mirror{ pixel_y = 28 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "in" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "io" = ( /obj/structure/rack, @@ -2893,9 +2904,7 @@ /area/awaymission/academy/academyaft) "ir" = ( /obj/structure/mineral_door/iron, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "is" = ( /obj/structure/rack, @@ -2920,17 +2929,13 @@ pixel_x = -12; pixel_y = 2 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "iw" = ( /obj/machinery/light{ dir = 4 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "ix" = ( /obj/machinery/light{ @@ -2948,18 +2953,14 @@ /obj/machinery/light{ dir = 8 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "iA" = ( /obj/structure/sink{ dir = 4; pixel_x = 11 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "iB" = ( /obj/structure/rack, @@ -2978,9 +2979,7 @@ /obj/machinery/light/small{ dir = 1 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "iE" = ( /obj/machinery/light{ @@ -3001,9 +3000,7 @@ /obj/machinery/light/small{ dir = 1 }, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "iH" = ( /obj/item/paper, @@ -3038,9 +3035,7 @@ dir = 1 }, /obj/effect/decal/cleanable/vomit, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "iO" = ( /obj/structure/cable{ @@ -3132,7 +3127,7 @@ dir = 1 }, /obj/structure/table, -/obj/item/soulstone, +/obj/item/gun/ballistic/revolver/russian/soul, /turf/open/floor/plasteel/airless{ icon_state = "whitered"; dir = 4 @@ -3226,6 +3221,7 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/mob/living/simple_animal/hostile/wizard, /turf/open/floor/plasteel, /area/awaymission/academy/academyaft) "jk" = ( @@ -3251,6 +3247,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/mob/living/simple_animal/hostile/wizard, /turf/open/floor/plasteel/airless/white{ dir = 4 }, @@ -3565,8 +3562,6 @@ "kh" = ( /obj/machinery/power/apc/unlocked{ dir = 1; - environ = 3; - equipment = 3; pixel_y = 32; req_access = null }, @@ -3577,12 +3572,14 @@ /area/awaymission/academy/academygate) "ki" = ( /obj/item/stack/cable_coil/random, +/obj/effect/landmark/awaystart, /turf/open/floor/plating, /area/awaymission/academy/academygate) "kj" = ( /obj/structure/cable{ icon_state = "0-2" }, +/obj/effect/landmark/awaystart, /turf/open/floor/plating, /area/awaymission/academy/academygate) "kk" = ( @@ -3597,36 +3594,12 @@ }, /turf/open/floor/carpet, /area/awaymission/academy/academygate) -"km" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/obj/structure/cable{ - icon_state = "1-4" - }, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) "kn" = ( -/obj/machinery/gateway{ - dir = 1 - }, /obj/structure/cable{ icon_state = "2-8" }, /turf/open/floor/plating, /area/awaymission/academy/academygate) -"ko" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) -"kp" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) "kq" = ( /mob/living/simple_animal/hostile/wizard, /obj/effect/turf_decal/tile/yellow{ @@ -3637,28 +3610,6 @@ }, /turf/open/floor/plasteel, /area/awaymission/academy/classrooms) -"kr" = ( -/obj/machinery/gateway{ - dir = 4 - }, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) -"ks" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) -"kt" = ( -/obj/machinery/gateway, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) -"ku" = ( -/obj/machinery/gateway{ - dir = 6 - }, -/turf/open/floor/plating, -/area/awaymission/academy/academygate) "kv" = ( /obj/machinery/light, /turf/open/floor/carpet, @@ -3678,9 +3629,7 @@ /obj/machinery/door/poddoor/shutters{ id = "AcademyGate" }, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/awaymission/academy/academygate) "kz" = ( @@ -3728,9 +3677,7 @@ /area/awaymission/academy/headmaster) "kG" = ( /mob/living/simple_animal/hostile/wizard, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, +/turf/open/floor/plasteel/cafeteria, /area/awaymission/academy/academyaft) "kH" = ( /obj/structure/cable{ @@ -3744,9 +3691,7 @@ /area/awaymission/academy/academyaft) "kI" = ( /obj/structure/cable, -/obj/machinery/gateway/centeraway{ - calibrated = 1 - }, +/obj/machinery/gateway/away, /turf/open/floor/plating, /area/awaymission/academy/academygate) "kJ" = ( @@ -3864,7 +3809,7 @@ /area/awaymission/academy/academycellar) "lg" = ( /obj/structure/table/wood, -/obj/item/guardiancreator/choose, +/obj/item/nullrod/staff, /turf/open/floor/engine/cult, /area/awaymission/academy/academycellar) "lh" = ( @@ -3881,9 +3826,8 @@ /area/awaymission/academy/academycellar) "lk" = ( /obj/structure/safe/floor, -/obj/item/voodoo, -/obj/item/gun/magic/wand/fireball, /obj/item/clothing/suit/space/hardsuit/wizard, +/obj/item/gun/magic/wand/fireball/inert, /turf/open/floor/wood, /area/awaymission/academy/headmaster) "ll" = ( @@ -4051,7 +3995,6 @@ /area/awaymission/academy/academyengine) "lQ" = ( /obj/structure/table, -/obj/item/gun/magic/wand/polymorph, /turf/open/floor/plating, /area/awaymission/academy/academyengine) "lR" = ( @@ -4123,14 +4066,14 @@ /turf/closed/wall/r_wall, /area/awaymission/academy/academyengine) "me" = ( -/obj/structure/constructshell, +/obj/structure/fluff/divine/powerpylon, /turf/open/floor/plating, /area/awaymission/academy/academyengine) "mf" = ( -/obj/structure/constructshell, /obj/machinery/light{ dir = 1 }, +/obj/structure/fluff/divine/defensepylon, /turf/open/floor/plating, /area/awaymission/academy/academyengine) "mg" = ( @@ -4149,14 +4092,14 @@ /area/awaymission/academy/academyengine) "mj" = ( /obj/structure/rack, -/obj/item/book/granter/spell/summonitem, /obj/item/pen/fourcolor, +/obj/item/book/granter/spell/smoke, /turf/open/floor/vault, /area/awaymission/academy/academyengine) "mk" = ( /obj/structure/rack, -/obj/item/claymore, /obj/item/toy/figure/wizard, +/obj/item/claymore/weak/ceremonial, /turf/open/floor/vault, /area/awaymission/academy/academyengine) "ml" = ( @@ -4384,22 +4327,19 @@ }, /area/awaymission/academy/headmaster) "ng" = ( -/turf/closed/indestructible/fakeglass{ - icon_state = "fakewindows"; - dir = 8 - }, -/area/awaymission/academy/academyengine) +/obj/structure/trap/stun, +/turf/open/floor/engine/cult, +/area/awaymission/academy/academycellar) "nh" = ( -/turf/closed/indestructible/fakeglass{ - icon_state = "fakewindows2"; - dir = 8 +/obj/structure/cable{ + icon_state = "2-4" }, -/area/awaymission/academy/academyengine) +/obj/structure/trap/chill, +/turf/open/floor/carpet, +/area/awaymission/academy/headmaster) "ni" = ( -/turf/closed/indestructible/fakeglass{ - icon_state = "fakewindows"; - dir = 4 - }, +/obj/structure/trap/stun, +/turf/open/floor/plating, /area/awaymission/academy/academyengine) "nj" = ( /obj/structure/rack, @@ -4433,6 +4373,108 @@ }, /turf/open/floor/carpet, /area/awaymission/academy/headmaster) +"nr" = ( +/obj/structure/trap/stun, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/academy/academycellar) +"ox" = ( +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plating, +/area/awaymission/academy/classrooms) +"qF" = ( +/obj/structure/trap/fire, +/turf/open/floor/grass, +/area/awaymission/academy/academyaft) +"qO" = ( +/obj/structure/cable{ + icon_state = "4-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 + }, +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plasteel/dark, +/area/awaymission/academy/headmaster) +"qT" = ( +/obj/structure/trap/fire, +/turf/open/floor/carpet, +/area/awaymission/academy/academyaft) +"rz" = ( +/obj/structure/trap/damage, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/academy/academyaft) +"rU" = ( +/obj/structure/trap/fire, +/turf/open/floor/plating, +/area/awaymission/academy/classrooms) +"sI" = ( +/obj/structure/trap/stun, +/turf/open/floor/vault, +/area/awaymission/academy/academyengine) +"tH" = ( +/obj/structure/table/wood, +/obj/item/disk/design_disk/adv/knight_gear, +/turf/open/floor/wood, +/area/awaymission/academy/classrooms) +"yV" = ( +/obj/structure/chair/wood/normal{ + dir = 1 + }, +/obj/structure/trap/stun, +/turf/open/floor/wood, +/area/awaymission/academy/classrooms) +"Ao" = ( +/obj/effect/landmark/awaystart, +/turf/open/floor/plating, +/area/awaymission/academy/academygate) +"Ck" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/trap/chill, +/turf/open/floor/plasteel, +/area/awaymission/academy/classrooms) +"Cu" = ( +/obj/structure/trap/fire, +/turf/open/floor/plasteel, +/area/awaymission/academy/classrooms) +"Dd" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/trap/damage, +/turf/open/floor/carpet, +/area/awaymission/academy/headmaster) +"Di" = ( +/obj/structure/trap/stun, +/turf/open/floor/plasteel, +/area/awaymission/academy/academyengine) +"Fh" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/trap/damage, +/turf/open/floor/plasteel/grimy, +/area/awaymission/academy/classrooms) +"Im" = ( +/obj/structure/trap/damage, +/turf/open/floor/plasteel, +/area/awaymission/academy/classrooms) +"Kw" = ( +/obj/structure/trap/damage, +/turf/open/floor/wood, +/area/awaymission/academy/classrooms) +"KR" = ( +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plasteel/white, +/area/awaymission/academy/classrooms) "LW" = ( /obj/structure/cable{ icon_state = "4-8" @@ -4443,6 +4485,63 @@ }, /turf/open/floor/plating, /area/awaymission/academy/academyaft) +"Mx" = ( +/obj/structure/trap/chill, +/turf/open/floor/plasteel/grimy, +/area/awaymission/academy/academyaft) +"Nj" = ( +/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/structure/trap/damage, +/turf/open/floor/plasteel/dark, +/area/awaymission/academy/headmaster) +"NK" = ( +/obj/effect/landmark/awaystart, +/turf/open/floor/carpet, +/area/awaymission/academy/academygate) +"Oj" = ( +/obj/structure/trap/fire, +/turf/open/floor/wood, +/area/awaymission/academy/classrooms) +"Oq" = ( +/obj/structure/trap/chill, +/turf/open/floor/wood, +/area/awaymission/academy/classrooms) +"Rg" = ( +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plasteel/showroomfloor, +/area/awaymission/academy/headmaster) +"RB" = ( +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plasteel/dark, +/area/awaymission/academy/headmaster) +"Sd" = ( +/obj/structure/chair/stool, +/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 + }, +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plasteel/dark, +/area/awaymission/academy/classrooms) +"Sz" = ( +/obj/structure/trap/chill, +/turf/open/floor/plasteel, +/area/awaymission/academy/classrooms) "Tk" = ( /obj/structure/cable{ icon_state = "4-8" @@ -4453,6 +4552,25 @@ }, /turf/open/floor/plating, /area/awaymission/academy/academyaft) +"Va" = ( +/mob/living/simple_animal/hostile/wizard, +/turf/open/floor/plasteel, +/area/awaymission/academy/classrooms) +"Wy" = ( +/obj/structure/fluff/divine/defensepylon, +/turf/open/floor/plating, +/area/awaymission/academy/academyengine) +"WZ" = ( +/turf/open/space/basic, +/area/space) +"XX" = ( +/obj/structure/trap/fire, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/academy/academyaft) +"YK" = ( +/obj/structure/trap/chill, +/turf/open/floor/carpet, +/area/awaymission/academy/classrooms) (1,1,1) = {" aa @@ -5193,7 +5311,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -5816,7 +5934,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -6217,6 +6335,7 @@ aa aa aa aa +ac aa aa aa @@ -6225,8 +6344,7 @@ aa aa aa aa -aa -aa +ac aa aa aa @@ -6310,6 +6428,8 @@ aa aa aa aa +WZ +ac aa aa aa @@ -6322,9 +6442,7 @@ aa aa aa aa -aa -aa -aa +ac aa aa aa @@ -6429,7 +6547,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -6626,7 +6744,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -6653,7 +6771,7 @@ mN mN mN mN -mN +nr mN mN mD @@ -7458,6 +7576,7 @@ aa aa aa aa +ac aa aa aa @@ -7503,8 +7622,7 @@ aa aa aa aa -aa -aa +ac aa aa aa @@ -7804,7 +7922,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -8506,7 +8624,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -9059,7 +9177,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -9101,7 +9219,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -9501,7 +9619,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -10073,7 +10191,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -10186,7 +10304,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -10234,7 +10352,7 @@ ea es bB bB -bB +rU bB es ea @@ -10622,7 +10740,7 @@ de bE eb et -bz +Sz eK eT bz @@ -10739,7 +10857,7 @@ bv bB bB cj -bB +ox bB bB bB @@ -10894,7 +11012,7 @@ ga ga ga ga -ga +Ck ga gZ hc @@ -11001,14 +11119,14 @@ bB bB bB bB -bB +ox cO cZ bz bz cY bz -bz +Cu dT ee ee @@ -11367,7 +11485,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -11460,7 +11578,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -11788,7 +11906,7 @@ df ds dc dc -dc +Oj dV ej ej @@ -11931,7 +12049,7 @@ fz es dc gd -df +tH ds gd df @@ -12174,7 +12292,7 @@ bZ fR cQ dc -dc +Oq dc dc dc @@ -12205,7 +12323,7 @@ fD im il iw -il +rz il il iw @@ -12303,9 +12421,9 @@ bZ bZ cK cQ -dc +Kw dg -ds +yV df ds dc @@ -12434,7 +12552,7 @@ cC cC cR dd -dc +Oj dc dc dc @@ -12455,7 +12573,7 @@ dc dc dc dc -dc +Kw dc fD ho @@ -12767,7 +12885,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -12855,7 +12973,7 @@ ii ii ii ii -ii +qF ii ii ii @@ -12870,7 +12988,7 @@ fF jG gF fN -fN +Mx hc jT jV @@ -12879,10 +12997,10 @@ jY jW jW ki -kf -kf -kf -jW +Ao +Ao +Ao +NK kx jS mE @@ -13009,9 +13127,9 @@ jZ kb ke kj -km -kp -ks +kk +kf +kf kf kf ky @@ -13064,7 +13182,7 @@ aE aJ as ah -ah +cI aQ cI ah @@ -13138,10 +13256,10 @@ jV jY kc jW -kf +Ao kn kI -kt +kf kf kf ky @@ -13187,7 +13305,7 @@ aa kF ae ah -al +nh at az aF @@ -13220,7 +13338,7 @@ ah ah ah ah -el +YK ej el eN @@ -13269,9 +13387,9 @@ jY kc jW kf -ko -kr -ku +kf +kf +kf kf kf ky @@ -13332,7 +13450,7 @@ ap ba bh bk -ap +Dd bq ap ap @@ -13398,11 +13516,11 @@ jW ka kc kf -kf -kf -kf -kf -kf +Ao +Ao +Ao +Ao +Ao kf ky mG @@ -13488,7 +13606,7 @@ eV fe ej el -fF +qT fF fF fF @@ -13516,7 +13634,7 @@ fF fD jr jy -fF +qT jH fF fN @@ -13875,7 +13993,7 @@ ej ej eP ej -fg +Fh ej ej bE @@ -13954,7 +14072,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -14118,9 +14236,9 @@ aa ab bM cd -cl +Nj cd -bO +qO cd cT as @@ -14157,7 +14275,7 @@ il iz il il -il +XX iz il fD @@ -14274,7 +14392,7 @@ gm fP fP gI -gO +Sd gJ gO fD @@ -14377,7 +14495,7 @@ aP aP ab bO -cd +RB cl cd cl @@ -14834,6 +14952,7 @@ aa aa aa aa +ac aa aa aa @@ -14844,8 +14963,7 @@ aa aa aa aa -aa -aa +ac aa aa aa @@ -14899,18 +15017,18 @@ ab bT bT bT -bT +Rg bT cg bT as di bz +Va bz bz bz -bz -bz +Im ex eD eD @@ -15399,7 +15517,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -15687,12 +15805,12 @@ bs dm dm dm -dm +KR dR dZ dZ ey -eI +ig eI eI fm @@ -15928,7 +16046,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -16775,7 +16893,7 @@ aG aG mc me -me +Wy me lv mm @@ -16906,7 +17024,7 @@ aG mc mf me -me +Wy lv mm mm @@ -17024,7 +17142,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -17043,7 +17161,7 @@ lv lM mc mw -mq +mI mq mq mq @@ -17164,7 +17282,7 @@ aa aG aG mc -lv +lC lv lv lv @@ -17369,7 +17487,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -17528,7 +17646,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -17898,7 +18016,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -18205,7 +18323,7 @@ aa aG md mg -lt +sI lt lt md @@ -18346,7 +18464,7 @@ mu mu mu mu -ng +lF aa aa aa @@ -18476,7 +18594,7 @@ mu mu mA mu -nh +lF aa aa aa @@ -18606,7 +18724,7 @@ mu my mz mM -nh +lF aa aa aa @@ -18643,7 +18761,7 @@ kW dK dK gN -dK +ng dK le aL @@ -18729,14 +18847,14 @@ aG aG aG mc -mq +Di lJ mu mu mu mC mu -nh +lF aa aa aa @@ -18866,7 +18984,7 @@ mu mu mB mu -nh +lF aa aa aa @@ -18996,7 +19114,7 @@ mu mu mu mu -ni +lF aa aa aa @@ -19305,7 +19423,7 @@ aG lq ly lv -lv +ni lv lU lq @@ -19320,7 +19438,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -19785,7 +19903,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -19986,7 +20104,7 @@ aa aa aa aa -aa +ac aa aa aa @@ -20146,7 +20264,7 @@ aa aa aa aa -aa +ac aa aa aa diff --git a/_maps/RandomZLevels/away_mission/Cabin.dmm b/_maps/RandomZLevels/away_mission/Cabin.dmm deleted file mode 100644 index a0862213a2..0000000000 --- a/_maps/RandomZLevels/away_mission/Cabin.dmm +++ /dev/null @@ -1,66505 +0,0 @@ -//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"aa" = ( -/turf/closed/indestructible/rock/snow, -/area/space) -"ab" = ( -/turf/closed/indestructible/rock/snow, -/area/awaymission/snowforest) -"ac" = ( -/turf/open/floor/plating/asteroid/snow/temperatre, -/area/awaymission/snowforest) -"ad" = ( -/turf/closed/wall/mineral/wood, -/area/awaymission/snowforest/lumbermill) -"ae" = ( -/obj/item/grown/log/tree, -/turf/open/floor/plating/asteroid/snow/temperatre, -/area/awaymission/snowforest) -"af" = ( -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"ag" = ( -/obj/machinery/conveyor_switch/oneway{ - id = "lumbermill" - }, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"ah" = ( -/obj/machinery/conveyor{ - dir = 4; - id = "lumbermill" - }, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"ai" = ( -/obj/machinery/recycler/lumbermill, -/obj/machinery/conveyor{ - dir = 4; - id = "lumbermill" - }, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"aj" = ( -/obj/item/grown/log/tree, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"ak" = ( -/obj/structure/table/wood, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"al" = ( -/obj/structure/table/wood, -/obj/item/grown/log/tree, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"am" = ( -/obj/structure/table/wood, -/obj/item/twohanded/required/chainsaw, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest/lumbermill) -"an" = ( -/turf/closed/wall/mineral/wood, -/area/awaymission/cabin) -"ao" = ( -/obj/structure/window/fulltile, -/turf/open/floor/plating, -/area/awaymission/cabin) -"ap" = ( -/obj/structure/closet/crate/bin, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aq" = ( -/turf/open/floor/wood, -/area/awaymission/cabin) -"ar" = ( -/obj/machinery/door/airlock/wood{ - name = "bathroom" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"as" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/structure/mirror{ - pixel_y = 28 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"at" = ( -/obj/structure/sink{ - dir = 8; - pixel_x = -12; - pixel_y = 2 - }, -/obj/structure/mirror{ - pixel_y = 28 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"au" = ( -/obj/structure/dresser, -/turf/open/floor/wood, -/area/awaymission/cabin) -"av" = ( -/obj/machinery/power/apc{ - dir = 1; - name = "cabin APC" - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aw" = ( -/obj/machinery/power/smes/magical, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"ax" = ( -/obj/structure{ - density = 1; - desc = "Generates power from lava!"; - dir = 2; - icon = 'icons/obj/atmospherics/pipes/simple.dmi'; - icon_state = "turbine"; - name = "geothermal generator" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"ay" = ( -/obj/machinery/light/small, -/obj/structure/table/wood, -/obj/item/toy/syndicateballoon, -/turf/open/floor/wood, -/area/awaymission/cabin) -"az" = ( -/turf/open/floor/carpet, -/area/awaymission/cabin) -"aA" = ( -/obj/structure/bed, -/obj/item/bedsheet/brown, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aB" = ( -/obj/structure/toilet{ - dir = 8 - }, -/obj/machinery/light/small{ - dir = 8 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"aC" = ( -/obj/structure/toilet{ - dir = 4 - }, -/obj/machinery/light/small{ - dir = 4 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"aD" = ( -/obj/machinery/light/small{ - dir = 8 - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aE" = ( -/obj/machinery/power/terminal{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aF" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aG" = ( -/obj/item/reagent_containers/pill/patch/styptic, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"aH" = ( -/obj/machinery/light{ - dir = 8 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aI" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/table/wood, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aJ" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 8 - }, -/obj/machinery/door/window/northright, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"aK" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 4 - }, -/obj/machinery/door/window/northleft, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"aL" = ( -/turf/open/floor/plating, -/area/awaymission/cabin) -"aM" = ( -/obj/machinery/telecomms/relay/preset/mining, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aN" = ( -/obj/structure/chair/wood{ - dir = 4 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aO" = ( -/obj/structure/table/wood, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"aP" = ( -/obj/structure/chair/wood{ - dir = 8 - }, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"aQ" = ( -/obj/machinery/door/airlock/wood{ - name = "maintenance" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aR" = ( -/obj/machinery/door/window/westright{ - name = "fireplace" - }, -/obj/structure/fireplace, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aS" = ( -/obj/structure/extinguisher_cabinet{ - pixel_y = 24 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aT" = ( -/obj/machinery/door/window/eastleft{ - name = "fireplace" - }, -/obj/structure/fireplace, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aU" = ( -/obj/structure/fireplace, -/obj/machinery/door/window/westright{ - name = "fireplace" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aV" = ( -/obj/machinery/space_heater, -/turf/open/floor/wood, -/area/awaymission/cabin) -"aW" = ( -/obj/structure/fireplace, -/obj/machinery/door/window/eastleft{ - name = "fireplace" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) -"aX" = ( -/obj/structure/closet/crate/bin, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"aY" = ( -/obj/structure/table/wood, -/obj/item/phone, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"aZ" = ( -/obj/structure/guncase/shotgun, -/obj/item/gun/ballistic/shotgun/riot, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"ba" = ( -/obj/machinery/door/airlock/wood, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bb" = ( -/obj/machinery/light{ - dir = 8 - }, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"bc" = ( -/obj/structure/table/wood, -/obj/item/reagent_containers/food/drinks/britcup, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"bd" = ( -/obj/structure/chair/office/dark, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"be" = ( -/obj/machinery/computer/crew, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"bf" = ( -/obj/machinery/door/airlock/wood{ - name = "manager's office" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bg" = ( -/obj/machinery/door/window/westright{ - name = "manager's desk" - }, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"bh" = ( -/obj/machinery/light, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bi" = ( -/obj/machinery/door/airlock/wood{ - name = "manager's bedroom" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bj" = ( -/obj/structure/toilet, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bk" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bl" = ( -/obj/machinery/vending/autodrobe{ - req_access_txt = "0" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bm" = ( -/obj/machinery/door/airlock/wood{ - name = "stage left" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bn" = ( -/obj/machinery/light{ - dir = 1 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bo" = ( -/obj/structure/window{ - dir = 4 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bp" = ( -/obj/structure/chair/wood{ - dir = 8 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bq" = ( -/obj/structure/table/wood, -/obj/machinery/chem_dispenser/drinks, -/turf/open/floor/wood, -/area/awaymission/cabin) -"br" = ( -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/computer/arcade/orion_trail, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bs" = ( -/obj/machinery/computer/arcade/battle, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bt" = ( -/obj/machinery/computer/slot_machine, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bu" = ( -/obj/structure/table/wood, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bv" = ( -/obj/structure/table/wood, -/obj/machinery/chem_dispenser/drinks/beer{ - dir = 8 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bw" = ( -/obj/machinery/vending/dinnerware, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"bx" = ( -/obj/machinery/smartfridge, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"by" = ( -/obj/structure/table, -/obj/machinery/reagentgrinder, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"bz" = ( -/obj/structure/closet/secure_closet/freezer/kitchen, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"bA" = ( -/obj/machinery/chem_master/condimaster, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bB" = ( -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bC" = ( -/obj/machinery/gibber, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bD" = ( -/obj/structure/table/optable, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bE" = ( -/obj/machinery/computer/operating, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bF" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/machinery/portable_atmospherics/canister/oxygen, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bG" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bH" = ( -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bI" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 4 - }, -/obj/machinery/door/window/eastright, -/obj/structure/window{ - icon_state = "window"; - dir = 1 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bJ" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bK" = ( -/obj/effect/decal/cleanable/blood, -/obj/item/reagent_containers/pill/patch/styptic, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"bL" = ( -/obj/structure/bed, -/obj/item/bedsheet/patriot, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bM" = ( -/obj/machinery/vending/clothing, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bN" = ( -/obj/machinery/vending/boozeomat{ - req_access_txt = "0" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bO" = ( -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"bP" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 5 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bQ" = ( -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bR" = ( -/obj/machinery/atmospherics/components/unary/cryo_cell, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"bS" = ( -/turf/open/floor/wood/cold, -/area/awaymission/snowforest) -"bT" = ( -/obj/structure/table/wood, -/obj/item/instrument/violin, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bU" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/table/wood, -/obj/item/reagent_containers/food/drinks/shaker, -/turf/open/floor/wood, -/area/awaymission/cabin) -"bV" = ( -/obj/structure/table, -/obj/item/kitchen/knife/butcher, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"bW" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/table, -/obj/machinery/microwave, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"bX" = ( -/obj/structure/closet/crate/bin, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bY" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/processor, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"bZ" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/table, -/obj/item/surgicaldrill, -/obj/item/circular_saw, -/obj/item/cautery, -/obj/item/surgical_drapes, -/obj/item/scalpel, -/obj/item/hemostat, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"ca" = ( -/obj/machinery/atmospherics/pipe/simple/general/visible{ - dir = 9 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"cb" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cc" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cd" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"ce" = ( -/obj/structure/chair/wood{ - dir = 4 - }, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest) -"cf" = ( -/obj/structure/table/wood, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest) -"cg" = ( -/obj/structure/chair/wood{ - dir = 8 - }, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest) -"ch" = ( -/obj/machinery/light/small{ - dir = 8 - }, -/obj/structure/table/wood, -/obj/item/instrument/guitar, -/turf/open/floor/wood, -/area/awaymission/cabin) -"ci" = ( -/obj/structure/chair/wood, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cj" = ( -/obj/structure/table, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"ck" = ( -/obj/structure/table, -/obj/machinery/microwave, -/turf/open/floor/plasteel/cafeteria, -/area/awaymission/cabin) -"cl" = ( -/obj/structure/kitchenspike, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"cm" = ( -/obj/structure/table, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"cn" = ( -/obj/structure/bed/roller, -/obj/item/bedsheet, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"co" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cp" = ( -/obj/machinery/gateway/centeraway, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cq" = ( -/obj/machinery/gateway{ - dir = 4 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cr" = ( -/obj/machinery/light/small{ - dir = 4 - }, -/turf/open/floor/wood/cold, -/area/awaymission/snowforest) -"cs" = ( -/obj/structure/table/wood, -/obj/item/wrench, -/turf/open/floor/wood, -/area/awaymission/cabin) -"ct" = ( -/obj/structure/closet/secure_closet/freezer/fridge, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"cu" = ( -/obj/machinery/sleeper{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"cv" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/table, -/obj/item/storage/firstaid/regular, -/obj/item/storage/firstaid/brute, -/obj/item/storage/firstaid/fire, -/turf/open/floor/plasteel/white, -/area/awaymission/cabin) -"cw" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cx" = ( -/obj/machinery/gateway, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cy" = ( -/obj/machinery/gateway{ - dir = 6 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cz" = ( -/obj/structure/musician/piano, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cA" = ( -/obj/machinery/door/airlock/wood{ - name = "stage right" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cB" = ( -/obj/machinery/door/window/eastleft, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cC" = ( -/obj/structure/chair/wood{ - dir = 1 - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cD" = ( -/obj/machinery/door/window/westright{ - name = "bar" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cE" = ( -/obj/machinery/door/airlock/wood{ - name = "kitchen" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cF" = ( -/obj/machinery/door/airlock/wood{ - name = "kitchen cold room" - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"cG" = ( -/obj/structure/closet/secure_closet/freezer/meat, -/turf/open/floor/plasteel/freezer, -/area/awaymission/cabin) -"cH" = ( -/obj/effect/landmark/awaystart, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cI" = ( -/obj/machinery/door/airlock/wood{ - name = "backstage" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cJ" = ( -/obj/machinery/door/airlock/glass_large{ - name = "medbay" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cK" = ( -/obj/machinery/door/airlock/wood{ - name = "cabin" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cL" = ( -/obj/structure/sign/barsign{ - pixel_y = 32; - req_access = null - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cM" = ( -/obj/machinery/door/airlock/wood{ - name = "gateway" - }, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cN" = ( -/obj/machinery/vending/snack, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cO" = ( -/obj/machinery/light, -/obj/machinery/vending/cola, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cP" = ( -/obj/machinery/vending/cigarette, -/turf/open/floor/wood, -/area/awaymission/cabin) -"cQ" = ( -/obj/machinery/light{ - dir = 4 - }, -/turf/open/floor/carpet, -/area/awaymission/cabin) -"cR" = ( -/obj/machinery/door/poddoor/shutters{ - id = "garage_cabin"; - name = "garage door" - }, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cS" = ( -/obj/machinery/button/door{ - id = "garage_cabin"; - pixel_y = 24 - }, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cT" = ( -/obj/vehicle/ridden/atv, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cU" = ( -/obj/machinery/light{ - dir = 1 - }, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cV" = ( -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cW" = ( -/obj/structure/closet, -/obj/item/key, -/obj/item/key, -/obj/item/key, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cX" = ( -/obj/machinery/light, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/cabin) -"cY" = ( -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/asteroid/snow/temperatre, -/area/awaymission/snowforest) -"cZ" = ( -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"da" = ( -/obj/structure/chair, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"db" = ( -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dc" = ( -/obj/structure/chair, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dd" = ( -/obj/effect/decal/cleanable/blood/gibs, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"de" = ( -/obj/structure/chair{ - dir = 4 - }, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"df" = ( -/obj/structure/kitchenspike, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dg" = ( -/obj/structure/table, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dh" = ( -/obj/structure/kitchenspike, -/obj/effect/decal/cleanable/blood/gibs, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"di" = ( -/obj/structure/chair{ - dir = 8 - }, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dj" = ( -/turf/open/floor/plating/ice/temperate, -/area/awaymission/snowforest) -"dk" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dl" = ( -/obj/item/shard, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dm" = ( -/obj/structure/chair{ - dir = 8 - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dn" = ( -/obj/effect/decal/cleanable/blood/gibs/limb, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"do" = ( -/obj/item/chair, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dp" = ( -/obj/effect/decal/cleanable/blood/gibs/body, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dq" = ( -/obj/item/shard, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dr" = ( -/obj/structure/chair{ - dir = 1 - }, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"ds" = ( -/obj/structure/chair{ - dir = 1 - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/snowed/temperatre, -/area/awaymission/snowforest) -"dt" = ( -/obj/effect/landmark/mapGenerator/snowy, -/turf/open/floor/plating/asteroid/snow/temperatre, -/area/awaymission/snowforest) -"du" = ( -/obj/structure/closet/toolcloset, -/obj/item/lightreplacer, -/obj/item/storage/toolbox/mechanical, -/turf/open/floor/plating, -/area/awaymission/cabin) -"dv" = ( -/obj/structure{ - density = 1; - desc = "Generates power from lava!"; - dir = 1; - icon = 'icons/obj/atmospherics/pipes/simple.dmi'; - icon_state = "compressor"; - name = "geothermal generator" - }, -/turf/open/floor/plating, -/area/awaymission/cabin) - -(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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -"} -(3,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -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 -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 -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 -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 -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 -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 -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 -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 -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 -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 -"} -(6,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(7,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(8,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(9,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(10,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(11,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(12,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(13,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(14,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(15,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(16,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(17,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(18,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(19,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(20,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(21,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(22,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(23,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(24,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(25,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(26,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(27,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(28,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(29,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(30,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(31,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(32,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(33,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(34,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(35,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(36,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -"} -(37,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dt -ab -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 -aa -aa -aa -aa -aa -aa -"} -(38,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(39,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(41,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(42,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(43,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(44,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(45,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(46,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(47,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(48,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(49,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(50,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(51,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(52,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(53,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(54,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(55,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(56,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(57,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(58,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(59,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(60,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(61,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(62,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(63,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(64,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(65,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(66,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(67,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(68,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(69,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(70,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(71,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(72,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -bS -bS -bS -bS -bS -bS -bS -bS -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(73,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -bS -ce -ce -ce -bS -bS -bS -bS -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(74,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -bS -cf -cf -cf -bS -bS -bS -bS -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(75,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -bS -cg -cg -cg -bS -bS -bS -bS -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(76,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -bS -bS -cr -bS -bS -bS -bS -bS -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(77,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -an -an -ao -ao -an -an -an -an -an -an -an -an -cK -cK -an -cR -cR -cR -cR -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(78,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ap -au -aH -aN -aq -an -aq -aq -an -bl -bM -bT -ch -cs -cz -an -aq -aq -an -cS -cV -cV -cV -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(79,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aO -aq -ba -aq -aq -an -aq -aq -aq -aq -aq -aq -cI -aq -aq -an -cT -cT -cT -cT -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(80,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aP -aq -an -aq -bh -an -bm -an -an -an -an -cA -an -aq -aq -an -cU -cV -cV -cX -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(81,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -az -aq -an -aq -aq -an -aq -aq -aq -aq -aq -aq -an -aq -aq -an -cT -cT -cT -cT -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(82,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -aq -aA -aI -aA -aq -an -aq -aq -an -bn -aq -aq -aq -aq -bh -an -aq -bh -an -cV -cV -cV -cV -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(83,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ar -an -an -an -aR -an -aq -aq -an -aq -aq -aq -aq -aq -aq -an -aq -aq -an -cU -cV -cV -cX -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(84,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -as -aB -aJ -an -an -an -aq -aq -an -bn -aq -aq -aq -aq -bh -an -aq -aq -an -cV -cV -cV -cV -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(85,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -aS -ba -aq -bh -an -bo -bo -bo -bo -bo -cB -an -aq -aq -ba -cV -cV -cV -cV -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(86,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -at -aC -aK -an -an -an -aq -aq -an -bp -bp -bp -bp -bp -aq -aq -aq -aq -an -cV -cV -cW -cW -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(87,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ar -an -an -an -aT -an -aq -aq -an -bp -bp -bp -bp -bp -aq -aq -aq -cN -an -an -an -an -an -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(88,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -aq -ap -aH -aN -aq -an -aq -aq -ba -aq -aq -aq -aq -aq -aq -aq -aq -cO -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(89,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aO -aq -an -aq -aq -an -bq -aq -aq -aq -aq -aq -aq -aq -cP -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(90,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aP -aq -an -aq -bh -an -br -aq -aq -aq -aN -aq -aq -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(91,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -az -aq -ba -aq -aq -an -bs -aq -aq -ci -bu -cC -aq -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(92,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -au -aA -aI -aA -aq -an -aq -aq -an -bt -aq -aq -aq -bp -aq -aq -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(93,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -an -an -aq -aq -an -ap -aq -aq -aq -aq -aq -aq -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(94,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ap -au -aH -aN -aq -an -aq -aq -an -aN -aN -aN -aN -aN -aq -aq -aq -bh -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(95,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aO -aq -ba -aq -bh -an -bu -bu -bu -bu -bu -cD -an -cL -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(96,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aP -aq -an -aq -aq -an -aq -aq -aq -aq -aq -aq -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(97,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -az -aq -an -aq -aq -an -bv -bN -bU -aq -ap -aq -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(98,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -aq -aA -aI -aA -aq -an -aq -aq -an -an -an -an -bu -an -cE -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(99,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ar -an -an -an -aU -an -aq -aq -an -bw -bO -bO -bO -bO -bO -cE -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(100,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -as -aB -aJ -an -an -an -aq -aq -an -bx -bO -bV -cj -cj -bO -an -aq -bh -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(101,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -aV -ba -aq -aq -an -by -bO -bO -bO -bO -bO -an -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(102,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -at -aC -aK -an -an -an -aq -bh -an -bz -bO -bW -ck -cj -bO -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(103,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ar -an -an -an -aW -an -aq -aq -an -an -an -an -an -an -cF -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(104,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -aq -ap -aH -aN -aq -an -aq -aq -an -bA -bB -bX -cl -cl -bB -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(105,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aO -aq -an -aq -aq -an -bB -bB -bB -bB -bB -bB -an -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(106,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aP -aq -an -aq -aq -an -bC -bB -bY -bB -ct -cG -an -aq -bh -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(107,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -az -aq -ba -aq -aq -an -an -an -an -an -an -an -an -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -dj -dj -dj -dj -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(108,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -au -aA -aI -aA -aq -an -aq -aq -an -bD -bH -bZ -cm -cu -cu -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(109,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -an -an -aq -bh -an -bE -bH -bH -bH -bH -bH -an -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(110,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ap -au -aH -aN -aq -an -aq -aq -an -bF -bP -bH -bH -bH -bH -cJ -aq -aq -ao -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(111,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aO -aq -ba -aq -aq -an -bG -bQ -bP -bH -bH -bH -aq -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(112,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -aP -aq -an -aq -aq -an -bH -bR -ca -cn -cv -cn -an -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(113,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ao -aq -az -az -az -aq -an -aq -aq -an -an -an -an -an -an -an -an -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(114,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -aq -aA -aI -aA -aq -an -aq -aq -aq -aq -aq -aH -aq -aq -aq -aq -aq -bh -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(115,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -ar -an -an -an -aU -an -aq -aq -aq -aq -aq -aq -aq -aq -aq -aq -aq -aq -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(116,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -as -aB -aJ -an -an -an -bf -an -an -an -an -an -an -an -an -an -cM -cM -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(117,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -aX -bb -az -an -bj -bI -an -aq -aH -aq -cH -bu -az -az -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(118,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -av -aD -aL -aQ -az -az -az -an -bk -bJ -an -cb -co -cw -cH -bu -az -az -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(119,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -aw -aE -aL -an -aY -bc -bg -an -ar -an -an -cc -cp -cx -cH -aq -az -az -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(120,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -du -aF -aL -an -az -bd -az -an -aq -ay -an -cd -cq -cy -cH -bu -az -az -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(121,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -dv -ax -aM -an -aZ -be -az -bi -aq -bL -an -aq -aq -aq -cH -bu -az -cQ -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(122,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -an -an -an -an -an -ao -ao -ao -an -an -ao -an -an -ao -ao -ao -ao -ao -an -an -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(123,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(124,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cY -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(125,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cZ -cZ -cZ -de -de -de -de -de -de -dk -dk -cZ -cZ -cZ -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(126,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cZ -db -cZ -de -dk -de -dk -de -de -de -de -db -aG -cZ -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(127,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cY -cZ -cZ -cZ -dd -cZ -cZ -cZ -cZ -dd -cZ -cZ -cZ -db -cZ -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(128,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -da -cZ -df -df -df -df -dh -df -dg -df -cZ -dr -dr -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(129,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -da -bK -dg -cZ -cZ -do -cZ -cZ -db -df -cZ -dr -dr -cY -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(130,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -da -cZ -df -dl -cZ -db -cZ -dn -dq -df -cZ -dr -dr -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(131,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -dc -cZ -df -cZ -dn -cZ -cZ -cZ -cZ -df -cZ -ds -dr -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(132,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -da -dd -df -cZ -dl -cZ -db -cZ -db -df -cZ -dr -dr -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(133,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -da -cZ -df -cZ -db -cZ -cZ -cZ -dl -df -cZ -dr -ds -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(134,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ae -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -dc -cZ -dh -cZ -cZ -dp -cZ -do -dp -dg -db -ds -dr -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(135,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ae -ae -ac -ae -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -da -da -cZ -df -dg -df -df -df -df -df -df -cZ -dr -dr -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(136,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -ag -ah -aj -ak -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cY -cZ -cZ -cZ -db -cZ -cZ -aG -dd -cZ -cZ -cZ -cZ -cZ -cZ -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(137,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -aj -al -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cZ -aG -db -di -dm -di -di -di -dm -di -di -cZ -aG -cZ -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(138,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -af -ak -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cZ -cZ -cZ -di -di -di -dm -di -di -di -di -cZ -cZ -cZ -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(139,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -af -am -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cY -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(140,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -af -am -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -cY -ac -ac -ac -ac -ac -cY -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(141,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -af -am -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(142,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -af -am -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(143,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ai -af -ak -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(144,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -af -ah -af -ak -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(145,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ad -af -ag -ah -af -ak -ad -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(146,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(147,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(148,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(149,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(150,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(151,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(152,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(153,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(154,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(155,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(156,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(157,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(158,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(159,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ac -ab -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 -aa -aa -aa -aa -aa -aa -"} -(160,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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -"} -(161,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(162,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(163,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(164,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(165,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(166,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(167,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(168,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(169,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(170,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(171,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(172,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(173,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(174,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(175,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(176,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(177,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(178,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(179,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(180,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(181,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(182,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(183,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(184,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(185,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(186,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(187,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(188,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(189,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(190,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(191,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(192,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(193,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(194,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(195,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(196,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(197,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(198,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(199,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(200,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(201,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(202,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(203,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(204,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(205,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(206,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(207,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(208,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(209,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(210,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(211,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(212,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(213,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(214,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(215,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(216,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(217,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(218,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(219,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(220,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(221,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(222,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(223,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(224,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(225,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(226,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(227,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(228,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(229,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(230,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(231,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(232,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(233,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(234,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(235,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(236,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(237,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(238,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(239,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(240,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(241,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(242,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(243,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(244,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(245,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(246,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(247,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(248,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(249,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(250,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(251,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(252,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(253,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(254,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(255,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 -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 -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 -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 -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 -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} diff --git a/_maps/RandomZLevels/away_mission/SnowCabin.dmm b/_maps/RandomZLevels/away_mission/SnowCabin.dmm new file mode 100644 index 0000000000..249cb68b5d --- /dev/null +++ b/_maps/RandomZLevels/away_mission/SnowCabin.dmm @@ -0,0 +1,71027 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aa" = ( +/obj/structure/flora{ + desc = "Looks frozen."; + icon = 'icons/obj/flora/snowflora.dmi'; + icon_state = "snowgrass"; + name = "frozen flora" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"ab" = ( +/turf/closed/indestructible/rock/snow, +/area/awaymission/cabin/caves/mountain) +"ac" = ( +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"ad" = ( +/turf/closed/wall/mineral/wood, +/area/awaymission/cabin/lumbermill) +"ae" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"af" = ( +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ag" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"ah" = ( +/obj/structure/fence/door/opened, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"ai" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 5 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"aj" = ( +/turf/closed/indestructible/hotelwall{ + desc = "This wall looks stupid."; + name = "Purgatory" + }, +/area/awaymission/cabin/caves/mountain) +"ak" = ( +/obj/structure/table/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"al" = ( +/obj/structure/table/wood, +/obj/structure/showcase/machinery/tv{ + desc = "A slightly battered looking TV. Various infomercials play on a loop, accompanied by a jaunty tune."; + name = "Television Screen" + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"am" = ( +/obj/structure/chair/comfy{ + color = "#B22222"; + dir = 8 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"an" = ( +/turf/closed/wall/mineral/wood, +/area/awaymission/cabin) +"ao" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ap" = ( +/obj/structure/closet/crate/bin, +/turf/open/floor/wood, +/area/awaymission/cabin) +"aq" = ( +/turf/open/floor/wood, +/area/awaymission/cabin) +"ar" = ( +/obj/machinery/door/airlock/command{ + name = "Manager's Office" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"as" = ( +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/obj/structure/mirror{ + pixel_y = 28 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"at" = ( +/obj/structure/sink{ + dir = 8; + pixel_x = -12; + pixel_y = 2 + }, +/obj/structure/mirror{ + pixel_y = 28 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"au" = ( +/obj/structure/dresser, +/turf/open/floor/wood, +/area/awaymission/cabin) +"av" = ( +/obj/machinery/telecomms/relay/preset/mining, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aw" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ax" = ( +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/closed/wall/mineral/wood, +/area/awaymission/cabin) +"ay" = ( +/obj/machinery/light/small, +/obj/item/storage/backpack/bannerpack{ + pixel_y = 7 + }, +/obj/structure/dresser, +/turf/open/floor/wood, +/area/awaymission/cabin) +"az" = ( +/turf/open/floor/carpet, +/area/awaymission/cabin) +"aA" = ( +/obj/structure/bed, +/obj/item/bedsheet/brown, +/turf/open/floor/wood, +/area/awaymission/cabin) +"aB" = ( +/obj/structure/toilet{ + dir = 8 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_x = -32 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"aC" = ( +/obj/structure/toilet{ + dir = 4 + }, +/obj/machinery/light/small{ + dir = 4 + }, +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_x = 32 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"aD" = ( +/obj/machinery/power/smes/magical{ + desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. It seems to be powered just fine without our intervention."; + name = "nanotrasen power storage unit" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aE" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/baseturf_helper/asteroid/snow, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"aF" = ( +/obj/machinery/power/apc{ + dir = 1; + name = "cabin APC"; + pixel_y = 23 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aG" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"aH" = ( +/obj/machinery/shower{ + dir = 1 + }, +/obj/structure/curtain, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"aI" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/awaymission/cabin) +"aJ" = ( +/obj/structure/table, +/obj/item/surgicaldrill, +/obj/item/circular_saw, +/obj/item/cautery, +/obj/item/surgical_drapes, +/obj/item/scalpel, +/obj/item/hemostat, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"aK" = ( +/obj/structure/table/optable, +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"aL" = ( +/turf/open/floor/plating, +/area/awaymission/cabin) +"aM" = ( +/obj/machinery/power/terminal{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"aN" = ( +/obj/structure/chair/wood{ + dir = 4 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"aO" = ( +/obj/structure/chair/wood{ + dir = 8 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"aP" = ( +/obj/structure/table/wood, +/obj/machinery/chem_dispenser/drinks{ + desc = "Contains a large reservoir of soft drinks so that you can refill your cup. For free."; + name = "free refill dispenser" + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"aQ" = ( +/obj/structure{ + anchored = 1; + density = 1; + desc = "Generates power from lava!"; + dir = 1; + icon = 'icons/obj/atmospherics/pipes/simple.dmi'; + icon_state = "compressor"; + name = "geothermal generator" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"aR" = ( +/obj/machinery/door/window/westright{ + name = "fireplace" + }, +/obj/structure/fireplace, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aS" = ( +/obj/structure/sink/kitchen{ + desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; + name = "sink"; + pixel_y = 28 + }, +/obj/structure/janitorialcart, +/obj/item/mop, +/obj/item/reagent_containers/glass/bucket, +/obj/item/caution, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aT" = ( +/obj/machinery/door/window/eastleft{ + name = "fireplace" + }, +/obj/structure/fireplace, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aU" = ( +/obj/structure/fireplace, +/obj/machinery/door/window/westright{ + name = "fireplace" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aV" = ( +/obj/machinery/space_heater, +/turf/open/floor/wood, +/area/awaymission/cabin) +"aW" = ( +/obj/structure/fireplace, +/obj/machinery/door/window/eastleft{ + name = "fireplace" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"aX" = ( +/obj/structure/closet/crate/bin, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"aY" = ( +/obj/structure/table/wood, +/obj/item/phone, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"aZ" = ( +/obj/structure/guncase/shotgun, +/obj/item/gun/ballistic/shotgun/riot, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"ba" = ( +/obj/structure/fans/tiny, +/obj/machinery/door/airlock/wood/glass{ + name = "Cabin" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bb" = ( +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bc" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/britcup, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bd" = ( +/obj/structure/chair/office, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"be" = ( +/obj/machinery/computer/crew{ + dir = 8 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bf" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bg" = ( +/obj/machinery/door/window/westleft{ + name = "manager's desk" + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bh" = ( +/obj/machinery/light, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bi" = ( +/obj/machinery/door/airlock/wood{ + id_tag = "WheresTheSyndiBalloon"; + name = "Manager's Bedroom" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bj" = ( +/obj/structure/toilet{ + dir = 4 + }, +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bk" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bl" = ( +/obj/machinery/vending/autodrobe, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bm" = ( +/obj/machinery/door/airlock/wood{ + id_tag = "snowdinbutworse5"; + name = "Cabin 5" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bn" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bo" = ( +/obj/structure/window{ + dir = 4 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bp" = ( +/obj/structure/chair/wood{ + dir = 8 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bq" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/vending/cigarette, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bs" = ( +/obj/machinery/newscaster{ + pixel_y = 32 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bt" = ( +/obj/machinery/vending/coffee, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"bu" = ( +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bv" = ( +/obj/structure/table/wood, +/obj/machinery/chem_dispenser/drinks/beer{ + dir = 8 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bw" = ( +/obj/machinery/vending/dinnerware, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"bx" = ( +/obj/machinery/smartfridge, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"by" = ( +/obj/structure/table, +/obj/machinery/reagentgrinder, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"bz" = ( +/obj/structure/sink/kitchen{ + desc = "A sink used for washing one's hands and face. It looks rusty and home-made"; + name = "sink"; + pixel_y = 28 + }, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"bA" = ( +/obj/machinery/chem_master/condimaster, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bB" = ( +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bC" = ( +/obj/machinery/gibber, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bD" = ( +/obj/machinery/computer/operating, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"bE" = ( +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"bF" = ( +/obj/machinery/atmospherics/components/unary/cryo_cell, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"bG" = ( +/obj/structure/sink{ + dir = 8; + pixel_x = -12; + pixel_y = 2 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"bH" = ( +/obj/machinery/shower{ + dir = 1 + }, +/obj/structure/curtain, +/obj/item/soap/nanotrasen{ + pixel_x = -1; + pixel_y = -3 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bJ" = ( +/obj/structure/sink{ + dir = 4; + pixel_x = 11 + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bK" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"bL" = ( +/obj/structure/bed, +/obj/item/bedsheet/nanotrasen, +/obj/item/clothing/suit/hooded/wintercoat/captain{ + name = "manager's winter coat" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bM" = ( +/obj/machinery/vending/clothing, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bN" = ( +/obj/machinery/vending/boozeomat, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bO" = ( +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"bP" = ( +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"bQ" = ( +/obj/machinery/atmospherics/pipe/manifold/general/visible{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"bS" = ( +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"bT" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/item/instrument/guitar, +/obj/item/instrument/violin, +/obj/item/instrument/accordion, +/obj/item/instrument/trumpet, +/obj/structure/closet/crate/wooden, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bU" = ( +/obj/structure/table/wood/fancy, +/obj/item/reagent_containers/food/drinks/shaker, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bV" = ( +/obj/machinery/door/airlock/maintenance{ + name = "Garage" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"bW" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/table, +/obj/machinery/microwave, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"bX" = ( +/obj/structure/closet/crate/bin, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"bY" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/processor, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"ce" = ( +/obj/structure/chair/wood{ + dir = 4 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"cf" = ( +/obj/structure/table/wood, +/obj/item/toy/snowball, +/obj/item/toy/snowball{ + pixel_y = 8 + }, +/obj/item/toy/snowball{ + pixel_x = 8 + }, +/obj/item/toy/snowball{ + pixel_x = -5; + pixel_y = 5 + }, +/obj/item/toy/snowball{ + pixel_x = 7; + pixel_y = 4 + }, +/obj/item/toy/snowball{ + pixel_x = -5; + pixel_y = -2 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"cg" = ( +/obj/structure/chair/wood{ + dir = 8 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"ch" = ( +/obj/structure/flora/stump{ + desc = "Breaking it should be easy."; + max_integrity = 20; + name = "old stump" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"ci" = ( +/obj/structure/chair/wood, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cj" = ( +/obj/structure/table, +/obj/item/clothing/suit/hooded/wintercoat/hydro{ + name = "service winter coat"; + pixel_y = 4 + }, +/obj/item/clothing/suit/hooded/wintercoat/hydro{ + name = "service winter coat"; + pixel_y = 4 + }, +/obj/item/clothing/suit/hooded/wintercoat/hydro{ + name = "service winter coat"; + pixel_y = 4 + }, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"ck" = ( +/obj/structure/table, +/obj/machinery/microwave, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"cl" = ( +/obj/structure/kitchenspike, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"cm" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"cn" = ( +/turf/open/lava, +/area/awaymission/cabin/caves/mountain) +"cp" = ( +/obj/machinery/gateway/away, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cr" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin) +"cs" = ( +/obj/structure/table/wood, +/obj/item/wrench, +/obj/item/soap, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ct" = ( +/obj/structure/sign/poster/official/soft_cap_pop_art{ + pixel_y = 32 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cu" = ( +/obj/machinery/atmospherics/components/unary/thermomachine/freezer/on{ + dir = 1 + }, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"cv" = ( +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"cz" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/musician/piano, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cA" = ( +/obj/machinery/door/airlock/wood{ + name = "Stage Left" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cB" = ( +/obj/machinery/door/window/eastleft, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cD" = ( +/obj/structure/sign/barsign{ + pixel_y = -32; + req_access = null + }, +/obj/machinery/door/window/westleft{ + name = "Bar" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cE" = ( +/obj/item/clothing/shoes/winterboots/ice_boots, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/snowforest) +"cF" = ( +/obj/structure/table, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"cG" = ( +/obj/structure/closet/secure_closet/freezer/meat/open, +/obj/item/reagent_containers/food/snacks/meat/slab/synthmeat, +/obj/item/reagent_containers/food/snacks/meat/slab/synthmeat, +/obj/item/reagent_containers/food/snacks/meat/slab/synthmeat, +/obj/item/reagent_containers/food/snacks/meat/slab/synthmeat, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"cH" = ( +/obj/effect/landmark/awaystart, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cI" = ( +/obj/structure/chair/office/light, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"cJ" = ( +/obj/structure/table, +/obj/item/reagent_containers/food/condiment/peppermill{ + pixel_x = 8; + pixel_y = 10 + }, +/obj/item/reagent_containers/food/condiment/peppermill{ + pixel_x = 8 + }, +/obj/item/reagent_containers/food/condiment/saltshaker{ + pixel_x = -8; + pixel_y = 10 + }, +/obj/item/reagent_containers/food/condiment/saltshaker{ + pixel_x = -8 + }, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"cK" = ( +/obj/structure/table/wood/fancy, +/obj/item/reagent_containers/food/drinks/sillycup/smallcarton{ + pixel_y = 4 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cL" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"cM" = ( +/obj/machinery/door/airlock/wood{ + name = "Gateway" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"cN" = ( +/obj/machinery/computer/slot_machine, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"cO" = ( +/obj/structure/chair/wood{ + dir = 4 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"cP" = ( +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"cQ" = ( +/obj/effect/landmark/awaystart, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"cR" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"cS" = ( +/obj/machinery/button/door{ + id = "garage_cabin"; + pixel_y = 24 + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"cT" = ( +/obj/vehicle/ridden/atv, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/awaymission/cabin) +"cU" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"cV" = ( +/obj/vehicle/ridden/atv, +/turf/open/floor/plating, +/area/awaymission/cabin) +"cW" = ( +/obj/item/shovel, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/awaymission/cabin) +"cX" = ( +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/awaymission/cabin) +"cY" = ( +/obj/vehicle/ridden/atv{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"cZ" = ( +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"da" = ( +/obj/structure/chair, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"db" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/structure/table/reinforced, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dc" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/item/reagent_containers/food/drinks/bottle/vodka/badminka{ + desc = "A fancy bottle of vodka. The name isn't in Galactic Common though."; + name = "Porosha Vodka" + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dd" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/obj/structure/chair/comfy/shuttle{ + desc = "A comfortable, secure seat. It has a more sturdy looking buckling system, for making it harder to get dragged into the ring."; + name = "announcer seat" + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"de" = ( +/obj/structure/chair/wood{ + dir = 4 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"df" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 5 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dg" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dh" = ( +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"di" = ( +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dj" = ( +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/snowforest) +"dk" = ( +/obj/structure/chair, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dl" = ( +/obj/structure/chair, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dm" = ( +/obj/structure/table/reinforced, +/obj/item/pda/syndicate{ + background_color = "#0039A6"; + default_cartridge = /obj/item/cartridge/virus/mime; + desc = "A portable microcomputer by Thinktronic Systems, LTD. Seems like it may have useful information on it."; + name = "soviet PDA"; + note = "TRANSLATED TO GALACTIC COMMON:
My partner has left to help those Nanotrasen fucks three days ago. They said that a distress signal came from down south and they had to check it out. How fucking long does it take to investigate a mining outpost? Either those Nanotrasen fuckers betrayed us or something really did go wrong. Either way, I'm leaving before this becomes an issue for me and anyone else here. That dumb idiot." + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dn" = ( +/obj/structure/table/reinforced, +/obj/item/megaphone/sec{ + name = "soviet megaphone" + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"do" = ( +/obj/structure/table/reinforced, +/obj/item/cigbutt/cigarbutt, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dp" = ( +/obj/machinery/vending/sovietsoda, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dq" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dr" = ( +/obj/effect/decal/cleanable/blood, +/obj/item/reagent_containers/pill/patch/styptic, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ds" = ( +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dt" = ( +/obj/structure/closet/secure_closet/freezer/fridge/open, +/obj/item/reagent_containers/food/condiment/mayonnaise, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"du" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"dv" = ( +/obj/structure{ + anchored = 1; + density = 1; + desc = "Generates power from lava!"; + icon = 'icons/obj/atmospherics/pipes/simple.dmi'; + icon_state = "turbine"; + name = "geothermal generator" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"dw" = ( +/mob/living/simple_animal/hostile/bear/snow{ + desc = "It's a polar bear, in space, but not actually in space. It's actually on a planet. This is a planet."; + melee_damage_lower = 10; + melee_damage_upper = 20; + name = "fat space polar bear"; + speed = 3 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dx" = ( +/obj/structure/fence{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"dy" = ( +/obj/structure/fence/door, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"dz" = ( +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/snowforest) +"dA" = ( +/turf/closed/wall/ice, +/area/awaymission/cabin/snowforest) +"dB" = ( +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin) +"dC" = ( +/obj/structure/fence, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"dD" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"dE" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dF" = ( +/obj/structure/chair{ + dir = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dG" = ( +/obj/structure/kitchenspike, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dH" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"dI" = ( +/obj/structure/table, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dJ" = ( +/obj/structure/kitchenspike, +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dK" = ( +/obj/structure/chair{ + dir = 8 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dL" = ( +/obj/structure/fence/door/opened, +/obj/structure/barricade/wooden/crude/snow, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"dM" = ( +/obj/structure/chair{ + dir = 8 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dN" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"dO" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dP" = ( +/obj/item/shard, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dQ" = ( +/obj/item/lighter/greyscale, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dR" = ( +/obj/structure/chair{ + dir = 8 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dS" = ( +/obj/effect/decal/cleanable/blood/gibs/limb, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dT" = ( +/obj/item/broken_bottle, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dU" = ( +/obj/item/chair, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dV" = ( +/obj/effect/decal/cleanable/blood/gibs/body, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dW" = ( +/obj/item/reagent_containers/pill/patch/styptic, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"dX" = ( +/mob/living/simple_animal/pet/penguin/emperor, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/snowforest) +"dY" = ( +/mob/living/simple_animal/pet/penguin/baby, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/snowforest) +"dZ" = ( +/obj/structure/chair{ + dir = 8 + }, +/obj/effect/decal/cleanable/blood, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/mob/living/simple_animal/hostile/bear/snow{ + desc = "It's a polar bear, in space, but not actually in space. It's actually on a planet. This is a planet."; + melee_damage_lower = 10; + melee_damage_upper = 20; + name = "fat space polar bear"; + speed = 3 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ea" = ( +/obj/item/reagent_containers/food/snacks/carpmeat, +/obj/item/reagent_containers/food/snacks/carpmeat, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/snowforest) +"eb" = ( +/obj/structure/closet, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ec" = ( +/obj/machinery/light, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"ed" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ee" = ( +/obj/machinery/light, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"ef" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"eg" = ( +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"eh" = ( +/obj/machinery/door/airlock/wood/glass, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ei" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/glass, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ej" = ( +/obj/structure/chair/wood, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"ek" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/snowforest) +"el" = ( +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin) +"em" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"en" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin) +"eo" = ( +/obj/machinery/door/airlock{ + name = "Kitchen" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ep" = ( +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin) +"eq" = ( +/obj/machinery/door/poddoor/shutters{ + id = "garage_cabin"; + name = "garage door" + }, +/obj/structure/fans/tiny, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin) +"er" = ( +/obj/effect/turf_decal/weather/snow/corner, +/obj/effect/light_emitter{ + set_cap = 1; + set_luminosity = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin) +"es" = ( +/obj/structure/fluff/fokoff_sign, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"et" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"eu" = ( +/obj/structure/table/wood/fancy, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ev" = ( +/obj/structure/table/wood/fancy, +/obj/item/reagent_containers/rag, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ew" = ( +/obj/structure/closet/crate/wooden, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ex" = ( +/obj/structure/closet/crate/wooden, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ey" = ( +/obj/structure/sign/warning/nosmoking/circle, +/turf/closed/wall/mineral/wood, +/area/awaymission/cabin/snowforest) +"ez" = ( +/obj/structure/fence, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 5 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eA" = ( +/obj/structure/table/wood, +/obj/item/chainsaw, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"eB" = ( +/obj/structure/chair/sofa/right, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"eC" = ( +/obj/structure/fence, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eD" = ( +/obj/structure/bonfire/dense{ + desc = "Multiple logs thrown together into a pile hastily. Let's burn it for fun!."; + name = "pile of logs" + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eE" = ( +/obj/structure/table/wood, +/obj/item/grown/log/tree{ + pixel_x = -7 + }, +/obj/item/grown/log/tree, +/obj/item/grown/log/tree{ + pixel_x = 7 + }, +/obj/item/grown/log/tree{ + pixel_x = 14 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eF" = ( +/obj/structure/table/wood, +/obj/item/grown/log/tree{ + pixel_x = -7 + }, +/obj/item/grown/log/tree, +/obj/item/grown/log/tree{ + pixel_x = 7 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eG" = ( +/obj/structure/mineral_door/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"eH" = ( +/obj/structure/grille, +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/lumbermill) +"eI" = ( +/obj/effect/turf_decal/stripes/red/corner, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eJ" = ( +/obj/effect/turf_decal/stripes/red/line, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eK" = ( +/obj/machinery/conveyor_switch/oneway{ + id = "lumbermill" + }, +/obj/effect/turf_decal/stripes/red/line, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eL" = ( +/obj/effect/turf_decal/stripes/red/corner{ + dir = 8 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eM" = ( +/obj/effect/turf_decal/stripes/red/line{ + dir = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eN" = ( +/obj/structure/bookcase/random, +/turf/open/floor/wood, +/area/awaymission/cabin) +"eO" = ( +/obj/structure/flora{ + desc = "Looks frozen."; + icon = 'icons/obj/flora/snowflora.dmi'; + icon_state = "snowgrass3"; + name = "frozen flora" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"eP" = ( +/obj/structure/chair/sofa, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"eQ" = ( +/obj/structure/table/wood, +/obj/item/phone{ + desc = "If I forgot where the gateway was then I can just call the station with this phone! Wait, where's the phone lines?"; + name = "phone" + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"eR" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "lumbermill" + }, +/obj/effect/turf_decal/stripes/red/full, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/lumbermill) +"eS" = ( +/obj/machinery/recycler/lumbermill{ + desc = "Is better at killing people than cutting logs, for some reason." + }, +/obj/machinery/conveyor{ + dir = 4; + id = "lumbermill" + }, +/obj/effect/turf_decal/stripes/red/full, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/lumbermill) +"eT" = ( +/obj/structure/closet/crate/wooden{ + anchored = 1 + }, +/obj/effect/turf_decal/delivery/red, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/lumbermill) +"eU" = ( +/obj/effect/turf_decal/stripes/red/corner{ + dir = 4 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eV" = ( +/obj/effect/turf_decal/stripes/red/line{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eW" = ( +/obj/effect/turf_decal/stripes/red/line{ + dir = 1 + }, +/obj/item/wrench, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eX" = ( +/obj/effect/turf_decal/stripes/red/corner{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"eY" = ( +/obj/structure/closet/crate/wooden, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"eZ" = ( +/obj/structure/closet/crate/wooden, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/obj/item/stack/sheet/mineral/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"fa" = ( +/obj/structure/fence, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 6 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"fb" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"fc" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"fd" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 6 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"fe" = ( +/obj/structure/table/wood, +/obj/item/shovel, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ff" = ( +/obj/structure/table/wood, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"fg" = ( +/obj/structure/chair/sofa/left, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"fh" = ( +/obj/structure{ + anchored = 1; + desc = "It is a ghostly cat."; + icon = 'icons/mob/mob.dmi'; + icon_state = "catghost"; + layer = 3; + max_integrity = 66666; + name = "Cat" + }, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"fi" = ( +/obj/item/trash/can, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"fj" = ( +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"fk" = ( +/obj/item/reagent_containers/food/snacks/burger/ghost{ + desc = "I killed a burger for you. Hope you're grateful, bastards."; + pixel_x = -2; + pixel_y = 4 + }, +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"fl" = ( +/turf/open/floor/carpet, +/area/awaymission/cabin/caves/mountain) +"fm" = ( +/turf/open/chasm{ + desc = "I told you that you can't get past those doors."; + name = "anti-fun pit" + }, +/area/awaymission/cabin/caves/mountain) +"fn" = ( +/obj/structure/table/wood/poker{ + desc = "I bought this for, like, one hundred space credits."; + name = "cheap and fancy table" + }, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"fo" = ( +/obj/structure/table/wood/poker{ + desc = "I bought this for, like, one hundred space credits."; + name = "cheap and fancy table" + }, +/obj/structure/showcase/machinery/tv{ + desc = "Up next after these commercials, the season premiere of Ghost Court will be on."; + icon = 'icons/obj/stationobjs.dmi'; + icon_state = "wooden_tv"; + light_range = 8; + name = "Ghastly Entertainment Device" + }, +/turf/open/floor/wood, +/area/awaymission/cabin/caves/mountain) +"fp" = ( +/turf/closed/indestructible/riveted, +/area/awaymission/cabin/caves/mountain) +"fq" = ( +/obj/structure/sign/poster/contraband/fun_police, +/turf/closed/indestructible/riveted, +/area/awaymission/cabin/caves/mountain) +"fr" = ( +/obj/structure/reagent_dispensers/water_cooler, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fs" = ( +/obj/structure/reagent_dispensers/peppertank{ + pixel_y = 32 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"ft" = ( +/obj/structure/filingcabinet/security, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fu" = ( +/obj/machinery/computer/prisoner{ + desc = "Used to manage tracking implants placed inside criminals and the prison cells."; + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fv" = ( +/obj/structure/chair/office/light{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/structure/ladder/unbreakable/rune{ + alpha = 0; + color = "#000000"; + desc = "Examining things is a good idea after all."; + height = 1; + id = "TheRealSecretPlace"; + name = "\improper Tear In The Fabric of Reality" + }, +/obj/structure/sign/plaques/golden{ + desc = "Holding the record for about 500 years now."; + name = "The Most Annoying Organization Ever"; + pixel_y = 32 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fw" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 1 + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"fx" = ( +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"fy" = ( +/obj/machinery/computer/secure_data{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fz" = ( +/obj/structure/filingcabinet/security, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fA" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"fB" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"fC" = ( +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"fD" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 6 + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/snowforest) +"fE" = ( +/obj/structure/reagent_dispensers/peppertank{ + pixel_y = 32 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fF" = ( +/obj/machinery/vending/sustenance{ + desc = "A vending machine which vends food."; + name = "\improper Snack Machine"; + product_ads = "Sufficiently healthy.;Mmm! So good!;Have a meal.;You need food to live!"; + product_slogans = "Enjoy your meal." + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fG" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fH" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fI" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fJ" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fK" = ( +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fL" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fM" = ( +/turf/closed/indestructible/fakedoor{ + desc = "It looks like there really is no way out this time."; + name = "Cell Block Y8" + }, +/area/awaymission/cabin/caves/mountain) +"fN" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fO" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fP" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fQ" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fR" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fS" = ( +/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/dark, +/area/awaymission/cabin/caves/mountain) +"fT" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fU" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"fV" = ( +/turf/closed/indestructible/fakeglass, +/area/awaymission/cabin/caves/mountain) +"fW" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7210" + }, +/area/awaymission/cabin/caves/mountain) +"fX" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7211" + }, +/area/awaymission/cabin/caves/mountain) +"fY" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7212" + }, +/area/awaymission/cabin/caves/mountain) +"fZ" = ( +/obj/structure/grille, +/obj/structure/window/reinforced/fulltile{ + desc = "Enjoy the view."; + name = "window" + }, +/turf/open/floor/plating, +/area/awaymission/cabin/caves/mountain) +"ga" = ( +/mob/living/simple_animal/hostile/bear/snow{ + desc = "It's a polar bear, in space, but not actually in space. It's actually on a planet. This is a planet."; + melee_damage_lower = 10; + melee_damage_upper = 20; + name = "fat space polar bear"; + speed = 3; + wander = 0 + }, +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/snowforest) +"gb" = ( +/obj/machinery/door/airlock/centcom{ + desc = "Look at what you have done."; + max_integrity = 2000; + name = "Jail Cell 7213" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gc" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7214" + }, +/area/awaymission/cabin/caves/mountain) +"gd" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7215" + }, +/area/awaymission/cabin/caves/mountain) +"ge" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7216" + }, +/area/awaymission/cabin/caves/mountain) +"gf" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Jail."; + name = "Jail Cell 7217" + }, +/area/awaymission/cabin/caves/mountain) +"gg" = ( +/obj/structure/weightmachine/stacklifter, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine, +/area/awaymission/cabin/caves/mountain) +"gh" = ( +/obj/structure/weightmachine/weightlifter, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/engine, +/area/awaymission/cabin/caves/mountain) +"gi" = ( +/obj/item/toy/spinningtoy{ + anchored = 1; + desc = "He keeps breaking out somehow due to the help of cultists that utilize cargo shipments or atmospherical sabotage." + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gj" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gk" = ( +/obj/item/gun/ballistic/automatic/toy{ + anchored = 1; + desc = "Don't try it."; + name = "Nanotrasen Saber SMG" + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gl" = ( +/obj/structure/sign/poster/contraband/free_drone{ + desc = "This poster is just really ironic right now." + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gm" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gn" = ( +/obj/structure/ladder/unbreakable/rune{ + alpha = 0; + color = "#000000"; + desc = "It is time to bust out of this joint"; + height = 1; + id = "whatkindofnerdusesmapmakertocheattheirwaytoateleportrune"; + mouse_opacity = 0; + name = "\improper secret escape route" + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"go" = ( +/obj/structure/easel{ + desc = "Art so fine, the universe can't handle it!"; + name = "Canvas Art" + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gp" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/item/nullrod/claymore/multiverse{ + anchored = 1; + force = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gq" = ( +/obj/structure/fluff/empty_sleeper{ + desc = "An open sleeper. It looks as though it would be awaiting another patient, were it not LOCKED BEHIND BARS!!!"; + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gr" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/structure/showcase/mecha/marauder{ + desc = "Used by vigilantes to fight the ruffians causing trouble in neighborhoods and space stations"; + icon_state = "seraph"; + name = "gang warfare seraph" + }, +/turf/open/indestructible, +/area/awaymission/cabin/caves/mountain) +"gs" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine, +/area/awaymission/cabin/caves/mountain) +"gt" = ( +/obj/structure/sign/poster/contraband/pwr_game{ + pixel_x = 32 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine, +/area/awaymission/cabin/caves/mountain) +"gu" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/poster/official/do_not_question{ + pixel_x = 32 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gv" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine, +/area/awaymission/cabin/caves/mountain) +"gw" = ( +/obj/structure/punching_bag, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/engine, +/area/awaymission/cabin/caves/mountain) +"gx" = ( +/turf/closed/indestructible/rock/snow/ice, +/area/awaymission/cabin/caves/mountain) +"gy" = ( +/obj/structure/barricade/wooden/crude{ + desc = "Buffing things is illegal for it causes fun." + }, +/turf/closed/indestructible/fakedoor{ + desc = "The room for buffing things."; + name = "Exercise Room" + }, +/area/awaymission/cabin/caves/mountain) +"gz" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/obj/structure/signpost/salvation{ + density = 0; + desc = "An intercomm. Someone seems to be on the other end. I should use it."; + icon = 'icons/obj/radio.dmi'; + icon_state = "intercom"; + max_integrity = 99999; + name = "\proper Fun Jail intercom"; + pixel_y = 32; + question = "We have a case of fun happening. Get out there and do your job." + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gA" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/poster/official/space_cops{ + pixel_y = 32 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gB" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/poster/official/no_erp{ + pixel_y = -32 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gC" = ( +/obj/effect/baseturf_helper/asteroid/snow, +/turf/closed/indestructible/rock/snow/ice, +/area/awaymission/cabin/caves/mountain) +"gD" = ( +/turf/open/chasm{ + color = "#000000"; + desc = "Leave this place, insect."; + name = "Abyss" + }, +/area/awaymission/cabin/caves/mountain) +"gE" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/item/reagent_containers/food/snacks/egg/rainbow{ + desc = "Was an egg really worth this much effort?"; + name = "easter egg" + }, +/obj/structure/table, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gF" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/item/banhammer{ + desc = "I'm sorry, sir, but fun actions are illegal."; + name = "fun baton" + }, +/obj/structure/table, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"gG" = ( +/turf/closed/indestructible{ + icon = 'icons/turf/floors.dmi'; + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gH" = ( +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gI" = ( +/obj/structure/signpost/salvation{ + desc = "Come closer, insect."; + icon = 'icons/mob/nest.dmi'; + icon_state = "nether"; + max_integrity = 99999; + name = "\proper Netherworld Link"; + question = "You have come far, insect. Farther than most. While I could keep you for an eternity, I would prefer some peace and quiet right now. Now, insect, offer yourself to me." + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gJ" = ( +/obj/structure{ + alpha = 100; + anchored = 1; + desc = "It is impossible to comprehend such a thing"; + icon = 'icons/mob/mob.dmi'; + icon_state = "shadowling_ascended"; + max_integrity = 66666; + mouse_opacity = 0; + name = "Ascension" + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gK" = ( +/obj/item/book_of_babel{ + desc = "Finally, a tome that seems actually fucking useful here.
I'm losing my mind here.
Why did I come here?

I'm not myself anymore, am I?"; + icon_state = "bookblind"; + name = "Unknown Tome" + }, +/turf/closed/indestructible{ + icon = 'icons/turf/floors.dmi'; + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gL" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/plating, +/area/awaymission/cabin) +"gM" = ( +/obj/structure/closet, +/obj/effect/decal/cleanable/dirt, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"gN" = ( +/obj/machinery/light, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/awaymission/cabin) +"gO" = ( +/obj/structure/fence/door{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"gP" = ( +/obj/structure/flora/tree/pine, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"gQ" = ( +/obj/item/storage/book/bible{ + deity_name = "The Holy Lord Above"; + desc = "There is no salvation here."; + icon_state = "burning"; + name = "Holy Tome" + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gR" = ( +/obj/structure/flora{ + desc = "Looks frozen."; + icon = 'icons/obj/flora/snowflora.dmi'; + icon_state = "snowgrass2"; + name = "frozen flora" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"gS" = ( +/obj/item/storage/book/bible{ + deity_name = "THE VOICES IN MY HEAD"; + desc = "There are some things that you can not get.
I had more faith in you than that.
"; + icon_state = "scrapbook"; + name = "Insane Tome" + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gT" = ( +/obj/structure/ladder/unbreakable/rune{ + alpha = 0; + color = "#000000"; + desc = "EXAMINING THAT WAS A MISTAKE!"; + icon_state = "7"; + id = "TheRealSecretPlace"; + light_range = 10; + mouse_opacity = 0; + name = "\improper void" + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gU" = ( +/obj/structure/flora{ + desc = "Looks frozen."; + icon = 'icons/obj/flora/snowflora.dmi'; + icon_state = "snowgrass_sw"; + name = "frozen flora" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"gV" = ( +/obj/item/storage/book/bible{ + deity_name = "Cthulhu"; + desc = "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn."; + icon_state = "necronomicon"; + name = "Elder Tome" + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"gW" = ( +/obj/structure/flora/tree/dead, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"gX" = ( +/obj/structure/flora/stump{ + desc = "Breaking it should be easy."; + max_integrity = 20; + name = "old stump" + }, +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/snowforest) +"gY" = ( +/obj/structure/table/wood, +/obj/item/clothing/suit/hooded/wintercoat/hydro, +/obj/item/clothing/ears/earmuffs, +/obj/item/clothing/head/hardhat, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"gZ" = ( +/obj/item/chair/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ha" = ( +/obj/structure/chair/wood/wings{ + name = "dealer chair" + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hb" = ( +/obj/structure/table/wood/fancy, +/obj/item/coin{ + desc = "Looks old."; + pixel_x = 4; + pixel_y = 5 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hc" = ( +/obj/structure/table/wood/poker, +/obj/item/toy/cards/deck{ + pixel_y = 5 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hd" = ( +/obj/structure/chair/wood{ + dir = 1 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"he" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_y = -2 + }, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_x = 8; + pixel_y = 8 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hf" = ( +/obj/machinery/space_heater, +/obj/effect/decal/remains/robot, +/obj/structure/sign/warning/fire{ + pixel_y = 32 + }, +/obj/machinery/space_heater, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hg" = ( +/obj/machinery/door/airlock/maintenance{ + name = "janitor closet" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hh" = ( +/obj/structure/sign/poster/official/fruit_bowl{ + pixel_y = 32 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hi" = ( +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"hj" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hk" = ( +/obj/structure/sign/poster/official/nanotrasen_logo{ + pixel_x = 32 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hl" = ( +/obj/structure/sign/poster/official/here_for_your_safety{ + pixel_y = 32 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hm" = ( +/obj/machinery/door/airlock/wood{ + name = "Gateway" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hn" = ( +/obj/structure/sign/poster/official/high_class_martini{ + pixel_y = 32 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ho" = ( +/obj/item/wrench/medical, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"hp" = ( +/obj/machinery/sleeper{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"hq" = ( +/obj/machinery/vending/medical, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"hr" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/oil, +/obj/effect/decal/cleanable/generic, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hs" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/sign/poster/contraband/missing_gloves{ + pixel_x = 32 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ht" = ( +/obj/structure/window{ + dir = 4 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hu" = ( +/obj/structure/table/reinforced, +/obj/item/clothing/glasses/cold, +/obj/item/clothing/glasses/cold, +/obj/item/clothing/glasses/cold, +/obj/item/clothing/suit/hooded/wintercoat/engineering, +/obj/item/clothing/suit/hooded/wintercoat/engineering, +/obj/item/clothing/suit/hooded/wintercoat/engineering, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hv" = ( +/obj/structure/table/reinforced, +/obj/item/clothing/head/welding{ + pixel_y = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hw" = ( +/obj/structure/closet/toolcloset, +/obj/item/lightreplacer, +/obj/item/storage/toolbox/mechanical, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/awaymission/cabin) +"hx" = ( +/obj/machinery/door/airlock/wood{ + name = "Stage Right" + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hy" = ( +/obj/machinery/door/airlock/maintenance{ + name = "heater storage" + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/awaymission/cabin) +"hz" = ( +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plasteel/cafeteria, +/area/awaymission/cabin) +"hA" = ( +/obj/machinery/door/airlock/freezer{ + name = "Freezer" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"hB" = ( +/obj/machinery/door/airlock{ + name = "Backstage" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hC" = ( +/obj/structure/chair/wood{ + dir = 8 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hD" = ( +/obj/structure/table/reinforced, +/obj/item/folder/white, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"hE" = ( +/obj/machinery/door/airlock{ + name = "Kitchen" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hF" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_y = 2 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hG" = ( +/obj/structure/chair/wood{ + dir = 1 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"hH" = ( +/obj/effect/landmark/awaystart, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hI" = ( +/obj/effect/landmark/awaystart, +/obj/structure/sign/poster/official/report_crimes{ + pixel_y = -32 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"hJ" = ( +/obj/item/storage/book/bible{ + deity_name = "Netherworld"; + desc = "Suffering and pain waits for you.
Death will not be your end for, with every step you take, your soul moves closer to me.
Your darkest fears will soon be realized.
There is nowhere to run, for I am everywhere.
"; + icon_state = "tome"; + name = "Void Tome" + }, +/turf/open/indestructible{ + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"hK" = ( +/obj/item/storage/book/bible{ + deity_name = "Greytide"; + desc = "Hey, I'm not actually a spooky book. Can you help me find my toolbox? Thanks."; + icon_state = "insuls"; + name = "Mortal Tome" + }, +/turf/closed/indestructible{ + icon = 'icons/turf/floors.dmi'; + icon_state = "black"; + name = "void" + }, +/area/awaymission/cabin/caves/mountain) +"hL" = ( +/obj/structure/sign/nanotrasen, +/turf/closed/wall/mineral/snow, +/area/awaymission/cabin/caves/mountain) +"hM" = ( +/turf/closed/wall/mineral/snow, +/area/awaymission/cabin/caves/mountain) +"hN" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"hO" = ( +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"hP" = ( +/obj/item/candle/infinite, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"hQ" = ( +/obj/item/reagent_containers/food/drinks/beer, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"hR" = ( +/obj/structure/reagent_dispensers/beerkeg{ + desc = "Hey, Centcom, we located our complimentary case of space beer! The pamphlet didn't lie!"; + name = "complimentary keg of space beer" + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"hS" = ( +/mob/living/simple_animal/hostile/tree{ + desc = "I am death. I will have my vengeance upon my enemies."; + melee_damage_upper = 8; + wander = 0 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"hT" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"hU" = ( +/obj/item/toy/figure/clown{ + desc = "Shut up, we don't talk about him."; + name = "exploration squad Clown" + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"hV" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1; + name = "Who" + }, +/obj/item/clothing/head/helmet/knight/yellow{ + armor = list("melee" = 11, "bullet" = 2, "laser" = 1, "energy" = 1, "bomb" = 5, "bio" = 2, "rad" = 0, "fire" = 0, "acid" = 10); + desc = "A classic metal helmet. The cold has made it unreliable though."; + name = "old medieval helmet"; + pixel_y = 7 + }, +/obj/item/claymore/weak/ceremonial{ + desc = "Brought to you by the guys in charge of making replica katana toys!"; + force = 1; + layer = 3.01; + name = "replica claymore"; + pixel_x = 5; + pixel_y = 8; + throwforce = 2 + }, +/obj/item/shield/riot/roman/fake{ + layer = 3.01; + pixel_x = -7 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"hW" = ( +/obj/item/toy/figure/borg{ + desc = "The robot that was manufactured just for this exploration team."; + name = "exploration squad Cyborg"; + pixel_x = 8; + toysay = "I. AM. ALIVE." + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"hX" = ( +/obj/item/clothing/suit/armor/vest/russian_coat{ + pixel_x = 16; + pixel_y = 16 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"hY" = ( +/obj/effect/decal/cleanable/blood/gibs, +/obj/item/reagent_containers/pill/patch/styptic, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"hZ" = ( +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/decal/cleanable/blood, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 8 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ia" = ( +/obj/effect/decal/cleanable/blood, +/obj/item/shard/plasma, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ib" = ( +/obj/item/hatchet, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ic" = ( +/obj/effect/decal/cleanable/blood, +/obj/item/trash/popcorn{ + pixel_y = 12 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"id" = ( +/obj/structure/chair{ + dir = 1 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ie" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"if" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 10 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ig" = ( +/obj/item/toy/figure/dsquad{ + desc = "The muscle behind the exploration team. May or may not be a secret soldier depending on the mood of Nanotrasen following their own lore."; + name = "exploration squad Officer"; + toysay = "We're top secret until we're not!" + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"ih" = ( +/obj/item/toy/figure/md{ + desc = "The doctor that got volunteered to join the exploration team."; + name = "exploration squad Medic"; + pixel_x = -8; + toysay = "Guess I'll be useless until stuns are involved!" + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"ii" = ( +/turf/closed/indestructible/syndicate, +/area/awaymission/cabin/caves/sovietcave) +"ij" = ( +/obj/structure/table/wood, +/obj/item/storage/crayons, +/obj/item/storage/crayons, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ik" = ( +/obj/structure/door_assembly/door_assembly_vault{ + anchored = 1; + name = "vault door" + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"il" = ( +/obj/item/toy/prize/deathripley{ + desc = "The mining mecha of the exploration team."; + name = "exploraton squad Ripley"; + pixel_y = 15 + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"im" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"in" = ( +/obj/structure/extinguisher_cabinet{ + pixel_y = 32 + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"io" = ( +/obj/structure/extinguisher_cabinet{ + pixel_x = -24 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ip" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/hatch, +/obj/structure/barricade/wooden, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"iq" = ( +/obj/effect/decal/cleanable/dirt/dust, +/mob/living/simple_animal/hostile/hivebot/range{ + desc = "Looks like he's been left behind."; + faction = list("russian"); + maxHealth = 5; + name = "soviet machine" + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"ir" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/barricade/sandbags, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"is" = ( +/obj/structure/closet/secure_closet/freezer/kitchen, +/obj/item/reagent_containers/food/condiment/enzyme, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"it" = ( +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"iu" = ( +/obj/item/grenade/barrier{ + pixel_x = -14; + pixel_y = 14 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"iv" = ( +/turf/closed/wall/mineral/snow, +/area/awaymission/cabin/caves) +"iw" = ( +/obj/structure/floodlight_frame, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"ix" = ( +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"iy" = ( +/obj/item/paper/pamphlet/gateway, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"iz" = ( +/turf/closed/wall/ice, +/area/awaymission/cabin/caves) +"iA" = ( +/obj/structure/frame/machine, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iB" = ( +/obj/structure/frame/computer, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iC" = ( +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iD" = ( +/obj/structure/closet/acloset, +/obj/item/clothing/suit/hooded/bloated_human, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iE" = ( +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"iF" = ( +/obj/item/shovel{ + desc = "A large tool for digging and moving snow."; + force = 10; + name = "eskimo shovel" + }, +/obj/effect/decal/remains/human{ + color = "#72e4fa" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"iG" = ( +/obj/structure/fluff/iced_abductor, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iH" = ( +/obj/structure/table/glass, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iI" = ( +/obj/structure/closet/acloset, +/obj/item/toy/foamblade, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iJ" = ( +/obj/structure/bed/alien, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"iK" = ( +/obj/structure/flora/rock/icy{ + desc = "A mountain rock." + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"iL" = ( +/turf/open/floor/plating/asteroid/snow{ + floor_variance = 0; + icon_state = "snow_dug"; + slowdown = 1 + }, +/area/awaymission/cabin/caves) +"iM" = ( +/turf/open/floor/wood, +/area/awaymission/cabin/caves) +"iN" = ( +/obj/machinery/icecream_vat, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"iO" = ( +/obj/structure/chair, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"iP" = ( +/obj/structure/sign/picture_frame{ + pixel_y = 32 + }, +/turf/open/floor/wood, +/area/awaymission/cabin/caves) +"iQ" = ( +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/awaymission/cabin/caves) +"iR" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_x = -7; + pixel_y = -2 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iS" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_x = 7; + pixel_y = 2 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iT" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_x = -4; + pixel_y = 4 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iU" = ( +/obj/structure/table/wood, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_x = -5; + pixel_y = 2 + }, +/obj/item/reagent_containers/food/drinks/mug/coco{ + desc = "Still hot!"; + pixel_x = 7; + pixel_y = -2 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iV" = ( +/obj/machinery/door/airlock/wood{ + id_tag = "snowdinbutworse1"; + name = "Cabin 1" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iW" = ( +/obj/machinery/door/airlock/wood{ + id_tag = "snowdinbutworse2"; + name = "Cabin 2" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iX" = ( +/obj/machinery/door/airlock/wood{ + id_tag = "snowdinbutworse3"; + name = "Cabin 3" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iY" = ( +/obj/machinery/door/airlock/wood{ + id_tag = "snowdinbutworse4"; + name = "Cabin 4" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/wood, +/area/awaymission/cabin) +"iZ" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "fightingcommunity10" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"ja" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "fightingcommunity20" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"jb" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "fightingcommunity30" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"jc" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "fightingcommunity40" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"jd" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "fightingcommunity50" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"je" = ( +/obj/structure/window/reinforced/fulltile/ice{ + name = "frozen window" + }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "fightingcommunity60" + }, +/turf/open/floor/plating, +/area/awaymission/cabin) +"jf" = ( +/obj/machinery/button/door{ + id = "fightingcommunity60"; + name = "shutter button"; + pixel_x = -8; + pixel_y = 30 + }, +/obj/machinery/button/door{ + id = "WheresTheSyndiBalloon"; + name = "airlock button"; + pixel_x = 8; + pixel_y = 30 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jg" = ( +/obj/machinery/button/door{ + id = "snowdinbutworse2"; + name = "airlock button"; + pixel_y = -27 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jh" = ( +/obj/machinery/button/door{ + id = "snowdinbutworse1"; + name = "airlock button"; + pixel_y = -27 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ji" = ( +/obj/machinery/button/door{ + id = "snowdinbutworse3"; + name = "airlock button"; + pixel_y = -27 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jj" = ( +/obj/machinery/button/door{ + id = "snowdinbutworse4"; + name = "airlock button"; + pixel_y = -27 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jk" = ( +/obj/machinery/button/door{ + id = "snowdinbutworse5"; + name = "airlock button"; + pixel_y = -27 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jl" = ( +/obj/machinery/button/door{ + id = "fightingcommunity10"; + name = "shutter button"; + pixel_x = -28; + pixel_y = 30 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jm" = ( +/obj/machinery/button/door{ + id = "fightingcommunity20"; + name = "shutter button"; + pixel_x = 28; + pixel_y = 30 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jn" = ( +/obj/machinery/button/door{ + id = "fightingcommunity30"; + name = "shutter button"; + pixel_x = -28; + pixel_y = 30 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jo" = ( +/obj/machinery/button/door{ + id = "fightingcommunity40"; + name = "shutter button"; + pixel_x = 28; + pixel_y = 30 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jp" = ( +/obj/machinery/button/door{ + id = "fightingcommunity50"; + name = "shutter button"; + pixel_x = -28; + pixel_y = 30 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jq" = ( +/obj/item/clothing/suit/hooded/wintercoat/medical{ + pixel_y = 3 + }, +/obj/structure/table/reinforced, +/obj/item/clothing/suit/hooded/wintercoat/medical{ + pixel_y = 3 + }, +/obj/item/reagent_containers/glass/bottle/cryoxadone, +/obj/item/reagent_containers/glass/bottle/cryoxadone, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"jr" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/closet/secure_closet/personal/cabinet{ + anchored = 1 + }, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/neck/scarf/zebra, +/turf/open/floor/wood, +/area/awaymission/cabin) +"js" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/table, +/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/brute, +/obj/item/storage/firstaid/fire, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"jt" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/closet/secure_closet/personal/cabinet{ + anchored = 1 + }, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/neck/scarf/christmas, +/turf/open/floor/wood, +/area/awaymission/cabin) +"ju" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/closet/secure_closet/personal/cabinet{ + anchored = 1 + }, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/neck/stripedbluescarf, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jv" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/closet/secure_closet/personal/cabinet{ + anchored = 1 + }, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/neck/stripedgreenscarf, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jw" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/closet/secure_closet/personal/cabinet{ + anchored = 1 + }, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/shoes/winterboots, +/obj/item/clothing/neck/stripedredscarf, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jx" = ( +/obj/structure/table/wood/poker, +/obj/item/dice/d6{ + pixel_x = 5; + pixel_y = 2 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"jy" = ( +/obj/structure/table/wood/fancy, +/obj/item/reagent_containers/food/drinks/bottle/wine{ + pixel_y = 4 + }, +/obj/item/reagent_containers/food/drinks/drinkingglass{ + pixel_x = -7; + pixel_y = 3 + }, +/obj/item/reagent_containers/food/drinks/drinkingglass{ + pixel_x = 7; + pixel_y = 3 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jz" = ( +/obj/structure/table/wood, +/obj/item/paper_bin, +/obj/item/pen/red, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jA" = ( +/obj/structure/table/wood, +/obj/item/folder/yellow{ + pixel_x = -7 + }, +/obj/item/folder/blue{ + pixel_x = 7 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jB" = ( +/obj/effect/baseturf_helper/asteroid/snow, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jC" = ( +/obj/machinery/door/airlock/engineering{ + name = "Generator Room" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"jD" = ( +/obj/structure/table/wood, +/obj/item/clothing/mask/gas/explorer, +/obj/item/tank/internals/emergency_oxygen, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jE" = ( +/obj/structure/closet/crate/bin, +/obj/item/tank/internals/emergency_oxygen/engi/empty, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"jF" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/tray, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jG" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/pistachios, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jH" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/can, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jI" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/candy, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jJ" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/cheesie, +/turf/open/floor/wood, +/area/awaymission/cabin) +"jK" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mine/stun, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"jL" = ( +/obj/structure/table/wood, +/obj/machinery/plantgenes{ + name = "tree DNA manipulator"; + pixel_y = 5 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jM" = ( +/obj/machinery/space_heater, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jN" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"jO" = ( +/obj/structure/sign/warning/nosmoking{ + pixel_x = 32 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jP" = ( +/obj/structure/sign/warning/nosmoking{ + pixel_x = -32 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jQ" = ( +/obj/structure/table/wood, +/obj/structure/sign/warning/nosmoking/circle{ + pixel_x = -16; + pixel_y = 32 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jR" = ( +/obj/structure/table/wood, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = 7; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = -7; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = -3; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = 3; + throwforce = 4 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jS" = ( +/obj/structure/table/wood, +/obj/item/storage/firstaid/brute, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jT" = ( +/obj/structure/table/wood, +/obj/item/radio/off{ + pixel_x = -5; + pixel_y = 4 + }, +/obj/item/radio/off{ + pixel_y = 4 + }, +/obj/item/radio/off{ + pixel_x = 5; + pixel_y = 4 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jU" = ( +/obj/structure/chair/wood, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jV" = ( +/mob/living/simple_animal/bot/firebot, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jW" = ( +/obj/structure/table/wood, +/obj/item/gun/energy/floragun, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jX" = ( +/obj/structure/table/wood, +/obj/item/pizzabox/vegetable{ + pixel_x = -6; + pixel_y = 12 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jY" = ( +/obj/structure/table/wood, +/obj/item/razor{ + pixel_y = 3 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"jZ" = ( +/obj/structure/table/wood, +/obj/item/extinguisher{ + pixel_x = -7; + pixel_y = 3 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ka" = ( +/obj/structure/table/wood, +/obj/item/extinguisher, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"kb" = ( +/obj/structure/table/wood, +/obj/item/flashlight{ + pixel_x = 4; + pixel_y = 6 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"kc" = ( +/obj/structure/table/wood, +/obj/item/flashlight{ + pixel_y = 2 + }, +/obj/item/flashlight{ + pixel_y = 15 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"kd" = ( +/obj/structure/table/wood, +/obj/item/paper_bin/construction{ + pixel_y = 3 + }, +/obj/item/pen{ + pixel_y = 3 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"ke" = ( +/obj/structure/table/wood, +/obj/item/restraints/legcuffs/beartrap{ + pixel_y = 7 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"kf" = ( +/obj/structure/table/wood, +/obj/item/paper_bin, +/obj/item/pen/fountain, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"kg" = ( +/obj/structure/flora/tree/pine, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin) +"kh" = ( +/obj/structure/flora/rock/icy{ + desc = "A mountain rock." + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/snowforest) +"ki" = ( +/turf/open/floor/wood/cold, +/area/awaymission/cabin/caves) +"kj" = ( +/obj/structure/mineral_door/wood, +/turf/open/floor/wood, +/area/awaymission/cabin/caves) +"kk" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/tank_dispenser/oxygen, +/turf/open/floor/wood, +/area/awaymission/cabin) +"kl" = ( +/obj/structure/bonfire, +/turf/open/floor/plating, +/area/awaymission/cabin/caves) +"km" = ( +/obj/structure/bed, +/obj/effect/spawner/lootdrop/bedsheet, +/turf/open/floor/wood, +/area/awaymission/cabin/caves) +"kn" = ( +/obj/structure/sign/basic{ + pixel_x = 32 + }, +/turf/open/floor/plating/asteroid/snow{ + floor_variance = 0; + icon_state = "snow_dug"; + slowdown = 1 + }, +/area/awaymission/cabin/caves) +"ko" = ( +/turf/open/floor/wood/cold{ + icon_state = "wood-broken" + }, +/area/awaymission/cabin/caves) +"kp" = ( +/turf/open/floor/wood/cold{ + icon_state = "wood-broken4" + }, +/area/awaymission/cabin/caves) +"kq" = ( +/turf/open/floor/wood/cold{ + icon_state = "wood-broken5" + }, +/area/awaymission/cabin/caves) +"kr" = ( +/turf/open/floor/wood/cold{ + icon_state = "wood-broken3" + }, +/area/awaymission/cabin/caves) +"ks" = ( +/turf/open/floor/wood/cold{ + icon_state = "wood-broken2" + }, +/area/awaymission/cabin/caves) +"kt" = ( +/obj/structure/barricade/wooden/snowed, +/turf/open/floor/plating/asteroid/snow{ + floor_variance = 0; + icon_state = "snow_dug"; + slowdown = 1 + }, +/area/awaymission/cabin/caves) +"ku" = ( +/turf/open/floor/wood/cold{ + icon_state = "wood-broken7" + }, +/area/awaymission/cabin/caves) +"kv" = ( +/obj/structure/barricade/wooden/snowed, +/obj/structure/barricade/wooden/crude/snow, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kw" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"kx" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"ky" = ( +/obj/structure/flora/stump{ + desc = "Breaking it should be easy."; + max_integrity = 20; + name = "old stump" + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kz" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1; + name = "What" + }, +/obj/item/clothing/head/wizard/fake{ + pixel_x = -1; + pixel_y = 13 + }, +/obj/item/staff{ + layer = 3.01 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kA" = ( +/obj/effect/decal/cleanable/blood, +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/snowforest) +"kB" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1; + name = "I Don't Know" + }, +/obj/item/gun/magic/wand{ + desc = "It's just a fancy staff so that holy clerics and priests look cool. What? You didn't think someone would leave a REAL magic artifact with a snowman out in the cold, did you?"; + icon_state = "revivewand"; + layer = 3.01; + name = "holy staff"; + pixel_y = -2 + }, +/obj/item/clothing/head/christmashatg{ + pixel_y = 12; + pixel_x = 3 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kC" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1; + name = "Because" + }, +/obj/item/clothing/head/scarecrow_hat{ + desc = "A replica straw hat that isn't actually made out of straw"; + name = "synthetic straw hat"; + pixel_x = -1; + pixel_y = 10 + }, +/obj/item/gun/ballistic/shotgun/toy/unrestricted{ + pixel_y = -2 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kD" = ( +/obj/structure/table/wood, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = 7; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = -7; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = -3; + throwforce = 4 + }, +/obj/item/hatchet{ + desc = "A decent axe blade upon a short fibremetal handle. It has a long history of chopping things, but now it is used for chopping wood."; + force = 4; + name = "weak hatchet"; + pixel_x = 3; + throwforce = 4 + }, +/obj/structure/sign/warning/nosmoking/circle{ + pixel_x = 16; + pixel_y = -32 + }, +/turf/open/floor/wood/cold, +/area/awaymission/cabin/lumbermill) +"kE" = ( +/obj/structure/closet, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/suit/hooded/wintercoat, +/turf/open/floor/plating, +/area/awaymission/cabin) +"kF" = ( +/obj/structure/barricade/sandbags, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kG" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kH" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kI" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/assembly/infra, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kJ" = ( +/obj/effect/decal/hammerandsickle, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kK" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/table/reinforced, +/obj/item/reagent_containers/food/drinks/bottle/vodka, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kL" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/head/helmet/rus_ushanka, +/obj/structure/table/reinforced, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kM" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/table/reinforced, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags{ + pixel_x = -2; + pixel_y = 3 + }, +/obj/item/stack/sheet/mineral/sandbags, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"kN" = ( +/turf/open/floor/plating, +/area/awaymission/cabin/caves/sovietcave) +"kO" = ( +/obj/item/bear_armor, +/turf/open/floor/plating, +/area/awaymission/cabin/caves/sovietcave) +"kP" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1; + name = "Why" + }, +/obj/item/clothing/head/bandana{ + pixel_x = -1; + pixel_y = -1 + }, +/obj/item/throwing_star{ + desc = "I better not rely on this being useful."; + force = 1; + name = "frozen throwing star"; + throwforce = 1 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kQ" = ( +/obj/structure/flora/tree/pine, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kR" = ( +/obj/structure/sign/warning/explosives, +/turf/closed/indestructible/syndicate, +/area/awaymission/cabin/caves/sovietcave) +"kS" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/remains/human, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kT" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kU" = ( +/obj/effect/decal/remains/human, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kV" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/obj/effect/decal/remains/human, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kW" = ( +/obj/effect/decal/cleanable/oil, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kX" = ( +/obj/structure/ladder/unbreakable/rune{ + desc = "Get me out of this boring room."; + height = 1; + icon_state = "hierophant"; + id = "GETMEOUTOFHEREYOUFUCKS"; + name = "\improper Return Rune" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kY" = ( +/obj/effect/decal/remains/human, +/obj/item/shovel, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"kZ" = ( +/obj/structure/sign/warning, +/turf/closed/indestructible/syndicate, +/area/awaymission/cabin/caves/sovietcave) +"la" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/item/crowbar/large, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lb" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"lc" = ( +/turf/closed/indestructible/fakedoor{ + desc = "I can't get past this."; + name = "Reinforced Soviet Hatch" + }, +/area/awaymission/cabin/caves/sovietcave) +"ld" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"le" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lf" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lg" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/effect/decal/cleanable/oil, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lh" = ( +/obj/effect/decal/remains/human, +/obj/item/reagent_containers/spray/pepper/empty, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"li" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/effect/decal/cleanable/generic, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lj" = ( +/obj/effect/decal/remains/xeno, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lk" = ( +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"ll" = ( +/obj/structure/barricade/wooden/snowed, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lm" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"ln" = ( +/obj/item/weldingtool/mini, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lo" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lp" = ( +/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lq" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/mob/living/simple_animal/hostile/statue{ + desc = "Just a snowman. Just a snowman. Oh god, it's just a snowman."; + faction = list("statue","mining"); + health = 5000; + icon_dead = "snowman"; + icon_living = "snowman"; + icon_state = "snowman"; + loot = list(/obj/item/dnainjector/geladikinesis); + maxHealth = 5000; + melee_damage_lower = 65; + melee_damage_upper = 65; + name = "Frosty" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lr" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/item/kitchen/knife/carrotshiv, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"ls" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/item/melee/baseball_bat, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lt" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/mob/living/simple_animal/hostile/asteroid/hivelord/legion/snow, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lu" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lv" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/effect/decal/cleanable/molten_object/large, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lw" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/item/clothing/head/helmet/skull{ + armor = list("melee" = 15, "bullet" = 5, "laser" = 5, "energy" = 2, "bomb" = 10, "bio" = 5, "rad" = 20, "fire" = 20, "acid" = 20); + desc = "It's not bloody for some reason. Dear god."; + name = "human skull" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lx" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/effect/decal/cleanable/plasma, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"ly" = ( +/obj/item/chair/stool, +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lz" = ( +/obj/structure/sign/poster/official/cleanliness{ + pixel_y = -32 + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"lA" = ( +/obj/effect/decal/cleanable/glitter/blue{ + desc = "It looks like fancy glitter to me."; + name = "icy wind" + }, +/obj/effect/decal/remains/xeno/larva, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lB" = ( +/obj/structure/statue/snow/snowman{ + anchored = 1; + desc = "You didn't seriously examine each snowman to see if their description is different, did you?" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lC" = ( +/obj/machinery/conveyor{ + dir = 4; + id = "lumbermill" + }, +/obj/effect/turf_decal/stripes/red/full, +/obj/structure/barricade/wooden/snowed, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/lumbermill) +"lD" = ( +/obj/structure/ladder/unbreakable/rune{ + desc = "I want out of this spookfest."; + icon_state = "hierophant"; + id = "GETMEOUTOFHEREYOUFUCKS"; + name = "\improper Emergency Escape Rune" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lE" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/item/hatchet, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lF" = ( +/obj/effect/mine/stun, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lG" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/item/grenade/chem_grenade/large, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lH" = ( +/obj/effect/decal/remains/human, +/obj/structure/light_construct, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lI" = ( +/obj/structure/light_construct, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lJ" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/remains/human{ + desc = "They look like human remains. They're covered in scratch marks."; + name = "mangled remains" + }, +/obj/effect/decal/cleanable/shreds, +/obj/effect/decal/cleanable/shreds{ + pixel_y = 7 + }, +/obj/effect/decal/cleanable/shreds{ + pixel_x = -3; + pixel_y = -5 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lK" = ( +/obj/item/pickaxe{ + desc = "It's almost broken."; + force = 8; + name = "damaged pickaxe"; + throwforce = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lL" = ( +/obj/effect/decal/remains/human, +/obj/item/pickaxe{ + desc = "It's almost broken."; + force = 8; + name = "damaged pickaxe"; + throwforce = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lM" = ( +/obj/effect/decal/cleanable/blood/old, +/obj/item/shovel, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lN" = ( +/obj/item/pickaxe/drill, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lO" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/item/clothing/shoes/sneakers/brown, +/obj/structure/closet{ + anchored = 1; + name = "uniform closet" + }, +/obj/item/clothing/under/rank/security/officer/spacepol{ + armor = list("melee" = 2, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 10, "acid" = 10); + desc = "Anyone enjoying their time while working in a megacorporation, planetary government, or band of pirates is under the jurisdiction of the fun police." + }, +/obj/item/clothing/head/helmet, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"lP" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/closed/wall/ice, +/area/awaymission/cabin/caves) +"lQ" = ( +/obj/structure/sign/warning/enginesafety{ + desc = "A sign detailing the various safety protocols when working on-site to ensure a safe shift. It seems to particularly focus on how dangerous the sawblade is."; + name = "\improper LUMBERMILL SAFETY" + }, +/turf/closed/wall/mineral/wood, +/area/awaymission/cabin/lumbermill) +"lR" = ( +/obj/structure/closet/crate/wooden{ + desc = "Gotta know what waits within! Could it be a secret treasure cache or a deadly tool of sin?"; + name = "wooden box" + }, +/obj/item/paper{ + info = "Moving these crates through a tunnel that isn't even finished yet is really annoying. It's such a pain in the ass to haul even a single crate to the cabin. It made sense to haul food and other goods however these are fake fucking trophies. Why do they even need these fake artifacts for some asshole's trophy case? We'll just leave the crates in the cave that has all those bones inside. Fuck it."; + name = "Shipment Delivery Note" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lS" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/spider/stickyweb, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"lT" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Seriously, I can't map an entire soviet bunker and new landscape for you. You can't get past this."; + name = "Soviet Hatch" + }, +/area/awaymission/cabin/caves/sovietcave) +"lU" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Can you just stop?"; + name = "GO BACK THE WAY YOU CAME" + }, +/area/awaymission/cabin/caves/sovietcave) +"lV" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mine/sound/bwoink, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"lW" = ( +/obj/structure/flora/tree/dead, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"lX" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/caves) +"lY" = ( +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/caves) +"lZ" = ( +/obj/effect/decal/cleanable/blood, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow{ + name = "packed snow"; + slowdown = 0 + }, +/area/awaymission/cabin/caves) +"ma" = ( +/obj/structure/flora/stump{ + desc = "Breaking it should be easy."; + max_integrity = 20; + name = "old stump" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mb" = ( +/obj/effect/mine/sound/bwoink{ + name = "explosive mine" + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mc" = ( +/obj/structure/flora{ + desc = "Looks frozen."; + icon = 'icons/obj/flora/snowflora.dmi'; + icon_state = "snowgrass2"; + name = "frozen flora" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"md" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/obj/structure/flora/tree/pine, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"me" = ( +/obj/structure/flora{ + desc = "Looks frozen."; + icon = 'icons/obj/flora/snowflora.dmi'; + icon_state = "snowgrass3"; + name = "frozen flora" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mf" = ( +/obj/machinery/light{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/snow{ + floor_variance = 0; + icon_state = "snow_dug"; + slowdown = 1 + }, +/area/awaymission/cabin/caves) +"mg" = ( +/mob/living/simple_animal/hostile/bear/russian{ + desc = "He'll hold the line against you!"; + light_range = 3; + melee_damage_upper = 25; + name = "Artyom"; + speak = list("Blyat!","Rawr!","GRR!","Growl!"); + wander = 0 + }, +/turf/open/floor/plating/asteroid/snow{ + floor_variance = 0; + icon_state = "snow_dug"; + slowdown = 1 + }, +/area/awaymission/cabin/caves) +"mh" = ( +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/snow{ + floor_variance = 0; + icon_state = "snow_dug"; + slowdown = 1 + }, +/area/awaymission/cabin/caves) +"mi" = ( +/obj/effect/decal/cleanable/generic, +/obj/effect/decal/cleanable/shreds{ + pixel_x = 10; + pixel_y = -12 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mj" = ( +/obj/effect/decal/cleanable/generic, +/obj/effect/decal/cleanable/generic{ + pixel_x = -17 + }, +/obj/effect/decal/cleanable/shreds{ + pixel_y = -12 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mk" = ( +/obj/structure/fence{ + dir = 4 + }, +/obj/structure/sign/nanotrasen, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"ml" = ( +/obj/structure/fence{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mm" = ( +/obj/structure/fence/door, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mn" = ( +/obj/structure/fence/cut/large{ + dir = 4 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mo" = ( +/obj/structure/fence/cut/medium{ + dir = 4 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mp" = ( +/obj/structure/fence/cut/medium{ + dir = 4 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mq" = ( +/obj/effect/decal/cleanable/generic, +/obj/effect/decal/cleanable/generic{ + pixel_x = 11; + pixel_y = -4 + }, +/obj/effect/decal/cleanable/shreds{ + pixel_y = -12 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mr" = ( +/obj/effect/decal/cleanable/shreds{ + pixel_x = -12; + pixel_y = -12 + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"ms" = ( +/turf/closed/indestructible/rock/snow/ice, +/area/awaymission/cabin/caves) +"mt" = ( +/obj/structure/fence, +/obj/effect/light_emitter{ + name = "cave light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mu" = ( +/obj/effect/light_emitter{ + name = "cave light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mv" = ( +/obj/effect/light_emitter{ + name = "cave light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mw" = ( +/obj/structure/sign/warning{ + name = "\improper SAWBLADE WARNING"; + pixel_x = -32 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"mx" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/decal/cleanable/cobweb/cobweb2{ + desc = "No, the spider web doesn't have any secrets. For fucksake." + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"my" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/gun/ballistic/automatic/surplus{ + desc = "Uses 10mm ammo and its bulky frame prevents one-hand firing. It has the word CHEKOV engraved on the stock."; + name = "chekov's rifle" + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mz" = ( +/obj/structure/fence/end, +/obj/effect/light_emitter{ + name = "cave light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mA" = ( +/obj/effect/light_emitter{ + name = "cave light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/closed/wall/ice, +/area/awaymission/cabin/caves) +"mB" = ( +/turf/open/floor/plating/snowed/smoothed, +/area/awaymission/cabin/caves) +"mC" = ( +/obj/item/flashlight/flare, +/obj/effect/light_emitter{ + name = "cave light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mD" = ( +/obj/structure/closet/crate/wooden{ + desc = "Gotta know what waits within! Could it be a secret treasure cache or a deadly tool of sin?"; + name = "wooden box" + }, +/obj/item/fakeartefact, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mE" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/closed/indestructible/rock/snow, +/area/awaymission/cabin/caves) +"mF" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 5 + }, +/obj/effect/turf_decal/weather/snow, +/turf/open/floor/plasteel/dark/snowdin, +/area/awaymission/cabin/caves) +"mG" = ( +/obj/effect/turf_decal/weather/snow, +/obj/effect/turf_decal/weather/snow/corner{ + dir = 9 + }, +/obj/effect/turf_decal/weather/snow, +/turf/open/floor/plasteel/dark/snowdin, +/area/awaymission/cabin/caves) +"mH" = ( +/mob/living/simple_animal/hostile/skeleton/ice{ + desc = "A reanimated skeleton covered in thick sheet of natural ice. It is obvious to tell that they look really slow."; + maxHealth = 20; + melee_damage_lower = 5; + melee_damage_upper = 5; + name = "frozen skeleton"; + speed = 7; + wander = 0 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"mI" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mJ" = ( +/obj/effect/turf_decal/weather/snow, +/turf/open/floor/plasteel/dark/snowdin, +/area/awaymission/cabin/caves) +"mK" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Seriously, You can't get past this."; + name = "Soviet Hatch" + }, +/area/awaymission/cabin/caves/sovietcave) +"mL" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/ladder/unbreakable/rune{ + color = "#ff0000"; + desc = "ONE HUNDRED AND TEN PERCENT REAL."; + id = "whatkindofnerdusesmapmakertocheattheirwaytoateleportrune"; + name = "\improper TOTALLY LEGIT PORTAL OF FUN" + }, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mM" = ( +/obj/machinery/door/airlock/hatch, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mN" = ( +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mO" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mP" = ( +/turf/closed/indestructible/rock/snow, +/area/awaymission/cabin/caves) +"mQ" = ( +/obj/structure/closet/crate/wooden{ + desc = "Gotta know what waits within! Could it be a secret treasure cache or a deadly tool of sin?"; + name = "wooden box" + }, +/obj/item/fakeartefact, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"mR" = ( +/obj/effect/decal/cleanable/vomit/old, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mS" = ( +/obj/machinery/door/airlock/vault{ + desc = "Made by the Russians."; + name = "Soviet Door" + }, +/obj/effect/mapping_helpers/airlock/locked, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"mT" = ( +/mob/living/simple_animal/hostile/skeleton/ice{ + desc = "A reanimated skeleton covered in thick sheet of natural ice. It is obvious to tell that they look really slow."; + maxHealth = 20; + melee_damage_lower = 5; + melee_damage_upper = 5; + name = "frozen skeleton"; + speed = 7; + wander = 0 + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"mU" = ( +/obj/effect/turf_decal/weather/snow, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"mV" = ( +/obj/effect/turf_decal/weather/snow, +/obj/item/flashlight/flare, +/turf/open/floor/plasteel/dark/snowdin, +/area/awaymission/cabin/caves) +"mW" = ( +/obj/effect/turf_decal/weather/snow, +/turf/closed/indestructible/rock/snow, +/area/awaymission/cabin/caves) +"mX" = ( +/obj/effect/turf_decal/weather/snow, +/obj/item/flashlight/flare, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"mY" = ( +/obj/effect/turf_decal/weather/snow, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"mZ" = ( +/obj/item/key{ + desc = "A small grey key meant to be placed inside a vehicle. There is nothing special about this key at all besides that."; + name = "ATV key" + }, +/obj/effect/decal/remains/human{ + color = "#72e4fa" + }, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) +"na" = ( +/obj/vehicle/ridden/atv{ + dir = 4 + }, +/turf/open/floor/plating/snowed, +/area/awaymission/cabin/caves) +"nb" = ( +/obj/effect/turf_decal/weather/snow, +/obj/item/pda/syndicate{ + background_color = "#0039A6"; + default_cartridge = /obj/item/cartridge/virus/clown; + desc = "A portable microcomputer by Thinktronic Systems, LTD. Seems like it may have useful information on it."; + name = "soviet PDA"; + note = "TRANSLATED TO GALACTIC COMMON:
DO NOT GO SOUTH." + }, +/obj/effect/decal/remains/human{ + color = "#72e4fa" + }, +/turf/open/floor/plasteel/dark/snowdin, +/area/awaymission/cabin/caves) +"nc" = ( +/obj/effect/baseturf_helper/asteroid/snow, +/turf/closed/wall/ice, +/area/awaymission/cabin/caves) +"nd" = ( +/turf/closed/indestructible/fakedoor{ + desc = "I think that intercomm could open the door."; + name = "Hallway Y8" + }, +/area/awaymission/cabin/caves/mountain) +"ne" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nf" = ( +/obj/effect/decal/cleanable/insectguts, +/obj/effect/decal/cleanable/dirt, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"ng" = ( +/turf/closed/indestructible/fakedoor{ + desc = "Eh, I don't think trying to get past it is worth it anyways."; + name = "Flood Gate" + }, +/area/awaymission/cabin/caves/mountain) +"nh" = ( +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"ni" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"nj" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/effect/decal/cleanable/blood, +/obj/effect/turf_decal/weather/snow/corner, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"nk" = ( +/obj/effect/turf_decal/weather/snow/corner{ + dir = 6 + }, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest/sovietsurface) +"nl" = ( +/obj/structure/lattice/catwalk, +/turf/open/indestructible{ + icon_state = "plating"; + name = "bridge" + }, +/area/awaymission/cabin/caves/mountain) +"nm" = ( +/turf/open/indestructible{ + icon_state = "plating"; + name = "plating" + }, +/area/awaymission/cabin/caves/mountain) +"nn" = ( +/turf/open/indestructible/binary{ + density = 1; + desc = "No, I am not going through this."; + icon = 'icons/misc/beach.dmi'; + icon_state = "water"; + name = "dirty water" + }, +/area/awaymission/cabin/caves/mountain) +"no" = ( +/obj/structure/ladder/unbreakable{ + desc = "Finally."; + icon_state = "ladder10"; + id = "whyisitcalledladder10andnotladder1"; + name = "Freedom" + }, +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/turf/open/indestructible{ + icon_state = "plating"; + name = "plating" + }, +/area/awaymission/cabin/caves/mountain) +"np" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/greenglow, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nq" = ( +/obj/structure/girder, +/obj/effect/decal/cleanable/shreds, +/turf/open/indestructible{ + icon_state = "plating"; + name = "plating" + }, +/area/awaymission/cabin/caves/mountain) +"nr" = ( +/obj/effect/decal/cleanable/greenglow, +/obj/effect/decal/cleanable/dirt, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"ns" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/structure/ladder/unbreakable{ + desc = "Who left the grate open?"; + height = 1; + icon_state = "ladder01"; + id = "dealwentoffwithoutahitchBRO"; + name = "Grate"; + pixel_y = -10 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"nt" = ( +/obj/effect/decal/cleanable/insectguts, +/obj/effect/decal/cleanable/dirt, +/obj/structure/barricade/security, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nu" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/barricade/security, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nv" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/dirt, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nw" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/vomit/old, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nx" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood, +/obj/item/mop, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"ny" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/displaycase{ + start_showpiece_type = /obj/item/dice/d6/space; + trophy_message = "Stolen from dice collector before he could enjoy his day." + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/cabin/caves/mountain) +"nz" = ( +/obj/effect/light_emitter{ + name = "outdoor light"; + set_cap = 3; + set_luminosity = 6 + }, +/obj/structure/ladder/unbreakable{ + alpha = 0; + desc = "Finally."; + height = 1; + icon_state = ""; + id = "whyisitcalledladder10andnotladder1"; + mouse_opacity = 0; + name = "" + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"nA" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/ladder/unbreakable{ + desc = "Yeah, I'll just go back to jail instead of this. It's not like there is an escape out of here, right?"; + icon_state = "ladder10"; + id = "dealwentoffwithoutahitchBRO"; + name = "Sewer Ladder" + }, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nB" = ( +/obj/structure/table/wood/poker, +/obj/item/dice/d6{ + pixel_x = -8 + }, +/turf/open/floor/carpet, +/area/awaymission/cabin) +"nC" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nD" = ( +/obj/effect/decal/cleanable/greenglow, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood, +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nE" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/mob_spawn/human/corpse/damaged, +/obj/effect/decal/cleanable/blood, +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nF" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood, +/obj/effect/decal/cleanable/blood/gibs, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nG" = ( +/obj/effect/decal/cleanable/insectguts, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/blood, +/obj/effect/decal/cleanable/blood/gibs, +/mob/living/simple_animal/hostile/skeleton{ + desc = "Oh shit!"; + dir = 1; + faction = list("sewer"); + name = "sewer skeleton"; + wander = 0 + }, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nH" = ( +/obj/effect/decal/cleanable/dirt, +/mob/living/simple_animal/mouse{ + faction = list("sewer") + }, +/turf/open/indestructible/hoteltile, +/area/awaymission/cabin/caves/mountain) +"nI" = ( +/obj/effect/rune/malformed{ + color = "#5772E0"; + cultist_desc = "The snowman council will now decide your fate."; + cultist_name = "The Snowman Council Rune"; + desc = "An odd collection of symbols drawn in what seems to be frozen water. Despite the fancy setup, the rune seems quite mundane which makes it unworthy of translation."; + icon_state = "2"; + invocation = "Frosty the Snowman was a jolly happy soul with a corncob pipe and a button nose and his eyes made out of coal!"; + invoke_damage = 60; + name = "ice rune" + }, +/obj/item/clothing/suit/snowman{ + desc = "The dead body of a snowman. There's holes to stick your own body in it."; + name = "snowman corpse" + }, +/obj/item/clothing/head/snowman{ + desc = "The head of a dead snowman. There's enough room inside for your own head."; + pixel_x = -1; + pixel_y = 10 + }, +/turf/open/floor/plating/asteroid/snow, +/area/awaymission/cabin/caves) +"nJ" = ( +/obj/effect/turf_decal/stripes/red/line, +/obj/structure/barricade/wooden/snowed, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"nK" = ( +/obj/effect/turf_decal/stripes/red/line{ + dir = 1 + }, +/obj/structure/barricade/wooden/snowed, +/turf/open/floor/plating/snowed/temperatre, +/area/awaymission/cabin/snowforest) +"nL" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/grunge, +/turf/open/floor/mineral/plastitanium/red{ + name = "soviet floor" + }, +/area/awaymission/cabin/caves/sovietcave) +"nM" = ( +/obj/machinery/door/airlock/glass_large{ + name = "Medical Bay" + }, +/turf/open/floor/plasteel/white, +/area/awaymission/cabin) +"nN" = ( +/obj/machinery/light/small, +/turf/open/floor/wood, +/area/awaymission/cabin) +"nO" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/table/wood, +/obj/machinery/chem_dispenser/drinks{ + dir = 8 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"nR" = ( +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"nS" = ( +/obj/machinery/newscaster{ + pixel_y = -32 + }, +/turf/open/floor/wood, +/area/awaymission/cabin) +"nT" = ( +/obj/structure/window{ + dir = 4 + }, +/obj/structure/chair/stool, +/turf/open/floor/wood, +/area/awaymission/cabin) +"nU" = ( +/obj/machinery/door/airlock{ + name = "Bathroom" + }, +/turf/open/floor/plasteel/freezer, +/area/awaymission/cabin) +"nV" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/maintenance{ + name = "Maintenance" + }, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"MS" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/oil, +/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto, +/turf/open/floor/plating, +/area/awaymission/cabin) +"TZ" = ( +/obj/structure/closet/crate/wooden{ + desc = "Gotta know what waits within! Could it be a secret treasure cache or a deadly tool of sin?"; + name = "wooden box" + }, +/obj/item/fakeartefact, +/obj/item/clothing/shoes/winterboots/ice_boots, +/turf/open/floor/plating/ice/smooth, +/area/awaymission/cabin/caves) + +(1,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(2,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(3,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(4,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(5,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +"} +(6,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +"} +(7,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +gx +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(8,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +"} +(9,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gC +gx +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +ab +gx +gx +ab +gx +ab +ab +ab +ab +ab +ab +ab +"} +(10,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fM +fM +fp +fp +fp +fp +fp +nd +nd +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(11,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fG +fN +fN +fS +fV +gi +fp +fp +gz +fN +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ms +ms +ms +ms +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(12,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fW +gj +fp +fp +fP +fP +gE +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +ab +gx +ms +ms +it +mH +ms +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(13,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fr +fI +fH +fQ +fT +fp +fp +fp +fp +fP +fP +gF +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +gx +ms +ms +it +it +ms +ms +ms +ms +gx +gx +gx +gx +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(14,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fs +fJ +fH +fQ +fT +fV +gk +fp +fp +fP +fN +lO +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +gx +gx +ms +it +it +it +it +it +it +mP +ms +ms +gx +gx +gx +ab +ab +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(15,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fX +gj +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +gx +ms +ms +it +it +hO +hO +it +it +it +it +mP +gx +gx +gx +ab +ab +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +"} +(16,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fH +fH +fQ +fT +fp +fp +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +gx +ms +it +it +hO +mQ +hO +it +it +it +it +mP +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(17,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fV +gl +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +ms +ms +it +hO +hO +hO +hO +it +it +it +it +mP +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(18,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fH +ns +fQ +fT +fY +gj +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +ms +it +it +hO +hO +mT +hO +it +ms +it +it +ms +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(19,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fp +fp +fp +fp +fP +gB +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +ab +ms +mD +it +hO +hO +hO +hO +it +it +it +it +ms +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(20,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +ft +fI +fH +fQ +fT +fZ +gm +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +ab +ms +ms +it +hO +hO +hO +hO +hO +it +it +it +ms +gx +gx +gx +ab +ab +ab +ab +ab +gx +gx +ab +ab +ab +ab +ab +"} +(21,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fu +fK +fO +fR +fT +gb +gn +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +ms +ms +mH +hO +hO +TZ +hO +hO +mH +it +it +ms +ms +gx +gx +ab +ab +ab +ab +ab +gx +gx +ab +ab +ab +ab +ab +"} +(22,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fv +fK +fO +fR +fT +fp +fp +fp +fp +fP +fN +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ms +it +it +hO +hO +hO +hO +hO +it +it +it +it +ms +gx +gx +gx +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +"} +(23,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fy +fK +fO +fR +fT +fV +go +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +ms +it +it +it +hO +hO +hO +hO +it +it +ms +it +ms +ms +gx +gx +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +"} +(24,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fz +fJ +fH +fQ +fT +gc +gj +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +ms +it +hO +hO +hO +mT +hO +hO +it +it +it +it +it +ms +ms +gx +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +"} +(25,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fp +fp +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +ab +ms +it +hO +hO +hO +hO +hO +hO +it +it +it +ms +it +it +ms +gx +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +"} +(26,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fH +fH +fQ +fT +fV +gp +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +gx +ms +it +hO +mQ +hO +hO +hO +it +it +it +it +it +it +it +mP +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +"} +(27,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +gd +gj +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +ms +ms +it +hO +hO +hO +hO +it +it +ms +it +ms +it +it +it +ms +ms +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +"} +(28,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fH +fH +fQ +fT +fp +fp +fp +fp +gA +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ms +it +it +it +hO +hO +it +it +ms +ms +it +it +it +it +it +it +ms +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +"} +(29,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fV +gq +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ms +ms +it +it +it +it +it +ms +ms +mP +mP +it +it +it +it +lR +ms +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(30,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fE +fI +fH +fQ +fT +ge +gj +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +kx +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ms +ms +ms +ms +ms +ms +ms +ab +ab +mP +mP +it +ms +it +it +mP +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(31,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fF +fJ +fH +fQ +fT +fp +fp +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +hS +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +mP +it +it +it +ms +ms +ms +ms +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(32,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fq +fH +fH +fQ +fT +fV +gr +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +gP +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +mP +mP +it +it +ms +ms +it +ms +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(33,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fL +fN +fN +fU +gf +gj +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +ab +gx +gx +gx +mP +it +it +it +it +mH +ms +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(34,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fM +fM +fp +fp +fp +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +gx +gx +gx +gx +mP +mP +it +it +mP +mP +mP +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(35,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fP +fN +fp +gg +gs +gv +gy +fP +fN +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +mP +mP +it +it +mP +mP +mP +ab +ab +ab +ab +ab +ab +ab +ab +"} +(36,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fP +fP +fP +fp +gh +gt +gw +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +mP +it +it +it +it +mP +mP +ab +ab +ab +ab +ab +ab +ab +"} +(37,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +ny +fP +fP +fP +fp +fp +fp +fp +fp +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +nz +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kQ +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +it +kQ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +mP +mP +it +it +it +it +mP +mP +ab +ab +ab +ab +ab +ab +"} +(38,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fP +fP +fP +fP +fP +fP +fN +fP +fP +fP +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +gP +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +mP +mP +it +it +ms +it +it +mP +ab +ab +ab +ab +ab +ab +"} +(39,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fN +fP +fP +fP +gu +fP +fP +fP +fN +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +gP +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +me +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +mP +mH +it +it +it +it +ms +mP +ab +ab +ab +ab +ab +ab +"} +(40,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +kx +ac +ac +ac +ac +ac +ac +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +it +kx +kx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ms +ms +ms +it +it +it +ms +ms +ab +ab +ab +ab +ab +ab +"} +(41,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +it +it +it +it +kv +kx +kx +ab +ab +ab +ab +ab +ab +ab +kw +kw +hO +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +gP +kx +kx +kx +lW +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ms +ms +it +it +it +ms +ab +ab +ab +ab +ab +ab +"} +(42,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +ng +ng +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +it +it +it +hO +kw +dj +kx +kx +kx +kx +ab +ab +ab +ab +kw +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +kx +it +kx +kx +ab +ab +ab +ab +kx +kx +kx +kx +ac +ac +ac +gP +ac +kx +kx +ab +ab +kx +kx +kx +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +gW +ac +ac +ac +ac +ac +ac +ac +it +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +iz +iz +mP +mP +mP +mP +mP +iz +iz +iz +iz +nc +ab +ab +ab +ab +ab +"} +(43,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +nr +ne +nn +nn +ne +ne +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +it +it +it +hO +hO +kw +dj +dj +dj +ac +kx +kx +kx +kx +kw +kw +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +gP +ac +kx +kx +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +kx +kx +kx +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +gP +ac +ac +ac +ac +eO +ac +ac +eO +ac +mi +mt +mz +kx +mE +mP +iz +mP +iz +mP +mP +mP +iz +iz +iz +mP +iz +mP +iz +iz +iz +iz +iz +iz +ab +ab +ab +ab +ab +"} +(44,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +ne +nf +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +it +it +it +it +hO +hO +kw +dj +dj +dj +dj +dj +ac +ac +gP +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +kx +kx +kx +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ma +kx +ac +ac +ac +ac +ac +ac +eO +aa +eO +ac +eO +ac +mj +mu +lP +mE +mE +iz +iz +mP +iz +iz +iz +mP +mJ +mJ +mJ +mJ +mJ +mJ +mU +mU +mY +mY +mU +mW +ab +ab +ab +ab +ab +"} +(45,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +nA +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +it +it +it +it +hO +hO +hO +kw +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +lW +kx +kx +ac +ac +ac +ac +gR +ac +ac +ac +ac +eO +ac +ac +ac +ac +mk +mu +mA +mA +mA +iz +mJ +mJ +mJ +mJ +mJ +mJ +mJ +mJ +mJ +mW +mW +mW +mX +mY +mY +mY +mW +mW +ab +ab +ab +ab +ab +"} +(46,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +nH +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +it +hO +hO +hO +hO +kw +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +kx +kx +ab +ab +ab +kx +kx +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +gR +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ml +mv +mv +mF +mJ +mJ +mJ +mJ +mU +mU +mU +mJ +iC +iC +mP +mP +mP +hO +iC +mZ +hO +hO +mP +mP +ab +ab +ab +ab +ab +"} +(47,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +it +hO +hO +hO +hO +hO +kw +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +kx +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gR +eO +ac +ac +ac +ac +ac +mm +mv +mB +mB +iC +iC +iC +iC +iC +mP +mP +iC +iC +hO +hO +hO +hO +hO +hO +hO +hO +na +mP +mP +ab +ab +ab +ab +ab +"} +(48,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +nr +nn +nn +ne +nr +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +hO +hO +hO +hO +hO +hO +it +kv +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +dj +cE +dj +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +kx +kx +kx +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +mn +mv +mC +mB +iC +iC +iC +iC +mP +mP +mP +mP +iC +hO +hO +hO +hO +hO +hO +hO +hO +mP +mP +mP +ab +ab +ab +ab +ab +"} +(49,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +hO +hO +hO +hO +hO +hO +it +kv +kx +ac +ac +ac +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gW +ac +ac +kx +kx +kx +kx +kx +kx +lW +kx +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +mo +mv +mu +mB +iC +iC +iC +iC +mP +mP +mP +mP +iC +hO +hO +hO +hO +hO +hO +hO +iC +mP +mP +mP +ab +ab +ab +ab +ab +"} +(50,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nf +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +hO +hO +hO +hO +hO +hO +it +it +ab +kx +ac +ac +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +eO +ac +ac +ac +ac +ac +ac +ac +eO +ac +ac +mm +mv +mB +mB +iC +iC +iC +iC +iC +mP +mP +iC +iC +iC +iC +hO +hO +hO +hO +hO +iC +mP +mP +mP +ab +ab +ab +ab +ab +"} +(51,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +it +it +it +hO +hO +hO +hO +hO +it +it +it +ab +kx +ac +ac +dj +dj +dj +dj +ac +ac +iO +iN +ac +ac +ac +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gU +ac +gR +ac +ac +ac +ac +ac +ac +gR +ac +ac +ac +gR +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +mp +mv +mu +mG +mJ +mJ +mJ +mJ +mJ +mJ +mU +mJ +iC +iC +iC +iC +hO +iC +hO +iC +iC +mP +mP +mP +ab +ab +ab +ab +ab +"} +(52,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +nf +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +gx +gx +it +it +it +hO +hO +hO +hO +hO +it +it +it +ab +kx +ac +ac +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +mk +mu +mA +mA +mA +iz +mJ +mJ +mJ +mV +mJ +mJ +mW +mW +mW +mU +mU +mU +mU +mU +mJ +nb +mW +mW +ab +ab +ab +ab +ab +"} +(53,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +nf +nH +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +it +it +it +hO +hO +hO +hO +hO +it +it +it +ab +kx +ac +ac +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +eO +ac +ch +ac +mq +mu +lP +lP +mE +iz +iz +mP +iz +iz +iz +mP +mW +mW +mW +mW +mJ +mJ +mJ +mW +mW +mW +mW +mW +ab +ab +ab +ab +ab +"} +(54,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +ab +it +it +it +it +hO +hO +hO +hO +it +it +it +ab +ab +kx +ac +ac +dj +dj +cE +dj +dj +dj +ac +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gW +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +gW +ac +ac +ac +ac +ac +ac +eO +ac +ac +ac +mr +mt +mz +kx +mE +mP +iz +mP +mP +iz +iz +iz +iz +iz +mP +mP +mP +iz +iz +iz +iz +mP +mP +mP +ab +ab +ab +ab +ab +"} +(55,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nr +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +it +it +it +it +hO +hO +hO +hO +it +it +it +ab +ab +kx +ac +ac +ac +dj +dj +dj +dj +dj +dj +ac +ac +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +eO +mc +kx +kx +mE +mP +ab +ab +ab +ab +ab +ab +ab +iz +iz +iz +mP +mP +mP +mP +mP +iz +iz +iz +iz +ab +ab +ab +ab +ab +"} +(56,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +ne +ne +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +it +it +it +it +hO +hO +hO +hO +it +it +ab +ab +ab +kx +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(57,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +nv +ne +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +hO +hO +hO +hO +hO +iK +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +cE +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gU +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +me +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(58,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +nf +ne +nn +nn +ne +ne +ne +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +it +hO +hO +hO +hO +it +it +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gW +ac +ac +ac +ac +ac +ac +gP +ac +ac +eO +ac +ac +ac +ac +ac +ac +kQ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(59,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +nr +ne +nx +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +it +it +hO +hO +hO +hO +it +gx +gx +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gR +ac +ac +ac +ac +ac +ac +ac +gR +ac +ac +ac +eO +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(60,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +nr +nn +nn +ne +ne +nt +ne +ne +ne +ne +nD +nE +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +it +it +hO +hO +hO +hO +hO +it +gx +gx +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(61,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +nn +nn +ne +nu +nH +ne +nC +nf +nC +ne +nF +nG +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +it +hO +hO +hO +hO +hO +it +it +it +gx +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +eO +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(62,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +nH +nn +nn +nt +ne +ne +nr +ne +ne +ne +nw +ne +nE +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +hO +hO +hO +hO +hO +hO +it +it +it +gx +ab +ab +ab +kx +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +gW +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(63,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nf +ne +ne +nn +nn +nn +nn +nn +nn +nn +nn +nl +nl +nn +nn +ng +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +ki +ki +kq +ks +ki +ki +ki +it +it +gx +gx +gx +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(64,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +nf +nn +nn +nn +nn +nn +nn +nn +nn +nl +nl +nn +nn +ng +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +ko +ki +ki +ki +ki +ku +ki +it +it +gx +gx +gx +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kQ +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(65,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +ne +ne +ne +nf +ne +ne +ne +ne +ne +ne +ne +ne +nH +ne +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +hO +hO +hO +hO +hO +hO +it +it +it +gx +gx +gx +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gW +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gU +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(66,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +ne +nr +ne +ne +nH +ne +ne +ne +ne +nr +ne +ne +ne +ne +nr +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +fA +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gW +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +kx +mc +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(67,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +ne +ne +ne +ne +ne +np +ne +ne +ne +ne +ne +nf +ne +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +fw +fB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(68,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +fp +fp +nq +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +fw +fC +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kh +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +lW +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(69,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +nm +nm +nm +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +it +it +it +gx +gx +gx +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +hN +ac +ac +em +fx +fx +fB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gR +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(70,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +fp +nm +nm +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +it +it +it +gx +gx +gx +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +fw +fx +fx +fD +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(71,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +hO +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +kx +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +fw +fx +fC +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(72,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +hO +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +cR +ek +ek +ek +ek +ek +ek +fx +fx +fC +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gU +ac +ac +kQ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(73,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +hO +hO +hO +hO +hO +hO +hO +hO +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +cR +bS +ce +ce +ce +bS +bS +bS +fx +fx +fC +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(74,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fp +fp +fp +fp +nm +nm +fp +fp +fp +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +hO +hO +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +cR +bS +bS +cf +cf +cf +bS +bS +bS +fx +fx +fx +fB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gW +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(75,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +hO +hO +hO +hO +hO +hO +hO +it +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ef +bS +bS +cg +cg +cg +bS +bS +bS +fx +fx +fx +fC +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(76,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +it +hO +hO +hO +hO +hO +hO +hO +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +dB +dB +dB +dB +dB +dB +dB +dB +dB +dB +dB +dB +cr +el +el +en +el +el +el +el +el +ep +ep +ep +er +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(77,1,1) = {" +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +dB +an +an +an +an +an +an +an +ao +ao +an +an +an +an +an +an +an +an +ba +ba +an +eq +eq +eq +eq +an +dB +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(78,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +it +it +it +it +it +ki +ki +ki +ki +ki +kr +it +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +aV +jr +au +jk +an +aq +aq +an +bl +bM +ij +bT +cs +bl +an +aq +aq +an +cS +aL +aL +aL +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(79,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +gx +gx +it +it +ki +ki +ki +kp +ki +ki +it +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +dB +iZ +aN +jl +bb +bb +bb +eg +bm +eg +nS +an +eg +eg +eg +eg +eg +eg +hB +eg +aq +an +cT +cV +gL +cV +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(80,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +it +gx +it +it +it +hO +hO +hO +hO +hO +hO +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +iZ +jy +jG +az +az +az +aq +an +eg +bh +an +cA +an +an +an +an +hx +an +eg +aq +an +cU +nR +aL +ec +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(81,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +gx +gx +gx +gx +iK +hO +hO +hO +hO +hO +hO +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +iZ +bp +aq +az +az +az +aq +an +eg +aq +an +aq +aq +aq +aq +aq +aq +an +eg +aq +an +cV +MS +cV +cV +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(82,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +it +gx +gx +gx +it +it +hO +hO +hO +hO +hO +hO +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +aA +aI +aA +aq +an +in +aq +an +bn +aq +aq +aq +aq +bh +an +eg +bh +an +aL +nR +aL +ed +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(83,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +it +it +gx +it +it +it +hO +hO +hO +hO +hO +hO +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +dB +an +nU +an +an +an +aR +an +eg +aq +an +aq +aq +eg +aq +aq +aq +an +eg +aq +an +cU +cW +aL +gN +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +gW +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(84,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +it +gx +it +it +hO +hO +hO +hO +hO +hO +hO +it +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +dB +an +as +aB +aH +an +an +an +eg +aq +an +cz +aq +eg +aq +aq +bh +an +eg +aq +an +ed +nR +aL +kE +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(85,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +dB +an +an +an +an +an +aS +hg +eg +bh +an +nT +bo +ht +bo +bo +cB +an +eg +eg +bV +aw +aw +gM +an +an +dB +gP +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(86,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +gP +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +at +aC +aH +an +an +an +eg +aq +an +aO +aO +hC +hC +hC +bb +bb +eg +aq +an +eb +cX +an +an +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(87,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +dB +an +nU +an +an +an +aT +an +eg +aq +an +az +aq +aq +az +aq +aq +cO +eg +bh +an +an +an +an +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +gP +ac +ac +ac +ac +md +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(88,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +au +jt +aV +aq +an +bs +aq +eh +az +aq +az +cO +az +ci +he +hG +aq +eN +an +dB +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dX +dj +dj +dj +dj +dj +dX +dj +dj +dj +dj +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(89,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +no +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kC +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +dB +ja +aN +aq +az +az +az +aq +an +eg +aq +an +aP +az +ej +nB +hd +az +aO +eg +aq +aq +an +an +dB +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(90,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +nm +nm +nm +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +kx +kz +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +ja +jy +jF +az +az +az +aq +an +eg +bh +an +bq +az +ha +hc +hd +az +az +eg +aq +aq +aN +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(91,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +iK +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +ab +ab +kx +it +ac +hV +ac +hT +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +dB +ja +bp +jm +bb +bb +bb +eg +iY +eg +aq +an +bt +az +ej +jx +hd +az +cO +eg +aq +aq +iR +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(92,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +iK +it +it +gx +gx +gx +gx +ab +ab +ab +kx +kB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +aA +aI +aA +jj +an +eg +aq +an +cN +aq +az +aO +az +ci +hF +hG +aq +aq +bp +ao +dB +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dX +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(93,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fp +fp +fp +fp +fp +fp +fp +fp +fp +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +gx +gx +gx +gx +gx +ab +ab +ab +kx +kP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +dB +dB +an +an +an +an +an +an +an +ct +aq +an +jE +aq +aq +az +aq +aq +aO +eg +aq +aq +an +an +dB +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +ea +cE +dj +dj +dj +dj +dX +dj +dj +dj +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(94,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +dB +an +an +aq +aV +ju +au +ji +an +eg +aq +an +de +de +de +de +de +bb +bb +eg +bh +an +an +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dY +ea +dY +ea +dY +dj +dj +dj +dj +dj +dj +ac +ac +gW +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(95,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +iK +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +kx +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +jb +aN +jn +bb +bb +bb +eg +iX +eg +bh +an +hb +bU +ev +eu +cK +cD +an +eg +aq +aq +an +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +dj +dj +dj +dj +dj +dj +dY +ea +dY +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(96,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +jb +jy +jH +az +az +az +aq +an +eg +aq +an +hn +aq +aq +aq +aq +aq +an +eg +aq +aq +aN +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(97,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +fm +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +it +it +it +iK +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +kx +kx +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +jb +bp +aq +az +az +az +aq +an +eg +aq +an +bv +bN +nO +aq +ap +aq +an +eg +aq +aq +iU +ao +dB +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(98,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +aA +aI +aA +aq +an +in +aq +an +an +an +an +bu +an +eo +an +eg +aq +aq +bp +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +gP +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(99,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +iK +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +kQ +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +dB +an +nU +an +an +an +aU +an +eg +aq +an +bw +bO +bO +bO +bO +hz +hE +eg +aq +aq +an +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(100,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +cn +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +dB +an +as +aB +aH +an +an +an +eg +aq +an +bx +bO +cJ +cF +cJ +hz +an +eg +bh +an +an +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dX +dj +dj +dj +dj +dj +dj +dj +dj +dX +dj +dj +dj +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(101,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +iK +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +dB +an +an +an +an +an +hf +hy +eg +aq +an +by +hz +hz +hz +hz +hz +an +eg +aq +aq +an +an +dB +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(102,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +ab +ab +it +it +it +it +it +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +hO +it +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +dB +an +at +aC +aH +an +an +an +eg +bh +an +bz +bO +bW +ck +cj +hz +an +eg +aq +aq +aN +ao +dB +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dX +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(103,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +it +it +it +it +it +hO +hO +iL +iL +iL +iL +iL +iL +iL +iL +iL +it +it +it +it +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +dB +an +nU +an +an +an +aW +an +eg +aq +an +an +an +an +an +an +hA +an +eg +aq +aq +iS +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(104,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iK +it +it +it +it +iL +iL +iL +iL +iL +iL +iL +iL +iL +iL +iL +it +it +it +it +it +iK +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +dB +an +an +aq +au +jv +aV +aq +an +bs +aq +an +bA +bB +bX +cl +cl +hi +an +eg +aq +aq +bp +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(105,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +it +it +it +it +iL +iL +iL +iL +it +iL +iL +iL +it +it +iL +iL +it +it +iK +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +dB +jc +aN +aq +az +az +az +aq +an +eg +aq +an +hi +hi +hi +hi +hi +hi +an +hh +aq +aq +an +an +dB +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(106,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +it +it +it +it +it +it +it +it +it +iL +iL +iL +it +it +it +iL +iL +it +it +it +it +gx +gx +ab +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +jc +jy +jI +az +az +az +aq +an +eg +aq +an +bC +bB +bY +is +dt +cG +an +eg +bh +an +an +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +dj +dj +dj +ac +ac +gW +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(107,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +it +iK +it +it +it +it +it +it +it +iL +iL +kn +it +it +it +iL +iL +it +it +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +dB +jc +bp +jo +bb +bb +bb +eg +iW +eg +aq +an +an +an +an +an +an +an +an +eg +aq +aq +an +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dj +dj +dj +dj +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(108,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +it +it +it +it +it +it +it +it +iv +iv +kj +iv +iv +it +it +iL +iL +iL +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +dB +an +an +au +aA +aI +aA +jg +an +eg +aq +an +aJ +bG +bE +cv +hq +cv +an +eg +aq +aq +aN +ao +dB +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(109,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +it +iv +iv +iM +iM +iM +iv +iv +it +it +iL +iL +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kg +dB +an +an +an +an +an +an +an +ct +bh +an +aK +bE +bE +bE +bE +lz +an +eg +aq +aq +iT +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(110,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +gx +gx +it +it +it +it +it +it +iv +iM +iM +iM +iM +iM +iv +it +it +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +aV +jw +au +jh +an +eg +aq +an +bD +bE +bE +cI +hD +bE +nM +eg +aq +aq +bp +ao +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(111,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +it +it +it +it +it +iv +iP +iM +kl +iM +iM +iv +it +it +iL +iL +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +jd +aN +jp +bb +bb +bb +eg +iV +eg +aq +an +cP +cP +cP +cP +jq +cP +cP +eg +aq +aq +an +an +dB +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(112,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +it +it +it +iK +it +iv +iM +iM +iM +iM +iM +iv +it +it +iL +iL +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +it +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +dB +jd +jy +jJ +az +az +az +aq +an +eg +aq +an +bF +bP +cm +ho +bE +lz +an +eg +aq +an +an +dB +dB +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(113,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +it +it +it +it +iv +iv +iQ +km +iQ +iv +iv +it +it +iL +iL +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +it +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +jd +bp +aq +az +az +az +aq +an +eg +nS +an +bF +bQ +cu +hp +js +hp +an +eg +aq +an +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(114,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +gx +gx +ab +it +it +it +iv +iv +iv +iv +iv +it +it +it +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +an +aq +aA +aI +aA +aq +an +in +nN +an +an +an +an +an +an +an +an +eg +bh +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(115,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +gx +gx +gx +gx +gx +gx +kt +kt +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +dB +dB +an +nU +an +an +an +aU +an +eg +eg +nV +ei +et +hj +hr +hs +et +nV +eg +aq +an +dB +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(116,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iL +iL +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +an +as +aB +aH +an +an +an +ar +an +an +an +an +an +an +an +an +an +cM +hm +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(117,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kt +kt +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +cY +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +dB +dB +an +an +an +an +an +aX +bf +bb +an +bj +bH +an +kk +aq +aq +aq +io +bb +az +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(118,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +it +iL +iL +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +ax +an +aF +cL +aw +jC +bb +bb +bb +an +bk +bJ +an +aq +aq +aq +aq +cH +cQ +ee +an +dB +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(119,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +it +it +iL +iL +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dD +dH +dH +dH +dH +dH +dN +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +ax +av +aw +ed +hu +an +aY +bc +bg +an +nU +an +an +aq +cp +eg +eg +eg +cQ +hI +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(120,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +it +iL +iL +iL +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ad +ad +eG +eG +eH +eG +eG +ad +ad +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +ax +ed +aw +ed +hv +an +hl +bd +az +an +jf +ay +an +aq +aq +aq +aq +cH +hH +ee +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(121,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +it +iL +iL +iL +gx +gx +gx +gx +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ad +ad +jP +af +af +af +af +af +jP +ad +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +ax +aD +aM +du +hw +an +aZ +be +az +bi +hk +bL +an +bn +aq +aq +aq +aq +az +az +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(122,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +it +it +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ad +ad +af +af +af +af +jB +af +af +af +af +ad +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +gP +dB +ax +aE +aQ +dv +an +an +ao +ao +ao +an +an +je +an +an +jD +jD +an +jA +jz +an +an +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(123,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +gx +gx +gx +gx +gx +gx +gx +it +it +iL +iL +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +kx +ac +ch +ac +ac +ac +ac +ac +ac +ac +ad +ew +af +af +al +kf +ff +eQ +ak +af +af +eY +ad +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +ax +ax +ax +ax +ax +dB +dB +dB +dB +dB +dB +dB +dB +an +ao +ao +an +ao +ao +an +dB +dB +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(124,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +it +it +iL +iL +iL +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ad +ad +af +af +ak +af +am +af +fe +af +af +ad +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dB +dB +dB +dB +dB +dB +dB +ac +ac +ac +ac +ac +ac +dB +dB +dB +dB +dB +dB +dB +dB +dB +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +it +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(125,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ad +jM +af +af +af +jV +af +af +af +jM +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(126,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ad +gY +af +af +af +af +af +af +af +jR +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(127,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +iL +iL +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ch +ac +ac +ac +ac +ac +ad +gY +af +af +ak +af +ak +af +af +kD +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(128,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +iL +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ch +ac +ac +ad +jQ +af +ak +jX +af +ka +ke +af +eA +ad +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dA +dC +dC +gO +dC +gO +dC +dC +dC +dC +lP +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(129,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iz +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ad +gY +af +jW +af +af +jU +jT +af +jR +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(130,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iz +iz +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +iL +iL +iL +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ad +jM +af +kb +gZ +af +af +jS +af +jM +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +es +ac +ac +dx +dz +dz +dz +dz +dz +gX +dz +dz +dz +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(131,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iA +iC +gx +gx +iA +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +iL +iL +iL +it +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +iK +kx +ac +ac +ac +ac +ac +ac +ac +ad +ad +af +af +ak +jL +af +kd +kc +af +af +ad +ad +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dy +dz +dz +dz +dz +dz +dz +dz +dz +gX +dz +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(132,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iB +iC +iG +iC +iH +gx +gx +gx +gx +gx +gx +gx +gx +iK +it +iL +iL +iL +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ad +ex +af +af +af +jZ +af +jY +af +af +af +eZ +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +ga +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +lX +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(133,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iz +iA +iC +iC +iC +iJ +iz +gx +gx +gx +gx +gx +it +it +it +it +iL +iL +iL +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ad +ad +af +af +af +af +af +af +af +af +af +ad +ad +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dL +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(134,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iz +iz +iD +iH +iI +iz +iz +gx +gx +gx +gx +it +it +it +it +iL +iL +iL +it +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ch +ac +ch +ac +ac +ac +ac +ae +ad +ad +jO +af +af +af +af +af +jO +ad +ad +fb +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(135,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +iz +iz +iz +iz +iz +it +gx +gx +gx +it +it +it +it +iL +iL +iL +it +it +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +ad +ad +eH +eG +lQ +eG +eH +ad +ad +cZ +fc +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dz +dz +dz +gX +dz +dz +dz +dz +dz +gX +dz +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(136,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +gx +gx +gx +gx +it +it +it +iL +iL +iL +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +iK +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +mw +bS +bS +eI +eM +eU +bS +bS +mw +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +gX +dz +dz +dz +dz +dz +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(137,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +gx +gx +gx +it +it +it +iL +iL +iL +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ch +ac +ag +cZ +bS +bS +eE +eJ +eR +eV +eE +bS +bS +cZ +fc +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +gX +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(138,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +hO +it +it +it +gx +gx +gx +it +it +iL +iL +iL +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ch +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +bS +eD +eF +eJ +eR +eV +eF +eD +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +dx +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(139,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +hO +hO +it +it +iE +gx +gx +gx +it +it +iL +iL +iL +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +bS +eE +cZ +eJ +eR +eV +cZ +eE +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(140,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +hO +hO +it +it +it +gx +gx +it +it +it +iL +iL +iL +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ch +ac +ac +ac +ac +ac +ac +ah +cZ +bS +eF +cZ +eK +eR +eV +cZ +eF +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +gX +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +dz +kA +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(141,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +hO +hO +it +it +it +gx +it +it +it +it +it +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +bS +bS +cZ +eJ +lC +eV +cZ +bS +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +aG +dg +dg +dE +dE +dE +dE +dE +dE +hZ +hZ +dg +dg +if +lX +lY +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(142,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +hO +hO +it +it +it +it +it +it +it +it +it +iK +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ch +ac +ac +ac +ag +cZ +bS +bS +cZ +nJ +eS +nK +cZ +bS +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +bK +dh +di +dF +dO +dF +dh +dF +dF +dF +dF +ic +dp +nh +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(143,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +it +hO +it +it +it +it +it +it +it +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ch +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +bS +bS +bS +eJ +lC +eV +bS +bS +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +kA +bK +di +di +ds +di +di +dw +di +hY +di +di +di +dh +nh +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(144,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +it +iE +hO +hO +it +it +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +bS +bS +bS +eK +eR +eW +bS +bS +bS +cZ +fc +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +da +dk +di +dG +dG +dG +dG +dJ +dG +dI +dG +di +id +ni +lX +lY +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(145,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +it +hO +hO +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ky +ac +ac +ac +ac +ac +ac +ac +ac +ac +ag +cZ +cZ +bS +bS +eL +eT +eX +bS +bS +cZ +cZ +fc +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +kx +kx +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +dx +dz +gX +dz +dz +db +dl +dr +dI +di +di +dU +fi +di +dh +dG +di +id +ni +lZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(146,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ai +cZ +cZ +cZ +bS +bS +bS +bS +bS +cZ +cZ +cZ +fd +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dc +dm +di +dG +dP +di +dh +dW +dS +ia +dG +di +id +ni +lX +lY +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(147,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +kx +kx +ac +ac +ch +ac +ac +ac +ac +ac +ch +ac +ey +ez +eC +eC +eC +eC +eC +eC +eC +eC +eC +fa +ey +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +kx +it +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dd +dn +di +dG +di +dS +di +hX +di +di +dG +di +ie +ni +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(148,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +ix +hO +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ky +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +ab +ab +ab +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +dx +dz +dz +dz +dz +dd +dn +ds +dG +di +dT +di +dh +di +dh +dG +di +id +ni +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(149,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +kx +kx +kx +kx +kx +kx +kx +ac +ac +ac +ac +ac +gP +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +gP +ac +dx +dz +dz +dz +dz +db +do +di +dG +di +dh +di +di +di +ib +dG +dw +id +nj +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(150,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ch +ac +ac +ac +ch +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +kx +kx +kx +kx +ac +ac +ac +ac +kx +kx +kx +kx +ab +ab +ab +ab +ab +kx +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +gP +kx +kx +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +kx +ac +kx +kx +lP +lX +dz +gX +dz +db +dl +di +dJ +dQ +di +dV +di +dU +dV +dI +dh +ie +ni +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(151,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +kx +kx +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +gP +ac +ac +ac +kx +kx +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +it +kx +ab +ab +lX +lX +dz +dz +da +dk +dw +dG +dI +dG +dG +dG +dG +dG +dG +di +id +ni +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(152,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +gP +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ab +ab +ab +ab +lX +lX +kA +bK +di +di +dh +di +di +dW +ds +di +di +di +di +di +nh +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(153,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +lX +lX +bK +dp +dh +dK +dR +dK +dK +dK +dh +dK +dK +di +dp +nh +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(154,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +ix +hO +hO +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +ab +kx +ac +ac +ac +ac +kx +kx +kx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +lX +df +dq +dq +dM +dM +dM +dZ +dM +dM +dM +dM +dq +dq +nk +lX +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(155,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +it +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ch +ac +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +kx +kx +kx +it +kV +kx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +lX +lX +lX +dz +dz +lX +lX +lX +dz +dz +dz +lX +lX +lX +lX +lZ +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(156,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +hO +hO +hO +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +kx +kx +kx +kx +kx +kx +kx +ac +ch +ac +ch +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +gx +iv +iv +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +lX +lX +lZ +lX +ab +lX +lX +lX +lZ +lX +ab +gx +lX +lY +iL +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(157,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +it +it +iF +it +it +it +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ch +ac +kx +kx +ab +ab +ab +ab +ab +kx +kx +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +gx +gx +gx +iv +iv +gx +gx +gx +gx +it +it +gx +gx +lp +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +lY +ab +ab +ab +lY +ab +ab +lY +ab +ab +gx +gx +iL +iL +iL +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(158,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +it +it +it +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +ac +gW +ac +ac +ch +ac +ac +ac +ac +ch +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +iK +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +gx +gx +gx +iv +iv +gx +gx +it +it +it +it +it +it +it +it +it +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +it +iL +iL +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(159,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +it +hO +hO +hO +hO +hO +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +ac +ac +ac +ac +ac +ac +ch +ac +ac +ac +ac +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +kU +it +it +gx +gx +kX +it +it +it +it +it +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +iL +iL +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(160,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +hO +hO +hO +hO +hO +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +kx +kx +kx +kx +kx +kx +kx +kx +kx +kx +kx +kx +kx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +it +it +it +gx +gx +it +it +it +it +it +it +it +gx +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +iL +iL +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(161,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +hO +hO +hO +hO +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +it +kT +it +gx +gx +gx +gx +it +it +it +it +it +it +lu +lu +lu +it +iK +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +iL +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(162,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +gx +gx +gx +gx +gx +it +it +it +it +lu +it +it +it +lu +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(163,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ix +hO +hO +it +it +it +it +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +it +it +kU +it +gx +gx +gx +gx +gx +it +it +it +it +it +nI +it +lu +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +it +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(164,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +kU +it +it +it +gx +gx +gx +gx +gx +gx +lp +gx +lu +it +it +it +lu +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +it +iL +iL +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(165,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +iy +hO +it +it +it +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +kU +gx +gx +gx +gx +gx +gx +gx +gx +lB +lu +lu +iK +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +it +iL +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(166,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +it +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +gx +it +it +it +hO +hO +hO +ix +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +gx +ab +iL +iL +iL +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(167,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +hL +hO +hO +hO +hO +hO +it +it +it +it +gx +gx +gx +it +it +it +it +gx +gx +hO +ix +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +kS +it +it +gx +it +kU +it +kT +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +ab +gx +gx +ab +iL +iL +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(168,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +hM +hP +hQ +hP +hW +hO +it +gx +it +it +it +it +it +it +it +it +gx +gx +gx +gx +hO +hO +ix +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +gx +ab +iL +iL +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(169,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +hM +hQ +hR +hQ +ig +il +hO +gx +gx +gx +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +kU +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +ab +ab +iL +iL +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(170,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +hM +hP +hQ +hP +ih +hO +hO +gx +gx +gx +iv +iw +iv +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +kT +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +iL +iL +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(171,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +hL +hO +hO +hO +hO +hO +gx +gx +gx +gx +iv +iv +iv +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kU +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +it +iL +iL +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(172,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +kS +gx +it +it +kU +gx +gx +gx +gx +gx +gx +gx +lh +gx +it +it +kU +it +it +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +it +iL +iL +iL +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(173,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +it +it +it +gx +gx +gx +gx +gx +la +it +it +it +it +gx +gx +it +it +it +kU +gx +it +kS +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +it +iL +iL +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(174,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +ab +gx +gx +gx +it +gx +it +it +it +gx +gx +gx +gx +it +it +it +it +it +it +it +it +it +it +it +it +it +it +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +iL +iL +iL +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(175,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hO +hO +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +it +it +gx +gx +gx +gx +it +kU +it +gx +gx +kT +gx +it +gx +gx +it +it +it +it +it +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +iL +iL +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(176,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +hO +hU +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +gx +gx +gx +gx +it +it +it +gx +it +it +it +it +kU +gx +gx +lE +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +iL +iL +iL +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(177,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +iK +it +kU +it +gx +gx +gx +it +it +kT +it +it +it +it +kU +it +it +gx +it +it +it +it +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +iL +iL +iL +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(178,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +gx +gx +gx +gx +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +it +gx +it +kT +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +iL +iL +iL +iL +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(179,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +it +it +gx +gx +gx +gx +it +kU +it +it +ld +gx +lm +ld +gx +gx +gx +it +gx +it +it +it +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +iL +iL +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(180,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +it +it +gx +gx +gx +it +it +gx +gx +gx +le +le +le +lg +le +lf +gx +it +gx +gx +it +it +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(181,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +it +gx +gx +gx +gx +kU +it +gx +gx +gx +gx +li +ld +lq +lk +lv +gx +it +gx +gx +it +it +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +iL +iL +it +it +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(182,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +kT +it +gx +gx +gx +it +it +gx +gx +gx +lf +li +le +lr +le +ld +gx +it +gx +gx +it +it +kU +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +iK +iL +iL +iL +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(183,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kS +gx +it +kU +gx +gx +gx +it +it +gx +gx +gx +gx +lj +le +li +le +lw +gx +it +gx +it +it +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +it +it +it +iL +iL +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(184,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +gx +gx +gx +kW +it +gx +gx +gx +gx +gx +ln +le +ld +lx +gx +it +gx +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +iL +iL +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(185,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +gx +gx +gx +it +it +it +gx +gx +gx +gx +gx +ls +le +ly +gx +kT +gx +it +it +it +it +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +ab +ab +ab +iL +iL +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(186,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +gx +gx +gx +it +gx +kU +gx +gx +gx +gx +li +le +le +lo +gx +lD +gx +it +it +gx +it +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +it +iL +iL +it +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(187,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +gx +gx +gx +it +it +it +it +gx +gx +le +lk +le +ld +lA +gx +gx +gx +lF +gx +gx +kU +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +it +it +iL +iL +it +it +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(188,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kU +it +gx +gx +gx +gx +it +iE +it +it +lg +le +le +lg +lt +gx +gx +gx +it +it +it +gx +it +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +iL +iL +ab +it +it +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(189,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +gx +gx +gx +gx +gx +kU +it +gx +lk +lo +gx +gx +gx +gx +gx +it +gx +gx +gx +it +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +iL +iL +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(190,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +kU +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +gx +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +gx +gx +iL +iL +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(191,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +kT +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +gx +gx +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +gx +ab +ab +iL +iL +ab +ab +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(192,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +gx +gx +kY +it +it +ll +it +kT +it +ll +it +kT +it +it +it +gx +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +ab +gx +ab +it +iL +iL +it +it +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(193,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +kU +it +it +it +it +it +it +gx +gx +gx +gx +gx +gx +it +it +it +kU +gx +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +ab +ab +iL +iL +it +it +it +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(194,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +gx +it +kU +it +it +it +it +gx +it +gx +gx +gx +gx +it +it +gx +gx +gx +kT +it +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +gx +gx +ab +ab +gx +gx +gx +gx +gx +it +iL +iL +it +gx +it +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(195,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kS +it +it +it +it +kU +it +kT +it +it +it +gx +it +it +gx +it +gx +it +it +it +it +it +it +iK +gx +gx +it +it +it +kU +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +ab +gx +gx +gx +ab +ab +gx +gx +gx +ab +ab +gx +it +iL +iL +it +it +it +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(196,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +gx +gx +gx +gx +gx +it +it +gx +it +kU +gx +it +it +it +gx +gx +gx +it +kT +it +gx +it +it +it +gx +it +it +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +iL +iL +ab +ab +it +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(197,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +it +it +iK +it +gx +gx +it +it +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +gx +ab +ab +gx +gx +gx +gx +ii +ii +ab +ab +gx +iL +iL +it +ab +ab +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(198,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +gx +it +lp +it +it +it +it +gx +gx +it +kT +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +it +it +ab +it +iL +iL +it +ab +ab +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(199,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kT +it +iu +gx +it +lG +gx +gx +it +lK +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +ii +it +it +it +iL +iL +iL +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(200,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +kY +gx +it +it +it +gx +kU +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +it +it +iL +iL +iL +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(201,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kU +it +gx +gx +gx +it +it +it +it +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +ii +ii +mf +iL +iL +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(202,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +gx +gx +gx +gx +kU +gx +it +it +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +ii +ii +ii +ii +ii +iL +mg +mh +it +it +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(203,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +lN +it +it +it +gx +gx +gx +gx +gx +it +it +iK +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +mM +im +mS +iL +iL +ii +it +it +iK +ii +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(204,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kS +it +it +it +lM +it +gx +gx +gx +it +lH +ii +ii +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +ii +ii +ii +gx +ii +mO +im +ii +ii +ii +mS +ii +ii +ii +ii +ii +ii +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(205,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +kU +gx +it +it +kU +it +it +it +it +ii +iq +ii +gx +ii +ii +ii +ii +gx +ii +ii +ii +ii +gx +gx +ii +lb +im +ii +ii +ii +im +im +kF +iq +ii +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(206,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kU +it +gx +gx +gx +gx +gx +it +it +ii +ik +ii +ir +ii +ii +ii +kH +im +ii +ii +ii +kH +im +ii +ii +gx +ii +im +im +kF +kH +im +im +im +kF +kF +ii +mM +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(207,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +gx +gx +gx +lJ +it +lp +ik +im +ip +jK +im +im +ir +ir +ir +ir +im +ir +ir +ir +ir +ii +gx +ii +im +kF +kF +im +im +im +im +im +im +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(208,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +it +it +gx +gx +it +it +it +ii +ii +ii +jN +im +im +jK +im +im +jK +im +im +im +im +im +ii +ii +ii +im +my +kF +im +im +im +im +im +im +im +im +ii +gx +gx +gx +gx +gx +gx +gx +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(209,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +lL +it +it +it +it +it +it +it +ik +im +ip +im +im +im +im +im +ir +ir +im +im +im +im +im +ii +kO +ii +im +kF +kF +im +im +kJ +im +im +ii +ii +ii +ii +gx +gx +gx +gx +gx +gx +gx +ab +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(210,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +iK +gx +it +it +kU +it +ii +ik +ii +im +jK +im +im +im +ir +im +im +im +kJ +im +im +ii +ii +ii +im +im +kF +im +im +im +im +mI +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(211,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kT +it +it +it +it +kU +ii +im +im +im +im +jK +ir +ir +im +im +im +im +im +ir +im +ii +ii +ii +ii +im +im +im +im +kF +ii +ii +gx +gx +gx +gx +gx +ab +gx +ab +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(212,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +it +it +it +lI +ii +ii +ii +kF +kF +kF +im +im +im +im +im +im +im +im +im +nL +kH +im +nL +im +im +im +im +kF +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(213,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +kT +it +gx +gx +ii +ii +kG +ii +ii +ii +ii +kI +im +im +im +ir +im +ii +im +kF +ii +mN +im +im +im +kF +mR +ii +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(214,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +it +gx +gx +gx +gx +ii +ii +ii +gx +gx +ii +ii +ir +ir +ir +ii +ii +ii +im +im +ii +ii +ii +ii +ii +ii +ii +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(215,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +ir +im +ir +ii +kN +ii +kF +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(216,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +im +ii +ii +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(217,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +kK +kL +kM +ii +gx +ii +im +kF +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(218,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +ii +ii +ii +ii +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(219,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +kF +mI +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(220,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(221,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gK +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lc +lc +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(222,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gH +gH +gS +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +iq +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(223,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gH +gH +gH +gH +gH +gH +gH +hK +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +mI +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(224,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gI +gH +gH +gH +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +iq +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(225,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gH +gH +gH +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(226,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gH +gH +gT +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(227,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gH +gH +gH +gH +hJ +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(228,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gQ +gH +gH +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +ab +gx +gx +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(229,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gH +gH +gH +gV +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +ab +gx +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(230,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gH +gJ +gH +gH +gH +gH +gH +gH +gH +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(231,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +iq +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(232,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(233,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +iq +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(234,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +jN +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(235,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +lS +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(236,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +lS +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(237,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gG +gD +gD +gD +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +lS +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(238,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lT +mK +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(239,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(240,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +gD +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +mI +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(241,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +mI +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(242,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(243,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(244,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lS +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(245,1,1) = {" +ab +ab +ab +ab +aj +aj +aj +aj +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kR +im +im +kR +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(246,1,1) = {" +ab +ab +ab +aj +aj +fh +fj +fj +aj +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kZ +jN +im +kZ +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(247,1,1) = {" +ab +ab +ab +aj +eB +fj +fl +fj +fn +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kR +jN +im +kR +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(248,1,1) = {" +ab +ab +ab +aj +eP +fj +fl +fj +fo +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +kZ +im +lS +kZ +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(249,1,1) = {" +ab +ab +ab +aj +fg +fj +fl +fj +fn +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lU +lU +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(250,1,1) = {" +ab +ab +ab +aj +aj +fk +fj +fj +aj +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +lV +lV +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(251,1,1) = {" +ab +ab +ab +ab +aj +aj +aj +aj +aj +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +mb +mb +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(252,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(253,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +im +im +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(254,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +mx +mL +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(255,1,1) = {" +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ii +ii +ii +ii +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +gx +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} diff --git a/_maps/RandomZLevels/away_mission/TheBeach.dmm b/_maps/RandomZLevels/away_mission/TheBeach.dmm index 5430d8dd92..6877eb4b35 100644 --- a/_maps/RandomZLevels/away_mission/TheBeach.dmm +++ b/_maps/RandomZLevels/away_mission/TheBeach.dmm @@ -224,63 +224,13 @@ /mob/living/simple_animal/crab, /turf/open/floor/plating/beach/sand, /area/awaymission/beach) -"aL" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 9 - }, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) -"aM" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 1 - }, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) -"aN" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 5 - }, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) "aO" = ( /obj/effect/baseturf_helper/beach/sand, /turf/open/floor/plating/beach/sand, /area/awaymission/beach) -"aP" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 8 - }, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) "aQ" = ( -/obj/machinery/gateway/centeraway, /obj/effect/turf_decal/sand, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) -"aR" = ( -/obj/machinery/gateway{ - dir = 4 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 4 - }, +/obj/machinery/gateway/away, /turf/open/floor/plating/beach/sand, /area/awaymission/beach) "aS" = ( @@ -295,32 +245,6 @@ dir = 8 }, /area/awaymission/beach) -"aU" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 10 - }, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) -"aV" = ( -/obj/machinery/gateway, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) -"aW" = ( -/obj/machinery/gateway{ - dir = 6 - }, -/obj/effect/turf_decal/sand, -/obj/effect/turf_decal/stripes/asteroid/line{ - dir = 6 - }, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) "aX" = ( /turf/closed/wall/mineral/sandstone, /area/awaymission/beach) @@ -666,7 +590,7 @@ pixel_x = 24; specialfunctions = 4 }, -/obj/item/bedsheet/red, +/obj/effect/spawner/lootdrop/bedsheet, /turf/open/floor/wood, /area/awaymission/beach) "bU" = ( @@ -799,9 +723,7 @@ /turf/open/floor/wood, /area/awaymission/beach) "cn" = ( -/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." - }, +/obj/machinery/vending/boozeomat, /turf/open/floor/wood, /area/awaymission/beach) "co" = ( @@ -897,9 +819,7 @@ /area/awaymission/beach) "cD" = ( /obj/structure/table/wood, -/obj/item/reagent_containers/rag{ - pixel_y = 7 - }, +/obj/item/reagent_containers/rag, /turf/open/floor/wood, /area/awaymission/beach) "cE" = ( @@ -1081,14 +1001,6 @@ /obj/item/clothing/glasses/heat, /turf/open/floor/plating/beach/sand, /area/awaymission/beach) -"iy" = ( -/obj/item/toy/seashell, -/turf/open/floor/plating/beach/coastline_t, -/area/awaymission/beach) -"MD" = ( -/obj/item/toy/seashell, -/turf/open/floor/plating/beach/sand, -/area/awaymission/beach) (1,1,1) = {" aa @@ -4660,9 +4572,9 @@ ac aw af ay -MD ak -MD +ak +ak aT ao aY @@ -4766,7 +4678,7 @@ ac aw af ay -MD +ak ak ak ak @@ -4875,7 +4787,7 @@ ay ak ak ak -MD +ak ak ak ak @@ -5216,7 +5128,7 @@ aY ae aw ag -MD +ak aZ ak ak @@ -5317,7 +5229,7 @@ ak ak ak ak -MD +ak aT aj aj @@ -5328,7 +5240,7 @@ ak ak ak ak -MD +ak aT ao ar @@ -6294,7 +6206,7 @@ ak ak ak ak -iy +ap ar ac ac @@ -6474,7 +6386,7 @@ ac ac ad ag -MD +ak ak ak ak @@ -6822,7 +6734,7 @@ cl bd bd bd -cD +cC cH ba ak @@ -6908,9 +6820,9 @@ ak ak ak ak -aL -aP -aU +bf +bp +bx ak ak ba @@ -6929,7 +6841,7 @@ cm bd bd bd -cC +cD cH ba ak @@ -7015,9 +6927,9 @@ ak ak ak ak -aM +bg aQ -aV +by ba ba ba @@ -7122,9 +7034,9 @@ ak ak ak ak -aN -aR -aW +bh +br +bz ak ak ak @@ -8956,7 +8868,7 @@ ak ak ak ak -MD +ak ak ak cu @@ -10328,7 +10240,7 @@ ac ac aw ag -MD +ak ak ak ak @@ -10436,7 +10348,7 @@ ad af ay ak -MD +ak ak ak ak @@ -10574,7 +10486,7 @@ ak ak cO ak -iy +ap ar ac ac @@ -10787,7 +10699,7 @@ ak ak ak aK -MD +ak ap ar ac @@ -10970,7 +10882,7 @@ ac ac ax ag -MD +ak ak ak ak @@ -11000,7 +10912,7 @@ ak ak ak ak -MD +ak bo aq ar @@ -15007,7 +14919,7 @@ ad ag al ak -MD +ak ap ar ab diff --git a/_maps/RandomZLevels/away_mission/caves.dmm b/_maps/RandomZLevels/away_mission/caves.dmm index c84acf0131..33aca48f29 100644 --- a/_maps/RandomZLevels/away_mission/caves.dmm +++ b/_maps/RandomZLevels/away_mission/caves.dmm @@ -12,7 +12,6 @@ /turf/open/lava/smooth{ desc = "Looks hot."; luminosity = 5; - name = "lava"; initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) @@ -37,7 +36,6 @@ /turf/open/lava/smooth{ desc = "Looks hot."; luminosity = 5; - name = "lava"; initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_three) @@ -73,11 +71,6 @@ initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) -"ao" = ( -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) "ap" = ( /obj/structure/destructible/cult/pylon, /turf/open/floor/engine/cult{ @@ -116,7 +109,7 @@ }, /obj/item/veilrender/honkrender, /obj/item/clothing/mask/gas/clown_hat, -/obj/item/organ/heart/demon, +/obj/item/organ/heart/cursed, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -188,9 +181,7 @@ amount = 25 }, /obj/item/coin/antagtoken, -/obj/item/book/granter/spell/summonitem{ - name = "an extremely flamboyant book" - }, +/obj/item/book/granter/spell/smoke, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -239,7 +230,6 @@ /area/awaymission/caves/BMP_asteroid/level_three) "aM" = ( /obj/structure/ladder/unbreakable{ - anchored = 1; height = 1; id = "minedeep" }, @@ -266,7 +256,6 @@ /area/awaymission/caves/BMP_asteroid/level_three) "aP" = ( /obj/structure/ladder/unbreakable{ - anchored = 1; height = 1; id = "dungeon"; name = "rusty ladder" @@ -317,7 +306,6 @@ /turf/open/lava/smooth{ desc = "Looks hot."; luminosity = 5; - name = "lava"; initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) @@ -356,7 +344,11 @@ /area/awaymission/caves/BMP_asteroid/level_four) "ba" = ( /obj/structure/destructible/cult/talisman, -/obj/item/book/granter/martial/plasma_fist, +/obj/item/storage/belt/champion, +/obj/item/melee/sabre{ + icon_state = "cultblade"; + name = "blood-red sabre" + }, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -397,79 +389,19 @@ initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_three) -"bi" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) -"bj" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) -"bk" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) -"bl" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) "bm" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) -"bn" = ( -/obj/machinery/gateway{ - dir = 4 - }, +/obj/machinery/gateway/away, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) "bo" = ( -/obj/structure/flora/rock, -/obj/item/soulstone/anybody, -/turf/open/floor/plating/asteroid/basalt{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_three) -"bp" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/turf/open/floor/engine/cult{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_four) -"bq" = ( -/obj/machinery/gateway, -/turf/open/floor/engine/cult{ +/obj/structure/trap/chill, +/turf/open/floor/plating/asteroid/basalt/lava{ initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) "br" = ( -/obj/machinery/gateway{ - dir = 6 - }, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -516,8 +448,8 @@ }, /area/awaymission/caves/BMP_asteroid/level_three) "by" = ( -/obj/item/twohanded/mjollnir, /mob/living/simple_animal/hostile/poison/giant_spider/nurse, +/obj/item/nullrod/hammmer, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -531,8 +463,8 @@ /area/awaymission/caves/BMP_asteroid/level_four) "bA" = ( /obj/structure/destructible/cult/tome, -/obj/item/necromantic_stone, /obj/effect/decal/cleanable/blood, +/obj/item/immortality_talisman, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -563,7 +495,6 @@ /area/awaymission/caves/BMP_asteroid/level_four) "bF" = ( /obj/structure/ladder/unbreakable{ - anchored = 1; height = 2; id = "dungeon"; name = "rusty ladder" @@ -573,7 +504,9 @@ }, /area/awaymission/caves/BMP_asteroid/level_three) "bG" = ( -/obj/item/gun/ballistic/automatic/pistol/deagle/gold, +/obj/item/gun/ballistic/revolver/reverse{ + name = "suspicious .357 revovler" + }, /turf/open/floor/plating/asteroid/basalt/lava{ initial_gas_mix = "n2=23;o2=14" }, @@ -581,12 +514,14 @@ "bH" = ( /obj/effect/decal/remains/human, /obj/item/clothing/under/misc/patriotsuit, +/obj/structure/trap/chill, /turf/open/floor/plating/asteroid/basalt/lava{ initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) "bI" = ( /obj/item/bedsheet/patriot, +/obj/structure/trap/chill, /turf/open/floor/plating/asteroid/basalt/lava{ initial_gas_mix = "n2=23;o2=14" }, @@ -606,7 +541,6 @@ /turf/open/lava/smooth{ desc = "Looks hot."; luminosity = 5; - name = "lava"; initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid) @@ -617,7 +551,6 @@ /turf/open/lava/smooth{ desc = "Looks hot."; luminosity = 5; - name = "lava"; initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_two) @@ -734,7 +667,6 @@ /area/awaymission/caves/BMP_asteroid/level_two) "ce" = ( /obj/structure/ladder/unbreakable{ - anchored = 1; height = 1; id = "mineintro" }, @@ -1030,7 +962,7 @@ /area/awaymission/caves/research) "cX" = ( /obj/structure/table, -/obj/item/melee/baton, +/obj/item/gun/energy/temperature, /turf/open/floor/plasteel{ initial_gas_mix = "n2=23;o2=14" }, @@ -1093,9 +1025,6 @@ /obj/structure/closet/secure_closet/miner{ name = "weapon equipment" }, -/obj/item/grenade/syndieminibomb/concussion, -/obj/item/grenade/syndieminibomb/concussion, -/obj/item/grenade/syndieminibomb/concussion, /turf/open/floor/plasteel{ initial_gas_mix = "n2=23;o2=14" }, @@ -1122,7 +1051,6 @@ /area/awaymission/caves/BMP_asteroid/level_two) "dj" = ( /obj/structure/ladder/unbreakable{ - anchored = 1; height = 2; id = "minedeep" }, @@ -1195,7 +1123,6 @@ "dw" = ( /obj/structure/bed, /obj/item/bedsheet, -/obj/effect/landmark/awaystart, /turf/open/floor/plasteel, /area/awaymission/caves/BMP_asteroid/level_two) "dx" = ( @@ -1376,35 +1303,29 @@ "eg" = ( /obj/effect/decal/cleanable/robot_debris/old, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eh" = ( /obj/structure/table, /obj/item/radio, /obj/item/radio, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "ei" = ( /obj/structure/table, /obj/item/paper_bin, /obj/item/pen, /turf/open/floor/plating, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "ej" = ( /turf/open/floor/plating, /area/awaymission/caves/BMP_asteroid) "ek" = ( /obj/structure/window{ - icon_state = "window"; dir = 8 }, /mob/living/simple_animal/hostile/mining_drone, /turf/open/floor/plating, -/area/awaymission/caves/BMP_asteroid) -"el" = ( -/obj/structure/closet/secure_closet/personal, -/obj/item/gun/energy/laser/captain/scattershot, -/turf/open/floor/wood, -/area/awaymission/caves/northblock) +/area/awaymission/caves/listeningpost) "em" = ( /obj/structure/closet/secure_closet/personal, /turf/open/floor/wood{ @@ -1433,20 +1354,19 @@ dir = 8 }, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "er" = ( /obj/structure/chair/stool, /turf/open/floor/plating, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "es" = ( /obj/structure/window{ - icon_state = "window"; dir = 8 }, /obj/structure/window, /mob/living/simple_animal/hostile/mining_drone, /turf/open/floor/plating, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "et" = ( /obj/effect/decal/cleanable/shreds, /turf/open/floor/plating{ @@ -1467,37 +1387,41 @@ /obj/item/mining_scanner, /obj/item/mining_scanner, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "ex" = ( -/obj/structure/closet/secure_closet/miner, /obj/effect/decal/cleanable/cobweb, -/obj/item/survivalcapsule, -/obj/item/extinguisher/mini, -/turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) -"ey" = ( -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) -"ez" = ( -/obj/machinery/light/small/built{ - dir = 1 +/obj/structure/cable{ + icon_state = "0-4" }, +/obj/machinery/power/port_gen/pacman, +/obj/item/wrench, +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) +"ey" = ( /obj/machinery/suit_storage_unit/mining{ desc = "An industrial unit made to hold space suits. Age has seemed to rust the sliding door mechanisms, making it difficult to open."; name = "rusted suit storage unit" }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) +"ez" = ( +/obj/structure/cable{ + icon_state = "1-8" + }, +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) "eA" = ( /obj/structure/table, /obj/item/paper/fluff/awaymissions/caves/work_notice, +/obj/machinery/light/small/built{ + dir = 1 + }, +/obj/item/stack/sheet/mineral/plasma, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) -"eB" = ( -/obj/structure/barricade/wooden, -/turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eC" = ( /obj/structure/table, /obj/item/gps/mining, @@ -1506,17 +1430,13 @@ /obj/item/clothing/glasses/meson, /obj/item/clothing/glasses/meson, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eD" = ( /obj/structure/closet/secure_closet/miner, /obj/item/survivalcapsule, /obj/item/extinguisher/mini, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) -"eE" = ( -/obj/effect/landmark/awaystart, -/turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eF" = ( /turf/closed/wall, /area/awaymission/caves/listeningpost) @@ -1526,7 +1446,7 @@ "eH" = ( /obj/machinery/vending/sustenance, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eI" = ( /obj/structure/closet/crate/trashcart, /obj/item/switchblade, @@ -1546,7 +1466,7 @@ "eL" = ( /obj/machinery/vending/sovietsoda, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eM" = ( /obj/machinery/light/small{ dir = 8 @@ -1593,7 +1513,7 @@ "eR" = ( /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eS" = ( /obj/machinery/light/small/built, /obj/machinery/suit_storage_unit/mining{ @@ -1601,11 +1521,11 @@ name = "rusted suit storage unit" }, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eT" = ( /obj/structure/closet/emcloset, /turf/open/floor/plasteel, -/area/awaymission/caves/BMP_asteroid) +/area/awaymission/caves/listeningpost) "eU" = ( /obj/structure/table, /obj/item/storage/toolbox/mechanical, @@ -1651,16 +1571,11 @@ /area/awaymission/caves/BMP_asteroid/level_two) "fc" = ( /obj/structure/closet/crate, -/obj/item/paper/fluff/awaymissions/caves/shipment_receipt, -/obj/item/gun/energy/laser/captain/scattershot, -/obj/item/gun/energy/laser/captain/scattershot, /obj/item/gun/energy/laser, -/obj/item/grenade/syndieminibomb/concussion, -/obj/item/grenade/syndieminibomb/concussion, -/obj/item/grenade/syndieminibomb/concussion, -/obj/item/slimepotion/fireproof, -/obj/item/slimepotion/fireproof, -/obj/item/clothing/glasses/thermal, +/obj/item/gun/energy/laser, +/obj/item/survivalcapsule, +/obj/item/kitchen/knife/combat/survival, +/obj/item/kitchen/knife/combat/survival, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -1707,12 +1622,6 @@ initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_two) -"fk" = ( -/obj/item/grenade/syndieminibomb/concussion, -/turf/open/floor/plating/asteroid/basalt{ - initial_gas_mix = "n2=23;o2=14" - }, -/area/awaymission/caves/BMP_asteroid/level_two) "fl" = ( /obj/effect/decal/remains/human, /turf/open/floor/plating/asteroid/basalt{ @@ -1726,10 +1635,11 @@ /obj/structure/closet/crate{ icon_state = "crateopen" }, -/obj/item/paper/fluff/awaymissions/caves/shipment_receipt, -/obj/item/organ/eyes/robotic/thermals, -/obj/item/gun/energy/laser/captain/scattershot, -/obj/item/slimepotion/fireproof, +/obj/item/gun/energy/laser, +/obj/item/gun/energy/laser, +/obj/item/survivalcapsule, +/obj/item/kitchen/knife/combat/survival, +/obj/item/kitchen/knife/combat/survival, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -1791,11 +1701,12 @@ }, /area/awaymission/caves/BMP_asteroid/level_two) "fw" = ( -/obj/item/gun/energy/laser/captain/scattershot, -/turf/open/floor/plating/asteroid/basalt{ - initial_gas_mix = "n2=23;o2=14" +/obj/structure/cable{ + icon_state = "0-2" }, -/area/awaymission/caves/BMP_asteroid/level_two) +/obj/machinery/gateway/away, +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) "fx" = ( /obj/effect/bump_teleporter{ id = "mineintroup"; @@ -1968,7 +1879,6 @@ /area/awaymission/caves/BMP_asteroid) "ga" = ( /obj/structure/ladder/unbreakable{ - anchored = 1; height = 2; id = "mineintro" }, @@ -2035,11 +1945,11 @@ /turf/open/floor/plasteel, /area/awaymission/caves/BMP_asteroid) "gk" = ( -/obj/effect/landmark/awaystart, -/turf/open/floor/plating/asteroid/basalt{ - initial_gas_mix = "n2=23;o2=14" +/obj/machinery/light{ + dir = 4 }, -/area/awaymission/caves/BMP_asteroid/level_two) +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) "gl" = ( /obj/item/trash/plate, /turf/open/floor/plasteel, @@ -2260,7 +2170,6 @@ /turf/open/lava/smooth{ desc = "Looks hot."; luminosity = 5; - name = "lava"; initial_gas_mix = "n2=23;o2=14" }, /area/awaymission/caves/BMP_asteroid/level_four) @@ -2276,6 +2185,28 @@ /obj/effect/baseturf_helper/asteroid/basalt, /turf/closed/wall, /area/awaymission/caves/northblock) +"CY" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) +"GV" = ( +/obj/structure/barricade/wooden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) +"Hp" = ( +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/awaymission/caves/listeningpost) (1,1,1) = {" aa @@ -6581,7 +6512,7 @@ dO dP dI dZ -el +dA dt bL bL @@ -10180,13 +10111,13 @@ bL bL bL bL -dX -dX -dW -dW -dW -dW -dW +eG +eG +eF +eF +eF +eF +eF bL bL bL @@ -10432,18 +10363,18 @@ bL bL bM bL -bL -bL -bL -bL -bL -dX +eG +eG +eF +eF +eG +eG ex eD eD eD eD -dX +eG bL bL bL @@ -10689,18 +10620,18 @@ bL bL bM bM -bL -bL -bL -bL -bL -dW +eF +eJ +eq +eJ +eJ +eF ey -ev -ev -ev +eJ +eJ +eJ eR -dX +eG bL bL bL @@ -10946,18 +10877,18 @@ bL bL bL bM -bL -bL -bL -bL -bL -dX +eG +eJ +fw +Hp +CY +GV ez -eE -ev -ev +eO +eJ +eJ eS -dX +eG bL bL bL @@ -11203,18 +11134,18 @@ bL bL bL bM -bL -bL -bL -bL -bL -dX +eG +eJ +gk +eJ +eJ +eG eA -ev -ev -ev +eJ +eJ +eJ eT -dW +eF bL bV bV @@ -11460,17 +11391,17 @@ bL bL bL bM -bL -bL -bL -bL -bL -dX -ev -ev -ev -ev -ev +eF +eF +eG +eG +eG +eG +eJ +eJ +eJ +eJ +eJ eF eG eG @@ -11719,15 +11650,15 @@ bL bV bV bL -dW -dX -dX -dX -eB -dW +eF +eG +eG +eG +eW +eF eH eL -ev +eJ eW eN eJ @@ -11976,11 +11907,11 @@ bL bV bV bL -dW +eF eg eq -ev -ev +eJ +eJ eF eF eF @@ -12233,11 +12164,11 @@ bL bV bV bL -dX +eG eh -ej +fm eg -ev +eJ eF eI eM @@ -12490,11 +12421,11 @@ bL bV bV bL -dX +eG ei er -ej -ev +fm +eJ eG eJ eN @@ -12624,7 +12555,7 @@ ae ac ac ac -bo +aj bv ac ag @@ -12747,11 +12678,11 @@ bL bV bV bL -dX -ej -ej -ev -ev +eG +fm +fm +eJ +eJ eG eJ eO @@ -13004,7 +12935,7 @@ bL bV bV bL -dW +eF ek es ew @@ -13261,11 +13192,11 @@ bL bV bV bV -dW -dW -dX -dX -dW +eF +eF +eG +eG +eF eF eK eP @@ -50925,7 +50856,7 @@ ad ai ai ai -ai +bo ai ai ad @@ -51181,7 +51112,7 @@ ad ad ad ai -ai +bo bG bI ai @@ -53487,11 +53418,11 @@ ai ai ai ai -ao +br ai ai -ao -ao +br +br ai ai ai @@ -53740,19 +53671,19 @@ ad ad ad ai -ao -ao +br +br ai ai am ai ai -ao -ao -ao +br +br +br aw -ao -ao +br +br ai ai ad @@ -53995,7 +53926,7 @@ ad ad ai ai -ao +br ai ai ai @@ -54008,8 +53939,8 @@ ai ai ai ai -ao -ao +br +br ai ai ad @@ -54147,7 +54078,7 @@ bJ bJ bJ cQ -gk +bJ bJ gs bJ @@ -54249,9 +54180,9 @@ ad ad ad ai -ao -ao -ao +br +br +br ai ax ad @@ -54266,7 +54197,7 @@ ai ad ad ai -ao +br ai ai ad @@ -54505,7 +54436,7 @@ ad ad ai ai -ao +br am ai ad @@ -54762,7 +54693,7 @@ ai ai ai ai -ao +br ai ai ad @@ -54777,9 +54708,9 @@ ad ad ad ax -ao +br ai -ao +br ai ai ai @@ -54976,10 +54907,10 @@ ad ad al am -ao -ao +br +br ap -ao +br am ai al @@ -55015,7 +54946,7 @@ aV aV ax aA -ao +br ax ax ai @@ -55033,7 +54964,7 @@ ad ad ad ad -ao +br ai ai ai @@ -55233,11 +55164,11 @@ ad ad al am -ao +br ar as ar -ao +br am al ad @@ -55250,29 +55181,29 @@ ad ad ad ad -ao +br ad ad ad -ao -ao -ao -ao -ao -ao -ao -ao -ao -ao -ao -ao -ao +br +br +br +br +br +br +br +br +br +br +br +br +br ad ad ad -ao -ao -ao +br +br +br aB ax ai @@ -55290,7 +55221,7 @@ ad ad ad ax -ao +br ai ai ai @@ -55505,32 +55436,32 @@ ad ad ad ad -ao +br ad -ao +br ad ad ad ad ad -ao -ao -ao +br +br +br ap ad ad ad -ao -ao +br +br ap -ao +br ad ad -ao -ao -ao +br +br +br ap -ao +br ax ai ai @@ -55546,8 +55477,8 @@ ad ad ad ad -ao -ao +br +br ai ai ai @@ -55747,11 +55678,11 @@ ad ad al am -ao +br ar as ar -ao +br am al ad @@ -55762,31 +55693,31 @@ ad ad ad ad -ao +br ad ad -ao +br ad ad ad ad -ao -ao +br +br ad ad -ao -ao +br +br ad ad -ao -ao -ao +br +br +br ad ad -ao -ao -ao -ao +br +br +br +br aR ax ai @@ -55803,7 +55734,7 @@ ad ad ad ad -ao +br ai am at @@ -56004,10 +55935,10 @@ ad ad al am -ao -ao +br +br ap -ao +br am ai al @@ -56019,8 +55950,8 @@ ad ad ad ad -ao -ao +br +br ad ad ad @@ -56043,8 +55974,8 @@ aV aV ax aR -ao -ao +br +br ax ai ai @@ -56060,7 +55991,7 @@ ad ad ad ax -ao +br ai ai ai @@ -56262,8 +56193,8 @@ ad ai al am -ao -ao +br +br am ai al @@ -56276,9 +56207,9 @@ ad ad ad ad -ao -ao -ao +br +br +br ad ad ad @@ -56299,9 +56230,9 @@ ai ad ad ax -ao -ao -ao +br +br +br ax ai ai @@ -56317,8 +56248,8 @@ ad ad ad ax -ao -ao +br +br ai ai ai @@ -56520,7 +56451,7 @@ ad ai al al -ao +br al al ai @@ -56533,9 +56464,9 @@ ax ax ax ax -ao -ao -ao +br +br +br ad ad ai @@ -56556,9 +56487,9 @@ ax ad ai ax -ao -ao -ao +br +br +br ax ai ai @@ -56575,12 +56506,12 @@ ad ad ad ax -ao +br am ai ai ad -ao +br ai ai ai @@ -56777,7 +56708,7 @@ ad ai aq ai -ao +br ai ai ad @@ -56787,12 +56718,12 @@ ad ad ax ay -ao +br aD ax -ao -ao -ao +br +br +br ad ad ai @@ -56806,16 +56737,16 @@ aR ax ai ax -ao -ao -ao +br +br +br ax ad ai ax -ao +br av -ao +br ax ai ai @@ -56833,15 +56764,15 @@ ad ad ad aR -ao -ao -ao -ao +br +br +br +br ai -ao -ao -ao -ao +br +br +br +br ai ad ad @@ -57044,12 +56975,12 @@ ad ad ax az -ao -ao +br +br ax -ao -ao -ao +br +br +br ai ai ai @@ -57057,22 +56988,22 @@ ai ai ai ax -ao -ao -ao +br +br +br ax ai ax -ao -ao -ao +br +br +br ad ad ai ax -ao -ao -ao +br +br +br ax ai ai @@ -57092,14 +57023,14 @@ ad ad ax ax -ao +br ax ad ad ai ai ai -ao +br ai ad ad @@ -57300,13 +57231,13 @@ ad ad ad ax -ao -ao +br +br av aF -ao -ao -ao +br +br +br ai ai ai @@ -57314,22 +57245,22 @@ aq ai ai ax -ao -ao -ao +br +br +br ax ai ax -ao -ao +br +br aR ax ai ai ax -ao -ao -ao +br +br +br ax ai ai @@ -57340,10 +57271,10 @@ ad ai ai ax -ao -ao -ao -ao +br +br +br +br aR aR ad @@ -57357,8 +57288,8 @@ ad ad ai ai -ao -ao +br +br ad ad ad @@ -57548,7 +57479,7 @@ ad an ai ai -ao +br ai ai ai @@ -57557,13 +57488,13 @@ ad ad ad ax -ao +br av -ao +br ax -ao -ao -ao +br +br +br ai ai ai @@ -57571,22 +57502,22 @@ ai ai ai ax -ao -ao +br +br aG ax ai ax -ao -ao -ao +br +br +br ax ai ai ax -ao +br aG -ao +br ax ai ai @@ -57596,13 +57527,13 @@ ad ad ai aR -ao -ao +br +br bf -ao -ao -ao -ao +br +br +br +br aR ad ad @@ -57615,7 +57546,7 @@ ad ad ad ax -ao +br ad ad ad @@ -57805,8 +57736,8 @@ ad ai ai ai -ao -ao +br +br ai ai ai @@ -57818,9 +57749,9 @@ aA ax ax ax -ao -ao -ao +br +br +br ai ai ai @@ -57828,21 +57759,21 @@ ax ax ax ax -ao +br ax -ao +br ax ax ax -ao +br ap -ao +br ax ax ax ax -ao -ao +br +br aR ax ax @@ -57852,15 +57783,15 @@ ad ax ax aR -ao -ao +br +br bf ap bf -ao -ao -ao -ao +br +br +br +br ax ai ad @@ -57871,7 +57802,7 @@ ad ad ad aR -ao +br ai ad ad @@ -58062,62 +57993,62 @@ ad ad ai ai -ao -ao -ao +br +br +br ai ai ai ai ai -ao -ao -ao -ao -ao -ao -ao -ao +br +br +br +br +br +br +br +br ai ai ai ax -ao -ao +br +br ax -ao -ao +br +br av ad ad ad ad -ao -ao -ao -ao -ao +br +br +br +br +br ad ad -ao -ao -ao +br +br +br al ad ad al -ao -ao -ao -ao +br +br +br +br bf -bi -bl -bp +br +br +br aw -ao +br bz -ao +br aR am ai @@ -58128,7 +58059,7 @@ ad ad ad ax -ao +br ai ai ad @@ -58321,20 +58252,20 @@ ai ai ai ai -ao -ao +br +br ai -ao -ao -ao -ao +br +br +br +br aB av -ao -ao -ao +br +br +br ap -ao +br ai ai ai @@ -58342,35 +58273,35 @@ ax aP aw aF -ao +br ap -ao +br ad ad -ao -ao -ao -ao -ao -ao -ao -ao -ao +br +br +br +br +br +br +br +br +br ap -ao +br al ad ad ad ad al -ao -ao +br +br bf ap -bj +br bm -bq +br bf bw bA @@ -58384,8 +58315,8 @@ ad ad ad ax -ao -ao +br +br am ai ai @@ -58579,59 +58510,59 @@ ad ai ai ai -ao -ao -ao +br +br +br ai ai -ao -ao -ao -ao -ao -ao +br +br +br +br +br +br aG -ao +br ai ai ai ax -ao -ao +br +br ax -ao -ao -ao -ao -ao -ao -ao +br +br +br +br +br +br +br av ad ad ad -ao -ao -ao -ao -ao -ao -al -ad -ad -al -ao -ao -ao -ao -bf -bk -bn br -ao -ao +br +br +br +br +br +al +ad +ad +al +br +br +br +br +bf +br +br +br +br +br bz -ao +br aR ai ai @@ -58641,8 +58572,8 @@ ad ad ad ax -ao -ao +br +br ai ai ai @@ -58837,7 +58768,7 @@ ai ai ai ai -ao +br ai ai ai @@ -58846,9 +58777,9 @@ ax ax ax ax -ao -ao -ao +br +br +br ai ai ai @@ -58856,22 +58787,22 @@ ax ax ax ax -ao +br ax -ao +br ax ax ax -ao +br ap -ao +br ax ax ax ax aR -ao -ao +br +br ax ax ad @@ -58881,14 +58812,14 @@ ax ax aR aR -ao +br bf ap bf -ao -ao -ao -ao +br +br +br +br ax ai ai @@ -59099,13 +59030,13 @@ ai ai ad ax -ao -ao -ao +br +br +br ax -ao -ao -ao +br +br +br ad ai ai @@ -59114,21 +59045,21 @@ ai ai ax aR -ao -ao +br +br ax ai ax -ao -ao -ao +br +br +br ax ai ai ax -ao -ao -ao +br +br +br ax ai ad @@ -59139,12 +59070,12 @@ ai ad ad aR -ao +br bf -ao -ao -ao -ao +br +br +br +br aR ai ai @@ -59154,7 +59085,7 @@ ad ad ad ax -ao +br am ai bs @@ -59356,13 +59287,13 @@ ad ad ad ax -ao -ao -ao +br +br +br aF -ao -ao -ao +br +br +br ad ai ai @@ -59370,22 +59301,22 @@ ai ai ai ax -ao -ao -ao +br +br +br ax ai ax -ao -ao +br +br aR ax ai ai ax -ao -ao -ao +br +br +br ax ai ad @@ -59396,11 +59327,11 @@ ai ad ad aR -ao -ao -ao -ao -ao +br +br +br +br +br aR ai ai @@ -59411,7 +59342,7 @@ ad ad ad aR -ao +br ai ai ai @@ -59613,13 +59544,13 @@ ad ad ad ax -ao -ao -ao +br +br +br ax -ao -ao -ao +br +br +br ai ai ai @@ -59627,22 +59558,22 @@ ai ai ai ax -ao -ao -ao +br +br +br ax ai ax -ao -ao -ao +br +br +br ax ad ad ax -ao -ao -ao +br +br +br ax ai ai @@ -59654,9 +59585,9 @@ ad ad ai ax -ao -ao -ao +br +br +br ax ai ai @@ -59668,7 +59599,7 @@ ad ad ad ax -ao +br ai ai ai @@ -59871,12 +59802,12 @@ ad ad ax aC -ao +br aE ax -ao -ao -ao +br +br +br ai ai ai @@ -59886,20 +59817,20 @@ ai ax aR aR -ao +br ax ai ax -ao -ao -ao +br +br +br ax ad ad ax -ao -ao -ao +br +br +br ax ai ai @@ -59924,8 +59855,8 @@ ad ad ad ad -ao -ao +br +br ai ai ai @@ -60131,9 +60062,9 @@ ax ax ax ax -ao -ao -ao +br +br +br ai ai ai @@ -60147,7 +60078,7 @@ ai ai ai ax -ao +br aR aR ax @@ -60155,7 +60086,7 @@ ad ai ax aw -ao +br aR ax ai @@ -60181,8 +60112,8 @@ ad ad ax ax -ao -ao +br +br am ai ad @@ -60388,9 +60319,9 @@ ad ad ad ad -ao -ao -ao +br +br +br ad ai ai @@ -60411,9 +60342,9 @@ ai ad ai ax -ao +br aw -ao +br ax ai ai @@ -60425,7 +60356,7 @@ ad ad ad al -ao +br al ad ad @@ -60437,8 +60368,8 @@ ad ax al ai -ao -ao +br +br ai ai ai @@ -60646,8 +60577,8 @@ ad ad ad ad -ao -ao +br +br ad ai ai @@ -60656,7 +60587,7 @@ ai ai ax aS -ao +br aS ax ax @@ -60668,9 +60599,9 @@ ax ad ad ax -ao +br av -ao +br ax ai ai @@ -60681,7 +60612,7 @@ ad ad ad ai -ao +br ai ax ad @@ -60691,8 +60622,8 @@ ad ad ad ad -ao -ao +br +br ai ai ai @@ -60903,31 +60834,31 @@ ad ad ad ad -ao -ao -ao -ao +br +br +br +br ad ad -ao -ao -ao -ao -ao -ao -ao -ao -ao -ao +br +br +br +br +br +br +br +br +br +br aG -ao -ao +br +br ad ad ad -ao -ao -ao +br +br +br ax ai ai @@ -60938,7 +60869,7 @@ ad ad ad ai -ao +br ai ad ad @@ -60948,8 +60879,8 @@ ad ad ad ad -ao -ao +br +br ai ai ai @@ -61161,30 +61092,30 @@ ad ad ad ad -ao -ao -ao +br +br +br ad ad -ao -ao -ao -ao +br +br +br +br ap av -ao +br ad ad ad ap ad -ao -ao +br +br ad ad -ao +br ap -ao +br ax ai ai @@ -61205,7 +61136,7 @@ ai ad ax ai -ao +br ai ai ad @@ -61423,24 +61354,24 @@ ad ad ad ad -ao -ao -ao -ao -ao +br +br +br +br +br ad ad ad ad -ao -ao +br +br ad ad -ao -ao -ao -ao -ao +br +br +br +br +br aB ax ai @@ -61454,13 +61385,13 @@ ad ai ai ai -ao +br ai ai ai ai -ao -ao +br +br ai ai ai @@ -61711,10 +61642,10 @@ ad ad ad ai -ao -ao -ao -ao +br +br +br +br ai ai ai @@ -64011,7 +63942,7 @@ ad ai ai aY -ao +br aZ ai ad @@ -64267,9 +64198,9 @@ ad ad ad an -ao +br ba -ao +br an ad ad @@ -64525,7 +64456,7 @@ ad ad ai aZ -ao +br aY ad ad @@ -64676,7 +64607,7 @@ bJ bK bK bK -fw +bJ bJ bJ cq @@ -64931,7 +64862,7 @@ bJ bJ bJ fe -fk +bJ fn fd bJ diff --git a/_maps/RandomZLevels/away_mission/challenge.dmm b/_maps/RandomZLevels/away_mission/challenge.dmm index bf164cb4fa..7342f7ffe6 100644 --- a/_maps/RandomZLevels/away_mission/challenge.dmm +++ b/_maps/RandomZLevels/away_mission/challenge.dmm @@ -7,125 +7,81 @@ icon_state = "iron0" }, /area/awaymission/challenge/start) -"ac" = ( -/obj/structure/girder, -/turf/open/floor/plating/airless, -/area/awaymission/challenge/start) -"ad" = ( -/turf/open/floor/plating, -/area/awaymission/challenge/start) -"ae" = ( -/turf/open/floor/plasteel/airless{ - icon_state = "damaged5" - }, -/area/awaymission/challenge/start) -"af" = ( -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" - }, -/area/awaymission/challenge/start) "ag" = ( /obj/item/clothing/suit/space/syndicate/blue, /obj/item/clothing/head/helmet/space/syndicate/blue, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" - }, -/area/awaymission/challenge/start) -"ah" = ( -/turf/open/floor/plasteel/airless, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ai" = ( /obj/item/flashlight{ icon_state = "flashlight-on"; on = 1 }, -/turf/open/floor/plasteel/airless, -/area/awaymission/challenge/start) -"aj" = ( -/obj/effect/landmark/awaystart, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged3" - }, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ak" = ( /obj/effect/decal/remains/human, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged4" - }, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "al" = ( /obj/effect/landmark/awaystart, -/turf/open/floor/plasteel/airless, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "am" = ( /obj/item/clothing/suit/space/syndicate/green, /obj/item/clothing/head/helmet/space/syndicate/green, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" - }, -/area/awaymission/challenge/start) -"an" = ( -/turf/open/floor/plasteel/airless{ - icon_state = "damaged3" - }, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ao" = ( /obj/item/clothing/suit/space/syndicate/orange, /obj/item/clothing/head/helmet/space/syndicate/orange, -/turf/open/floor/plasteel/airless, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ap" = ( /obj/item/gun/energy/laser/retro, -/turf/open/floor/plasteel/airless, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "aq" = ( /obj/item/stack/rods, -/turf/open/floor/plasteel, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ar" = ( /obj/effect/decal/cleanable/oil, -/turf/open/floor/plasteel/airless, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "as" = ( /obj/effect/decal/remains/robot, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" - }, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "at" = ( /obj/structure/girder, -/turf/open/floor/plating, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "au" = ( -/turf/closed/wall, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "av" = ( -/turf/open/floor/plasteel/airless{ - icon_state = "damaged4" - }, +/obj/item/storage/firstaid/regular, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "aw" = ( /obj/item/stack/rods, /obj/effect/decal/cleanable/blood/splatter, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" - }, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ax" = ( /obj/effect/decal/cleanable/oil, /mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/plating, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "ay" = ( /obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel/airless, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "az" = ( /obj/item/clothing/suit/space/syndicate/black, /obj/item/clothing/head/helmet/space/syndicate/black, -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" - }, +/turf/open/floor/carpet, /area/awaymission/challenge/start) "aA" = ( /turf/closed/indestructible{ @@ -133,16 +89,18 @@ }, /area/awaymission/challenge/main) "aB" = ( -/obj/structure/girder, -/turf/open/floor/plating, -/area/awaymission/challenge/main) +/obj/machinery/power/smes/magical, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/floor/plasteel/airless, +/area/awaymission/challenge/start) "aC" = ( /turf/open/floor/plating, /area/awaymission/challenge/main) "aD" = ( -/turf/open/floor/plasteel/airless{ - icon_state = "damaged3" - }, +/obj/structure/fans/tiny, +/turf/open/floor/carpet, /area/awaymission/challenge/main) "aE" = ( /turf/closed/wall, @@ -151,16 +109,23 @@ /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "aG" = ( -/turf/open/floor/plasteel/airless{ - icon_state = "damaged2" +/obj/machinery/power/terminal{ + dir = 8 }, -/area/awaymission/challenge/main) +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plasteel/airless, +/area/awaymission/challenge/start) "aH" = ( /turf/open/floor/plasteel/airless, /area/awaymission/challenge/main) "aI" = ( /obj/machinery/power/emitter/ctf{ - dir = 2 + active = 0 }, /turf/open/floor/plating/airless, /area/awaymission/challenge/main) @@ -191,7 +156,7 @@ "aO" = ( /obj/structure/window/reinforced, /obj/machinery/power/emitter/ctf{ - dir = 2 + active = 0 }, /turf/open/floor/plating/airless, /area/awaymission/challenge/main) @@ -210,6 +175,7 @@ /area/awaymission/challenge/main) "aS" = ( /obj/machinery/power/emitter/ctf{ + active = 0; dir = 4 }, /turf/open/floor/plating/airless, @@ -234,6 +200,7 @@ /area/awaymission/challenge/main) "aW" = ( /obj/machinery/power/emitter/ctf{ + active = 0; dir = 8 }, /turf/open/floor/plating/airless, @@ -294,15 +261,16 @@ /turf/open/floor/plating, /area/awaymission/challenge/main) "bf" = ( -/obj/machinery/power/emitter/ctf{ - dir = 1 - }, /obj/structure/window/reinforced{ dir = 1 }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/power/emitter/ctf{ + active = 0; + dir = 1 + }, /turf/open/floor/plating, /area/awaymission/challenge/main) "bg" = ( @@ -321,15 +289,16 @@ /turf/open/floor/plasteel, /area/awaymission/challenge/main) "bi" = ( -/obj/machinery/power/emitter/ctf{ - dir = 1 - }, /obj/structure/window/reinforced{ dir = 8 }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/power/emitter/ctf{ + active = 0; + dir = 1 + }, /turf/open/floor/plating, /area/awaymission/challenge/main) "bj" = ( @@ -337,22 +306,24 @@ /turf/open/floor/plating, /area/awaymission/challenge/main) "bk" = ( +/obj/machinery/light, /obj/machinery/power/emitter/ctf{ + active = 0; dir = 1 }, -/obj/machinery/light, /turf/open/floor/plating, /area/awaymission/challenge/main) "bl" = ( /obj/structure/window/reinforced{ dir = 4 }, -/obj/machinery/power/emitter/ctf{ - dir = 1 - }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/power/emitter/ctf{ + active = 0; + dir = 1 + }, /turf/open/floor/plating, /area/awaymission/challenge/main) "bm" = ( @@ -363,15 +334,15 @@ /turf/closed/wall/mineral/plastitanium, /area/awaymission/challenge/main) "bo" = ( -/obj/machinery/power/emitter/ctf{ - dir = 2 - }, /obj/structure/window/reinforced{ dir = 8 }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/power/emitter/ctf{ + active = 0 + }, /turf/open/floor/plating, /area/awaymission/challenge/main) "bp" = ( @@ -420,9 +391,7 @@ /area/awaymission/challenge/main) "bv" = ( /obj/structure/window/reinforced, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/awaymission/challenge/main) "bw" = ( @@ -435,15 +404,6 @@ }, /turf/open/floor/plating, /area/awaymission/challenge/main) -"bx" = ( -/obj/machinery/power/emitter/ctf{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/plating/airless, -/area/awaymission/challenge/main) "by" = ( /obj/machinery/light{ dir = 8 @@ -474,6 +434,7 @@ dir = 8 }, /obj/machinery/power/emitter/ctf{ + active = 0; dir = 8 }, /turf/open/floor/plating/airless, @@ -483,6 +444,7 @@ dir = 4 }, /obj/machinery/power/emitter/ctf{ + active = 0; dir = 4 }, /turf/open/floor/plating/airless, @@ -492,14 +454,10 @@ /turf/open/floor/plasteel/airless, /area/awaymission/challenge/main) "bF" = ( -/turf/open/floor/plasteel/white/corner{ - dir = 2 - }, +/turf/open/floor/plasteel/white/corner, /area/awaymission/challenge/main) "bG" = ( -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, +/turf/open/floor/plasteel/white/side, /area/awaymission/challenge/main) "bH" = ( /turf/open/floor/plasteel/white/corner{ @@ -531,36 +489,40 @@ /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "bL" = ( -/obj/machinery/power/emitter/ctf{ +/obj/structure/window/reinforced{ dir = 1 }, -/obj/structure/window/reinforced{ +/obj/machinery/power/emitter/ctf{ + active = 0; dir = 1 }, /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "bM" = ( /obj/machinery/power/emitter/ctf{ + active = 0; dir = 1 }, /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "bN" = ( -/obj/machinery/power/emitter/ctf{ - dir = 1 - }, /obj/structure/window/reinforced{ dir = 4 }, +/obj/machinery/power/emitter/ctf{ + active = 0; + dir = 1 + }, /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "bO" = ( -/obj/machinery/power/emitter/ctf{ - dir = 1 - }, /obj/structure/window/reinforced{ dir = 8 }, +/obj/machinery/power/emitter/ctf{ + active = 0; + dir = 1 + }, /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "bP" = ( @@ -570,9 +532,7 @@ /area/awaymission/challenge/end) "bQ" = ( /obj/item/gun/ballistic/revolver/russian, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, +/turf/open/floor/plasteel/white/side, /area/awaymission/challenge/main) "bR" = ( /obj/structure/table/reinforced, @@ -602,9 +562,7 @@ /turf/open/floor/plating/airless, /area/awaymission/challenge/main) "bU" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/white, /area/awaymission/challenge/main) "bV" = ( @@ -644,7 +602,7 @@ dir = 1 }, /obj/structure/rack, -/obj/item/clothing/suit/armor/heavy, +/obj/item/clothing/suit/armor/vest/russian, /turf/open/floor/wood, /area/awaymission/challenge/end) "cb" = ( @@ -670,7 +628,6 @@ "cf" = ( /obj/machinery/door/airlock/centcom{ name = "Airlock"; - opacity = 1; req_access_txt = "109" }, /turf/open/floor/plating, @@ -701,7 +658,7 @@ /area/awaymission/challenge/end) "ck" = ( /obj/structure/rack, -/obj/item/gun/ballistic/revolver/mateba, +/obj/item/gun/ballistic/revolver/doublebarrel/improvised, /turf/open/floor/wood, /area/awaymission/challenge/end) "cl" = ( @@ -758,7 +715,7 @@ /area/awaymission/challenge/end) "ct" = ( /obj/structure/rack, -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced, +/obj/item/gun/ballistic/revolver/detective, /turf/open/floor/wood, /area/awaymission/challenge/end) "cu" = ( @@ -773,13 +730,12 @@ /area/awaymission/challenge/end) "cw" = ( /obj/structure/rack, -/obj/item/gun/ballistic/automatic/l6_saw, +/obj/item/gun/ballistic/revolver/doublebarrel, /turf/open/floor/wood, /area/awaymission/challenge/end) "cx" = ( /obj/machinery/door/airlock/centcom{ name = "Security"; - opacity = 1; req_access_txt = "109" }, /turf/open/floor/plasteel/dark, @@ -807,7 +763,6 @@ "cB" = ( /obj/machinery/door/airlock/centcom{ name = "Administrator"; - opacity = 1; req_access_txt = "109" }, /turf/open/floor/plasteel/dark, @@ -903,150 +858,55 @@ /turf/open/floor/plating, /area/awaymission/challenge/end) "cR" = ( -/obj/machinery/gateway{ - dir = 9 +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/turf/closed/indestructible{ + icon_state = "iron0" }, -/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/awaymission/challenge/end) +/area/awaymission/challenge/start) "cS" = ( -/obj/machinery/gateway{ - 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/dark, -/area/awaymission/challenge/end) -"cT" = ( -/obj/machinery/gateway{ - 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/dark, -/area/awaymission/challenge/end) +/obj/machinery/gateway/away, +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "cV" = ( -/obj/machinery/gateway{ - dir = 8 +/obj/structure/cable{ + icon_state = "1-2" }, -/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/awaymission/challenge/end) +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "cW" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, +/obj/item/clothing/suit/space/hardsuit/shielded/syndi, +/obj/item/clothing/mask/gas/syndicate, +/obj/item/documents/syndicate, +/obj/structure/safe, /turf/open/floor/plasteel/dark, /area/awaymission/challenge/end) "cX" = ( -/obj/machinery/gateway{ - 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{ +/obj/machinery/light{ dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/awaymission/challenge/end) -"cY" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/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/awaymission/challenge/end) +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "cZ" = ( -/obj/machinery/gateway, /obj/structure/cable{ - icon_state = "0-2" + icon_state = "1-2" }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/light{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/awaymission/challenge/end) -"da" = ( -/obj/machinery/gateway{ - dir = 6 - }, -/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/awaymission/challenge/end) +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "db" = ( /obj/structure/window/reinforced, /turf/open/floor/circuit, /area/awaymission/challenge/end) "dc" = ( /obj/structure/cable{ - icon_state = "1-2" + icon_state = "0-4" }, -/turf/open/floor/plasteel/dark, -/area/awaymission/challenge/end) +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "dd" = ( /obj/structure/window/reinforced{ dir = 8 @@ -1077,16 +937,6 @@ /area/awaymission/challenge/end) "di" = ( /obj/structure/table, -/obj/item/implanter/explosive, -/obj/item/implanter/explosive{ - pixel_y = 4 - }, -/obj/item/implanter/explosive{ - pixel_y = 8 - }, -/obj/item/implanter/explosive{ - pixel_y = 12 - }, /turf/open/floor/plasteel/dark, /area/awaymission/challenge/end) "dj" = ( @@ -1099,7 +949,6 @@ "dk" = ( /obj/machinery/door/airlock/centcom{ name = "Gateway Access"; - opacity = 1; req_access_txt = "109" }, /turf/open/floor/plasteel/dark, @@ -1111,12 +960,6 @@ /turf/open/floor/plating, /area/awaymission/challenge/end) "dm" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "1-4" - }, /mob/living/simple_animal/hostile/syndicate{ name = "Syndicate Technician" }, @@ -1124,10 +967,10 @@ /area/awaymission/challenge/end) "dn" = ( /obj/structure/cable{ - icon_state = "2-8" + icon_state = "1-8" }, -/turf/open/floor/plasteel/dark, -/area/awaymission/challenge/end) +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "do" = ( /obj/machinery/light, /turf/open/floor/circuit, @@ -1137,17 +980,8 @@ /turf/open/floor/circuit, /area/awaymission/challenge/end) "dq" = ( -/obj/structure/cable, -/obj/machinery/power/smes/magical, -/turf/open/floor/circuit, -/area/awaymission/challenge/end) -"dr" = ( -/obj/machinery/power/terminal{ - dir = 8 - }, -/obj/structure/cable, -/turf/open/floor/circuit, -/area/awaymission/challenge/end) +/turf/open/floor/bluespace, +/area/awaymission/challenge/start) "ds" = ( /obj/structure/closet/l3closet, /turf/open/floor/circuit, @@ -27984,11 +27818,11 @@ aa aa aa aa -aa -aa -aa -aa -aa +ab +ab +ab +ab +ab ab ab ab @@ -28239,20 +28073,20 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa ab -ac -af -an -ah -ad -an +ab +ab +dq +cX +dq +ab +ab +at +au +au +au +au +au ax aA aF @@ -28496,21 +28330,21 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa ab -ad -aj -an +aB +ab +dq +cS +dc +dq +dq +au +al +au ao -af -an -av +au +au +au aA aA aA @@ -28753,23 +28587,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa ab -ae +aG +cR +cV +cZ +dn +ab +ab +au ak al -af -ad +au +au aw -av -aB -aC +au +aE +aH aJ aR aH @@ -29010,23 +28844,23 @@ aa aa aa aa -aa -aa -aa -aa -aa -aa -aa ab -af +ab +ab +ab +ab +ab +ab +ab +au al -ah -af +au +au at -af -an -aC -aG +au +au +aD +aH aK aR aH @@ -29072,9 +28906,9 @@ cd cn cH cN -cR -cV -cY +co +co +co db dg cd @@ -29276,14 +29110,14 @@ aa aa ab ag -ah +au al ap au -af +au ay aD -aC +aH aL aR aH @@ -29329,14 +29163,14 @@ cd cn cH cN -cS +co cW -cZ -dc -dc -dc +co +cd +cd +cd dm -dq +cn bP aa aa @@ -29532,12 +29366,12 @@ aa aa aa ab -ah +au al -ah +au aq at -an +au az aE aH @@ -29586,14 +29420,14 @@ cd cn cH cN -cT -cX -da +co +co +co db dh cd -dn -dr +cd +cn bP aa aa @@ -29790,12 +29624,12 @@ aa aa ab ai -ah +au al ar -af -av -ad +au +au +au aA aA aA @@ -30046,13 +29880,13 @@ aa aa aa ab -ah +au am -ad +au as av -ae -av +au +au aA aF aN @@ -31102,7 +30936,7 @@ aV aV aV aV -bx +bC aV aV aV diff --git a/_maps/RandomZLevels/away_mission/moonoutpost19.dmm b/_maps/RandomZLevels/away_mission/moonoutpost19.dmm index d85c8b12d6..ff2db79c83 100644 --- a/_maps/RandomZLevels/away_mission/moonoutpost19.dmm +++ b/_maps/RandomZLevels/away_mission/moonoutpost19.dmm @@ -18,7 +18,6 @@ /area/awaymission/moonoutpost19/hive) "ae" = ( /obj/machinery/computer/arcade{ - icon_state = "arcade"; dir = 1 }, /turf/open/floor/plasteel/dark, @@ -192,60 +191,6 @@ heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/syndicate) -"aG" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/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{ - heat_capacity = 1e+006 - }, -/area/awaymission/moonoutpost19/syndicate) -"aH" = ( -/obj/machinery/gateway{ - 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/dark{ - heat_capacity = 1e+006 - }, -/area/awaymission/moonoutpost19/syndicate) -"aI" = ( -/obj/machinery/gateway{ - 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/dark{ - heat_capacity = 1e+006 - }, -/area/awaymission/moonoutpost19/syndicate) "aJ" = ( /obj/structure/alien/weeds, /obj/structure/alien/weeds{ @@ -292,46 +237,8 @@ heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/syndicate) -"aO" = ( -/obj/machinery/gateway{ - 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{ - heat_capacity = 1e+006 - }, -/area/awaymission/moonoutpost19/syndicate) "aP" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, -/turf/open/floor/plasteel/dark{ - heat_capacity = 1e+006 - }, -/area/awaymission/moonoutpost19/syndicate) -"aQ" = ( -/obj/machinery/gateway{ - 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 - }, +/obj/machinery/gateway/away, /turf/open/floor/plasteel/dark{ heat_capacity = 1e+006 }, @@ -359,7 +266,6 @@ /mob/living/simple_animal/hostile/alien/queen/large{ desc = "A gigantic alien who is in charge of the hive and all of its loyal servants."; name = "alien queen"; - pixel_x = -16; plants_off = 1 }, /turf/open/floor/plating/asteroid{ @@ -379,9 +285,6 @@ }, /area/awaymission/moonoutpost19/syndicate) "aW" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -397,7 +300,6 @@ }, /area/awaymission/moonoutpost19/syndicate) "aX" = ( -/obj/machinery/gateway, /obj/structure/cable{ icon_state = "0-2" }, @@ -416,9 +318,6 @@ }, /area/awaymission/moonoutpost19/syndicate) "aY" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -435,9 +334,7 @@ }, /area/awaymission/moonoutpost19/syndicate) "aZ" = ( -/obj/effect/turf_decal/tile/red{ - dir = 2 - }, +/obj/effect/turf_decal/tile/red, /turf/open/floor/plasteel/dark{ heat_capacity = 1e+006 }, @@ -490,9 +387,7 @@ /area/awaymission/moonoutpost19/syndicate) "bh" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/red{ - dir = 2 - }, +/obj/effect/turf_decal/tile/red, /turf/open/floor/plasteel/dark{ heat_capacity = 1e+006 }, @@ -915,11 +810,9 @@ /area/awaymission/moonoutpost19/syndicate) "bT" = ( /obj/machinery/power/smes{ - charge = 0; input_level = 10000; inputting = 0; - output_level = 15000; - outputting = 1 + output_level = 15000 }, /obj/structure/cable{ icon_state = "0-8" @@ -961,7 +854,6 @@ /area/awaymission/moonoutpost19/hive) "bX" = ( /obj/machinery/conveyor{ - dir = 2; id = "awaysyndie" }, /obj/effect/turf_decal/stripes/line{ @@ -1334,8 +1226,7 @@ /area/awaymission/moonoutpost19/syndicate) "cC" = ( /obj/machinery/mineral/processing_unit{ - dir = 1; - output_dir = 2 + dir = 1 }, /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -1426,8 +1317,6 @@ "cK" = ( /obj/structure/cable, /obj/machinery/power/apc/highcap/fifteen_k{ - dir = 2; - locked = 1; name = "Worn-out APC"; pixel_y = -25; req_access = null; @@ -1472,12 +1361,9 @@ "cN" = ( /obj/structure/cable, /obj/machinery/power/port_gen/pacman{ - desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator" }, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating{ heat_capacity = 1e+006 }, @@ -1486,12 +1372,9 @@ /obj/structure/cable, /obj/effect/decal/cleanable/dirt, /obj/machinery/power/port_gen/pacman/super{ - desc = "A portable generator for emergency backup power."; name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator" }, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating{ heat_capacity = 1e+006 }, @@ -1823,7 +1706,6 @@ /obj/structure/closet/secure_closet{ desc = "It's a secure locker for personnel. The first card swiped gains control."; icon_state = "cabinet"; - locked = 1; name = "personal closet"; req_access_txt = "150" }, @@ -2036,8 +1918,7 @@ /turf/open/floor/plating{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; + icon_state = "platingdmg1"; temperature = 251 }, /area/awaymission/moonoutpost19/syndicate) @@ -2059,23 +1940,11 @@ /obj/machinery/light/small{ dir = 1 }, -/turf/open/floor/plating{ +/turf/open/floor/plating/asteroid{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 251 + heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/syndicate) -"dM" = ( -/turf/open/floor/plating{ - initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 251 - }, -/area/awaymission/moonoutpost19/main) "dN" = ( /obj/item/stack/ore/iron{ pixel_x = -7; @@ -2400,14 +2269,12 @@ /area/awaymission/moonoutpost19/research) "eK" = ( /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/research) "eL" = ( /obj/structure/alien/weeds, /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/research) @@ -2467,7 +2334,6 @@ /area/awaymission/moonoutpost19/research) "eS" = ( /obj/machinery/power/port_gen/pacman{ - desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator" }, /obj/structure/cable{ @@ -2479,7 +2345,6 @@ /area/awaymission/moonoutpost19/research) "eT" = ( /obj/machinery/power/port_gen/pacman/super{ - desc = "A portable generator for emergency backup power."; name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator" }, /obj/structure/cable{ @@ -2525,8 +2390,7 @@ charge = 1.5e+006; input_level = 10000; inputting = 0; - output_level = 15000; - outputting = 1 + output_level = 15000 }, /turf/open/floor/plating{ heat_capacity = 1e+006 @@ -2619,9 +2483,7 @@ icon_state = "2-8" }, /obj/structure/alien/weeds, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -2655,7 +2517,6 @@ /area/awaymission/moonoutpost19/research) "fh" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/structure/table, @@ -2801,9 +2662,7 @@ icon_state = "1-4" }, /obj/structure/alien/weeds, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -3041,7 +2900,6 @@ "fT" = ( /obj/structure/closet/secure_closet{ icon_state = "sec"; - locked = 1; name = "security officer's locker"; req_access_txt = "201" }, @@ -3109,9 +2967,7 @@ icon_state = "1-2" }, /obj/structure/alien/weeds, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -3241,9 +3097,7 @@ pixel_x = 28 }, /obj/structure/alien/weeds, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -3471,9 +3325,7 @@ req_access = null; start_charge = 100 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -3626,9 +3478,7 @@ pixel_x = 23; req_access = null }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -3712,7 +3562,6 @@ "hb" = ( /obj/machinery/light{ active_power_usage = 0; - dir = 2; icon_state = "tube-broken"; status = 2 }, @@ -3826,7 +3675,6 @@ req_access_txt = "201" }, /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/research) @@ -3842,7 +3690,6 @@ status = 2 }, /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/research) @@ -3867,7 +3714,6 @@ "hq" = ( /obj/structure/closet/secure_closet{ icon_state = "rd"; - locked = 1; name = "research director's locker"; req_access_txt = "201" }, @@ -3885,7 +3731,6 @@ pixel_y = 2 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /turf/open/floor/plasteel/cafeteria{ @@ -3935,9 +3780,7 @@ }, /area/awaymission/moonoutpost19/research) "hw" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -4027,7 +3870,6 @@ }, /obj/machinery/light/small{ active_power_usage = 0; - dir = 2; icon_state = "bulb-broken"; status = 2 }, @@ -4303,7 +4145,6 @@ /obj/structure/closet/l3closet, /obj/machinery/light/small{ active_power_usage = 0; - dir = 2; icon_state = "bulb-broken"; status = 2 }, @@ -4453,7 +4294,6 @@ }, /obj/machinery/shower{ dir = 4; - icon_state = "shower"; name = "emergency shower" }, /obj/effect/turf_decal/stripes/line{ @@ -4581,7 +4421,6 @@ }, /obj/machinery/light/small{ active_power_usage = 0; - dir = 2; icon_state = "bulb-broken"; status = 2 }, @@ -4623,9 +4462,7 @@ /area/awaymission/moonoutpost19/research) "iL" = ( /obj/machinery/light/small, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -4720,9 +4557,7 @@ /turf/closed/wall/rust, /area/awaymission/moonoutpost19/arrivals) "iU" = ( -/obj/machinery/vending/boozeomat{ - req_access_txt = "0" - }, +/obj/machinery/vending/boozeomat, /turf/open/floor/plasteel/cafeteria{ dir = 5 }, @@ -4911,7 +4746,7 @@ }, /area/awaymission/moonoutpost19/research) "jq" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ desc = "A plastic potted plant."; pixel_y = 3 }, @@ -5680,9 +5515,7 @@ /obj/machinery/door/firedoor/closed{ opacity = 0 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -5830,9 +5663,7 @@ /obj/structure/chair{ dir = 8 }, -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -6048,9 +5879,7 @@ }, /area/awaymission/moonoutpost19/arrivals) "lG" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -6224,9 +6053,7 @@ }, /area/awaymission/moonoutpost19/arrivals) "mh" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; heat_capacity = 1e+006; @@ -6237,7 +6064,6 @@ /obj/machinery/portable_atmospherics/canister/air, /obj/effect/decal/cleanable/dirt, /obj/structure/window{ - icon_state = "window"; dir = 1 }, /turf/open/floor/plating{ @@ -6271,7 +6097,6 @@ /area/awaymission/moonoutpost19/arrivals) "mm" = ( /obj/structure/closet/secure_closet{ - icon_state = "secure"; locked = 0; name = "kitchen Cabinet"; req_access_txt = "201" @@ -6375,9 +6200,7 @@ /area/awaymission/moonoutpost19/arrivals) "mx" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; heat_capacity = 1e+006; @@ -6786,18 +6609,6 @@ heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/arrivals) -"nu" = ( -/obj/machinery/light/small{ - dir = 8 - }, -/turf/open/floor/plating{ - initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 251 - }, -/area/awaymission/moonoutpost19/arrivals) "nw" = ( /obj/machinery/washing_machine, /obj/effect/turf_decal/tile/blue{ @@ -6842,9 +6653,7 @@ pixel_x = 23; req_access = null }, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; heat_capacity = 1e+006; @@ -7088,18 +6897,6 @@ heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/arrivals) -"nW" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/turf/open/floor/plating{ - initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 251 - }, -/area/awaymission/moonoutpost19/arrivals) "nX" = ( /obj/structure/chair/comfy/black{ dir = 8 @@ -7117,9 +6914,7 @@ dir = 4 }, /obj/effect/decal/cleanable/generic, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; heat_capacity = 1e+006; @@ -7128,12 +6923,9 @@ /area/awaymission/moonoutpost19/arrivals) "nZ" = ( /obj/structure/disposalpipe/segment, -/turf/open/floor/plating{ +/turf/open/floor/plating/asteroid{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 251 + heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/main) "oa" = ( @@ -7144,7 +6936,7 @@ }, /area/awaymission/moonoutpost19/arrivals) "ob" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ desc = "A plastic potted plant."; pixel_y = 3 }, @@ -7163,12 +6955,9 @@ /obj/structure/disposalpipe/trunk{ dir = 1 }, -/turf/open/floor/plating{ +/turf/open/floor/plating/asteroid{ initial_gas_mix = "co2=48.7;n2=13.2;o2=32.4;TEMP=251"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 251 + heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/main) "od" = ( @@ -7203,7 +6992,6 @@ /obj/structure/window/reinforced, /obj/structure/closet/secure_closet{ icon_state = "science"; - locked = 1; name = "scientist's locker"; req_access_txt = "201" }, @@ -36454,7 +36242,7 @@ hI hI hI hI -nW +lj ba ba ba @@ -36711,7 +36499,7 @@ zZ nA nK Wf -dM +ba ba ba ba @@ -36968,7 +36756,7 @@ zZ lM lN Wf -dM +ba ba ba ba @@ -37225,7 +37013,7 @@ hI nB nL hI -nW +lj ba ba ba @@ -40774,7 +40562,7 @@ du dx dC dI -dM +ba ba ba ba @@ -41594,13 +41382,13 @@ hJ lM lN hI -dM ba ba ba -dM -dM -dM +ba +ba +ba +ba od ba ba @@ -41857,7 +41645,7 @@ nZ nZ nZ oc -dM +ba ba ba ba @@ -42040,8 +41828,8 @@ ac ac at az -aG -aO +aW +aW aW aV br @@ -42108,13 +41896,13 @@ hI nJ nR hJ -dM ba ba ba -dM -dM -dM +ba +ba +ba +ba ba oe ba @@ -42297,7 +42085,7 @@ ac ac at aA -aH +aW aP aX bg @@ -42554,8 +42342,8 @@ ac ac at aB -aI -aQ +aW +aW aY bh bt @@ -42872,9 +42660,9 @@ lN hJ ba ba -dM -dM -nu +ba +ba +mO ba ba ba diff --git a/_maps/RandomZLevels/away_mission/research.dmm b/_maps/RandomZLevels/away_mission/research.dmm index c07499fb57..4710d9829b 100644 --- a/_maps/RandomZLevels/away_mission/research.dmm +++ b/_maps/RandomZLevels/away_mission/research.dmm @@ -117,7 +117,7 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/engineering) "ax" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20"; pixel_y = 3 }, @@ -592,27 +592,18 @@ /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bA" = ( -/obj/machinery/gateway{ - dir = 9 - }, /obj/effect/turf_decal/stripes/line{ dir = 9 }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bB" = ( -/obj/machinery/gateway{ - dir = 1 - }, /obj/effect/turf_decal/stripes/line{ dir = 1 }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bC" = ( -/obj/machinery/gateway{ - dir = 5 - }, /obj/effect/turf_decal/stripes/line{ dir = 5 }, @@ -764,24 +755,16 @@ /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bS" = ( -/obj/machinery/gateway{ - dir = 8 - }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bT" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, +/obj/machinery/gateway/away, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bU" = ( -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -830,24 +813,17 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/engineering) "bY" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/turf_decal/stripes/line{ dir = 10 }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "bZ" = ( -/obj/machinery/gateway, /obj/effect/landmark/awaystart, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/gateway) "ca" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -919,7 +895,6 @@ /area/awaymission/research/interior/gateway) "ck" = ( /obj/machinery/door/window/eastright{ - icon_state = "right"; dir = 2 }, /obj/effect/landmark/awaystart, @@ -1363,16 +1338,6 @@ "dc" = ( /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) -"dd" = ( -/obj/structure/closet/crate, -/obj/item/disk/data{ - desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines."; - name = "encrypted genetic data disk"; - read_only = 1 - }, -/obj/item/firing_pin/dna, -/turf/open/floor/plasteel/dark, -/area/awaymission/research/interior/secure) "de" = ( /obj/structure/filingcabinet, /obj/structure/filingcabinet, @@ -1391,8 +1356,8 @@ name = "encrypted genetic data disk"; read_only = 1 }, -/obj/item/dnainjector/xraymut, -/obj/item/dnainjector/xraymut, +/obj/item/dnainjector/glow, +/obj/item/storage/toolbox/syndicate, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) "dg" = ( @@ -1481,18 +1446,6 @@ "do" = ( /turf/closed/wall/r_wall, /area/awaymission/research/interior/security) -"dp" = ( -/obj/structure/closet/crate, -/obj/item/disk/data{ - desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines."; - name = "encrypted genetic data disk"; - read_only = 1 - }, -/obj/item/dnainjector/telemut, -/obj/item/dnainjector/telemut, -/obj/item/dnainjector/chavmut, -/turf/open/floor/plasteel/dark, -/area/awaymission/research/interior/secure) "dq" = ( /obj/machinery/light{ dir = 8 @@ -1743,8 +1696,6 @@ "dJ" = ( /obj/structure/rack, /obj/item/clothing/suit/armor/bulletproof, -/obj/item/clothing/suit/armor/bulletproof, -/obj/item/clothing/head/helmet/alt, /obj/item/clothing/head/helmet/alt, /obj/machinery/light/small{ dir = 4 @@ -1769,19 +1720,19 @@ /area/awaymission/research/interior/secure) "dL" = ( /obj/structure/closet/crate, -/obj/item/disk/data{ - desc = "A data disk used to store cloning and genetic records. The name on the label appears to be scratched off with the words 'DO NOT CLONE' hastily written over it."; - fields = list("label" = "Buffer1:George Melons", "UI" = "3c300f11b5421ca7014d8", "SE" = "430431205660551642142504334461413202111310233445620533134255", "UE" = "6893e6a0b0076a41897776b10cc2b324", "name" = "George Melons", "blood_type" = "B+"); - name = "old genetics data disk" - }, /obj/item/disk/data{ desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines."; name = "encrypted genetic data disk"; read_only = 1 }, -/obj/item/firing_pin/dna, -/obj/item/dnainjector/dwarf, -/obj/item/dnainjector/dwarf, +/obj/item/disk/data{ + desc = "A data disk used to store cloning and genetic records. The name on the label appears to be scratched off."; + fields = list("label" = "Buffer1:Kr-$$@##", "UI" = "f8f603857000f930127c4", "SE" = "414401462231053131010241514651403453121613263463440351136366", "UE" = "340008485c321e542aed4df7032ac04d", "name" = "Krystal Symers", "blood_type" = "A+"); + name = "dusty genetics data disk"; + read_only = 1 + }, +/obj/item/dnainjector/insulated, +/obj/item/gun/energy/disabler, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) "dM" = ( @@ -1792,15 +1743,17 @@ read_only = 1 }, /obj/item/disk/data{ - desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines."; - name = "encrypted genetic data disk"; + desc = "A data disk used to store cloning and genetic records. The name on the label appears to be scratched off."; + fields = list("label" = "Buffer1:Kr-$$@##", "UI" = "f8f603857000f930127c4", "SE" = "414401462231053131010241514651403453121613263463440351136366", "UE" = "340008485c321e542aed4df7032ac04d", "name" = "Krystal Symers", "blood_type" = "A+"); + name = "dusty genetics data disk"; read_only = 1 }, -/obj/item/dnainjector/chameleonmut, +/obj/item/dnainjector/glow, +/obj/item/storage/toolbox/syndicate, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) "dN" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/effect/turf_decal/tile/purple{ @@ -1890,7 +1843,6 @@ "dU" = ( /obj/structure/rack, /obj/item/gun/ballistic/automatic/wt550, -/obj/item/gun/ballistic/automatic/wt550, /obj/item/ammo_box/magazine/wt550m9, /obj/item/ammo_box/magazine/wt550m9, /obj/effect/turf_decal/tile/red{ @@ -2070,7 +2022,6 @@ "ep" = ( /obj/structure/rack, /obj/item/gun/ballistic/automatic/pistol/m1911, -/obj/item/gun/ballistic/automatic/pistol/m1911, /obj/item/ammo_box/magazine/m45, /obj/item/ammo_box/magazine/m45, /obj/effect/turf_decal/tile/red{ @@ -3071,7 +3022,6 @@ icon_state = "4-8" }, /obj/machinery/door/airlock/highsecurity{ - aiDisabledIdScanner = 0; name = "Vault Storage"; req_access_txt = "36" }, @@ -3531,7 +3481,6 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/cryo) "gR" = ( -/obj/item/melee/classic_baton/telescopic, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -3542,6 +3491,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/item/melee/baton/cattleprod, /turf/open/floor/plasteel/white, /area/awaymission/research/interior/cryo) "gS" = ( @@ -3914,7 +3864,6 @@ /area/awaymission/research/interior/cryo) "hw" = ( /obj/machinery/computer/arcade{ - icon_state = "arcade"; dir = 8 }, /turf/open/floor/plasteel/yellowsiding{ @@ -4126,20 +4075,22 @@ /area/awaymission/research/interior/security) "hS" = ( /obj/structure/closet/crate, +/obj/item/clothing/head/collectable/petehat{ + name = "dusty hat" + }, /obj/item/disk/data{ desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines."; name = "encrypted genetic data disk"; read_only = 1 }, /obj/item/disk/data{ - desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines. This one has the initials 'C.P' marked on the front. "; - name = "encrypted genetic data disk"; + desc = "A data disk used to store cloning and genetic records. The name on the label appears to be scratched off."; + fields = list("label" = "Buffer1:Kr-$$@##", "UI" = "f8f603857000f930127c4", "SE" = "414401462231053131010241514651403453121613263463440351136366", "UE" = "340008485c321e542aed4df7032ac04d", "name" = "Krystal Symers", "blood_type" = "A+"); + name = "dusty genetics data disk"; read_only = 1 }, -/obj/item/clothing/head/collectable/petehat{ - name = "dusty hat" - }, -/obj/item/firing_pin/dna, +/obj/item/dnainjector/gigantism, +/obj/item/kitchen/knife/combat/survival, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) "hT" = ( @@ -4150,12 +4101,13 @@ read_only = 1 }, /obj/item/disk/data{ - desc = "A specialized data disk for holding critical genetic backup data. Without proper passwords, information will turn up blank on most DNA machines."; - name = "encrypted genetic data disk"; + desc = "A data disk used to store cloning and genetic records. The name on the label appears to be scratched off."; + fields = list("label" = "Buffer1:Kr-$$@##", "UI" = "f8f603857000f930127c4", "SE" = "414401462231053131010241514651403453121613263463440351136366", "UE" = "340008485c321e542aed4df7032ac04d", "name" = "Krystal Symers", "blood_type" = "A+"); + name = "dusty genetics data disk"; read_only = 1 }, -/obj/item/firing_pin/dna, -/obj/item/dnainjector/hulkmut, +/obj/item/dnainjector/antenna, +/obj/item/clothing/suit/armor/vest, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) "hU" = ( @@ -4173,7 +4125,7 @@ /turf/open/floor/plasteel, /area/awaymission/research/interior/genetics) "hV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/purple{ @@ -4268,7 +4220,7 @@ /turf/open/floor/plasteel, /area/awaymission/research/interior/security) "ii" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ desc = "A potted plant, it doesn't look very healthy..."; name = "dead potted plant" }, @@ -4296,10 +4248,14 @@ name = "encrypted genetic data disk"; read_only = 1 }, -/obj/item/firing_pin/dna/dredd, -/obj/item/firing_pin/dna/dredd, -/obj/item/dnainjector/lasereyesmut, -/obj/item/dnainjector/lasereyesmut, +/obj/item/disk/data{ + desc = "A data disk used to store cloning and genetic records. The name on the label appears to be scratched off."; + fields = list("label" = "Buffer1:Kr-$$@##", "UI" = "f8f603857000f930127c4", "SE" = "414401462231053131010241514651403453121613263463440351136366", "UE" = "340008485c321e542aed4df7032ac04d", "name" = "Krystal Symers", "blood_type" = "A+"); + name = "dusty genetics data disk"; + read_only = 1 + }, +/obj/item/dnainjector/gigantism, +/obj/item/kitchen/knife/combat/survival, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) "im" = ( @@ -4603,7 +4559,6 @@ /area/awaymission/research/interior/bathroom) "iN" = ( /obj/machinery/shower{ - icon_state = "shower"; dir = 8 }, /turf/open/floor/plasteel/freezer, @@ -4746,7 +4701,7 @@ /turf/open/floor/wood, /area/awaymission/research/interior/dorm) "jm" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel/yellowsiding{ @@ -5350,7 +5305,7 @@ /turf/open/floor/plating, /area/awaymission/research/interior/medbay) "kC" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/yellowsiding{ @@ -5416,7 +5371,7 @@ /area/awaymission/research/interior/dorm) "kS" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel, /area/awaymission/research/interior/dorm) "kT" = ( @@ -5707,7 +5662,7 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/medbay) "ly" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/yellowsiding{ @@ -6185,7 +6140,7 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/escapepods) "mJ" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/effect/turf_decal/tile/green{ dir = 1 }, @@ -6222,7 +6177,7 @@ /turf/open/floor/grass, /area/awaymission/research/interior/escapepods) "mN" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/effect/turf_decal/tile/green, @@ -6335,7 +6290,7 @@ /area/space/nearstation) "nb" = ( /obj/structure/table/wood, -/obj/item/book/granter/spell/random, +/obj/item/book/granter/spell/smoke, /turf/open/floor/mineral/plasma, /area/space/nearstation) "nc" = ( @@ -6460,6 +6415,11 @@ }, /turf/open/floor/plating, /area/awaymission/research/interior/maint) +"Hs" = ( +/obj/structure/table/wood, +/obj/item/book/granter/crafting_recipe/bone_bow, +/turf/open/floor/mineral/plasma, +/area/space/nearstation) "Km" = ( /obj/machinery/door/airlock/security/glass{ id_tag = "outerbrig"; @@ -6582,6 +6542,11 @@ }, /turf/open/floor/plating, /area/awaymission/research/interior/escapepods) +"ZZ" = ( +/obj/structure/table/wood, +/obj/item/book/granter/action/origami, +/turf/open/floor/mineral/plasma, +/area/space/nearstation) (1,1,1) = {" aa @@ -11121,8 +11086,8 @@ ab ab na nb -nb -nb +Hs +ZZ na ab ab @@ -31113,8 +31078,8 @@ ad ad ad cQ -dd -dp +dL +dL dL cQ dc @@ -31126,7 +31091,7 @@ cQ dc cQ hS -dM +il il cQ ad @@ -32399,7 +32364,7 @@ ad ad cQ df -dd +dM dM cQ dc @@ -32412,7 +32377,7 @@ dc cQ hT hT -dd +hT cQ ad ad diff --git a/_maps/RandomZLevels/away_mission/snowdin.dmm b/_maps/RandomZLevels/away_mission/snowdin.dmm index a40066df4f..00530695e9 100644 --- a/_maps/RandomZLevels/away_mission/snowdin.dmm +++ b/_maps/RandomZLevels/away_mission/snowdin.dmm @@ -417,7 +417,6 @@ dir = 1 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/effect/turf_decal/tile/neutral{ @@ -1035,7 +1034,6 @@ /area/awaymission/snowdin/post/research) "cE" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/effect/decal/cleanable/dirt, @@ -1281,7 +1279,6 @@ "cY" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -1329,7 +1326,6 @@ "db" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -1389,7 +1385,6 @@ "df" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -1861,7 +1856,6 @@ /area/awaymission/snowdin/post) "em" = ( /obj/machinery/power/apc{ - dir = 2; name = "Gateway APC"; pixel_y = -24; req_access = 150 @@ -1936,9 +1930,7 @@ /turf/open/floor/plasteel, /area/awaymission/snowdin/post/messhall) "et" = ( -/obj/machinery/vending/boozeomat{ - req_access_txt = "0" - }, +/obj/machinery/vending/boozeomat, /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ dir = 1 @@ -1968,7 +1960,6 @@ /area/awaymission/snowdin/post/messhall) "ew" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/effect/turf_decal/tile/bar, @@ -2210,7 +2201,6 @@ dir = 1 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/effect/turf_decal/tile/blue{ @@ -2411,7 +2401,6 @@ /area/awaymission/snowdin/post/dorm) "fw" = ( /obj/machinery/sleeper{ - icon_state = "sleeper"; dir = 4 }, /obj/effect/turf_decal/tile/blue{ @@ -2525,27 +2514,6 @@ "fF" = ( /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) -"fG" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/awaymission/snowdin/post/gateway) -"fH" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/awaymission/snowdin/post/gateway) -"fI" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/awaymission/snowdin/post/gateway) "fJ" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/bar, @@ -2631,7 +2599,6 @@ /area/awaymission/snowdin/post/hydro) "fT" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/effect/turf_decal/tile/green{ @@ -2906,29 +2873,16 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) -"gw" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/turf_decal/bot, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, -/area/awaymission/snowdin/post/gateway) "gx" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, /obj/effect/turf_decal/bot, /obj/structure/cable/yellow{ icon_state = "0-2" }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/gateway/away, /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) "gy" = ( -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) @@ -3275,15 +3229,11 @@ /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) "hl" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) "hm" = ( -/obj/machinery/gateway, /obj/effect/turf_decal/bot, /obj/structure/cable/yellow{ icon_state = "0-2" @@ -3295,9 +3245,6 @@ /turf/open/floor/plasteel, /area/awaymission/snowdin/post/gateway) "hn" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/bot, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, @@ -3808,7 +3755,6 @@ /area/awaymission/snowdin/post) "iu" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -4483,7 +4429,8 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/garage) "jL" = ( -/obj/vehicle/ridden/atv, +/obj/vehicle/ridden/atv/snowmobile, +/obj/item/key, /turf/open/floor/plating, /area/awaymission/snowdin/post/garage) "jM" = ( @@ -5060,8 +5007,9 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/garage) "lc" = ( -/obj/vehicle/ridden/atv, /obj/effect/decal/cleanable/oil, +/obj/vehicle/ridden/atv/snowmobile, +/obj/item/key, /turf/open/floor/plating, /area/awaymission/snowdin/post/garage) "ld" = ( @@ -5285,7 +5233,6 @@ /area/awaymission/snowdin/post) "lv" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -5421,7 +5368,6 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -5468,7 +5414,6 @@ /area/awaymission/snowdin/post/hydro) "lG" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 2; piping_layer = 3; pixel_x = 5; pixel_y = 5 @@ -6601,7 +6546,6 @@ /obj/item/ammo_box/a762, /obj/structure/closet/secure_closet{ icon_state = "sec"; - locked = 1; name = "security officer's locker"; req_access_txt = "201" }, @@ -6800,7 +6744,6 @@ /area/awaymission/snowdin/post/hydro) "ot" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /turf/open/floor/plasteel, @@ -8715,7 +8658,6 @@ /area/awaymission/snowdin/outside) "sW" = ( /obj/machinery/power/turbine{ - dir = 2; luminosity = 2 }, /obj/structure/cable, @@ -9863,7 +9805,6 @@ "wm" = ( /obj/machinery/porta_turret/centcom_shuttle/weak{ desc = "A turret built with substandard parts and run down further with age."; - icon_state = "syndie_off"; dir = 9; faction = list("pirate") }, @@ -9958,7 +9899,6 @@ }, /obj/effect/light_emitter{ light_color = "#FAA019"; - light_power = 1; light_range = 4; name = "fire light" }, @@ -9990,7 +9930,6 @@ /area/awaymission/snowdin/outside) "wC" = ( /obj/vehicle/ridden/atv{ - icon_state = "atv"; dir = 4 }, /obj/effect/light_emitter{ @@ -11092,10 +11031,8 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/minipost) "zq" = ( -/obj/vehicle/ridden/atv{ - icon_state = "atv"; - dir = 8 - }, +/obj/vehicle/ridden/atv/snowmobile, +/obj/item/key, /turf/open/floor/plating, /area/awaymission/snowdin/post/minipost) "zr" = ( @@ -11412,12 +11349,6 @@ /obj/item/clothing/suit/hooded/wintercoat, /turf/open/floor/plating/snowed, /area/awaymission/snowdin/outside) -"Ah" = ( -/obj/structure/window/reinforced/fulltile/ice, -/obj/structure/grille, -/obj/item/clothing/suit/hooded/wintercoat, -/turf/open/floor/plating, -/area/awaymission/snowdin/post/minipost) "Ai" = ( /turf/open/floor/plating{ icon_state = "platingdmg1" @@ -11588,7 +11519,6 @@ }, /obj/effect/light_emitter{ light_color = "#FAA019"; - light_power = 1; light_range = 4; name = "fire light" }, @@ -12299,7 +12229,6 @@ desc = "It's a storage unit for a Syndicate boarding party." }, /obj/effect/turf_decal/bot_white, -/obj/item/gun/ballistic/automatic/pistol, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -12345,7 +12274,6 @@ /area/awaymission/snowdin/cave) "CP" = ( /obj/structure/shuttle/engine/heater{ - icon_state = "heater"; dir = 4 }, /obj/effect/turf_decal/stripes/line{ @@ -12635,14 +12563,6 @@ /obj/item/stack/rods, /turf/open/floor/mineral/plastitanium/red, /area/awaymission/snowdin/cave) -"Ds" = ( -/obj/item/grenade/plastic/c4, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/awaymission/snowdin/cave) "Dt" = ( /obj/structure/table/reinforced, /obj/structure/window/reinforced{ @@ -12880,7 +12800,6 @@ /area/awaymission/snowdin/cave) "DU" = ( /obj/structure/shuttle/engine/heater{ - icon_state = "heater"; dir = 4 }, /obj/effect/turf_decal/stripes/line{ @@ -13215,26 +13134,14 @@ /obj/item/toy/plush/nukeplushie, /turf/open/floor/plasteel/dark, /area/awaymission/snowdin/cave) -"EE" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/turf_decal/weather/snow, -/obj/machinery/suit_storage_unit{ - state_open = 1 - }, -/turf/open/floor/mineral/plastitanium{ - initial_gas_mix = "o2=22;n2=82;TEMP=180"; - planetary_atmos = 1; - temperature = 180 - }, -/area/awaymission/snowdin/cave) "EF" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 }, /obj/effect/turf_decal/weather/snow, -/obj/machinery/suit_storage_unit/syndicate, +/obj/item/clothing/suit/hooded/wintercoat/security, +/obj/item/tank/internals/emergency_oxygen/engi, +/obj/structure/rack, /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; @@ -13246,9 +13153,9 @@ dir = 5 }, /obj/effect/turf_decal/weather/snow, -/obj/machinery/suit_storage_unit{ - state_open = 1 - }, +/obj/item/clothing/suit/hooded/wintercoat/security, +/obj/item/tank/internals/emergency_oxygen/engi, +/obj/structure/rack, /turf/open/floor/mineral/plastitanium{ initial_gas_mix = "o2=22;n2=82;TEMP=180"; planetary_atmos = 1; @@ -13320,7 +13227,6 @@ /area/awaymission/snowdin/cave) "EN" = ( /obj/machinery/sleeper/syndie{ - icon_state = "sleeper_s"; dir = 1 }, /obj/effect/turf_decal/bot_white, @@ -13333,7 +13239,6 @@ "EP" = ( /obj/effect/turf_decal/bot_white, /obj/machinery/sleeper/syndie{ - icon_state = "sleeper_s"; dir = 1 }, /turf/open/floor/plasteel/dark, @@ -13757,7 +13662,6 @@ /area/awaymission/snowdin/cave/cavern) "FY" = ( /obj/machinery/conveyor{ - dir = 2; id = "snowdin_belt_mine" }, /obj/machinery/light/small{ @@ -13780,8 +13684,7 @@ /area/awaymission/snowdin/post/mining_main) "Gc" = ( /obj/structure/statue/snow/snowman{ - anchored = 1; - name = "snowman" + anchored = 1 }, /obj/item/pickaxe/mini{ pixel_x = 5; @@ -13868,7 +13771,6 @@ "Gn" = ( /obj/structure/plasticflaps, /obj/machinery/conveyor{ - dir = 2; id = "snowdin_belt_mine" }, /turf/open/floor/plating, @@ -14054,7 +13956,6 @@ output_dir = 2 }, /obj/machinery/conveyor{ - dir = 2; id = "snowdin_belt_mine" }, /turf/open/floor/plating, @@ -14170,7 +14071,6 @@ /area/awaymission/snowdin/post/mining_main/mechbay) "Hk" = ( /obj/machinery/conveyor{ - dir = 2; id = "snowdin_belt_mine" }, /turf/open/floor/plating, @@ -14286,11 +14186,9 @@ /area/awaymission/snowdin/post/mining_main/mechbay) "HC" = ( /obj/machinery/mineral/processing_unit{ - dir = 1; - output_dir = 2 + dir = 1 }, /obj/machinery/conveyor{ - dir = 2; id = "snowdin_belt_mine" }, /turf/open/floor/plating, @@ -14555,7 +14453,6 @@ /area/awaymission/snowdin/post/mining_main/mechbay) "In" = ( /obj/mecha/working/ripley/mining{ - icon_state = "ripley"; dir = 1 }, /obj/effect/turf_decal/bot, @@ -14615,11 +14512,9 @@ /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_main) "Ix" = ( -/obj/vehicle/ridden/atv{ - icon_state = "atv"; - dir = 1 - }, /obj/effect/decal/cleanable/oil, +/obj/vehicle/ridden/atv/snowmobile, +/obj/item/key, /turf/open/floor/plating, /area/awaymission/snowdin/post/mining_main) "Iy" = ( @@ -26665,8 +26560,8 @@ bE az en fh -fG -gw +gy +hl hl hR iA @@ -26922,7 +26817,7 @@ bE dK eo fh -fH +gy gx hm hS @@ -27179,7 +27074,7 @@ dk dK ep fh -fI +gy gy hn hT @@ -27300,7 +27195,7 @@ oa dX yW yW -Ah +AX Av Lw yX @@ -36093,7 +35988,7 @@ CC El an an -EE +EF CC ae ae @@ -36607,7 +36502,7 @@ OF En Es Dp -EE +EF CC zh af @@ -38396,7 +38291,7 @@ CC CL CW Di -Ds +Di Di CC CX @@ -55604,7 +55499,7 @@ eL eJ tp qi -tt +tz qi tp eJ @@ -56372,13 +56267,13 @@ eJ eJ tp qi -tt +tz tv qi tt qi tv -tt +tz qi tp eJ @@ -57146,7 +57041,7 @@ eJ eJ tp qi -tt +tz qi tp eJ @@ -69622,7 +69517,7 @@ tp qi tz qi -tt +tz qi qi qi @@ -70385,7 +70280,7 @@ eJ gW tp qi -tt +tz tp qi qi @@ -71159,7 +71054,7 @@ qi qi tp qi -tt +tz qi tp tp diff --git a/_maps/RandomZLevels/away_mission/spacebattle.dmm b/_maps/RandomZLevels/away_mission/spacebattle.dmm deleted file mode 100644 index ca44e7d7b7..0000000000 --- a/_maps/RandomZLevels/away_mission/spacebattle.dmm +++ /dev/null @@ -1,68453 +0,0 @@ -//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE -"aa" = ( -/turf/closed/mineral/random, -/area/space/nearstation) -"ab" = ( -/turf/open/space, -/area/space) -"ac" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/mob/living/simple_animal/hostile/syndicate/melee/sword, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ad" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate2) -"ae" = ( -/obj/structure/shuttle/engine/propulsion{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate2) -"af" = ( -/obj/structure/shuttle/engine/propulsion/left{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate2) -"ah" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate2) -"ai" = ( -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate2) -"aj" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"ak" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate2) -"al" = ( -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"am" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/suit/space/hardsuit/syndi, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"an" = ( -/obj/structure/table/reinforced, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"ao" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"ap" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/spacebattle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"aq" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"ar" = ( -/obj/structure/table/reinforced, -/obj/item/grenade/empgrenade, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"as" = ( -/obj/structure/table/reinforced, -/obj/item/ammo_casing/c10mm, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"at" = ( -/obj/structure/table/reinforced, -/obj/item/gun/ballistic/automatic/c20r, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"aw" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate3) -"ax" = ( -/obj/structure/shuttle/engine/propulsion{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate3) -"ay" = ( -/obj/structure/shuttle/engine/propulsion/left{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate3) -"aA" = ( -/obj/structure/table/reinforced, -/obj/item/gun/ballistic/automatic/pistol, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"aB" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate3) -"aC" = ( -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate3) -"aD" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"aE" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate3) -"aG" = ( -/mob/living/simple_animal/hostile/syndicate/melee/spacebattle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"aI" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/suit/space/hardsuit/syndi, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"aJ" = ( -/obj/structure/table/reinforced, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"aK" = ( -/obj/machinery/computer/shuttle{ - dir = 1 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"aP" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate1) -"aQ" = ( -/obj/structure/shuttle/engine/propulsion{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate1) -"aR" = ( -/obj/structure/shuttle/engine/propulsion/left{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate1) -"aT" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"aU" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate1) -"aV" = ( -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate1) -"aW" = ( -/obj/structure/window/reinforced, -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate2) -"aX" = ( -/obj/structure/window/reinforced, -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate2) -"aY" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"aZ" = ( -/obj/structure/chair{ - dir = 4 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"ba" = ( -/obj/structure/chair{ - dir = 8 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"bb" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate1) -"bc" = ( -/obj/machinery/porta_turret{ - dir = 8; - set_obj_flags = "EMAGGED"; - installation = /obj/item/gun/energy/lasercannon - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate2) -"bd" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"be" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/suit/space/hardsuit/syndi, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bf" = ( -/obj/structure/table/reinforced, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bg" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/gloves/tackler/combat/insulated, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bh" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bi" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/head/helmet/swat, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"bj" = ( -/obj/machinery/computer/pod{ - dir = 1; - id = "spacebattlepod3"; - name = "Hull Door Control" - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"bk" = ( -/obj/machinery/door/poddoor{ - icon_state = "pdoor1"; - id = "spacebattlepod3"; - name = "Front Hull Door"; - opacity = 1 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate2) -"bl" = ( -/obj/structure/table/reinforced, -/obj/item/grenade/plastic/c4, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"bm" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bn" = ( -/obj/structure/table/reinforced, -/obj/item/grenade/plastic/c4, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bo" = ( -/obj/structure/table/reinforced, -/obj/item/grenade/spawnergrenade/manhacks, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bp" = ( -/obj/structure/table/reinforced, -/obj/item/restraints/handcuffs, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"br" = ( -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"bt" = ( -/obj/structure/table/reinforced, -/obj/item/melee/transforming/energy/sword/saber/red, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bu" = ( -/obj/machinery/computer/shuttle{ - dir = 1 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"bx" = ( -/obj/structure/table/reinforced, -/obj/item/clothing/head/helmet/swat, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"by" = ( -/obj/machinery/porta_turret{ - dir = 8; - set_obj_flags = "EMAGGED"; - installation = /obj/item/gun/energy/lasercannon - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate3) -"bA" = ( -/obj/structure/chair, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate2) -"bC" = ( -/obj/machinery/computer/shuttle{ - dir = 1 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"bG" = ( -/obj/machinery/porta_turret{ - dir = 8; - set_obj_flags = "EMAGGED"; - installation = /obj/item/gun/energy/lasercannon - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate1) -"bH" = ( -/turf/closed/wall/mineral/plastitanium{ - dir = 8; - icon_state = "diagonalWall3" - }, -/area/awaymission/spacebattle/cruiser) -"bI" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/cruiser) -"bJ" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"bK" = ( -/obj/structure/shuttle/engine/propulsion/left{ - dir = 1 - }, -/turf/open/space, -/area/awaymission/spacebattle/cruiser) -"bL" = ( -/turf/closed/wall/mineral/plastitanium{ - dir = 1; - icon_state = "diagonalWall3" - }, -/area/awaymission/spacebattle/cruiser) -"bM" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/cruiser) -"bN" = ( -/obj/structure/window/reinforced, -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"bO" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"bP" = ( -/obj/structure/window/reinforced, -/obj/structure/shuttle/engine/heater{ - dir = 1 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"bQ" = ( -/obj/structure/chair{ - dir = 4 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"bR" = ( -/obj/structure/chair{ - dir = 8 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"bS" = ( -/turf/closed/wall/mineral/titanium/overspace, -/area/awaymission/spacebattle/cruiser) -"bT" = ( -/turf/closed/wall/mineral/titanium, -/area/awaymission/spacebattle/cruiser) -"bX" = ( -/obj/structure/shuttle/engine/propulsion/burst/left{ - dir = 8 - }, -/turf/open/space, -/area/awaymission/spacebattle/cruiser) -"bY" = ( -/obj/structure/shuttle/engine/heater{ - dir = 8 - }, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"bZ" = ( -/obj/machinery/computer/telecomms/monitor{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ca" = ( -/turf/open/floor/plasteel{ - icon_state = "damaged5" - }, -/area/awaymission/spacebattle/cruiser) -"cb" = ( -/obj/machinery/computer/pod{ - dir = 1; - id = "spacebattlepod"; - name = "Hull Door Control" - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"cc" = ( -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cd" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cf" = ( -/obj/structure/shuttle/engine/propulsion{ - dir = 8 - }, -/turf/open/space, -/area/awaymission/spacebattle/cruiser) -"cg" = ( -/obj/structure/table/reinforced, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ci" = ( -/obj/machinery/door/poddoor/preopen{ - id = "spacebattlepod"; - name = "Front Hull Door" - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ck" = ( -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"cm" = ( -/turf/open/floor/plasteel{ - icon_state = "damaged4" - }, -/area/awaymission/spacebattle/cruiser) -"cn" = ( -/turf/open/floor/plasteel{ - icon_state = "damaged3" - }, -/area/awaymission/spacebattle/cruiser) -"cp" = ( -/turf/open/floor/plasteel{ - icon_state = "damaged1" - }, -/area/awaymission/spacebattle/cruiser) -"cq" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Rosen Miller"; - name = "Rosen Miller" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cr" = ( -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ct" = ( -/turf/closed/wall/mineral/titanium/nodiagonal, -/area/awaymission/spacebattle/cruiser) -"cv" = ( -/obj/machinery/power/smes/magical{ - desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."; - name = "power storage unit" - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cw" = ( -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/turf/open/floor/plasteel{ - icon_state = "damaged2" - }, -/area/awaymission/spacebattle/cruiser) -"cx" = ( -/obj/item/stack/sheet/metal, -/obj/item/ammo_casing/c10mm, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cy" = ( -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cz" = ( -/obj/structure/closet/cabinet, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cA" = ( -/obj/structure/bed, -/obj/item/bedsheet, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cB" = ( -/obj/machinery/vending/cigarette, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cC" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/food/snacks/sausage, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cD" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/food/condiment/enzyme, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cE" = ( -/obj/structure/table/reinforced, -/obj/item/kitchen/knife, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cF" = ( -/obj/structure/table/reinforced, -/obj/item/kitchen/rollingpin, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cG" = ( -/obj/structure/closet/secure_closet/freezer/kitchen, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cH" = ( -/obj/structure/closet/secure_closet/freezer/fridge, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cI" = ( -/obj/structure/table/reinforced, -/obj/machinery/microwave, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cJ" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"cK" = ( -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"cL" = ( -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cM" = ( -/obj/item/ammo_casing/c10mm, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cN" = ( -/turf/open/floor/plasteel{ - icon_state = "damaged2" - }, -/area/awaymission/spacebattle/cruiser) -"cO" = ( -/obj/effect/landmark/awaystart, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cP" = ( -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cQ" = ( -/obj/item/stack/sheet/metal, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cS" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Bill Sanchez"; - name = "Bill Sanchez" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"cT" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cU" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/food/snacks/fries, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cV" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/food/snacks/soup/stew, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cW" = ( -/obj/structure/table/reinforced, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"cY" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/end{ - dir = 1 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"cZ" = ( -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"da" = ( -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"db" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/spacebattle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"dc" = ( -/obj/machinery/computer/pod{ - dir = 1; - id = "spacebattlepod2"; - name = "Hull Door Control" - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"dd" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle{ - dir = 4 - }, -/obj/structure/window/reinforced, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"de" = ( -/obj/machinery/shieldgen{ - anchored = 1 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"df" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 8 - }, -/turf/open/space, -/area/awaymission/spacebattle/cruiser) -"dg" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "John Locke"; - name = "John Locke" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dh" = ( -/obj/structure/rack, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"di" = ( -/obj/structure/closet/secure_closet/engineering_electrical, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dj" = ( -/obj/structure/closet/secure_closet/engineering_welding, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dk" = ( -/obj/structure/closet/wardrobe/engineering_yellow, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dl" = ( -/obj/structure/closet/toolcloset, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dm" = ( -/obj/effect/mob_spawn/human/doctor{ - mob_name = "Daniel Kalla"; - name = "Daniel Kalla" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dn" = ( -/obj/effect/decal/cleanable/blood, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dr" = ( -/obj/machinery/door/poddoor/preopen{ - id = "spacebattlepod2"; - name = "Front Hull Door" - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"du" = ( -/obj/effect/decal/cleanable/blood, -/turf/closed/wall/mineral/titanium, -/area/awaymission/spacebattle/cruiser) -"dx" = ( -/obj/structure/chair, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dy" = ( -/obj/structure/rack, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dz" = ( -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dA" = ( -/obj/effect/landmark/awaystart, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dB" = ( -/obj/structure/closet/secure_closet/security, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dC" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dD" = ( -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"dE" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/directional{ - dir = 9 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"dF" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"dG" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/directional{ - dir = 1 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"dH" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/directional{ - dir = 5 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"dJ" = ( -/obj/item/stack/rods, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dK" = ( -/obj/mecha/medical/odysseus, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"dL" = ( -/obj/mecha/working/ripley/firefighter, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"dM" = ( -/obj/structure/closet/crate{ - name = "Gold Crate" - }, -/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"dN" = ( -/obj/machinery/mech_bay_recharge_port{ - icon_state = "recharge_port"; - dir = 2 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"dO" = ( -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"dP" = ( -/obj/structure/reagent_dispensers/fueltank, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"dQ" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dR" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/food/condiment/peppermill, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dS" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dT" = ( -/obj/structure/chair{ - dir = 8 - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dU" = ( -/obj/structure/rack, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dV" = ( -/obj/structure/closet/secure_closet/security, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dW" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"dX" = ( -/obj/effect/mob_spawn/human/engineer/rig{ - id_job = "Gunner"; - mob_name = "Andrew Thorn"; - name = "Andrew Thorn" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"dY" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle{ - dir = 4 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"dZ" = ( -/obj/machinery/porta_turret{ - dir = 8; - set_obj_flags = "EMAGGED"; - installation = /obj/item/gun/energy/lasercannon - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"ea" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Clay Dawson"; - name = "Clay Dawson" - }, -/turf/open/floor/plasteel{ - icon_state = "damaged5" - }, -/area/awaymission/spacebattle/cruiser) -"eb" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle{ - dir = 4 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ec" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ed" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ee" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ef" = ( -/mob/living/simple_animal/hostile/syndicate/melee/spacebattle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"eg" = ( -/obj/structure/closet/crate{ - name = "Gold Crate" - }, -/obj/item/mecha_parts/mecha_equipment/repair_droid, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"eh" = ( -/mob/living/simple_animal/hostile/syndicate/melee/spacebattle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"ei" = ( -/obj/structure/closet/l3closet/security, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ej" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ek" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/end, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"el" = ( -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"em" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"en" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"eo" = ( -/obj/machinery/gateway{ - dir = 4 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ep" = ( -/obj/structure/chair{ - dir = 1 - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"er" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate4) -"et" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"eu" = ( -/obj/machinery/gateway, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ev" = ( -/obj/machinery/gateway{ - dir = 6 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ew" = ( -/obj/structure/chair, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate3) -"ex" = ( -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ey" = ( -/obj/effect/mob_spawn/human/bridgeofficer{ - mob_name = "Davis Hume"; - name = "Davis Hume" - }, -/obj/item/gun/ballistic/shotgun/automatic/combat, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ez" = ( -/obj/item/ammo_casing/shotgun, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eA" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/spacebattle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"eC" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eD" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eE" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eG" = ( -/obj/structure/chair, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate1) -"eH" = ( -/obj/effect/mob_spawn/human/engineer/rig{ - id_job = "Gunner"; - mob_name = "Peter West"; - name = "Peter West" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"eK" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate4) -"eL" = ( -/obj/machinery/computer/shuttle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate4) -"eM" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eN" = ( -/obj/item/shield/energy, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eO" = ( -/obj/structure/chair{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eP" = ( -/obj/machinery/computer/med_data{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eR" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate4) -"eS" = ( -/obj/structure/chair{ - dir = 1 - }, -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate4) -"eT" = ( -/obj/structure/closet/crate, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"eU" = ( -/obj/structure/table/reinforced, -/obj/item/reagent_containers/food/condiment/saltshaker, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eV" = ( -/obj/structure/table/reinforced, -/obj/item/kitchen/fork, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eW" = ( -/obj/effect/mob_spawn/human/syndicatesoldier, -/obj/item/melee/transforming/energy/sword/saber/red, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eX" = ( -/obj/effect/mob_spawn/human/bridgeofficer{ - mob_name = "Kurt Kliest"; - name = "Kurt Kliest" - }, -/obj/item/gun/ballistic/shotgun/automatic/combat, -/obj/item/ammo_casing/shotgun, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eY" = ( -/obj/item/ammo_casing/shotgun, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"eZ" = ( -/obj/machinery/computer/crew{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fa" = ( -/obj/effect/mob_spawn/human/engineer/rig{ - id_job = "Gunner"; - mob_name = "Eric Abnett"; - name = "Eric Abnett" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fb" = ( -/obj/structure/closet/crate, -/obj/item/clothing/glasses/night, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"fc" = ( -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fd" = ( -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fe" = ( -/obj/structure/chair{ - dir = 4 - }, -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"ff" = ( -/obj/machinery/button/door{ - dir = 2; - id = "spacebattlestorage"; - name = "Secure Storage"; - pixel_x = 32 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fg" = ( -/obj/item/hand_labeler, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"fh" = ( -/obj/machinery/door/poddoor{ - id = "spacebattlestorage"; - name = "Secure Storage" - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fi" = ( -/obj/structure/chair{ - dir = 8 - }, -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"fj" = ( -/obj/machinery/computer/security/telescreen, -/turf/closed/wall/mineral/titanium, -/area/awaymission/spacebattle/cruiser) -"fl" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate4) -"fm" = ( -/mob/living/simple_animal/hostile/syndicate/melee/sword, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fn" = ( -/obj/structure/closet/crate, -/obj/item/light/tube, -/obj/item/light/tube, -/obj/item/light/tube, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"fo" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fp" = ( -/obj/effect/mob_spawn/human/syndicatesoldier, -/obj/item/gun/ballistic/automatic/c20r, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/effect/decal/cleanable/blood, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fq" = ( -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fr" = ( -/obj/effect/mob_spawn/human/nanotrasensoldier, -/obj/item/gun/ballistic/automatic/wt550, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fs" = ( -/obj/item/ammo_casing/shotgun, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ft" = ( -/obj/item/ammo_casing/a357, -/obj/item/ammo_casing/a357, -/obj/item/gun/ballistic/revolver/mateba, -/obj/effect/mob_spawn/human/commander{ - mob_name = "Aaron Bowden"; - name = "Aaron Bowden" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fu" = ( -/obj/structure/chair{ - dir = 4 - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fv" = ( -/obj/machinery/computer/shuttle{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fw" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "1" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fx" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "2" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fy" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "3" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fz" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "4" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fA" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "5" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fB" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "6" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fC" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "7" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fD" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "8" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fE" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "9" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fF" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "10" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fG" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "11" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fH" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "12" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fI" = ( -/obj/effect/landmark/awaystart, -/turf/open/floor/plasteel/cafeteria{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"fJ" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fK" = ( -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fL" = ( -/obj/item/stack/sheet/metal, -/turf/open/floor/plasteel{ - icon_state = "damaged1" - }, -/area/awaymission/spacebattle/cruiser) -"fM" = ( -/obj/item/ammo_casing/shotgun, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fN" = ( -/obj/effect/mob_spawn/human/syndicatesoldier, -/obj/item/gun/ballistic/automatic/c20r, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/effect/decal/cleanable/blood, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fO" = ( -/obj/item/ammo_casing/c10mm, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fP" = ( -/obj/machinery/computer/communications{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"fQ" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "13" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fR" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "14" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fS" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "15" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fT" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "16" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fU" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "17" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fV" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "18" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fW" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "19" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fX" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "20" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fY" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "21" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"fZ" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "22" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"ga" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "23" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gb" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "24" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gc" = ( -/obj/structure/closet/crate, -/obj/item/poster/random_contraband, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gd" = ( -/obj/effect/mob_spawn/human/bridgeofficer{ - mob_name = "Robert Faver"; - name = "Robert Faver" - }, -/obj/item/ammo_casing/shotgun, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ge" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "25" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gf" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "26" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gg" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "27" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gh" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "28" - }, -/obj/machinery/artillerycontrol, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gi" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "29" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gj" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "30" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gk" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "31" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gl" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "32" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gm" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "33" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gn" = ( -/obj/structure/artilleryplaceholder/decorative{ - icon_state = "34" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"go" = ( -/obj/structure/artilleryplaceholder{ - icon_state = "35" - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gp" = ( -/obj/structure/closet/crate/secure/weapon, -/obj/item/ammo_casing/a357, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gq" = ( -/obj/structure/closet/crate, -/obj/item/lipstick/black, -/obj/item/lipstick/jade, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gr" = ( -/obj/machinery/button/door{ - dir = 2; - id = "spacebattlestorage"; - name = "Secure Storage"; - pixel_x = 24 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gs" = ( -/obj/machinery/computer/operating, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"gt" = ( -/obj/structure/table/reinforced, -/obj/item/scalpel, -/obj/item/circular_saw, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"gu" = ( -/obj/structure/table/reinforced, -/obj/item/retractor, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"gv" = ( -/obj/structure/table/reinforced, -/obj/item/hemostat, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"gw" = ( -/obj/structure/table/reinforced, -/obj/item/scalpel, -/turf/open/floor/plasteel/white/side{ - dir = 2 - }, -/area/awaymission/spacebattle/cruiser) -"gx" = ( -/obj/machinery/vending/cigarette, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"gy" = ( -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"gz" = ( -/obj/item/gun/ballistic/shotgun/automatic/combat, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"gC" = ( -/obj/structure/closet/crate/secure/weapon, -/obj/item/gun/energy/laser, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gD" = ( -/obj/structure/closet/crate, -/obj/item/stack/spacecash/c10, -/obj/item/stack/spacecash/c10, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gF" = ( -/obj/effect/mob_spawn/human/doctor{ - mob_name = "Adam Smith"; - name = "Adam Smith" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"gG" = ( -/obj/structure/table/optable, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"gH" = ( -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"gI" = ( -/obj/machinery/vending/coffee, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"gJ" = ( -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"gK" = ( -/obj/machinery/computer/security{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"gL" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lamp/green, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"gM" = ( -/obj/structure/table/wood, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"gN" = ( -/obj/machinery/computer/secure_data{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"gO" = ( -/obj/effect/mob_spawn/human/engineer/rig{ - id_job = "Gunner"; - name = "Jeremy Tailor" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"gP" = ( -/obj/machinery/porta_turret{ - dir = 8; - set_obj_flags = "EMAGGED"; - installation = /obj/item/gun/energy/lasercannon - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate7) -"gR" = ( -/obj/structure/shuttle/engine/heater, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate4) -"gS" = ( -/obj/structure/reagent_dispensers/beerkeg, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gT" = ( -/obj/item/stack/ore/bananium, -/obj/item/stack/ore/bananium, -/obj/item/stack/ore/bananium, -/obj/item/stack/ore/bananium, -/obj/item/stack/ore/bananium, -/obj/structure/closet/crate, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"gU" = ( -/obj/machinery/computer/operating, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"gV" = ( -/obj/effect/mob_spawn/human/doctor{ - mob_name = "Allan Yoshimaru"; - name = "Allan Yoshimaru" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"gW" = ( -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"gX" = ( -/obj/structure/chair{ - dir = 8 - }, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"gY" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"gZ" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ha" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/end, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hc" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate7) -"hd" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/open/space, -/area/awaymission/spacebattle/syndicate4) -"he" = ( -/obj/item/pickaxe, -/obj/item/gun/energy/plasmacutter, -/obj/structure/closet/crate, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hf" = ( -/obj/item/circular_saw, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"hg" = ( -/obj/structure/table/wood, -/obj/item/paper_bin, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"hh" = ( -/obj/effect/mob_spawn/human/engineer/rig{ - id_job = "Gunner"; - mob_name = "Dan Hedricks"; - name = "Dan Hedricks" - }, -/obj/effect/decal/cleanable/blood, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"hi" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/end{ - dir = 1 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate7) -"hj" = ( -/obj/structure/table/reinforced, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate7) -"hk" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate7) -"hl" = ( -/obj/structure/shuttle/engine/heater{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate7) -"hm" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 4 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate7) -"hn" = ( -/obj/structure/closet/crate/large, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ho" = ( -/obj/structure/closet/crate/secure/plasma, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hp" = ( -/obj/structure/closet/crate/medical, -/obj/item/storage/firstaid/fire, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hq" = ( -/obj/structure/rack, -/obj/item/clothing/suit/space/hardsuit, -/obj/item/clothing/head/helmet/space/hardsuit, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"hr" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"hs" = ( -/obj/structure/girder, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ht" = ( -/turf/closed/wall/r_wall, -/area/awaymission/spacebattle/cruiser) -"hu" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle{ - dir = 4 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate7) -"hv" = ( -/obj/structure/shuttle/engine/propulsion/left{ - dir = 4 - }, -/turf/open/space, -/area/awaymission/spacebattle/syndicate7) -"hw" = ( -/obj/structure/closet/crate/large, -/mob/living/simple_animal/pet/dog/corgi/puppy, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hx" = ( -/obj/structure/closet/crate, -/obj/item/paint/anycolor, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hy" = ( -/obj/machinery/computer/mech_bay_power_console, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/cruiser) -"hz" = ( -/obj/structure/closet/crate/medical, -/obj/item/storage/firstaid/regular, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hA" = ( -/obj/structure/closet/crate/medical, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"hB" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"hC" = ( -/obj/structure/chair, -/obj/effect/landmark/awaystart, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"hD" = ( -/obj/structure/table/reinforced, -/obj/item/storage/firstaid/regular, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"hE" = ( -/obj/structure/table/wood, -/obj/item/instrument/violin, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"hF" = ( -/obj/item/stack/sheet/metal, -/turf/open/floor/plasteel{ - icon_state = "damaged3" - }, -/area/awaymission/spacebattle/cruiser) -"hI" = ( -/obj/structure/table/reinforced, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"hJ" = ( -/obj/structure/bed, -/obj/item/bedsheet/captain, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"hK" = ( -/obj/structure/closet/secure_closet/captains, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"hL" = ( -/obj/effect/mob_spawn/human/engineer{ - id_job = "Gunner"; - mob_name = "William Gannon"; - name = "William Gannon" - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"hM" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"hN" = ( -/obj/structure/rack, -/obj/structure/window/reinforced{ - dir = 8 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"hO" = ( -/obj/structure/rack, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"hP" = ( -/obj/structure/rack, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"hQ" = ( -/obj/item/stack/sheet/metal, -/turf/open/floor/plasteel{ - icon_state = "damaged4" - }, -/area/awaymission/spacebattle/cruiser) -"hS" = ( -/obj/machinery/computer/shuttle{ - dir = 4 - }, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate7) -"hT" = ( -/obj/structure/chair{ - dir = 8 - }, -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate7) -"hU" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate7) -"hV" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 4 - }, -/obj/item/bikehorn/rubberducky, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"hW" = ( -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"hX" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 8 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"hY" = ( -/obj/structure/toilet, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"hZ" = ( -/obj/structure/table/reinforced, -/obj/item/storage/firstaid/fire, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"ib" = ( -/obj/machinery/door/unpowered/shuttle, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"id" = ( -/obj/item/storage/firstaid/regular, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"ie" = ( -/obj/structure/table/reinforced, -/obj/item/storage/firstaid/o2, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"if" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 4 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"ig" = ( -/obj/machinery/shower{ - icon_state = "shower"; - dir = 8 - }, -/obj/item/soap, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"ih" = ( -/obj/structure/rack, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/item/gun/energy/laser, -/obj/item/gun/energy/laser, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"ii" = ( -/obj/effect/mob_spawn/human/doctor{ - mob_name = "Herbert West"; - name = "Herbert West" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"ij" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Carth Robinson"; - name = "Carth Robinson" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"ik" = ( -/obj/structure/rack, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"il" = ( -/obj/machinery/sleeper, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"im" = ( -/obj/machinery/sleep_console, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"io" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"ip" = ( -/obj/machinery/sleeper, -/turf/open/floor/plasteel/white/side{ - dir = 1 - }, -/area/awaymission/spacebattle/cruiser) -"iq" = ( -/obj/machinery/sleep_console, -/turf/open/floor/plasteel/white/side{ - dir = 1 - }, -/area/awaymission/spacebattle/cruiser) -"ir" = ( -/turf/open/floor/plasteel/white/side{ - dir = 1 - }, -/area/awaymission/spacebattle/cruiser) -"is" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Cyrion"; - name = "Cyrion" - }, -/obj/item/flamethrower/full, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"it" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/smg, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"iu" = ( -/obj/effect/mob_spawn/human/syndicatesoldier, -/obj/item/gun/ballistic/automatic/c20r, -/turf/open/floor/plasteel{ - icon_state = "damaged2" - }, -/area/awaymission/spacebattle/cruiser) -"iv" = ( -/obj/structure/shuttle/engine/propulsion/burst/right{ - dir = 8 - }, -/turf/open/space, -/area/awaymission/spacebattle/cruiser) -"iw" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Mercutio"; - name = "Mercutio" - }, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"ix" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) -"iy" = ( -/obj/effect/mob_spawn/human/syndicatesoldier, -/turf/open/space, -/area/space/nearstation) -"iz" = ( -/turf/closed/wall/mineral/plastitanium, -/area/space/nearstation) -"iB" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red/airless, -/area/space/nearstation) -"iC" = ( -/turf/open/floor/mineral/plastitanium/red/airless, -/area/space/nearstation) -"iD" = ( -/obj/effect/mob_spawn/human/syndicatesoldier, -/turf/open/floor/mineral/plastitanium/red/airless, -/area/space/nearstation) -"iE" = ( -/turf/closed/mineral/bananium, -/area/space/nearstation) -"iF" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating/airless, -/area/space/nearstation) -"iG" = ( -/obj/item/stack/rods, -/turf/open/floor/mineral/plastitanium/red/airless, -/area/space/nearstation) -"iI" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate5) -"iL" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate5) -"iM" = ( -/obj/machinery/computer/shuttle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate5) -"iP" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate5) -"iQ" = ( -/obj/structure/chair{ - dir = 1 - }, -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate5) -"iR" = ( -/obj/structure/shuttle/engine/heater, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/open/floor/plating/airless, -/area/space/nearstation) -"iS" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/open/space, -/area/space/nearstation) -"iT" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate5) -"iW" = ( -/obj/structure/shuttle/engine/heater, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate5) -"iX" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/open/space, -/area/awaymission/spacebattle/syndicate5) -"iZ" = ( -/turf/closed/wall/mineral/plastitanium, -/area/awaymission/spacebattle/syndicate6) -"jb" = ( -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate6) -"jc" = ( -/obj/machinery/computer/shuttle, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate6) -"jd" = ( -/obj/machinery/sleeper, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate6) -"je" = ( -/obj/structure/chair{ - dir = 1 - }, -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/mineral/plastitanium/red, -/area/awaymission/spacebattle/syndicate6) -"jf" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, -/area/awaymission/spacebattle/syndicate6) -"ji" = ( -/obj/structure/shuttle/engine/heater, -/obj/structure/window/reinforced{ - dir = 1 - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/syndicate6) -"jj" = ( -/obj/structure/shuttle/engine/propulsion, -/turf/open/space, -/area/awaymission/spacebattle/syndicate6) -"jk" = ( -/turf/open/floor/plating/asteroid/airless, -/area/space/nearstation) -"jl" = ( -/turf/closed/wall/mineral/plasma, -/area/awaymission/spacebattle/secret) -"jm" = ( -/turf/open/floor/plasteel/rockvault/alien, -/area/awaymission/spacebattle/secret) -"jn" = ( -/obj/machinery/door/airlock/plasma, -/turf/closed/wall/mineral/plasma, -/area/awaymission/spacebattle/secret) -"jo" = ( -/obj/item/clothing/suit/space/hardsuit/wizard, -/turf/open/floor/plasteel/rockvault/alien, -/area/awaymission/spacebattle/secret) -"jp" = ( -/obj/mecha/combat/gygax, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jq" = ( -/obj/structure/closet/crate{ - name = "Gold Crate" - }, -/obj/item/gun/medbeam/mech, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jr" = ( -/mob/living/simple_animal/hostile/syndicate/melee/sword/space, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"js" = ( -/obj/structure/rack, -/obj/item/gun/ballistic/automatic/laser, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jt" = ( -/obj/structure/rack, -/obj/item/gun/energy/e_gun/advtaser, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"ju" = ( -/obj/structure/rack, -/obj/structure/window/reinforced, -/obj/item/gun/energy/laser, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jv" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jw" = ( -/obj/structure/table/reinforced, -/obj/machinery/button/door{ - dir = 2; - id = "spacebattlearmory"; - name = "Weapon Cache" - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"jx" = ( -/obj/structure/table/reinforced, -/obj/machinery/button/door{ - dir = 2; - id = "spacebattlearmory2"; - name = "Weapon Cache" - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"jy" = ( -/obj/structure/table/reinforced, -/obj/machinery/button/door{ - dir = 2; - id = "spacebattlearmory1"; - name = "Weapon Cache" - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"jz" = ( -/mob/living/simple_animal/hostile/syndicate/mecha_pilot{ - spawn_mecha_type = /obj/mecha/combat/gygax/dark/loaded - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"jA" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged/smg, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jB" = ( -/obj/structure/rack, -/obj/structure/window/reinforced, -/obj/item/gun/energy/e_gun/advtaser, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jC" = ( -/obj/structure/chair{ - dir = 8 - }, -/obj/effect/landmark/awaystart, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"jD" = ( -/obj/structure/barricade/security, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jE" = ( -/obj/structure/closet/crate, -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jF" = ( -/obj/structure/closet/crate, -/obj/item/ammo_box/magazine/recharge, -/obj/item/ammo_box/magazine/recharge, -/obj/item/ammo_box/magazine/recharge, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jG" = ( -/obj/machinery/door/poddoor{ - id = "spacebattlearmory1"; - name = "Secure Cache 1" - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jH" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jI" = ( -/obj/structure/closet/crate, -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jJ" = ( -/obj/structure/closet/crate, -/obj/effect/spawner/lootdrop/armory_contraband, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jL" = ( -/obj/machinery/door/poddoor{ - id = "spacebattlearmory"; - name = "Secure Armory" - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jM" = ( -/obj/effect/mob_spawn/human/bridgeofficer{ - mob_name = "Walter Strider"; - name = "Walter Strider" - }, -/obj/item/gun/ballistic/shotgun/automatic/combat, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel{ - icon_state = "damaged3" - }, -/area/awaymission/spacebattle/cruiser) -"jN" = ( -/obj/structure/closet/crate, -/obj/item/ammo_box/magazine/recharge, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"jO" = ( -/obj/item/ammo_casing/shotgun, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/item/stack/sheet/metal, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"jP" = ( -/obj/structure/closet/crate/internals, -/obj/item/storage/firstaid/o2, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jQ" = ( -/obj/machinery/door/poddoor{ - id = "spacebattlearmory2"; - name = "Secure Cache 2" - }, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jR" = ( -/obj/item/stack/sheet/metal, -/turf/open/floor/wood, -/area/awaymission/spacebattle/cruiser) -"jS" = ( -/turf/open/floor/plasteel/airless, -/area/awaymission/spacebattle/cruiser) -"jT" = ( -/obj/item/stack/sheet/metal, -/turf/open/floor/plasteel/airless, -/area/awaymission/spacebattle/cruiser) -"jU" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/smg/space, -/turf/open/floor/plasteel/airless, -/area/awaymission/spacebattle/cruiser) -"jV" = ( -/mob/living/simple_animal/hostile/syndicate/mecha_pilot{ - spawn_mecha_type = /obj/mecha/combat/gygax/dark/loaded - }, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"jW" = ( -/mob/living/simple_animal/hostile/syndicate/mecha_pilot{ - spawn_mecha_type = /obj/mecha/combat/gygax/dark/loaded - }, -/turf/open/floor/plasteel/airless, -/area/awaymission/spacebattle/cruiser) -"jX" = ( -/obj/structure/rack, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/item/gun/energy/pulse/pistol/loyalpin, -/obj/item/gun/energy/pulse/pistol/loyalpin, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"jY" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/smg/space, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"jZ" = ( -/obj/structure/rack, -/obj/item/gun/ballistic/automatic/laser, -/obj/item/gun/ballistic/automatic/laser, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"ka" = ( -/obj/effect/spawner/lootdrop/crate_spawner, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"kb" = ( -/obj/structure/girder, -/turf/open/floor/plating/airless, -/area/awaymission/spacebattle/cruiser) -"kc" = ( -/obj/structure/rack, -/obj/item/gun/energy/laser/scatter, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"kd" = ( -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"ke" = ( -/obj/item/stack/rods, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kf" = ( -/obj/structure/rack, -/obj/structure/window/reinforced, -/obj/item/gun/energy/laser/scatter, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"kg" = ( -/obj/structure/rack, -/obj/structure/window/reinforced, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"kh" = ( -/mob/living/simple_animal/hostile/syndicate, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"ki" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/end{ - dir = 1 - }, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kj" = ( -/turf/open/floor/mech_bay_recharge_floor, -/area/awaymission/spacebattle/cruiser) -"kk" = ( -/obj/item/shard, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kl" = ( -/obj/effect/mob_spawn/human/nanotrasensoldier, -/obj/item/gun/ballistic/automatic/wt550, -/obj/effect/decal/cleanable/blood, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"km" = ( -/obj/structure/closet/crate{ - name = "Gold Crate" - }, -/obj/item/mecha_parts/mecha_equipment/drill, -/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"kn" = ( -/obj/machinery/computer/mech_bay_power_console{ - dir = 8 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"kp" = ( -/obj/structure/rack, -/obj/item/gun/energy/xray, -/turf/open/floor/engine, -/area/awaymission/spacebattle/cruiser) -"kq" = ( -/obj/machinery/porta_turret{ - dir = 8; - set_obj_flags = "EMAGGED"; - installation = /obj/item/gun/energy/lasercannon - }, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kr" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle{ - dir = 4 - }, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"ks" = ( -/obj/machinery/mech_bay_recharge_port{ - icon_state = "recharge_port"; - dir = 2 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"kt" = ( -/obj/structure/barricade/security, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"ku" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/smg, -/turf/open/floor/plasteel/white, -/area/awaymission/spacebattle/cruiser) -"kv" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/middle, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kw" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/directional{ - dir = 10 - }, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kx" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/directional, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"ky" = ( -/obj/structure/grille, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kz" = ( -/obj/effect/spawner/structure/window/hollow/reinforced/directional{ - dir = 6 - }, -/turf/open/floor/engine/vacuum, -/area/awaymission/spacebattle/cruiser) -"kA" = ( -/obj/effect/mob_spawn/human/engineer{ - mob_name = "Javier Wismer"; - name = "Javier Wismer" - }, -/turf/open/floor/plasteel/airless, -/area/awaymission/spacebattle/cruiser) -"kB" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/electrical, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"kC" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical, -/obj/item/storage/toolbox/electrical, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"kD" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical, -/turf/open/floor/plasteel, -/area/awaymission/spacebattle/cruiser) -"kE" = ( -/obj/item/shard, -/turf/open/space, -/area/space/nearstation) -"kF" = ( -/obj/item/stack/rods, -/turf/open/space, -/area/space/nearstation) -"kG" = ( -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/obj/item/ammo_casing/c10mm, -/mob/living/simple_animal/hostile/syndicate/ranged/smg, -/turf/open/floor/plasteel/freezer, -/area/awaymission/spacebattle/cruiser) -"kH" = ( -/obj/machinery/mech_bay_recharge_port{ - icon_state = "recharge_port"; - dir = 1 - }, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"kI" = ( -/obj/item/stack/sheet/metal, -/turf/open/space, -/area/space/nearstation) -"kJ" = ( -/obj/item/shard, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) -"kK" = ( -/obj/structure/lattice, -/obj/item/stack/rods, -/turf/open/space, -/area/space/nearstation) -"kL" = ( -/obj/structure/closet/crate, -/obj/item/stock_parts/cell/high, -/obj/item/stock_parts/cell/high, -/obj/item/mecha_parts/mecha_equipment/weapon/energy/ion, -/turf/open/floor/plating, -/area/awaymission/spacebattle/cruiser) -"vw" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/syndicate5) -"zS" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/syndicate6) -"BO" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/syndicate2) -"Dv" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/syndicate3) -"UZ" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/syndicate1) -"Wv" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/cruiser) -"Yq" = ( -/turf/closed/wall/mineral/plastitanium/nodiagonal, -/area/awaymission/spacebattle/syndicate4) - -(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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -aa -"} -(2,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -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 -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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -aa -aa -aa -"} -(5,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(6,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(7,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(8,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(9,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(10,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(11,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(12,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(13,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(14,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 -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 -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(15,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(16,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(17,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(18,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(19,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(20,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(21,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(22,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(23,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(24,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(25,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(26,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(27,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(28,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(29,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(30,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(31,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(32,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -"} -(33,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(34,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 -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 -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(35,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 -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 -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(36,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 -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 -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(37,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 -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 -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(38,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 -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 -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(39,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 -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 -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(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 -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 -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(41,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(42,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(43,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(44,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(45,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(46,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(47,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(48,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 -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(49,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(50,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -er -er -fl -fl -er -er -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(51,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -Yq -eK -eK -eK -eK -eK -eR -Yq -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(52,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -Yq -eR -eK -eK -eK -eK -eK -eK -eR -Yq -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(53,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -eK -eK -eK -eK -eK -eK -eK -eK -eK -eR -er -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(54,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -eL -eS -eK -eK -eK -eK -eK -eK -eK -eK -gR -hd -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(55,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -eK -eK -eK -eK -eK -eK -eK -eK -eK -eK -gR -hd -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(56,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -eK -eK -eK -eK -eK -eK -eK -eK -eK -eK -gR -hd -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(57,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -eL -eS -eK -eK -eK -eK -eK -eK -eK -eK -gR -hd -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(58,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -eK -eK -eK -eK -eK -eK -eK -eK -eK -eR -er -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(59,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -Yq -eR -eK -eK -eK -eK -eK -eK -eR -Yq -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(60,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -Yq -eK -eK -eK -eK -eK -eR -Yq -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(61,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -er -er -er -fl -fl -er -er -er -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(62,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(63,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(64,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(65,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(66,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -ab -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(67,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(68,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(69,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(70,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(71,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(72,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aU -aU -aU -bb -bb -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iI -iI -iT -iT -iI -iI -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(73,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aP -aV -aY -aY -aY -be -aU -bh -aY -bh -aY -bh -aY -aU -bf -bo -bo -bf -bf -bx -aU -bh -bh -UZ -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bX -cf -cf -cf -cf -cf -cf -cf -df -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bX -cf -cf -cf -cf -cf -cf -cf -iv -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -vw -iL -iL -iL -iL -iL -iP -vw -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(74,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -ck -aY -aY -be -aU -aY -aY -aY -ck -aY -aY -aU -bf -aY -aY -aY -aY -aY -aU -aY -aY -eG -bC -aU -aU -aU -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -bY -bY -bY -bY -bY -bY -bY -bY -bY -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -bY -bY -bY -bY -bY -bY -bY -bY -bY -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -vw -iP -iL -iL -iL -iL -iL -iL -iP -vw -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(75,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -aY -aY -aY -aY -aY -aY -aU -bf -aY -ck -aY -aY -aY -aU -aY -aY -eG -bC -aU -aU -aU -aU -bG -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -bZ -cg -cg -cv -cv -cv -cg -cg -cg -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cg -cg -cg -cv -cv -cv -cg -cg -bZ -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iL -iL -iL -iL -iL -iL -iL -iL -iL -iP -iI -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(76,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -aY -aY -aY -aY -aY -aY -aU -bf -aY -aY -aY -aY -aY -aU -aY -aY -aY -UZ -aU -aU -aU -aU -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -ca -cc -cc -cc -cc -cc -cc -cQ -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -iw -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iM -iQ -iL -iL -iL -iL -iL -iL -iL -iL -iW -iX -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(77,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -bh -aY -bh -aY -aY -aY -aU -bf -bp -bf -bf -aY -aY -aU -aY -aY -aY -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bH -bM -bM -bM -bM -bM -bM -bM -bM -bM -cc -cp -cc -cr -kl -cc -dg -du -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iL -iL -iL -iL -iL -iL -iL -iL -iL -iL -iW -iX -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(78,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -aU -aU -aU -aU -bm -bm -aU -aU -aU -aU -aU -bm -bm -aU -aY -aY -aY -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bI -bN -bQ -fe -bQ -bQ -bO -bO -cb -Wv -bM -cc -cL -cc -cr -cr -cr -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iL -iL -iL -iL -iL -iL -iL -iL -iL -iL -iW -iX -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(79,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -aY -aY -aY -aY -aY -aY -aY -aY -aY -eh -aY -aY -aY -aY -aY -aY -aY -aY -aY -bb -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bJ -bO -bO -bO -bO -bO -bO -bO -bO -ci -cm -cw -cp -cc -cQ -cc -dh -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -kB -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iM -iQ -iL -iL -iL -iL -iL -iL -iL -iL -iW -iX -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(80,1,1) = {" -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -aY -aY -aY -aY -aY -aY -aY -aY -aY -eh -aY -aY -aY -aY -aY -aY -aY -aY -aY -bb -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bJ -bO -bO -bO -bO -bO -hy -bO -bO -ci -cn -cm -cM -cc -cc -cc -dh -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -kD -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iL -iL -iL -iL -iL -iL -iL -iL -iL -iP -iI -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(81,1,1) = {" -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -aU -aU -aU -aU -bm -bm -aU -aU -aU -aU -aU -bm -bm -aU -aY -aY -aY -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bK -bP -bR -fi -bR -bR -dN -bO -bO -Wv -bM -cx -cN -cM -cc -cc -dh -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -kC -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -vw -iP -iL -iL -iL -iL -iL -iL -iP -vw -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(82,1,1) = {" -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bg -aU -bh -aY -bh -aY -aY -aY -aU -bf -bf -bf -bf -aY -aY -aU -aY -aY -aY -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bL -bM -bM -bM -bM -bM -bM -bM -bM -bM -cp -cc -cN -cc -cc -cr -di -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -di -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -vw -iL -iL -iL -iL -iL -iP -vw -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(83,1,1) = {" -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -aY -aY -aY -aY -aY -aY -aU -bf -aY -aY -aY -aY -aY -aU -aY -aY -aY -UZ -aU -aU -aU -aU -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cS -cc -di -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -di -cc -cc -cc -cc -cr -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iI -iI -iI -iT -iT -iI -iI -iI -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(84,1,1) = {" -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -ck -aY -bf -aU -aY -aY -ck -aY -aY -aY -aU -bn -aY -aY -aY -eA -aY -aU -aY -aY -eG -bC -aU -aU -aU -aU -bG -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cL -cQ -cc -cc -dj -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -ht -dj -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(85,1,1) = {" -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aQ -aV -aY -aY -aY -bf -aU -aY -aY -aY -aY -aY -aY -aU -bn -aY -aY -aY -aY -aY -aU -aY -aY -eG -bC -aU -aU -aU -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -kl -cy -cM -cc -cc -cc -dj -ht -el -ih -js -ju -jA -jD -ht -el -el -el -el -ht -jD -jA -ik -kc -kf -el -ht -dj -cc -cc -cc -cc -cc -is -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -"} -(86,1,1) = {" -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aR -aV -aY -aY -aY -bf -aU -bh -aY -bh -aY -bh -aY -aU -bf -bf -bf -bt -bf -bf -aU -bh -bh -UZ -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cr -cc -cc -cc -cc -cc -cc -dk -ht -el -el -el -el -el -jD -jG -el -el -el -el -jQ -jD -el -el -el -el -el -ht -dk -cc -cc -cc -cc -cc -cc -it -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -"} -(87,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aU -aU -aU -bb -bb -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -aU -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -dk -ht -hN -el -el -el -jA -jD -ht -el -el -el -el -ht -jD -jA -el -el -el -hN -ht -dk -cc -cc -cc -cc -cc -cc -cc -cL -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(88,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cO -cO -cO -dk -ht -hP -el -el -el -el -el -ht -el -el -el -el -ht -el -el -el -el -el -kp -ht -dk -cc -cc -cc -cc -cc -cN -cc -cL -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(89,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cr -cc -cO -cO -cO -dl -ht -hO -el -el -el -el -el -ht -el -el -el -el -ht -el -el -el -el -el -hO -ht -dl -cc -cc -cc -cc -fm -cM -cN -cN -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(90,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cq -cc -cc -cc -cc -cc -dl -ht -el -el -el -el -el -el -ht -jH -el -el -jH -ht -el -el -el -el -el -el -ht -dl -cc -cc -cc -cc -cc -cc -iu -cp -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(91,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cr -cc -cc -cc -cc -cc -dl -ht -el -ik -jt -jt -jB -el -ht -jD -jD -jD -jD -ht -el -jX -jZ -hP -kg -el -ht -dl -cc -cc -cc -cc -cc -cp -cN -cN -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(92,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cd -cd -bT -bT -bT -bT -bT -bT -bT -ht -ht -ht -ht -ht -ht -ht -ht -ht -jL -jL -ht -ht -ht -ht -ht -ht -ht -ht -ht -bT -bT -bT -bT -bT -bT -bT -cd -cd -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(93,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cz -cz -cz -cz -cz -cz -bT -cK -cK -cK -cK -cK -jE -jE -jI -el -el -jP -gp -gC -gC -gS -gS -hn -hw -bT -hV -hW -if -hW -if -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(94,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -cc -cc -cc -bT -cK -ec -em -et -cK -cK -cK -el -el -el -el -cK -cK -cK -gS -gS -hn -hn -bT -hW -hW -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(95,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cA -cc -cA -cc -cA -cc -bT -cK -ed -en -eu -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -gT -he -hn -hn -bT -hX -hW -ig -hW -hX -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(96,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -cc -cc -cc -bT -cK -ee -eo -ev -cK -jF -fb -jE -jE -eT -gc -gq -gD -cK -ka -ka -hn -hn -bT -bT -bT -bT -du -bT -ib -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -iZ -iZ -jf -jf -iZ -iZ -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(97,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cA -cc -cA -cc -cA -cc -bT -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -ka -ka -hn -hn -bT -hY -ib -hW -ij -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -zS -jb -jb -jb -jb -jb -jd -zS -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(98,1,1) = {" -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -cc -cc -cc -bT -dK -jp -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -ho -ho -bT -bT -bT -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -zS -jd -jb -jb -jb -jb -jb -jb -jd -zS -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(99,1,1) = {" -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cA -cO -cA -cc -cA -cc -bT -dL -dL -cK -cK -cK -eT -eT -jJ -fn -jN -jN -eT -eT -cK -cK -cK -ho -ho -bT -hY -ib -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -jb -jb -jb -jb -jb -jb -jb -jb -jb -jd -iZ -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(100,1,1) = {" -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -cc -cc -cc -bT -dM -jq -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -eT -hx -bT -bT -bT -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -jc -je -jb -jb -jb -jb -jb -jb -jb -jb -ji -jj -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(101,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cA -cc -cA -cc -cA -cc -bT -km -eg -cK -cK -cK -cK -cK -fg -cK -cK -cK -cK -cK -jv -cK -cK -eT -kL -bT -hY -ib -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -jb -jb -jb -jb -jb -jb -jb -jb -jb -jb -ji -jj -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(102,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -cc -cc -cc -bT -dO -dO -cK -jv -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -jJ -eT -bT -bT -bT -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -jb -jb -jb -jb -jb -jb -jb -jb -jb -jb -ji -jj -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(103,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cA -cc -cA -cc -cA -cr -bT -dO -dO -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -eT -hz -bT -hY -ib -hW -kG -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -jc -je -jb -jb -jb -jb -jb -jb -jb -jb -ji -jj -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -"} -(104,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -cc -cc -dm -bT -dP -dP -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -cK -hp -hz -bT -bT -bT -hW -hW -hW -hW -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -jb -jb -jb -jb -jb -jb -jb -jb -jb -jd -iZ -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(105,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cB -cc -cc -cc -cc -cr -bT -dP -dP -cK -kn -ks -kj -cK -kt -kt -kt -kt -gr -kj -kH -kn -cK -hp -hA -bT -hY -ib -hW -hW -io -io -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -iE -aa -iE -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -zS -jd -jb -jb -jb -jb -jb -jb -jd -zS -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(106,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -ct -bT -bT -cd -cd -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -fh -fh -fh -fh -bT -du -bT -bT -bT -bT -bT -bT -bT -bT -cd -cd -bT -bT -ct -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -zS -jb -jb -jb -jb -jb -jd -zS -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(107,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -fm -cc -cc -cc -cc -cc -cc -cc -cc -fr -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -gF -cr -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -fm -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iZ -iZ -iZ -jf -jf -iZ -iZ -iZ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(108,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -fm -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -iE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(109,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -ct -bT -bT -bT -bT -bT -bT -cd -cd -bT -bT -bT -bT -bT -bT -ct -cc -cc -ct -bT -bT -bT -bT -bT -bT -hB -hB -bT -bT -bT -bT -bT -bT -ct -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -iE -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(110,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cC -cP -cP -bT -da -da -da -da -da -da -da -dQ -dQ -da -bT -cc -cc -bT -gs -gG -gH -gU -gG -gH -gH -gH -gH -gH -gH -il -gH -ip -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -iE -iE -iE -iE -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(111,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cD -cP -cP -cT -da -da -da -da -da -da -dx -dS -eU -ep -bT -cc -cc -bT -gt -gH -gH -gH -gH -gH -gH -gH -gH -kh -gH -im -gH -iq -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iE -aa -aa -aa -aa -aa -iE -iE -iE -iE -aa -aa -iE -iE -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(112,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cE -cP -fI -bT -da -dn -da -da -da -da -dx -dS -dS -ep -bT -cc -cc -bT -gt -gH -gH -gH -gH -gH -gH -gH -gH -gH -gH -gH -gH -ir -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -iE -iE -iE -iE -aa -aa -iE -iE -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(113,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cF -cP -cP -cU -da -dn -dn -da -da -da -da -jC -jC -da -bT -cc -cc -bT -gu -gH -gH -gH -gH -gH -gH -ku -gH -gH -gH -il -gH -ip -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(114,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cG -cP -cP -cU -da -da -da -dQ -dQ -da -da -dQ -dQ -da -bT -cc -cc -bT -gv -gH -gH -gV -hf -gH -gH -gH -gH -gH -gH -im -gH -iq -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -iE -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(115,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cH -cP -cP -cV -da -da -hC -dR -dS -ep -dx -dR -dS -ep -bT -cc -cc -bT -gw -gH -gH -gW -gW -kh -gH -gH -gH -gH -ii -gH -gH -ir -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -iE -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(116,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cI -cP -cP -cW -da -da -hC -dS -dS -ep -dx -dS -eV -ep -bT -cc -cc -bT -gt -gH -gH -gH -gH -gH -gH -gH -gH -id -gW -il -gH -ip -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(117,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cI -cP -cP -cW -da -da -da -dT -dT -da -da -dT -dT -da -bT -cc -cc -bT -gs -gG -gH -gU -gG -gH -hD -hI -hZ -ie -gH -im -gH -iq -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(118,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -ct -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -ct -cc -cc -ct -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -bT -ct -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(119,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cn -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(120,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -it -cc -fL -cn -cn -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -jz -cc -cc -cc -cc -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(121,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bT -bT -bT -cJ -cJ -ct -cc -cc -ct -bT -bT -bT -bT -bT -cK -hs -bT -bT -cd -cd -bT -bT -bT -bT -bT -bT -bT -bT -bT -ct -cc -cc -ct -cJ -cJ -bT -bT -bT -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(122,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cK -cK -bT -cc -cc -bT -dy -dU -dU -dU -ex -cp -fL -fc -bT -fo -fJ -bT -gx -gI -gy -gy -gy -gy -hE -hJ -bT -cc -cc -bT -cK -cK -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(123,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cK -cK -bT -cc -cc -bT -dz -cc -cc -cc -ey -cQ -cc -fd -bT -fp -fK -bT -gy -gy -gy -gy -gy -gy -gy -gy -bT -cp -cc -bT -cK -cK -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(124,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cK -cK -bT -cc -cc -bT -dz -cc -cc -cc -ez -cc -cc -cp -cd -fq -jO -cd -jR -gy -gy -gy -gy -gy -gy -gy -cK -cp -cp -bT -cK -cK -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(125,1,1) = {" -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cK -cK -bT -cc -cc -bT -dA -cc -cc -cc -cc -cc -cQ -cn -hs -jM -cp -cK -gy -gy -gL -gM -hg -gy -gy -gy -hs -cQ -cc -bT -cK -cK -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(126,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cK -cK -bT -cc -cc -bT -dB -dV -ei -ei -cn -cm -cm -cn -cK -hF -fM -bT -gy -gy -gM -gX -gy -gy -gy -hK -bT -cc -cQ -bT -cK -cK -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(127,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cK -cK -bT -cc -cc -bT -bT -bT -bT -bT -bT -hs -cK -bT -ct -fo -fN -ct -bT -bT -bT -bT -bT -bT -bT -bT -bT -cc -cc -bT -cK -cK -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(128,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -cJ -cJ -bT -cc -cc -bT -dh -dh -dh -bT -eC -cn -fL -cp -ac -fs -fO -ac -eM -eM -eM -gY -bT -hq -dh -dh -bT -cp -cc -bT -cJ -cJ -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(129,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cm -cK -cm -cc -cc -bT -jw -eN -eW -cc -cL -cM -cc -cM -cc -cr -cc -gZ -bT -cc -cQ -cn -hs -cn -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(130,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -fL -cp -hs -cm -hQ -cc -bT -jy -cc -cc -cr -cM -cL -cM -cM -cc -cc -cc -gZ -bT -cc -cc -cp -bT -cn -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(131,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cp -hs -hF -cc -cc -bT -jx -cc -cc -cc -cc -cr -cc -gd -gz -cc -it -gZ -bT -cc -cc -hL -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(132,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -ah -ah -ak -ak -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cd -cc -cc -cc -bT -eD -cc -cc -cc -cc -cc -cc -eY -cc -cc -cc -gZ -bT -cc -cc -cc -cd -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(133,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ad -ai -aj -aj -aj -am -ah -ao -aj -ao -aj -ao -aj -ah -ar -an -an -an -at -an -ah -ao -ao -BO -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -bT -eD -cr -eX -ez -cc -cr -cc -cc -cc -cc -cc -gZ -bT -cc -cc -cc -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(134,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -am -ah -aj -aj -aj -aj -aj -aj -ah -an -aj -aj -aj -aj -aj -ah -aj -aj -bA -aK -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -bT -eD -cc -eY -cc -it -ft -cc -cc -cc -cc -cc -gZ -bT -cc -cc -cc -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(135,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -aj -aj -aG -aj -aj -aj -ah -an -aj -aj -al -aj -aj -ah -aj -aj -bA -aK -ah -ah -ah -ah -bc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cc -cc -cc -bT -eD -eO -eO -ff -eO -fu -eO -eO -cc -eO -eO -gZ -bT -cc -cc -cc -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(136,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -al -aj -an -ah -aj -aj -aj -aj -aj -aj -ah -an -aj -aj -aj -aj -aj -ah -aG -aj -aj -BO -ah -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -dC -dW -ej -bT -eE -eP -eZ -eE -fj -fv -fP -fj -eE -gK -gN -eE -bT -hr -dW -hM -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(137,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -ao -aj -ao -aj -aj -aj -ah -an -as -an -an -aj -aj -ah -aj -aj -aj -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -bT -cd -bT -bT -cY -eb -eb -eb -eb -eb -eb -eb -eb -eb -eb -ha -bT -bT -cd -bT -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(138,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -ah -ah -ah -ah -aq -aq -ah -ah -ah -ah -ah -aq -aq -ah -aj -aj -aj -ah -ad -aW -aZ -aZ -aZ -aZ -aZ -aj -bj -BO -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(139,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -aj -aj -aj -aj -aj -ap -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -ak -ak -aj -aj -aj -aj -aj -aj -aj -aj -bk -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -jr -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(140,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -aj -ap -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -ak -ak -aj -aj -aj -aj -aj -aj -aj -aj -bk -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -gO -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(141,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -ah -ah -ah -ah -aq -aq -ah -ah -ah -ah -ah -aq -aq -ah -aj -aj -aj -ah -af -aX -ba -ba -ba -ba -ba -aj -aj -BO -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fw -fQ -ge -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(142,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -ao -aj -ao -aj -aj -aj -ah -an -as -an -an -aj -aj -ah -aj -aj -aj -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -dD -dX -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fx -fR -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(143,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -al -an -ah -aj -aj -aj -aj -aj -aj -ah -as -aj -aj -aj -aj -aj -ah -aj -aj -aj -BO -ah -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -fa -cZ -cZ -fy -fS -gf -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(144,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -aj -aj -aj -aj -aj -aj -ah -an -aj -aj -aj -aG -aj -ah -aj -aj -bA -aK -ah -ah -ah -ah -bc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fz -fT -gg -cZ -cZ -cZ -cZ -cZ -cZ -jr -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(145,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -aj -aj -aj -an -ah -aj -aj -aj -al -aj -aj -ah -an -aj -aj -aj -aj -aj -ah -aj -aj -bA -aK -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -it -bT -cZ -cZ -jr -cZ -cZ -cZ -cZ -cZ -cZ -fA -fU -gh -cZ -jV -cZ -cZ -hh -dD -cZ -cZ -bT -it -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(146,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -af -ai -aj -aj -aj -an -ah -ao -aj -ao -aj -ao -aj -ah -an -an -an -an -an -aA -ah -ao -ao -BO -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fB -fV -gi -cZ -cZ -cZ -cZ -cZ -dD -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(147,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -ah -ah -ak -ak -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fC -fW -gj -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(148,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fD -fX -gk -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(149,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -dD -eH -dD -cZ -cZ -cZ -fE -fY -gl -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(150,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -dD -dD -cZ -cZ -cZ -fF -fZ -gm -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(151,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fG -ga -gn -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(152,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -fH -gb -go -cZ -cZ -jY -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(153,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(154,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -ct -bT -bT -bT -bT -bT -bT -bT -bT -ct -ab -ab -ct -bT -bT -bT -bT -bT -bT -bT -bT -ct -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(155,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cd -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -cd -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(156,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cd -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -cd -cc -cc -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(157,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bT -bT -bT -bT -bT -bT -bT -ct -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -ct -bT -bT -bT -bT -bT -bT -bT -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(158,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bT -bT -bT -bT -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -bT -bT -bT -bT -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(159,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ct -bT -bT -bT -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -bT -bT -bT -ct -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(160,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dE -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -ki -kr -kw -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(161,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -kd -kq -kv -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(162,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -ki -kr -kx -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(163,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jU -jS -bT -kd -kd -kq -kd -ab -ab -kE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(164,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cr -cc -bT -ab -ab -bT -jT -jS -jS -bT -kd -ki -kd -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(165,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -kl -cr -bT -ab -ab -bT -jS -jS -jS -bT -kd -kd -ix -kJ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(166,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jT -jS -kb -kd -kk -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(167,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -cZ -kd -kI -kF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -ix -iF -iF -iz -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(168,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -it -cc -bT -ab -ab -bT -jS -jW -jS -cZ -ke -ix -ab -ab -ab -ab -ab -ab -kE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -iC -iC -iC -iC -iC -iB -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(169,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -kb -kd -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iz -iB -iC -iC -iG -iC -iC -iC -iB -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(170,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jT -jS -kb -kd -ix -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iC -iD -iC -iC -iC -iC -iC -iB -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(171,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -cd -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -cd -kd -kJ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iC -iC -iC -iC -iC -iC -iC -iC -iR -iS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(172,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jU -jS -jS -bT -kd -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -iC -iC -iC -iC -iC -iC -iC -iR -iS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(173,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jT -jS -bT -kd -kK -ab -ab -ab -ab -kF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -ab -ab -ab -ix -iC -iC -iC -iC -iC -iC -iR -iS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(174,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -kd -ab -ab -kE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -ab -ix -iC -iC -iC -iC -iC -iR -iS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(175,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -kk -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iC -ix -iC -iC -iC -iC -iC -iB -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(176,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -ki -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iy -ab -ix -iB -iC -iC -iC -iG -iC -iC -iB -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(177,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -kd -kd -ky -ab -ab -kE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iz -iz -iC -iC -iC -iC -iC -iB -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(178,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -ki -kr -kx -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -iz -iz -iz -iF -iF -iz -iz -iz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(179,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -kd -kq -kv -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(180,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dG -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -ki -kr -kx -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ix -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(181,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dF -dZ -el -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -kd -kq -kv -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(182,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -dH -dY -ek -el -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -kd -ki -kr -kz -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(183,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ct -bT -bT -bT -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -bT -bT -bT -ct -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -"} -(184,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aB -aB -aB -aE -aE -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bT -bT -bT -bT -bT -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -bT -bT -bT -bT -bT -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(185,1,1) = {" -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aw -aC -aD -aD -aD -aI -aB -aT -aD -aT -aD -aT -aD -aB -aJ -aJ -bl -aJ -aJ -aJ -aB -aT -aT -Dv -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -bT -bT -bT -bT -bT -bT -bT -ct -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -ct -bT -bT -bT -bT -bT -bT -bT -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(186,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -br -aI -aB -aD -aD -aD -aD -aD -aD -aB -aJ -aD -aD -aD -aD -aD -aB -aD -aD -ew -bu -aB -aB -aB -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cQ -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(187,1,1) = {" -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aD -aD -aD -db -aD -aD -aB -aJ -aD -aD -aD -aD -aD -aB -aD -aD -ew -bu -aB -aB -aB -aB -by -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cm -cc -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(188,1,1) = {" -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aD -aD -aD -aD -aD -aD -aB -aJ -aD -aD -aD -ef -aD -aB -aD -aD -aD -Dv -aB -aB -aB -aB -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cm -cn -cp -cp -cn -cc -dJ -cc -cc -fr -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(189,1,1) = {" -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aT -aD -aT -aD -aD -aD -aB -aJ -aJ -aJ -aJ -aD -aD -aB -aD -ef -aD -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bH -bM -bM -bM -bM -bM -bM -bM -bM -bM -cm -it -cc -cc -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(190,1,1) = {" -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aB -aB -aB -aB -bd -bd -aB -aB -aB -aB -aB -bd -bd -aB -aD -aD -aD -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bI -bN -fe -bQ -bQ -bQ -bO -bO -dc -Wv -bM -cp -cc -cc -cQ -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jU -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(191,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bJ -bO -bO -bO -bO -bO -gJ -bO -bO -dr -cn -cp -cn -cc -jz -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -kA -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(192,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aD -aE -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bJ -bO -bO -bO -bO -bO -hy -bO -bO -dr -ca -ea -cc -cc -cc -cc -cc -cQ -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -"} -(193,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aB -aB -aB -aB -bd -bd -aB -aB -aB -aB -aB -bd -bd -aB -aD -aD -aD -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bK -bP -bR -bR -bR -bR -dN -bO -bO -Wv -bM -cc -ca -cc -cc -dJ -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(194,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aT -aD -aT -aD -aD -aD -aB -aJ -aJ -aJ -aJ -aD -aD -aB -aD -aD -aD -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bL -bM -bM -bM -bM -bM -bM -bM -bM -bM -cc -cn -cp -cQ -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(195,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -br -aJ -aB -aD -aD -aD -aD -aD -aD -aB -aJ -aD -aD -aD -aD -aD -aB -aD -db -aD -Dv -aB -aB -aB -aB -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cN -cc -cc -cc -cc -cc -it -cc -cc -cc -bT -ab -ab -bT -jS -jU -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(196,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aD -aD -aD -br -aD -aD -aB -aJ -aD -db -aD -aD -aD -aB -aD -aD -ew -bu -aB -aB -aB -aB -by -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cp -cc -cc -dJ -cc -cc -cc -cc -cc -cc -fr -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(197,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ax -aC -aD -aD -aD -aJ -aB -aD -aD -aD -aD -aD -aD -aB -aJ -aD -aD -aD -aD -aD -aB -aD -aD -ew -bu -aB -aB -aB -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -cc -bT -ab -ab -bT -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -jS -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -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 -aa -aa -aa -aa -"} -(198,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ay -aC -aD -aD -aD -aJ -aB -aT -aD -aT -aD -aT -aD -aB -bi -aJ -aJ -aJ -aJ -aJ -aB -aT -aT -Dv -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cY -dd -cJ -cY -eb -eb -eb -dd -cJ -cY -dd -bT -ab -ab -bT -cY -dd -cJ -cY -eb -eb -eb -dd -cJ -cY -dd -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -"} -(199,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aB -aB -aB -aE -aE -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -aB -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -ab -ab -bT -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -cZ -bT -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -"} -(200,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -bS -cZ -de -cZ -de -cZ -de -cZ -de -cZ -de -cZ -bS -ab -ab -bS -cZ -de -cZ -de -cZ -de -cZ -de -cZ -de -cZ -bS -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -"} -(201,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(202,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(203,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(204,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(205,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(206,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(207,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(208,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(209,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(210,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -"} -(211,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -"} -(212,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -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 -aa -aa -aa -aa -"} -(213,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -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 -aa -aa -aa -aa -"} -(214,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -"} -(215,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -"} -(216,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -"} -(217,1,1) = {" -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -"} -(218,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -"} -(219,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -"} -(220,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -"} -(221,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 -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -"} -(222,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 -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(223,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 -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(224,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 -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(225,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 -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(226,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 -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(227,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 -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(228,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 -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(229,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hi -hu -hu -hu -hu -hu -hu -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(230,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hj -hj -hj -hS -hj -hj -hj -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(231,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -gP -hc -hk -hk -hk -hT -hk -hk -hk -hc -gP -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(232,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hc -hk -hk -hk -hk -hk -hk -hk -hc -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(233,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hk -hk -hk -hk -hk -hk -hk -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(234,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hk -hk -hk -hk -hk -hk -hk -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(235,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hk -hk -hk -hk -hk -hk -hk -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(236,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hk -hk -hk -hk -hk -hk -hk -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(237,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hk -hk -hk -hk -hk -hk -hk -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(238,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hl -hl -hc -hU -hc -hl -hl -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -aa -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -aa -aa -aa -aa -aa -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(239,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -hc -hm -hv -hc -ab -hc -hm -hv -hc -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -aa -jk -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -aa -jl -jl -jl -jl -jl -jn -jl -jl -jl -jl -jl -aa -aa -aa -aa -aa -aa -"} -(240,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(241,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -aa -aa -aa -aa -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(242,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -aa -aa -jk -jk -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(243,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -aa -jk -jk -jk -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(244,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(245,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -jk -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(246,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -jk -jk -jk -jk -jk -jk -jk -jk -aa -aa -aa -jk -jk -jk -jk -aa -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(247,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -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 -aa -aa -aa -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(248,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(249,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -aa -aa -aa -aa -jl -jm -jm -jm -jm -jm -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(250,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -jl -jm -jm -jm -jm -jo -jm -jm -jm -jm -jl -aa -aa -aa -aa -aa -aa -"} -(251,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -jl -jl -jl -jl -jl -jl -jl -jl -jl -jl -jl -aa -aa -aa -aa -aa -aa -"} -(252,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -jk -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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -"} -(253,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -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 -"} -(254,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -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 -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 -"} -(255,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 -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -jk -jk -jk -jk -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 -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/RandomZLevels/away_mission/undergroundoutpost45.dmm b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm index 33fdb7a28d..78a656128c 100644 --- a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm +++ b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm @@ -261,9 +261,7 @@ /area/awaymission/undergroundoutpost45/central) "aO" = ( /obj/machinery/door/firedoor, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -423,7 +421,6 @@ /obj/effect/decal/cleanable/dirt, /obj/structure/closet/secure_closet{ icon_state = "sec"; - locked = 1; name = "security officer's locker"; req_access_txt = "201" }, @@ -626,8 +623,7 @@ /area/awaymission/undergroundoutpost45/central) "bB" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5; - level = 1 + dir = 5 }, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -652,8 +648,7 @@ /area/awaymission/undergroundoutpost45/central) "bD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10; - level = 1 + dir = 10 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -811,8 +806,7 @@ /area/awaymission/undergroundoutpost45/central) "bV" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10; - level = 1 + dir = 10 }, /turf/closed/wall, /area/awaymission/undergroundoutpost45/central) @@ -1260,7 +1254,6 @@ }, /obj/machinery/portable_atmospherics/scrubber, /obj/structure/window{ - icon_state = "window"; dir = 8 }, /turf/open/floor/plating{ @@ -1282,7 +1275,6 @@ }, /obj/structure/reagent_dispensers/fueltank, /obj/structure/window{ - icon_state = "window"; dir = 4 }, /turf/open/floor/plating{ @@ -1291,8 +1283,7 @@ /area/awaymission/undergroundoutpost45/central) "cV" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10; - level = 1 + dir = 10 }, /turf/closed/wall/rust, /area/awaymission/undergroundoutpost45/central) @@ -1428,7 +1419,6 @@ /area/awaymission/undergroundoutpost45/central) "dm" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /turf/open/floor/plasteel{ @@ -1444,13 +1434,11 @@ }, /area/awaymission/undergroundoutpost45/central) "do" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/green{ - dir = 2 - }, +/obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -1729,7 +1717,6 @@ dir = 4 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/effect/turf_decal/tile/green{ @@ -1858,9 +1845,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -2125,15 +2110,6 @@ icon_state = "platingdmg1" }, /area/awaymission/undergroundoutpost45/central) -"eu" = ( -/turf/open/floor/plating{ - initial_gas_mix = "co2=173.4;n2=135.1;plasma=229.8;TEMP=351.9"; - heat_capacity = 1e+006; - icon_plating = "asteroidplating"; - icon_state = "asteroidplating"; - temperature = 363.9 - }, -/area/awaymission/undergroundoutpost45/caves) "ev" = ( /obj/item/clothing/under/misc/pj/red, /obj/structure/closet/secure_closet{ @@ -2328,9 +2304,7 @@ /obj/machinery/door/firedoor, /obj/item/folder/red, /obj/machinery/door/window/southleft{ - base_state = "left"; dir = 8; - icon_state = "left"; name = "Security Checkpoint"; req_access_txt = "201" }, @@ -2369,9 +2343,7 @@ /obj/structure/table/reinforced, /obj/machinery/door/firedoor, /obj/machinery/door/window/southleft{ - base_state = "left"; dir = 4; - icon_state = "left"; name = "Hydroponics Desk"; req_access_txt = "201" }, @@ -2508,9 +2480,7 @@ }, /area/awaymission/undergroundoutpost45/central) "fb" = ( -/obj/effect/turf_decal/tile/green{ - dir = 2 - }, +/obj/effect/turf_decal/tile/green, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -2568,7 +2538,6 @@ network = list("uo45") }, /obj/machinery/power/apc/highcap/fifteen_k{ - dir = 2; locked = 0; name = "Hydroponics APC"; pixel_y = -25; @@ -2972,7 +2941,7 @@ }, /area/awaymission/undergroundoutpost45/central) "fT" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /obj/effect/decal/cleanable/dirt, @@ -3055,15 +3024,13 @@ /area/awaymission/undergroundoutpost45/central) "gc" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5; - level = 1 + dir = 5 }, /turf/closed/wall/r_wall, /area/awaymission/undergroundoutpost45/central) "gd" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10; - level = 1 + dir = 10 }, /turf/closed/wall/r_wall, /area/awaymission/undergroundoutpost45/central) @@ -3319,7 +3286,6 @@ amount = 23 }, /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/research) @@ -3327,7 +3293,6 @@ /obj/structure/table, /obj/item/storage/toolbox/mechanical, /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/research) @@ -3359,60 +3324,6 @@ icon_state = "platingdmg1" }, /area/awaymission/undergroundoutpost45/central) -"gR" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/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{ - heat_capacity = 1e+006 - }, -/area/awaymission/undergroundoutpost45/gateway) -"gS" = ( -/obj/machinery/gateway{ - 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/dark{ - heat_capacity = 1e+006 - }, -/area/awaymission/undergroundoutpost45/gateway) -"gT" = ( -/obj/machinery/gateway{ - 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/dark{ - heat_capacity = 1e+006 - }, -/area/awaymission/undergroundoutpost45/gateway) "gU" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating{ @@ -3452,7 +3363,6 @@ }, /obj/machinery/camera{ c_tag = "Research Lab"; - dir = 2; network = list("uo45","uo45r") }, /turf/open/floor/plasteel/white{ @@ -3461,7 +3371,6 @@ /area/awaymission/undergroundoutpost45/research) "gZ" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /turf/open/floor/plasteel/white{ @@ -3614,9 +3523,7 @@ }, /area/awaymission/undergroundoutpost45/crew_quarters) "ho" = ( -/obj/machinery/vending/boozeomat{ - req_access_txt = "0" - }, +/obj/machinery/vending/boozeomat, /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ dir = 1 @@ -3673,46 +3580,8 @@ heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/crew_quarters) -"ht" = ( -/obj/machinery/gateway{ - 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{ - heat_capacity = 1e+006 - }, -/area/awaymission/undergroundoutpost45/gateway) "hu" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, -/turf/open/floor/plasteel/dark{ - heat_capacity = 1e+006 - }, -/area/awaymission/undergroundoutpost45/gateway) -"hv" = ( -/obj/machinery/gateway{ - 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 - }, +/obj/machinery/gateway/away, /turf/open/floor/plasteel/dark{ heat_capacity = 1e+006 }, @@ -3997,26 +3866,7 @@ heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/central) -"hY" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/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{ - heat_capacity = 1e+006 - }, -/area/awaymission/undergroundoutpost45/gateway) "hZ" = ( -/obj/machinery/gateway, /obj/structure/cable{ icon_state = "0-2" }, @@ -4035,9 +3885,6 @@ }, /area/awaymission/undergroundoutpost45/gateway) "ia" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -4531,8 +4378,7 @@ /area/awaymission/undergroundoutpost45/gateway) "iX" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10; - level = 1 + dir = 10 }, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 @@ -4626,7 +4472,6 @@ /area/awaymission/undergroundoutpost45/crew_quarters) "jf" = ( /obj/structure/closet/secure_closet{ - icon_state = "secure"; locked = 0; name = "kitchen Cabinet"; req_access_txt = "201" @@ -5169,7 +5014,6 @@ /obj/effect/decal/cleanable/dirt, /obj/structure/closet/secure_closet{ icon_state = "rd"; - locked = 1; name = "research director's locker"; req_access_txt = "201" }, @@ -5207,7 +5051,7 @@ }, /area/awaymission/undergroundoutpost45/gateway) "kh" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /obj/effect/decal/cleanable/dirt, @@ -5934,7 +5778,6 @@ }, /obj/machinery/camera{ c_tag = "Gateway Ready Room"; - dir = 2; network = list("uo45","uo45r") }, /turf/open/floor/plasteel{ @@ -5971,7 +5814,6 @@ /obj/item/reagent_containers/spray/pepper, /obj/structure/closet/secure_closet{ icon_state = "sec"; - locked = 1; name = "security officer's locker"; req_access_txt = "201" }, @@ -6029,9 +5871,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6041,9 +5881,7 @@ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6064,9 +5902,7 @@ dir = 1; network = list("uo45","uo45r") }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6081,9 +5917,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6096,9 +5930,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6115,9 +5947,7 @@ name = "Research Division Access"; req_access_txt = "201" }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6130,9 +5960,7 @@ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6151,9 +5979,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6171,9 +5997,7 @@ pixel_y = -24 }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6183,7 +6007,6 @@ icon_state = "0-8" }, /obj/machinery/power/apc/highcap/fifteen_k{ - dir = 2; locked = 0; name = "UO45 Research Division APC"; pixel_y = -25; @@ -6196,9 +6019,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6211,9 +6032,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6234,9 +6053,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6245,17 +6062,13 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/research) "lM" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6270,9 +6083,7 @@ dir = 1; network = list("uo45","uo45r") }, -/obj/effect/turf_decal/tile/purple{ - dir = 2 - }, +/obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6408,7 +6219,6 @@ }, /obj/machinery/camera{ c_tag = "Engineering Secure Storage"; - dir = 2; network = list("uo45") }, /turf/open/floor/plating{ @@ -6472,7 +6282,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/portable_atmospherics/scrubber, /obj/structure/window{ - icon_state = "window"; dir = 4 }, /obj/effect/decal/cleanable/dirt, @@ -6547,9 +6356,7 @@ pixel_y = -32 }, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -6744,7 +6551,6 @@ "mE" = ( /obj/structure/cable, /obj/machinery/power/apc/highcap/fifteen_k{ - dir = 2; locked = 0; name = "UO45 Gateway APC"; pixel_y = -25; @@ -6867,7 +6673,7 @@ /area/awaymission/undergroundoutpost45/research) "mQ" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /turf/open/floor/plasteel/cafeteria{ @@ -7392,9 +7198,7 @@ /obj/structure/cable{ icon_state = "2-4" }, -/obj/effect/turf_decal/stripes/corner{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel/dark{ heat_capacity = 1e+006 }, @@ -7409,9 +7213,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/turf_decal/stripes/line{ - dir = 2 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/dark{ heat_capacity = 1e+006 }, @@ -7495,7 +7297,6 @@ }, /obj/machinery/computer/security/telescreen{ desc = "Used for monitoring the research division and the labs within."; - dir = 2; name = "research monitor"; network = list("uo45r") }, @@ -7687,7 +7488,6 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/machinery/camera{ c_tag = "Dormitories"; - dir = 2; network = list("uo45") }, /obj/effect/turf_decal/tile/neutral{ @@ -7943,8 +7743,7 @@ charge = 1.5e+006; input_level = 10000; inputting = 0; - output_level = 7000; - outputting = 1 + output_level = 7000 }, /turf/open/floor/plating{ heat_capacity = 1e+006 @@ -7956,8 +7755,7 @@ charge = 1.5e+006; input_level = 30000; inputting = 0; - output_level = 7000; - outputting = 1 + output_level = 7000 }, /turf/open/floor/plating{ heat_capacity = 1e+006 @@ -8091,9 +7889,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -8121,9 +7917,7 @@ "oJ" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -8164,9 +7958,7 @@ /area/awaymission/undergroundoutpost45/crew_quarters) "oM" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 2 - }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -8281,7 +8073,6 @@ dir = 1 }, /obj/machinery/power/port_gen/pacman{ - desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator" }, /obj/structure/cable{ @@ -8296,7 +8087,6 @@ dir = 1 }, /obj/machinery/power/port_gen/pacman/super{ - desc = "A portable generator for emergency backup power."; name = "S.U.P.E.R.P.A.C.M.A.N.-type portable generator" }, /obj/item/wrench, @@ -8315,7 +8105,6 @@ dir = 1 }, /obj/machinery/power/port_gen/pacman{ - desc = "A portable generator for emergency backup power."; name = "P.A.C.M.A.N.-type portable generator" }, /obj/structure/cable{ @@ -8471,7 +8260,7 @@ }, /area/awaymission/undergroundoutpost45/research) "pl" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /obj/effect/decal/cleanable/dirt, @@ -8676,7 +8465,6 @@ /area/awaymission/undergroundoutpost45/engineering) "pE" = ( /obj/machinery/atmospherics/components/unary/vent_pump/high_volume/siphon/atmos{ - dir = 2; icon_state = "in"; id_tag = "UO45_air_out"; name = "air out" @@ -8688,7 +8476,6 @@ /area/awaymission/undergroundoutpost45/engineering) "pF" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/atmos{ - dir = 2; id = "UO45_air_in" }, /turf/open/floor/engine/air, @@ -9012,7 +8799,6 @@ /obj/item/clothing/glasses/hud/health, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/white/corner{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/research) @@ -9025,7 +8811,6 @@ /obj/item/hand_labeler, /obj/item/clothing/neck/stethoscope, /turf/open/floor/plasteel/white/side{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/research) @@ -9248,7 +9033,6 @@ }, /obj/machinery/camera{ c_tag = "Atmospherics"; - dir = 2; network = list("uo45") }, /obj/structure/table, @@ -9257,7 +9041,6 @@ pixel_y = 5 }, /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/item/multitool, @@ -9303,21 +9086,15 @@ dir = 10 }, /obj/machinery/portable_atmospherics/scrubber, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) "qN" = ( /obj/machinery/portable_atmospherics/canister/air, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) @@ -9544,7 +9321,7 @@ }, /area/awaymission/undergroundoutpost45/engineering) "rk" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /obj/effect/turf_decal/tile/yellow{ @@ -9560,7 +9337,6 @@ /area/awaymission/undergroundoutpost45/engineering) "rl" = ( /obj/machinery/firealarm{ - dir = 2; pixel_y = 24 }, /obj/structure/tank_dispenser{ @@ -9643,7 +9419,6 @@ }, /obj/machinery/power/apc/highcap/fifteen_k{ dir = 8; - locked = 1; name = "UO45 Engineering APC"; pixel_x = -25; req_access = null; @@ -9683,7 +9458,6 @@ /obj/item/clothing/head/helmet, /obj/structure/closet/secure_closet{ icon_state = "sec"; - locked = 1; name = "security officer's locker"; req_access_txt = "201" }, @@ -9750,11 +9524,8 @@ "rx" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/machinery/portable_atmospherics/scrubber, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) @@ -10167,9 +9938,7 @@ name = "Privacy Shutters" }, /obj/machinery/door/window/southleft{ - base_state = "left"; dir = 4; - icon_state = "left"; name = "Engineering Reception"; req_access_txt = "201" }, @@ -10260,7 +10029,6 @@ "sj" = ( /obj/structure/cable, /obj/machinery/power/apc/highcap/fifteen_k{ - dir = 2; locked = 0; name = "UO45 Mining APC"; pixel_y = -25; @@ -10280,9 +10048,7 @@ }, /obj/item/storage/backpack/satchel/eng, /obj/item/clothing/gloves/fingerless, -/obj/effect/turf_decal/tile/brown{ - dir = 2 - }, +/obj/effect/turf_decal/tile/brown, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -10290,8 +10056,7 @@ "sk" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 8; - name = "Mix to Distro"; - on = 0 + name = "Mix to Distro" }, /turf/open/floor/plasteel{ heat_capacity = 1e+006 @@ -10955,9 +10720,7 @@ }, /area/awaymission/undergroundoutpost45/crew_quarters) "tv" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 2 - }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/machinery/portable_atmospherics/pump, /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -10969,9 +10732,7 @@ /area/awaymission/undergroundoutpost45/engineering) "tw" = ( /obj/machinery/light/small, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 2 - }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/structure/window/reinforced{ dir = 4; layer = 2.9 @@ -11145,8 +10906,7 @@ /area/awaymission/undergroundoutpost45/engineering) "tK" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5; - level = 1 + dir = 5 }, /turf/closed/wall/rust, /area/awaymission/undergroundoutpost45/research) @@ -11404,11 +11164,8 @@ dir = 1 }, /obj/machinery/portable_atmospherics/canister/air, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) @@ -11716,17 +11473,13 @@ }, /area/awaymission/undergroundoutpost45/research) "uL" = ( -/obj/machinery/atmospherics/components/binary/valve{ - dir = 2 - }, +/obj/machinery/atmospherics/components/binary/valve, /turf/open/floor/plating{ heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/research) "uM" = ( -/obj/machinery/atmospherics/components/binary/valve{ - dir = 2 - }, +/obj/machinery/atmospherics/components/binary/valve, /obj/effect/turf_decal/stripes/line{ dir = 4 }, @@ -11813,8 +11566,7 @@ /area/awaymission/undergroundoutpost45/engineering) "uV" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5; - level = 1 + dir = 5 }, /obj/structure/chair/office/dark{ dir = 8 @@ -12342,9 +12094,7 @@ /obj/structure/sign/warning/electricshock{ pixel_y = -32 }, -/obj/machinery/vending/engivend{ - req_access_txt = "0" - }, +/obj/machinery/vending/engivend, /obj/machinery/camera{ c_tag = "Engineering Foyer"; dir = 1; @@ -12402,11 +12152,8 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) @@ -12415,11 +12162,8 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) @@ -12428,11 +12172,8 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, -/obj/effect/turf_decal/bot{ - dir = 2 - }, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel{ - dir = 2; heat_capacity = 1e+006 }, /area/awaymission/undergroundoutpost45/engineering) @@ -12486,7 +12227,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ layer = 5 }, /obj/effect/decal/cleanable/dirt, @@ -13274,7 +13015,6 @@ /area/awaymission/undergroundoutpost45/engineering) "xl" = ( /obj/machinery/conveyor{ - dir = 2; id = "UO45_mining" }, /obj/effect/turf_decal/stripes/line{ @@ -13328,7 +13068,6 @@ /area/awaymission/undergroundoutpost45/mining) "xq" = ( /obj/machinery/conveyor{ - dir = 2; id = "UO45_mining" }, /obj/structure/sign/warning/nosmoking{ @@ -13383,8 +13122,7 @@ /area/awaymission/undergroundoutpost45/mining) "xw" = ( /obj/machinery/mineral/processing_unit{ - dir = 1; - output_dir = 2 + dir = 1 }, /obj/effect/turf_decal/stripes/line{ dir = 5 @@ -13468,7 +13206,6 @@ /area/awaymission/undergroundoutpost45/mining) "xE" = ( /obj/machinery/conveyor{ - dir = 2; id = "UO45_mining" }, /obj/machinery/light/small{ @@ -13604,7 +13341,6 @@ /area/awaymission/undergroundoutpost45/mining) "xS" = ( /obj/machinery/mech_bay_recharge_port{ - icon_state = "recharge_port"; dir = 8 }, /obj/structure/cable{ @@ -33348,9 +33084,9 @@ ad ad gv gJ -gR -ht -hY +ia +ia +ia it iO jh @@ -33605,7 +33341,7 @@ ad ad gv gJ -gS +ia hu hZ iu @@ -33862,8 +33598,8 @@ ad ad gw gJ -gT -hv +ia +ia ia iv iQ @@ -42626,7 +42362,7 @@ tT gy uN hH -eu +eJ eJ ad ad @@ -42883,7 +42619,7 @@ tU uw uO vk -eu +eJ eJ eJ ad @@ -43140,7 +42876,7 @@ tV ux uP hH -eu +eJ eJ eJ eJ @@ -48811,7 +48547,7 @@ ww xZ yc ww -eu +eJ eJ eJ eJ @@ -49068,7 +48804,7 @@ xX ya yd yf -eu +eJ eJ eJ eJ @@ -49325,7 +49061,7 @@ xY yb ye ww -eu +eJ eJ eJ eJ @@ -51326,9 +51062,9 @@ ad ad ad ad -eu -eu -eu +eJ +eJ +eJ fn eJ eJ diff --git a/_maps/RandomZLevels/away_mission/wildwest.dmm b/_maps/RandomZLevels/away_mission/wildwest.dmm index 76c59a8e1d..77d11a4552 100644 --- a/_maps/RandomZLevels/away_mission/wildwest.dmm +++ b/_maps/RandomZLevels/away_mission/wildwest.dmm @@ -50,73 +50,28 @@ /turf/open/floor/circuit/off, /area/awaymission/wildwest/vault) "an" = ( -/turf/open/floor/plasteel/cult{ - name = "engraved floor" - }, +/turf/open/floor/plasteel/cult, /area/awaymission/wildwest/vault) "ao" = ( /turf/open/floor/circuit/green/off, /area/awaymission/wildwest/vault) "ap" = ( -/obj/machinery/wish_granter_dark, +/obj/item/nullrod/claymore/glowing, /turf/open/floor/circuit/green/off, /area/awaymission/wildwest/vault) "aq" = ( /obj/structure/destructible/cult/pylon, /turf/open/floor/circuit/green/off, /area/awaymission/wildwest/vault) -"ar" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) -"as" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) -"at" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) -"au" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) -"av" = ( -/obj/machinery/gateway/centeraway{ - calibrated = 0 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) "aw" = ( -/obj/machinery/gateway{ - dir = 4 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) -"ax" = ( -/obj/machinery/gateway{ - dir = 10 - }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) -"ay" = ( -/obj/machinery/gateway, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) +/turf/open/floor/plating/ironsand{ + icon_state = "ironsand1" + }) "az" = ( -/obj/machinery/gateway{ - dir = 6 +/turf/open/floor/plating/ironsand{ + icon_state = "ironsand1" }, -/turf/open/floor/circuit/green/off, -/area/awaymission/wildwest/vault) +/area/awaymission/wildwest/mines) "aA" = ( /obj/effect/meatgrinder, /turf/open/floor/circuit/green/off, @@ -162,9 +117,7 @@ /area/awaymission/wildwest/vault) "aL" = ( /obj/item/paper/fluff/awaymissions/wildwest/grinder, -/turf/open/floor/plasteel/cult{ - name = "engraved floor" - }, +/turf/open/floor/plasteel/cult, /area/awaymission/wildwest/vault) "aM" = ( /turf/closed/mineral/silver, @@ -174,9 +127,7 @@ /area/awaymission/wildwest/mines) "aO" = ( /obj/effect/mob_spawn/human/corpse/syndicatecommando, -/turf/open/floor/plasteel/cult{ - name = "engraved floor" - }, +/turf/open/floor/plasteel/cult, /area/awaymission/wildwest/vault) "aP" = ( /obj/effect/decal/cleanable/blood/splatter, @@ -349,11 +300,6 @@ /obj/structure/bed, /turf/open/floor/wood, /area/awaymission/wildwest/mines) -"bC" = ( -/obj/structure/table/wood, -/obj/item/gun/ballistic, -/turf/open/floor/wood, -/area/awaymission/wildwest/mines) "bD" = ( /obj/structure/table/wood, /turf/open/floor/wood, @@ -595,17 +541,8 @@ dir = 5 }, /area/awaymission/wildwest/mines) -"ch" = ( -/obj/structure/table/wood, -/obj/item/gun/ballistic, -/turf/open/floor/plasteel/cafeteria{ - dir = 5 - }, -/area/awaymission/wildwest/mines) "ci" = ( -/obj/structure/mineral_door/wood{ - icon_state = "wood" - }, +/obj/structure/mineral_door/wood, /turf/open/floor/wood, /area/awaymission/wildwest/mines) "cj" = ( @@ -755,7 +692,7 @@ /area/awaymission/wildwest/mines) "cL" = ( /obj/structure/table/wood, -/obj/item/twohanded/dualsaber, +/obj/item/nullrod/claymore/saber/red, /turf/open/floor/wood, /area/awaymission/wildwest/gov) "cM" = ( @@ -767,9 +704,7 @@ /turf/open/floor/wood, /area/awaymission/wildwest/gov) "cO" = ( -/obj/structure/mineral_door/wood{ - icon_state = "wood" - }, +/obj/structure/mineral_door/wood, /turf/open/floor/wood, /area/awaymission/wildwest/gov) "cP" = ( @@ -946,17 +881,13 @@ /turf/open/floor/carpet, /area/awaymission/wildwest/mines) "dm" = ( -/obj/structure/mineral_door/wood{ - icon_state = "wood" - }, +/obj/structure/mineral_door/wood, /turf/open/floor/plating/ironsand{ icon_state = "ironsand1" }, /area/awaymission/wildwest/mines) "dn" = ( -/obj/structure/mineral_door/wood{ - icon_state = "wood" - }, +/obj/structure/mineral_door/wood, /obj/effect/decal/cleanable/blood/tracks, /turf/open/floor/plating/ironsand{ icon_state = "ironsand1" @@ -1048,9 +979,7 @@ }, /area/awaymission/wildwest/gov) "dD" = ( -/obj/structure/mineral_door/wood{ - icon_state = "wood" - }, +/obj/structure/mineral_door/wood, /turf/open/floor/plating/ironsand{ icon_state = "ironsand1" }, @@ -1176,7 +1105,6 @@ /area/awaymission/wildwest/gov) "dV" = ( /obj/machinery/shower{ - icon_state = "shower"; dir = 4 }, /turf/open/floor/plasteel/cafeteria{ @@ -1185,7 +1113,6 @@ /area/awaymission/wildwest/mines) "dW" = ( /obj/machinery/shower{ - icon_state = "shower"; dir = 8 }, /turf/open/floor/plasteel/cafeteria{ @@ -2009,10 +1936,6 @@ /obj/machinery/photocopier, /turf/open/floor/wood, /area/awaymission/wildwest/mines) -"gm" = ( -/obj/item/gun/ballistic, -/turf/open/floor/wood, -/area/awaymission/wildwest/mines) "gn" = ( /mob/living/simple_animal/hostile/netherworld, /turf/open/floor/grass, @@ -2195,10 +2118,9 @@ /area/awaymission/wildwest/mines) "gW" = ( /obj/structure/table/reinforced, -/obj/item/clothing/suit/space/syndicate/black/orange, -/obj/item/clothing/head/helmet/space/syndicate/black/orange, -/obj/item/clothing/mask/gas/syndicate, /obj/item/tank/internals/oxygen, +/obj/item/clothing/suit/space/syndicate/blue, +/obj/item/clothing/head/helmet/space/syndicate/blue, /turf/open/floor/mineral/titanium/yellow, /area/awaymission/wildwest/refine) "gX" = ( @@ -33277,8 +33199,8 @@ aN aN aT aT -aT -aT +aw +az aT aT aT @@ -38117,7 +38039,7 @@ bu bz bM bM -ch +bM by bu bj @@ -39913,7 +39835,7 @@ bj bj aT bu -bC +bD bj bj bu @@ -46340,7 +46262,7 @@ aT bu bD bj -bC +bD cl bj bj @@ -47563,9 +47485,9 @@ aa ab ab ab -ar -au -ax +ao +ao +ao ao ao ao @@ -47820,9 +47742,9 @@ aa ab ab ab -as -av -ay +ao +ao +ao ao ao ao @@ -48077,9 +47999,9 @@ aa aa ab ab -at -aw -az +ao +ao +ao ao ao ao @@ -48850,7 +48772,7 @@ aa ab ab ao -ao +ap ao ab ab @@ -51159,7 +51081,7 @@ aa aa aa ab -ap +ao ao aq ab @@ -52283,7 +52205,7 @@ eX dj bj bu -gm +bj bj eM bj diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 2902cf12c4..c0b4e6a88a 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -350,7 +350,7 @@ /area/security/prison) "aaV" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel, /area/security/prison) "aaW" = ( @@ -1257,6 +1257,16 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "acV" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/solar/port/fore) +"acW" = ( /obj/structure/cable{ icon_state = "0-2" }, @@ -1266,11 +1276,6 @@ }, /turf/open/floor/plasteel/airless/solarpanel, /area/solar/port/fore) -"acW" = ( -/obj/structure/cable, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/solar/port/fore) "acX" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -1489,7 +1494,12 @@ /obj/structure/lattice/catwalk, /turf/open/space, /area/solar/starboard/fore) -"adu" = ( +"adw" = ( +/obj/structure/cable, +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/solar/port/fore) +"adx" = ( /obj/structure/cable{ icon_state = "4-8" }, @@ -1502,56 +1512,17 @@ /obj/structure/lattice/catwalk, /turf/open/space, /area/solar/port/fore) -"adv" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/solar/port/fore) -"adw" = ( -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/solar/port/fore) -"adx" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/solar/port/fore) "ady" = ( /obj/structure/lattice/catwalk, /turf/open/space, /area/solar/port/fore) -"adz" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/solar/port/fore) "adA" = ( -/obj/structure/cable{ - icon_state = "2-8" +/obj/structure/cable, +/obj/machinery/power/solar{ + id = "auxsolareast"; + name = "Port Auxiliary Solar Array" }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/structure/lattice/catwalk, -/turf/open/space, +/turf/open/floor/plasteel/airless/solarpanel, /area/solar/port/fore) "adB" = ( /obj/structure/cable{ @@ -1817,12 +1788,11 @@ /turf/open/space, /area/solar/starboard/fore) "adZ" = ( -/obj/structure/cable, -/obj/machinery/power/solar{ - id = "auxsolareast"; - name = "Port Auxiliary Solar Array" +/obj/structure/cable{ + icon_state = "0-8" }, -/turf/open/floor/plasteel/airless/solarpanel, +/obj/structure/lattice/catwalk, +/turf/open/space, /area/solar/port/fore) "aea" = ( /obj/machinery/portable_atmospherics/canister/nitrous_oxide, @@ -4879,6 +4849,10 @@ dir = 4 }, /obj/machinery/holopad, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "hopqueue"; + name = "HoP Queue Shutters" + }, /turf/open/floor/plasteel, /area/hallway/primary/central) "aiW" = ( @@ -5050,12 +5024,16 @@ /turf/open/floor/plasteel/dark, /area/security/courtroom) "ajq" = ( -/obj/structure/lattice/catwalk, +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/space, -/area/solar/port/fore) +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/plating, +/area/maintenance/solars/port/fore) "ajr" = ( /obj/structure/table/wood, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -5103,7 +5081,7 @@ /area/security/main) "ajv" = ( /obj/machinery/computer/med_data{ - dir = 3 + dir = 4 }, /obj/structure/sign/poster/official/medical_green_cross{ pixel_x = -32 @@ -5413,16 +5391,12 @@ /turf/open/floor/plating, /area/maintenance/solars/port/fore) "ajW" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "0-4" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/turf/open/floor/plating, -/area/maintenance/solars/port/fore) +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/solar/port/fore) "ajX" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -6467,6 +6441,12 @@ }, /turf/open/floor/plasteel/white, /area/science/xenobiology) +"alX" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "alY" = ( /obj/structure/cable{ icon_state = "1-2" @@ -6658,15 +6638,17 @@ /area/security/courtroom) "amv" = ( /obj/structure/cable{ - icon_state = "1-2" + icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" +/obj/structure/cable{ + icon_state = "2-8" }, -/turf/open/floor/plating, -/area/maintenance/solars/starboard/fore) +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/solar/port/fore) "amw" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -8069,6 +8051,13 @@ }, /turf/open/floor/plasteel/showroomfloor, /area/security/warden) +"apI" = ( +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/structure/closet/secure_closet/medical1, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "apJ" = ( /turf/closed/wall, /area/construction/mining/aux_base) @@ -8555,13 +8544,15 @@ /turf/open/floor/plasteel, /area/security/processing) "aqJ" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" +/obj/structure/cable{ + icon_state = "2-8" }, -/turf/open/floor/plating, -/area/maintenance/port/fore) +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/solar/port/fore) "aqK" = ( /obj/structure/chair/stool, /turf/open/floor/plasteel, @@ -9381,6 +9372,13 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/construction/mining/aux_base) +"asG" = ( +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/disposal/bin, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "asH" = ( /obj/structure/closet/toolcloset, /obj/effect/turf_decal/tile/yellow{ @@ -9424,6 +9422,35 @@ }, /turf/open/floor/plating, /area/maintenance/port/fore) +"asL" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24 + }, +/obj/item/reagent_containers/spray/cleaner, +/obj/item/crowbar, +/obj/item/clothing/neck/stethoscope, +/obj/item/storage/box/gloves{ + pixel_x = 3; + pixel_y = 4 + }, +/obj/item/storage/box/masks, +/obj/structure/table, +/turf/open/floor/plasteel/white, +/area/medical/sleeper) +"asM" = ( +/obj/structure/table, +/obj/item/crowbar, +/obj/item/clothing/neck/stethoscope, +/obj/item/reagent_containers/spray/cleaner, +/obj/structure/sign/warning/nosmoking{ + pixel_y = 30 + }, +/turf/open/floor/plasteel/dark, +/area/medical/sleeper) "asN" = ( /obj/machinery/airalarm{ dir = 4; @@ -9453,12 +9480,66 @@ /obj/structure/closet/firecloset, /turf/open/floor/plating, /area/maintenance/fore) +"asT" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/medical/medbay/central) +"asU" = ( +/obj/structure/sign/warning/nosmoking{ + pixel_y = 30 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/machinery/door/airlock/medical/glass{ + id_tag = "MedbayFoyer"; + name = "Medbay"; + req_access_txt = "5" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"asV" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/medical/medbay/central) "asW" = ( /obj/machinery/light/small{ dir = 8 }, /turf/open/floor/plasteel/grimy, /area/security/detectives_office) +"asX" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/medical/glass{ + id_tag = "MedbayFoyer"; + name = "Medbay"; + req_access_txt = "5" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"asY" = ( +/obj/structure/sign/warning/nosmoking{ + pixel_y = 30 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "ata" = ( /turf/open/floor/wood, /area/lawoffice) @@ -11788,63 +11869,12 @@ /obj/item/instrument/eguitar, /turf/open/floor/wood, /area/crew_quarters/theatre) -"azJ" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/obj/effect/turf_decal/bot_white/right, -/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/gateway) "azK" = ( /obj/machinery/light{ dir = 8 }, /turf/open/floor/plasteel/dark, /area/gateway) -"azL" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/obj/effect/turf_decal/bot_white/left, -/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/gateway) -"azM" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/obj/effect/turf_decal/bot_white, -/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/gateway) "azN" = ( /obj/machinery/light{ dir = 4 @@ -12316,30 +12346,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/closed/wall/r_wall, /area/ai_monitored/nuke_storage) -"aBd" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/turf_decal/bot_white, -/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/gateway) "aBe" = ( /turf/open/floor/plasteel/dark, /area/gateway) "aBf" = ( -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -12692,9 +12702,6 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/nuke_storage) "aBX" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -12709,9 +12716,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "aBY" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -12726,7 +12730,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "aBZ" = ( -/obj/machinery/gateway, /obj/structure/cable{ icon_state = "0-2" }, @@ -13425,7 +13428,6 @@ pixel_y = 32 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/machinery/button/door{ @@ -13795,8 +13797,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/nuke_storage) "aEQ" = ( -/obj/structure/table, -/obj/item/paper/pamphlet/gateway, +/obj/machinery/computer/gateway_control, /turf/open/floor/plasteel, /area/gateway) "aER" = ( @@ -14312,7 +14313,6 @@ pixel_y = 32 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/machinery/button/door{ @@ -17770,7 +17770,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20" }, /turf/open/floor/plasteel, @@ -21108,7 +21108,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -21669,7 +21669,7 @@ dir = 1; pixel_y = -24 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /turf/open/floor/wood, @@ -21797,7 +21797,6 @@ pixel_y = 32 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/machinery/button/door{ @@ -24226,7 +24225,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-13" }, /turf/open/floor/plasteel, @@ -24275,7 +24274,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel, @@ -24549,12 +24548,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, /area/engine/gravity_generator) -"bgP" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) "bgQ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 8 @@ -28292,12 +28285,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"bpy" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "bpz" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 8 @@ -28786,13 +28773,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/central) -"bqM" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/medical/medbay/central) "bqN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 @@ -28825,22 +28805,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"bqR" = ( -/obj/structure/table, -/obj/item/crowbar, -/obj/item/clothing/neck/stethoscope, -/obj/item/reagent_containers/spray/cleaner, -/obj/structure/sign/warning/nosmoking{ - pixel_y = 30 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "bqS" = ( /obj/structure/cable{ icon_state = "4-8" @@ -29343,13 +29307,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/crew_quarters/heads/hop) -"brV" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/medical/medbay/central) "brW" = ( /obj/structure/cable{ icon_state = "4-8" @@ -29357,18 +29314,6 @@ /obj/machinery/vending/cart, /turf/open/floor/plasteel, /area/crew_quarters/heads/hop) -"brX" = ( -/obj/structure/table, -/obj/item/storage/box/masks, -/obj/item/storage/box/gloves{ - pixel_x = 3; - pixel_y = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "brY" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -29832,7 +29777,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/white, @@ -30970,7 +30915,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "bvH" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ @@ -31293,23 +31238,10 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/medical/medbay/central) -"bwy" = ( -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "bwz" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"bwA" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "bwB" = ( /obj/structure/chair, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ @@ -33049,17 +32981,6 @@ }, /turf/open/floor/plating, /area/maintenance/port/aft) -"bAp" = ( -/obj/structure/closet/secure_closet/medical1, -/obj/machinery/light{ - dir = 8 - }, -/obj/machinery/firealarm{ - dir = 4; - pixel_x = -24 - }, -/turf/open/floor/plasteel/white, -/area/medical/sleeper) "bAq" = ( /obj/machinery/sleeper{ dir = 8 @@ -33921,7 +33842,7 @@ /obj/machinery/light_switch{ pixel_y = -23 }, -/obj/item/twohanded/required/kirbyplants/dead, +/obj/item/kirbyplants/dead, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/heads/hor) "bCg" = ( @@ -39086,7 +39007,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/plasteel/white/side{ dir = 1 }, @@ -42398,15 +42319,9 @@ /turf/open/floor/plasteel, /area/science/circuit) "bXv" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/obj/item/stack/rods, +/turf/open/space, +/area/space) "bXw" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, @@ -45120,7 +45035,7 @@ dir = 4 }, /turf/closed/wall/r_wall, -/area/engine/engineering) +/area/engine/atmos) "cez" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, @@ -45574,9 +45489,12 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cfK" = ( -/obj/structure/sign/warning/securearea, -/turf/closed/wall, -/area/engine/engineering) +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-2" + }, +/turf/open/space, +/area/solar/port/fore) "cfL" = ( /obj/machinery/firealarm{ pixel_y = 24 @@ -46376,18 +46294,11 @@ /turf/open/floor/plating, /area/maintenance/solars/port/aft) "chO" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, /obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" + req_access_txt = "13" }, /turf/open/floor/plating, -/area/maintenance/solars/port/aft) +/area/maintenance/fore/secondary) "chP" = ( /obj/structure/cable{ icon_state = "4-8" @@ -48355,8 +48266,8 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel, /area/engine/engineering) "cnB" = ( @@ -49405,15 +49316,16 @@ /turf/open/space, /area/maintenance/aft) "csg" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 +/obj/structure/cable{ + icon_state = "1-2" }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/external{ - name = "Engineering External Access"; - req_access_txt = "10;13" + name = "Solar Maintenance"; + req_access_txt = "10; 13" }, /turf/open/floor/plating, -/area/engine/engineering) +/area/maintenance/solars/starboard/fore) "csi" = ( /obj/structure/transit_tube/curved/flipped{ dir = 1 @@ -51206,13 +51118,10 @@ /turf/open/floor/plasteel, /area/security/processing) "cxW" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "External Access"; - req_access_txt = "13" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/structure/lattice, +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/space/nearstation) "cxY" = ( /obj/machinery/camera{ c_tag = "Arrivals Escape Pod 1"; @@ -51311,14 +51220,13 @@ /turf/open/floor/plating, /area/hallway/secondary/entry) "cyC" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/external{ + name = "External Access"; req_access_txt = "13" }, /turf/open/floor/plating, -/area/maintenance/starboard) +/area/maintenance/port/fore) "cyD" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 @@ -51340,15 +51248,13 @@ /turf/open/floor/plating, /area/maintenance/port/aft) "cyG" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/door/airlock/external{ - name = "Atmospherics External Airlock"; - req_access_txt = "24" + name = "External Access"; + req_access_txt = "13" }, /turf/open/floor/plating, -/area/engine/atmos) +/area/maintenance/starboard/fore) "cyK" = ( /obj/structure/cable{ icon_state = "4-8" @@ -51394,18 +51300,14 @@ /turf/open/space/basic, /area/space) "cyU" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 + dir = 8 }, /obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" + req_access_txt = "13" }, /turf/open/floor/plating, -/area/maintenance/solars/starboard/aft) +/area/maintenance/starboard) "czg" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 @@ -52086,7 +51988,7 @@ /obj/structure/table/reinforced, /obj/machinery/cell_charger, /obj/item/stock_parts/cell/high/plus, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel, /area/crew_quarters/heads/chief) "cBN" = ( @@ -52311,10 +52213,9 @@ /turf/open/space, /area/space/nearstation) "cCS" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) +/turf/closed/wall/r_wall, +/area/engine/atmos) "cCT" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -52381,12 +52282,15 @@ /turf/closed/wall, /area/engine/engineering) "cDY" = ( -/obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 9 +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 }, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + name = "External Access"; + req_access_txt = "13" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "cDZ" = ( /obj/structure/cable{ icon_state = "1-2" @@ -53516,6 +53420,7 @@ "dfh" = ( /obj/machinery/power/apc{ areastring = "/area/science/circuit"; + dir = 4; name = "Circuitry Lab APC"; pixel_x = 30 }, @@ -53664,6 +53569,11 @@ dir = 8 }, /area/crew_quarters/fitness/pool) +"dCt" = ( +/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/structure/lattice, +/turf/open/space, +/area/space/nearstation) "dCV" = ( /obj/structure/cable{ icon_state = "1-4" @@ -53760,9 +53670,6 @@ }, /turf/open/floor/mineral/titanium/blue, /area/crew_quarters/toilet) -"dVU" = ( -/turf/open/floor/plating, -/area/space/nearstation) "dXq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -53806,7 +53713,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-04" }, /turf/open/floor/plasteel/white, @@ -53815,7 +53722,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 6 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "egt" = ( /obj/effect/turf_decal/tile/bar, @@ -53939,7 +53846,7 @@ /turf/open/floor/plating, /area/crew_quarters/fitness) "exP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel, @@ -54285,7 +54192,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-06" }, /turf/open/floor/plasteel/white/corner{ @@ -54335,6 +54242,12 @@ }, /turf/open/floor/plasteel, /area/security/range) +"fty" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/structure/lattice, +/turf/open/space, +/area/space/nearstation) "ftE" = ( /obj/item/radio/intercom{ pixel_y = 25 @@ -54444,7 +54357,7 @@ "fIs" = ( /obj/structure/grille, /obj/structure/lattice, -/turf/open/floor/plating, +/turf/open/space/basic, /area/space/nearstation) "fJY" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -54466,6 +54379,7 @@ /obj/structure/chair/office/dark{ dir = 1 }, +/obj/effect/landmark/start/atmospheric_technician, /turf/open/floor/plasteel, /area/engine/atmos) "fMp" = ( @@ -54483,7 +54397,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 10 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /turf/open/floor/plasteel, @@ -54601,19 +54515,6 @@ }, /turf/open/floor/carpet, /area/crew_quarters/cryopod) -"ghq" = ( -/obj/structure/lattice/catwalk, -/obj/item/stack/marker_beacon{ - anchored = 1; - icon_state = "markerburgundy-on"; - light_color = "#FA644B"; - light_power = 3; - light_range = 3; - name = "Docking Beacon"; - picked_color = "Burgundy" - }, -/turf/open/floor/plating, -/area/space/nearstation) "ghD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, @@ -54770,7 +54671,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 9 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "gJi" = ( /obj/structure/lattice/catwalk, @@ -54855,7 +54756,6 @@ dir = 8 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/structure/mirror{ @@ -54906,10 +54806,6 @@ dir = 8 }, /area/medical/sleeper) -"haL" = ( -/obj/structure/lattice, -/turf/open/space/basic, -/area/space) "haM" = ( /obj/item/radio/intercom{ name = "Station Intercom (General)"; @@ -54949,7 +54845,7 @@ /area/engine/atmos) "hgO" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice{ +/obj/item/storage/box/dice{ pixel_x = 4; pixel_y = 4 }, @@ -55007,7 +54903,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 10 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "hxn" = ( /obj/effect/spawner/structure/window/reinforced, @@ -55190,6 +55086,13 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"imk" = ( +/obj/structure/lattice, +/obj/machinery/atmospherics/pipe/simple/orange/visible{ + dir = 9 + }, +/turf/open/space/basic, +/area/space/nearstation) "imH" = ( /obj/structure/falsewall, /turf/open/floor/plating, @@ -55485,6 +55388,10 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) +"jiK" = ( +/obj/structure/sign/warning/securearea, +/turf/closed/wall, +/area/engine/engineering) "jjC" = ( /obj/structure/table/wood, /obj/item/toy/cards/deck, @@ -56091,6 +55998,10 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/theatre) +"kEm" = ( +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/plating, +/area/maintenance/port/aft) "kEY" = ( /obj/effect/landmark/stationroom/box/engine, /turf/open/space/basic, @@ -56444,7 +56355,7 @@ /turf/open/floor/plasteel, /area/security/processing) "lPr" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /turf/open/floor/plasteel, @@ -56653,7 +56564,6 @@ }, /area/maintenance/bar) "mqZ" = ( -/obj/structure/reagent_dispensers/keg/aphro/strong, /obj/item/reagent_containers/glass/beaker, /turf/open/floor/plating, /area/maintenance/bar) @@ -56794,6 +56704,19 @@ /obj/structure/table/wood, /turf/open/floor/wood, /area/maintenance/bar) +"mQp" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/aft) "mQS" = ( /obj/machinery/light{ dir = 8; @@ -57154,6 +57077,7 @@ dir = 4; pixel_y = 5 }, +/obj/item/clothing/head/hardhat/cakehat, /turf/open/floor/wood, /area/crew_quarters/bar) "oby" = ( @@ -57277,7 +57201,6 @@ dir = 8 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/structure/mirror{ @@ -57369,7 +57292,7 @@ /area/crew_quarters/theatre) "oyN" = ( /obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "oyX" = ( /obj/machinery/atmospherics/components/binary/pump/on{ @@ -57926,7 +57849,6 @@ pixel_y = 32 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /turf/open/floor/mineral/titanium/blue, @@ -57989,7 +57911,6 @@ pixel_y = 32 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/machinery/light/small{ @@ -58024,7 +57945,7 @@ /turf/open/floor/carpet, /area/crew_quarters/theatre) "qTV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/white, @@ -58210,7 +58131,7 @@ dir = 5 }, /obj/machinery/camera{ - c_tag = "Bar Backroom" + c_tag = "Gravity Generator - Fore" }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -58221,6 +58142,10 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/floor/plating, /area/maintenance/fore) +"rtU" = ( +/mob/living/simple_animal/opossum, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "ruo" = ( /obj/structure/cable{ icon_state = "4-8" @@ -58493,7 +58418,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "slk" = ( /obj/machinery/door/airlock/maintenance{ @@ -58750,9 +58675,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, /area/engine/engine_smes) -"sQX" = ( -/turf/open/floor/plating, -/area/space) "sRH" = ( /obj/machinery/autolathe/secure{ name = "public autolathe" @@ -58869,7 +58791,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "trb" = ( /obj/machinery/light{ @@ -58924,14 +58846,10 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/pool) "tAH" = ( -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/fore/secondary) +/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/structure/lattice, +/turf/open/space/basic, +/area/space/nearstation) "tCa" = ( /obj/structure/table/wood, /obj/item/instrument/guitar{ @@ -58954,6 +58872,19 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"tEK" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) "tHh" = ( /obj/machinery/disposal/bin, /obj/effect/turf_decal/tile/red, @@ -59092,7 +59023,7 @@ /area/hallway/primary/central) "uaw" = ( /obj/machinery/power/apc{ - areastring = "/area/storage/art"; + areastring = "/area/maintenance/bar"; dir = 1; name = "Maint bar"; pixel_y = 24 @@ -59324,7 +59255,7 @@ "uDO" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "0-2" + icon_state = "1-2" }, /turf/open/space, /area/solar/port/fore) @@ -59505,7 +59436,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "vbi" = ( /obj/structure/table, @@ -60068,6 +59999,16 @@ /obj/machinery/holopad, /turf/open/floor/plasteel/showroomfloor, /area/security/main) +"wmu" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external{ + name = "Engineering External Access"; + req_access_txt = "10;13" + }, +/turf/open/floor/plating, +/area/engine/engineering) "woR" = ( /obj/machinery/cryopod{ dir = 1 @@ -60227,6 +60168,16 @@ /obj/item/hand_labeler, /turf/open/floor/plasteel, /area/hallway/secondary/service) +"wWi" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/external{ + name = "Atmospherics External Airlock"; + req_access_txt = "24" + }, +/turf/open/floor/plating, +/area/engine/atmos) "wWT" = ( /obj/effect/landmark/start/roboticist, /turf/open/floor/plasteel/white, @@ -60604,7 +60555,7 @@ name = "Docking Beacon"; picked_color = "Burgundy" }, -/turf/open/space/basic, +/turf/open/floor/plating/airless, /area/space/nearstation) "xOx" = ( /obj/structure/chair/comfy/brown{ @@ -60752,7 +60703,6 @@ pixel_y = 32 }, /obj/structure/sink{ - dir = 1; pixel_y = 25 }, /obj/machinery/button/door{ @@ -66838,11 +66788,11 @@ aaa aaa aaa aaa -ghq +xLX aaa aaa aaa -ghq +xLX aaa aaa aaa @@ -67089,9 +67039,9 @@ aaa aaa aaa aaa -ghq +xLX aaa -ghq +xLX aaa aaa aaa @@ -67103,9 +67053,9 @@ gXs aaa aaa aaa -ghq +xLX aaa -ghq +xLX aaa aaa aaa @@ -67618,7 +67568,7 @@ gXs gXs gJi gJi -haL +gXs aag gJi aaa @@ -68372,7 +68322,7 @@ aaa aaa aaa aae -ktS +aaa gXs aaa aaa @@ -68629,7 +68579,7 @@ aaa aaa aaa aaa -ktS +aaa gXs aaa aaa @@ -68886,7 +68836,7 @@ aaa aaa aaa aaa -ktS +aaa gXs aaa aaa @@ -69143,7 +69093,7 @@ aaa aaa aaa aaa -ktS +aaa gXs aaa cqq @@ -69400,7 +69350,7 @@ aaf aaf aaf aaa -ktS +aaa arB asE cyb @@ -73762,11 +73712,11 @@ aaa aae aaa aaa -aaa aag alU alU alU +alU aCW amC asK @@ -74019,9 +73969,9 @@ aaa aaa aaa aaa -aaa aag -aqJ +cyC +amC amC gLH ase @@ -74276,7 +74226,7 @@ aaa aaa aaa aaa -aaa +gJi alU alU alU @@ -75025,7 +74975,6 @@ aaa aaa aaa aaa -aaa aaS aaS aaS @@ -75044,6 +74993,7 @@ aaS aaf aaf aaf +aaf aaa aaa aaa @@ -75282,7 +75232,6 @@ aaa aaa aaa aaa -aaa abY aaa aaf @@ -75295,7 +75244,7 @@ acy aaa aaf aaa -aiS +bXv aaa aaS aaa @@ -75304,6 +75253,7 @@ aaa aaa aaa aaa +aaa alU aoR apO @@ -75539,25 +75489,25 @@ aaa aaa aaa aaa -aaa abY aaa +acW acV -adv -adZ +adA aaa +acW acV -adv -adZ +adA aaa +acW acV -adv -adZ +adA aaa aaS aaf aaf aaf +aaf aaa aaa aaa @@ -75793,23 +75743,22 @@ aaa aaa aaa aaa -aaa aae aaa aaa abY aaf -acV -adu -adZ +acW +adx +adA aaa -acV -adu -adZ +acW +adx +adA aaa -acV -adu -adZ +acW +adx +adA aaf aaf aaa @@ -75818,6 +75767,7 @@ aaa aaa aaa aaa +aaa alU alU alU @@ -76053,20 +76003,19 @@ aaa aaa aaa aaa -aaa abY aaa -acV -adu -adZ +acW +adx +adA aaf -acV -adu -adZ +acW +adx +adA aaf -acV -adu -adZ +acW +adx +adA aaa aaf aaa @@ -76075,6 +76024,7 @@ aaa aaa aaa aaa +aaa aaf aaa ali @@ -76310,20 +76260,20 @@ aaa aaa aaa aaa -aaa aaf aaf -acV -adu -adZ +acW +adx +adA aaa -acV -adu -adZ +acW +adx +adA aaa -acV -adu -adZ +acW +adx +adA +aaf aaf aaf aaf @@ -76564,26 +76514,26 @@ aaa aaa aaa aaa -aaa aaS aaS aaS aaf aaa -acV -adu -adZ +acW +adx +adA aaa -acV -adu -adZ +acW +adx +adA aaa -acV -adu -adZ +acW +adx +adA aaa aaf aaa +aaa ajV alR alR @@ -76654,7 +76604,7 @@ aaa aaa aaa aaa -aag +aaa aaa aaa aaa @@ -76821,27 +76771,27 @@ aaa aaa aaa aaa -aaa aaS aaa aaf aaa aaa aaa -adw +adZ aaa aaa aaa -adw +adZ aaa aaa aaa -adw +adZ aaa aaa ajV ajV ajV +ajV alQ amy ang @@ -76911,7 +76861,7 @@ aaa aaa aaa aaa -aag +aaa aaa aaa aaa @@ -77078,13 +77028,12 @@ aaa aaa aaa aaa -aaa aaS aaf abs abZ abZ -acW +adw ady ady ady @@ -77094,9 +77043,10 @@ ady ady ady ady +cfK uDO ajq -ajW +akB akB alh alT @@ -77168,7 +77118,7 @@ aaa aaa aaa aaa -aag +aaa aaa aaa aaa @@ -77335,27 +77285,27 @@ aaa aaa aaa aaa -aaa aaS aaa aaf aaa aaa aaa -adx +ajW aaa aaa aaa -adx +ajW aaa aaa aaa -adx +ajW aaa aaa ajV ajV ajV +ajV alS amz anh @@ -77425,7 +77375,7 @@ aaa aaa aaa aaa -aag +aaa aaa aaa aaa @@ -77592,26 +77542,26 @@ aaa aaa aaa aaa -aaa aaS aba aaS aaf aaa -acV -adz -adZ +acW +amv +adA aaa -acV -adz -adZ +acW +amv +adA aaa -acV -adz -adZ +acW +amv +adA aaa aaf aaa +aaa ajV alR alR @@ -77682,7 +77632,7 @@ aaa aaa aaa aaa -aag +aaa aaa aaa aaa @@ -77852,22 +77802,22 @@ aaa aaa aaa aaa +aaf +aaf +acW +amv +adA aaa -aaf -aaf -acV -adz -adZ +acW +amv +adA aaa -acV -adz -adZ +acW +amv +adA +aaf +aaf aaa -acV -adz -adZ -aaf -aaf aaa aaa aaa @@ -77939,7 +77889,7 @@ aaa aaa aaa aaa -aag +aaa aaa aaa aaa @@ -78109,24 +78059,24 @@ aaa aaa aaa aaa -aaa aaS aaa -acV -adz -adZ +acW +amv +adA aaf -acV -adz -adZ +acW +amv +adA aaf -acV -adz -adZ +acW +amv +adA aaa aaf aaf aaf +aaf gXs alU alF @@ -78196,7 +78146,7 @@ aaa aaa aaa aaa -aag +aaa aaa aoV bZm @@ -78366,25 +78316,25 @@ aaa aaa aaa aaa -aaa aaS aaf -acV -adz -adZ +acW +amv +adA aaa -acV -adz -adZ +acW +amv +adA aaa -acV -adz -adZ +acW +amv +adA aaf aaf aaa aaa aaa +aaa alU alU ank @@ -78453,13 +78403,13 @@ aaa aaa aaa aaa -aag +aaa aaa aoV bVz aaf aaf -sQX +aoV aaa aaS aaf @@ -78623,22 +78573,22 @@ aaa aaa aaa aaa +aaS +aaa +acW +aqJ +adA +aaa +acW +aqJ +adA +aaa +acW +aqJ +adA aaa aaS aaa -acV -adA -adZ -aaa -acV -adA -adZ -aaa -acV -adA -adZ -aaa -aaS aaa aaa aaa @@ -78710,7 +78660,7 @@ aaa aaa aaa aaa -aag +aaa aaa aag bVz @@ -78725,9 +78675,9 @@ aaf aaa aaf aaa -aaa +aaf hrF -aaa +aaf aaa aaf aaa @@ -78880,7 +78830,6 @@ aaa aaa aaa aaa -aaa aaS aaa aaf @@ -78898,6 +78847,7 @@ aaa aaS aaf aaf +aaf gXs alU amC @@ -78967,7 +78917,7 @@ aaa aaa aaa aaa -aag +gJi aaa aaf bVz @@ -78982,9 +78932,9 @@ aaf aaf aaf aaf -aaf -hrF -aaf +cfx +tEK +cfx aaf aaf aaf @@ -79137,7 +79087,6 @@ aaa aaa aaa aaa -aaa aaS aaS aaS @@ -79156,6 +79105,7 @@ aaS aaa aaa aaa +aaa alU amE ann @@ -79224,7 +79174,7 @@ aaa aaa aaa aaa -aag +gJi aaa aaf bVz @@ -79240,7 +79190,7 @@ aaf aaa aaa cfx -chO +chN cfx aaa aaf @@ -79488,8 +79438,8 @@ caf aoV aag aaf -aaa -aaa +gXs +gXs aaf aaa aaa @@ -79742,9 +79692,9 @@ bLv bCq aoV cbj -aoV -aag -aaf +bLv +cDY +bLv aaf bCq bCq @@ -80000,7 +79950,7 @@ bCq bCq cbj bLv -bXv +bHE bLv aaf bCq @@ -80016,7 +79966,7 @@ ciQ cfw aaa aaa -aaa +gXs aaf aaf aaa @@ -80271,9 +80221,9 @@ cgC chR ciS cfw -aaa -aaa -aaa +aag +aag +aag aaa aaf aaf @@ -80528,9 +80478,9 @@ cgB chQ ciR cfw -aag -aag -aag +bCq +cDY +bCq aaa aaa aaf @@ -80786,7 +80736,7 @@ chS cfw cfw bCq -bXv +bHE bCq aaa aaa @@ -84053,8 +84003,8 @@ esK awb axt ayG -azJ -aBd +aBY +aBf aBX aDi aEQ @@ -84274,7 +84224,7 @@ aaa aaa gXs gXs -dVU +aaH abc abu abu @@ -84310,7 +84260,7 @@ arP awb axt ayG -azM +aBf aBg aBZ aDx @@ -84567,7 +84517,7 @@ arP vgJ hSl ayG -azL +aBX aBf aBY aDw @@ -85409,7 +85359,7 @@ bVI bTA xgk bHE -bHE +kEm bHE bHE bHE @@ -90282,7 +90232,7 @@ bUE bWM bXJ bMK -bMK +bYH bYH bYH bVg @@ -92315,7 +92265,7 @@ btJ buV bws bqH -aJq +asY aJq byW bCv @@ -92598,10 +92548,10 @@ bWQ bWQ caD bWQ -ccw -ccw +bLK +bLK cey -ccw +bLK ccw ccw ccw @@ -92877,14 +92827,14 @@ ckF cpE cjR crW -csg +ciZ +wmu aag aaa aaa aaa aaa aaa -aaa ctv ctv ctv @@ -93134,14 +93084,14 @@ crw cjO ccw crX -cfK +ciZ +jiK aag aaa aaa aaa aaa aaa -aaa aaT aaT aaT @@ -93392,7 +93342,7 @@ cjm ccw ccw cig -aag +cig aag aag aag @@ -94366,8 +94316,8 @@ bfF bfF bfF bfF -bqM -brV +asT +asV bof bwv bvj @@ -94623,8 +94573,8 @@ bmF bob bnB bfF -bqR -brX +asU +asX bof bwx bvj @@ -95070,10 +95020,10 @@ aaa aaa aaa aaa -aaa acw abp abp +abp adR abp lJC @@ -95131,7 +95081,7 @@ aYV bfF bhc bip -bgP +alX bjL bkL bmT @@ -95326,10 +95276,10 @@ aaa aaa aaa aaa -aaa aaf aag acU +anF adr sXy aeC @@ -95397,7 +95347,7 @@ bpF bqS brY bwz -bwy +asG bvj bza bxb @@ -95584,12 +95534,12 @@ aaa aaa aaa aaa -aaa aag abp abp abp abp +abp mxn abp abp @@ -95653,10 +95603,10 @@ bpt bfF bqV bEe +bhh bBL -bwA bvj -bAl +asM bAl bvh bzS @@ -96112,7 +96062,7 @@ aaa ahn ahn ahn -tAH +anF ahn eMs anG @@ -96171,7 +96121,7 @@ bvh ajv bxN bze -bAp +asL bvh bCG bBd @@ -96368,8 +96318,8 @@ aaa aaa aaa aaa -gJi -gJi +ahn +chO ahn ahn khB @@ -96457,10 +96407,10 @@ bQA bPj bOh cCQ -bLK -cyG -bLK -aoV +cCS +chg +cCS +aaf aoV aoV aaf @@ -96625,8 +96575,8 @@ aaa aaa aaa aaa -aaa -aaa +gJi +gJi dFX wWW dqb @@ -96713,21 +96663,21 @@ cbI ccC cdD bOh -cCG +cCQ cCS +wWi cCS -cCI -cCI -cCI -cCI -cCI -cCI -cCI -cCI -cCI -cCI -cCI -cDY +aaa +aaa +aaa +gXs +aaa +aaa +aaa +aaa +aaa +aaa +cCQ aaf aaf aaf @@ -96970,21 +96920,21 @@ cbH ccB cbH bOh -aaf -aaa -aoV -aaf -aoV -aoV -aoV -aaf -aoV -aoV -aoV -aoV -aoV -aoV -gXs +cCG +tAH +dCt +fty +dCt +dCt +dCt +fty +dCt +dCt +dCt +dCt +dCt +dCt +imk aoV aaa aaa @@ -97228,11 +97178,11 @@ ccD cbH bOh aaf -aaf -aaf -aaf -aaf -aoV +aaa +aaa +aaa +aaa +aaa aoV aaf aoV @@ -98219,7 +98169,7 @@ bjX blp bmO bhi -bpy +apI bwz brg btZ @@ -100491,7 +100441,7 @@ aaa aaa aaa aaa -aaa +gXs aaf aaf alO @@ -100747,8 +100697,8 @@ aaa aaa aaa aaa -aaa -aag +gJi +alO alO arp alO @@ -101004,9 +100954,9 @@ aaa aaa aaa aaa -aaa -aag -cxW +gJi +cyG +anf anf aqv ayf @@ -101261,10 +101211,10 @@ aaf aaf aaf aaf -aaf -aag +cxW alO anf +anf alO mAH jaF @@ -101770,7 +101720,7 @@ aaa aaa aaf aaa -aaa +amw amw amw amw @@ -102027,8 +101977,8 @@ eaR jIs jIs jIs -acx -amv +csg +ane ane cxN aog @@ -102284,7 +102234,7 @@ aaa aaa aaf aaa -aaa +amw amw amw amw @@ -104354,7 +104304,7 @@ anf anf alP alP -anf +rtU alP alP alP @@ -110602,7 +110552,7 @@ cmw cnj cnj cnj -aaa +cnj aaa aaf aaa @@ -110809,7 +110759,7 @@ aaf aaf aaf bky -cyC +btp bns boF bqe @@ -110858,8 +110808,8 @@ clx cmv cnk cnK -cyU -cpi +cnK +mQp cpi cpi cqJ @@ -111064,9 +111014,9 @@ aQE aNa aaa aaf -aaa -aaf -aaa +gXs +bky +cyU bns boF bqe @@ -111116,7 +111066,7 @@ cmx cnj cnj cnj -aaa +cnj aaa aaf aaa @@ -111321,7 +111271,7 @@ afE aNa aaa aaa -aaa +gXs aaf aaa bns @@ -112903,7 +112853,7 @@ aaa aaa aaf cNW -cPI +cOe cNW aaf aaf @@ -113159,9 +113109,9 @@ aaa aaa aaa aaf -aag -aag -aag +cNW +cPI +cNW aaf aaa aaa @@ -113415,11 +113365,11 @@ aaa aaa aaa aaa -aaa -aaa +gXs aag -aaa -aaa +aag +aag +gXs aaa aaa aaa @@ -113674,7 +113624,7 @@ aaa aaa aaa aaa -aaf +aag aaa aaa aaa diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm index 1ba8c82249..3c64b9f6ad 100644 --- a/_maps/map_files/CogStation/CogStation.dmm +++ b/_maps/map_files/CogStation/CogStation.dmm @@ -242,13 +242,13 @@ pixel_x = 22 }, /obj/structure/rack, -/obj/item/gun/energy{ +/obj/item/gun/energy/e_gun{ pixel_y = -6 }, -/obj/item/gun/energy{ +/obj/item/gun/energy/e_gun{ pixel_y = -3 }, -/obj/item/gun/energy, +/obj/item/gun/energy/e_gun, /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "aaI" = ( @@ -346,9 +346,6 @@ /obj/structure/cable{ icon_state = "0-8" }, -/obj/structure/cable{ - icon_state = "4-8" - }, /turf/open/space/basic, /area/solar/starboard/fore) "aaU" = ( @@ -410,10 +407,7 @@ "abc" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "2-8" + icon_state = "0-4" }, /turf/open/space/basic, /area/solar/starboard/fore) @@ -432,10 +426,7 @@ "abe" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "0-4" - }, -/obj/structure/cable{ - icon_state = "4-8" + icon_state = "0-2" }, /turf/open/space/basic, /area/solar/starboard/fore) @@ -850,6 +841,10 @@ /area/maintenance/fore) "acc" = ( /obj/effect/spawner/structure/window/plasma/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "solitarylock"; + name = "Brig Lockdown" + }, /turf/open/floor/plating, /area/security/brig) "acd" = ( @@ -1199,7 +1194,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/checker, @@ -1246,11 +1241,10 @@ /obj/effect/turf_decal/tile/purple{ dir = 1 }, -/obj/structure/closet/crate/freezer, /obj/machinery/firealarm{ pixel_y = 26 }, -/obj/item/reagent_containers/food/snacks/meat/slab, +/obj/machinery/washing_machine, /turf/open/floor/plasteel, /area/crew_quarters/lounge) "acW" = ( @@ -1401,7 +1395,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/dark/corner{ @@ -1696,10 +1690,10 @@ "aee" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "2-4" + icon_state = "0-8" }, /turf/open/space/basic, -/area/solar/starboard/fore) +/area/solar/port) "aef" = ( /obj/machinery/atmospherics/pipe/manifold/general/visible{ dir = 8 @@ -1854,9 +1848,6 @@ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/machinery/light_switch{ - pixel_y = -24 - }, /turf/open/floor/plasteel/dark, /area/crew_quarters/observatory) "aez" = ( @@ -2183,6 +2174,9 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral, +/obj/machinery/light_switch{ + pixel_x = 24 + }, /turf/open/floor/plasteel/dark, /area/crew_quarters/observatory) "afl" = ( @@ -2403,6 +2397,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/washing_machine, /turf/open/floor/plasteel/checker, /area/hallway/secondary/entry) "afP" = ( @@ -2636,9 +2631,6 @@ /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/mob/living/simple_animal/pet/redpanda{ - name = "Stinky" - }, /turf/open/floor/plasteel, /area/crew_quarters/lounge) "agt" = ( @@ -2667,6 +2659,11 @@ pixel_y = 28 }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/displaycase/labcage{ + desc = "A glass lab container for storing smelly creatures."; + name = "stinky panda containment"; + start_showpiece_type = /mob/living/simple_animal/pet/redpanda/stinky + }, /turf/open/floor/plasteel, /area/crew_quarters/lounge) "agx" = ( @@ -2725,10 +2722,6 @@ dir = 1; pixel_y = -22 }, -/obj/machinery/camera{ - c_tag = "Observatory Viewing Area"; - dir = 4 - }, /obj/machinery/light/small{ dir = 8 }, @@ -2885,7 +2878,6 @@ /turf/closed/wall/r_wall, /area/security/processing) "agX" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/structure/cable{ icon_state = "1-2" }, @@ -3089,6 +3081,10 @@ /area/crew_quarters/kitchen) "ahy" = ( /obj/effect/spawner/structure/window/plasma/reinforced, +/obj/machinery/door/poddoor/preopen{ + id = "solitarylock"; + name = "Brig Lockdown" + }, /turf/open/floor/plating, /area/security/warden) "ahz" = ( @@ -3187,6 +3183,9 @@ /obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ dir = 1 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plating, /area/maintenance/starboard/fore) "ahL" = ( @@ -3326,15 +3325,12 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/observatory) "aif" = ( -/obj/machinery/firealarm{ - pixel_y = 26 - }, -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plating, /area/maintenance/starboard/fore) "aig" = ( @@ -3416,7 +3412,7 @@ "aiq" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "4-8" + icon_state = "0-2" }, /turf/open/space/basic, /area/solar/port) @@ -3586,6 +3582,8 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/effect/turf_decal/bot, +/obj/structure/closet/secure_closet/genpop, /turf/open/floor/plasteel, /area/security/brig) "aiL" = ( @@ -3623,7 +3621,7 @@ /turf/open/floor/wood, /area/crew_quarters/fitness) "aiS" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-06" }, /turf/open/floor/wood, @@ -3694,17 +3692,9 @@ /area/maintenance/starboard/fore) "ajc" = ( /obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/structure/cable{ - icon_state = "1-8" - }, +/obj/structure/cable, /turf/open/space/basic, -/area/solar/starboard/fore) +/area/solar/port) "ajd" = ( /obj/structure/cable{ icon_state = "1-2" @@ -3791,6 +3781,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/washing_machine, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -3895,7 +3886,7 @@ /area/security/brig) "ajA" = ( /obj/effect/turf_decal/bot, -/obj/structure/closet/secure_closet/brig, +/obj/structure/closet/secure_closet/genpop, /turf/open/floor/plasteel, /area/security/brig) "ajB" = ( @@ -3905,6 +3896,10 @@ }, /obj/effect/turf_decal/delivery, /obj/effect/decal/cleanable/dirt, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, /turf/open/floor/plasteel, /area/security/prison) "ajC" = ( @@ -4175,22 +4170,11 @@ /turf/open/floor/plasteel, /area/construction/secondary) "akg" = ( -/obj/machinery/power/solar_control{ - dir = 4; - id = "foreport"; - name = "Port Bow Solar Control" - }, -/obj/structure/sign/warning/electricshock{ - pixel_x = -32 - }, /obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "0-4" + icon_state = "1-2" }, /turf/open/floor/plating, -/area/maintenance/solars/port) +/area/maintenance/solars/starboard/fore) "akh" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, @@ -4200,14 +4184,16 @@ /turf/open/floor/plating, /area/construction/secondary) "akj" = ( -/obj/structure/chair{ - dir = 8 - }, /obj/structure/cable{ icon_state = "4-8" }, +/obj/machinery/door/airlock/external{ + name = "Starboard Bow Solar Exterior Airlock"; + req_access_txt = "10;13" + }, +/obj/machinery/door/firedoor, /turf/open/floor/plating, -/area/maintenance/solars/port) +/area/maintenance/solars/starboard/fore) "akk" = ( /obj/item/stack/tile/plasteel{ pixel_x = 10; @@ -4365,18 +4351,12 @@ /turf/open/floor/plasteel, /area/security/warden) "akz" = ( -/obj/machinery/light/small{ - dir = 1; - light_color = "#ffc1c1" +/obj/machinery/door/airlock/external, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 }, -/obj/machinery/power/terminal{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/turf/open/floor/plating, -/area/maintenance/solars/port) +/turf/open/floor/plasteel, +/area/router/service) "akA" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -4483,17 +4463,8 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "akN" = ( -/obj/structure/plasticflaps, -/obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ - id = "secblock"; - name = "Security Router" - }, -/obj/machinery/conveyor/auto{ - id = "sec" - }, -/turf/open/floor/plating, -/area/router/sec) +/turf/open/space/basic, +/area/router/aux) "akO" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -5517,11 +5488,10 @@ /turf/open/floor/plating, /area/maintenance/disposal) "ann" = ( -/obj/effect/turf_decal/plaque{ +/obj/effect/landmark/event_spawn, +/turf/open/floor/goonplaque{ desc = "It reads 'In honor of spacemen past, whose work allowed this station to find its new home. The fact that you stand on a station originally built light years away is a definitive representation of the ingenuity of the human spirit.' Beneath this is the image of a spaceman rocketing upwards by means of what appears to be a match and flatulence." }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel, /area/hallway/secondary/entry) "ano" = ( /obj/structure/disposalpipe/segment, @@ -6201,12 +6171,20 @@ /turf/open/floor/grass, /area/hydroponics) "aoJ" = ( -/obj/machinery/atmospherics/pipe/simple/supply/visible, -/obj/machinery/space_heater, -/turf/open/floor/plasteel, -/area/engine/engineering{ - name = "Engine Room" - }) +/obj/machinery/firealarm{ + pixel_y = 26 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) "aoK" = ( /turf/closed/wall/r_wall, /area/router/service) @@ -6301,7 +6279,7 @@ /obj/machinery/conveyor{ id = "serv_off" }, -/obj/machinery/door/poddoor/preopen{ +/obj/machinery/door/poddoor{ id = "servblock"; name = "Service Router" }, @@ -6310,7 +6288,7 @@ "aoT" = ( /obj/structure/plasticflaps, /obj/structure/fans/tiny, -/obj/machinery/door/poddoor/preopen{ +/obj/machinery/door/poddoor{ id = "servblock"; name = "Service Router" }, @@ -6337,16 +6315,16 @@ /turf/open/floor/plasteel, /area/security/brig) "aoW" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/external/glass{ - name = "Port Bow Solars External Access"; - req_access_txt = "10;13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +/obj/machinery/power/solar_control{ + dir = 4; + id = "foreport"; + name = "Port Bow Solar Control" }, /obj/structure/cable{ - icon_state = "4-8" + icon_state = "0-4" + }, +/obj/structure/cable{ + icon_state = "2-4" }, /turf/open/floor/plating, /area/maintenance/solars/port) @@ -6976,14 +6954,9 @@ /area/security/brig) "aqA" = ( /obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "0-2" - }, -/obj/structure/cable{ - icon_state = "1-2" - }, +/obj/structure/cable, /turf/open/space/basic, -/area/solar/starboard/fore) +/area/solar/starboard/aft) "aqB" = ( /turf/closed/wall, /area/hydroponics) @@ -7346,12 +7319,19 @@ /turf/open/floor/plasteel, /area/security/brig) "arr" = ( -/obj/structure/table, -/obj/machinery/cell_charger, -/obj/structure/sign/warning/vacuum/external{ - pixel_x = -32 +/obj/machinery/light/small{ + dir = 1; + light_color = "#ffc1c1" + }, +/obj/machinery/power/terminal{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/structure/chair{ + dir = 8 }, -/obj/item/stock_parts/cell/high/plus, /turf/open/floor/plating, /area/maintenance/solars/port) "ars" = ( @@ -7785,10 +7765,16 @@ /turf/open/floor/plasteel, /area/security/prison) "asl" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/machinery/camera{ - c_tag = "Port Bow Solar Maintenance"; - dir = 1 +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/external/glass{ + name = "Port Bow Solars External Access"; + req_access_txt = "10;13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 }, /turf/open/floor/plating, /area/maintenance/solars/port) @@ -8002,12 +7988,18 @@ name = "Canister Storage" }) "asH" = ( -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -26 +/obj/machinery/camera{ + c_tag = "Port Bow Solar Maintenance"; + dir = 1 }, -/obj/machinery/atmospherics/pipe/manifold/general/visible{ - dir = 8 +/obj/structure/table, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/high/plus, +/obj/structure/sign/warning/vacuum/external{ + pixel_x = -32 + }, +/obj/structure/sign/warning/electricshock{ + pixel_y = -32 }, /turf/open/floor/plating, /area/maintenance/solars/port) @@ -8247,12 +8239,16 @@ /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/kitchen) "atn" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/obj/machinery/atmospherics/pipe/manifold/general/visible{ dir = 8 }, -/obj/machinery/door/airlock/external, -/turf/open/floor/plasteel, -/area/router/service) +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/plating, +/area/maintenance/solars/port) "ato" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -8613,7 +8609,7 @@ /obj/effect/turf_decal/tile/bar{ dir = 1 }, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/item/toy/cards/deck, /turf/open/floor/plasteel, /area/crew_quarters/bar) @@ -9042,10 +9038,6 @@ /area/hallway/secondary/civilian) "avg" = ( /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/public/glass{ - name = "Brig"; - req_access_txt = "2" - }, /obj/structure/cable{ icon_state = "4-8" }, @@ -9054,6 +9046,12 @@ /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, +/obj/machinery/turnstile{ + name = "Genpop Entrance Turnstile"; + icon_state = "turnstile_map"; + dir = 8; + req_access_txt = "69" + }, /turf/open/floor/plasteel, /area/security/prison) "avh" = ( @@ -9161,13 +9159,10 @@ "avr" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "1-8" - }, -/obj/structure/cable{ - icon_state = "1-4" + icon_state = "0-8" }, /turf/open/space/basic, -/area/solar/starboard/fore) +/area/solar/starboard/aft) "avs" = ( /turf/closed/wall, /area/router/service) @@ -9548,7 +9543,7 @@ /obj/effect/turf_decal/tile/green{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on, @@ -9727,10 +9722,19 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, +/obj/machinery/turnstile{ + name = "Genpop Entrance Turnstile"; + icon_state = "turnstile_map"; + dir = 8; + req_access_txt = "69" + }, /turf/open/floor/plasteel, /area/security/prison) "awI" = ( @@ -9820,6 +9824,10 @@ dir = 1 }, /obj/effect/turf_decal/tile/bar, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, /turf/open/floor/plasteel, /area/security/main) "awR" = ( @@ -9903,13 +9911,21 @@ name = "Thermo-Electric Generator" }) "awY" = ( -/obj/structure/closet/wardrobe/orange, /obj/effect/turf_decal/tile/red{ dir = 1 }, /obj/effect/turf_decal/tile/red{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/machinery/button/door{ + id = "solitarylock"; + name = "Solitary Lockdown"; + pixel_x = -24; + req_access_txt = "2" + }, /turf/open/floor/plasteel, /area/security/brig) "awZ" = ( @@ -10015,7 +10031,7 @@ pixel_y = 28 }, /obj/effect/turf_decal/bot, -/obj/structure/closet/secure_closet/brig, +/obj/structure/closet/secure_closet/genpop, /turf/open/floor/plasteel, /area/security/brig) "axj" = ( @@ -10442,13 +10458,11 @@ /turf/open/floor/circuit, /area/ai_monitored/turret_protected/ai) "aya" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 }, -/obj/machinery/camera{ - c_tag = "AI Core Exterior"; - dir = 1 +/obj/structure/cable{ + icon_state = "2-4" }, /turf/open/floor/plating/airless, /area/space/nearstation) @@ -10780,6 +10794,10 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, /turf/open/floor/plasteel, /area/security/main) "ayP" = ( @@ -10943,6 +10961,7 @@ /area/maintenance/port/central) "aze" = ( /obj/machinery/power/apc{ + dir = 1; name = "AI Chamber APC"; pixel_y = 24 }, @@ -11617,13 +11636,6 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/item/gun/energy/e_gun/advtaser{ - pixel_y = 6 - }, -/obj/item/gun/energy/e_gun/advtaser, -/obj/item/gun/energy/e_gun/advtaser{ - pixel_y = -6 - }, /obj/machinery/vending/security, /turf/open/floor/plasteel, /area/security/brig) @@ -12159,6 +12171,10 @@ dir = 1 }, /obj/effect/turf_decal/tile/bar, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, /turf/open/floor/plasteel, /area/security/main) "aBy" = ( @@ -12171,7 +12187,7 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/machinery/camera{ @@ -12687,6 +12703,9 @@ pixel_x = 24; req_access_txt = "2" }, +/obj/effect/turf_decal/arrows/red{ + dir = 1 + }, /turf/open/floor/plasteel, /area/security/brig) "aCF" = ( @@ -12709,18 +12728,21 @@ /turf/open/floor/plasteel, /area/security/brig) "aCH" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/public/glass{ - name = "Brig"; - req_access_txt = "2" +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/obj/effect/turf_decal/delivery, -/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/arrows/red{ + dir = 8 + }, +/obj/effect/turf_decal/arrows/red{ + dir = 1 + }, /turf/open/floor/plasteel, -/area/security/prison) +/area/security/brig) "aCI" = ( /obj/effect/turf_decal/tile/green, /obj/effect/turf_decal/tile/green{ @@ -13373,15 +13395,23 @@ /turf/open/floor/plating, /area/maintenance/solars/port) "aDW" = ( -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, +/obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, +/obj/effect/turf_decal/delivery, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, +/obj/machinery/turnstile{ + dir = 4; + name = "Genpop Exit Turnstile"; + req_access_txt = "70" + }, /turf/open/floor/plasteel, -/area/security/brig) +/area/security/prison) "aDX" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -13393,6 +13423,10 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/machinery/door/poddoor/preopen{ + id = "briglockdown"; + name = "Brig Lockdown" + }, /turf/open/floor/plasteel, /area/security/prison) "aDZ" = ( @@ -13757,7 +13791,7 @@ /turf/open/floor/carpet, /area/chapel/main) "aEJ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /turf/open/floor/wood, @@ -13795,7 +13829,7 @@ /turf/open/floor/wood, /area/crew_quarters/barbershop) "aEP" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/wood, /area/crew_quarters/barbershop) "aEQ" = ( @@ -14374,7 +14408,9 @@ /turf/open/floor/plasteel, /area/storage/emergency/generic) "aFX" = ( -/obj/structure/filingcabinet, +/obj/machinery/computer/security/hos{ + dir = 4 + }, /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/hos) "aFY" = ( @@ -14809,7 +14845,9 @@ c_tag = "Security - Head of Security's Office"; pixel_x = 22 }, -/obj/machinery/computer/security/hos, +/obj/structure/chair/comfy/brown{ + dir = 8 + }, /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/hos) "aGL" = ( @@ -14971,13 +15009,19 @@ /turf/open/floor/plasteel/stairs/medium, /area/hallway/secondary/entry) "aHa" = ( -/obj/structure/disposalpipe/junction/yjunction, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 8 +/obj/structure/cable, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/locker"; + dir = 8; + name = "Locker Room APC"; + pixel_x = -24 }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plasteel, -/area/hallway/primary/port/fore) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/fore) "aHb" = ( /obj/structure/chair, /obj/machinery/firealarm{ @@ -15065,19 +15109,19 @@ }, /area/chapel/main) "aHj" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "4-8" }, -/obj/machinery/door/airlock/external{ - name = "Starboard Bow Solar Exterior Airlock"; - req_access_txt = "10;13" +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 }, -/turf/open/floor/plating, -/area/maintenance/solars/starboard/fore) +/turf/open/floor/plasteel, +/area/tcommsat/computer) "aHk" = ( /obj/structure/chair{ dir = 4 @@ -15125,12 +15169,12 @@ /turf/open/floor/plasteel, /area/tcommsat/computer) "aHp" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden, -/turf/open/floor/plasteel, -/area/hallway/primary/port/fore) +/turf/open/floor/plating, +/area/maintenance/fore) "aHq" = ( /obj/effect/turf_decal/bot, /obj/structure/disposalpipe/segment, @@ -15233,13 +15277,14 @@ /area/bridge) "aHE" = ( /obj/structure/cable{ - icon_state = "2-4" + icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/turf/open/floor/plating, +/area/tcommsat/computer) "aHF" = ( /turf/open/floor/plasteel/dark, /area/bridge) @@ -15803,12 +15848,16 @@ /turf/open/floor/carpet/royalblue, /area/bridge) "aIJ" = ( -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/maintenance{ + name = "Fore Maintenance"; + req_one_access_txt = "12;46" }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plasteel, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, /area/hallway/primary/port/fore) "aIK" = ( /obj/structure/table/wood, @@ -16299,8 +16348,9 @@ }, /obj/effect/turf_decal/tile/red, /obj/item/storage/belt/medical, -/obj/item/clothing/suit/space/hardsuit/medical, /obj/item/tank/internals/emergency_oxygen, +/obj/item/clothing/suit/space/eva/paramedic, +/obj/item/clothing/head/helmet/space/eva/paramedic, /turf/open/floor/plasteel/white, /area/medical/medbay/zone2{ name = "Medbay Treatment Center" @@ -16481,11 +16531,28 @@ /turf/open/floor/plasteel, /area/security/main) "aJV" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/closed/wall, -/area/security/prison) +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel, +/area/science/research{ + name = "Research Sector" + }) "aJW" = ( /obj/machinery/cryopod{ dir = 8 @@ -16748,7 +16815,7 @@ /area/bridge) "aKw" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/item/toy/cards/deck, /obj/structure/disposalpipe/segment{ dir = 4 @@ -16773,7 +16840,7 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/machinery/flasher/portable, +/obj/machinery/rnd/production/techfab/department/security, /turf/open/floor/plasteel, /area/security/brig) "aKz" = ( @@ -17033,13 +17100,22 @@ /turf/open/floor/plating, /area/maintenance/fore) "aLc" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Central Maintenance"; - req_one_access_txt = "12" +/obj/structure/disposalpipe/segment{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plating, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, /area/hallway/primary/port/fore) "aLd" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, @@ -17248,7 +17324,7 @@ /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-06" }, /turf/open/floor/plasteel, @@ -17665,14 +17741,16 @@ /turf/closed/wall, /area/maintenance/department/chapel) "aMo" = ( -/obj/structure/disposalpipe/segment{ - dir = 6 +/obj/structure/disposalpipe/junction/yjunction, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "1-4" }, -/turf/open/floor/plating, -/area/maintenance/starboard/central) +/turf/open/floor/plasteel, +/area/hallway/primary/port/fore) "aMp" = ( /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/simple/orange/hidden, @@ -17824,18 +17902,15 @@ }, /area/chapel/main) "aMG" = ( -/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/manifold4w/supplymain/hidden, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "2-8" }, -/obj/machinery/camera{ - c_tag = "Central Starboard Maintenance"; - dir = 8; - pixel_y = -22 - }, -/mob/living/simple_animal/hostile/retaliate/bat, -/turf/open/floor/plating, -/area/maintenance/starboard/central) +/turf/open/floor/plasteel, +/area/hallway/primary/port/fore) "aMH" = ( /obj/structure/cable{ icon_state = "2-8" @@ -18308,7 +18383,7 @@ pixel_x = 22 }, /obj/machinery/power/apc/highcap/fifteen_k{ - areastring = "area/tcommsat/computer"; + areastring = "/area/tcommsat/server"; dir = 1; name = "Telecomms Server APC"; pixel_y = 24 @@ -18317,7 +18392,7 @@ dir = 4 }, /turf/open/floor/plasteel, -/area/tcommsat/computer) +/area/tcommsat/server) "aND" = ( /turf/open/floor/plasteel/white, /area/medical{ @@ -18660,7 +18735,7 @@ /obj/structure/sign/warning/securearea{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_y = 3 }, @@ -18676,7 +18751,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/plasteel/dark/side{ dir = 1 }, @@ -19373,7 +19448,7 @@ icon_state = "4-8" }, /turf/open/floor/plating/airless, -/area/space/nearstation) +/area/crew_quarters/fitness/cogpool) "aPS" = ( /obj/machinery/holopad, /turf/open/floor/plasteel/white, @@ -19794,7 +19869,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ @@ -19824,9 +19899,16 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/fitness/cogpool) "aQS" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plating, -/area/maintenance/central) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/fore) "aQT" = ( /obj/machinery/door/airlock/engineering{ name = "Thermo-Electric Generator"; @@ -20346,7 +20428,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ @@ -20910,19 +20992,18 @@ /turf/open/floor/plasteel, /area/security/brig) "aTh" = ( -/obj/effect/turf_decal/stripes/line, -/obj/machinery/light{ +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/door/airlock/external/glass{ + name = "Telecommunications External Access"; + req_access_txt = "61" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, -/obj/machinery/power/apc{ - name = "AI Upload Foyer APC"; - pixel_y = -24 - }, -/obj/structure/cable{ - icon_state = "0-4" - }, -/turf/open/floor/plasteel, -/area/ai_monitored/turret_protected/ai_upload_foyer) +/turf/open/floor/plating, +/area/tcommsat/computer) "aTi" = ( /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -21208,7 +21289,7 @@ name = "Station Intercom (Common)"; pixel_x = -26 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel, @@ -21752,7 +21833,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/red, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/machinery/airalarm{ @@ -22306,6 +22387,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/machinery/computer/gateway_control{ + dir = 8 + }, /turf/open/floor/plasteel/dark/side{ dir = 4 }, @@ -22326,11 +22410,17 @@ /turf/open/floor/plating, /area/maintenance/department/eva) "aWr" = ( -/obj/machinery/gateway{ - dir = 10 +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/maintenance{ + name = "Central Maintenance"; + req_one_access_txt = "12" }, -/turf/open/floor/engine, -/area/gateway) +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/hallway/primary/port/fore) "aWs" = ( /obj/machinery/light{ dir = 8; @@ -22358,16 +22448,10 @@ /turf/open/floor/plating, /area/maintenance/central) "aWu" = ( -/obj/structure/cable{ - icon_state = "0-2" - }, -/obj/machinery/power/apc{ - areastring = "/area/crew_quarters/fitness/cogpool"; - dir = 4; - name = "Pool APC"; - pixel_x = 24 - }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plating, /area/maintenance/central) "aWv" = ( @@ -22725,24 +22809,18 @@ /turf/open/floor/wood, /area/library) "aXf" = ( -/obj/structure/window/reinforced/spawner/east, -/obj/structure/table/wood, +/obj/machinery/photocopier, /obj/machinery/light{ dir = 1; - light_color = "#c1caff" + light_color = "#e8eaff" }, -/turf/open/floor/carpet, -/area/library) +/obj/item/paper/fluff/cogstation/eva, +/turf/open/floor/plasteel/dark, +/area/security/checkpoint/customs) "aXg" = ( -/obj/structure/bookcase/random/reference, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/wood, -/area/library) +/obj/machinery/vending/coffee, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "aXh" = ( /obj/machinery/atmospherics/pipe/simple/supply/visible{ dir = 6 @@ -22791,9 +22869,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "aXm" = ( -/obj/machinery/gateway, -/turf/open/floor/engine, -/area/gateway) +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 1 + }, +/turf/closed/wall/r_wall, +/area/tcommsat/computer) "aXn" = ( /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ @@ -22834,11 +22914,14 @@ /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) "aXs" = ( -/obj/machinery/gateway{ - dir = 6 +/obj/structure/cable{ + icon_state = "4-8" }, -/turf/open/floor/engine, -/area/gateway) +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/turf/open/floor/plating, +/area/tcommsat/computer) "aXt" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/warning/securearea, @@ -22863,7 +22946,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /turf/open/floor/plasteel/dark/side, @@ -23326,7 +23409,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/atmospherics/pipe/simple/orange/hidden, @@ -23400,6 +23483,17 @@ }, /turf/open/floor/plasteel/grimy, /area/security/detectives_office) +"aYG" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/light, +/obj/structure/disposalpipe/junction/flip{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "aYH" = ( /obj/effect/turf_decal/tile/yellow{ dir = 8 @@ -23824,35 +23918,20 @@ /turf/closed/wall, /area/lawoffice) "aZz" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/lattice, +/obj/machinery/camera{ + c_tag = "Routing Depot - Fore Exterior"; dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/item/paper_bin, -/obj/item/pen, -/turf/open/floor/plasteel/dark, -/area/lawoffice) +/turf/open/space/basic, +/area/maintenance/department/eva) "aZA" = ( -/obj/structure/table/reinforced, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/computer/card{ dir = 8 }, +/obj/item/paper/guides/cogstation/job_changes, /turf/open/floor/plasteel/dark, -/area/lawoffice) +/area/security/checkpoint/customs) "aZB" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -23872,7 +23951,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/book/manual/wiki/security_space_law, +/obj/item/paper_bin, +/obj/item/pen, +/obj/structure/window/reinforced/spawner/north, /turf/open/floor/plasteel/dark, /area/lawoffice) "aZD" = ( @@ -23929,13 +24010,21 @@ /turf/open/floor/plasteel, /area/hallway/secondary/civilian) "aZI" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/landmark/start/lawyer, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/door/window/northleft{ + name = "Law Office Counter"; + req_access_txt = "38" + }, /turf/open/floor/plasteel/dark, /area/lawoffice) "aZJ" = ( @@ -24298,6 +24387,15 @@ }, /turf/open/floor/carpet, /area/crew_quarters/bar) +"bau" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/disposalpipe/junction/flip{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/science/lab) "bav" = ( /obj/structure/chair/sofa/right, /obj/machinery/firealarm{ @@ -24328,13 +24426,21 @@ /turf/open/floor/wood, /area/library) "baz" = ( -/obj/machinery/photocopier, -/obj/machinery/light{ - dir = 1; - light_color = "#e8eaff" +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/item/book/manual/wiki/security_space_law, +/obj/structure/window/reinforced/spawner/north, /turf/open/floor/plasteel/dark, -/area/security/checkpoint/customs) +/area/lawoffice) "baA" = ( /obj/structure/filingcabinet/chestdrawer, /obj/item/folder/blue, @@ -24367,10 +24473,12 @@ /turf/open/floor/plasteel/dark, /area/security/checkpoint/customs) "baE" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 +/obj/structure/bookcase/random/reference, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, -/turf/open/floor/wood, +/turf/open/floor/plasteel/dark, /area/library) "baF" = ( /obj/structure/chair/office/dark{ @@ -24919,18 +25027,21 @@ /turf/open/floor/plating, /area/security/checkpoint/customs) "bbQ" = ( -/obj/structure/sign/warning/vacuum/external{ - pixel_x = -32; - pixel_y = 32 +/obj/structure/cable{ + icon_state = "0-2" }, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/fitness/cogpool"; + dir = 4; + name = "Pool APC"; + pixel_x = 24 + }, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plasteel, -/area/engine/engineering{ - name = "Engine Room" - }) +/turf/open/floor/plating, +/area/maintenance/central) "bbR" = ( /obj/structure/closet/crate/hydroponics, /obj/effect/turf_decal/tile/green, @@ -25011,7 +25122,7 @@ /turf/closed/wall/r_wall, /area/space/nearstation) "bcd" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel/white, @@ -25179,11 +25290,17 @@ /turf/closed/wall/r_wall, /area/science/mixing) "bcz" = ( -/obj/machinery/computer/card{ - dir = 8 +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/newscaster{ + pixel_x = -30 }, /turf/open/floor/plasteel/dark, -/area/security/checkpoint/customs) +/area/lawoffice) "bcA" = ( /obj/effect/turf_decal/tile/brown{ dir = 1 @@ -26028,9 +26145,21 @@ /turf/open/floor/plasteel, /area/quartermaster/office) "beC" = ( -/obj/machinery/recharge_station, -/turf/open/floor/plating, -/area/ai_monitored/turret_protected/ai_upload_foyer) +/obj/structure/rack, +/obj/item/storage/toolbox/mechanical, +/obj/item/radio/off, +/obj/effect/turf_decal/tile/yellow, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/turf/open/floor/plasteel, +/area/tcommsat/computer) "beD" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 @@ -26053,13 +26182,16 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "beG" = ( -/obj/structure/lattice, -/obj/machinery/camera{ - c_tag = "Routing Depot - Fore Exterior"; +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/turf/open/space/basic, -/area/space/nearstation) +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/landmark/start/lawyer, +/obj/structure/chair/stool, +/turf/open/floor/plasteel/dark, +/area/lawoffice) "beH" = ( /obj/structure/window/reinforced/spawner/east, /obj/machinery/light{ @@ -26419,6 +26551,7 @@ dir = 1 }, /obj/effect/spawner/lootdrop/maintenance, +/obj/machinery/atmospherics/components/unary/thermomachine/heater/on, /turf/open/floor/plating, /area/crew_quarters/fitness/cogpool) "bfz" = ( @@ -26675,6 +26808,19 @@ /obj/effect/landmark/start/cargo_technician, /turf/open/floor/plasteel, /area/quartermaster/sorting) +"bga" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "bgb" = ( /obj/structure/disposalpipe/sorting/mail{ sortType = 30 @@ -27000,8 +27146,8 @@ /area/quartermaster/warehouse) "bgJ" = ( /obj/machinery/portable_atmospherics/pump, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 }, /turf/open/floor/plating, /area/crew_quarters/fitness/cogpool) @@ -27322,19 +27468,16 @@ /turf/open/floor/wood, /area/medical/medbay/lobby) "bhy" = ( -/obj/structure/closet/crate/science, -/obj/item/stack/sheet/metal/ten, -/obj/item/stack/sheet/glass/five, -/obj/item/stack/rods/twentyfive, -/obj/item/target/syndicate, -/obj/item/target/alien, -/obj/item/target, -/obj/item/target/clown, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 10 +/obj/structure/plasticflaps, +/obj/structure/fans/tiny, +/obj/machinery/conveyor/auto{ + id = "sec" }, -/turf/open/floor/plasteel, -/area/science/mixing) +/obj/machinery/door/poddoor{ + name = "Security Router" + }, +/turf/open/floor/plating, +/area/router/sec) "bhz" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ @@ -27467,7 +27610,7 @@ dir = 1 }, /obj/structure/disposalpipe/segment, -/obj/item/twohanded/required/kirbyplants/dead, +/obj/item/kirbyplants/dead, /turf/open/floor/plasteel, /area/security/main) "bhO" = ( @@ -27502,7 +27645,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_y = 3 }, @@ -27703,8 +27846,15 @@ /turf/open/floor/plating, /area/quartermaster/storage) "bim" = ( -/turf/open/space/basic, -/area/space/nearstation) +/obj/effect/decal/cleanable/dirt, +/obj/machinery/button/massdriver{ + id = "router_in"; + name = "mass driver button (Router)"; + pixel_x = 24; + pixel_y = -8 + }, +/turf/open/floor/plating, +/area/maintenance/disposal) "bin" = ( /obj/machinery/computer/mecha{ dir = 4 @@ -27922,7 +28072,7 @@ dir = 4; light_color = "#c1caff" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20"; pixel_y = 3 }, @@ -28002,6 +28152,13 @@ /obj/machinery/pipedispenser, /turf/open/floor/plasteel, /area/science/mixing) +"biU" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/maintenance/aft) "biV" = ( /turf/closed/wall, /area/storage/primary) @@ -28847,7 +29004,7 @@ dir = 4; light_color = "#c1caff" }, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /obj/item/stock_parts/cell/high/plus, /obj/item/clothing/glasses/meson, /obj/item/cartridge/atmos, @@ -29276,15 +29433,7 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/item/surgical_drapes, -/obj/item/scalpel, -/obj/item/circular_saw{ - pixel_y = 16 - }, -/obj/item/hemostat, -/obj/item/retractor, -/obj/item/surgicaldrill, -/obj/item/cautery, +/obj/item/storage/backpack/duffelbag/med/surgery, /turf/open/floor/plasteel/white, /area/medical/medbay/zone2{ name = "Medbay Treatment Center" @@ -29502,6 +29651,13 @@ }, /turf/closed/wall/r_wall, /area/science/mixing) +"blU" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/closet/cardboard, +/turf/open/floor/plating, +/area/maintenance/aft) "blV" = ( /obj/machinery/computer/cargo{ dir = 8 @@ -30240,11 +30396,17 @@ /turf/open/floor/plasteel, /area/science/mixing) "bnl" = ( -/obj/machinery/gateway{ - dir = 9 +/obj/structure/cable{ + icon_state = "1-4" }, -/turf/open/floor/engine, -/area/gateway) +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/central) "bnm" = ( /obj/machinery/atmospherics/pipe/manifold/orange/hidden{ dir = 4 @@ -30516,9 +30678,11 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bnS" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/on, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/cogpool) "bnT" = ( /obj/structure/disposalpipe/segment, /turf/closed/wall/r_wall, @@ -30635,17 +30799,17 @@ /turf/open/floor/plasteel, /area/ai_monitored/nuke_storage) "bof" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, /obj/machinery/door/airlock/external/glass{ name = "Pool Exterior Access"; req_access_txt = "13" }, -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, -/turf/open/floor/plating, +/turf/open/space/basic, /area/crew_quarters/fitness/cogpool) "bog" = ( /obj/machinery/light{ @@ -31292,13 +31456,28 @@ /turf/open/space/basic, /area/space/nearstation) "bpA" = ( -/obj/structure/closet/emcloset, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 26 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "bpB" = ( -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/closed/wall, +/area/hallway/primary/aft) "bpC" = ( /obj/effect/turf_decal/plaque{ icon_state = "L10" @@ -31599,8 +31778,14 @@ }, /area/hallway/secondary/exit) "bqq" = ( -/turf/closed/wall, -/area/science/robotics/lab) +/obj/machinery/chem_master, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/camera{ + c_tag = "Medbay - Chemistry Lab"; + network = list("ss13","rd") + }, +/turf/open/floor/plasteel, +/area/medical/chemistry) "bqr" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -31612,10 +31797,12 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bqs" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/disposalpipe/segment, +/obj/structure/closet/emcloset, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/plating, -/area/science/robotics/lab) +/area/maintenance/aft) "bqt" = ( /obj/structure/table, /obj/effect/turf_decal/tile/red{ @@ -31629,7 +31816,6 @@ /obj/item/clothing/mask/surgical, /obj/item/healthanalyzer, /obj/item/clothing/neck/stethoscope, -/obj/item/razor, /turf/open/floor/plasteel/white, /area/medical/medbay/zone2{ name = "Medbay Treatment Center" @@ -31694,16 +31880,8 @@ /turf/open/floor/plasteel, /area/quartermaster/miningoffice) "bqz" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/machinery/light, -/obj/structure/disposalpipe/junction/flip{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) +/turf/closed/wall, +/area/medical/chemistry) "bqA" = ( /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ @@ -31825,7 +32003,7 @@ /obj/effect/turf_decal/tile/green{ dir = 4 }, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/item/toy/cards/deck, /turf/open/floor/plasteel/white/corner{ dir = 1 @@ -32192,9 +32370,26 @@ /turf/open/floor/plasteel, /area/hallway/secondary/civilian) "brz" = ( -/obj/machinery/computer/rdconsole/robotics, -/turf/open/floor/circuit, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/machinery/power/apc{ + areastring = "/area/science/research"; + name = "Research Sector APC"; + pixel_y = -24 + }, +/obj/structure/cable, +/turf/open/floor/plasteel, +/area/science/research{ + name = "Research Sector" + }) "brA" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -32252,14 +32447,14 @@ /turf/open/floor/plasteel, /area/hallway/secondary/civilian) "brF" = ( -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/stripes/white/full, -/obj/effect/turf_decal/stripes/line, -/obj/structure/disposalpipe/trunk{ - dir = 1 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "chem1"; + name = "chem lab shutters" }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/medical/chemistry) "brG" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -32274,13 +32469,9 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/hos) "brH" = ( -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/obj/structure/disposalpipe/trunk, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment, +/turf/closed/wall, +/area/medical/chemistry) "brI" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -32298,32 +32489,21 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "brJ" = ( -/obj/machinery/vending/assist, -/obj/machinery/light/small{ - dir = 1; - light_color = "#ffc1c1" +/obj/effect/spawner/lootdrop/maintenance, +/obj/structure/disposalpipe/segment{ + dir = 4 }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/turf/open/floor/plating, +/area/maintenance/aft) "brK" = ( -/obj/structure/closet/crate/medical, -/obj/item/storage/firstaid/regular{ - empty = 1; - name = "First-Aid (empty)" +/obj/structure/window/reinforced/spawner/east, +/obj/machinery/chem_dispenser, +/obj/machinery/airalarm{ + pixel_y = 24 }, -/obj/item/storage/firstaid/regular{ - empty = 1; - name = "First-Aid (empty)" - }, -/obj/item/storage/firstaid/regular{ - empty = 1; - name = "First-Aid (empty)" - }, -/obj/item/healthanalyzer, -/obj/item/healthanalyzer, -/obj/item/healthanalyzer, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, -/area/science/robotics/lab) +/area/medical/chemistry) "brL" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -32482,7 +32662,7 @@ /turf/open/floor/plasteel, /area/maintenance/disposal) "brZ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /turf/open/floor/wood, @@ -32730,19 +32910,9 @@ /turf/open/floor/plasteel/stairs/left, /area/hydroponics) "bsx" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/door/airlock/external{ - name = "Recycler Exterior Access"; - req_one_access_txt = "13;50" - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plasteel, -/area/maintenance/disposal) +/obj/structure/lattice, +/turf/closed/wall/r_wall, +/area/crew_quarters/fitness/cogpool) "bsy" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment, @@ -32802,11 +32972,14 @@ /turf/open/floor/grass, /area/hydroponics) "bsG" = ( -/obj/item/twohanded/required/kirbyplants{ - icon_state = "plant-03" +/obj/effect/decal/cleanable/dirt, +/obj/structure/table, +/obj/effect/decal/cleanable/cobweb, +/obj/structure/sign/poster/contraband/borg_fancy_2{ + pixel_y = 32 }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/turf/open/floor/plasteel, +/area/maintenance/aft) "bsH" = ( /obj/structure/table/glass, /obj/item/storage/box/syringes{ @@ -32844,21 +33017,41 @@ /turf/open/floor/grass, /area/hydroponics) "bsL" = ( -/obj/effect/turf_decal/stripes/corner, -/obj/effect/landmark/start/roboticist, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/table, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/machinery/reagentgrinder{ + pixel_y = 8 + }, +/obj/item/storage/box/syringes, +/obj/item/storage/box/beakers{ + pixel_x = -2; + pixel_y = -2 + }, +/turf/open/floor/plasteel, +/area/medical/chemistry) "bsM" = ( -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel/dark, +/turf/closed/wall, /area/science/robotics/lab) "bsN" = ( +/obj/structure/table, /obj/effect/turf_decal/stripes/line, -/obj/structure/disposalpipe/segment{ - dir = 5 +/obj/machinery/light{ + dir = 1 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/item/stack/sheet/mineral/plasma, +/obj/item/stack/cable_coil/random, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/screwdriver{ + pixel_x = -2; + pixel_y = 6 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel, +/area/medical/chemistry) "bsO" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -32866,20 +33059,22 @@ /turf/closed/wall/r_wall, /area/hallway/secondary/civilian) "bsP" = ( -/obj/effect/turf_decal/stripes/corner{ +/obj/structure/disposalpipe/trunk{ dir = 1 }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/stripes/white/full, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/medical/chemistry) "bsQ" = ( -/obj/structure/disposalpipe/segment{ - dir = 9 +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/stripes/line{ + dir = 6 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/disposalpipe/trunk, +/turf/open/floor/plasteel, +/area/medical/chemistry) "bsR" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel/grimy, @@ -32899,9 +33094,7 @@ /turf/open/space/basic, /area/space/nearstation) "bsU" = ( -/obj/effect/landmark/start/roboticist, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "bsV" = ( /turf/closed/wall, @@ -33039,18 +33232,27 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "btn" = ( -/obj/machinery/computer/mech_bay_power_console, -/turf/open/floor/plasteel, -/area/science/robotics/lab) -"bto" = ( -/turf/open/floor/mech_bay_recharge_floor, -/area/science/robotics/lab) -"btp" = ( -/obj/machinery/mech_bay_recharge_port{ - dir = 8 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics"; + name = "robotics lab shutters" }, /turf/open/floor/plating, /area/science/robotics/lab) +"bto" = ( +/turf/open/floor/plasteel, +/area/science/robotics/lab) +"btp" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/window/reinforced/spawner, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "btq" = ( /obj/machinery/vending/cigarette, /obj/effect/decal/cleanable/dirt, @@ -33073,8 +33275,13 @@ /turf/open/floor/plating, /area/maintenance/department/chapel) "bts" = ( -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/effect/decal/cleanable/dirt, +/obj/structure/light_construct/small{ + icon_state = "bulb-construct-stage1"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/aft) "btt" = ( /obj/structure/chair{ dir = 8 @@ -33104,28 +33311,16 @@ /turf/closed/wall, /area/hallway/secondary/civilian) "btv" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical, -/obj/item/storage/belt/utility, -/obj/item/stack/cable_coil/random, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/landmark/event_spawn, +/turf/open/floor/plating, +/area/maintenance/aft) "btw" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/light/small, -/turf/open/floor/plating{ - icon_state = "platingdmg2" - }, -/area/maintenance/department/eva) +/obj/machinery/atmospherics/components/unary/outlet_injector/on, +/turf/open/floor/plating/airless, +/area/router) "btx" = ( /obj/machinery/space_heater, /turf/open/floor/plating, @@ -33327,17 +33522,8 @@ /turf/open/floor/plating, /area/router) "bua" = ( -/obj/machinery/camera{ - c_tag = "Robotics Backroom"; - dir = 8; - network = list("ss13","medbay"); - pixel_y = -22 - }, -/obj/structure/sign/poster/contraband/borg_fancy_2{ - pixel_x = 32 - }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/turf/closed/wall/r_wall, +/area/science/robotics/mechbay) "bub" = ( /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ @@ -33391,11 +33577,9 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit) "buj" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/closet/crate, +/turf/open/floor/plating, +/area/maintenance/aft) "buk" = ( /obj/structure/cable{ icon_state = "1-2" @@ -33410,15 +33594,9 @@ /turf/open/floor/plating, /area/router) "bul" = ( -/obj/machinery/light_switch{ - pixel_x = 24 - }, -/obj/machinery/light{ - dir = 4; - light_color = "#c1caff" - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/girder, +/turf/open/floor/plating, +/area/maintenance/aft) "bum" = ( /obj/structure/closet/crate, /obj/effect/spawner/lootdrop/maintenance, @@ -33760,9 +33938,18 @@ /area/janitor) "bvb" = ( /obj/structure/disposalpipe/segment, -/obj/effect/landmark/blobstart, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/engineering{ + name = "Electrical Substation"; + req_access_txt = "10" + }, +/obj/structure/fans/tiny, /turf/open/floor/plating, -/area/maintenance/starboard/central) +/area/engine/storage_shared{ + name = "Electrical Substation" + }) "bvc" = ( /obj/machinery/computer/cargo/request, /obj/machinery/airalarm{ @@ -33791,7 +33978,7 @@ /turf/open/floor/plating, /area/construction) "bvf" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/carpet{ @@ -33869,16 +34056,12 @@ /turf/open/floor/plating, /area/maintenance/solars/starboard/fore) "bvn" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, +/obj/machinery/rnd/production/protolathe/department/science, /obj/structure/disposalpipe/segment{ - dir = 5 + dir = 4 }, -/obj/structure/window/reinforced/spawner, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/turf/open/floor/plasteel, +/area/science/lab) "bvo" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 @@ -34046,11 +34229,11 @@ /turf/open/floor/carpet/green, /area/crew_quarters/heads/hop) "bvK" = ( -/obj/structure/table/optable, -/obj/item/tank/internals/anesthetic, -/obj/item/clothing/mask/breath, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "bvL" = ( /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ @@ -34063,17 +34246,13 @@ /turf/open/floor/plasteel, /area/crew_quarters/bar) "bvM" = ( -/obj/machinery/door/airlock/external/glass{ - name = "External Construction Access"; - req_one_access_txt = "10;31" +/obj/structure/lattice, +/obj/machinery/camera{ + c_tag = "Routing Depot - Aft Exterior"; + pixel_x = 22 }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plasteel, -/area/quartermaster/warehouse) +/turf/open/space/basic, +/area/router) "bvN" = ( /obj/machinery/atmospherics/components/binary/valve/digital/on{ dir = 4 @@ -34228,9 +34407,11 @@ /turf/open/floor/plating, /area/maintenance/department/chapel) "bwf" = ( -/obj/machinery/computer/operating, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "bwg" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -34318,10 +34499,13 @@ /turf/open/floor/plating, /area/maintenance/starboard/central) "bwp" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-8" +/obj/structure/disposalpipe/segment{ + dir = 6 }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plating, /area/maintenance/starboard/central) "bwq" = ( @@ -34536,9 +34720,6 @@ c_tag = "Research - Gateway Chamber"; network = list("ss13","rd") }, -/obj/machinery/gateway{ - dir = 1 - }, /turf/open/floor/engine, /area/gateway) "bwL" = ( @@ -34549,11 +34730,19 @@ /turf/open/floor/plating, /area/router) "bwM" = ( -/obj/machinery/gateway{ - dir = 5 +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, -/turf/open/floor/engine, -/area/gateway) +/obj/machinery/camera{ + c_tag = "Central Starboard Maintenance"; + dir = 8; + pixel_y = -22 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/mob/living/simple_animal/hostile/retaliate/bat, +/turf/open/floor/plating, +/area/maintenance/starboard/central) "bwN" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 @@ -34787,21 +34976,30 @@ /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai) "bxm" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/turf/closed/wall/r_wall, -/area/tcommsat/computer) -"bxn" = ( -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "2-4" }, /obj/structure/cable{ - icon_state = "4-8" + icon_state = "2-8" }, -/turf/open/floor/plasteel, -/area/tcommsat/computer) +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/light/small, +/turf/open/floor/plating, +/area/maintenance/department/eva) +"bxn" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/camera{ + c_tag = "AI Core Exterior"; + dir = 1 + }, +/turf/open/floor/plating/airless, +/area/maintenance/department/eva) "bxo" = ( /obj/machinery/door/airlock/external{ name = "Telecommunications External Access"; @@ -34825,11 +35023,16 @@ /turf/open/floor/plating, /area/maintenance/department/chapel) "bxq" = ( +/obj/structure/disposalpipe/segment, /obj/structure/cable{ - icon_state = "4-8" + icon_state = "1-2" }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plating, -/area/tcommsat/computer) +/area/maintenance/starboard/central) "bxr" = ( /obj/structure/table, /obj/effect/turf_decal/tile/purple, @@ -34859,18 +35062,13 @@ /turf/open/floor/plating, /area/maintenance/disposal) "bxt" = ( -/obj/machinery/door/airlock/external/glass{ - name = "Telecommunications External Access"; - req_access_txt = "61" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/structure/cable{ - icon_state = "4-8" +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 4 }, /turf/open/floor/plating, -/area/tcommsat/computer) +/area/maintenance/disposal) "bxu" = ( /obj/structure/rack, /obj/item/circuitboard/machine/telecomms/broadcaster, @@ -35028,18 +35226,15 @@ /turf/open/floor/plasteel, /area/tcommsat/computer) "bxK" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical, -/obj/item/radio/off, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, /turf/open/floor/plasteel, -/area/tcommsat/computer) +/area/maintenance/disposal) "bxL" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -35332,41 +35527,43 @@ /turf/open/floor/plasteel, /area/router/eva) "byt" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plating, +/area/maintenance/starboard/central) +"byu" = ( +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plating, +/area/maintenance/starboard/central) +"byv" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/machinery/camera{ c_tag = "Central Starboard Exterior Access" }, -/turf/open/floor/plating, -/area/maintenance/starboard/central) -"byu" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/structure/disposalpipe/segment{ +/obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 }, -/obj/machinery/door/airlock/external{ - name = "Central Starboard Exterior Access"; - req_access_txt = "13" - }, -/turf/open/floor/plating, -/area/maintenance/starboard/central) -"byv" = ( -/obj/structure/disposalpipe/junction/flip{ - dir = 1 - }, /turf/open/floor/plating, /area/maintenance/starboard/central) "byw" = ( -/obj/machinery/firealarm{ - dir = 4; - pixel_x = -28 +/obj/machinery/airalarm{ + pixel_y = 24 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "byx" = ( /obj/machinery/telecomms/processor/preset_three, /turf/open/floor/circuit/telecomms/mainframe, @@ -35396,9 +35593,25 @@ /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) "byD" = ( -/obj/effect/landmark/start/roboticist, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/machinery/camera{ + c_tag = "Medbay - Lobby"; + network = list("ss13","rd") + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "byE" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -35698,11 +35911,11 @@ /turf/open/floor/plating, /area/maintenance/starboard/central) "bzp" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, +/obj/structure/lattice/catwalk, +/obj/structure/disposalpipe/segment, +/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, -/area/maintenance/solars/starboard/fore) +/area/maintenance/disposal) "bzq" = ( /obj/machinery/light{ dir = 8 @@ -35784,13 +35997,23 @@ /turf/open/floor/plasteel/white, /area/gateway) "bzA" = ( -/obj/structure/cable{ - icon_state = "0-2" +/obj/machinery/power/apc{ + areastring = "/area/medical/chemistry"; + dir = 1; + name = "Chemistry APC"; + pixel_y = 24 }, -/turf/closed/wall, -/area/science/research{ - name = "Research Sector" - }) +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bzB" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 6 @@ -35833,11 +36056,14 @@ /turf/open/floor/plating, /area/router) "bzG" = ( -/obj/machinery/light{ - dir = 8 +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bzH" = ( /obj/structure/disposalpipe/segment, /obj/structure/grille/broken, @@ -35852,9 +36078,21 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bzJ" = ( -/obj/structure/sign/warning/biohazard, -/turf/closed/wall, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "bzK" = ( /obj/machinery/disposal/bin{ name = "Chapel Corpse Delivery" @@ -35994,14 +36232,19 @@ /turf/open/floor/plasteel, /area/gateway) "bAd" = ( -/obj/structure/cable{ - icon_state = "1-4" +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 }, -/obj/structure/cable{ - icon_state = "2-4" +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "Central Starboard Exterior Access"; + req_access_txt = "13" }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 5 + dir = 4 }, /turf/open/floor/plating, /area/maintenance/starboard/central) @@ -36234,11 +36477,14 @@ name = "Medbay Treatment Center" }) "bAz" = ( -/obj/machinery/gateway{ - dir = 8 +/obj/structure/disposalpipe/junction/flip{ + dir = 1 }, -/turf/open/floor/engine, -/area/gateway) +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 9 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/central) "bAA" = ( /obj/structure/lattice, /obj/structure/cable{ @@ -36258,26 +36504,61 @@ /turf/open/floor/plasteel, /area/quartermaster/sorting) "bAC" = ( -/obj/machinery/recharge_station, -/obj/effect/turf_decal/stripes/line{ - dir = 9 +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bAD" = ( -/obj/machinery/recharge_station, -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/machinery/door/firedoor, +/obj/structure/table/reinforced, +/obj/effect/turf_decal/delivery, +/obj/structure/cable{ + icon_state = "4-8" }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/machinery/door/window/eastleft{ + name = "Chemistry Desk"; + req_access_txt = "33" + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bAE" = ( -/obj/effect/turf_decal/stripes/line{ +/obj/structure/disposalpipe/segment, +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/machinery/button/door{ + id = "chem1"; + name = "Shutters Control Button"; + pixel_x = -8; + pixel_y = 24; + req_access_txt = "29" + }, +/obj/effect/landmark/start/chemist, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/landmark/start/ai/secondary, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/extinguisher_cabinet{ + pixel_x = 5; + pixel_y = 32 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bAF" = ( /obj/machinery/gateway/centerstation, /turf/open/floor/engine, @@ -36338,6 +36619,7 @@ name = "Chief Medical Officer's Office APC"; pixel_y = 24 }, +/mob/living/simple_animal/pet/cat/Runtime, /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) "bAK" = ( @@ -36361,11 +36643,18 @@ name = "Medbay Treatment Center" }) "bAN" = ( -/obj/machinery/gateway{ - dir = 4 +/obj/structure/rack, +/obj/item/clothing/suit/space/fragile, +/obj/item/clothing/head/helmet/space/fragile, +/obj/item/tank/internals/air, +/obj/item/flashlight, +/obj/machinery/airalarm{ + dir = 1; + locked = 0; + pixel_y = -22 }, -/turf/open/floor/engine, -/area/gateway) +/turf/open/floor/plating, +/area/maintenance/starboard/central) "bAO" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 @@ -36626,12 +36915,14 @@ /turf/open/floor/plating, /area/maintenance/disposal) "bBs" = ( -/obj/machinery/aug_manipulator, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 5 }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/aft) "bBt" = ( /obj/structure/cable{ icon_state = "4-8" @@ -36814,12 +37105,25 @@ name = "Power Monitoring" }) "bBP" = ( -/obj/structure/disposalpipe/segment, -/turf/closed/wall, +/obj/machinery/door/firedoor, +/obj/structure/table/reinforced, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/machinery/door/window/eastright{ + name = "Chemistry Desk"; + req_access_txt = "33" + }, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "bBQ" = ( -/turf/closed/wall, -/area/medical/chemistry) +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/light_switch{ + pixel_x = -24 + }, +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "bBR" = ( /obj/structure/cable{ icon_state = "0-8" @@ -36970,11 +37274,27 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hop) "bCf" = ( -/obj/structure/sign/warning/fire, -/turf/closed/wall/r_wall, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/landmark/start/chemist, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "bCg" = ( -/turf/closed/wall/r_wall, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/landmark/start/chemist, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "bCh" = ( /obj/effect/spawner/structure/window/reinforced, @@ -37292,15 +37612,29 @@ name = "Thermo-Electric Generator" }) "bCX" = ( -/obj/effect/turf_decal/bot, -/obj/machinery/vending/snack/random, -/obj/structure/disposalpipe/segment, +/obj/machinery/rnd/production/circuit_imprinter/department/science, +/obj/item/reagent_containers/glass/beaker/sulphuric, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, /turf/open/floor/plasteel, -/area/hallway/primary/aft) +/area/science/lab) "bCY" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/structure/sign/warning/nosmoking{ + pixel_x = 32 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bCZ" = ( /obj/machinery/conveyor{ dir = 8; @@ -37316,12 +37650,20 @@ /turf/open/floor/plasteel/showroomfloor, /area/medical/morgue) "bDb" = ( -/mob/living/simple_animal/mouse/white{ - desc = "Wubba lubba dub dub."; - name = "Rick" +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "1-2" }, -/turf/open/floor/plasteel/showroomfloor, -/area/medical/morgue) +/obj/machinery/door/airlock/external{ + name = "Recycler Exterior Access"; + req_one_access_txt = "13;50" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, +/turf/open/floor/plasteel, +/area/maintenance/disposal) "bDc" = ( /obj/machinery/vending/security, /obj/structure/disposalpipe/segment, @@ -37334,12 +37676,19 @@ /turf/open/floor/plasteel/grimy, /area/security/detectives_office) "bDd" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ +/obj/structure/disposalpipe/segment, +/obj/machinery/camera{ + c_tag = "Aft Maintenance - Port"; + pixel_x = 22 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/aft) "bDe" = ( /obj/machinery/disposal/bin{ name = "Corpse Delivery" @@ -37381,7 +37730,7 @@ /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, /obj/effect/decal/cleanable/dirt, -/obj/item/pipe_meter, +/obj/machinery/meter, /turf/open/floor/plating, /area/maintenance/department/chapel) "bDk" = ( @@ -37413,19 +37762,27 @@ /turf/open/floor/plasteel, /area/quartermaster/warehouse) "bDm" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/structure/cable{ + icon_state = "0-4" }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/hallway/primary/aft"; + dir = 1; + name = "Aft Primary Hallway APC"; + pixel_x = 1; + pixel_y = 24 }, -/obj/machinery/firealarm{ - dir = 8; - pixel_x = 26 +/obj/structure/cable{ + icon_state = "2-4" }, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 10 + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/turf/open/floor/plating, +/area/maintenance/aft) "bDn" = ( /obj/machinery/icecream_vat, /turf/open/floor/plasteel/freezer, @@ -37465,7 +37822,7 @@ /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 }, -/obj/item/pipe_meter, +/obj/machinery/meter, /turf/closed/wall/r_wall, /area/crew_quarters/kitchen/backroom) "bDs" = ( @@ -37692,13 +38049,10 @@ /turf/open/floor/plasteel/stairs, /area/crew_quarters/bar) "bDT" = ( -/obj/machinery/chem_heater, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/airalarm{ - pixel_y = 24 - }, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/turf/closed/wall, +/area/science/robotics/lab) "bDU" = ( /obj/machinery/atmospherics/pipe/simple/supplymain/hidden, /obj/effect/spawner/structure/window/reinforced, @@ -37935,16 +38289,20 @@ }, /area/crew_quarters/heads/captain) "bEr" = ( -/obj/structure/cable, -/obj/machinery/power/apc{ - areastring = "/area/crew_quarters/locker"; - dir = 8; - name = "Locker Room APC"; - pixel_x = -24 +/obj/structure/sign/warning/vacuum/external{ + pixel_x = -32; + pixel_y = 32 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/maintenance/fore) +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/engineering{ + name = "Engine Room" + }) "bEs" = ( /obj/machinery/portable_atmospherics/canister/oxygen, /obj/effect/turf_decal/tile/yellow{ @@ -38132,9 +38490,15 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/bar) "bEK" = ( -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/maintenance/fore) +/obj/machinery/atmospherics/pipe/simple/supply/visible, +/obj/machinery/space_heater, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/engine/engineering{ + name = "Engine Room" + }) "bEL" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -38368,9 +38732,19 @@ /turf/open/floor/plasteel, /area/ai_monitored/turret_protected/ai) "bFg" = ( -/obj/effect/turf_decal/tile/brown, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/machinery/suit_storage_unit/engine, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 4 + }, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -23 + }, /turf/open/floor/plasteel, -/area/quartermaster/miningoffice) +/area/engine/engineering{ + name = "Engine Room" + }) "bFh" = ( /obj/effect/turf_decal/tile/brown, /obj/machinery/light, @@ -38464,8 +38838,12 @@ "bFu" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/disposalpipe/segment, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics"; + name = "robotics lab shutters" + }, /turf/open/floor/plating, -/area/medical/chemistry) +/area/science/robotics/lab) "bFv" = ( /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -38485,18 +38863,19 @@ }, /obj/structure/cable, /obj/machinery/power/apc{ - areastring = "area/science/xenobiology"; + areastring = "/area/science/xenobiology"; name = "Xenobiology Lab APC"; pixel_y = -24 }, /turf/open/floor/plasteel, /area/science/xenobiology) "bFx" = ( -/obj/machinery/chem_dispenser, -/obj/effect/turf_decal/stripes/line, -/obj/item/reagent_containers/glass/beaker/large, +/obj/machinery/mecha_part_fabricator, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, /turf/open/floor/plasteel, -/area/medical/chemistry) +/area/science/robotics/lab) "bFy" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ @@ -38524,33 +38903,20 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bFB" = ( -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/stripes/white/full, -/obj/structure/disposalpipe/trunk, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/closed/wall, +/area/science/lab) "bFC" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/bot, +/obj/machinery/vending/snack/random, +/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/machinery/firealarm{ - pixel_y = 26 - }, -/obj/item/storage/fancy/donut_box, -/obj/item/storage/box/beakers, -/obj/item/clothing/glasses/science, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel, +/area/hallway/primary/aft) "bFD" = ( /obj/structure/disposaloutlet{ dir = 4 @@ -38562,10 +38928,16 @@ /turf/open/floor/plasteel, /area/quartermaster/sorting) "bFE" = ( -/obj/machinery/smoke_machine, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, +/area/maintenance/aft) "bFF" = ( /obj/machinery/light_switch{ pixel_y = 24 @@ -38576,8 +38948,8 @@ /turf/open/floor/plating, /area/storage/tech) "bFG" = ( -/obj/structure/sign/departments/chemistry, -/turf/closed/wall, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "bFH" = ( /obj/machinery/power/apc{ @@ -38733,7 +39105,7 @@ /turf/open/floor/wood, /area/crew_quarters/fitness) "bFR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /turf/open/floor/wood, @@ -38825,38 +39197,13 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bFY" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/structure/noticeboard{ - pixel_y = 28 - }, -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/obj/structure/lattice/catwalk, +/turf/closed/wall/r_wall, +/area/engine/atmos) "bFZ" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/machinery/light_switch{ - pixel_y = 24 - }, -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ - dir = 1 - }, +/obj/machinery/chem_heater, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/chemistry) "bGa" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/plasteel/dark, @@ -39037,14 +39384,15 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bGu" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Fore Maintenance"; - req_one_access_txt = "12;46" +/obj/structure/cable{ + icon_state = "1-4" }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/hallway/primary/port/fore) +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/restrooms) "bGv" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -39199,7 +39547,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20"; pixel_y = 3 }, @@ -39411,20 +39759,15 @@ /turf/open/floor/plasteel, /area/security/main) "bHi" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 +/obj/effect/landmark/event_spawn, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/fore) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/restrooms) "bHj" = ( /obj/structure/table, /obj/structure/bedsheetbin/towel, @@ -39544,7 +39887,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel, @@ -39569,53 +39912,26 @@ /turf/open/floor/plating, /area/crew_quarters/locker) "bHC" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/machinery/firealarm{ - pixel_y = 26 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, +/obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/chemistry) "bHD" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/aft) "bHE" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ - dir = 1 +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, +/obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/chemistry) "bHF" = ( /obj/structure/table/reinforced, /obj/item/assembly/timer{ @@ -39637,27 +39953,11 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "bHG" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/machinery/airalarm{ - pixel_y = 24 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Medbay - Starboard"; - network = list("ss13","rd") - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/landmark/event_spawn, +/turf/open/floor/plasteel, +/area/maintenance/aft) "bHH" = ( /obj/structure/table, /obj/machinery/recharger, @@ -39672,30 +39972,15 @@ }, /area/gateway) "bHI" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/medbay/lobby) "bHJ" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 10 +/obj/item/kirbyplants{ + icon_state = "plant-03" }, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/medbay/lobby) "bHK" = ( /obj/structure/sign/warning/biohazard, /turf/closed/wall, @@ -39807,55 +40092,64 @@ /turf/open/floor/plasteel/white, /area/science/xenobiology) "bIc" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/disposalpipe/junction{ - dir = 8 +/obj/structure/cable{ + icon_state = "1-2" }, -/turf/open/floor/plating, -/area/medical/chemistry) +/obj/structure/disposalpipe/sorting/mail{ + dir = 1; + sortType = 14 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "bId" = ( +/obj/structure/table, +/obj/item/mmi, +/obj/item/mmi, +/obj/item/storage/box/bodybags, +/obj/structure/window/reinforced/spawner/west, /obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ dir = 1 }, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/tile/purple{ dir = 4 }, -/mob/living/simple_animal/bot/firebot, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "bIe" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/structure/table, +/obj/item/stack/sheet/metal/fifty, +/obj/item/stack/sheet/metal/fifty, +/obj/item/stack/sheet/glass/fifty{ + pixel_x = 1 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 +/obj/item/stack/sheet/glass/fifty{ + pixel_x = 1 }, -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/item/stack/sheet/metal/fifty, +/obj/item/stack/sheet/metal/fifty, +/obj/machinery/requests_console{ + department = "Robotics"; + departmentType = 2; + name = "Robotics RC"; + pixel_y = 31; + receive_ore_updates = 1 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/science/robotics/lab) "bIf" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/machinery/door/firedoor, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/effect/landmark/start/chemist, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/door/airlock/maintenance{ + name = "Chemistry Maintenance"; + req_access_txt = "5; 33" }, -/obj/structure/chair/office/light{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel/white, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plating, /area/medical/chemistry) "bIg" = ( /obj/structure/table, @@ -39874,32 +40168,37 @@ name = "Research Sector" }) "bIh" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/machinery/disposal/bin, +/obj/effect/turf_decal/delivery/white, +/obj/structure/disposalpipe/trunk{ + dir = 8 }, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "bIi" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bIj" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bIk" = ( /obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/chemistry) +"bIj" = ( +/obj/structure/table/optable{ + name = "Robotics Operating Table" + }, +/obj/item/tank/internals/anesthetic, +/obj/item/clothing/mask/breath, +/obj/machinery/light{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/science/robotics/lab) +"bIk" = ( +/turf/closed/wall/r_wall, +/area/science/robotics/lab) "bIl" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -39978,15 +40277,25 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bIt" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 5 +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, +/obj/structure/cable{ + icon_state = "1-8" + }, +/obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/chemistry) "bIu" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/medical{ @@ -40120,17 +40429,33 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "bIL" = ( -/obj/structure/closet/l3closet/scientist, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/disposalpipe/segment, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/effect/turf_decal/tile/blue{ dir = 1 }, +/obj/structure/table/glass, +/obj/item/reagent_containers/glass/beaker/large{ + pixel_x = -3; + pixel_y = 3 + }, +/obj/item/reagent_containers/glass/beaker/large, +/obj/item/reagent_containers/dropper, +/obj/item/reagent_containers/dropper, /turf/open/floor/plasteel/white, /area/medical/chemistry) "bIM" = ( -/turf/open/floor/plasteel/white, +/obj/machinery/shower{ + desc = "The HS-451. Standard Nanotrasen Hygiene Division design, although it looks like this one was installed more recently."; + dir = 8; + name = "emergency shower"; + pixel_y = -4 + }, +/obj/structure/window/reinforced/spawner/north, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, /area/medical/chemistry) "bIN" = ( /obj/structure/disposalpipe/segment{ @@ -40309,15 +40634,15 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bJd" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 8 +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -22 +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/disposalpipe/segment{ + dir = 5 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bJe" = ( /obj/structure/closet/secure_closet/personal/patient, /obj/effect/turf_decal/tile/blue, @@ -40332,20 +40657,14 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bJf" = ( -/obj/structure/closet/secure_closet/personal/patient, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/purple{ - dir = 8 +/obj/machinery/door/airlock/maintenance{ + name = "Chemistry Maintenance"; + req_access_txt = "5; 33" }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/window/reinforced/spawner, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/obj/machinery/door/firedoor, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/medical/chemistry) "bJg" = ( /obj/structure/table, /obj/effect/turf_decal/tile/red{ @@ -40547,27 +40866,47 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bJC" = ( +/obj/machinery/camera{ + c_tag = "Library"; + network = list("ss13","rd") + }, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/library) +"bJD" = ( +/obj/machinery/disposal/bin{ + name = "Corpse Disposal Unit" + }, +/obj/structure/disposalpipe/trunk, +/obj/effect/turf_decal/stripes/red/full, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bJD" = ( -/obj/machinery/chem_heater, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/area/science/robotics/lab) "bJE" = ( -/obj/machinery/chem_dispenser, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/mecha_part_fabricator, +/obj/machinery/light{ dir = 1 }, -/obj/item/reagent_containers/glass/beaker/large, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/machinery/light_switch{ + pixel_y = 24 + }, /turf/open/floor/plasteel, -/area/medical/chemistry) +/area/science/robotics/lab) "bJF" = ( /obj/effect/turf_decal/tile/purple{ dir = 1 @@ -40600,8 +40939,12 @@ /area/hallway/primary/central) "bJH" = ( /obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics2"; + name = "robotics lab shutters" + }, /turf/open/floor/plating, -/area/medical/chemistry) +/area/science/robotics/lab) "bJI" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -40685,15 +41028,11 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "bJU" = ( -/obj/effect/turf_decal/tile/brown, -/obj/machinery/light{ - dir = 4 +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/quartermaster/miningoffice) +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/toilet/restrooms) "bJV" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer/on{ dir = 1; @@ -40773,30 +41112,40 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "bKd" = ( -/obj/structure/closet/bombcloset, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/table, +/obj/item/assembly/flash/handheld, +/obj/item/assembly/flash/handheld, +/obj/item/assembly/flash/handheld, +/obj/item/assembly/flash/handheld, +/obj/item/assembly/flash/handheld, +/obj/item/assembly/flash/handheld, +/obj/item/clothing/glasses/welding, +/obj/item/clothing/glasses/welding, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/disposalpipe/segment, +/obj/item/radio/intercom{ + name = "Station Intercom (Common)"; + pixel_y = 26 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"bKe" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics"; + name = "robotics lab shutters" + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/plating, +/area/science/robotics/lab) +"bKf" = ( +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bKe" = ( -/obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bKf" = ( -/obj/structure/sink{ - dir = 4; - pixel_x = 11 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "bKg" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 @@ -41120,85 +41469,36 @@ /turf/open/floor/engine, /area/science/xenobiology) "bKN" = ( -/obj/machinery/vending/wardrobe/chem_wardrobe, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, +/obj/structure/table, +/obj/item/storage/backpack/duffelbag/med/surgery, +/obj/structure/window/reinforced/spawner/west, +/obj/structure/window/reinforced, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "bKO" = ( -/obj/structure/closet/crate/medical, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/item/stack/sheet/mineral/plasma, -/obj/item/stack/sheet/mineral/plasma, -/obj/item/reagent_containers/glass/bottle/ammonia, -/obj/item/reagent_containers/glass/bottle/atropine, -/obj/item/reagent_containers/glass/bottle/bromine, -/obj/item/reagent_containers/glass/bottle/charcoal, -/obj/item/reagent_containers/glass/bottle/diethylamine, -/obj/item/reagent_containers/glass/bottle/epinephrine, -/obj/item/reagent_containers/glass/bottle/ethanol, -/obj/item/reagent_containers/glass/bottle/formaldehyde, -/obj/item/reagent_containers/glass/bottle/iron, -/obj/item/reagent_containers/glass/bottle/morphine, -/obj/item/reagent_containers/glass/bottle/salglu_solution, -/obj/item/reagent_containers/glass/bottle/toxin, -/obj/item/reagent_containers/glass/bottle/carbon, +/obj/structure/window/reinforced, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "bKP" = ( -/obj/effect/turf_decal/delivery, -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/door/window/northright{ - name = "Emergency Shower" - }, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/obj/machinery/door/window/southright, +/turf/open/floor/plasteel/white, +/area/science/robotics/lab) "bKQ" = ( -/obj/effect/turf_decal/delivery, -/obj/structure/window/reinforced{ - dir = 1 - }, -/obj/machinery/shower{ - dir = 8; - name = "emergency shower"; - pixel_y = -4 - }, -/turf/open/floor/plasteel, -/area/medical/chemistry) -"bKR" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/structure/disposalpipe/segment, +/obj/structure/window/reinforced, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ dir = 4 }, -/obj/machinery/camera{ - c_tag = "Library"; - network = list("ss13","rd") +/turf/open/floor/plasteel/white, +/area/science/robotics/lab) +"bKR" = ( +/obj/structure/bookcase/random/religion, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, -/obj/machinery/airalarm{ - pixel_y = 24 - }, -/turf/open/floor/wood, +/turf/open/floor/plasteel/dark, /area/library) "bKS" = ( /obj/machinery/door/firedoor, @@ -41762,7 +42062,7 @@ /turf/open/floor/plasteel/cafeteria, /area/medical/medbay/central) "bLX" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ @@ -42743,13 +43043,10 @@ "bOc" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "0-8" - }, -/obj/structure/cable{ - icon_state = "4-8" + icon_state = "0-4" }, /turf/open/space/basic, -/area/solar/port) +/area/solar/starboard/aft) "bOd" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -42770,10 +43067,10 @@ "bOf" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ - icon_state = "2-8" + icon_state = "0-2" }, /turf/open/space/basic, -/area/solar/port) +/area/solar/starboard/aft) "bOg" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -42821,22 +43118,30 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit) "bOn" = ( -/obj/machinery/door/airlock/external/glass{ - name = "Shuttle Maintenance Access" +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/maintenance{ + name = "Bathroom Maintenance"; + req_access_txt = "12" }, -/turf/open/floor/plasteel, -/area/hallway/secondary/exit) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/crew_quarters/toilet/restrooms) "bOo" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/warning/docking, /turf/open/floor/plating, /area/hallway/secondary/exit) "bOp" = ( -/obj/machinery/door/airlock/external/glass{ - name = "Departures Shuttle Dock" +/obj/structure/cable{ + icon_state = "2-8" }, -/turf/open/floor/plasteel, -/area/hallway/secondary/exit) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/aft) "bOq" = ( /obj/machinery/power/tracker, /obj/structure/cable, @@ -43689,7 +43994,7 @@ pixel_x = 22 }, /obj/machinery/turretid{ - control_area = "area/ai_monitored/turret_protected/ai"; + control_area = "/area/ai_monitored/turret_protected/ai"; dir = 1; name = "AI Chamber turret control"; pixel_x = 5; @@ -43834,12 +44139,11 @@ /turf/open/floor/plasteel/showroomfloor, /area/medical/morgue) "bQp" = ( -/obj/item/radio/intercom{ - name = "Station Intercom (Common)"; - pixel_x = -26 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/effect/decal/cleanable/dirt, +/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/light/small, +/turf/open/floor/plasteel, +/area/maintenance/aft) "bQq" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -44134,29 +44438,18 @@ name = "Research Sector" }) "bQQ" = ( -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/purple{ dir = 4 }, -/obj/effect/turf_decal/tile/red{ - dir = 1 +/obj/effect/turf_decal/tile/purple, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -28 }, -/obj/machinery/disposal/bin, -/obj/machinery/light, -/obj/effect/turf_decal/stripes/red/full, -/obj/structure/disposalpipe/trunk{ - dir = 1 +/turf/open/floor/plasteel/dark/side{ + dir = 8 }, -/obj/structure/sign/poster/official/cleanliness{ - pixel_y = -32 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone2{ - name = "Medbay Treatment Center" - }) +/area/science/robotics/lab) "bQR" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/directions/evac{ @@ -44485,7 +44778,7 @@ dir = 1; network = list("minisat") }, -/turf/open/floor/circuit/green/telecomms, +/turf/open/floor/circuit/green, /area/science/server{ name = "Computer Core" }) @@ -44717,19 +45010,24 @@ name = "Research Sector" }) "bRT" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, +/obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plasteel, -/area/science/research{ - name = "Research Sector" - }) +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/disposal/bin{ + name = "Lab Delivery" + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bRU" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 @@ -44737,11 +45035,11 @@ /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) "bRV" = ( -/obj/structure/sign/departments/chemistry, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/closed/wall, -/area/medical/chemistry) +/obj/effect/turf_decal/tile/purple, +/turf/open/floor/plasteel/dark/side{ + dir = 9 + }, +/area/science/robotics/lab) "bRW" = ( /obj/effect/turf_decal/bot, /obj/structure/cable{ @@ -44756,24 +45054,29 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bRX" = ( -/obj/effect/landmark/start/medical_doctor, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) -"bRY" = ( -/obj/structure/closet/secure_closet/medical3, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/item/storage/belt/medical, -/obj/item/clothing/neck/stethoscope, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) -"bRZ" = ( -/obj/structure/closet/l3closet, /obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"bRY" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"bRZ" = ( +/obj/structure/bookcase/random/nonfiction, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/library) "bSa" = ( /obj/structure/closet/secure_closet/medical3, /obj/effect/turf_decal/tile/blue, @@ -44796,35 +45099,24 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "bSd" = ( -/obj/structure/closet/secure_closet/chemical, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow{ +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/loading_area, +/turf/open/floor/plasteel/dark/side{ dir = 1 }, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "bSe" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/light{ +/obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/machinery/requests_console{ - department = "Robotics"; - departmentType = 2; - name = "Robotics RC"; - pixel_x = -30; - receive_ore_updates = 1 +/obj/effect/turf_decal/tile/purple, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/plasteel/dark/side{ + dir = 1 }, -/turf/open/floor/plasteel/dark, /area/science/robotics/lab) "bSf" = ( /obj/structure/table, @@ -45150,6 +45442,7 @@ /obj/machinery/cell_charger, /obj/item/stock_parts/cell/high/plus, /obj/item/stock_parts/cell/high/plus, +/obj/item/stack/cable_coil/red, /turf/open/floor/plasteel/white, /area/science/lab) "bSN" = ( @@ -45324,23 +45617,36 @@ /turf/open/floor/plasteel/white, /area/science/lab) "bTg" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 +/obj/machinery/power/apc/highcap/ten_k{ + areastring = "/area/science/robotics/mechbay"; + dir = 1; + name = "Mech Bay APC"; + pixel_y = 28 }, -/obj/structure/disposalpipe/segment{ - dir = 10 +/obj/structure/cable{ + icon_state = "0-2" }, -/turf/open/floor/plasteel/white, -/area/science/lab) +/obj/machinery/airalarm{ + dir = 8; + pixel_x = 23 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/mechbay) "bTh" = ( -/obj/machinery/rnd/production/protolathe/department/science, +/obj/effect/turf_decal/bot, +/obj/effect/landmark/start/cyborg, /turf/open/floor/plasteel, -/area/science/lab) +/area/science/robotics/lab) "bTi" = ( -/obj/machinery/rnd/production/circuit_imprinter/department/science, -/obj/item/reagent_containers/glass/beaker/sulphuric, -/turf/open/floor/plasteel, -/area/science/lab) +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel/dark/side{ + dir = 5 + }, +/area/science/robotics/lab) "bTj" = ( /obj/structure/table, /obj/item/reagent_containers/glass/beaker/large{ @@ -45471,7 +45777,7 @@ /turf/open/floor/plating, /area/quartermaster/warehouse) "bTy" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 9 }, @@ -45511,27 +45817,19 @@ }, /area/medical/medbay/lobby) "bTC" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/plasteel/white, /area/medical/chemistry) "bTD" = ( /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "bTE" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel/white, @@ -45559,11 +45857,11 @@ /area/engine/atmos) "bTJ" = ( /obj/structure/lattice, -/obj/machinery/atmospherics/pipe/simple/violet/hidden{ - dir = 8 - }, -/turf/open/space/basic, -/area/space/nearstation) +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/maintenance/disposal) "bTK" = ( /turf/open/floor/engine/co2, /area/engine/atmos) @@ -45801,17 +46099,12 @@ /turf/open/floor/plasteel, /area/ai_monitored/turret_protected/ai_upload_foyer) "bUj" = ( -/obj/structure/cable{ - icon_state = "1-8" +/obj/machinery/atmospherics/pipe/simple/violet/hidden{ + dir = 8 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/ai_monitored/turret_protected/ai_upload_foyer) +/obj/structure/lattice/catwalk, +/turf/open/space/basic, +/area/space/nearstation) "bUk" = ( /obj/structure/closet/crate, /obj/effect/decal/cleanable/cobweb, @@ -46183,11 +46476,11 @@ /turf/open/floor/plasteel, /area/ai_monitored/turret_protected/ai_upload_foyer) "bUV" = ( -/obj/structure/lattice, /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/violet/hidden{ dir = 10 }, +/obj/structure/lattice/catwalk, /turf/open/space/basic, /area/space/nearstation) "bUW" = ( @@ -46420,15 +46713,15 @@ /turf/open/floor/plasteel, /area/quartermaster/sorting) "bVt" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/brown{ + dir = 1 }, -/obj/structure/cable{ - icon_state = "1-4" +/obj/effect/turf_decal/tile/purple{ + dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/starboard/central) +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plasteel, +/area/quartermaster/miningoffice) "bVu" = ( /obj/effect/decal/cleanable/dirt, /obj/item/radio/intercom{ @@ -46539,14 +46832,9 @@ /turf/open/floor/plating, /area/ai_monitored/turret_protected/ai_upload_foyer) "bVD" = ( -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 - }, -/turf/open/floor/plating, -/area/ai_monitored/turret_protected/ai_upload_foyer) +/obj/structure/lattice, +/turf/open/space/basic, +/area/space) "bVE" = ( /obj/effect/landmark/start/atmospheric_technician, /obj/machinery/atmospherics/pipe/simple/orange/visible{ @@ -46972,13 +47260,16 @@ /turf/open/floor/engine/n2o, /area/engine/atmos) "bWq" = ( -/obj/structure/lattice, -/obj/machinery/camera{ - c_tag = "Routing Depot - Aft Exterior"; - pixel_x = 22 +/obj/effect/turf_decal/stripes/line{ + dir = 4 }, -/turf/open/space/basic, -/area/space/nearstation) +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/airalarm{ + dir = 8; + pixel_x = 23 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "bWr" = ( /obj/structure/closet/l3closet/scientist, /obj/effect/turf_decal/stripes/line, @@ -47144,17 +47435,18 @@ /turf/closed/wall/r_wall, /area/ai_monitored/turret_protected/ai_upload_foyer) "bWJ" = ( -/obj/effect/turf_decal/stripes/line, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "2-4" - }, +/obj/structure/lattice/catwalk, /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plasteel, -/area/ai_monitored/turret_protected/ai_upload_foyer) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/supplymain/visible{ + dir = 1 + }, +/turf/open/space/basic, +/area/space/nearstation) "bWK" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/orange/visible, @@ -47385,7 +47677,7 @@ pixel_x = 24; pixel_y = 6 }, -/obj/item/twohanded/required/kirbyplants/photosynthetic, +/obj/item/kirbyplants/photosynthetic, /turf/open/floor/plasteel, /area/crew_quarters/heads/chief) "bXg" = ( @@ -47493,15 +47785,18 @@ /turf/open/floor/plating, /area/router) "bXq" = ( -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/structure/disposalpipe/segment{ + dir = 10 }, /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold4w/orange/hidden, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "bXr" = ( /obj/effect/turf_decal/tile/purple{ dir = 1 @@ -47587,7 +47882,7 @@ }, /obj/effect/turf_decal/tile/purple, /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel, @@ -47735,11 +48030,11 @@ name = "Research Sector" }) "bXL" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/obj/effect/decal/cleanable/dirt, +/obj/structure/rack, +/obj/item/storage/belt/utility, +/turf/open/floor/plasteel, +/area/maintenance/aft) "bXM" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/conveyor{ @@ -47749,11 +48044,9 @@ /turf/open/floor/plating, /area/router) "bXN" = ( -/obj/structure/cable{ - icon_state = "2-8" - }, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/machinery/smartfridge/organ/preloaded, +/turf/closed/wall, +/area/medical/morgue) "bXO" = ( /obj/structure/table/glass, /obj/machinery/reagentgrinder, @@ -47770,7 +48063,7 @@ /obj/structure/cable{ icon_state = "0-4" }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "bXQ" = ( /obj/structure/closet/l3closet/scientist, @@ -47827,7 +48120,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "bXW" = ( /obj/structure/disposalpipe/segment{ @@ -48005,31 +48298,22 @@ /turf/open/floor/plating, /area/maintenance/starboard/aft) "bYo" = ( -/obj/structure/closet/emcloset, /obj/structure/disposalpipe/segment, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/obj/machinery/computer/mech_bay_power_console, +/turf/open/floor/circuit/green, +/area/science/robotics/mechbay) "bYp" = ( -/obj/structure/rack, -/obj/item/clothing/suit/fire/firefighter, -/obj/item/clothing/mask/gas, -/obj/item/wrench, -/obj/item/light/tube, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/turf/open/floor/plasteel/recharge_floor, +/area/science/robotics/mechbay) "bYq" = ( /obj/machinery/light/small{ dir = 1 }, -/obj/effect/spawner/lootdrop/maintenance, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/obj/machinery/mech_bay_recharge_port{ + dir = 8 + }, +/turf/open/floor/circuit/green, +/area/science/robotics/mechbay) "bYr" = ( /obj/effect/turf_decal/tile/purple{ dir = 8 @@ -48104,9 +48388,7 @@ }) "bYv" = ( /turf/closed/wall, -/area/science/research{ - name = "Research Sector" - }) +/area/science/robotics/mechbay) "bYw" = ( /obj/effect/turf_decal/tile/purple{ dir = 4 @@ -48126,10 +48408,8 @@ /obj/structure/cable{ icon_state = "4-8" }, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/turf/open/floor/circuit, +/area/science/robotics/mechbay) "bYy" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -48140,13 +48420,8 @@ /obj/structure/cable{ icon_state = "1-4" }, -/obj/structure/cable{ - icon_state = "2-4" - }, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/turf/open/floor/circuit, +/area/science/robotics/mechbay) "bYz" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 10 @@ -48170,24 +48445,15 @@ name = "Research Sector" }) "bYB" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/item/clothing/gloves/color/latex, -/obj/item/book/manual/wiki/chemistry, -/obj/item/reagent_containers/dropper, -/obj/item/radio/headset/headset_medsci, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "bYC" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, @@ -48215,12 +48481,11 @@ /turf/open/floor/plating, /area/maintenance/starboard/aft) "bYF" = ( -/obj/machinery/portable_atmospherics/pump, /obj/structure/disposalpipe/segment, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/obj/structure/cable, +/obj/machinery/recharge_station, +/turf/open/floor/circuit/green, +/area/science/robotics/mechbay) "bYG" = ( /obj/effect/turf_decal/tile/red{ dir = 8 @@ -48237,78 +48502,39 @@ name = "Medbay Treatment Center" }) "bYH" = ( -/obj/structure/reagent_dispensers/fueltank, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/obj/structure/sign/poster/contraband/kss13{ + pixel_y = -32 + }, +/obj/structure/cable, +/obj/machinery/recharge_station, +/turf/open/floor/circuit/green, +/area/science/robotics/mechbay) "bYI" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/landmark/start/medical_doctor, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"bYJ" = ( +/obj/structure/closet/secure_closet/medical3, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/item/storage/box/beakers, -/obj/item/assembly/timer{ - pixel_y = 6 - }, -/obj/item/assembly/timer{ - pixel_y = 6 - }, -/obj/item/assembly/timer{ - pixel_y = 6 - }, -/obj/item/assembly/timer{ - pixel_y = 6 - }, -/obj/item/assembly/igniter{ - pixel_y = -4 - }, -/obj/item/assembly/igniter{ - pixel_y = -4 - }, -/obj/item/assembly/igniter{ - pixel_y = -4 - }, -/obj/item/assembly/igniter{ - pixel_y = -4 - }, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ - dir = 8 +/obj/item/storage/belt/medical, +/obj/item/clothing/neck/stethoscope, +/obj/structure/disposalpipe/segment{ + dir = 4 }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bYJ" = ( -/obj/structure/disposalpipe/segment{ +/area/medical/medbay/central) +"bYK" = ( +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 5 }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /turf/open/floor/plasteel/white, -/area/medical/chemistry) -"bYK" = ( -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/sorting/mail{ - dir = 8; - sortType = 4 - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/lobby) "bYL" = ( /obj/effect/turf_decal/tile/purple{ dir = 4 @@ -48439,13 +48665,13 @@ name = "Computer Core" }) "bYY" = ( -/turf/open/floor/circuit/green/telecomms, +/turf/open/floor/circuit/green, /area/science/server{ name = "Computer Core" }) "bYZ" = ( /obj/structure/disposalpipe/segment, -/turf/open/floor/circuit/green/telecomms, +/turf/open/floor/circuit/green, /area/science/server{ name = "Computer Core" }) @@ -48476,7 +48702,7 @@ }, /obj/item/circuitboard/machine/rdserver, /obj/item/disk/tech_disk, -/turf/open/floor/circuit/green/telecomms, +/turf/open/floor/circuit/green, /area/science/server{ name = "Computer Core" }) @@ -48486,7 +48712,7 @@ }, /obj/machinery/light, /obj/structure/disposalpipe/segment, -/turf/open/floor/circuit/green/telecomms, +/turf/open/floor/circuit/green, /area/science/server{ name = "Computer Core" }) @@ -48586,8 +48812,10 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/restrooms) "bZo" = ( -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/toilet/restrooms) +/obj/effect/turf_decal/tile/brown, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plasteel, +/area/quartermaster/miningoffice) "bZp" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -48621,13 +48849,13 @@ /turf/open/floor/plating, /area/hallway/primary/central) "bZs" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Bathroom Maintenance"; - req_access_txt = "12" +/obj/effect/turf_decal/tile/brown, +/obj/effect/turf_decal/tile/purple{ + dir = 4 }, -/turf/open/floor/plating, -/area/crew_quarters/toilet/restrooms) +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plasteel, +/area/quartermaster/miningoffice) "bZt" = ( /turf/closed/wall, /area/maintenance/starboard/aft) @@ -48774,8 +49002,11 @@ /turf/open/floor/carpet, /area/library) "bZK" = ( -/obj/structure/bookcase/random/nonfiction, -/turf/open/floor/wood, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, /area/library) "bZL" = ( /obj/machinery/air_sensor/atmos/nitrous_tank, @@ -48818,20 +49049,20 @@ /area/library) "bZT" = ( /obj/structure/table, -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/item/book/manual/wiki/robotics_cyborgs{ + pixel_x = -3; + pixel_y = -2 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 +/obj/item/book/manual/ripley_build_and_repair{ + pixel_x = 3; + pixel_y = 2 }, -/obj/item/storage/box/pillbottles, -/obj/item/hand_labeler, -/obj/item/clothing/glasses/science, -/obj/structure/sign/poster/official/safety_eye_protection{ - pixel_y = 32 +/obj/item/mmi/posibrain, +/obj/effect/turf_decal/stripes/line{ + dir = 9 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel, +/area/science/robotics/lab) "bZU" = ( /obj/structure/table/wood, /obj/machinery/door/window/northright{ @@ -48843,14 +49074,15 @@ }, /area/library) "bZV" = ( +/obj/structure/window/reinforced/spawner/east, /obj/structure/table/wood, -/obj/structure/window/reinforced/spawner/north, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/floor/carpet{ - icon_state = "carpetsymbol" +/obj/machinery/light{ + dir = 1; + light_color = "#c1caff" }, +/obj/item/paper_bin, +/obj/item/pen, +/turf/open/floor/carpet, /area/library) "bZW" = ( /obj/structure/sign/warning/fire, @@ -48948,18 +49180,17 @@ /turf/open/floor/plasteel, /area/engine/atmos) "caj" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ +/obj/effect/turf_decal/tile/blue{ dir = 8 }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/central) "cak" = ( /obj/structure/sign/warning/fire, /turf/closed/wall/r_wall, @@ -49058,9 +49289,12 @@ /turf/open/floor/engine/n2, /area/engine/atmos) "caz" = ( -/obj/structure/disposalpipe/segment, -/turf/closed/wall, -/area/science/explab) +/obj/machinery/door/airlock/research{ + name = "Mech Bay"; + req_access_txt = "29" + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/mechbay) "caA" = ( /obj/structure/closet/radiation, /turf/open/floor/plasteel, @@ -49078,6 +49312,7 @@ pixel_y = 3 }, /obj/item/storage/toolbox/mechanical, +/obj/item/stack/cable_coil/red, /turf/open/floor/plasteel, /area/science/explab) "caD" = ( @@ -49107,32 +49342,24 @@ /area/engine/atmos) "caG" = ( /obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, /obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ dir = 8 }, -/turf/open/floor/plasteel/dark/side{ - dir = 8 - }, +/turf/open/floor/plasteel/dark, /area/science/explab) "caH" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/landmark/start/chemist, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/chair/office/light, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/effect/turf_decal/tile/blue, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 + dir = 6 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/central) "caI" = ( /obj/structure/table/reinforced, /obj/item/integrated_electronics/analyzer, @@ -49171,15 +49398,20 @@ /turf/open/floor/engine/o2, /area/engine/atmos) "caO" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, /obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "4-8" +/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ + dir = 8 }, -/obj/structure/cable{ - icon_state = "2-4" +/turf/open/floor/plasteel/dark/side{ + dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/aft) +/area/science/robotics/lab) "caP" = ( /obj/structure/chair/office/light, /obj/effect/turf_decal/stripes/line, @@ -49210,7 +49442,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-06" }, /obj/machinery/airalarm{ @@ -49387,6 +49619,17 @@ /obj/item/healthanalyzer, /turf/open/floor/engine, /area/science/explab) +"cbm" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/machinery/door/airlock/maintenance{ + name = "Medbay Maintenance"; + req_access_txt = "5" + }, +/turf/open/floor/plating, +/area/medical/medbay/central) "cbn" = ( /obj/structure/window/reinforced{ dir = 4; @@ -49427,6 +49670,28 @@ /obj/item/pen, /turf/open/floor/engine, /area/science/explab) +"cbr" = ( +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) +"cbs" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "cbt" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/engine, @@ -49535,18 +49800,24 @@ /turf/open/floor/plating, /area/ai_monitored/storage/eva) "cbI" = ( -/obj/structure/lattice/catwalk, /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/manifold/supplymain/visible{ - dir = 1 - }, /obj/structure/disposalpipe/segment{ dir = 4 }, -/turf/open/space/basic, -/area/space/nearstation) +/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "Atmospherics External Airlock"; + req_access_txt = "24" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/atmos) "cbJ" = ( /obj/structure/table/reinforced, /obj/item/analyzer, @@ -49565,35 +49836,36 @@ name = "Thermo-Electric Generator" }) "cbK" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ dir = 1 }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/departments/chemistry{ + pixel_x = 32; + pixel_y = -32 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/lobby) "cbL" = ( /obj/structure/cable{ icon_state = "4-8" }, -/obj/machinery/door/airlock/external{ - name = "Atmospherics External Airlock"; - req_access_txt = "24" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ dir = 4 }, /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/atmos) "cbM" = ( @@ -49761,18 +50033,18 @@ /obj/effect/turf_decal/tile/purple{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/purple, +/obj/machinery/light{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ +/obj/machinery/camera{ + c_tag = "Robotics Lab"; dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ +/turf/open/floor/plasteel/dark/side{ dir = 8 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "cce" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 @@ -49853,19 +50125,10 @@ /turf/open/floor/plasteel/stairs, /area/maintenance/department/chapel) "ccm" = ( -/obj/structure/table, -/obj/effect/turf_decal/stripes/line{ - dir = 10 +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 }, -/obj/machinery/mecha_part_fabricator, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/glass{ - amount = 20; - layer = 3.2 - }, -/turf/open/floor/plasteel, +/turf/closed/wall/r_wall, /area/science/robotics/lab) "ccn" = ( /obj/effect/decal/cleanable/dirt, @@ -49930,9 +50193,7 @@ "cct" = ( /obj/structure/disposalpipe/segment, /turf/closed/wall, -/area/science/research{ - name = "Research Sector" - }) +/area/science/robotics/mechbay) "ccu" = ( /obj/structure/cable{ icon_state = "1-2" @@ -50021,16 +50282,23 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/door/window/westleft{ - name = "Chemistry Desk"; - req_access_txt = "33" - }, /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics2"; + name = "robotics lab shutters" + }, +/obj/machinery/door/window/eastright{ + base_state = "left"; + dir = 8; + icon_state = "left"; + name = "Robotics Desk"; + req_access_txt = "29" + }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "ccC" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -50703,77 +50971,74 @@ /turf/closed/wall/r_wall, /area/engine/teg_hot) "cdW" = ( -/obj/machinery/airalarm{ - pixel_y = 24 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 10 }, -/obj/machinery/light{ +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics2"; + name = "robotics lab shutters" + }, +/turf/open/floor/plating, +/area/science/robotics/lab) +"cdX" = ( +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/effect/landmark/start/chemist, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/item/radio/intercom{ + broadcasting = 1; + frequency = 1485; + listening = 0; + name = "Station Intercom (Medical)"; + pixel_y = -30 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) +"cdY" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ dir = 1 }, /turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/area/medical/medbay/central) "cdZ" = ( /turf/closed/wall/r_wall, /area/medical/medbay/lobby) "cea" = ( -/obj/effect/turf_decal/delivery, -/obj/machinery/photocopier, -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/structure/table/wood, +/obj/structure/window/reinforced/spawner/north, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/requests_console{ - department = "Cargo Bay"; - departmentType = 2; - name = "Cargo RC"; - pixel_y = 30 +/obj/item/paper_bin, +/obj/item/pen, +/turf/open/floor/carpet{ + icon_state = "carpetsymbol" }, -/obj/machinery/camera{ - c_tag = "Supply - Delivery Office Aft"; - network = list("ss13","rd") - }, -/obj/item/paper/guides/cogstation/disposals, -/turf/open/floor/plasteel, -/area/quartermaster/sorting) +/area/library) "ceb" = ( -/obj/structure/table, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/light{ - dir = 1 +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics3"; + name = "robotics lab shutters" }, -/obj/item/stack/sheet/plasteel{ - amount = 15 - }, -/obj/item/storage/belt/utility, -/obj/item/crowbar/large, -/obj/item/multitool, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/structure/disposalpipe/segment, -/obj/machinery/mecha_part_fabricator, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/metal/fifty, -/obj/item/stack/sheet/glass{ - amount = 20; - layer = 3.2 - }, -/obj/item/stack/sheet/plasteel{ - amount = 15 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plating, /area/science/robotics/lab) "cec" = ( /obj/structure/table/glass, @@ -51819,28 +52084,18 @@ /turf/open/floor/plasteel, /area/engine/atmos) "cgf" = ( -/obj/structure/table, -/obj/structure/table, -/obj/machinery/reagentgrinder, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 9 - }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/central) "cgg" = ( /obj/effect/landmark/start/atmospheric_technician, /obj/machinery/atmospherics/pipe/simple/cyan/visible{ @@ -51940,19 +52195,19 @@ /turf/open/floor/plasteel, /area/quartermaster/warehouse) "cgr" = ( -/obj/structure/cable{ - icon_state = "0-2" +/obj/machinery/vending/wardrobe/robo_wardrobe, +/obj/structure/disposalpipe/segment{ + dir = 5 }, -/obj/machinery/power/apc{ - areastring = "/area/science/research"; +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/machinery/airalarm{ dir = 1; - name = "Research Sector APC"; - pixel_y = 24 + pixel_y = -22 }, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/turf/open/floor/plasteel, +/area/science/robotics/lab) "cgs" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -52497,9 +52752,8 @@ /turf/open/floor/plasteel, /area/engine/teg_hot) "chC" = ( -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/maintenance/disposal) +/turf/closed/wall/r_wall/rust, +/area/space/nearstation) "chD" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -52691,6 +52945,18 @@ }, /turf/open/floor/wood, /area/library) +"chV" = ( +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 26 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "chW" = ( /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -52882,9 +53148,7 @@ dir = 4 }, /turf/closed/wall, -/area/science/research{ - name = "Research Sector" - }) +/area/science/robotics/mechbay) "cip" = ( /obj/machinery/mass_driver{ id = "cargo_in"; @@ -52965,12 +53229,16 @@ /turf/open/floor/plating, /area/maintenance/port/fore) "ciA" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/brown, +/obj/machinery/light{ + dir = 4 }, -/turf/open/space/basic, -/area/solar/port) +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plasteel, +/area/quartermaster/miningoffice) "ciB" = ( /obj/structure/frame/computer, /obj/structure/disposalpipe/segment, @@ -53100,21 +53368,12 @@ /turf/open/floor/plasteel, /area/quartermaster/warehouse) "ciQ" = ( -/obj/structure/cable{ - icon_state = "0-4" +/obj/effect/turf_decal/tile/blue, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/hallway/primary/aft"; - dir = 1; - name = "Aft Primary Hallway APC"; - pixel_x = 1; - pixel_y = 24 - }, -/turf/open/floor/plating, -/area/maintenance/aft) +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "ciR" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/tile/red, @@ -53170,7 +53429,7 @@ "ciW" = ( /obj/structure/disposalpipe/sorting/mail/flip{ dir = 8; - sortType = 14 + sortType = 11 }, /obj/structure/cable{ icon_state = "4-8" @@ -53407,7 +53666,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/photosynthetic, +/obj/item/kirbyplants/photosynthetic, /turf/open/floor/plasteel, /area/hallway/primary/aft) "cjA" = ( @@ -53419,7 +53678,7 @@ dir = 4; pixel_x = -28 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/quartermaster/office) "cjB" = ( @@ -53716,23 +53975,31 @@ /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) "cka" = ( -/obj/item/beacon, /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ +/obj/structure/disposalpipe/segment{ dir = 4 }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/central) "ckb" = ( -/obj/machinery/chem_master, -/obj/effect/turf_decal/stripes/line{ - dir = 5 +/obj/effect/turf_decal/tile/purple{ + dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ + dir = 4 + }, +/obj/structure/disposalpipe/junction{ + dir = 1 + }, +/turf/open/floor/plasteel/dark/side{ + dir = 4 + }, +/area/science/robotics/lab) "ckc" = ( /obj/machinery/portable_atmospherics/canister/air, /obj/machinery/atmospherics/pipe/simple/general/visible, @@ -53764,10 +54031,10 @@ /obj/effect/turf_decal/tile/purple{ dir = 4 }, +/obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow, /turf/open/floor/plasteel, /area/science/research{ name = "Research Sector" @@ -53815,16 +54082,11 @@ c_tag = "Research Maintenance"; dir = 4 }, -/obj/machinery/power/apc{ - areastring = "/area/maintenance/department/science"; - dir = 8; - name = "Research Wing Maintenance APC"; - pixel_x = -24 +/obj/structure/cable{ + icon_state = "2-4" }, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/turf/open/floor/circuit, +/area/science/robotics/mechbay) "ckl" = ( /turf/open/space/basic, /area/space/station_ruins) @@ -53854,17 +54116,16 @@ name = "Engine Room" }) "ckp" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, -/obj/machinery/light, -/obj/structure/table, -/obj/item/book/manual/wiki/robotics_cyborgs, -/obj/item/mmi, -/obj/item/mmi, -/obj/item/mmi, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/blue, +/obj/effect/landmark/start/chemist, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "ckq" = ( /obj/structure/closet/crate/hydroponics, /obj/machinery/light_switch{ @@ -53970,8 +54231,8 @@ /obj/machinery/light_switch{ pixel_x = -24 }, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /obj/item/stack/cable_coil/red, /obj/item/stack/cable_coil/red, /obj/item/stock_parts/cell/high/plus, @@ -53999,31 +54260,19 @@ /turf/open/floor/plasteel, /area/engine/teg_cold) "ckD" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/effect/turf_decal/tile/yellow{ + dir = 8 }, -/obj/structure/table, -/obj/item/storage/belt/utility, -/obj/item/crowbar/large, -/obj/item/multitool, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/warning/fire{ + pixel_x = 32; + pixel_y = -32 }, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 9 }, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/assembly/prox_sensor{ - pixel_x = -6; - pixel_y = 4 - }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "ckE" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel, @@ -54268,6 +54517,17 @@ }, /turf/open/floor/plasteel/dark, /area/science/xenobiology) +"clc" = ( +/obj/machinery/vending/wardrobe/chem_wardrobe, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "cld" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -54423,21 +54683,12 @@ }, /area/library) "clv" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/blue, +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/item/clothing/gloves/color/latex, -/obj/item/storage/box/syringes, -/obj/item/reagent_containers/dropper, -/obj/machinery/light{ - dir = 1 - }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/central) "clw" = ( /obj/effect/landmark/start/librarian, /obj/machinery/newscaster{ @@ -54554,18 +54805,15 @@ /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) "clO" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/brown, +/obj/effect/turf_decal/tile/purple{ + dir = 4 }, -/obj/machinery/door/airlock/engineering{ - name = "Electrical Substation"; - req_access_txt = "10" +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 }, -/turf/open/floor/plating, -/area/engine/storage_shared{ - name = "Electrical Substation" - }) +/turf/open/floor/plasteel, +/area/quartermaster/miningoffice) "clP" = ( /obj/structure/table, /obj/item/stock_parts/subspace/amplifier, @@ -54906,17 +55154,13 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/bar) "cmB" = ( -/obj/structure/cable{ - icon_state = "0-8" +/obj/structure/window/reinforced/spawner/west, +/obj/effect/turf_decal/delivery, +/obj/machinery/door/window/northright{ + name = "Emergency Shower" }, -/obj/machinery/power/apc{ - areastring = "/area/science/robotics/lab"; - dir = 4; - name = "Robotics Lab APC"; - pixel_x = 24 - }, -/turf/open/floor/plating, -/area/maintenance/aft) +/turf/open/floor/plasteel, +/area/medical/chemistry) "cmC" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 @@ -55013,6 +55257,23 @@ }, /turf/open/floor/plasteel, /area/quartermaster/miningoffice) +"cmK" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "cmL" = ( /obj/effect/landmark/blobstart, /turf/open/floor/plating, @@ -55070,20 +55331,25 @@ /turf/open/floor/engine, /area/science/xenobiology) "cmR" = ( +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "cmS" = ( -/obj/machinery/chem_master, -/obj/effect/turf_decal/stripes/line{ - dir = 5 +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 9 }, -/obj/machinery/light, /turf/open/floor/plasteel, -/area/medical/chemistry) +/area/science/robotics/lab) "cmT" = ( /obj/structure/table/reinforced, /obj/machinery/door/firedoor, @@ -55106,12 +55372,20 @@ /turf/open/floor/plasteel, /area/security/checkpoint/supply) "cmU" = ( -/obj/machinery/camera{ - c_tag = "Medbay - Lobby"; - network = list("ss13","rd") +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/area/medical/chemistry) "cmV" = ( /obj/structure/disposalpipe/segment, /obj/structure/cable{ @@ -55278,14 +55552,16 @@ name = "Research Observatory" }) "cnk" = ( -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/light, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 6 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "cnl" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 4 @@ -55421,6 +55697,21 @@ /area/science/server{ name = "Computer Core" }) +"cnz" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 1 + }, +/obj/structure/sign/departments/chemistry{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cnA" = ( /obj/effect/turf_decal/tile/brown{ dir = 4 @@ -55482,40 +55773,28 @@ }, /area/maintenance/port/fore) "cnG" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "1-2" +/obj/machinery/door/airlock/external/glass{ + name = "Shuttle Maintenance Access" }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/turf/open/space/basic, -/area/solar/port) +/obj/structure/fans/tiny, +/turf/open/floor/plasteel, +/area/hallway/secondary/exit) "cnH" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "0-2" +/obj/machinery/door/airlock/external/glass{ + name = "Departures Shuttle Dock" }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/space/basic, -/area/solar/port) +/obj/structure/fans/tiny, +/turf/open/floor/plasteel, +/area/hallway/secondary/exit) "cnI" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/obj/structure/cable{ - icon_state = "1-2" +/turf/open/floor/plating{ + icon_state = "platingdmg3" }, -/turf/open/space/basic, -/area/solar/port) +/area/space/nearstation) "cnJ" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "1-8" - }, -/turf/open/space/basic, -/area/solar/port) +/obj/structure/girder, +/turf/open/floor/plating/airless, +/area/space/nearstation) "cnK" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -55526,70 +55805,68 @@ /turf/open/floor/plasteel, /area/engine/teg_hot) "cnL" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/space/basic, -/area/solar/starboard/aft) +/obj/structure/closet/crate/science, +/obj/item/stack/sheet/metal/ten, +/obj/item/stack/sheet/glass/five, +/obj/item/stack/rods/twentyfive, +/obj/item/target/syndicate, +/obj/item/target/alien, +/obj/item/target, +/obj/item/target/clown, +/turf/open/floor/plasteel, +/area/science/mixing) "cnM" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "0-8" +/obj/machinery/mass_driver{ + dir = 8; + id = "pb_in"; + name = "Router Driver" }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/space/basic, -/area/solar/starboard/aft) +/turf/open/floor/plating/airless, +/area/router/aux) "cnN" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "1-2" +/obj/structure/bookcase/random/fiction, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/turf/open/space/basic, -/area/solar/starboard/aft) +/turf/open/floor/plasteel/dark, +/area/library) "cnO" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/engine, /area/science/storage) "cnP" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "1-2" +/obj/structure/disposalpipe/segment{ + dir = 9 }, +/obj/item/kirbyplants{ + icon_state = "plant-21"; + pixel_y = 3 + }, +/turf/open/floor/wood, +/area/library) +"cnQ" = ( +/obj/structure/lattice, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/camera{ + c_tag = "Supply - Warehouse Exterior"; + dir = 1 + }, +/turf/open/space/basic, +/area/quartermaster/warehouse) +"cnR" = ( /obj/structure/cable{ icon_state = "1-8" }, -/obj/structure/cable{ - icon_state = "1-4" +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 }, -/turf/open/space/basic, -/area/solar/starboard/aft) -"cnQ" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "0-4" +/obj/machinery/atmospherics/pipe/manifold/supplymain/hidden{ + dir = 4 }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/turf/open/space/basic, -/area/solar/starboard/aft) -"cnR" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable{ - icon_state = "0-2" - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/space/basic, -/area/solar/starboard/aft) +/turf/open/floor/plasteel, +/area/ai_monitored/turret_protected/ai_upload_foyer) "cnS" = ( /obj/structure/cable{ icon_state = "0-2" @@ -55777,22 +56054,20 @@ /turf/open/floor/plasteel, /area/engine/teg_hot) "col" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "com" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Robotics Storage"; - req_access_txt = "29" +/obj/machinery/chem_master, +/obj/effect/turf_decal/stripes/end{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/window/reinforced/spawner, +/turf/open/floor/plasteel, +/area/medical/chemistry) "con" = ( /obj/structure/cable{ icon_state = "1-2" @@ -55879,11 +56154,11 @@ /turf/open/floor/plasteel, /area/crew_quarters/heads/chief) "cov" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/disposalpipe/segment, -/obj/structure/cable, -/turf/open/floor/plating, -/area/science/robotics/lab) +/obj/structure/sign/warning/nosmoking{ + pixel_y = -32 + }, +/turf/closed/wall, +/area/medical/medbay/central) "cow" = ( /obj/machinery/door/airlock/external/glass{ name = "Asteroid Mining Access"; @@ -55904,10 +56179,15 @@ /turf/open/floor/plasteel, /area/quartermaster/miningoffice) "cox" = ( -/obj/machinery/vending/wardrobe/robo_wardrobe, -/obj/effect/decal/cleanable/cobweb, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 5 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "coy" = ( /obj/structure/sign/poster/official/safety_internals{ pixel_x = -32 @@ -56013,10 +56293,25 @@ /turf/open/floor/engine, /area/science/explab) "coH" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/medical/chemistry) +/obj/machinery/door/firedoor, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/research{ + name = "Robotics Lab"; + req_access_txt = "29" + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "coI" = ( /obj/structure/closet/secure_closet/medical1, /obj/effect/turf_decal/tile/yellow{ @@ -56213,6 +56508,8 @@ c_tag = "Medbay - Cryogenics"; dir = 1 }, +/obj/item/reagent_containers/glass/beaker/cryoxadone, +/obj/item/reagent_containers/glass/beaker/cryoxadone, /turf/open/floor/plasteel/white, /area/medical/medbay/zone2{ name = "Medbay Treatment Center" @@ -56338,18 +56635,25 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "cpm" = ( -/obj/structure/chair/stool, -/obj/effect/turf_decal/tile/neutral{ +/obj/effect/turf_decal/delivery, +/obj/machinery/photocopier, +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/machinery/requests_console{ + department = "Cargo Bay"; + departmentType = 2; + name = "Cargo RC"; + pixel_y = 30 }, -/obj/machinery/newscaster{ - pixel_x = -30 +/obj/machinery/camera{ + c_tag = "Supply - Delivery Office Aft"; + network = list("ss13","rd") }, -/turf/open/floor/plasteel/dark, -/area/lawoffice) +/obj/item/paper/guides/cogstation/disposals, +/obj/item/paper/fluff/cogstation/mulebot, +/turf/open/floor/plasteel, +/area/quartermaster/sorting) "cpn" = ( /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ @@ -56419,7 +56723,6 @@ icon_state = "2-4" }, /obj/machinery/holopad, -/obj/effect/turf_decal/bot, /turf/open/floor/wood, /area/library) "cpv" = ( @@ -56430,36 +56733,18 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "cpw" = ( -/obj/structure/table, +/obj/machinery/computer/operating, /obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/screwdriver, -/obj/item/stack/cable_coil/random, -/obj/item/stack/cable_coil/random, -/obj/machinery/light{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Research - Chemistry Lab"; dir = 4 }, -/obj/machinery/requests_console{ - department = "Chemistry"; - departmentType = 1; - name = "Chemistry RC"; - pixel_x = -30; - receive_ore_updates = 1 +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/structure/sign/poster/official/space_cops{ + pixel_y = 32 }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "cpx" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/mineral/titanium/blue, @@ -56561,12 +56846,13 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "cpI" = ( -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ +/obj/machinery/chem_dispenser, +/obj/effect/turf_decal/stripes/end{ dir = 4 }, +/obj/structure/window/reinforced/spawner, /turf/open/floor/plasteel, -/area/science/robotics/lab) +/area/medical/chemistry) "cpJ" = ( /turf/closed/wall/r_wall/rust, /area/quartermaster/office) @@ -57034,28 +57320,11 @@ /turf/open/floor/plasteel, /area/engine/break_room) "cqz" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/item/clothing/gloves/color/latex, -/obj/item/book/manual/wiki/cit/chem_recipies, -/obj/item/book/manual/wiki/cit/chemistry{ - pixel_x = 2; - pixel_y = -3 - }, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden, -/obj/item/paper/fluff/cogstation/chemists, -/obj/item/reagent_containers/dropper, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel, +/area/science/robotics/lab) "cqA" = ( /obj/structure/cable{ icon_state = "1-2" @@ -57247,6 +57516,13 @@ /area/hallway/secondary/entry) "cqW" = ( /obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/structure/window/reinforced/spawner, +/obj/structure/disposalpipe/junction/flip{ + dir = 4 + }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cqX" = ( @@ -57368,24 +57644,32 @@ /turf/open/floor/plasteel, /area/quartermaster/miningoffice) "crf" = ( -/obj/structure/cable, -/obj/machinery/power/apc{ - areastring = "/area/medical/chemistry"; - name = "Chemistry Lab APC"; - pixel_y = -26 - }, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plasteel/dark, +/area/science/robotics/mechbay) "crg" = ( -/obj/structure/reagent_dispensers/fueltank/high, -/obj/machinery/light/small, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/machinery/door/firedoor, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/machinery/door/airlock/medical/glass{ + name = "Chemistry Lab"; + req_access_txt = "5; 33" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "crh" = ( /obj/machinery/mass_driver{ dir = 1; @@ -57439,6 +57723,15 @@ }, /turf/open/floor/plating, /area/engine/teg_cold) +"crn" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "chem1"; + name = "chem lab shutters" + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/turf/open/floor/plating, +/area/medical/chemistry) "cro" = ( /turf/closed/wall/r_wall/rust, /area/maintenance/starboard/aft) @@ -57552,10 +57845,29 @@ name = "Engine Room" }) "cry" = ( -/obj/structure/bookcase/random/religion, -/obj/effect/turf_decal/bot, -/turf/open/floor/wood, -/area/library) +/obj/structure/table, +/obj/item/stack/sheet/plasteel{ + amount = 10; + pixel_x = -5 + }, +/obj/item/stack/cable_coil/random, +/obj/item/stack/cable_coil/random{ + pixel_x = -2; + pixel_y = -2 + }, +/obj/item/stack/cable_coil/random{ + pixel_x = 2; + pixel_y = 2 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/camera{ + c_tag = "Robotics - Surgery"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/science/robotics/lab) "crz" = ( /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ @@ -57570,10 +57882,12 @@ /turf/open/floor/plasteel, /area/tcommsat/computer) "crA" = ( -/obj/structure/bookcase/random/fiction, -/obj/effect/turf_decal/bot, -/turf/open/floor/wood, -/area/library) +/obj/machinery/aug_manipulator, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/science/robotics/lab) "crB" = ( /obj/structure/lattice, /obj/machinery/camera/motion{ @@ -57752,9 +58066,14 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "crW" = ( -/obj/effect/landmark/start/paramedic, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/obj/machinery/computer/rdconsole/robotics{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/science/robotics/lab) "crX" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 @@ -57890,12 +58209,14 @@ /turf/open/floor/plasteel, /area/security/checkpoint/supply) "csi" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 4 +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "chem1"; + name = "chem lab shutters" }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plating, +/area/medical/chemistry) "csj" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 @@ -58195,9 +58516,23 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "csK" = ( +/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue, +/obj/machinery/door/window/northright{ + name = "Medbay Desk"; + req_access_txt = "5" + }, +/obj/item/clipboard, /obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/closed/wall, -/area/science/robotics/lab) +/obj/item/paper/guides/cogstation/letter_med, +/obj/item/clothing/glasses/hud/health, +/obj/item/pen, +/obj/item/clothing/glasses/hud/health, +/turf/open/floor/plasteel/white, +/area/medical/medbay/lobby) "csL" = ( /obj/effect/landmark/xmastree/rdrod, /turf/open/floor/carpet{ @@ -58266,19 +58601,21 @@ /turf/open/floor/plating, /area/storage/tech) "csV" = ( -/obj/machinery/chem_master, -/obj/effect/turf_decal/stripes/line{ - dir = 6 +/obj/effect/turf_decal/tile/purple{ + dir = 4 }, -/obj/machinery/light{ - dir = 1 +/obj/effect/turf_decal/tile/purple, +/obj/machinery/button/door{ + id = "robotics"; + name = "Shutters Control Button"; + pixel_y = 8; + req_access_txt = "29"; + pixel_x = -24 }, -/obj/item/radio/intercom{ - name = "Station Intercom (Common)"; - pixel_y = 26 +/turf/open/floor/plasteel/dark/side{ + dir = 8 }, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/area/science/robotics/lab) "csW" = ( /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel/dark, @@ -58296,10 +58633,11 @@ /turf/open/floor/plasteel/white, /area/science/xenobiology) "csZ" = ( -/obj/machinery/holopad, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/robotics/lab) "cta" = ( /obj/effect/landmark/blobstart, /obj/effect/landmark/xeno_spawn, @@ -59009,20 +59347,42 @@ name = "Research Observatory" }) "cum" = ( -/obj/machinery/disposal/bin, -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/structure/rack, +/obj/item/storage/firstaid/regular{ + empty = 1; + name = "First-Aid (empty)" }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ +/obj/item/storage/firstaid/regular{ + empty = 1; + name = "First-Aid (empty)" + }, +/obj/item/storage/firstaid/regular{ + empty = 1; + name = "First-Aid (empty)" + }, +/obj/item/healthanalyzer{ + pixel_x = 4; + pixel_y = -4 + }, +/obj/item/healthanalyzer{ + pixel_x = 4; + pixel_y = -4 + }, +/obj/item/healthanalyzer{ + pixel_x = 4; + pixel_y = -4 + }, +/obj/item/assembly/prox_sensor, +/obj/item/assembly/prox_sensor, +/obj/item/assembly/prox_sensor, +/obj/item/assembly/prox_sensor, +/obj/item/assembly/prox_sensor, +/obj/machinery/light, +/obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/structure/disposalpipe/trunk, -/obj/structure/sign/poster/official/science{ - pixel_y = 32 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel, +/area/science/robotics/lab) "cun" = ( /obj/structure/table/reinforced, /obj/item/reagent_containers/food/snacks/meat/steak, @@ -59040,21 +59400,14 @@ /turf/open/floor/plating, /area/hallway/primary/aft) "cup" = ( -/obj/structure/table, -/obj/item/surgical_drapes, -/obj/item/scalpel, -/obj/item/circular_saw{ - pixel_y = 16 +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/obj/item/hemostat, -/obj/item/retractor, -/obj/item/cautery, -/obj/item/clothing/gloves/color/latex, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 +/obj/effect/turf_decal/tile/blue{ + dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cuq" = ( /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -59110,7 +59463,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/photosynthetic, +/obj/item/kirbyplants/photosynthetic, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -59402,38 +59755,30 @@ /area/medical/medbay/central) "cuY" = ( /obj/machinery/door/firedoor, -/obj/machinery/door/airlock/research{ - name = "Chemistry Lab"; - req_access_txt = "8;33;47" - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/turf/open/floor/plasteel, -/area/medical/chemistry) +/obj/machinery/door/airlock/research{ + name = "Robotics Lab"; + req_access_txt = "29" + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "cuZ" = ( /obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 5 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel/dark/side{ dir = 4 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/science/robotics/lab) "cva" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -59583,22 +59928,22 @@ /area/medical/virology) "cvt" = ( /obj/effect/turf_decal/tile/purple{ - dir = 8 + dir = 4 }, -/obj/effect/turf_decal/tile/yellow, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"cvu" = ( -/obj/machinery/holopad, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 +/turf/open/floor/plasteel/dark/side{ + dir = 10 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/dark, /area/science/robotics/lab) +"cvu" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cvv" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -59899,56 +60244,46 @@ /area/janitor) "cvQ" = ( /obj/effect/turf_decal/tile/purple{ - dir = 8 + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 }, -/obj/effect/landmark/start/chemist, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/chair/office/light, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"cvR" = ( -/obj/structure/table, -/obj/item/storage/toolbox/emergency, -/obj/item/clothing/head/welding, -/obj/item/clothing/glasses/welding, -/obj/item/weldingtool, -/obj/machinery/camera{ - c_tag = "Robotics"; - dir = 8; - network = list("ss13","medbay"); - pixel_y = -22 - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = 26 - }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel/dark/side, /area/science/robotics/lab) -"cvS" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ +"cvR" = ( +/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/item/paper_bin, -/obj/item/pen, -/obj/item/clothing/glasses/science, -/obj/item/hand_labeler{ - pixel_y = 8 +/obj/structure/disposalpipe/sorting/mail/flip{ + sortType = 23 }, -/obj/structure/extinguisher_cabinet{ - pixel_y = -32 +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, /turf/open/floor/plasteel/white, -/area/medical/chemistry) +/area/medical/medbay/central) +"cvS" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/holopad, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "cvT" = ( /obj/structure/extinguisher_cabinet, /turf/closed/wall, @@ -60068,23 +60403,18 @@ /turf/open/floor/plasteel/dark, /area/security/checkpoint/customs) "cwb" = ( -/obj/machinery/door/airlock/maintenance{ - name = "Research Maintenance"; - req_one_access_txt = "12;47" - }, /obj/structure/disposalpipe/segment{ dir = 4 }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/structure/cable{ - icon_state = "1-8" +/obj/machinery/door/airlock/research{ + name = "Mech Bay"; + req_access_txt = "29" }, -/turf/open/floor/plating, -/area/science/research{ - name = "Research Sector" - }) +/turf/open/floor/circuit, +/area/science/robotics/mechbay) "cwc" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -60274,11 +60604,22 @@ /turf/open/floor/plasteel, /area/engine/workshop) "cws" = ( -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/machinery/light_switch{ + pixel_x = -24 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "cwt" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/orange/hidden, @@ -60569,19 +60910,41 @@ /turf/open/floor/plasteel, /area/quartermaster/warehouse) "cxf" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) -"cxg" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) -"cxh" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 5 +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"cxg" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"cxh" = ( +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/landmark/start/chemist, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "cxi" = ( /obj/structure/rack, /obj/effect/turf_decal/tile/yellow{ @@ -61031,17 +61394,15 @@ /turf/open/floor/plasteel, /area/quartermaster/miningoffice) "cyd" = ( -/obj/effect/turf_decal/tile/brown{ - dir = 1 +/obj/structure/cable{ + icon_state = "1-8" }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 5 - }, -/turf/open/floor/plasteel, -/area/quartermaster/miningoffice) +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/turf/open/floor/plating, +/area/ai_monitored/turret_protected/ai_upload_foyer) "cye" = ( /obj/structure/disposalpipe/segment{ dir = 5 @@ -61106,10 +61467,6 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/general/hidden{ - dir = 8; - icon_state = "intact" - }, /obj/structure/disposalpipe/segment{ dir = 9 }, @@ -61187,6 +61544,7 @@ pixel_y = 24 }, /obj/machinery/power/apc{ + dir = 4; name = "Restrooms APC"; pixel_x = 24 }, @@ -61214,25 +61572,34 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "cyt" = ( -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 5 +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 }, -/turf/open/floor/plating, -/area/maintenance/aft) -"cyu" = ( /obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/purple, +/obj/machinery/power/apc{ + areastring = "/area/science/robotics/lab"; + dir = 8; + name = "Robotics Lab APC"; + pixel_x = -25 + }, /obj/structure/cable{ - icon_state = "2-4" + icon_state = "0-4" }, -/obj/machinery/camera{ - c_tag = "Aft Maintenance - Port"; - pixel_x = 22 +/turf/open/floor/plasteel, +/area/science/research{ + name = "Research Sector" + }) +"cyu" = ( +/obj/structure/closet/wardrobe/chemistry_white{ + anchored = 1 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 10 - }, -/turf/open/floor/plating, -/area/maintenance/aft) +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "cyv" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 @@ -61296,24 +61663,38 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) "cyB" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/sign/poster/official/medical_green_cross{ + pixel_y = 32 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cyC" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/obj/structure/cable{ - icon_state = "1-4" +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cyD" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -61328,50 +61709,32 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) "cyF" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 - }, +/obj/structure/closet/secure_closet/chemical, /turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/area/medical/chemistry) "cyG" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/obj/machinery/chem_master, +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "cyH" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Aft Maintenance"; - req_access_txt = "12" +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 8 - }, -/turf/open/floor/plating, -/area/medical/medbay/lobby) -"cyI" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/aft) +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"cyI" = ( +/obj/effect/turf_decal/tile/blue, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 10 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cyJ" = ( /obj/effect/turf_decal/tile/green{ dir = 8 @@ -61388,41 +61751,37 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) "cyL" = ( -/obj/structure/closet/cardboard, -/obj/structure/disposalpipe/segment{ +/obj/effect/turf_decal/tile/blue, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 5 }, -/obj/structure/cable{ - icon_state = "1-4" +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 5 - }, -/turf/open/floor/plating, -/area/maintenance/aft) +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cyM" = ( -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ - dir = 10 - }, -/turf/open/floor/plating, -/area/maintenance/aft) -"cyN" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Robotics Lab Maintenance"; - req_access_txt = "29" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ +/obj/structure/closet/secure_closet/personal/patient, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/purple{ dir = 8 }, -/turf/open/floor/plating, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/window/reinforced/spawner, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"cyN" = ( +/obj/machinery/chem_dispenser/apothecary, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "cyO" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -61787,16 +62146,23 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) "czv" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/research{ - name = "Morgue"; - req_access_txt = "5;29" +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -28 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "czw" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 @@ -61843,18 +62209,12 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) "czB" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/maintenance{ - name = "Medbay Maintenance"; - req_access_txt = "5" +/obj/effect/turf_decal/tile/yellow{ + dir = 4 }, -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "czC" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 @@ -61888,41 +62248,26 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "czF" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/structure/disposalpipe/sorting/mail/flip{ - sortType = 23 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel/white, -/area/medical/medbay/central) +/area/medical/chemistry) "czG" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel/showroomfloor, /area/medical/morgue) "czH" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 +/obj/machinery/button/door{ + id = "robotics2"; + name = "Shutters Control Button"; + pixel_x = 24; + pixel_y = -24; + req_access_txt = "29" }, -/obj/effect/turf_decal/tile/yellow, /obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) "czI" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -61957,9 +62302,15 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "czM" = ( -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/obj/machinery/requests_console{ + department = "Chemistry"; + departmentType = 2; + name = "Chemistry RC"; + pixel_x = 30; + receive_ore_updates = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) "czN" = ( /obj/structure/closet/crate/trashcart, /obj/structure/sign/departments/custodian{ @@ -61984,11 +62335,12 @@ /turf/open/floor/plating, /area/maintenance/disposal) "czP" = ( -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 10 +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/machinery/light/small{ + dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "czQ" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment, @@ -62065,24 +62417,14 @@ /turf/open/floor/plasteel, /area/maintenance/disposal) "czW" = ( -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/machinery/door/airlock/research/glass{ - name = "Robotics Lab"; - req_access_txt = "29" - }, -/obj/effect/turf_decal/tile/purple{ +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/chair/office/light{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/white, -/area/science/robotics/lab) +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "czX" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/orange/hidden, @@ -62141,14 +62483,11 @@ /turf/open/floor/plasteel, /area/maintenance/disposal) "cAc" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, -/turf/open/floor/plasteel/white, +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, /area/medical/medbay/central) "cAd" = ( /obj/structure/disposalpipe/segment, @@ -62273,23 +62612,17 @@ /turf/open/floor/plating, /area/maintenance/disposal) "cAo" = ( -/obj/structure/table/reinforced, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/blue, -/obj/machinery/door/window/northright{ - name = "Medbay Desk"; - req_access_txt = "5" +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 }, -/obj/item/clipboard, -/obj/item/clothing/glasses/hud/health, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/obj/item/paper/fluff/cogstation/sleepers, -/obj/item/pen, -/obj/item/clothing/glasses/hud/health, /turf/open/floor/plasteel/white, -/area/medical/medbay/lobby) +/area/medical/medbay/central) "cAp" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ @@ -63866,9 +64199,6 @@ /obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ dir = 8 }, -/obj/structure/chair/comfy/brown{ - dir = 8 - }, /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/hos) "cCX" = ( @@ -64110,7 +64440,7 @@ /obj/structure/sign/warning/securearea{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/machinery/airalarm{ @@ -64323,6 +64653,40 @@ }, /turf/open/floor/engine, /area/gateway) +"cDL" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/machinery/atmospherics/pipe/manifold/orange/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Medbay - Apothecary"; + dir = 8; + network = list("ss13","medbay"); + pixel_y = -22 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"cDM" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/table/glass, +/obj/item/book/manual/wiki/chemistry, +/obj/item/book/manual/wiki/chemistry{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/clothing/glasses/science, +/obj/item/clothing/glasses/science{ + pixel_x = 2; + pixel_y = 4 + }, +/turf/open/floor/plasteel, +/area/medical/chemistry) "cDN" = ( /obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 8 @@ -64383,6 +64747,10 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 }, +/obj/item/stack/cable_coil/red, +/obj/item/stack/cable_coil/red{ + pixel_x = 3 + }, /turf/open/floor/plasteel, /area/gateway) "cDU" = ( @@ -64992,15 +65360,18 @@ name = "Research Sector" }) "cEN" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, /obj/structure/disposalpipe/segment, /obj/structure/cable{ icon_state = "1-2" }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/structure/cable{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/science/research{ name = "Research Sector" @@ -65011,37 +65382,28 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/door/airlock/research{ - name = "Chemistry Lab"; - req_access_txt = "8; 33" - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel, -/area/medical/chemistry) -"cEP" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/machinery/door/airlock/research{ + name = "Robotics Lab"; + req_access_txt = "29" }, -/obj/effect/turf_decal/tile/yellow{ - dir = 1 - }, -/obj/structure/disposalpipe/segment, /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"cEP" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel/dark/side, +/area/science/robotics/lab) "cEQ" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -65385,27 +65747,24 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cFs" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/red{ - dir = 8 +/obj/structure/noticeboard{ + pixel_y = 28 }, -/obj/item/surgical_drapes, -/obj/item/scalpel, -/obj/item/circular_saw{ - pixel_y = 16 +/obj/machinery/light{ + dir = 1 }, -/obj/item/hemostat, -/obj/item/retractor, -/obj/item/surgicaldrill, -/obj/item/cautery, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/item/paper/guides/cogstation/letter_med, /turf/open/floor/plasteel/white, -/area/medical/medbay/zone2{ - name = "Medbay Treatment Center" - }) +/area/medical/medbay/central) "cFt" = ( /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -65738,68 +66097,63 @@ /turf/open/floor/plasteel/white, /area/medical/virology) "cFV" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 8 +/obj/structure/table, +/obj/item/storage/belt/utility, +/obj/item/storage/belt/utility, +/obj/item/multitool{ + pixel_x = 3 }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/item/multitool{ + pixel_x = 3 }, -/obj/structure/cable{ - icon_state = "1-4" +/obj/item/storage/toolbox/mechanical{ + pixel_x = 2; + pixel_y = -1 }, -/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"cFW" = ( -/obj/effect/turf_decal/tile/purple{ - dir = 4 +/obj/item/storage/toolbox/mechanical{ + pixel_x = 2; + pixel_y = -1 }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 +/obj/item/storage/toolbox/electrical{ + pixel_x = -1; + pixel_y = 4 }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ - dir = 4 +/obj/item/storage/toolbox/electrical{ + pixel_x = -1; + pixel_y = 4 }, -/obj/structure/cable{ - icon_state = "4-8" +/obj/item/clothing/head/welding{ + pixel_x = -3; + pixel_y = 5 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 +/obj/item/clothing/head/welding{ + pixel_x = -3; + pixel_y = 5 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) -"cFX" = ( -/obj/machinery/door/firedoor, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/door/airlock/research/glass{ - name = "Chemistry Lab"; - req_access_txt = "33" - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/purple{ - dir = 8 +/turf/open/floor/plasteel, +/area/science/robotics/lab) +"cFW" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "robotics2"; + name = "robotics lab shutters" }, -/obj/effect/turf_decal/tile/purple{ +/obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 +/turf/open/floor/plating, +/area/science/robotics/lab) +"cFX" = ( +/obj/machinery/chem_heater, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 26 }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "cFY" = ( /turf/open/floor/plasteel, /area/router/air) @@ -66267,6 +66621,14 @@ /obj/machinery/portable_atmospherics/pump, /turf/open/floor/engine, /area/science/storage) +"cGI" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/chair/office/light, +/obj/effect/landmark/start/chemist, +/turf/open/floor/plasteel, +/area/medical/chemistry) "cGJ" = ( /obj/machinery/portable_atmospherics/canister/oxygen, /obj/effect/turf_decal/stripes/line{ @@ -66298,6 +66660,21 @@ /obj/structure/tank_dispenser, /turf/open/floor/engine, /area/science/storage) +"cGN" = ( +/obj/structure/closet/l3closet, +/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"cGO" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cGP" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -66336,6 +66713,17 @@ }, /turf/open/floor/plasteel/white, /area/science/circuit) +"cGU" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/machinery/door/airlock/medical{ + name = "Morgue"; + req_access_txt = "5;6" + }, +/turf/open/floor/plasteel/showroomfloor, +/area/medical/morgue) "cGV" = ( /obj/machinery/portable_atmospherics/canister/toxins, /obj/effect/turf_decal/delivery, @@ -66423,6 +66811,7 @@ /obj/item/stock_parts/cell/high/plus, /obj/item/stock_parts/cell/high/plus, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/item/stack/cable_coil/red, /turf/open/floor/plasteel/white, /area/science/circuit) "cHg" = ( @@ -66577,14 +66966,8 @@ dir = 8; network = list("ss13","medbay") }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/dark/side{ - dir = 8 - }, +/turf/open/floor/plasteel/dark, /area/science/explab) "cHw" = ( /obj/structure/disposalpipe/segment, @@ -66659,10 +67042,6 @@ /obj/structure/cable{ icon_state = "0-8" }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/yellow, /obj/machinery/power/apc{ areastring = "/area/science/explab"; dir = 4; @@ -66670,9 +67049,7 @@ pixel_x = 24 }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden, -/turf/open/floor/plasteel/dark/side{ - dir = 8 - }, +/turf/open/floor/plasteel/dark, /area/science/explab) "cHD" = ( /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ @@ -66866,13 +67243,18 @@ /turf/open/floor/plasteel, /area/security/checkpoint/supply) "cHW" = ( -/obj/machinery/rnd/production/circuit_imprinter, -/obj/item/reagent_containers/glass/beaker, -/obj/structure/sign/poster/official/state_laws{ - pixel_y = 32 +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/delivery, +/obj/structure/table/reinforced, +/obj/machinery/door/window/eastright{ + base_state = "left"; + dir = 2; + icon_state = "left"; + name = "Chemistry Desk"; + req_access_txt = "33" }, -/turf/open/floor/circuit, -/area/science/robotics/lab) +/turf/open/floor/plasteel, +/area/medical/chemistry) "cHX" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -67236,7 +67618,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/photosynthetic, +/obj/item/kirbyplants/photosynthetic, /obj/machinery/airalarm{ pixel_y = 24 }, @@ -67573,12 +67955,10 @@ /turf/open/floor/plasteel/freezer, /area/crew_quarters/toilet/restrooms) "cJg" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/toilet/restrooms) +/obj/structure/disposalpipe/segment, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/quartermaster/warehouse) "cJh" = ( /obj/structure/table, /obj/structure/bedsheetbin/towel, @@ -67681,15 +68061,17 @@ name = "Engine Room" }) "cJq" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/machinery/suit_storage_unit/engine, -/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supplymain/visible, +/obj/structure/cable{ + icon_state = "1-2" }, +/obj/machinery/door/airlock/external/glass{ + name = "External Construction Access"; + req_one_access_txt = "10;31" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plasteel, -/area/engine/engineering{ - name = "Engine Room" - }) +/area/quartermaster/warehouse) "cJr" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/simple/supplymain/visible{ @@ -67698,23 +68080,28 @@ /turf/open/space/basic, /area/space/nearstation) "cJs" = ( -/obj/structure/lattice/catwalk, /obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/simple/supplymain/visible{ - dir = 4 - }, -/turf/open/space/basic, -/area/space/nearstation) +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/quartermaster/warehouse) "cJt" = ( -/obj/structure/lattice/catwalk, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/light{ + dir = 8 + }, +/obj/machinery/power/apc{ + name = "AI Upload Foyer APC"; + pixel_y = -24 + }, /obj/structure/cable{ - icon_state = "1-2" + icon_state = "0-4" }, -/obj/machinery/atmospherics/pipe/manifold/supplymain/visible{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 5 }, -/turf/open/space/basic, -/area/space/nearstation) +/turf/open/floor/plasteel, +/area/ai_monitored/turret_protected/ai_upload_foyer) "cJu" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 1 @@ -68196,12 +68583,14 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/lobby) "cKi" = ( -/obj/structure/sign/poster/official/space_cops{ - pixel_y = 32 +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/machinery/door/airlock/medical{ + name = "Apothecary"; + req_access_txt = "5" }, -/obj/machinery/atmospherics/pipe/manifold/orange/hidden, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/showroomfloor, +/area/medical/medbay/central) "cKj" = ( /obj/structure/closet/secure_closet/CMO, /obj/effect/turf_decal/tile/blue, @@ -68432,6 +68821,24 @@ /obj/structure/closet/wardrobe/yellow, /turf/open/floor/plasteel, /area/hallway/primary/central) +"cKH" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/machinery/airalarm{ + pixel_y = 24 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cKI" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -69642,12 +70049,20 @@ /turf/open/floor/plating, /area/quartermaster/miningdock/airless) "cNC" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 +/obj/effect/turf_decal/stripes/line, +/obj/structure/disposalpipe/segment, +/obj/structure/cable{ + icon_state = "2-4" }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/toilet/restrooms) +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/ai_monitored/turret_protected/ai_upload_foyer) "cND" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel, @@ -69696,17 +70111,24 @@ /turf/open/floor/plating/airless, /area/router/aux) "cNJ" = ( -/obj/structure/disposalpipe/segment, -/obj/structure/cable{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/obj/structure/cable{ - icon_state = "1-8" +/obj/structure/disposalpipe/segment{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plating, -/area/maintenance/aft) +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden{ + dir = 1 + }, +/obj/machinery/camera{ + c_tag = "Medbay - Starboard"; + network = list("ss13","rd") + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cNK" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/on{ dir = 4 @@ -69789,14 +70211,18 @@ /turf/open/floor/plating, /area/quartermaster/miningdock/airless) "cNV" = ( -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -23 +/obj/effect/turf_decal/tile/blue{ + dir = 1 }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel, -/area/science/robotics/lab) +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/manifold/cyan/hidden, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cNW" = ( /obj/structure/lattice/catwalk, /obj/machinery/camera{ @@ -70482,38 +70908,19 @@ icon_state = "4-8" }, /obj/effect/landmark/event_spawn, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/obj/structure/cable{ + icon_state = "2-4" + }, +/turf/open/floor/circuit, +/area/science/robotics/mechbay) "cPw" = ( -/obj/structure/reagent_dispensers/watertank, -/obj/structure/sign/poster/contraband/kss13{ - pixel_y = -32 - }, -/turf/open/floor/plating, -/area/maintenance/department/science{ - name = "Research Maintenance" - }) +/turf/open/floor/plasteel/dark, +/area/science/robotics/mechbay) "cPx" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/machinery/light{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, /obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ dir = 4 }, -/obj/structure/sign/poster/official/medical_green_cross{ - pixel_y = 32 - }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cPy" = ( @@ -70598,15 +71005,25 @@ /turf/open/space/basic, /area/space/nearstation) "cPG" = ( -/obj/structure/lattice, -/obj/structure/disposalpipe/segment, -/obj/machinery/camera{ - c_tag = "Supply - Warehouse Exterior"; - dir = 1 +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable{ + icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/simple/orange/hidden, -/turf/open/space/basic, -/area/space/nearstation) +/obj/machinery/turretid{ + control_area = "/area/science/server"; + icon_state = "control_stun"; + name = "Computer Core turret control"; + pixel_x = -3; + pixel_y = -23; + req_access_txt = "65" + }, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/science/server{ + name = "Computer Core" + }) "cPH" = ( /obj/machinery/conveyor_switch{ id = "EngiCargoConveyer" @@ -70713,45 +71130,12 @@ /turf/open/floor/plating, /area/maintenance/starboard/aft) "cPP" = ( -/obj/structure/table, -/obj/machinery/light{ - dir = 4; - light_color = "#c1caff" +/obj/effect/landmark/start/paramedic, +/obj/structure/disposalpipe/segment{ + dir = 9 }, -/obj/machinery/cell_charger, -/obj/item/stock_parts/cell/high/plus, -/obj/item/stock_parts/cell/high/plus{ - pixel_y = 8 - }, -/obj/item/stock_parts/cell/high/plus{ - pixel_y = 8 - }, -/obj/item/assembly/flash/handheld{ - pixel_x = -8; - pixel_y = 4 - }, -/obj/item/assembly/flash/handheld{ - pixel_x = -8; - pixel_y = 4 - }, -/obj/item/assembly/flash/handheld{ - pixel_x = -8; - pixel_y = 4 - }, -/obj/item/assembly/flash/handheld{ - pixel_x = -8; - pixel_y = 4 - }, -/obj/item/assembly/flash/handheld{ - pixel_x = -8; - pixel_y = 4 - }, -/obj/item/assembly/flash/handheld{ - pixel_x = -8; - pixel_y = 4 - }, -/turf/open/floor/plasteel/dark, -/area/science/robotics/lab) +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) "cPQ" = ( /obj/structure/disposalpipe/segment{ dir = 6 @@ -71419,7 +71803,7 @@ /turf/open/floor/plating, /area/bridge) "cQV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /obj/structure/cable{ @@ -71492,9 +71876,6 @@ /obj/item/paper/guides/jobs/medical/cloning{ pixel_x = -4 }, -/obj/item/paper/fluff/cogstation/cloner{ - pixel_x = 6 - }, /turf/open/floor/plasteel, /area/medical/medbay/central) "cRc" = ( @@ -71560,20 +71941,201 @@ /turf/open/floor/plasteel/white/corner, /area/engine/atmos) "cRh" = ( -/obj/effect/turf_decal/stripes/line, -/obj/structure/cable{ - icon_state = "1-8" +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 4 }, -/obj/machinery/turretid{ - control_area = "area/science/server"; - icon_state = "control_stun"; - name = "Computer Core turret control"; - pixel_x = -3; - pixel_y = -23; - req_access_txt = "65" +/turf/closed/wall/r_wall, +/area/ai_monitored/turret_protected/ai_upload_foyer) +"cRi" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel/dark/side, +/area/science/robotics/lab) +"cRj" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/plasteel/dark/side{ + dir = 6 + }, +/area/science/robotics/lab) +"cRk" = ( +/obj/structure/table, +/obj/machinery/cell_charger, +/obj/item/stock_parts/cell/high{ + charge = 100; + maxcharge = 15000; + pixel_y = 3; + pixel_x = 4 + }, +/obj/item/stock_parts/cell/high{ + charge = 100; + maxcharge = 15000; + pixel_x = -6; + pixel_y = 6 + }, +/obj/item/stock_parts/cell/high{ + charge = 100; + maxcharge = 15000 + }, +/obj/machinery/button/door{ + id = "robotics3"; + name = "Shutters Control Button"; + pixel_x = 24; + pixel_y = -24; + req_access_txt = "29" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 }, /turf/open/floor/plasteel, +/area/science/robotics/lab) +"cRl" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"cRm" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/machinery/light, +/obj/effect/turf_decal/stripes/red/full, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/structure/sign/poster/official/cleanliness{ + pixel_y = -32 + }, +/obj/machinery/disposal/bin{ + name = "Corpse Disposal Unit" + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone2{ + name = "Medbay Treatment Center" + }) +"cRn" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden, +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"cRo" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 8 + }, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"cRp" = ( +/obj/machinery/atmospherics/pipe/simple/cyan/hidden{ + dir = 5 + }, +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/landmark/start/roboticist, +/turf/open/floor/plasteel/dark, +/area/science/robotics/lab) +"cRq" = ( +/obj/machinery/rnd/production/circuit_imprinter/department/science, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/science/robotics/lab) +"cRr" = ( +/obj/machinery/droneDispenser, +/obj/item/stack/sheet/metal/fifty, +/obj/item/stack/sheet/glass/fifty, +/obj/effect/turf_decal/stripes/line{ + dir = 5; + layer = 2.03 + }, +/turf/open/floor/plasteel, +/area/science/robotics/lab) +"cRs" = ( +/obj/machinery/recharge_station, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{ + dir = 9 + }, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/turf/open/floor/plating, /area/ai_monitored/turret_protected/ai_upload_foyer) +"cRt" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supplymain/hidden, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/quartermaster/warehouse) +"cRu" = ( +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/science/mixing) +"cRv" = ( +/mob/living/simple_animal/opossum{ + desc = "Wubba lubba dub dub."; + name = "Rick" + }, +/turf/open/floor/plasteel/showroomfloor, +/area/medical/morgue) +"cRw" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, +/obj/item/paper/guides/cogstation/letter_med{ + pixel_y = 4 + }, +/obj/item/storage/backpack/duffelbag/med/surgery, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone2{ + name = "Medbay Treatment Center" + }) "cVq" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 4 @@ -71681,14 +72243,6 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) -"frb" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/simple/supplymain/visible, -/obj/structure/cable{ - icon_state = "1-2" - }, -/turf/open/space/basic, -/area/space/nearstation) "fti" = ( /obj/machinery/atmospherics/components/binary/pump, /obj/machinery/atmospherics/pipe/simple/orange/hidden{ @@ -84501,7 +85055,7 @@ akI aAJ cMp aYa -bxm +akI akI aNC bxv @@ -84757,7 +85311,7 @@ aLH akI aAK aRC -bxn +aHj akI bxA hiV @@ -85270,11 +85824,11 @@ aaU aaa aaU aEa -cMK -bxq +aXm +aXs bxC akI -bxK +beC bxY byh byb @@ -85528,7 +86082,7 @@ aaU aaU aEa cMK -bxt +aHE akI akI akI @@ -85784,9 +86338,9 @@ aaU aaa aaU aEa -aHE -bab -aaa +cMK +aTh +akI aaa aaU aaa @@ -86041,7 +86595,8 @@ aaU aaU aaU aEb -aPT +aya +bab aaU aaU aye @@ -86059,7 +86614,6 @@ aye aye aye aye -aye aaa aaa aaa @@ -86801,7 +87355,7 @@ aaa aaa aaa aaU -aiq +aee aaU aaa aaa @@ -87058,7 +87612,7 @@ aaa aaa aaa aaU -aiq +abh aaU aaa aaa @@ -87315,7 +87869,7 @@ abi aaa aaa aaK -aaM +aaL abi aaa aaa @@ -89880,17 +90434,17 @@ aaa aaa aaa aaU -bOc +aee aaU aaU aaU aaU -bOc +aee aaU aaU aaU aaU -bOc +aee aaU aaU aaU @@ -90137,17 +90691,17 @@ aaa aaa aaa aaU -bOf -ciA -ciA -ciA -ciA -cnG -cnH +abh +abh +abh +abh +abh +abh +aiq aaL -cnI -ciA -cnJ +ajc +abh +abh abh abh abh @@ -90208,7 +90762,7 @@ aaa aaa aaa aaa -aaa +aWj aaU aaa aaU @@ -90464,9 +91018,9 @@ aaa aaa aaa aaa -aaa -aWj -aaU +bcw +aUZ +bcw aaa bcy cnU @@ -90722,7 +91276,7 @@ aaa aaa aaa bcw -aUZ +cRu bcw aaa bcy @@ -90744,7 +91298,7 @@ aaa aaa aaU aaa -bAb +brs bxT bFq bHY @@ -90914,10 +91468,10 @@ aaa aaa aaU abx -aqw -aoW -aqw -aqw +aiN +alu +aiN +abx aaU aaa aaa @@ -91171,9 +91725,9 @@ aaa aaa aaU abx -akg -apS -arr +aiN +asl +aiN abx aaU aaa @@ -91428,9 +91982,9 @@ aaa aaa aaU aiN -akj -anV -asl +aoW +apS +asH abx aaU aaU @@ -91685,9 +92239,9 @@ aaa aaa aaU aiN -akz +arr aDO -asH +atn awm axc awm @@ -92262,7 +92816,7 @@ aaa aaa aaa aaa -aaU +aaa bcy bed boJ @@ -92776,11 +93330,11 @@ aaa aaa aaa aaa -aaa +aaU +bQe +aaU aaU aaU -aaa -aaa bcw bdf bdf @@ -93033,13 +93587,13 @@ aaa aaa aaa aaa -aaa -bim +aaU +aye +aaU aaU aaU -aaa bcw -bhy +cnL bdf bpR bJw @@ -93291,10 +93845,10 @@ aaa aaa aaa aaU -aaa -aaa -aaU -aaU +chC +abp +abp +abp bcy biK bdf @@ -93548,10 +94102,10 @@ aaa aaa aaa aaU -aaa -aaa -aaa -aaU +brs +brs +brs +brs bcw biT bdf @@ -93805,8 +94359,8 @@ aaU aaU aaU aaU -aaa -aaa +cnI +cnJ bgW bgW bgW @@ -95050,7 +95604,7 @@ aNL aNL aVl aYT -baz +aXf bFH aYT aaU @@ -95114,7 +95668,7 @@ bYv bYv cio cct -caz +cct bOO cHq cHs @@ -95268,7 +95822,7 @@ adb anU aaR aqa -amZ +awY adO acN amZ @@ -95279,8 +95833,8 @@ alM axK axX azk -awY -awY +acN +acN azl aJw anU @@ -95371,15 +95925,15 @@ cct bYo ckk bYF -bBP +cct bFu -bIc -bBQ -bBQ -bFG +bKe +bsM +bsM +bsM cuY -bCg -bCg +bIk +bIk cbB cbB cbB @@ -95628,15 +96182,15 @@ bYv bYp bYx cPw -bBQ -bFE -bId -bIL -cpw -bKd -cuZ -bKN -bCg +caz +bsU +bRV +bQQ +ccd +csV +cvt +bZT +bIk aaU aaU aaU @@ -95885,15 +96439,15 @@ bYv bYq cPv bYH -bBQ -bDT -bIe -bIM -bIM -bIM -cvt -bJD -bJH +bYv +bFx +bSd +bTh +bto +bTh +cvQ +crW +ceb aaU aaa aaa @@ -96053,7 +96607,7 @@ aew axi atW aCE -aDW +aCH anU anU anU @@ -96136,21 +96690,21 @@ bpz aaa aaU bXU -bKs -bKv +aJV +brz bYv -cgr +bTg bYy crf -bBQ -bFx -bIf -bIM +bYv +bIe +bSe +bto csZ -bIM -cvQ -bJE -bJH +bto +cEP +cRq +ceb aaU aaa aaa @@ -96310,11 +96864,11 @@ aeJ aeJ aeJ aew -aCH +aDW aew aIn aew -aJV +aFG aew aew ayT @@ -96396,18 +96950,18 @@ bXU bKs bLG bYv -bzA +bYv cwb bYv -bBQ -csV -bIe -bYB +bua +bJE +bSd +bTh cqz -bIM -cvt -cmS -bJH +bTh +cRi +cum +ceb aaU aaa aaa @@ -96594,7 +97148,7 @@ aVL aYT baG bbM -bcz +aZA aYT bdy beM @@ -96655,16 +97209,16 @@ bLU bRM bRO bRR -bRT -bRV -bSd -bTC -bYI -cgf -bKe -czH -bKO -bJH +cyt +bDT +bKd +bTi +caO +ckb +cuZ +cRj +cFV +ceb aaU aaa aaa @@ -96830,7 +97384,7 @@ aJt aJN aQg akv -aeJ +aew ayU aSQ aTg @@ -96914,14 +97468,14 @@ cEs bRS cEN cEO -cEP -bTD -bYJ -cka +bIc +bRX +cRn +cvS cmR -cFV -bKP -bJH +cRp +cRk +ceb aaU aaa aaa @@ -97087,7 +97641,7 @@ aLf aJO aQi alU -aeJ +aew ayW aSQ aAB @@ -97170,15 +97724,15 @@ cfZ bWX bWX ckf -bCf -bFB +btn bIh -bYK -bJC +bRY +bTD +czH bKf -cFW -bKQ -bCg +cRl +cRr +bIk aaU aaa aaa @@ -97344,7 +97898,7 @@ akv aKa aKw alU -aeJ +aew azc aSQ aAB @@ -97427,15 +97981,15 @@ bXU bXU bXU bWa -bCg -bFC -bIi -caj -bJD -bCg -cFX +bIk +bId +bKN +bTD +cmS +ccm +coH bJH -bCg +bIk cOI cOI cOI @@ -97568,21 +98122,21 @@ aaa aaa aaa aaa -aak -aak -aak +aaU +aaa +aaU aaa aaa aaa aaa aaa aaa -akN +bhy alq alq apn aqF -aeJ +aew agD ahr aiH @@ -97645,7 +98199,7 @@ bgA bWf bXm bZQ -ccN +bWq ccN cei ccN @@ -97684,12 +98238,12 @@ aaU aaU aaU aaU -bCg -clv -bIi -caH -bJE -bCg +bIk +bIj +bKO +bTD +cry +ccm cOx cOA cOE @@ -97903,7 +98457,7 @@ aZy aZy aZy aZy -beJ +aXg bfd bjg bUt @@ -97941,12 +98495,12 @@ aaa aaa aaa aaU -bCg -bZT -bIi -cbK -ckb -coH +bIk +cpw +bKP +cRo +crA +cdW cOy cOB cOF @@ -98082,9 +98636,9 @@ aaa aaa aaa aaa -aWj -aWj -aWj +aaU +aaa +aaU aaa aaa aaa @@ -98198,12 +98752,12 @@ aaU aaU aaU aaU -bCg -cum -bIj -ccd -cvS -bCg +bIk +bJD +bKQ +bYB +cgr +bIk cOz cOC cOG @@ -98332,16 +98886,16 @@ aaU aar abM ace -aWj -aWj -aWj -aWj -aWj -aWj -aWj -aWj +aaU +aaU +aaU +aaU +aaU +aaU +aaU +aaU abp -aWj +aaU aaU aaU aaU @@ -98455,12 +99009,12 @@ brU cdZ brU brU -bCg -bFG +bIk +bIk bIk ccB -bJH -bCg +cFW +bIk cGb bRI cOH @@ -98589,16 +99143,16 @@ aaU aar abR ace -aWj +aaU aaa aaa aaa aaa aaa aaa -aWj -aWj -aWj +aaU +aaa +aaU aaa aaa aaa @@ -98716,7 +99270,7 @@ bCh bRL bIs ccC -bRZ +cGN cFn cGc bMj @@ -98846,7 +99400,7 @@ aaU aar abM acf -aWj +aaU aaa aaa aaa @@ -98931,12 +99485,12 @@ bWh csG bQA aZy -aXf +bZV bZJ bZF cpu bax -bZV +cea bZX ccY cab @@ -98973,7 +99527,7 @@ coc bTz bTE ccD -bTE +cGO bTE cGd cvT @@ -99102,8 +99656,8 @@ aaa aaU aaa acM -aWj -aWj +aaa +aaU aaa aaa aaa @@ -99179,8 +99733,8 @@ bnz bpw bQx bll -aZz -cpm +aZC +bcz bad bah baR @@ -99188,8 +99742,8 @@ bWi aWh cmN aZy -aXg -bZK +baE +bRZ bZF csH bay @@ -99203,9 +99757,9 @@ aaa aaa aaa aUk -bnl -bAz -aWr +bmG +bmG +bmG cDN bmG aUk @@ -99216,7 +99770,7 @@ bSE bSN bSU bTa -bTg +bau bTn bSC bRH @@ -99230,7 +99784,7 @@ bRI bTA bVO cfN -ckd +cPx ckd cGe bMj @@ -99359,7 +99913,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -99436,8 +99990,8 @@ bnA bpy bQI bll -aZA aZI +beG bae chP baS @@ -99445,8 +99999,8 @@ bWj baS bbr aZy -bKR -bZF +bJC +bZK bZF cjx bay @@ -99462,7 +100016,7 @@ aaa aUk bwK bAF -aXm +bmG cDN bmG aUk @@ -99473,21 +100027,21 @@ bSE bYV cEC cEL -bTh +bvn bSC bSC bRJ bth bTB cek -cAo +csK cKk cKl cKm cKn cKo -bRX -crW +bYI +cPP bIq cqZ bMj @@ -99616,7 +100170,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -99693,7 +100247,7 @@ bnD bpC bQx bll -aZC +baz aZN bCS bak @@ -99702,11 +100256,11 @@ bWk cdE bbs aZy -cry -crA +bKR +cnN bZF cCJ -baE +cnP bZS bZS bGI @@ -99717,9 +100271,9 @@ aaa aaa aaa aUk -bwM -bAN -aXs +bmG +bmG +bmG cDN bmG aUk @@ -99730,7 +100284,7 @@ bSE bSP cED bTb -bTi +bCX bSC brk bsp @@ -99743,7 +100297,7 @@ cel bCh cEQ bXn -bRY +bYJ bSa bSc bSg @@ -99873,7 +100427,7 @@ aaa aaU aaa aaU -aWj +aaa aaU add adC @@ -99987,7 +100541,7 @@ bSH bSG cij bSG -bSC +bFB bSC bhx bqv @@ -100000,7 +100554,7 @@ cem bRI cER cEU -bCh +bSh bCh bCh bSh @@ -100130,7 +100684,7 @@ aaa aaU aaa aaU -aWj +aaa aaU adf aad @@ -100244,7 +100798,7 @@ coB bbl cEF buD -bCX +bFC bqc brm bst @@ -100257,7 +100811,7 @@ coV bCh cES cEV -cFj +cgf cFj cFo cFr @@ -100387,7 +100941,7 @@ aaa aaU aaa aaU -aWj +aaa aaU adf aad @@ -100501,7 +101055,7 @@ cqe cqg cEG bdv -bDd +bqr bqe brq bst @@ -100514,7 +101068,7 @@ bAo cuW cET cEW -bQk +cka bQk bQk bQu @@ -100644,7 +101198,7 @@ aaa aaU aaa aaU -aWj +aaa aaU adf aad @@ -100758,7 +101312,7 @@ cID bZm cEH bdv -bDd +bqr cyy cyA bst @@ -100771,7 +101325,7 @@ bAq cuX bFJ cEX -cqW +clv bWD cqb bKy @@ -100901,7 +101455,7 @@ aaa aaU aaa aaU -aWj +aaa aaU adf aad @@ -101015,12 +101569,12 @@ cIE cEz cEI bXi -bXq +bga caQ bXC -bXL -cyF -bst +bvK +bHI +bYK buK bst bst @@ -101028,7 +101582,7 @@ bKi bPP bQa cEY -bvn +cqW bJg bQl bYG @@ -101158,7 +101712,7 @@ aaa aaU aaa aaU -aWj +aaa aaU adf aad @@ -101272,12 +101826,12 @@ cIF ccp bqo buF -bDm +bpA bqe ceY -bst -cyG -bst +bwf +bHJ +cbr cDE cDG cEa @@ -101415,7 +101969,7 @@ aaa aaU aaa aaU -aWj +aaa aaU adh adC @@ -101529,12 +102083,12 @@ cIF ccp bqr bbh -bbh +bpB bqm bqm -cdW -cyG +byw bst +cbr cDF cDJ cKC @@ -101672,7 +102226,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -101786,12 +102340,12 @@ cIF ccp cpH bbh -bpA +bqs bXz bqm -cmU -cyG -bst +byD +bHJ +cbs buS cDZ czg @@ -101927,9 +102481,9 @@ aaa aaa aaa aaU -aar aaU -aWj +aaU +aaU aaU aaU aaU @@ -102043,12 +102597,12 @@ cIF ccp cJe bbh -bpB -bPw +brJ +btv bqm -bsG -cyG -bsG +bzJ +bst +cbK buS bAJ czh @@ -102184,9 +102738,9 @@ aaa aaa aaa abp -aar +akN aTd -aWj +aaa abp aaa aaU @@ -102300,18 +102854,18 @@ cIG ccw csM cyo -cyt -bPw -bqm -bqm -cyH -bqm +bBs +blU +bqz +bAD +bIi +bBP buS caR czi cKj buS -bFY +cFs cEX bIU aJE @@ -102321,7 +102875,7 @@ bot bot bjx bAH -bQQ +cRm cpz cvs cwj @@ -102441,9 +102995,9 @@ aaa aaa aaa aaU -aar aaU -aWj +aaU +aaU aaU aaU aaU @@ -102557,18 +103111,18 @@ cIH cgv coE bxM -cyu -cNJ -cyB -cyC -cyI -cyL +bDd +bXt +brH +bAE +bIL +cdX buS buS buS buS buS -bFZ +cnz cEZ bJa aKZ @@ -102700,7 +103254,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -102814,18 +103368,18 @@ cIF cgB bqr bbh -ciQ -bpD -bpD -cmB -bpD -cyM -cyB -cyB -cyB -cyB -czB -czF +bDm +bFE +bIf +bIt +bJd +bXq +cmK +cws +czv +cmU +crg +cvR cFd bEl aMm @@ -102957,7 +103511,7 @@ aaa aaa aaa aaU -aWj +aaa aaU aaa adj @@ -103072,22 +103626,22 @@ cgB bqx bbh bPw -bqq -bqq -bqq -bqq -bqq -bqq -bqq -bqq -bqq -bqq -bHC +bqz +bqz +bzA +bRT +ciQ +col +cxh +czB +cnk +bqz +cKH cFe cFk cFm cFq -cFs +cRw cFz bqt blx @@ -103214,7 +103768,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adj @@ -103329,17 +103883,17 @@ cgB bqr bbh bPw +bqz bqq -brz -bsL -bSe -bJd -bQp -byw bzG -bAC -bCY -bHD +bFZ +ckp +com +cyu +czF +cDM +crn +cxf cFf bEl aOF @@ -103471,7 +104025,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adF @@ -103586,17 +104140,17 @@ cgB bqr bbh bPw -bqq +bqz +brK +bCf +bTC +ckD +cpI +cyF +czM +cGI cHW -bsM -btn -buj -bvK -bts -bts -bAD -bCY -bHD +cxg cFf bJb bJJ @@ -103728,7 +104282,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adF @@ -103843,17 +104397,17 @@ cgB bqr bcT bPw -bqq -ccm -bsM -bto -buj -bwf -byD -bts -bAE -bCY -bHE +bqz +bsL +bzG +bFG +clc +bqz +bqz +bqz +bqz +bqz +cNJ cAm cAt cAv @@ -103985,7 +104539,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adF @@ -104019,12 +104573,12 @@ aJF aJF aJF aJF -bEr -bEK -bEK -bGu -bHi aHa +aHp +aHp +aIJ +aLc +aMo cBj cBw cBF @@ -104097,20 +104651,20 @@ bbh bdF cIL ciF -bqz +aYG bdu -caO -cov -ceb +biU +brF bsN -btp -buj -cup -bts -bts -ckp -bqq -bHG +bCg +bHC +cmB +bqz +cyG +czP +bBQ +cKi +cNV cFf bJc bJL @@ -104242,7 +104796,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adF @@ -104281,15 +104835,15 @@ aim aim aEh aEq -aHp -aIJ -aLc -aQS -aQS -aQS -aQS +aMG aQS +aWr aWu +aWu +aWu +aWu +aWu +bbQ aWA aXd bre @@ -104332,8 +104886,8 @@ bLz bNe ajO bQb -bUj -aTh +cnR +cJt bfh brb bzN @@ -104357,17 +104911,17 @@ ciW bqC bdu bXt -bqs -brF -bsP -cnk csi -cvu -cxf -cxh -ckD -bqq -cPx +bsP +bAC +bHC +bIM +bqz +cyN +czW +cFX +bRI +cyB cFh bJe cRb @@ -104499,7 +105053,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adF @@ -104573,9 +105127,9 @@ bOV aRq cjD bnU -btw +bxm bns -aya +bxn avy alo awn @@ -104590,7 +105144,7 @@ bPp bPU bQi bUU -bWJ +cNC bWP cbV bzR @@ -104614,19 +105168,19 @@ cjV bdu bdu bXu -bqq -brH +bqz bsQ -col -bul -cws -cxg -czM -bBs bCY -bHI +bHE +bqz +bqz +bMj +cAc +cov +bMj +cyC cFf -bJc +btp bJN cHO bKz @@ -104756,7 +105310,7 @@ aaa aaa aaa aaU -aWj +aaa aaU adj adj @@ -104830,7 +105384,7 @@ aSt aSt aSt aSt -cpG +aWd aSt brs avv @@ -104847,7 +105401,7 @@ cRf bPV bQT bVq -cRh +cPG bfh cbY cdn @@ -104871,17 +105425,17 @@ cgB bTv bcT bQE -bqq -bqq -bqq -com -bqq -cws -byD -czP -cxf -czW -cAc +bqz +bqz +bqz +bJf +bqz +caj +cdY +cAo +cdY +cup +cyH cFi bMF bNF @@ -105013,7 +105567,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaU adj @@ -105074,7 +105628,7 @@ axV aog aog aSH -beG +aZz aaU aaU aaU @@ -105086,9 +105640,9 @@ aRv aaU aaU aaU -aWj -aSq -aWj +aSt +cpG +aSt aaU avv ajO @@ -105104,7 +105658,7 @@ ajO ajO aRy bVC -aRy +cRh bfh bfh bBR @@ -105128,19 +105682,19 @@ cgB bYW bcT bQE -bqq +bsV +bsG +bHD +bHD +bMj +caH +chV +cDL cox -cNV -cpI -csK -cKi -cvR -cPP -bts -bCY -bHJ -bIt -bJf +cvu +cyI +cyL +cyM bJO cKp cHS @@ -105270,7 +105824,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -105360,8 +105914,8 @@ bmH aYZ bht bcY -bVD -beC +cyd +cRs cgF bfh bBS @@ -105385,16 +105939,16 @@ cgB bbh bbh bQE -bqq -brJ -bsU -crg -bqq -cyN -bqq -bzJ -czv -bqq +bsV +bts +bHG +bQp +bMj +cbm +byQ +bHK +cGU +bXN bHK bIu bJh @@ -105527,7 +106081,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -105584,7 +106138,7 @@ aOJ aOJ bmF bnT -aRJ +bnT aRJ aRJ chm @@ -105642,11 +106196,11 @@ cgB bbh bpm bQE -bqq -brK -bua -btv -bqq +bsV +buj +bpD +bXL +bsV cyO byN bzK @@ -105784,7 +106338,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -105840,13 +106394,13 @@ bfv bfv bkW bmJ +bnS bof aQJ aQJ aQJ aQJ aQJ -aQJ aRZ aaU aaa @@ -105899,16 +106453,16 @@ cmn bWZ bXj bXv -bqq -bqq -bqq -bqq -bqq +bsV +bul +bpD +bsV +bsV cyP byQ bzS czw -bDb +cRv bBu crX czI @@ -106041,7 +106595,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -106098,7 +106652,7 @@ bjL blD bmK boi -aaU +bsx aaU aaU aaU @@ -106298,7 +106852,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -106356,7 +106910,7 @@ aOJ aPN bes aaU -aye +bQe aye bQe aye @@ -106555,7 +107109,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -106812,7 +107366,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -106925,11 +107479,11 @@ cIA cIP cIY cJf -cJg -cNC -bZo -bZs -bXN +bGu +bHi +bJU +bOn +bOp bJp bJp cyT @@ -107069,7 +107623,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -107326,7 +107880,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaU @@ -107390,7 +107944,7 @@ aye aye aaU aWj -bnS +btw buq bwC bAr @@ -107583,7 +108137,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -107838,9 +108392,9 @@ aaa aaa aaa aaU -aar +aaU aTd -aWj +aaU aaU aaU aaU @@ -108097,7 +108651,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -108170,7 +108724,7 @@ bMS bBv bXM bvB -bWq +bvM acY adz bsz @@ -108354,7 +108908,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -108611,7 +109165,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -108675,7 +109229,7 @@ aaa aaa aaU aWj -bnS +btw buq bwZ bBC @@ -108747,7 +109301,7 @@ bme bme bme bme -bOn +cnG bme bOo aaa @@ -108868,7 +109422,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -109006,7 +109560,7 @@ bOe bOi cnd bOl -bOp +cnH aaa aaa aaa @@ -109125,7 +109679,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -109382,7 +109936,7 @@ aaa aaa aaa aaU -aWj +aaa aae aaa aaa @@ -109520,7 +110074,7 @@ bme bOh cne bOm -bOp +cnH aaa aaa aaa @@ -109639,7 +110193,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -109896,7 +110450,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -109976,7 +110530,7 @@ bsz aej agc agT -cJq +bFg apm aqS arP @@ -110153,7 +110707,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -110214,7 +110768,7 @@ bpH ang coh cfy -clO +bvb aRu aSv aSy @@ -110232,7 +110786,7 @@ cxa bPr sVC aNH -bbQ +bEr cJA aqO anE @@ -110410,7 +110964,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -110489,7 +111043,7 @@ cxb bsz aej agC -aoJ +bEK cJB apm aqT @@ -110667,7 +111221,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -110922,9 +111476,9 @@ aaa aaa aaa aaU -aav +aaU aTd -aWj +aaU aaU aaU aaU @@ -111062,7 +111616,7 @@ bme bOi bOj bOl -bOp +cnH cnE aaa aaa @@ -111181,7 +111735,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -111438,7 +111992,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaU @@ -111576,7 +112130,7 @@ bOe bOh cnc bOm -bOp +cnH aaa aaa aaa @@ -111695,7 +112249,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -111716,7 +112270,7 @@ afm apT adS bEu -ahN +aif afa aha ahx @@ -111831,7 +112385,7 @@ bme bme bme bme -bOn +cnG bme bOo aaa @@ -111952,7 +112506,7 @@ aaa aaa aaa aaU -aWj +aaa aaa aaa aaa @@ -111973,7 +112527,7 @@ aiV anv aec axS -ahN +aif afK ahb ahx @@ -112022,7 +112576,7 @@ bxP arE aMI cgX -chC +bim cik bwW bsT @@ -112209,7 +112763,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -112230,7 +112784,7 @@ aja aoM aec agi -ahN +aif afK ahc ahx @@ -112464,9 +113018,9 @@ aaa aaa aaa aaU -aav aaU -aWj +aaU +aaU aaU aaU aaU @@ -112487,7 +113041,7 @@ bEp bEp bEp bEp -ahN +aif afK ahd ahx @@ -112532,8 +113086,8 @@ arE att cqr arE -byt -bzo +byv +bAN aMI cgZ cif @@ -112721,9 +113275,9 @@ aaa aaa aaa abp -aav +aaa aTd -aWj +aaa abp aaa aaa @@ -112734,17 +113288,17 @@ aaa aaa aaa aaU -aee -aeP -aeP -aqA +aaV +aaV +aaV +abe aeP agX ajS -aHj +akg bvm ahP -ahN +aif afK afK ahT @@ -112789,7 +113343,7 @@ att btP bwo arE -byu +bAd arE aMI cha @@ -112978,20 +113532,20 @@ aaa aaa aaa aaU -aav aaU -aWj -aWj -aWj -aWj -aWj -aWj -aWj -aWj -aWj -aWj -aWj -adx +aaU +aaU +aaU +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaU +aaV aaU aaU aaU @@ -112999,9 +113553,9 @@ aaV ahP ahP ahP -bzp +akj ahP -ahN +aif aiB afK ahU @@ -113040,13 +113594,13 @@ aYF beQ bjw bwu -bAd -aMo -aMG -bVt +bnl bwp -bvb -byv +bwM +bxq +byt +byu +bAz ceQ cgT chc @@ -113237,7 +113791,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -113248,7 +113802,7 @@ aaa aaa aaa aaU -adx +aaV aaU aaa aaa @@ -113258,7 +113812,7 @@ akn aJR bEg ahP -aif +aoJ ass afK afK @@ -113494,7 +114048,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -113505,7 +114059,7 @@ aaa aaa aaa aaU -abe +abc aaU aaa aaa @@ -113751,7 +114305,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -114008,7 +114562,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -114265,7 +114819,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -114522,7 +115076,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -114779,7 +115333,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -114908,11 +115462,11 @@ bHM aaa aaa aaU -cnM +avr aaU aaa aaU -cnM +avr aaU aaa aaa @@ -115036,7 +115590,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -115165,11 +115719,11 @@ bHM aaa aaa bNK -bYQ +bNS bNU aaa bNK -bYQ +bNS bNU aaa aaa @@ -115293,7 +115847,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -115372,10 +115926,10 @@ bra bwW bwW aaU -bdR -cJr -bTJ -aaa +anr +aWj +bUj +bVD aaa cPz aaa @@ -115550,7 +116104,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -115629,8 +116183,8 @@ brr bCr cwv bAQ -bAQ -cJs +bxt +bzp bUV caf bam @@ -115640,7 +116194,7 @@ bYl bam bam bam -bam +cJg bbX bbX bcn @@ -115807,7 +116361,7 @@ aaa aaU aaa aaU -aWj +aaa aaU aaa aaa @@ -115886,8 +116440,8 @@ brP brX bsh bsu -bsx -cJt +bxK +bDb sVC cdp sVC @@ -115897,8 +116451,8 @@ bZp sVC sVC sVC -frb -bvM +cJq +cRt bvW bvX bwd @@ -116064,7 +116618,7 @@ aaa aaU aaa ahv -aWj +aaa aaU aaa aaa @@ -116144,7 +116698,7 @@ bsi bsv bsy bsy -bsD +bTJ bsI bRv bsD @@ -116153,8 +116707,8 @@ bsD cPE cPF cPF -cPF -cPG +cnQ +cJs bBL bBL bCm @@ -116319,7 +116873,7 @@ aaa aaa aaa aaU -aav +cnM abM acj aaU @@ -116450,11 +117004,11 @@ bHN bHN bHN bNL -cnM +avr aaU aaU aaU -cnM +avr aaU aaU aaU @@ -116706,13 +117260,13 @@ bZy bHN bHz ckn -cnL -cnN -bOk -bOk -bOk -cnP -cnR +aqA +bNL +bNL +bNL +bNL +bNL +bOf bOk bOk bOq @@ -116968,7 +117522,7 @@ aaU aaU aaU aaU -cnQ +bOc aaU aaU aaU @@ -117355,17 +117909,17 @@ adl abM aZG aaU -abc -aeP -aeP -aeP -aeP -ajc -aeP -aeP -aeP -aeP -avr +aaV +aaV +aaV +aaV +aaV +aaV +aaV +aaV +aaV +aaV +aaV aaU aTx aoK @@ -117612,17 +118166,17 @@ adw adH aaU aaU -abe +abc aaU aaU aaU aaU -abe +abc aaU aaU aaU aaU -abe +abc aaU aaU aoT @@ -117692,9 +118246,9 @@ bJv aaU cwJ aaU -cbG -aaU -aaU +bWJ +mIT +cJr aaU bbT bbT @@ -117948,10 +118502,10 @@ bPA wPS aaa cwI -aaa +cwA cbI -mIT -cJr +cwA +anr aaa aaU aaU @@ -118205,9 +118759,9 @@ bgM cwA cwA cwL -cww +cwA cbL -cww +cwA bdR mIT mIT @@ -118221,7 +118775,7 @@ bgk bbT bkd bbT -cea +cpm bVG cgn cje @@ -119271,13 +119825,13 @@ cjb cxV cyb cyc -cyd -bFg -bHR -bHR -bHR -bJU -bHR +bVt +bZo +bZs +bZs +bZs +ciA +clO bHR bLb boK @@ -119427,7 +119981,7 @@ aaa aaa aaa arM -atn +atl arM aaU aaU @@ -119673,7 +120227,7 @@ aaa aaa aaa aaU -adx +aaV aaU aaa aaa @@ -119683,9 +120237,9 @@ aaa aaa aaa aaa -aaa -aWj -aaU +arM +akz +arM aaU aaU aaU @@ -119930,7 +120484,7 @@ aaa aaa aaa aaU -abe +abc aaU aaa aaa @@ -119941,9 +120495,9 @@ aaa aaa aaa aaa -aaa -aaa -aaa +aWj +aaU +aaU aaa aaa aaU @@ -124889,11 +125443,11 @@ aWj cww cJm cww -aaU -aaa -aaa -aaa -aaa +aWj +aWj +aWj +aWj +aWj aaU aaU aaa @@ -125144,9 +125698,9 @@ bal aaU aWj cww -cJn +cJm cww -aaU +aWj bal bal bal @@ -125400,10 +125954,10 @@ aaa aaa aaU aWj +bFY +cJn +cww aWj -aWj -aaa -aaa aaa aaa aaa @@ -125656,11 +126210,11 @@ aaa aaa aaa aaU -aaa -aaa -aaa -aaa -aaa +aWj +aWj +aWj +aWj +aWj bal bal bal diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 8a4b5f8130..53ca9a72b0 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -124,6 +124,45 @@ }, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) +"aaq" = ( +/obj/machinery/button/door{ + id = "cargounload"; + layer = 4; + name = "Loading Doors"; + pixel_x = 24; + pixel_y = 8 + }, +/obj/machinery/button/door{ + id = "cargoload"; + layer = 4; + name = "Loading Doors"; + pixel_x = 24; + pixel_y = -8 + }, +/obj/machinery/computer/cargo{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Cargo Bay - Starboard"; + dir = 8; + name = "cargo camera" + }, +/obj/effect/turf_decal/bot, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/quartermaster/storage) +"aar" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/light{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "aas" = ( /obj/docking_port/stationary/random{ id = "pod_lavaland1"; @@ -143,10 +182,224 @@ /obj/effect/landmark/xeno_spawn, /turf/open/space, /area/solar/starboard/fore) +"aav" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/crew_quarters/fitness/recreation) +"aaw" = ( +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/crew_quarters/fitness/recreation) +"aax" = ( +/obj/machinery/light, +/obj/machinery/camera{ + c_tag = "Recreation - Aft"; + dir = 1; + name = "recreation camera" + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"aay" = ( +/turf/closed/wall, +/area/crew_quarters/fitness/pool) +"aaz" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/door/airlock/public/glass{ + name = "Pool" + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) +"aaA" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"aaB" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"aaC" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/portable_atmospherics/canister/air, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"aaD" = ( +/obj/effect/spawner/structure/window/reinforced/tinted, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) "aaE" = ( /obj/structure/lattice/catwalk, /turf/open/space, /area/solar/starboard/fore) +"aaF" = ( +/obj/structure/closet/athletic_mixed, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/poolnoodle/blue, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaG" = ( +/obj/structure/closet/athletic_mixed, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/poolnoodle/red, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/fitness/pool"; + dir = 1; + name = "Pool APC"; + pixel_y = 24 + }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaH" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaI" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/table/glass, +/obj/structure/bedsheetbin/towel, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaJ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/table/glass, +/obj/item/storage/firstaid/regular, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaK" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaL" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaM" = ( +/obj/structure/bed, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aaN" = ( +/turf/open/pool, +/area/crew_quarters/fitness/pool) "aaO" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -154,9 +407,147 @@ "aaP" = ( /turf/closed/wall/mineral/plastitanium, /area/hallway/secondary/entry) +"aaQ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/structure/sign/poster/official/walk{ + pixel_x = -32 + }, +/turf/open/floor/plasteel/yellowsiding/corner, +/area/crew_quarters/fitness/pool) +"aaR" = ( +/obj/machinery/space_heater, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) "aaS" = ( /turf/closed/wall/mineral/plastitanium, /area/construction/mining/aux_base) +"aaT" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"aaU" = ( +/obj/machinery/door/airlock/maintenance_hatch/abandoned{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"aaV" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/yellowsiding, +/area/crew_quarters/fitness/pool) +"aaW" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"aaX" = ( +/obj/machinery/pool/controller, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/yellowsiding, +/area/crew_quarters/fitness/pool) +"aaY" = ( +/obj/structure/pool/Lboard, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"aaZ" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/yellowsiding/corner{ + dir = 8; + icon_state = "yellowcornersiding" + }, +/area/crew_quarters/fitness/pool) +"aba" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/firealarm{ + dir = 4; + pixel_x = -24; + pixel_y = 0 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abb" = ( +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abc" = ( +/obj/machinery/door/airlock/maintenance_hatch/abandoned{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abd" = ( +/obj/structure/pool/ladder{ + dir = 2; + pixel_y = 24 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) "abe" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -166,6 +557,31 @@ "abf" = ( /turf/closed/wall, /area/hallway/secondary/entry) +"abg" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/structure/rack, +/obj/item/weldingtool, +/obj/item/assembly/voice, +/obj/item/clothing/head/welding, +/obj/effect/spawner/lootdrop/maintenance, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abh" = ( +/obj/effect/landmark/blobstart, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) "abi" = ( /turf/closed/wall, /area/construction/mining/aux_base) @@ -173,6 +589,61 @@ /obj/structure/lattice/catwalk, /turf/open/space, /area/space/nearstation) +"abk" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/landmark/event_spawn, +/obj/structure/reagent_dispensers/watertank, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abl" = ( +/obj/machinery/pool/filter{ + pixel_y = 16 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abm" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 8; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abn" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abo" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) "abp" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small{ @@ -196,6 +667,18 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) +"abr" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) "abs" = ( /obj/docking_port/stationary{ dwidth = 1; @@ -207,11 +690,94 @@ /obj/structure/fans/tiny/invisible, /turf/open/space/basic, /area/space) +"abt" = ( +/obj/effect/spawner/structure/window/reinforced/tinted, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"abu" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Pool - Portside"; + dir = 4; + name = "pool camera" + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) "abv" = ( /obj/item/stack/cable_coil, /obj/structure/lattice/catwalk, /turf/open/space, /area/solar/starboard/fore) +"abw" = ( +/obj/machinery/pool/drain, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abx" = ( +/obj/structure/pool/Rboard, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 8; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"aby" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Pool - Starboard"; + dir = 8; + name = "pool camera" + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"abz" = ( +/obj/structure/closet/firecloset, +/turf/open/floor/plating, +/area/hallway/secondary/construction) +"abA" = ( +/obj/structure/dresser, +/turf/open/floor/wood, +/area/maintenance/starboard/aft) +"abB" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) "abC" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -262,6 +828,95 @@ }, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"abI" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/wood, +/area/maintenance/starboard/aft) +"abJ" = ( +/obj/structure/chair/office/dark{ + dir = 4 + }, +/obj/effect/landmark/xeno_spawn, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/wood, +/area/maintenance/starboard/aft) +"abK" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/reagent_dispensers/fueltank, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/maintenance/starboard/aft) +"abL" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abM" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/structure/closet/emcloset, +/obj/item/clothing/mask/breath, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abN" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/obj/machinery/portable_atmospherics/canister/air, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/aft) +"abO" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -23 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) "abP" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/external{ @@ -306,6 +961,71 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"abU" = ( +/obj/structure/pool/ladder{ + dir = 1; + pixel_y = -24 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abV" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_x = -26 + }, +/turf/open/floor/plasteel/yellowsiding/corner{ + dir = 4; + icon_state = "yellowcornersiding" + }, +/area/crew_quarters/fitness/pool) +"abW" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 1; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abX" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/yellowsiding/corner{ + dir = 1; + icon_state = "yellowcornersiding" + }, +/area/crew_quarters/fitness/pool) +"abY" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/closet/secure_closet/personal, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/poolnoodle/yellow, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) "abZ" = ( /obj/machinery/door/firedoor, /obj/effect/turf_decal/stripes/line, @@ -333,7 +1053,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -365,6 +1085,117 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/maintenance/solars/starboard/fore) +"acg" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/closet/secure_closet/personal, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/poolnoodle/red, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"ach" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"aci" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/chair{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"acj" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/table/glass, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"ack" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, +/obj/structure/chair{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"acl" = ( +/obj/structure/table/wood, +/obj/item/clothing/suit/toggle/owlwings, +/obj/item/clothing/under/costume/owl, +/obj/item/clothing/mask/gas/owl_mask, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/wood, +/area/maintenance/starboard/aft) +"acm" = ( +/obj/structure/table/wood, +/obj/item/storage/secure/briefcase, +/obj/item/restraints/handcuffs, +/obj/item/grenade/smokebomb, +/turf/open/floor/wood, +/area/maintenance/starboard/aft) +"acn" = ( +/obj/structure/table/wood, +/obj/item/modular_computer/tablet/preset/cheap, +/turf/open/floor/wood, +/area/maintenance/starboard/aft) "aco" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -379,7 +1210,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "acp" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, @@ -452,6 +1283,43 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard/fore) +"acw" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/closet/secure_closet/personal, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/poolnoodle/blue, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) +"acx" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/light, +/obj/structure/closet/secure_closet/personal, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/toy/poolnoodle/blue, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) "acF" = ( /obj/docking_port/stationary{ dir = 2; @@ -596,19 +1464,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external{ - name = "External Solar Access"; - req_access_txt = "10; 13" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/solars/starboard/fore) "acQ" = ( @@ -1019,7 +1875,7 @@ name = "Construction RC"; pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, @@ -1082,7 +1938,7 @@ dir = 1 }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -1092,7 +1948,7 @@ dir = 1 }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -1109,7 +1965,7 @@ dir = 1 }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -1373,14 +2229,14 @@ /area/hallway/secondary/entry) "agk" = ( /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "agl" = ( /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -1686,7 +2542,7 @@ dir = 4; pixel_x = -24 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 }, @@ -1926,7 +2782,7 @@ /area/maintenance/starboard/fore) "aio" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/poster/contraband/random{ pixel_y = 32 }, @@ -1997,7 +2853,7 @@ /area/maintenance/starboard/fore) "ais" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -2651,7 +3507,7 @@ dir = 4 }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -2711,7 +3567,7 @@ "ajR" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -3124,7 +3980,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "akJ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral, @@ -3148,7 +4004,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "akN" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -3401,7 +4257,7 @@ /turf/open/floor/plasteel/grimy, /area/security/vacantoffice) "alo" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ pixel_y = 24 }, @@ -3482,7 +4338,7 @@ pixel_x = 26; pixel_y = 26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -3906,7 +4762,7 @@ /turf/open/floor/plasteel/grimy, /area/hallway/secondary/entry) "amq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/hallway/secondary/entry) "amr" = ( @@ -4174,7 +5030,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/electronic_marketing_den) "amN" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -4205,7 +5061,7 @@ /turf/open/floor/wood, /area/crew_quarters/electronic_marketing_den) "amQ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/electronic_marketing_den) "amR" = ( @@ -4235,7 +5091,7 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/electronic_marketing_den) "amV" = ( @@ -4531,7 +5387,7 @@ /turf/open/floor/plating, /area/maintenance/starboard/fore) "anB" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -4561,7 +5417,7 @@ /turf/open/floor/plasteel, /area/maintenance/starboard/fore) "anD" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/red{ dir = 1 @@ -5299,7 +6155,7 @@ /turf/open/floor/plasteel/dark, /area/engine/atmospherics_engine) "aoM" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/dark, /area/crew_quarters/electronic_marketing_den) "aoN" = ( @@ -5600,7 +6456,7 @@ /turf/open/floor/plasteel, /area/maintenance/starboard/fore) "apt" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/maintenance/starboard/fore) "apu" = ( @@ -5994,7 +6850,7 @@ /turf/open/floor/plasteel/grimy, /area/security/vacantoffice) "aqf" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/security/vacantoffice) "aqg" = ( @@ -6087,7 +6943,7 @@ /obj/machinery/newscaster{ pixel_y = -32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/grimy, @@ -6484,7 +7340,7 @@ /turf/open/floor/wood, /area/crew_quarters/electronic_marketing_den) "aqT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white, /obj/machinery/power/apc{ areastring = "/area/crew_quarters/electronic_marketing_den"; @@ -6946,7 +7802,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "arM" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -6981,7 +7837,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "arQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -8462,7 +9318,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral{ @@ -8520,7 +9376,7 @@ /area/hallway/secondary/entry) "auq" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral, @@ -9908,7 +10764,7 @@ /turf/open/floor/plating, /area/crew_quarters/toilet/auxiliary) "awM" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Auxiliary Restroom"; name = "restroom camera" @@ -10208,7 +11064,7 @@ "axr" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/bot, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/engine/atmospherics_engine) "axs" = ( @@ -10359,7 +11215,7 @@ /turf/open/floor/plasteel, /area/engine/atmospherics_engine) "axG" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/warning/nosmoking{ pixel_x = 32 }, @@ -12299,7 +13155,7 @@ name = "Maintenance Garden" }) "aBh" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light/small{ dir = 1 }, @@ -12352,7 +13208,7 @@ name = "Maintenance Garden" }) "aBm" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/status_display/evac{ pixel_y = 32 }, @@ -12374,7 +13230,7 @@ name = "Maintenance Garden" }) "aBo" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light/small{ dir = 1 }, @@ -13688,7 +14544,7 @@ /turf/open/floor/plasteel/grimy, /area/hallway/secondary/service) "aDH" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/nanotrasen{ pixel_x = 32 }, @@ -13899,32 +14755,6 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) -"aEg" = ( -/obj/machinery/button/door{ - id = "cargounload"; - layer = 4; - name = "Loading Doors"; - pixel_x = 24; - pixel_y = 8 - }, -/obj/machinery/button/door{ - id = "cargoload"; - layer = 4; - name = "Loading Doors"; - pixel_x = 24; - pixel_y = -8 - }, -/obj/machinery/computer/cargo{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Cargo Bay - Starboard"; - dir = 8; - name = "cargo camera" - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/quartermaster/storage) "aEi" = ( /obj/structure/cable/white{ icon_state = "0-2" @@ -14600,7 +15430,7 @@ /turf/open/floor/plasteel, /area/engine/atmospherics_engine) "aFu" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -14791,7 +15621,7 @@ /turf/open/floor/plasteel, /area/engine/atmospherics_engine) "aFH" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -14807,7 +15637,7 @@ /turf/open/floor/plasteel, /area/engine/atmospherics_engine) "aFJ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, @@ -15724,7 +16554,7 @@ /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "aGX" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 }, @@ -15877,7 +16707,7 @@ /area/engine/atmospherics_engine) "aHj" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -15944,7 +16774,7 @@ /turf/open/floor/plasteel, /area/maintenance/port/fore) "aHq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/newscaster{ pixel_x = -32 }, @@ -16034,7 +16864,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/bar) "aHx" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -16414,19 +17244,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "External Solar Access"; - req_one_access_txt = "13; 24; 10" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/solars/port/fore) "aIk" = ( @@ -18576,7 +19394,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "aLO" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/brown{ dir = 1 }, @@ -18680,7 +19498,7 @@ /turf/open/floor/plasteel, /area/security/checkpoint/supply) "aLV" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/airalarm{ dir = 8; pixel_x = 24 @@ -18859,7 +19677,7 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -19123,7 +19941,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/abandoned_gambling_den/secondary) "aMR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/crew_quarters/abandoned_gambling_den/secondary) "aMS" = ( @@ -19133,7 +19951,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/abandoned_gambling_den/secondary) "aMT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm{ pixel_y = 23 @@ -19156,7 +19974,7 @@ }, /area/crew_quarters/abandoned_gambling_den/secondary) "aMV" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/abandoned_gambling_den/secondary) "aMW" = ( @@ -19546,7 +20364,7 @@ /area/security/prison) "aND" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -19981,7 +20799,7 @@ /turf/open/floor/plasteel/dark, /area/engine/atmos) "aOo" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -20207,7 +21025,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/crew_quarters/bar/atrium) "aOH" = ( @@ -20242,7 +21060,7 @@ /area/crew_quarters/bar/atrium) "aOJ" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -20965,7 +21783,7 @@ /turf/open/floor/plasteel/checker, /area/engine/atmos) "aPO" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 }, @@ -20990,7 +21808,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aPQ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -21487,7 +22305,7 @@ /area/quartermaster/sorting) "aQE" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/airalarm{ dir = 8; pixel_x = 24 @@ -21725,7 +22543,7 @@ /area/security/prison) "aRb" = ( /obj/machinery/light/small, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/red{ dir = 8 @@ -21769,7 +22587,7 @@ /turf/open/floor/plasteel, /area/security/prison) "aRg" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small, /turf/open/floor/plating{ @@ -23644,7 +24462,7 @@ /turf/open/floor/plasteel, /area/quartermaster/office) "aTY" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 4 }, @@ -24265,14 +25083,8 @@ /turf/open/floor/plasteel/dark, /area/security/execution/education) "aUK" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "Security External Airlock"; - req_access_txt = "63" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/structure/sign/warning/vacuum/external{ + pixel_x = 32 }, /turf/open/floor/plating, /area/security/prison) @@ -24472,7 +25284,7 @@ /turf/open/floor/engine/air, /area/engine/atmos) "aVc" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den/secondary) @@ -24571,7 +25383,7 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/camera{ c_tag = "Service Hallway - Aft"; @@ -27017,7 +27829,7 @@ /turf/open/floor/plasteel, /area/quartermaster/office) "aYR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 4; pixel_x = -24; @@ -27064,7 +27876,7 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "aYU" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/effect/turf_decal/tile/brown, /obj/effect/turf_decal/tile/brown{ @@ -27169,7 +27981,7 @@ /turf/open/floor/plasteel, /area/quartermaster/qm) "aZd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /obj/machinery/newscaster{ pixel_y = -32 @@ -27252,7 +28064,7 @@ /turf/open/floor/plating, /area/quartermaster/qm) "aZk" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "2-8" }, @@ -27968,7 +28780,7 @@ /obj/machinery/newscaster{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -28073,7 +28885,7 @@ /turf/open/floor/plasteel, /area/quartermaster/office) "baK" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/brown, /obj/effect/turf_decal/tile/brown{ dir = 8 @@ -28365,7 +29177,7 @@ /turf/open/floor/plasteel, /area/security/prison) "bbn" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/warning/pods{ dir = 8; pixel_y = -32 @@ -29767,7 +30579,7 @@ "bdP" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/disposalpipe/segment, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/brown{ @@ -29894,7 +30706,7 @@ /turf/open/floor/plasteel, /area/quartermaster/miningoffice) "beb" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/brown{ dir = 1 }, @@ -30115,7 +30927,7 @@ /area/engine/atmos) "beB" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -30275,6 +31087,11 @@ /obj/effect/turf_decal/tile/green{ dir = 8 }, +/obj/machinery/power/apc{ + areastring = "/area/hydroponics"; + name = "Hydroponics APC"; + pixel_y = -24 + }, /turf/open/floor/plasteel, /area/hydroponics) "beS" = ( @@ -30323,7 +31140,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/service) "beX" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -31242,7 +32059,7 @@ /turf/open/floor/plating, /area/quartermaster/miningoffice) "bgH" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -31296,7 +32113,7 @@ /area/quartermaster/miningoffice) "bgL" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -32336,7 +33153,7 @@ /turf/open/floor/plasteel, /area/security/brig) "biE" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "1-2" }, @@ -32365,7 +33182,7 @@ /turf/open/floor/plasteel, /area/security/brig) "biG" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -32435,7 +33252,7 @@ /obj/machinery/newscaster/security_unit{ pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -33179,7 +33996,7 @@ /area/hallway/primary/fore) "bjR" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/brown, @@ -33245,7 +34062,7 @@ /area/quartermaster/miningoffice) "bjW" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/brown{ dir = 1 }, @@ -34234,7 +35051,7 @@ /area/hallway/primary/fore) "blJ" = ( /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/brown, @@ -34608,7 +35425,7 @@ /turf/open/floor/plasteel, /area/security/main) "bmr" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -34757,7 +35574,7 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -34795,7 +35612,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -34997,7 +35814,7 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -35886,7 +36703,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -36177,7 +36994,7 @@ /turf/open/floor/plating, /area/security/execution/transfer) "bpd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 9 }, @@ -36958,7 +37775,7 @@ /turf/closed/wall/r_wall, /area/engine/atmos) "bqm" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/yellow{ @@ -39870,7 +40687,7 @@ /turf/open/floor/plasteel/dark, /area/security/main) "buT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/power/apc{ areastring = "/area/crew_quarters/heads/hos"; name = "Head of Security's Office APC"; @@ -40115,7 +40932,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bvk" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light/small, /obj/machinery/light_switch{ pixel_x = 26; @@ -40547,7 +41364,7 @@ /turf/open/floor/plasteel, /area/security/execution/transfer) "bwc" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 1; pixel_y = -24 @@ -40582,7 +41399,7 @@ /turf/open/floor/plasteel, /area/security/brig) "bwe" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -40627,7 +41444,7 @@ /turf/open/floor/plasteel, /area/security/main) "bwj" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ dir = 8 @@ -40688,7 +41505,7 @@ /obj/structure/cable/white{ icon_state = "2-4" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai) @@ -40717,7 +41534,7 @@ /obj/structure/cable/white{ icon_state = "2-8" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/warning/nosmoking{ pixel_y = 32 }, @@ -41299,7 +42116,7 @@ /turf/open/floor/plating, /area/security/execution/transfer) "bxo" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/red{ dir = 1 @@ -41703,7 +42520,7 @@ /area/engine/atmos) "bxT" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, @@ -42135,7 +42952,7 @@ /obj/machinery/gulag_item_reclaimer{ pixel_y = 28 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "4-8" }, @@ -42206,7 +43023,7 @@ /turf/open/floor/plasteel, /area/security/execution/transfer) "byI" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 8; pixel_x = 24 @@ -42451,7 +43268,7 @@ /turf/open/floor/circuit/green, /area/ai_monitored/turret_protected/ai) "bzb" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -42480,21 +43297,16 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai) "bzd" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/cobweb, -/obj/structure/closet/emcloset/anchored, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) +/obj/structure/lattice, +/turf/closed/wall, +/area/construction/mining/aux_base) "bze" = ( -/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bzf" = ( -/obj/machinery/light/small{ - dir = 4 - }, +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/emcloset/anchored, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/gravity_generator) @@ -43465,7 +44277,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai) "bAz" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 }, @@ -43600,122 +44412,83 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "bAI" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/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/gravity_generator) -"bAJ" = ( -/obj/structure/cable/white{ - icon_state = "0-2" - }, -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/sign/warning/electricshock{ - pixel_y = 32 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/gravity_generator) -"bAK" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/status_display/evac{ - pixel_y = 32 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bAL" = ( -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/engine/gravity_generator"; - dir = 1; - name = "Gravity Generator APC"; - pixel_y = 24 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "0-2" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bAM" = ( -/obj/machinery/power/terminal{ - dir = 4 - }, -/obj/item/radio/intercom{ - name = "Station Intercom"; - pixel_y = 26 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, -/obj/structure/cable/white{ - icon_state = "0-2" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bAN" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/machinery/power/smes{ - charge = 5e+006 - }, -/obj/structure/sign/nanotrasen{ - pixel_y = 32 - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = 26 - }, -/obj/structure/cable{ - icon_state = "0-2" - }, +/obj/structure/closet/firecloset, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bAO" = ( -/turf/closed/wall, -/area/engine/gravity_generator) -"bAP" = ( -/obj/machinery/door/firedoor, +/area/construction/mining/aux_base) +"bAJ" = ( +/obj/structure/reagent_dispensers/watertank, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel, +/area/construction/mining/aux_base) +"bAK" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 + dir = 8 }, /obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" + name = "External Solar Access"; + req_access_txt = "10; 13" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/fore) +"bAL" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable{ + icon_state = "0-4" + }, +/turf/open/space, +/area/solar/port/fore) +"bAM" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Solar Access"; + req_one_access_txt = "13; 24; 10" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/fore) +"bAN" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/airlock/external{ + name = "Security External Airlock"; + req_access_txt = "63" }, -/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/turf/open/floor/plating, +/area/security/prison) +"bAO" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bAP" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bAQ" = ( @@ -43994,7 +44767,7 @@ /turf/open/floor/plasteel, /area/storage/tech) "bBl" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/storage/tech) @@ -44126,7 +44899,7 @@ name = "WARNING: BLAST DOORS"; pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue{ @@ -44155,7 +44928,7 @@ /turf/open/floor/plasteel/dark, /area/bridge) "bBz" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -44762,7 +45535,7 @@ }, /turf/open/floor/circuit/green, /area/ai_monitored/turret_protected/ai) -"bCw" = ( +"bCx" = ( /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -44776,37 +45549,9 @@ }, /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) -"bCx" = ( -/obj/effect/turf_decal/bot_white, -/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/gravity_generator) -"bCy" = ( -/obj/effect/turf_decal/bot_white/left, -/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/gravity_generator) "bCz" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -44821,26 +45566,91 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "bCA" = ( -/obj/structure/cable/white, /obj/structure/cable/white{ icon_state = "0-2" }, /obj/effect/spawner/structure/window/reinforced, +/obj/structure/sign/warning/electricshock{ + pixel_y = 32 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plating, /area/engine/gravity_generator) "bCB" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/status_display/evac{ + pixel_y = 32 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /obj/effect/turf_decal/stripes/line{ - dir = 8 + dir = 9 }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bCC" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/engine/gravity_generator"; + dir = 1; + name = "Gravity Generator APC"; + pixel_y = 24 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, /obj/structure/cable{ - icon_state = "1-4" + icon_state = "0-2" }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bCD" = ( +/obj/machinery/power/terminal{ + dir = 4 + }, +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_y = 26 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bCE" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/machinery/power/smes{ + charge = 5e+006 + }, +/obj/structure/sign/nanotrasen{ + pixel_y = 32 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = 26 + }, +/obj/structure/cable{ + icon_state = "0-2" + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bCF" = ( +/obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -44851,80 +45661,26 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bCD" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bCE" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bCF" = ( -/obj/structure/sign/warning/radiation, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/closed/wall/r_wall, -/area/engine/gravity_generator) -"bCG" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/airalarm{ - pixel_y = 23 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/machinery/camera{ - c_tag = "Engineering - Gravity Generator Foyer"; - dir = 4; - name = "engineering camera" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "bCH" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 }, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bCI" = ( -/obj/structure/closet/radiation, -/obj/machinery/light/small{ - dir = 1 - }, -/obj/structure/extinguisher_cabinet{ - pixel_x = 26 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/turf/open/floor/plasteel, +/turf/closed/wall, /area/engine/gravity_generator) "bCJ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -44937,9 +45693,6 @@ icon_state = "0-4" }, /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /turf/open/floor/plating, /area/engine/break_room) "bCL" = ( @@ -44954,13 +45707,13 @@ /obj/structure/cable/white{ icon_state = "2-8" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bCM" = ( @@ -45070,7 +45823,7 @@ /turf/open/floor/plasteel, /area/engine/break_room) "bCU" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 1 }, @@ -45690,7 +46443,7 @@ /turf/open/floor/plasteel/dark, /area/bridge) "bDD" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "4-8" }, @@ -46132,7 +46885,7 @@ /turf/open/floor/plasteel, /area/security/execution/transfer) "bEb" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/extinguisher_cabinet{ pixel_x = 26 }, @@ -46346,11 +47099,8 @@ /turf/open/floor/circuit/green, /area/ai_monitored/turret_protected/ai) "bEn" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/sign/warning/radiation{ - pixel_x = -32 +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -46365,112 +47115,124 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "bEo" = ( -/turf/open/floor/circuit/green, -/area/engine/gravity_generator) -"bEp" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/command/glass{ - name = "Gravity Generator Chamber"; - req_access_txt = "19; 61" +/obj/effect/turf_decal/bot_white, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/cable/white{ - icon_state = "1-4" +/obj/effect/turf_decal/tile/neutral{ + dir = 8 }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "bEq" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bEr" = ( -/obj/machinery/holopad, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot, -/obj/structure/cable/white{ - icon_state = "4-8" +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "1-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/gravity_generator) "bEs" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/structure/cable{ + icon_state = "4-8" + }, /obj/structure/cable/white{ - icon_state = "1-4" + icon_state = "1-2" }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/structure/cable/white{ - icon_state = "1-8" - }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bEt" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bEu" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/highsecurity{ - name = "Gravity Generator Room"; - req_access_txt = "19;23" - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bEv" = ( -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/structure/cable/white{ - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bEw" = ( -/obj/machinery/holopad, -/obj/effect/decal/cleanable/dirt, -/obj/structure/cable/white{ - icon_state = "4-8" +/obj/structure/cable{ + icon_state = "1-8" }, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/gravity_generator) -"bEx" = ( +"bEu" = ( +/obj/structure/sign/warning/radiation, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/closed/wall/r_wall, +/area/engine/gravity_generator) +"bEv" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/airalarm{ + pixel_y = 23 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/obj/machinery/camera{ + c_tag = "Engineering - Gravity Generator Foyer"; + dir = 4; + name = "engineering camera" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bEw" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bEx" = ( +/obj/structure/closet/radiation, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = 26 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/structure/cable/white{ + icon_state = "4-8" }, -/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bEy" = ( @@ -46483,9 +47245,6 @@ req_access_txt = "10" }, /obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, @@ -46495,18 +47254,21 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bEz" = ( /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/stripes/end{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bEA" = ( @@ -46516,27 +47278,26 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bEB" = ( /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bEC" = ( @@ -46546,25 +47307,25 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bED" = ( +/obj/effect/turf_decal/stripes/end{ + dir = 4 + }, /obj/structure/cable/white{ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/stripes/end{ - dir = 4 - }, /turf/open/floor/plasteel, /area/engine/break_room) "bEE" = ( @@ -46776,7 +47537,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/port) "bES" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/status_display/evac{ pixel_x = -32 }, @@ -46805,7 +47566,7 @@ /turf/open/floor/plasteel, /area/storage/tech) "bEV" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/status_display/ai{ pixel_x = 32 }, @@ -47163,7 +47924,7 @@ /turf/open/floor/plasteel/dark, /area/bridge) "bFr" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -47222,7 +47983,7 @@ /turf/open/floor/plasteel/grimy, /area/bridge) "bFx" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -47599,22 +48360,15 @@ /turf/open/floor/plasteel/dark, /area/aisat) "bFW" = ( -/obj/machinery/gravity_generator/main/station, -/obj/effect/turf_decal/bot_white, -/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, +/turf/open/floor/circuit/green, /area/engine/gravity_generator) "bFX" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/sign/warning/radiation{ + pixel_x = -32 + }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -47628,96 +48382,99 @@ /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) "bFY" = ( -/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bFZ" = ( -/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 +/obj/machinery/holopad, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, +/obj/structure/cable/white{ + icon_state = "4-8" }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bGa" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 +/obj/structure/cable/white{ + icon_state = "1-4" }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bGb" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/power/port_gen/pacman, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bGc" = ( -/obj/structure/sign/warning/radiation, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/closed/wall/r_wall, -/area/engine/gravity_generator) -"bGd" = ( /obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/stripes/line{ - dir = 10 - }, -/turf/open/floor/plasteel, -/area/engine/gravity_generator) -"bGe" = ( -/obj/machinery/status_display/evac{ - pixel_x = 32; - pixel_y = -32 - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 + icon_state = "4-8" }, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/gravity_generator) -"bGf" = ( -/obj/structure/closet/radiation, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 +"bGc" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/highsecurity{ + name = "Gravity Generator Room"; + req_access_txt = "19;23" + }, +/obj/structure/cable/white{ + icon_state = "4-8" }, -/obj/machinery/light/small, /obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bGd" = ( +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/delivery, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bGe" = ( +/obj/machinery/holopad, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 }, /turf/open/floor/plasteel, /area/engine/gravity_generator) +"bGf" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/light/small, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "bGg" = ( /obj/machinery/firealarm{ dir = 4; pixel_x = -24 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/break_room) "bGh" = ( @@ -47732,6 +48489,9 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark/corner, /area/engine/break_room) "bGi" = ( @@ -47739,15 +48499,16 @@ /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/open/floor/plasteel/dark/corner, /area/engine/break_room) "bGj" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, /turf/open/floor/plasteel/dark/corner, /area/engine/break_room) "bGk" = ( @@ -47759,7 +48520,7 @@ dir = 1; pixel_y = -22 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/break_room) @@ -47891,7 +48652,7 @@ /turf/open/floor/plasteel, /area/engine/break_room) "bGt" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 8; pixel_x = 24 @@ -48118,7 +48879,7 @@ /turf/open/floor/plasteel, /area/storage/primary) "bGM" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/storage/primary) @@ -48168,7 +48929,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue, @@ -48446,7 +49207,7 @@ pixel_y = -32 }, /obj/machinery/light/small, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue, @@ -48474,7 +49235,7 @@ /area/security/detectives_office) "bHt" = ( /obj/structure/disposalpipe/segment, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/red{ @@ -48497,7 +49258,7 @@ /area/hallway/primary/starboard) "bHv" = ( /obj/structure/disposalpipe/segment, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -48777,9 +49538,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai) "bHN" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -48794,68 +49553,50 @@ /area/engine/gravity_generator) "bHO" = ( /obj/structure/cable/white, +/obj/structure/cable/white{ + icon_state = "0-2" + }, /obj/effect/spawner/structure/window/reinforced, -/obj/structure/sign/warning/electricshock{ - pixel_y = -32 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /turf/open/floor/plating, /area/engine/gravity_generator) "bHP" = ( -/obj/machinery/light, -/obj/machinery/status_display/evac{ - pixel_y = -32 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Engineering - Gravity Generator"; - dir = 1; - name = "engineering camera" - }, +/obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ - dir = 10 + dir = 8 }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bHQ" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/airalarm{ - dir = 1; - pixel_y = -22 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, -/obj/effect/turf_decal/stripes/line, +/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/gravity_generator) "bHR" = ( -/obj/machinery/newscaster{ - pixel_y = -32 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 }, /obj/effect/turf_decal/stripes/line{ - dir = 6 + dir = 4 }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bHS" = ( -/obj/machinery/firealarm{ - dir = 8; - pixel_x = 24 +/obj/effect/decal/cleanable/dirt, +/obj/machinery/power/port_gen/pacman, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, -/obj/machinery/light_switch{ - pixel_y = -26 - }, -/obj/structure/table/reinforced, -/obj/item/stack/sheet/plasteel/twenty, -/obj/item/wrench, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/engine/gravity_generator) @@ -48863,27 +49604,23 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/door/poddoor/preopen{ - id = "transitlock"; - name = "Transit Tube Lockdown Door" +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ - dir = 1 + dir = 10 }, /turf/open/floor/plasteel, /area/engine/gravity_generator) "bHU" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/door/poddoor/preopen{ - id = "transitlock"; - name = "Transit Tube Lockdown Door" +/obj/machinery/status_display/evac{ + pixel_x = 32; + pixel_y = -32 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 }, /turf/open/floor/plasteel, /area/engine/gravity_generator) @@ -48903,7 +49640,7 @@ /turf/closed/wall, /area/engine/break_room) "bHY" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 8 }, @@ -50170,29 +50907,32 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/door/airlock/hatch{ - name = "MiniSat Transit Tube Access"; - req_one_access_txt = "32;19" +/obj/machinery/door/poddoor/preopen{ + id = "transitlock"; + name = "Transit Tube Lockdown Door" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/tile/neutral{ +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ 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/transit_tube) +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "bJP" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/door/poddoor/preopen{ + id = "transitlock"; + name = "Transit Tube Lockdown Door" + }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall/r_wall, -/area/engine/transit_tube) +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "bJQ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -50235,7 +50975,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -50298,7 +51038,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/chief) "bJV" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ pixel_y = 24 }, @@ -50661,7 +51401,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/bridge/meeting_room/council) "bKB" = ( @@ -50828,7 +51568,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/captain) "bKT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/captain) "bKU" = ( @@ -51339,50 +52079,54 @@ /turf/closed/wall/r_wall, /area/engine/transit_tube) "bLG" = ( -/obj/structure/closet/emcloset/anchored, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/command/glass{ + name = "Gravity Generator Chamber"; + req_access_txt = "19; 61" }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/effect/turf_decal/stripes/line{ dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/engine/transit_tube) -"bLH" = ( -/obj/machinery/status_display/evac, -/turf/closed/wall, -/area/engine/transit_tube) -"bLI" = ( -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/engine/transit_tube"; - dir = 1; - name = "Transit Tube Access APC"; - pixel_y = 24 - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, /obj/structure/cable/white{ - icon_state = "0-4" + icon_state = "1-4" + }, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) +"bLH" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/engine/break_room) +"bLI" = ( +/obj/machinery/gravity_generator/main/station, +/obj/effect/turf_decal/bot_white, +/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/transit_tube) +/area/engine/gravity_generator) "bLJ" = ( /obj/structure/cable/white{ icon_state = "1-2" }, +/obj/machinery/door/airlock/hatch{ + name = "MiniSat Transit Tube Access"; + req_one_access_txt = "32;19" + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -51394,38 +52138,14 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/structure/cable/white{ - icon_state = "1-8" - }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bLK" = ( -/obj/item/twohanded/required/kirbyplants/random, -/obj/machinery/firealarm{ - dir = 8; - pixel_x = 24 - }, -/obj/machinery/button/door{ - id = "transitlock"; - name = "Transit Tube Lockdown Control"; - pixel_y = 26; - req_access_txt = "39; 19" - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/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, +/turf/closed/wall/r_wall, /area/engine/transit_tube) "bLL" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 8 }, @@ -51758,7 +52478,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/port) "bMg" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/status_display/ai{ pixel_x = -32 }, @@ -51792,7 +52512,7 @@ /turf/open/floor/plasteel, /area/storage/tech) "bMj" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/status_display/evac{ pixel_x = 32 }, @@ -51976,7 +52696,7 @@ name = "Telecomms Monitoring APC"; pixel_y = 28 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "0-2" }, @@ -52016,7 +52736,7 @@ /obj/machinery/airalarm{ pixel_y = 22 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, @@ -52372,7 +53092,7 @@ /turf/closed/wall, /area/security/brig) "bNk" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/door_timer{ id = "brig1"; name = "Cell 1"; @@ -52748,29 +53468,14 @@ /turf/open/space, /area/space/nearstation) "bNH" = ( -/obj/structure/lattice/catwalk, -/obj/structure/cable/white{ - icon_state = "2-4" +/obj/structure/sign/warning/radiation, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/turf/open/space, -/area/space/nearstation) +/turf/closed/wall/r_wall, +/area/engine/gravity_generator) "bNI" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/machinery/door/airlock/hatch{ - name = "MiniSat Exterior Access"; - req_one_access_txt = "32;19" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, +/obj/structure/closet/emcloset/anchored, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -52784,12 +53489,6 @@ /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bNJ" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -52800,39 +53499,21 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/structure/closet/firecloset, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bNK" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/hatch{ - name = "MiniSat Exterior Access"; - req_one_access_txt = "32;19" - }, -/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/dark, +/obj/machinery/status_display/evac, +/turf/closed/wall, /area/engine/transit_tube) "bNL" = ( -/obj/structure/cable/white{ - icon_state = "4-8" +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/engine/transit_tube"; + dir = 1; + name = "Transit Tube Access APC"; + pixel_y = 24 }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -52843,15 +53524,16 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bNM" = ( /obj/structure/cable/white{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 + icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -52862,11 +53544,22 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bNN" = ( -/obj/machinery/light/small{ - dir = 4 +/obj/item/kirbyplants/random, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/obj/machinery/button/door{ + id = "transitlock"; + name = "Transit Tube Lockdown Control"; + pixel_y = 26; + req_access_txt = "39; 19" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ @@ -53082,7 +53775,7 @@ /turf/open/floor/plasteel, /area/engine/break_room) "bOe" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ dir = 4 @@ -54054,9 +54747,38 @@ /turf/open/space, /area/space/nearstation) "bPL" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/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 + }, /obj/machinery/light/small, -/obj/structure/sign/warning/vacuum{ - pixel_x = -32 +/turf/open/floor/plasteel/dark, +/area/engine/transit_tube) +"bPM" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/hatch{ + name = "MiniSat Exterior Access"; + req_one_access_txt = "32;19" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -54070,20 +54792,11 @@ }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) -"bPM" = ( -/turf/closed/wall, -/area/engine/transit_tube) "bPN" = ( -/obj/item/twohanded/required/kirbyplants/random, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -23 - }, -/obj/machinery/flasher{ - id = "AI"; - pixel_x = -26; - pixel_y = -26 +/obj/structure/cable/white{ + icon_state = "4-8" }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -54097,6 +54810,9 @@ /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bPO" = ( +/obj/structure/cable/white{ + icon_state = "1-8" + }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -54107,15 +54823,16 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bPP" = ( -/obj/item/twohanded/required/kirbyplants/random, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/light_switch{ - pixel_x = 22; - pixel_y = -10 +/obj/machinery/light/small{ + dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -54280,7 +54997,7 @@ /turf/closed/wall, /area/engine/break_room) "bQb" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/engine/break_room) @@ -54391,7 +55108,7 @@ /turf/open/floor/plasteel, /area/storage/tech) "bQm" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 1; pixel_y = -24 @@ -54401,7 +55118,7 @@ /turf/open/floor/plasteel, /area/storage/tech) "bQn" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light_switch{ pixel_y = -26 }, @@ -54566,7 +55283,7 @@ /turf/open/floor/wood, /area/bridge/meeting_room/council) "bQG" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -54816,7 +55533,7 @@ dir = 1; pixel_y = -26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -54927,7 +55644,7 @@ /turf/open/floor/plasteel/dark, /area/security/detectives_office) "bRn" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 }, @@ -55200,7 +55917,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "bRF" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -55345,13 +56062,15 @@ /turf/open/space, /area/space/nearstation) "bRV" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/engine/transit_tube) -"bRW" = ( -/obj/machinery/door/airlock/hatch{ - name = "MiniSat Transit Tube Access"; - req_one_access_txt = "32;19" +/obj/item/kirbyplants/random, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -23 + }, +/obj/machinery/flasher{ + id = "AI"; + pixel_x = -26; + pixel_y = -26 }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -55365,10 +56084,38 @@ }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) +"bRW" = ( +/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/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/engine/transit_tube) "bRX" = ( -/obj/effect/spawner/structure/window/reinforced, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, +/obj/machinery/light_switch{ + pixel_x = 22; + pixel_y = -10 + }, +/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/transit_tube) "bRY" = ( /obj/machinery/keycard_auth{ @@ -55450,7 +56197,7 @@ /turf/open/floor/plating, /area/crew_quarters/heads/chief) "bSd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/newscaster{ pixel_y = 32 }, @@ -55694,7 +56441,7 @@ /area/bridge/meeting_room/council) "bSz" = ( /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/bridge/meeting_room/council) "bSA" = ( @@ -55753,12 +56500,12 @@ /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bSG" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bSH" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bSI" = ( @@ -56361,7 +57108,7 @@ /turf/closed/wall/r_wall, /area/ai_monitored/turret_protected/aisat_interior) "bTB" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/turretid{ control_area = "/area/ai_monitored/turret_protected/aisat_interior"; name = "Antechamber Turret Control"; @@ -56529,22 +57276,9 @@ /turf/open/space, /area/space/nearstation) "bTL" = ( -/obj/structure/window/reinforced{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 }, -/obj/structure/table/reinforced, -/obj/machinery/light/small{ - dir = 1 - }, -/obj/machinery/camera{ - c_tag = "AI Satellite - Transit Tube"; - name = "ai camera"; - network = list("minisat"); - start_active = 1 - }, -/obj/item/clipboard, -/obj/item/folder/blue, -/obj/item/pen, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -56556,30 +57290,16 @@ dir = 8 }, /turf/open/floor/plasteel/dark, -/area/engine/transit_tube) +/area/engine/gravity_generator) "bTM" = ( -/obj/structure/chair/office/dark{ - dir = 8 - }, -/obj/machinery/flasher{ - id = "AI"; - pixel_x = -26; - pixel_y = 26 - }, -/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, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, /area/engine/transit_tube) "bTN" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/door/airlock/hatch{ + name = "MiniSat Transit Tube Access"; + req_one_access_txt = "32;19" + }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -56590,22 +57310,13 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bTO" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/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, +/turf/open/floor/plating, /area/engine/transit_tube) "bTP" = ( /obj/machinery/computer/station_alert{ @@ -56857,7 +57568,7 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -57595,7 +58306,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bVk" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/door_timer{ id = "brig2"; name = "Cell 2"; @@ -58298,9 +59009,6 @@ /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bWc" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -58311,10 +59019,15 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, +/obj/structure/chair/office/light{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bWd" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -58325,10 +59038,16 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bWe" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light/small{ dir = 4 }, @@ -58429,7 +59148,7 @@ /turf/open/floor/plating, /area/crew_quarters/heads/chief) "bWm" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 1; pixel_x = -24; @@ -58884,7 +59603,7 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hop) "bWS" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/disposalpipe/segment{ dir = 6 }, @@ -58900,7 +59619,7 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hop) "bWU" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/wood, /area/crew_quarters/heads/hop) @@ -59758,7 +60477,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "bXY" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 8; pixel_x = 24 @@ -59860,7 +60579,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "bYh" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -60000,6 +60719,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/engine/transit_tube) "bYp" = ( @@ -60129,7 +60851,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/chief) "bYw" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light_switch{ pixel_x = 26; pixel_y = -26 @@ -61146,7 +61868,7 @@ /area/ai_monitored/turret_protected/aisat_interior) "cae" = ( /obj/structure/cable/white, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -61211,7 +61933,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "cai" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /obj/machinery/airalarm{ dir = 1; @@ -61248,7 +61970,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "cak" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light_switch{ pixel_x = -26 }, @@ -61331,7 +62053,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "cao" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/extinguisher_cabinet{ pixel_x = 26 }, @@ -61441,7 +62163,7 @@ /turf/open/floor/plating, /area/security/checkpoint/engineering) "caB" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/yellow{ @@ -61843,7 +62565,7 @@ /obj/structure/disposalpipe/segment{ dir = 5 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -62198,7 +62920,7 @@ /turf/closed/wall, /area/engine/engineering) "cbW" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 9 }, @@ -62239,7 +62961,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cca" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/machinery/light_switch{ pixel_y = 26 @@ -62738,7 +63460,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/captain/private) "ccS" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, @@ -62804,7 +63526,7 @@ /turf/open/floor/plasteel/dark, /area/security/courtroom) "ccX" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -62844,7 +63566,7 @@ /turf/open/floor/plating, /area/security/courtroom) "cda" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -63125,7 +63847,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload) "cdw" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 1 }, @@ -63652,8 +64374,8 @@ /area/library) "cel" = ( /obj/structure/chair/sofa/right{ - icon_state = "sofaend_right"; - dir = 8 + dir = 8; + icon_state = "sofaend_right" }, /obj/structure/sign/painting/library{ pixel_x = 32 @@ -63685,7 +64407,7 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -64817,7 +65539,7 @@ /obj/machinery/light{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/plaques/kiddie/library{ pixel_x = -32 }, @@ -64841,7 +65563,6 @@ pixel_x = -26 }, /obj/structure/sign/painting/library{ - pixel_x = 0; pixel_y = -32 }, /turf/open/floor/wood, @@ -64990,7 +65711,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/captain/private) "cgt" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/airalarm{ dir = 1; pixel_y = -22 @@ -65010,7 +65731,7 @@ /turf/open/floor/wood, /area/crew_quarters/heads/captain/private) "cgv" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 1; pixel_y = -26 @@ -66000,7 +66721,7 @@ /turf/open/floor/plasteel/grimy, /area/library) "chP" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/library) "chV" = ( @@ -67333,7 +68054,7 @@ /turf/open/floor/wood, /area/lawoffice) "ckg" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/sign/poster/official/report_crimes{ pixel_y = -32 @@ -68630,7 +69351,7 @@ /obj/machinery/status_display/ai{ pixel_x = 32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/crew_quarters/heads/hop) @@ -69228,7 +69949,7 @@ /area/aisat) "cnu" = ( /obj/structure/cable/white, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/power/apc{ @@ -69270,7 +69991,7 @@ icon_state = "1-2" }, /obj/structure/table/reinforced, -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 10 }, /obj/effect/turf_decal/tile/neutral{ @@ -69303,7 +70024,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload) "cny" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /obj/machinery/airalarm{ dir = 1; @@ -69790,7 +70511,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "cot" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/radio/intercom{ name = "Station Intercom"; pixel_x = -26 @@ -70406,7 +71127,7 @@ /turf/closed/wall, /area/crew_quarters/heads/hop) "cpD" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/hop) "cpE" = ( @@ -70424,7 +71145,7 @@ dir = 1; pixel_y = -26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/hop) "cpG" = ( @@ -70439,7 +71160,7 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hop) "cpH" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/wood, /area/crew_quarters/heads/hop) @@ -70602,7 +71323,7 @@ /turf/open/floor/plasteel/dark, /area/security/courtroom) "cpW" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -70617,7 +71338,7 @@ /turf/open/floor/plasteel/dark, /area/security/courtroom) "cpX" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -71418,7 +72139,7 @@ pixel_y = 32 }, /turf/open/space, -/area/space/nearstation) +/area/space) "crE" = ( /obj/structure/window/reinforced, /obj/structure/window/reinforced{ @@ -71556,7 +72277,7 @@ /turf/open/floor/plating, /area/engine/engineering) "crQ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Engineering - Central"; dir = 4; @@ -72638,7 +73359,7 @@ /turf/open/floor/plasteel, /area/maintenance/port) "ctH" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -72662,7 +73383,7 @@ /area/library) "ctK" = ( /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Library - Aft"; dir = 1; @@ -72672,7 +73393,7 @@ /area/library) "ctL" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/machinery/computer/security/telescreen/entertainment{ pixel_y = -32 }, @@ -72683,7 +73404,7 @@ /area/library) "ctM" = ( /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light_switch{ pixel_y = -26 }, @@ -72691,7 +73412,7 @@ /turf/open/floor/plasteel/grimy, /area/library) "ctN" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/library) "ctO" = ( @@ -72938,7 +73659,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/blue{ @@ -73351,7 +74072,7 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -73369,7 +74090,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -74250,7 +74971,7 @@ /turf/open/floor/plating, /area/maintenance/port) "cwq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/dark, /area/library) "cwr" = ( @@ -74329,7 +75050,7 @@ /turf/open/floor/plasteel/dark, /area/library) "cwy" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -74382,7 +75103,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 9 }, @@ -74399,7 +75120,7 @@ /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) "cwE" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 1 }, @@ -74431,7 +75152,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 5 }, @@ -74528,7 +75249,7 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/blue, @@ -74586,7 +75307,7 @@ /turf/open/floor/plasteel, /area/gateway) "cwV" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -74729,7 +75450,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "cxh" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -75079,7 +75800,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cxI" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/electricshock{ pixel_y = 32 @@ -75577,9 +76298,6 @@ /turf/open/floor/plating, /area/gateway) "cyE" = ( -/obj/machinery/gateway{ - dir = 9 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/tile/neutral{ @@ -75595,9 +76313,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "cyF" = ( -/obj/machinery/gateway{ - dir = 1 - }, /obj/machinery/status_display/evac{ pixel_y = 32 }, @@ -75616,9 +76331,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "cyG" = ( -/obj/machinery/gateway{ - dir = 5 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ @@ -75952,7 +76664,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -76176,8 +76888,8 @@ pixel_x = 26 }, /obj/effect/turf_decal/bot, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel, /area/engine/storage) "czz" = ( @@ -76575,26 +77287,10 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/gateway) -"cAi" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/bot_white, -/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/gateway) "cAj" = ( -/obj/machinery/gateway/centerstation, +/obj/machinery/gateway/centerstation{ + dir = 0 + }, /obj/structure/cable/white{ icon_state = "0-2" }, @@ -76602,9 +77298,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "cAk" = ( -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral{ @@ -77125,13 +77818,13 @@ /area/maintenance/port) "cAZ" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/cobweb/cobweb2, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/port) "cBa" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/extinguisher_cabinet{ pixel_x = -26 }, @@ -77178,7 +77871,7 @@ /turf/open/floor/plasteel/dark, /area/library) "cBh" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/newscaster{ pixel_x = 32 }, @@ -77428,9 +78121,6 @@ /turf/closed/wall, /area/gateway) "cBD" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/machinery/light{ dir = 8 }, @@ -77449,7 +78139,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "cBE" = ( -/obj/machinery/gateway, /obj/structure/cable/white{ icon_state = "0-2" }, @@ -77471,9 +78160,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "cBF" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/decal/cleanable/dirt, /obj/machinery/camera{ c_tag = "Bridge - Gateway Chamber"; @@ -77555,7 +78241,7 @@ dir = 4; pixel_x = -24 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -77632,7 +78318,7 @@ /turf/open/floor/plating, /area/crew_quarters/toilet/restrooms) "cBR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, @@ -78596,6 +79282,9 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, +/obj/machinery/computer/gateway_control{ + dir = 8 + }, /turf/open/floor/plasteel, /area/gateway) "cDj" = ( @@ -79245,7 +79934,7 @@ /turf/open/floor/plasteel/dark, /area/library) "cEr" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/radio/intercom{ name = "Station Intercom"; pixel_y = -26 @@ -79939,7 +80628,7 @@ /turf/open/floor/wood, /area/crew_quarters/dorms) "cFy" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/dorms) "cFz" = ( @@ -80183,7 +80872,7 @@ /area/engine/engineering) "cFT" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "1-8" }, @@ -80339,7 +81028,7 @@ name = "Station Intercom"; pixel_y = -26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, @@ -80360,7 +81049,7 @@ /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) "cGl" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/ai_monitored/storage/eva) @@ -80420,7 +81109,7 @@ dir = 1; pixel_y = -26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /turf/open/floor/plasteel/grimy, /area/bridge/showroom/corporate) @@ -80460,7 +81149,7 @@ pixel_x = 7; pixel_y = -26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /turf/open/floor/plasteel/grimy, /area/bridge/showroom/corporate) @@ -80523,7 +81212,7 @@ dir = 1; pixel_y = -22 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 @@ -80777,7 +81466,7 @@ /turf/open/floor/carpet, /area/crew_quarters/dorms) "cGY" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/carpet, /area/crew_quarters/dorms) @@ -80863,7 +81552,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cHi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 10 }, @@ -80927,7 +81616,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cHp" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 @@ -80938,7 +81627,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "cHq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/electricshock{ pixel_y = -32 @@ -81017,7 +81706,7 @@ /area/maintenance/port) "cHy" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/maintenance/port) "cHz" = ( @@ -82221,22 +82910,16 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "cJI" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ +/obj/structure/cable/white, +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/sign/warning/electricshock{ + pixel_y = -32 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/turf/open/floor/plating, +/area/engine/gravity_generator) "cJJ" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 @@ -83198,7 +83881,7 @@ /turf/open/floor/plating, /area/crew_quarters/dorms) "cKY" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -83331,7 +84014,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/dorms) "cLi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -83972,7 +84655,7 @@ }, /area/crew_quarters/dorms) "cMs" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, @@ -85062,7 +85745,7 @@ /turf/open/floor/plasteel, /area/maintenance/department/electrical) "cOw" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/maintenance/department/electrical) @@ -85079,7 +85762,7 @@ /obj/machinery/light_switch{ pixel_y = 26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/bot, @@ -85341,7 +86024,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "cPb" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 1 }, @@ -85480,7 +86163,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cPr" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 1 }, @@ -85595,7 +86278,7 @@ name = "medbay camera"; network = list("ss13","medbay") }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -85827,7 +86510,7 @@ /turf/open/floor/carpet, /area/crew_quarters/dorms) "cPT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/radio/intercom{ name = "Station Intercom"; pixel_x = 26; @@ -85965,7 +86648,7 @@ /turf/open/floor/plasteel/dark/corner, /area/maintenance/department/electrical) "cQi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/maintenance/department/electrical) @@ -86189,7 +86872,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "cQC" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/purple{ dir = 4 @@ -86405,7 +87088,7 @@ /turf/open/floor/plasteel, /area/science/research) "cQR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/purple{ @@ -86414,7 +87097,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "cQS" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/blue{ @@ -86491,7 +87174,7 @@ /turf/open/floor/plasteel, /area/medical/medbay/central) "cQY" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue{ @@ -86500,7 +87183,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cQZ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/button/door{ desc = "A remote control switch for the medbay foyer."; id = "MedbayFoyer"; @@ -86708,7 +87391,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/dorms) "cRv" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/nanotrasen{ pixel_x = 32; pixel_y = -32 @@ -87252,7 +87935,7 @@ /turf/open/floor/plasteel, /area/security/checkpoint/science/research) "cSp" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/purple{ @@ -87618,7 +88301,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cSR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/storage/pod{ pixel_x = 32; pixel_y = 32 @@ -87879,7 +88562,7 @@ /obj/machinery/status_display/evac{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/maintenance/department/electrical) @@ -88051,7 +88734,7 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "cTF" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 }, @@ -89392,7 +90075,7 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "cVM" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 1 }, @@ -89583,7 +90266,7 @@ /turf/open/floor/plating, /area/security/checkpoint/science/research) "cWb" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/purple{ @@ -89636,7 +90319,7 @@ /turf/open/floor/plasteel, /area/science/research) "cWf" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/purple, @@ -89661,7 +90344,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue{ @@ -89702,7 +90385,7 @@ /turf/open/floor/plasteel, /area/medical/medbay/central) "cWl" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/blue, @@ -90023,7 +90706,7 @@ /turf/open/floor/plasteel, /area/maintenance/department/electrical) "cWK" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -90425,7 +91108,7 @@ /obj/machinery/light{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Security Post - Science"; dir = 8; @@ -90472,7 +91155,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "cXu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/purple{ @@ -90518,7 +91201,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "cXy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/purple, @@ -90591,7 +91274,7 @@ /area/medical/medbay/central) "cXJ" = ( /obj/structure/disposalpipe/segment, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/blue{ @@ -90634,7 +91317,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "cXN" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue, @@ -91132,7 +91815,7 @@ /obj/machinery/light_switch{ pixel_y = -26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/maintenance/department/electrical) @@ -91261,7 +91944,7 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "cYT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -91681,7 +92364,7 @@ /turf/open/floor/plasteel, /area/security/checkpoint/medical) "cZE" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/airalarm{ dir = 8; pixel_x = 24 @@ -92030,6 +92713,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "dad" = ( @@ -92229,7 +92915,7 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "dau" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, @@ -92497,7 +93183,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/status_display/evac{ pixel_y = 32 }, @@ -94085,29 +94771,8 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) -"ddw" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel{ - heat_capacity = 1e+006 - }, -/area/crew_quarters/fitness/recreation) -"ddx" = ( -/obj/machinery/light, -/obj/machinery/camera{ - c_tag = "Recreation - Aft"; - dir = 1; - name = "recreation camera" - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness/recreation) "ddy" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) @@ -94325,7 +94990,7 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "ddT" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/science/xenobiology) @@ -94614,7 +95279,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "dev" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light/small, /obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, @@ -94731,7 +95396,7 @@ /area/medical/medbay/central) "deG" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/structure/sign/poster/official/help_others{ pixel_x = -32 }, @@ -94792,7 +95457,7 @@ /obj/structure/sign/departments/examroom{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -94854,7 +95519,7 @@ /turf/open/floor/plasteel, /area/medical/abandoned) "deS" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/medical/abandoned) @@ -95054,7 +95719,7 @@ /turf/open/floor/plasteel, /area/science/research) "dfl" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/storage/pod{ pixel_x = 32 }, @@ -95515,7 +96180,7 @@ /turf/closed/wall, /area/crew_quarters/abandoned_gambling_den) "dfZ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/cobweb, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -95527,7 +96192,7 @@ /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) "dgb" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, /area/crew_quarters/abandoned_gambling_den) @@ -95570,7 +96235,7 @@ /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) "dgf" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) "dgg" = ( @@ -95746,7 +96411,7 @@ /turf/open/floor/plasteel/dark, /area/science/xenobiology) "dgu" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -96009,7 +96674,7 @@ /turf/open/floor/plasteel, /area/science/lab) "dgP" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white, /area/science/lab) @@ -96617,7 +97282,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/abandoned_gambling_den) "dhP" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/structure/sign/poster/contraband/random{ pixel_x = 32 @@ -97420,28 +98085,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/starboard/aft) -"diX" = ( -/obj/effect/decal/cleanable/cobweb, -/obj/structure/dresser, -/turf/open/floor/wood, -/area/maintenance/starboard/aft) -"diY" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/structure/table/wood, -/obj/item/clothing/suit/toggle/owlwings, -/obj/item/clothing/under/costume/owl, -/obj/item/clothing/mask/gas/owl_mask, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) -"diZ" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/table/wood, -/obj/item/storage/secure/briefcase, -/obj/item/restraints/handcuffs, -/obj/item/grenade/smokebomb, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dja" = ( /obj/machinery/vending/assist, /obj/machinery/newscaster{ @@ -97570,7 +98213,7 @@ /turf/open/floor/plasteel/white/corner, /area/science/circuit) "djo" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/science/research/abandoned) @@ -97590,7 +98233,7 @@ /turf/open/floor/plasteel/white/side, /area/science/circuit) "djs" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, @@ -97895,7 +98538,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "djW" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, @@ -98014,7 +98657,7 @@ /turf/open/floor/plasteel, /area/science/lab) "dke" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/purple{ @@ -98030,7 +98673,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "dkf" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/yellow{ @@ -98377,7 +99020,7 @@ /area/medical/abandoned) "dkJ" = ( /obj/machinery/light/small, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/medical/abandoned) @@ -98454,20 +99097,6 @@ }, /turf/open/floor/plasteel/dark, /area/medical/abandoned) -"dkO" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/space_heater, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) -"dkP" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 - }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) "dkQ" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/door/airlock/maintenance_hatch/abandoned{ @@ -98485,30 +99114,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/starboard/aft) -"dkR" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/xeno_spawn, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 - }, -/turf/open/floor/wood{ - icon_state = "wood-broken2" - }, -/area/maintenance/starboard/aft) -"dkS" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/chair/office/dark{ - dir = 4 - }, -/turf/open/floor/wood, -/area/maintenance/starboard/aft) -"dkT" = ( -/obj/effect/decal/cleanable/dirt, -/obj/structure/table/wood, -/obj/item/modular_computer/tablet/preset/cheap, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dkU" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, @@ -99026,7 +99631,7 @@ /turf/closed/wall, /area/hallway/secondary/construction) "dmi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) @@ -99171,7 +99776,7 @@ /turf/open/floor/plasteel, /area/science/misc_lab) "dmB" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /obj/machinery/light_switch{ pixel_x = -26 @@ -99559,7 +100164,7 @@ /turf/open/floor/plasteel/white, /area/medical/genetics/cloning) "dno" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -99638,7 +100243,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "dnv" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/blue{ dir = 1 }, @@ -99715,7 +100320,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "dnC" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -99911,41 +100516,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/starboard/aft) -"dnV" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 - }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) -"dnW" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) -"dnX" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/xeno_spawn, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) -"dnY" = ( -/obj/machinery/portable_atmospherics/canister/air, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) "dnZ" = ( /obj/machinery/light/small{ dir = 8 @@ -100876,29 +101446,6 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/construction) -"dpJ" = ( -/obj/effect/landmark/blobstart, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) -"dpK" = ( -/obj/structure/closet/emcloset, -/obj/item/clothing/mask/breath, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) -"dpL" = ( -/obj/structure/reagent_dispensers/watertank, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) -"dpM" = ( -/obj/machinery/portable_atmospherics/canister/air, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dpN" = ( /obj/structure/table/wood/poker, /obj/item/clothing/glasses/sunglasses/big, @@ -101133,6 +101680,13 @@ /obj/effect/turf_decal/tile/purple{ dir = 4 }, +/obj/structure/cable/white, +/obj/machinery/power/apc{ + areastring = "/area/science/misc_lab"; + dir = 4; + name = "Science Lounge APC"; + pixel_x = 26 + }, /turf/open/floor/plasteel/white, /area/science/misc_lab) "dqi" = ( @@ -101232,7 +101786,7 @@ /turf/open/floor/plasteel, /area/science/explab) "dqr" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, @@ -101766,11 +102320,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/hallway/secondary/construction) -"drr" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "drs" = ( /obj/structure/chair/stool/bar, /obj/machinery/light/small{ @@ -101881,7 +102430,7 @@ pixel_x = 1; pixel_y = -24 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/white/side{ dir = 1 }, @@ -102033,7 +102582,7 @@ /obj/structure/cable/white, /obj/structure/disposalpipe/segment, /obj/effect/turf_decal/bot, -/obj/item/twohanded/required/kirbyplants/dead, +/obj/item/kirbyplants/dead, /turf/open/floor/plasteel, /area/crew_quarters/heads/hor) "drY" = ( @@ -102294,7 +102843,7 @@ /turf/open/floor/plasteel/white, /area/medical/genetics/cloning) "dsy" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/blue, /turf/open/floor/plasteel/white, @@ -103256,7 +103805,7 @@ /turf/open/floor/plating, /area/science/research/abandoned) "dun" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/science/research/abandoned) @@ -103662,7 +104211,7 @@ /turf/closed/wall, /area/medical/genetics) "dvd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -103755,7 +104304,7 @@ /turf/open/floor/plasteel, /area/medical/genetics) "dvm" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/firealarm{ pixel_x = -26; pixel_y = 26 @@ -104182,36 +104731,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/starboard/aft) -"dvQ" = ( -/obj/structure/rack, -/obj/effect/decal/cleanable/dirt, -/obj/item/weldingtool, -/obj/item/assembly/voice, -/obj/item/clothing/head/welding, -/obj/effect/spawner/lootdrop/maintenance, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) -"dvR" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/oil, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) -"dvS" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/structure/reagent_dispensers/fueltank, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dvT" = ( /obj/structure/table/wood, /obj/machinery/newscaster{ @@ -104261,7 +104780,7 @@ /turf/open/floor/wood, /area/crew_quarters/abandoned_gambling_den) "dvY" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/dark, /area/crew_quarters/abandoned_gambling_den) "dvZ" = ( @@ -105172,22 +105691,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) -"dxz" = ( -/obj/effect/landmark/xeno_spawn, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) -"dxA" = ( -/obj/structure/closet/firecloset, -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/maintenance/starboard/aft) "dxB" = ( /obj/structure/chair/wood/normal{ dir = 1 @@ -105746,7 +106249,7 @@ /turf/open/floor/plating, /area/crew_quarters/heads/cmo) "dyy" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -105792,7 +106295,7 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) "dyC" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -106023,13 +106526,6 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/hallway/secondary/construction) -"dyT" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dyU" = ( /turf/closed/wall/r_wall, /area/maintenance/solars/starboard/aft) @@ -106538,7 +107034,7 @@ /turf/open/floor/plasteel, /area/medical/genetics) "dzR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white, /area/medical/genetics) @@ -106700,7 +107196,7 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) "dAf" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable/white{ icon_state = "0-8" }, @@ -107193,7 +107689,7 @@ /turf/open/floor/plasteel, /area/medical/genetics) "dAZ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/airalarm{ dir = 1; pixel_y = -22 @@ -107255,7 +107751,7 @@ /obj/structure/sign/poster/official/do_not_question{ pixel_y = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/purple{ dir = 8 }, @@ -107639,16 +108135,6 @@ heat_capacity = 1e+006 }, /area/maintenance/starboard/aft) -"dBE" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dBF" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -107747,19 +108233,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external{ - name = "External Solar Access"; - req_access_txt = "10; 13" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/solars/starboard/aft) "dBN" = ( @@ -108410,12 +108884,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/starboard/aft) -"dDa" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) "dDb" = ( /obj/structure/sign/warning/electricshock, /turf/closed/wall/r_wall, @@ -109118,7 +109586,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "dEe" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/radio/intercom{ name = "Station Intercom"; pixel_y = -26 @@ -109509,7 +109977,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/science/robotics/lab) "dEO" = ( @@ -109796,7 +110264,7 @@ /turf/open/floor/wood, /area/crew_quarters/theatre/abandoned) "dFq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood{ icon_state = "wood-broken5" }, @@ -110762,7 +111230,7 @@ /obj/machinery/newscaster{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/security/detectives_office/private_investigators_office) "dGM" = ( @@ -112291,7 +112759,7 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) "dJm" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/green{ dir = 8 @@ -112470,7 +112938,7 @@ /obj/machinery/light/small{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/poster/official/do_not_question{ pixel_x = 32 }, @@ -112756,6 +113224,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/light/small, /turf/open/floor/plasteel/dark/telecomms, /area/science/server) "dKg" = ( @@ -112766,7 +113235,7 @@ /turf/open/floor/circuit/green/telecomms/mainframe, /area/science/server) "dKh" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/purple{ dir = 8 @@ -113170,7 +113639,7 @@ dir = 4 }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -113418,7 +113887,7 @@ /turf/open/floor/plasteel, /area/maintenance/aft) "dLj" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, @@ -113444,7 +113913,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "dLl" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/effect/turf_decal/tile/green{ dir = 4 @@ -113556,7 +114025,7 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/crew_quarters/theatre/abandoned) "dLv" = ( @@ -113879,7 +114348,7 @@ /turf/open/floor/plasteel, /area/science/research) "dMg" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -114460,7 +114929,7 @@ /area/crew_quarters/theatre/abandoned) "dNb" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/theatre/abandoned) "dNc" = ( @@ -114468,7 +114937,7 @@ dir = 1; pixel_y = -22 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood{ icon_state = "wood-broken3" }, @@ -114969,6 +115438,10 @@ /turf/open/floor/plasteel, /area/maintenance/port/aft) "dOc" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"dOd" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, @@ -114985,11 +115458,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/port/aft) -"dOd" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/port/aft) "dOe" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ @@ -114998,6 +115466,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel{ heat_capacity = 1e+006 }, @@ -115250,7 +115719,7 @@ /turf/open/floor/plasteel, /area/maintenance/port/aft) "dOz" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/airalarm{ dir = 4; pixel_x = -23 @@ -115330,7 +115799,7 @@ name = "hallway camera" }, /obj/effect/turf_decal/bot, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -115381,7 +115850,7 @@ /area/hallway/primary/aft) "dOI" = ( /obj/machinery/light/small, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/green{ dir = 8 @@ -115778,7 +116247,7 @@ /area/library/abandoned) "dPw" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -115804,7 +116273,7 @@ /area/library/abandoned) "dPz" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/dark, /area/library/abandoned) "dPA" = ( @@ -115839,7 +116308,7 @@ /area/library/abandoned) "dPE" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/grimy, /area/library/abandoned) "dPF" = ( @@ -116218,7 +116687,7 @@ /turf/open/floor/plating, /area/medical/virology) "dQi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/green{ dir = 1 }, @@ -116228,7 +116697,7 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/green{ dir = 1 }, @@ -116238,7 +116707,7 @@ /turf/open/floor/plasteel/white, /area/medical/virology) "dQk" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/green{ dir = 4 }, @@ -116295,7 +116764,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = 26 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/green{ dir = 4 }, @@ -116361,7 +116830,7 @@ /area/library/abandoned) "dQx" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/carpet, /area/library/abandoned) "dQy" = ( @@ -117988,14 +118457,14 @@ /turf/open/floor/plasteel/grimy, /area/library/abandoned) "dTq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood{ icon_state = "wood-broken7" }, /area/library/abandoned) "dTr" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood{ icon_state = "wood-broken" }, @@ -118062,7 +118531,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "dTz" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -118086,7 +118555,7 @@ "dTC" = ( /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -118150,7 +118619,7 @@ /area/hallway/secondary/exit/departure_lounge) "dTJ" = ( /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -118402,7 +118871,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "dUk" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 4 }, @@ -118469,7 +118938,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/main) "dUo" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -118490,7 +118959,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/main) "dUq" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/item/radio/intercom{ name = "Station Intercom"; pixel_y = 26 @@ -118556,7 +119025,7 @@ "dUv" = ( /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -118622,7 +119091,7 @@ /area/hallway/secondary/exit/departure_lounge) "dUB" = ( /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -118949,7 +119418,7 @@ /obj/machinery/status_display/evac{ pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/medical/virology) @@ -119529,11 +119998,11 @@ /area/library/abandoned) "dWE" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/library/abandoned) "dWF" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/library/abandoned) "dWG" = ( @@ -119604,7 +120073,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "dWM" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Chapel - Port"; dir = 4; @@ -119643,7 +120112,7 @@ }, /area/chapel/main) "dWR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel{ dir = 4; icon_state = "chapel" @@ -120183,7 +120652,7 @@ icon_state = "1-2" }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -120399,7 +120868,7 @@ }, /area/library/abandoned) "dYl" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light/small, /turf/open/floor/wood{ icon_state = "wood-broken3" @@ -120423,7 +120892,7 @@ /area/library/abandoned) "dYo" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/library/abandoned) "dYp" = ( @@ -120561,7 +121030,7 @@ icon_state = "1-2" }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -120660,7 +121129,7 @@ /turf/open/floor/plasteel, /area/medical/virology) "dYS" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/medical/virology) @@ -120669,7 +121138,7 @@ /obj/machinery/status_display/evac{ pixel_y = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/medical/virology) @@ -120943,7 +121412,7 @@ }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -121375,7 +121844,7 @@ /obj/structure/sign/nanotrasen{ pixel_y = -32 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 }, @@ -122036,19 +122505,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "External Solar Access"; - req_access_txt = "10; 13" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/solars/port/aft) "ebE" = ( @@ -122169,7 +122626,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plating, /area/maintenance/port/aft) "ebP" = ( @@ -122275,7 +122732,7 @@ }, /area/chapel/main) "ebZ" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light{ dir = 4 }, @@ -122563,7 +123020,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/main) "ecE" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light_switch{ pixel_x = 24; pixel_y = -24 @@ -122588,7 +123045,7 @@ name = "departures camera" }, /obj/effect/turf_decal/delivery, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -122603,7 +123060,7 @@ /area/hallway/secondary/exit/departure_lounge) "ecH" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) @@ -123385,21 +123842,23 @@ /turf/open/floor/plasteel/grimy, /area/chapel/office) "edW" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/warning/nosmoking{ pixel_x = 32 }, /turf/open/floor/plasteel/grimy, /area/chapel/office) "edX" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "edY" = ( @@ -123541,7 +124000,7 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 10 }, @@ -123587,7 +124046,7 @@ icon_state = "1-2" }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/line{ dir = 6 }, @@ -123653,7 +124112,7 @@ /turf/open/floor/plasteel/grimy, /area/chapel/office) "eey" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Chapel Quarters"; name = "chapel camera" @@ -124119,16 +124578,6 @@ /turf/open/floor/carpet, /area/chapel/office) "eft" = ( -/obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "efu" = ( @@ -124556,7 +125005,7 @@ /turf/open/floor/plasteel, /area/security/checkpoint/escape) "egi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ dir = 8 @@ -124969,6 +125418,24 @@ /obj/machinery/chem_dispenser/apothecary, /turf/open/floor/plasteel/dark, /area/medical/medbay/central) +"eMb" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/closet/crate{ + icon_state = "crateopen" + }, +/obj/item/flashlight, +/obj/effect/spawner/lootdrop/maintenance, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/maintenance/port) "eMD" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable/white{ @@ -124992,6 +125459,20 @@ }, /turf/open/floor/plasteel/dark, /area/science/mixing) +"ePP" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/door/airlock/public/glass{ + name = "Pool" + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) "eTv" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -125020,7 +125501,7 @@ /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "MiniSat Service Bay"; dir = 8; @@ -125107,6 +125588,9 @@ }, /turf/closed/wall/r_wall, /area/maintenance/disposal/incinerator) +"fMf" = ( +/turf/closed/wall, +/area/engine/transit_tube) "fRK" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -125387,10 +125871,27 @@ /turf/open/floor/plating, /area/chapel/office) "ijB" = ( -/obj/structure/reagent_dispensers/keg/aphro/strong, /obj/item/reagent_containers/glass/beaker, /turf/open/floor/plating, /area/crew_quarters/abandoned_gambling_den) +"ikq" = ( +/obj/machinery/light, +/obj/machinery/status_display/evac{ + pixel_y = -32 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Engineering - Gravity Generator"; + dir = 1; + name = "engineering camera" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "imI" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/effect/turf_decal/tile/neutral{ @@ -125456,7 +125957,6 @@ /area/chapel/office) "iNK" = ( /obj/structure/sign/painting/library{ - pixel_x = 0; pixel_y = -32 }, /turf/open/floor/wood, @@ -125519,6 +126019,25 @@ }, /turf/open/floor/plasteel/dark, /area/science/mixing) +"iUc" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Solar Access"; + req_access_txt = "10; 13" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/port/aft) "jdx" = ( /obj/structure/lattice, /obj/structure/grille, @@ -125720,6 +126239,9 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/science/mixing) +"jUu" = ( +/turf/closed/wall/r_wall, +/area/space/nearstation) "jYx" = ( /obj/effect/turf_decal/bot, /obj/machinery/portable_atmospherics/canister/carbon_dioxide, @@ -125760,6 +126282,13 @@ }, /turf/open/space, /area/engine/atmos) +"kqo" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/mob/living/simple_animal/opossum, +/turf/open/floor/plating, +/area/maintenance/port/fore) "ktK" = ( /obj/effect/turf_decal/tile/neutral{ dir = 4 @@ -126105,6 +126634,20 @@ }, /turf/open/floor/plasteel/dark, /area/science/mixing) +"mte" = ( +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/obj/machinery/light_switch{ + pixel_y = -26 + }, +/obj/structure/table/reinforced, +/obj/item/stack/sheet/plasteel/twenty, +/obj/item/wrench, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "mvm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable/white{ @@ -126246,6 +126789,18 @@ }, /turf/open/floor/plasteel, /area/maintenance/port/fore) +"nYv" = ( +/obj/machinery/newscaster{ + pixel_y = -32 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "odz" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 @@ -126330,7 +126885,7 @@ /turf/open/floor/plasteel/dark, /area/science/mixing) "oNF" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/security/prison) "oSD" = ( @@ -126418,6 +126973,10 @@ dir = 1 }, /area/science/circuit) +"pok" = ( +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/plasteel/grimy, +/area/crew_quarters/theatre/abandoned) "poI" = ( /obj/structure/bed, /obj/item/tank/internals/anesthetic, @@ -126486,6 +127045,25 @@ }, /turf/open/floor/plasteel, /area/science/research/abandoned) +"pQQ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/fitness/pool) "pWb" = ( /obj/structure/table/wood/fancy, /obj/structure/window/reinforced{ @@ -126517,6 +127095,25 @@ dir = 9 }, /area/science/circuit) +"qhB" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/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/dark, +/area/engine/transit_tube) "qnx" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/toxins_mixing_input, /turf/open/floor/engine/vacuum, @@ -126572,7 +127169,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "rPK" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -126712,6 +127309,24 @@ }, /turf/open/floor/plasteel, /area/science/circuit) +"tqP" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/crew_quarters/fitness/recreation) "twt" = ( /obj/machinery/vr_sleeper, /obj/effect/turf_decal/tile/neutral{ @@ -126736,6 +127351,25 @@ }, /turf/open/floor/plasteel/grimy, /area/library) +"tML" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/external{ + name = "External Solar Access"; + req_access_txt = "10; 13" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/solars/starboard/aft) "tNT" = ( /obj/effect/landmark/carpspawn, /turf/open/space, @@ -126981,6 +127615,32 @@ /obj/machinery/atmospherics/pipe/simple/green/visible, /turf/open/floor/plasteel/dark, /area/engine/atmos) +"vFT" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/hatch{ + name = "MiniSat Exterior Access"; + req_one_access_txt = "32;19" + }, +/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/dark, +/area/engine/transit_tube) "vHN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ @@ -127016,6 +127676,18 @@ }, /turf/open/floor/plasteel, /area/maintenance/port/aft) +"vYo" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plasteel, +/area/engine/gravity_generator) "wei" = ( /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, @@ -127078,6 +127750,16 @@ /obj/effect/turf_decal/tile/purple, /turf/open/floor/plasteel/white, /area/science/misc_lab) +"wFK" = ( +/obj/structure/lattice/catwalk, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/turf/open/space, +/area/space/nearstation) "wZT" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -127182,8 +127864,8 @@ /area/science/mixing) "xER" = ( /obj/structure/chair/sofa/left{ - icon_state = "sofaend_left"; - dir = 8 + dir = 8; + icon_state = "sofaend_left" }, /turf/open/floor/wood, /area/library) @@ -127263,6 +127945,22 @@ /obj/structure/fans/tiny/invisible, /turf/open/space/basic, /area/space) +"yfK" = ( +/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/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) "yiv" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ @@ -127284,6 +127982,23 @@ }, /turf/open/floor/plating, /area/engine/atmos) +"yja" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port) "yjc" = ( /obj/machinery/power/apc{ areastring = "/area/science/research/abandoned"; @@ -144626,12 +145341,12 @@ aaa aaa aaa aaa +aaa ajr ajr aad ajr ajr -ajr aad ajr ajr @@ -144883,11 +145598,11 @@ aaa aaa aaa aaa +aaa ajr aaa aaa aad -aaa aad aaa aad @@ -145140,11 +145855,11 @@ aaa aaa aaa aaa +aaa ajr aad ajr ajr -aad ajr ajr ajr @@ -145397,6 +146112,7 @@ aaa aaa aaa aaa +aaa ajr aaa ajr @@ -145408,7 +146124,6 @@ aad aad aad aad -aad ajr aaa bNF @@ -145654,6 +146369,7 @@ aaa aaa aaa aaa +aaa aad aaa ajr @@ -145664,12 +146380,11 @@ bxC bxC bxC bxC -bxC -aad +jUu aad aad bNF -aad +qgU bVZ aad aad @@ -145911,20 +146626,20 @@ aaa aaa aaa aaa -ajr -aad -ajr -aad -bxC -bAH -bAH -bEn -bAH -bAH -bxC -aad -ajr aaa +ajr +aad +ajr +aad +bxC +bAH +bAH +bFX +bAH +bAH +jUu +aad +ajr bNF aaa bVZ @@ -146168,20 +146883,20 @@ aaa aaa aaa aaa +aaa ajr aaa aad aad bxC bAH -bCw bCx -bCy +bEo +bCF bAH -bxC +jUu aad ajr -aaa bNF aaa bVZ @@ -146208,8 +146923,8 @@ cdB cdB cdB car -aad -abj +caE +yja caE caE cOj @@ -146402,7 +147117,7 @@ aAP aAP avY ask -ask +bAL aad abj abj @@ -146425,22 +147140,22 @@ aaa aaa aaa aaa +aaa ajr aad ajr aad bxC bAH -bCx bEo bFW +bLI bAH -bxC -aad +jUu aad aad bNF -aad +qgU bVY aad aad @@ -146465,8 +147180,8 @@ car car car car -caE -cJI +eMb +cqI caE cme cOk @@ -146658,9 +147373,9 @@ aad aad aad aad -aad -apK -aad +aFp +bAM +aFp aLb aad aaa @@ -146682,20 +147397,20 @@ aaa aaa aaa aaa +aaa aad aaa ajr aad bxC bAH -bCy +bCF +bEo bCx -bCw bAH -bxC +jUu aad ajr -aaa bNF aaa bVZ @@ -146940,19 +147655,19 @@ ajr ajr aad ajr +ajr aad ajr aad bxC -bAI bCz +bEn bAH -bFX bHN -bxC +bTL +jUu aad aad -aaa bNF aaa bVZ @@ -147200,18 +147915,18 @@ aad aaa aaa aad +aad bxC -bAJ -bCA -bEp bCA bHO -bxC +bLG +bHO +cJI +jUu aad -bNH -bPK +wFK bRU -aad +qgU bVZ aad car @@ -147457,18 +148172,18 @@ ajr ajr aad aad +aad bxC -bAK bCB bEq bFY bHP -bxC -aad -bNF -aad -aad -aad +ikq +bLF +bLF +vFT +bLF +qgU bVZ aad car @@ -147714,18 +148429,18 @@ aad aad aad aad +aad bxC -bAL bCC bEr bFZ bHQ -bxC +vYo bLF bNI +qhB bLF -bLF -aad +qgU bVZ aad car @@ -147971,18 +148686,18 @@ aRF aRF aad aad +aad bxC -bAM bCD bEs bGa bHR -bxC -bLG +nYv +bLF bNJ bPL bLF -bTK +qgU bWa bTK car @@ -148228,18 +148943,18 @@ bpO aRF aad aad +aad bxC -bAN bCE bEt bGb bHS -bxC -bLH +mte +bLF bNK bPM +fMf bLF -bTL bWb bYn car @@ -148484,15 +149199,15 @@ bpO btK aRF aad +qgU +qgU bxC bxC -bxC -bCF bEu bGc +bNH bxC -bxC -bLI +bLF bNL bPN bRV @@ -148742,9 +149457,9 @@ btL aRF abj bxC -bzd -bAO -bCG +bxC +bxC +bCI bEv bGd bHT @@ -149515,9 +150230,9 @@ aMG bxE bzg bzg -bCJ -bEy bzg +bEy +bLH bHV bJQ bLL @@ -153972,7 +154687,7 @@ aaa aad aad aad -ajr +qgU aad ebC aad @@ -154230,9 +154945,9 @@ ajr aad aad aad -aad -ebC -aad +eak +iUc +eak aad aaa aac @@ -161357,7 +162072,7 @@ bvL cjw bYU bvL -bvL +aar bvL bun bvL @@ -163350,7 +164065,7 @@ aof aky aky aky -arD +kqo asZ aui avF @@ -169227,8 +169942,8 @@ aaa aaa aaa aad -aad abi +bAI abR abi acp @@ -169484,9 +170199,9 @@ aaa aaa aaa abj -abj abH abS +abS acd acq acH @@ -169589,7 +170304,7 @@ cur cvC cvz cyE -cAi +cAk cBD cDk cEY @@ -169740,9 +170455,9 @@ aaa aaa aaa aaa -aaa -aad +qgU abi +bAJ abT abi acr @@ -169996,9 +170711,9 @@ aaa aaa aaa aaa -aaa -aac +jdx aad +bzd abi abi ace @@ -170253,8 +170968,8 @@ aaa aaa aaa aaa -aaa -aac +jdx +aad aad aad aad @@ -170510,7 +171225,7 @@ aaa aaa aaa aaa -aaa +aac aac aac aad @@ -171801,9 +172516,9 @@ aac aaa aad aad -aad -acQ -aad +acf +bAK +acf aad aaa abi @@ -172057,7 +172772,7 @@ aaa aac aac aad -aac +aad aad aaj aad @@ -172869,7 +173584,7 @@ ayD ayD hdH azD -aEg +aaq azD kam aHV @@ -178109,7 +178824,7 @@ dCX dEj dFq dGJ -dGJ +pok dJy dGJ dGJ @@ -178613,7 +179328,7 @@ dnR dpG dpG dpG -dpG +abz dpG dxu dyQ @@ -179132,7 +179847,7 @@ dvO dxw dyS dmh -dBz +abK dCV dEk dFt @@ -179632,22 +180347,22 @@ cZX dbD ddt ddt -dfV +aaB dbD diW -dkO +aaR dbA dnU -dbD -drr -diW +abg +abk +abo due dbD dbD -dyT diW -dBE -dCV +diW +abL +abM dEk dFv dGN @@ -179889,22 +180604,22 @@ cZY dbE cRr cRr -dfW +aaC dhB -cRr -dkP -dbE -dnV -dpJ dfW -dhB +aaT +aaW +abb +abh +dfW +abr dhB dvP dxx dfW dvP dBF -dDa +abN dEk dFw dGO @@ -180145,17 +180860,17 @@ cYp cZZ cIX ddu -cHU -dfX -cHU -cHU -dkQ -cHU -dkQ -cHU -cHU -dfX -cHU +aay +aaD +aay +aay +aaU +aay +abc +aay +aay +abt +aay cHU dkQ dyU @@ -180402,19 +181117,19 @@ cYq daa cuL cuL -cuL -aad -cHU -diX -dkR -cHU -dnW -dpK -cHU -aad -cHU -dvQ -dxy +aay +aaF +aaQ +aba +abn +abu +abB +abO +abV +abY +aay +abA +abI dyU dAl dBH @@ -180659,19 +181374,19 @@ cYr dab dbF ddv -cuL -aaa -dhC -diY -dkS -cHU -dnX -dpL -dfX -aaa -dfX -dvR -dxz +aay +aaG +aaV +aaN +aaN +aaN +aaN +aaN +abW +acg +aay +acl +abJ dyU dAm dBI @@ -180914,21 +181629,21 @@ cCl cWD cAz dac -cxy -ddw -cuM -aad -dhC -diZ -dkT -cHU -dnY -dpM -dfX -aad -dfX -dvS -dxA +yfK +tqP +ePP +pQQ +aaV +aaN +aaN +aaN +aaN +aaN +abW +acw +aay +acm +acn dyU dAn dBJ @@ -181172,19 +181887,19 @@ cWE cYs dad cTe -ddw -cuM -aaa +aav +aaz +aaH +aaV +aaN +aaN +aaN +aaN +aaN +abW +abY +aay dhC -dhC -cHU -cHU -cHU -dfX -dfX -aaa -dfX -dfX cHU dyV dyV @@ -181429,18 +182144,18 @@ cTe cYt dae dbG -ddw -cuM -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad +aaw +aaA +aaH +aaV +abd +aaN +aaN +aaN +abU +abW +acg +aay aad aad aad @@ -181686,18 +182401,18 @@ cxy cYt daf dbH -ddx -cuM -aad -aaa -ajr -ajr -ajr -ajr -ajr -aaa -ajr -aaa +aax +aaA +aaI +aaV +aaN +aaN +abw +aaN +aaN +abW +acx +aay ajr ajr aad @@ -181943,24 +182658,24 @@ cWF cYu dag dbI -cDL -cuM -aad -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +dbJ +aaA +aaJ +aaV +aaN +aaN +aaN +aaN +aaN +abW +ach +aaA aaa aaa aad -aaa -dBN -aad +dyV +tML +dyV aad aaa aad @@ -182201,22 +182916,22 @@ cYv dah cTe dbJ -cuM -aad -ajr +aaA +aaH +aaV +aaN +aaN +aaN +aaN +aaN +abW +aci +aaA aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -ajr -aad -dBO +qgU +qgU +dBN aad aaa dFy @@ -182458,19 +183173,19 @@ cYw czl cxy dbJ -cuM -aad -ajr -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa +aaA +aaH +aaX +aaN +aaN +aaN +aaN +aaN +abW +acj +aaA +qgU +qgU aad aaa dBO @@ -182715,17 +183430,17 @@ cQa dai dbJ ddy -cuM -aad -aaa -aaa -aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaA +aaK +aaV +abl +aaN +aaY +aaN +aaN +abW +ack +aaA aaa aaa ajr @@ -182972,17 +183687,17 @@ cuM daj dbK ddz -cuM -aad -ajr -aaa -aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaA +aaL +aaZ +abm +abm +abx +abm +abm +abX +aaL +aaA aaa aaa ajr @@ -183229,17 +183944,17 @@ cuM dak dbL ddA -cuM -aad -ajr -aaa -aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaA +aaM +aaM +aaM +aaM +aby +aaM +aaM +aaM +aaM +aaA aaa aaa ajr @@ -183486,19 +184201,19 @@ cuL cuM cuM cuM -cuL -aad -aaa -aaa -aaa -hZh -hZh -hZh -hZh -hZh -hZh -aaa -aaa +aay +aaA +aaA +aaA +aaA +aay +aaA +aaA +aaA +aaA +aay +qgU +qgU aad aaa dBO @@ -183745,18 +184460,18 @@ aad aad aad aad -ajr +aad +qgU aaa aaa -hZh -hZh -hZh -hZh -hZh -hZh aaa aaa -ajr +qgU +aaa +aaa +aaa +aaa +aad aad dBO dDf @@ -184003,16 +184718,16 @@ aaa ajr ajr ajr -aaa -aaa -hZh -hZh -hZh -hZh -hZh -hZh -aaa -aaa +qgU +ajr +ajr +ajr +ajr +qgU +ajr +ajr +ajr +qgU ajr aaa aaa @@ -184185,7 +184900,7 @@ aaa ajr ajr ajr -aaa +qgU aKZ aKZ aKZ @@ -184262,12 +184977,12 @@ aaa aaa aaa aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa ajr @@ -184442,9 +185157,9 @@ aaa aaa aaa aaa -aaa -aaa +qgU abj +bAN aUK aWs aXT @@ -184519,12 +185234,12 @@ aaa aaa aaa aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -184700,11 +185415,11 @@ aaa aaa aaa aaa -aaa aad aKV aKV aKV +aKV aZK bbt aNJ @@ -184776,12 +185491,12 @@ aaa aaa aaa aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -185033,12 +185748,12 @@ aaa aaa aaa aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -185290,12 +186005,12 @@ aaa aaa aaa aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -185547,12 +186262,12 @@ aaa aaa aab aaa -hZh -hZh -hZh -hZh -hZh -hZh +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index b205e7c324..518fa4e81e 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -2134,14 +2134,11 @@ /turf/open/floor/plasteel/dark, /area/maintenance/port) "adM" = ( -/obj/machinery/door/airlock/external{ - name = "Abandoned External Airlock" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/floor/plasteel/dark, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plasteel, /area/maintenance/fore) "adN" = ( /obj/effect/turf_decal/loading_area{ @@ -2160,11 +2157,16 @@ /turf/open/floor/engine, /area/ai_monitored/storage/satellite) "adO" = ( +/obj/machinery/door/airlock/external{ + name = "Satellite External Airlock"; + req_one_access_txt = "32;19" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/floor/engine, +/turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/atmos) "adP" = ( /obj/machinery/status_display/ai, @@ -2513,6 +2515,9 @@ /turf/open/floor/plating, /area/security/execution/education) "aeD" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, /obj/structure/disposalpipe/segment, /turf/open/floor/plating/airless, /area/space/nearstation) @@ -2598,13 +2603,20 @@ }, /obj/machinery/light/small, /turf/open/floor/plating/airless, -/area/maintenance/starboard/fore) +/area/space/nearstation) "aeL" = ( +/obj/machinery/door/airlock/external{ + name = "Abandoned External Airlock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/structure/cable{ - icon_state = "2-8" + icon_state = "1-2" + }, +/obj/structure/cable{ + icon_state = "1-2" }, /obj/structure/disposalpipe/segment, -/turf/open/floor/plating/airless, +/turf/open/floor/plasteel/dark, /area/maintenance/starboard/fore) "aeM" = ( /obj/machinery/photocopier, @@ -3429,7 +3441,7 @@ /obj/structure/cable{ icon_state = "0-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/showroomfloor, @@ -5704,13 +5716,6 @@ /turf/open/floor/plasteel/dark, /area/security/courtroom) "ajI" = ( -/obj/machinery/door/airlock/external{ - name = "Abandoned External Airlock" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/structure/cable{ - icon_state = "1-2" - }, /obj/structure/cable{ icon_state = "1-2" }, @@ -6935,7 +6940,6 @@ dir = 4 }, /obj/structure/closet/emcloset/anchored, -/obj/effect/decal/cleanable/cobweb, /obj/machinery/light/small{ dir = 8 }, @@ -7205,9 +7209,6 @@ /turf/open/floor/plasteel/dark, /area/tcommsat/computer) "amk" = ( -/obj/machinery/gateway{ - dir = 1 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -8802,7 +8803,7 @@ /turf/open/floor/plating, /area/medical/virology) "aoR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1{ @@ -8959,7 +8960,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/plasteel/dark, /area/security/courtroom) "apj" = ( @@ -9122,7 +9123,7 @@ /turf/open/floor/plasteel/dark, /area/teleporter) "apw" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -9661,12 +9662,19 @@ /turf/open/floor/plasteel/showroomfloor, /area/medical/genetics) "aqp" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/structure/lattice/catwalk, -/turf/open/floor/plating/airless, -/area/solar/port/fore) +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/maintenance/solars/port/fore) "aqq" = ( /obj/machinery/status_display/ai{ pixel_x = -32 @@ -10947,7 +10955,7 @@ /turf/open/floor/engine, /area/space) "asg" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/dark, @@ -11992,7 +12000,7 @@ /turf/open/floor/circuit/green/telecomms/mainframe, /area/tcommsat/server) "atV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/effect/turf_decal/tile/neutral, @@ -12465,12 +12473,18 @@ /turf/open/floor/plasteel, /area/bridge) "auN" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/structure/lattice/catwalk, -/turf/open/floor/plating/airless, -/area/solar/starboard/fore) +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/fore) "auO" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable{ @@ -13179,6 +13193,9 @@ dir = 8 }, /obj/effect/decal/cleanable/blood/old, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel, /area/security/courtroom) "avX" = ( @@ -13604,9 +13621,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm{ dir = 4; @@ -13851,7 +13865,6 @@ /obj/item/lighter, /obj/item/clothing/mask/cigarette/cigar/cohiba, /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/suit_storage_unit/ce, /turf/open/floor/plasteel, /area/crew_quarters/heads/chief) "axi" = ( @@ -14194,7 +14207,7 @@ /obj/machinery/cell_charger, /obj/item/stock_parts/cell/hyper, /obj/item/stack/cable_coil, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -14307,8 +14320,8 @@ /obj/item/stack/cable_coil, /obj/item/electronics/apc, /obj/item/electronics/apc, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel/dark, /area/engine/engineering) "axR" = ( @@ -17393,7 +17406,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/blue, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1{ @@ -19751,7 +19764,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel, @@ -19770,7 +19783,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ desc = "After his promotion, he was transferred to Kilo Station to serve as the gateway's protector."; icon_state = "plant-21"; name = "rodger" @@ -20601,7 +20614,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/blue, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/showroomfloor, @@ -20638,7 +20651,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/dark, @@ -21015,7 +21028,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/light{ @@ -22183,7 +22196,7 @@ /area/hallway/primary/aft) "aKO" = ( /obj/effect/decal/cleanable/cobweb, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/effect/decal/cleanable/blood/old, @@ -22217,7 +22230,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "aKR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/wood, @@ -22678,7 +22691,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/airalarm{ @@ -24453,7 +24466,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/showroomfloor, @@ -24742,7 +24755,7 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -24875,7 +24888,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/purple, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/machinery/button/door{ @@ -28508,7 +28521,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/blue, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /obj/machinery/camera{ @@ -28850,7 +28863,7 @@ /obj/structure/cable{ icon_state = "2-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/structure/disposalpipe/segment{ @@ -28949,7 +28962,7 @@ dir = 1 }, /obj/effect/decal/cleanable/cobweb, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -30057,7 +30070,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/yellow, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /turf/open/floor/plasteel/showroomfloor, @@ -30479,6 +30492,7 @@ /obj/machinery/light{ dir = 1 }, +/obj/machinery/airalarm/directional/north, /turf/open/floor/plasteel/dark, /area/science/research) "aXx" = ( @@ -33869,7 +33883,7 @@ }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel, @@ -38992,7 +39006,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -39326,7 +39340,7 @@ /obj/effect/turf_decal/tile/green{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -39567,7 +39581,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/structure/cable{ icon_state = "4-8" }, @@ -39606,7 +39620,7 @@ /area/quartermaster/sorting) "blR" = ( /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/structure/cable{ icon_state = "4-8" }, @@ -39923,7 +39937,7 @@ /turf/open/floor/plasteel/dark, /area/quartermaster/storage) "bmo" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/firealarm{ @@ -40109,7 +40123,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/dark, @@ -40960,7 +40974,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/yellow, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -40992,7 +41006,7 @@ /turf/open/floor/plasteel/dark, /area/quartermaster/office) "bnZ" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, @@ -42301,7 +42315,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/machinery/power/apc/highcap/ten_k{ areastring = "/area/bridge"; dir = 8; @@ -42952,7 +42966,7 @@ /obj/effect/turf_decal/tile/yellow{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/machinery/light{ @@ -43018,7 +43032,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/dark, @@ -43216,7 +43230,7 @@ /obj/machinery/light/small{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/spider/stickyweb, @@ -43680,10 +43694,6 @@ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, /area/maintenance/central/secondary) -"bsm" = ( -/obj/machinery/status_display/evac, -/turf/open/floor/plasteel, -/area/engine/supermatter) "bsn" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -43856,7 +43866,7 @@ /turf/open/floor/plasteel/dark, /area/quartermaster/office) "bsA" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -44007,7 +44017,7 @@ /turf/open/floor/plasteel, /area/hydroponics) "bsM" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/light_switch{ @@ -44136,7 +44146,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -44744,7 +44754,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/bar) "btZ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral{ @@ -45146,7 +45156,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -45872,7 +45882,7 @@ /turf/open/floor/plasteel/showroomfloor, /area/crew_quarters/toilet/restrooms) "bvP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel/showroomfloor, @@ -45926,7 +45936,7 @@ /turf/open/floor/plasteel/dark, /area/library) "bvV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -45969,7 +45979,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -46000,7 +46010,7 @@ /obj/structure/noticeboard{ pixel_y = 30 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-17"; pixel_x = -8; pixel_y = 3 @@ -46124,7 +46134,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/structure/extinguisher_cabinet{ pixel_x = 24 }, @@ -46864,7 +46874,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) "bxF" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -46970,14 +46980,14 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "bxO" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/showroomfloor, @@ -47265,7 +47275,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -48696,7 +48706,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/blue, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/disposalpipe/segment, @@ -49042,7 +49052,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -49723,7 +49733,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 6 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel, @@ -51809,7 +51819,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/dark, @@ -51937,7 +51947,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 9 }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/structure/cable{ icon_state = "1-8" }, @@ -52034,7 +52044,7 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/airalarm{ @@ -53281,7 +53291,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 10 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel, @@ -53305,7 +53315,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 6 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel/dark/corner{ @@ -54405,7 +54415,7 @@ }, /obj/effect/turf_decal/tile/neutral, /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/extinguisher_cabinet{ @@ -54428,7 +54438,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/structure/extinguisher_cabinet{ @@ -54780,7 +54790,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/item/radio/intercom{ @@ -55592,7 +55602,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/structure/cable{ @@ -55782,7 +55792,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/firealarm{ @@ -56179,7 +56189,7 @@ /obj/item/radio/intercom{ pixel_x = -28 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -57353,9 +57363,7 @@ name = "landing marker"; picked_color = "Burgundy" }, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "bOe" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1{ @@ -57850,7 +57858,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/power/apc/highcap/five_k{ @@ -58148,7 +58156,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -58242,7 +58250,7 @@ }, /obj/effect/turf_decal/tile/neutral, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-11" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -58401,7 +58409,7 @@ /obj/machinery/status_display/ai{ pixel_x = 32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -58484,7 +58492,7 @@ /area/hallway/primary/central) "bPT" = ( /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -58573,9 +58581,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "bQb" = ( /obj/structure/flora/rock, @@ -58625,7 +58631,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/red, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -58938,7 +58944,7 @@ dir = 8 }, /obj/machinery/power/apc{ - areastring = "/area/janitor"; + areastring = "/area/vacant_room/commissary"; dir = 4; name = "Vacant Commissary APC"; pixel_x = 27; @@ -59282,7 +59288,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/decal/cleanable/dirt, @@ -60372,7 +60378,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -60727,7 +60733,7 @@ /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /turf/open/floor/plasteel, @@ -60975,7 +60981,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -61293,9 +61299,7 @@ name = "landing marker"; picked_color = "Burgundy" }, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "bUk" = ( /obj/effect/turf_decal/tile/red, @@ -61575,9 +61579,7 @@ /turf/closed/wall, /area/engine/atmos) "bUN" = ( -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "bUP" = ( /obj/machinery/door/airlock/external{ @@ -62452,7 +62454,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/dark, @@ -62896,9 +62898,9 @@ pixel_x = 24 }, /obj/machinery/button/electrochromatic{ + id = "!interrogation_room"; pixel_x = 38; - pixel_y = -5; - id = "!interrogation_room" + pixel_y = -5 }, /turf/open/floor/plasteel, /area/security/warden) @@ -63053,7 +63055,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -63294,7 +63296,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/yellow, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/light, @@ -63575,7 +63577,7 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -64071,7 +64073,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/red, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/structure/noticeboard{ @@ -64685,7 +64687,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "bZx" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral, @@ -64794,11 +64796,15 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/starboard) "bZG" = ( -/obj/structure/sign/warning/vacuum/external{ - pixel_y = 32 +/obj/machinery/door/airlock/external{ + name = "Abandoned External Airlock" }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/fore) "bZH" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -64917,9 +64923,18 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bZP" = ( -/obj/structure/cable, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + name = "Prison External Airlock"; + req_access_txt = "2" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/security/prison) "bZQ" = ( /obj/structure/closet/l3closet/janitor, /obj/structure/window/reinforced, @@ -64968,7 +64983,7 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/light_switch{ @@ -65990,7 +66005,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/yellow, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/decal/cleanable/dirt, @@ -66540,7 +66555,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/structure/cable{ @@ -67260,7 +67275,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/showroomfloor, @@ -67358,7 +67373,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -67609,7 +67624,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/machinery/atmospherics/pipe/simple/cyan/hidden/layer1{ @@ -67705,11 +67720,6 @@ }, /area/ai_monitored/turret_protected/ai) "ceA" = ( -/obj/machinery/door/airlock/external{ - name = "Satellite External Airlock"; - req_one_access_txt = "32;19" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable{ icon_state = "1-2" @@ -68002,9 +68012,7 @@ name = "landing marker"; picked_color = "Burgundy" }, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "ceV" = ( /obj/effect/turf_decal/tile/yellow{ @@ -68029,18 +68037,14 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "ceX" = ( /obj/machinery/light{ dir = 8 }, /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "ceY" = ( /obj/machinery/airalarm{ @@ -68128,7 +68132,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/showroomfloor, @@ -68157,7 +68161,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{ dir = 9 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -68226,7 +68230,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -68250,7 +68254,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/effect/turf_decal/tile/neutral{ @@ -68888,9 +68892,7 @@ /area/engine/engineering) "cgI" = ( /obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "cgJ" = ( /obj/machinery/door/poddoor/preopen, @@ -69633,15 +69635,12 @@ /turf/open/floor/plasteel, /area/engine/atmos) "chO" = ( -/obj/structure/sign/warning/vacuum/external, -/turf/closed/wall, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/atmos) "chP" = ( -/obj/structure/reagent_dispensers/watertank, -/obj/structure/reagent_dispensers/watertank, -/obj/effect/turf_decal/delivery, -/obj/machinery/light, -/turf/open/floor/plasteel/dark, +/obj/structure/sign/warning/vacuum/external, +/turf/closed/wall, /area/ai_monitored/turret_protected/aisat/atmos) "chQ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -69720,12 +69719,19 @@ /turf/open/floor/plasteel, /area/engine/engineering) "chU" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/structure/lattice/catwalk, -/turf/open/floor/plating/airless, -/area/solar/port/aft) +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) "chW" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/hatch{ @@ -71366,16 +71372,9 @@ /turf/open/floor/plating, /area/engine/engineering) "ckJ" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) "ckK" = ( @@ -71550,7 +71549,7 @@ /turf/open/floor/plasteel, /area/security/processing) "cld" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -71786,16 +71785,9 @@ /turf/open/space/basic, /area/space/nearstation) "clx" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/maintenance/solars/port/aft) @@ -72402,7 +72394,7 @@ /obj/structure/noticeboard{ pixel_y = 28 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -72422,7 +72414,7 @@ /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /turf/open/floor/plasteel, @@ -74896,6 +74888,9 @@ dir = 8 }, /obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-4" + }, /turf/open/floor/plating{ icon_state = "platingdmg1" }, @@ -74965,6 +74960,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plasteel/dark, /area/maintenance/disposal) "crg" = ( @@ -76334,9 +76332,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/machinery/gateway{ - dir = 9 - }, /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/box/corners{ dir = 4 @@ -76403,9 +76398,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/machinery/gateway{ - dir = 5 - }, /obj/effect/decal/cleanable/dirt, /obj/machinery/camera{ c_tag = "Gateway"; @@ -76439,14 +76431,12 @@ /turf/open/floor/plating/airless, /area/solar/starboard/aft) "ctO" = ( -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, /area/maintenance/disposal) "ctP" = ( /obj/structure/cable{ @@ -76467,16 +76457,9 @@ /turf/open/floor/plating/airless, /area/solar/starboard/aft) "ctS" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/maintenance/solars/port/fore) @@ -77551,9 +77534,6 @@ dir = 8 }, /obj/effect/decal/cleanable/greenglow, -/obj/machinery/gateway{ - dir = 8 - }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, /area/gateway) @@ -77573,9 +77553,6 @@ dir = 4 }, /obj/effect/decal/cleanable/greenglow, -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, /area/gateway) @@ -77588,8 +77565,6 @@ /turf/open/floor/plasteel/dark, /area/maintenance/disposal) "cvQ" = ( -/obj/effect/turf_decal/bot, -/obj/structure/closet/cardboard, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small{ @@ -77599,6 +77574,9 @@ dir = 8; pixel_x = 32 }, +/obj/machinery/computer/gateway_control{ + dir = 8 + }, /turf/open/floor/plasteel/dark, /area/gateway) "cvR" = ( @@ -77635,7 +77613,6 @@ dir = 8 }, /obj/effect/decal/cleanable/greenglow, -/obj/machinery/gateway, /obj/effect/decal/cleanable/dirt, /obj/structure/cable{ icon_state = "0-2" @@ -77652,9 +77629,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/plasteel/dark, /area/gateway) @@ -77711,12 +77685,18 @@ /turf/open/floor/plating, /area/maintenance/disposal) "cwb" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/structure/lattice/catwalk, -/turf/open/floor/plating/airless, -/area/solar/starboard/aft) +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard/aft) "cwc" = ( /obj/machinery/atmospherics/components/binary/pump/on, /obj/machinery/airlock_sensor/incinerator_atmos{ @@ -77812,9 +77792,9 @@ /area/maintenance/starboard/aft) "cwk" = ( /obj/structure/cable{ - icon_state = "1-2" + icon_state = "2-8" }, -/turf/open/floor/plating/asteroid/airless, +/turf/open/floor/plating/airless, /area/space/nearstation) "cwl" = ( /obj/structure/cable{ @@ -77992,13 +77972,6 @@ /turf/open/floor/plating, /area/maintenance/starboard) "cwD" = ( -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, /turf/open/floor/plasteel/dark, /area/maintenance/starboard) "cwE" = ( @@ -78169,6 +78142,9 @@ icon_state = "1-8" }, /obj/effect/decal/cleanable/blood/old, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plating, /area/maintenance/disposal) "cwQ" = ( @@ -78282,6 +78258,9 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "4-8" + }, /turf/open/floor/plating{ icon_state = "platingdmg3" }, @@ -78339,6 +78318,9 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/blood/old, +/obj/structure/cable{ + icon_state = "2-8" + }, /turf/open/floor/plating, /area/maintenance/disposal) "cxh" = ( @@ -78378,6 +78360,9 @@ /area/maintenance/disposal) "cxj" = ( /obj/effect/decal/cleanable/dirt, +/obj/structure/cable{ + icon_state = "1-2" + }, /turf/open/floor/plating{ icon_state = "platingdmg3" }, @@ -78425,17 +78410,21 @@ }, /area/maintenance/port/fore) "cxp" = ( -/obj/structure/cable{ - icon_state = "1-4" +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/obj/structure/cable{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/disposal) "cxq" = ( -/obj/structure/cable{ - icon_state = "2-8" +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/plating{ + icon_state = "platingdmg1" }, -/turf/open/floor/plating/airless, -/area/space/nearstation) +/area/maintenance/fore) "cxr" = ( /obj/structure/sign/poster/contraband/clown, /turf/closed/wall/rust, @@ -78536,6 +78525,7 @@ icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/mob/living/simple_animal/opossum/poppy, /turf/open/floor/plating{ icon_state = "platingdmg3" }, @@ -80529,9 +80519,7 @@ /area/maintenance/fore) "cDp" = ( /obj/structure/lattice/catwalk, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "cDq" = ( /obj/machinery/door/airlock/maintenance{ @@ -80543,7 +80531,7 @@ /turf/open/floor/plasteel/dark, /area/maintenance/fore) "cDr" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02"; pixel_y = 3 }, @@ -80825,7 +80813,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "cDT" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/effect/turf_decal/tile/neutral, @@ -80919,9 +80907,6 @@ pixel_x = 4; pixel_y = 4 }, -/obj/item/storage/pill_bottle/dice{ - pixel_x = -4 - }, /obj/item/pen/red{ pixel_x = 4; pixel_y = 4 @@ -83852,16 +83837,9 @@ }, /area/maintenance/starboard) "cMH" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, /turf/open/floor/plating, /area/maintenance/solars/starboard/fore) "cMI" = ( @@ -84529,13 +84507,6 @@ /turf/open/space/basic, /area/space/nearstation) "cUD" = ( -/obj/machinery/door/airlock/external{ - name = "Prison External Airlock"; - req_access_txt = "2" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, /obj/structure/cable{ icon_state = "1-2" }, @@ -84553,6 +84524,10 @@ icon_state = "wood-broken" }, /area/security/vacantoffice) +"dky" = ( +/obj/structure/cable, +/turf/open/floor/plating/airless, +/area/space/nearstation) "dlg" = ( /obj/machinery/light, /turf/open/floor/wood, @@ -84616,7 +84591,7 @@ icon_state = "1-4" }, /obj/machinery/airalarm/directional/west, -/obj/item/twohanded/required/kirbyplants/dead, +/obj/item/kirbyplants/dead, /turf/open/floor/wood, /area/security/vacantoffice) "esR" = ( @@ -84701,12 +84676,15 @@ }, /area/security/vacantoffice) "fyr" = ( -/obj/machinery/light{ - dir = 4 - }, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/closed/mineral/random/labormineral, /area/space/nearstation) +"fAn" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_y = 32 + }, +/turf/open/floor/plating/airless, +/area/space/nearstation) "fXq" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -84946,10 +84924,13 @@ "jAT" = ( /obj/structure/lattice/catwalk, /obj/machinery/light, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) +"jGN" = ( +/obj/effect/decal/cleanable/dirt, +/mob/living/simple_animal/opossum, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "jHJ" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 9 @@ -84960,10 +84941,6 @@ /obj/structure/sign/warning/electricshock, /turf/closed/wall/r_wall/rust, /area/ai_monitored/turret_protected/ai_upload) -"jPE" = ( -/obj/structure/cable, -/turf/closed/mineral/random/labormineral, -/area/space/nearstation) "jQY" = ( /obj/structure/table/wood, /obj/item/paper_bin, @@ -85160,6 +85137,16 @@ /obj/structure/sign/poster/ripped, /turf/closed/wall, /area/crew_quarters/fitness/recreation) +"lqz" = ( +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/starboard) "lKu" = ( /obj/structure/table/wood, /obj/item/reagent_containers/food/drinks/soda_cans/thirteenloko, @@ -85217,6 +85204,9 @@ }, /turf/open/floor/plasteel/dark, /area/science/research) +"mKj" = ( +/turf/closed/wall/rust, +/area/security/execution/education) "mKp" = ( /obj/structure/cable{ icon_state = "1-2" @@ -85287,7 +85277,6 @@ icon_state = "1-2" }, /obj/structure/table/wood, -/obj/item/folder/paperwork, /turf/open/floor/wood, /area/security/vacantoffice) "ppP" = ( @@ -85401,9 +85390,7 @@ "rNm" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/lattice/catwalk, -/turf/open/floor/plating/airless{ - initial_gas_mix = "o2=14;n2=23;TEMP=300" - }, +/turf/open/floor/plating/airless, /area/hallway/secondary/entry) "swG" = ( /obj/item/reagent_containers/food/drinks/drinkingglass{ @@ -85463,7 +85450,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -85586,6 +85573,12 @@ icon_state = "wood-broken4" }, /area/maintenance/port/fore) +"yaV" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/turf/open/floor/plating/airless, +/area/space/nearstation) "ydo" = ( /obj/structure/cable{ icon_state = "4-8" @@ -99399,9 +99392,9 @@ bTK bVs hNk bXG +abp cZm -bZG -aeU +fAn aeU aeU aeU @@ -99658,7 +99651,7 @@ cTF bXH cUD bZP -aeU +dky coy aeU aeU @@ -99911,19 +99904,19 @@ aaG aez cIj aeB -cZm +mKj +aez aez aez cko cko -cko -aeU aeU aeU aeU aeU +cnS chU -aeU +cnS aUz aeU aeu @@ -100366,9 +100359,9 @@ aeu aeU aeU aeU -aeU +ctH aqp -aeU +ctH aeu aeu aeu @@ -112440,7 +112433,7 @@ aaa aaa aeU aUz -aeu +adH adH adH adH @@ -112697,8 +112690,8 @@ aaa aaa acm aeU -aeU adQ +cxq alN chj aoc @@ -112954,7 +112947,7 @@ aeR aeR aes aes -aes +bZG adM alO amL @@ -113211,7 +113204,7 @@ aaa aaa acm aaa -aaa +adH adH adH adQ @@ -119989,7 +119982,7 @@ ckw cmw xON axa -jPE +aeu aeu aeU dQe @@ -120652,9 +120645,9 @@ aaa aaa aaa aaa -aeU aeK baH +baH afb baH baH @@ -121773,7 +121766,7 @@ clM axW cnk coo -ayn +axU aLH aLx aLz @@ -122293,7 +122286,7 @@ aLF aag aag aag -bsm +aLF cuA cuW bYI @@ -124361,9 +124354,9 @@ cpb crf cnu cnu +cnu cko aeu -aeu aaa aaa aaa @@ -124619,7 +124612,7 @@ cxg cxj ctO cxp -aeU +yaV ciQ aeU aaa @@ -124875,7 +124868,7 @@ cnu cnd cnu cnu -cxq +cnu cwk cxu aeU @@ -125083,7 +125076,7 @@ bAP bCf bhQ bhQ -bAM +jGN bGH bOc bHZ @@ -126409,9 +126402,9 @@ bzG bzG aeu aeu -aeU +ckz cwb -aeU +ckz aeU aUz aeU @@ -129431,9 +129424,9 @@ aaQ aeo aeo acm -acm -acK -acm +bkd +lqz +bkd aaa aaa aaa @@ -129666,9 +129659,9 @@ aeu aeu aeu aeu -aeU +cLM auN -aeU +cLM aeu aeu aeu diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm index 825bc3c2aa..47d8dd9cb4 100644 --- a/_maps/map_files/LambdaStation/lambda.dmm +++ b/_maps/map_files/LambdaStation/lambda.dmm @@ -15609,7 +15609,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/newscaster{ pixel_x = -30 }, @@ -15985,7 +15985,7 @@ /turf/closed/wall/r_wall, /area/crew_quarters/heads/hor/private) "aDh" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/hor/private) "aDi" = ( @@ -16008,7 +16008,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/white, /area/science/explab) "aDl" = ( @@ -21689,7 +21689,7 @@ /turf/open/floor/plasteel, /area/security/brig) "aNv" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/neutral/filled/corner, /turf/open/floor/plasteel/dark, /area/security/brig) @@ -21757,7 +21757,7 @@ /turf/open/floor/plasteel/grimy, /area/lawoffice) "aNA" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /obj/structure/disposalpipe/segment{ @@ -23804,7 +23804,7 @@ /turf/open/floor/plasteel, /area/security/range) "aRr" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/captain/private) "aRs" = ( @@ -23834,7 +23834,7 @@ dir = 8; light_color = "#e8eaff" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/hop/private) "aRw" = ( @@ -25005,7 +25005,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/command) "aTI" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/hallway/secondary/command) "aTJ" = ( @@ -25230,7 +25230,7 @@ /turf/open/floor/plating, /area/maintenance/fore/secondary) "aUi" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera/autoname{ dir = 1 }, @@ -27581,7 +27581,7 @@ /turf/open/floor/plating, /area/crew_quarters/heads/captain) "aYV" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/captain) "aYX" = ( @@ -33412,6 +33412,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, +/obj/machinery/gateway/centerstation, /turf/open/floor/plasteel/dark, /area/gateway) "bkm" = ( @@ -34830,7 +34831,7 @@ /obj/effect/turf_decal/tile{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "bmX" = ( @@ -36560,7 +36561,7 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/crew_quarters/cafeteria) "bqv" = ( @@ -38499,7 +38500,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/red, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "buh" = ( @@ -42115,7 +42116,7 @@ /turf/open/floor/plasteel/white, /area/medical/cryo) "bBv" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/bar, /obj/effect/turf_decal/tile/bar{ dir = 1 @@ -44382,7 +44383,6 @@ /turf/open/floor/plasteel/white, /area/hallway/primary/aft) "bFB" = ( -/obj/structure/reagent_dispensers/keg/aphro/strong, /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood{ icon_state = "wood-broken5" @@ -45627,7 +45627,7 @@ /turf/open/floor/carpet/blue, /area/crew_quarters/heads/cmo/private) "bHP" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/cmo/private) "bHQ" = ( @@ -48277,7 +48277,7 @@ /obj/structure/cable{ icon_state = "1-4" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/blue/filled/line, /obj/structure/cable{ icon_state = "0-4" @@ -50299,7 +50299,7 @@ /turf/open/floor/wood, /area/maintenance/bar) "bPX" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/crew_quarters/cafeteria) "bPY" = ( @@ -50976,7 +50976,7 @@ /turf/open/floor/plasteel/dark, /area/bridge/showroom/corporate) "bRs" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "bRu" = ( @@ -51416,7 +51416,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "bSx" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 8 }, @@ -52110,7 +52110,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "bTR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/grimy, @@ -55491,7 +55491,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable{ icon_state = "1-2" }, @@ -56279,7 +56279,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/chief) "cbt" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/light_switch{ pixel_x = 26; pixel_y = -26 @@ -60349,8 +60349,8 @@ }, /obj/item/stack/cable_coil, /obj/item/stack/cable_coil, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel, /area/engine/break_room) "ckz" = ( @@ -61189,7 +61189,7 @@ /turf/open/floor/plasteel/dark, /area/storage/tcom) "cml" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable{ icon_state = "1-8" }, @@ -63310,7 +63310,7 @@ /area/engine/break_room) "cqz" = ( /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/cable{ icon_state = "1-4" }, @@ -64537,7 +64537,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "ctc" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile{ dir = 1 }, @@ -64547,7 +64547,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "ctd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile{ dir = 4 }, @@ -64808,7 +64808,7 @@ /obj/structure/cable{ icon_state = "1-8" }, -/obj/item/twohanded/required/kirbyplants/photosynthetic, +/obj/item/kirbyplants/photosynthetic, /obj/structure/disposalpipe/segment{ dir = 9 }, @@ -66739,7 +66739,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "cyc" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 6 }, @@ -66842,8 +66842,8 @@ }, /obj/item/electronics/airlock, /obj/item/electronics/airlock, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel, /area/engine/storage_shared) "cyq" = ( @@ -67734,7 +67734,7 @@ /turf/open/floor/plasteel/dark, /area/bridge) "cAd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/neutral/filled/corner{ dir = 4 }, @@ -70414,7 +70414,7 @@ /area/crew_quarters/locker) "cFb" = ( /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /obj/item/radio/intercom{ @@ -75050,7 +75050,7 @@ /turf/open/floor/plasteel, /area/engine/atmos) "cNx" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/machinery/camera{ c_tag = "Atmospherics - Control Room"; dir = 4 @@ -78128,7 +78128,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "cUc" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 4 }, @@ -78138,7 +78138,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) "cUd" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/sign/departments/holy{ pixel_x = -32 }, @@ -78405,7 +78405,7 @@ /turf/open/floor/plating, /area/maintenance/starboard/aft) "cUN" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/chief/private) "cUO" = ( @@ -80285,6 +80285,11 @@ }, /turf/open/space/basic, /area/engine/engineering) +"eCO" = ( +/obj/effect/decal/cleanable/dirt, +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/plasteel/dark, +/area/maintenance/starboard/aft) "eDP" = ( /obj/effect/turf_decal/trimline/blue/filled/corner{ dir = 8 @@ -80604,7 +80609,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel/dark, /area/science/circuit) "gIA" = ( @@ -80945,7 +80950,7 @@ /obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "kNb" = ( @@ -82038,6 +82043,10 @@ }, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/kitchen) +"vDO" = ( +/mob/living/simple_animal/opossum, +/turf/open/floor/plating, +/area/maintenance/fore) "vDW" = ( /obj/structure/cable{ icon_state = "1-2" @@ -107578,7 +107587,7 @@ aaA abY ayy acw -acw +vDO acw acw aeG @@ -135197,7 +135206,7 @@ bPp ccJ clR bQh -clN +eCO bPp bQh bYx diff --git a/_maps/map_files/Mafia/mafia_ayylmao.dmm b/_maps/map_files/Mafia/mafia_ayylmao.dmm new file mode 100644 index 0000000000..5d6f2aec5f --- /dev/null +++ b/_maps/map_files/Mafia/mafia_ayylmao.dmm @@ -0,0 +1,768 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"b" = ( +/turf/closed/indestructible{ + desc = "A wall with alien alloy plating."; + icon = 'icons/turf/walls/abductor_wall.dmi'; + icon_state = "abductor"; + name = "alien wall"; + smooth = 5 + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/fakespace, +/area/mafia) +"j" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien22" + }, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"l" = ( +/obj/structure/closet/abductor, +/turf/open/floor/plating/abductor, +/area/mafia) +"m" = ( +/obj/effect/landmark/mafia, +/obj/structure/bed/abductor, +/turf/open/floor/plating/abductor, +/area/mafia) +"n" = ( +/obj/effect/landmark/mafia, +/obj/structure/bed/abductor, +/turf/open/floor/plating/abductor2, +/area/mafia) +"o" = ( +/obj/structure/closet/abductor, +/turf/open/floor/plating/abductor2, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/turf/closed/indestructible/fakeglass, +/area/mafia) +"q" = ( +/turf/open/floor/plating/abductor, +/area/mafia) +"r" = ( +/turf/open/floor/plating/abductor2, +/area/mafia) +"t" = ( +/turf/open/floor/light/colour_cycle/dancefloor_a, +/area/mafia) +"u" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/turf/open/floor/light/colour_cycle/dancefloor_b, +/area/mafia) +"v" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"x" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/obj/effect/spawner/structure/window/plastitanium, +/turf/open/floor/plating/abductor2, +/area/mafia) +"z" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/fakespace, +/area/mafia) +"B" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien2" + }, +/area/mafia) +"D" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien15" + }, +/area/mafia) +"E" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien7" + }, +/area/mafia) +"F" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien12" + }, +/area/mafia) +"G" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien17" + }, +/area/mafia) +"H" = ( +/turf/open/space/basic, +/area/mafia) +"I" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien24" + }, +/area/mafia) +"J" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien18" + }, +/area/mafia) +"K" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien11" + }, +/area/mafia) +"L" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien14" + }, +/area/mafia) +"M" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien4" + }, +/area/mafia) +"N" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien21" + }, +/area/mafia) +"P" = ( +/turf/closed/indestructible/abductor, +/area/mafia) +"Q" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien5" + }, +/area/mafia) +"S" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien3" + }, +/area/mafia) +"U" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien23" + }, +/area/mafia) +"V" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien13" + }, +/area/mafia) +"W" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien20" + }, +/area/mafia) +"Y" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien8" + }, +/area/mafia) +"Z" = ( +/turf/closed/indestructible/abductor{ + icon_state = "alien10" + }, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +a +"} +(3,1,1) = {" +a +b +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +b +a +"} +(4,1,1) = {" +a +b +i +i +g +z +i +i +i +i +i +i +i +i +i +H +i +z +k +i +i +b +a +"} +(5,1,1) = {" +a +b +i +i +z +i +i +i +W +L +F +F +F +Z +P +i +i +i +h +i +i +b +a +"} +(6,1,1) = {" +a +b +i +i +i +W +L +Z +G +l +q +b +r +o +E +L +Z +P +i +i +i +b +a +"} +(7,1,1) = {" +a +b +i +i +i +N +o +r +p +m +q +x +r +n +x +q +l +B +i +i +i +b +a +"} +(8,1,1) = {" +a +b +i +i +i +U +n +r +b +b +q +b +r +b +b +q +m +M +i +i +i +b +a +"} +(9,1,1) = {" +a +b +i +i +W +G +x +r +r +x +q +x +r +x +q +q +x +E +P +i +i +b +a +"} +(10,1,1) = {" +a +b +i +i +N +l +x +b +x +x +x +x +x +x +x +b +x +o +B +i +i +b +a +"} +(11,1,1) = {" +a +b +i +i +j +m +q +q +q +x +t +t +t +x +r +r +r +n +S +i +i +b +a +"} +(12,1,1) = {" +a +b +i +i +j +b +x +b +x +x +t +u +t +x +x +b +x +b +S +i +i +b +a +"} +(13,1,1) = {" +a +b +i +i +j +n +r +r +r +x +t +t +t +x +q +q +q +m +S +i +i +b +a +"} +(14,1,1) = {" +a +b +i +i +U +o +x +b +x +x +x +x +x +x +x +b +x +l +M +i +i +b +a +"} +(15,1,1) = {" +a +b +i +i +I +J +x +q +q +x +r +x +q +x +r +r +x +Y +Q +i +i +b +a +"} +(16,1,1) = {" +a +b +i +i +i +N +m +q +b +b +r +b +q +b +b +r +n +B +i +i +i +b +a +"} +(17,1,1) = {" +a +b +i +i +i +U +l +q +x +n +r +x +q +m +x +r +o +M +i +i +i +b +a +"} +(18,1,1) = {" +a +b +i +i +i +I +D +K +J +o +r +b +q +l +Y +D +K +Q +i +i +i +b +a +"} +(19,1,1) = {" +a +b +i +i +z +i +i +i +I +D +V +V +V +K +Q +i +i +i +z +i +i +b +a +"} +(20,1,1) = {" +a +b +i +i +k +z +i +i +i +i +i +i +i +i +i +i +i +z +v +i +i +b +a +"} +(21,1,1) = {" +a +b +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +i +b +a +"} +(22,1,1) = {" +a +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_ball.dmm b/_maps/map_files/Mafia/mafia_ball.dmm new file mode 100644 index 0000000000..6ca955726b --- /dev/null +++ b/_maps/map_files/Mafia/mafia_ball.dmm @@ -0,0 +1,675 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"c" = ( +/turf/closed/wall/rust, +/area/mafia) +"d" = ( +/turf/open/floor/plating, +/area/mafia) +"e" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"f" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/mafia) +"j" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + max_integrity = 99999; + name = "Maintenance" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plating, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"l" = ( +/obj/structure/closet/cabinet{ + anchored = 1 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"m" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel/dark, +/area/mafia) +"n" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel, +/area/mafia) +"o" = ( +/obj/structure/closet/cabinet{ + anchored = 1 + }, +/turf/open/floor/plasteel, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/turf/closed/indestructible/fakeglass, +/area/mafia) +"q" = ( +/turf/open/floor/plasteel/dark, +/area/mafia) +"r" = ( +/turf/open/floor/plasteel, +/area/mafia) +"s" = ( +/turf/open/floor/fakespace, +/area/mafia) +"t" = ( +/turf/open/floor/plasteel/solarpanel, +/area/mafia) +"u" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/turf/open/floor/plasteel/solarpanel, +/area/mafia) +"v" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(3,1,1) = {" +a +a +a +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +a +a +a +"} +(4,1,1) = {" +a +a +a +c +g +h +d +d +d +d +d +e +d +d +d +d +d +h +k +c +a +a +a +"} +(5,1,1) = {" +a +a +a +c +h +d +d +e +a +a +j +a +j +a +a +d +d +i +h +c +a +a +a +"} +(6,1,1) = {" +a +a +a +c +i +a +a +j +a +l +q +a +r +o +a +j +a +a +d +c +a +a +a +"} +(7,1,1) = {" +a +a +c +c +d +a +o +r +p +m +q +p +r +n +p +q +l +a +d +c +c +a +a +"} +(8,1,1) = {" +a +a +c +d +d +a +n +r +a +a +q +a +r +a +a +q +m +a +d +d +c +a +a +"} +(9,1,1) = {" +a +a +c +d +a +a +p +r +r +p +q +p +r +p +q +q +p +a +a +d +c +a +a +"} +(10,1,1) = {" +a +a +c +d +a +l +p +a +p +p +p +p +p +p +p +a +p +o +a +d +c +a +a +"} +(11,1,1) = {" +a +a +c +d +j +m +q +q +q +p +s +t +s +p +r +r +r +n +j +e +c +a +a +"} +(12,1,1) = {" +a +a +c +e +a +a +p +a +p +p +t +u +t +p +p +a +p +a +a +d +c +a +a +"} +(13,1,1) = {" +a +a +c +d +j +n +r +r +r +p +s +t +s +p +q +q +q +m +j +d +c +a +a +"} +(14,1,1) = {" +a +a +c +d +a +o +p +a +p +p +p +p +p +p +p +a +p +l +a +i +c +a +a +"} +(15,1,1) = {" +a +a +c +d +a +a +p +q +q +p +r +p +q +p +r +r +p +a +a +d +c +a +a +"} +(16,1,1) = {" +a +a +c +f +d +a +m +q +a +a +r +a +q +a +a +r +n +a +d +d +c +a +a +"} +(17,1,1) = {" +a +a +c +c +d +a +l +q +p +n +r +p +q +m +p +r +o +a +d +c +c +a +a +"} +(18,1,1) = {" +a +a +a +c +d +a +a +j +a +o +r +a +q +l +a +j +a +a +d +c +a +a +a +"} +(19,1,1) = {" +a +a +a +c +h +i +d +d +a +a +j +a +j +a +a +d +e +d +h +c +a +a +a +"} +(20,1,1) = {" +a +a +a +c +k +h +d +d +e +d +d +d +d +d +d +d +d +h +v +c +a +a +a +"} +(21,1,1) = {" +a +a +a +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +a +a +a +"} +(22,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_gothic.dmm b/_maps/map_files/Mafia/mafia_gothic.dmm new file mode 100644 index 0000000000..a3c19fee85 --- /dev/null +++ b/_maps/map_files/Mafia/mafia_gothic.dmm @@ -0,0 +1,724 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"b" = ( +/turf/closed/wall/mineral/iron, +/area/mafia) +"c" = ( +/turf/closed/wall/rust, +/area/mafia) +"d" = ( +/turf/open/floor/plating, +/area/mafia) +"e" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"f" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/mafia) +"j" = ( +/turf/closed/indestructible/fakedoor, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"l" = ( +/obj/structure/closet/crate/coffin, +/turf/open/floor/carpet/red, +/area/mafia) +"m" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/carpet/red, +/area/mafia) +"n" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel/chapel{ + dir = 1 + }, +/area/mafia) +"o" = ( +/obj/structure/closet/crate/coffin, +/turf/open/floor/plasteel/chapel{ + dir = 4 + }, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/obj/effect/spawner/structure/window/plastitanium, +/turf/open/space/basic, +/area/mafia) +"q" = ( +/turf/open/floor/carpet/red, +/area/mafia) +"r" = ( +/turf/open/floor/plasteel/chapel{ + dir = 8 + }, +/area/mafia) +"t" = ( +/turf/open/floor/carpet/royalblack, +/area/mafia) +"u" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/turf/open/floor/carpet/royalblack, +/area/mafia) +"v" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"D" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel/chapel{ + dir = 4 + }, +/area/mafia) +"E" = ( +/turf/open/floor/plasteel/chapel{ + dir = 4 + }, +/area/mafia) +"H" = ( +/obj/structure/closet/cabinet{ + anchored = 1 + }, +/turf/open/floor/carpet/red, +/area/mafia) +"J" = ( +/obj/structure/closet/crate/coffin, +/turf/open/floor/plasteel/chapel{ + dir = 1 + }, +/area/mafia) +"M" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel/chapel{ + dir = 8 + }, +/area/mafia) +"N" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel/chapel, +/area/mafia) +"O" = ( +/turf/open/floor/plasteel/chapel, +/area/mafia) +"P" = ( +/obj/structure/closet/crate/coffin, +/turf/open/floor/plasteel/chapel, +/area/mafia) +"Q" = ( +/obj/structure/closet/crate/coffin, +/turf/open/floor/plasteel/chapel{ + dir = 8 + }, +/area/mafia) +"X" = ( +/turf/open/floor/plasteel/chapel{ + dir = 1 + }, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +a +"} +(3,1,1) = {" +a +b +b +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +b +b +a +"} +(4,1,1) = {" +a +b +b +c +g +h +d +d +d +d +d +e +d +d +d +d +d +h +k +c +b +b +a +"} +(5,1,1) = {" +a +b +b +c +h +d +d +e +b +b +j +b +j +b +b +d +d +i +h +c +b +b +a +"} +(6,1,1) = {" +a +b +b +c +i +b +b +j +b +l +q +b +X +Q +b +j +b +b +d +c +b +b +a +"} +(7,1,1) = {" +a +b +c +c +d +b +J +r +p +m +q +p +E +N +p +q +l +b +d +c +c +b +a +"} +(8,1,1) = {" +a +b +c +d +d +b +D +O +b +b +q +b +r +b +b +q +m +b +d +d +c +b +a +"} +(9,1,1) = {" +a +b +c +d +b +b +p +X +r +p +q +p +O +p +q +q +p +b +b +d +c +b +a +"} +(10,1,1) = {" +a +b +c +d +b +l +p +b +p +p +p +p +p +p +p +b +p +Q +b +d +c +b +a +"} +(11,1,1) = {" +a +b +c +d +j +m +q +q +q +p +t +t +t +p +X +r +E +N +j +e +c +b +a +"} +(12,1,1) = {" +a +b +c +e +b +b +p +b +p +p +t +u +t +p +p +b +p +b +b +d +c +b +a +"} +(13,1,1) = {" +a +b +c +d +j +n +r +E +O +p +t +t +t +p +q +q +q +m +j +d +c +b +a +"} +(14,1,1) = {" +a +b +c +d +b +o +p +b +p +p +p +p +p +p +p +b +p +l +b +i +c +b +a +"} +(15,1,1) = {" +a +b +c +d +b +b +p +q +q +p +X +p +q +p +E +O +p +b +b +d +c +b +a +"} +(16,1,1) = {" +a +b +c +f +d +b +m +q +b +b +E +b +q +b +b +X +M +b +d +d +c +b +a +"} +(17,1,1) = {" +a +b +c +c +d +b +l +q +p +n +r +p +q +m +p +E +P +b +d +c +c +b +a +"} +(18,1,1) = {" +a +b +b +c +d +b +b +j +b +o +O +b +q +H +b +j +b +b +d +c +b +b +a +"} +(19,1,1) = {" +a +b +b +c +h +i +d +d +b +b +j +b +j +b +b +d +e +d +h +c +b +b +a +"} +(20,1,1) = {" +a +b +b +c +k +h +d +d +e +d +d +d +d +d +d +d +d +h +v +c +b +b +a +"} +(21,1,1) = {" +a +b +b +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +b +b +a +"} +(22,1,1) = {" +a +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_lavaland.dmm b/_maps/map_files/Mafia/mafia_lavaland.dmm new file mode 100644 index 0000000000..8c58fb9054 --- /dev/null +++ b/_maps/map_files/Mafia/mafia_lavaland.dmm @@ -0,0 +1,976 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"c" = ( +/turf/closed/wall/rust, +/area/mafia) +"d" = ( +/turf/open/floor/plating, +/area/mafia) +"e" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"f" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/mafia) +"j" = ( +/obj/machinery/door/airlock/external{ + max_integrity = 99999; + name = "Maintenance" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plating, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"l" = ( +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/grass/fakebasalt, +/area/mafia) +"m" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/grass/fakebasalt, +/area/mafia) +"n" = ( +/obj/effect/landmark/mafia, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 9 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner, +/turf/open/floor/plasteel, +/area/mafia) +"o" = ( +/obj/effect/turf_decal/trimline/brown/filled/end{ + icon_state = "trimline_end_fill"; + dir = 4 + }, +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/plasteel, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/turf/closed/indestructible/fakeglass, +/area/mafia) +"q" = ( +/turf/open/floor/grass/fakebasalt, +/area/mafia) +"r" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 9 + }, +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/plasteel, +/area/mafia) +"s" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 9 + }, +/turf/open/floor/plasteel, +/area/mafia) +"t" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"u" = ( +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red, +/turf/open/floor/plasteel/dark, +/area/mafia) +"v" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"w" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner, +/turf/open/floor/plasteel, +/area/mafia) +"x" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/line, +/turf/open/floor/plasteel, +/area/mafia) +"y" = ( +/obj/effect/turf_decal/trimline/brown/filled/end{ + icon_state = "trimline_end_fill"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/mafia) +"z" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 5 + }, +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/plasteel, +/area/mafia) +"A" = ( +/obj/effect/landmark/mafia, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 6 + }, +/turf/open/floor/plasteel, +/area/mafia) +"B" = ( +/obj/effect/turf_decal/trimline/brown/filled/end{ + icon_state = "trimline_end_fill"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/mafia) +"C" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 4 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/mafia) +"D" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 10 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + icon_state = "trimline_corner_fill"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/mafia) +"E" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 1 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + icon_state = "trimline_corner_fill"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/mafia) +"F" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 5 + }, +/turf/open/floor/plasteel, +/area/mafia) +"G" = ( +/obj/effect/landmark/mafia, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 10 + }, +/turf/open/floor/plasteel, +/area/mafia) +"H" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 10 + }, +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/plasteel, +/area/mafia) +"I" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 6 + }, +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/plasteel, +/area/mafia) +"J" = ( +/obj/effect/landmark/mafia, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 6 + }, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + icon_state = "trimline_corner_fill"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/mafia) +"K" = ( +/obj/effect/turf_decal/trimline/brown/filled/end{ + icon_state = "trimline_end_fill"; + dir = 8 + }, +/obj/structure/closet{ + desc = "It's a storage unit. For mining stuff. Y'know."; + icon_state = "mining"; + name = "miner equipment locker" + }, +/obj/item/clothing/under/rank/cargo/miner/lavaland, +/turf/open/floor/plasteel, +/area/mafia) +"L" = ( +/obj/effect/landmark/mafia, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 5 + }, +/turf/open/floor/plasteel, +/area/mafia) +"M" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 10 + }, +/turf/open/floor/plasteel, +/area/mafia) +"N" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + icon_state = "trimline_corner_fill"; + dir = 4 + }, +/turf/open/floor/plasteel, +/area/mafia) +"O" = ( +/obj/effect/turf_decal/trimline/brown/filled/corner{ + icon_state = "trimline_corner_fill"; + dir = 8 + }, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 5 + }, +/turf/open/floor/plasteel, +/area/mafia) +"P" = ( +/obj/effect/turf_decal/trimline/brown/filled/end, +/turf/open/floor/plasteel, +/area/mafia) +"Q" = ( +/obj/effect/landmark/mafia, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 9 + }, +/turf/open/floor/plasteel, +/area/mafia) +"R" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"S" = ( +/obj/effect/turf_decal/trimline/brown/filled/end{ + icon_state = "trimline_end_fill"; + dir = 8 + }, +/turf/open/floor/plasteel, +/area/mafia) +"T" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/mafia) +"U" = ( +/obj/effect/turf_decal/trimline/brown/filled/line, +/obj/effect/turf_decal/trimline/brown/filled/corner{ + icon_state = "trimline_corner_fill"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/mafia) +"V" = ( +/obj/effect/turf_decal/trimline/brown/filled/line{ + icon_state = "trimline_fill"; + dir = 6 + }, +/turf/open/floor/plasteel, +/area/mafia) +"W" = ( +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"X" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"Y" = ( +/turf/closed/indestructible{ + icon = 'icons/turf/walls/reinforced_wall.dmi'; + icon_state = "r_wall"; + name = "reinforced wall" + }, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +a +"} +(3,1,1) = {" +a +Y +Y +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +Y +Y +a +"} +(4,1,1) = {" +a +Y +Y +c +g +h +d +d +d +d +d +e +d +d +d +d +d +h +k +c +Y +Y +a +"} +(5,1,1) = {" +a +Y +Y +c +h +d +d +e +Y +Y +j +Y +j +Y +Y +d +d +i +h +c +Y +Y +a +"} +(6,1,1) = {" +a +Y +Y +c +i +Y +Y +j +Y +l +q +Y +s +H +Y +j +Y +Y +d +c +Y +Y +a +"} +(7,1,1) = {" +a +Y +c +c +d +Y +r +M +p +m +q +p +w +A +p +q +l +Y +d +c +c +Y +a +"} +(8,1,1) = {" +a +Y +c +d +d +Y +L +N +Y +Y +q +Y +x +Y +Y +q +m +Y +d +d +c +Y +a +"} +(9,1,1) = {" +a +Y +c +d +Y +Y +p +O +P +p +q +p +y +p +q +q +p +Y +Y +d +c +Y +a +"} +(10,1,1) = {" +a +Y +c +d +Y +l +p +Y +p +p +p +p +p +p +p +Y +p +K +Y +d +c +Y +a +"} +(11,1,1) = {" +a +Y +c +d +j +m +q +q +q +p +q +u +q +p +B +C +C +J +j +e +c +Y +a +"} +(12,1,1) = {" +a +Y +c +e +Y +Y +p +Y +p +p +t +R +X +p +p +Y +p +Y +Y +d +c +Y +a +"} +(13,1,1) = {" +a +Y +c +d +j +n +C +C +P +p +q +W +q +p +q +q +q +m +j +d +c +Y +a +"} +(14,1,1) = {" +a +Y +c +d +Y +o +p +Y +p +p +p +p +p +p +p +Y +p +l +Y +i +c +Y +a +"} +(15,1,1) = {" +a +Y +c +d +Y +Y +p +q +q +p +S +p +q +p +B +D +p +Y +Y +d +c +Y +a +"} +(16,1,1) = {" +a +Y +c +f +d +Y +m +q +Y +Y +T +Y +q +Y +Y +E +G +Y +d +d +c +Y +a +"} +(17,1,1) = {" +a +Y +c +c +d +Y +l +q +p +Q +U +p +q +m +p +F +I +Y +d +c +c +Y +a +"} +(18,1,1) = {" +a +Y +Y +c +d +Y +Y +j +Y +z +V +Y +q +l +Y +j +Y +Y +d +c +Y +Y +a +"} +(19,1,1) = {" +a +Y +Y +c +h +i +d +d +Y +Y +j +Y +j +Y +Y +d +e +d +h +c +Y +Y +a +"} +(20,1,1) = {" +a +Y +Y +c +k +h +d +d +e +d +d +d +d +d +d +d +d +h +v +c +Y +Y +a +"} +(21,1,1) = {" +a +Y +Y +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +Y +Y +a +"} +(22,1,1) = {" +a +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +Y +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_reebe.dmm b/_maps/map_files/Mafia/mafia_reebe.dmm new file mode 100644 index 0000000000..e82174ff93 --- /dev/null +++ b/_maps/map_files/Mafia/mafia_reebe.dmm @@ -0,0 +1,658 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"b" = ( +/turf/open/indestructible/reebe_void, +/area/mafia) +"c" = ( +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/mafia) +"d" = ( +/obj/mafia_game_board, +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/mafia) +"e" = ( +/turf/closed/wall/clockwork, +/area/mafia) +"f" = ( +/turf/open/floor/clockwork/reebe, +/area/mafia) +"g" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"h" = ( +/obj/structure/window/reinforced/clockwork/fulltile, +/obj/structure/grille/ratvar, +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"i" = ( +/obj/structure/bed, +/obj/item/bedsheet/orange, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"j" = ( +/obj/structure/chair/brass{ + dir = 4 + }, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"k" = ( +/obj/structure/chair/brass, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"l" = ( +/obj/structure/chair/brass{ + dir = 8 + }, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"m" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/obj/structure/chair/brass, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"n" = ( +/obj/structure/chair/brass{ + icon_state = "brass_chair"; + dir = 1 + }, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"o" = ( +/obj/item/toy/plush/plushvar, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"p" = ( +/obj/structure/window/reinforced/clockwork/fulltile, +/obj/structure/grille/ratvar, +/turf/open/floor/clockwork/reebe, +/area/mafia) +"q" = ( +/obj/item/toy/plush/plushvar, +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +a +"} +(3,1,1) = {" +a +b +b +c +c +c +b +b +b +b +b +b +b +b +b +b +b +c +c +c +b +b +a +"} +(4,1,1) = {" +a +b +b +c +d +c +b +b +b +b +b +b +b +b +b +b +b +q +d +c +b +b +a +"} +(5,1,1) = {" +a +b +b +c +c +c +c +b +e +e +p +e +p +e +e +b +b +c +c +c +b +b +a +"} +(6,1,1) = {" +a +b +b +b +b +p +p +e +e +i +f +e +f +i +e +e +p +p +c +b +b +b +a +"} +(7,1,1) = {" +a +b +b +b +b +p +i +f +h +g +f +h +f +g +h +f +i +p +b +b +b +b +a +"} +(8,1,1) = {" +a +b +b +b +b +e +g +f +e +e +f +e +f +e +e +f +g +e +b +b +b +b +a +"} +(9,1,1) = {" +a +b +b +b +e +e +h +f +j +h +j +h +j +h +j +f +h +e +e +b +b +b +a +"} +(10,1,1) = {" +a +b +b +b +e +i +h +e +h +h +h +h +h +h +h +e +h +i +e +b +b +b +a +"} +(11,1,1) = {" +a +b +b +b +p +g +f +f +k +h +f +f +o +h +n +f +f +g +p +b +b +b +a +"} +(12,1,1) = {" +a +b +b +b +e +e +h +e +h +h +f +m +f +h +h +e +h +e +e +b +b +b +a +"} +(13,1,1) = {" +a +b +b +b +p +g +f +f +k +h +f +f +f +h +n +f +f +g +p +b +b +b +a +"} +(14,1,1) = {" +a +b +b +b +e +i +h +e +h +h +h +h +h +h +h +e +h +i +e +b +b +b +a +"} +(15,1,1) = {" +a +b +b +b +e +e +h +f +l +h +l +h +l +h +l +f +h +e +e +b +b +b +a +"} +(16,1,1) = {" +a +b +b +b +b +e +g +f +e +e +f +e +f +e +e +f +g +e +b +b +b +b +a +"} +(17,1,1) = {" +a +b +b +b +b +p +i +f +h +g +f +h +f +g +h +f +i +p +b +b +b +b +a +"} +(18,1,1) = {" +a +b +b +b +b +p +p +e +e +f +i +e +i +f +e +e +p +p +c +b +b +b +a +"} +(19,1,1) = {" +a +b +b +c +c +c +c +b +e +e +p +e +p +e +e +b +b +c +c +c +b +b +a +"} +(20,1,1) = {" +a +b +b +c +d +c +b +b +b +b +b +b +b +b +b +b +b +c +d +c +b +b +a +"} +(21,1,1) = {" +a +b +b +c +c +c +b +b +b +b +b +b +b +b +b +b +b +c +c +c +b +b +a +"} +(22,1,1) = {" +a +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +b +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_snow.dmm b/_maps/map_files/Mafia/mafia_snow.dmm new file mode 100644 index 0000000000..a47440f00e --- /dev/null +++ b/_maps/map_files/Mafia/mafia_snow.dmm @@ -0,0 +1,755 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"d" = ( +/turf/open/floor/plating, +/area/mafia) +"e" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"f" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/mafia) +"j" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + max_integrity = 99999; + name = "Maintenance" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plating, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"l" = ( +/obj/item/bedsheet/brown, +/obj/structure/bed, +/turf/open/floor/holofloor/wood, +/area/mafia) +"m" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/holofloor/wood, +/area/mafia) +"n" = ( +/obj/item/bedsheet/green, +/obj/structure/bed, +/turf/open/floor/holofloor/wood, +/area/mafia) +"o" = ( +/obj/item/bedsheet/blue, +/obj/structure/bed, +/turf/open/floor/holofloor/wood, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/turf/closed/indestructible/fakeglass, +/area/mafia) +"q" = ( +/turf/open/floor/plasteel/dark, +/area/mafia) +"r" = ( +/turf/open/floor/plasteel, +/area/mafia) +"s" = ( +/turf/closed/wall/ice, +/area/mafia) +"t" = ( +/turf/open/floor/holofloor/snow, +/area/mafia) +"u" = ( +/obj/structure/statue/plasma/scientist{ + anchored = 1 + }, +/turf/open/floor/holofloor/snow, +/area/mafia) +"v" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/turf/open/floor/holofloor/snow, +/area/mafia) +"w" = ( +/turf/open/lava/plasma, +/area/mafia) +"x" = ( +/obj/machinery/door/airlock/external{ + max_integrity = 9999; + opacity = 0 + }, +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plasteel/dark, +/area/mafia) +"y" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/holofloor/snow, +/area/mafia) +"z" = ( +/obj/structure/lattice/catwalk, +/turf/open/lava/plasma, +/area/mafia) +"A" = ( +/obj/machinery/door/airlock/external{ + max_integrity = 9999 + }, +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plasteel, +/area/mafia) +"B" = ( +/obj/effect/landmark/mafia, +/obj/structure/lattice/catwalk, +/turf/open/lava/plasma, +/area/mafia) +"C" = ( +/obj/mafia_game_board, +/turf/open/floor/holofloor/snow, +/area/mafia) +"D" = ( +/obj/structure/closet/crate/science, +/obj/item/clothing/suit/hooded/wintercoat, +/obj/item/clothing/shoes/winterboots, +/turf/open/floor/holofloor/snow, +/area/mafia) +"E" = ( +/obj/structure/lattice/catwalk, +/obj/structure/closet/crate/critter, +/obj/item/clothing/suit/hooded/wintercoat/miner, +/obj/item/clothing/shoes/winterboots, +/turf/open/lava/plasma, +/area/mafia) +"F" = ( +/turf/open/floor/holofloor/wood, +/area/mafia) +"G" = ( +/obj/item/bedsheet/orange, +/obj/structure/bed, +/turf/open/floor/holofloor/wood, +/area/mafia) +"H" = ( +/obj/item/bedsheet/black, +/obj/structure/bed, +/turf/open/floor/holofloor/wood, +/area/mafia) +"I" = ( +/obj/item/bedsheet/red, +/obj/structure/bed, +/turf/open/floor/holofloor/wood, +/area/mafia) +"J" = ( +/turf/open/floor/plating/snowed/smoothed, +/area/mafia) +"K" = ( +/turf/closed/indestructible/rock/snow, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +s +K +K +K +K +K +K +K +K +K +K +a +"} +(3,1,1) = {" +a +a +a +s +s +s +s +s +s +s +s +s +w +w +t +w +w +w +w +w +w +K +a +"} +(4,1,1) = {" +a +a +a +s +g +h +d +d +d +d +d +s +t +w +w +w +w +w +C +w +w +K +a +"} +(5,1,1) = {" +a +a +a +s +h +d +d +e +s +s +j +s +p +p +p +w +w +w +w +w +w +K +a +"} +(6,1,1) = {" +a +a +a +s +i +s +s +j +s +H +F +s +t +D +p +p +p +p +w +w +w +K +a +"} +(7,1,1) = {" +a +a +s +s +d +s +o +F +p +m +q +p +t +y +p +z +E +p +w +t +w +K +a +"} +(8,1,1) = {" +a +a +s +d +d +s +m +r +s +s +q +s +t +p +p +z +B +p +w +w +w +K +a +"} +(9,1,1) = {" +a +a +s +d +s +s +p +r +r +p +q +p +t +p +z +z +p +p +p +w +w +K +a +"} +(10,1,1) = {" +a +a +s +d +s +l +p +s +p +p +p +p +p +p +p +p +p +D +p +w +w +K +a +"} +(11,1,1) = {" +a +a +s +d +j +m +F +q +q +x +J +t +t +p +t +t +t +y +p +w +t +K +a +"} +(12,1,1) = {" +a +a +s +e +s +a +p +s +p +p +u +v +t +p +p +p +p +p +p +w +w +K +a +"} +(13,1,1) = {" +a +a +s +d +j +m +F +r +r +A +J +t +t +p +t +t +t +y +p +w +w +K +a +"} +(14,1,1) = {" +a +a +s +d +s +n +p +s +p +p +p +p +p +p +p +p +p +D +p +w +w +K +a +"} +(15,1,1) = {" +a +a +s +d +s +s +p +q +q +p +r +p +t +p +z +z +p +p +p +w +w +K +a +"} +(16,1,1) = {" +a +a +s +f +d +s +m +q +s +s +r +s +t +p +p +z +B +p +w +w +w +K +a +"} +(17,1,1) = {" +a +a +s +s +d +s +G +F +p +m +r +p +t +y +p +z +E +p +w +w +w +K +a +"} +(18,1,1) = {" +a +a +a +s +d +s +s +j +s +I +F +s +t +D +p +p +p +p +w +t +w +K +a +"} +(19,1,1) = {" +a +a +a +s +h +i +d +d +s +s +j +s +p +p +p +t +w +w +w +w +w +K +a +"} +(20,1,1) = {" +a +a +a +s +k +h +d +d +e +d +d +s +t +w +w +w +w +w +C +w +w +K +a +"} +(21,1,1) = {" +a +a +a +s +s +s +s +s +s +s +s +s +w +w +w +w +w +w +w +w +w +K +a +"} +(22,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +s +K +K +K +K +K +K +K +K +K +K +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_spiderclan.dmm b/_maps/map_files/Mafia/mafia_spiderclan.dmm new file mode 100644 index 0000000000..89771212b8 --- /dev/null +++ b/_maps/map_files/Mafia/mafia_spiderclan.dmm @@ -0,0 +1,690 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"b" = ( +/obj/structure/closet/cabinet{ + anchored = 1 + }, +/obj/item/reagent_containers/food/snacks/sashimi, +/turf/open/floor/carpet/black, +/area/mafia) +"c" = ( +/turf/closed/wall/rust, +/area/mafia) +"d" = ( +/turf/open/floor/plating, +/area/mafia) +"e" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"f" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/mafia) +"j" = ( +/turf/closed/wall/mineral/wood{ + desc = "A door that goes nowhere. How kafkaesque."; + icon = 'icons/obj/doors/mineral_doors.dmi'; + icon_state = "paperframe"; + name = "Door" + }, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"m" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/wood, +/area/mafia) +"n" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/carpet/black, +/area/mafia) +"o" = ( +/obj/structure/closet/cabinet{ + anchored = 1 + }, +/obj/item/reagent_containers/food/snacks/sashimi, +/turf/open/floor/wood, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/turf/closed/indestructible/fakeglass{ + icon = 'icons/obj/smooth_structures/paperframes.dmi'; + icon_state = "paper" + }, +/area/mafia) +"q" = ( +/turf/open/floor/wood, +/area/mafia) +"r" = ( +/turf/open/floor/carpet/black, +/area/mafia) +"t" = ( +/turf/open/floor/plating/beach/sand, +/area/mafia) +"u" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/turf/open/floor/plating/beach/sand, +/area/mafia) +"v" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"B" = ( +/obj/structure/showcase{ + density = 0; + desc = "Welp, only one way to recover your honour."; + icon = 'icons/obj/items_and_weapons.dmi'; + icon_state = "katana"; + name = "seppuku katana" + }, +/turf/open/floor/plating/beach/sand, +/area/mafia) +"S" = ( +/turf/closed/wall/mineral/wood, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +a +"} +(3,1,1) = {" +a +S +S +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +S +S +a +"} +(4,1,1) = {" +a +S +S +c +g +h +d +d +d +d +d +e +d +d +d +d +d +h +k +c +S +S +a +"} +(5,1,1) = {" +a +S +S +c +h +d +d +e +S +S +j +S +j +S +S +d +d +i +h +c +S +S +a +"} +(6,1,1) = {" +a +S +S +c +i +S +S +j +S +o +q +S +r +b +S +j +S +S +d +c +S +S +a +"} +(7,1,1) = {" +a +S +c +c +d +S +b +r +p +m +q +p +r +n +p +q +o +S +d +c +c +S +a +"} +(8,1,1) = {" +a +S +c +d +d +S +n +r +S +S +q +S +r +S +S +q +m +S +d +d +c +S +a +"} +(9,1,1) = {" +a +S +c +d +S +S +p +r +r +p +q +p +r +p +q +q +p +S +S +d +c +S +a +"} +(10,1,1) = {" +a +S +c +d +S +o +p +S +p +p +p +p +p +p +p +S +p +b +S +d +c +S +a +"} +(11,1,1) = {" +a +S +c +d +j +m +q +q +q +p +t +t +t +p +r +r +r +n +j +e +c +S +a +"} +(12,1,1) = {" +a +S +c +e +S +S +p +S +p +p +t +u +B +p +p +S +p +S +S +d +c +S +a +"} +(13,1,1) = {" +a +S +c +d +j +n +r +r +r +p +t +t +t +p +q +q +q +m +j +d +c +S +a +"} +(14,1,1) = {" +a +S +c +d +S +b +p +S +p +p +p +p +p +p +p +S +p +o +S +i +c +S +a +"} +(15,1,1) = {" +a +S +c +d +S +S +p +q +q +p +r +p +q +p +r +r +p +S +S +d +c +S +a +"} +(16,1,1) = {" +a +S +c +f +d +S +m +q +S +S +r +S +q +S +S +r +n +S +d +d +c +S +a +"} +(17,1,1) = {" +a +S +c +c +d +S +o +q +p +n +r +p +q +m +p +r +b +S +d +c +c +S +a +"} +(18,1,1) = {" +a +S +S +c +d +S +S +j +S +b +r +S +q +o +S +j +S +S +d +c +S +S +a +"} +(19,1,1) = {" +a +S +S +c +h +i +d +d +S +S +j +S +j +S +S +d +e +d +h +c +S +S +a +"} +(20,1,1) = {" +a +S +S +c +k +h +d +d +e +d +d +d +d +d +d +d +d +h +v +c +S +S +a +"} +(21,1,1) = {" +a +S +S +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +S +S +a +"} +(22,1,1) = {" +a +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +S +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/Mafia/mafia_syndie.dmm b/_maps/map_files/Mafia/mafia_syndie.dmm new file mode 100644 index 0000000000..d56c3cc0c6 --- /dev/null +++ b/_maps/map_files/Mafia/mafia_syndie.dmm @@ -0,0 +1,869 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/closed/indestructible/riveted, +/area/mafia) +"b" = ( +/obj/structure/closet/syndicate{ + desc = "A storage closet for syndicate conflict resolution operatives."; + name = "red closet" + }, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/clothing/under/syndicate/tacticool/skirt, +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"c" = ( +/turf/closed/wall/rust, +/area/mafia) +"d" = ( +/turf/open/floor/plating, +/area/mafia) +"e" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"f" = ( +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"g" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/mafia) +"h" = ( +/obj/structure/grille/indestructable, +/turf/open/floor/plating, +/area/mafia) +"i" = ( +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/mafia) +"j" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + max_integrity = 99999; + name = "Maintenance" + }, +/obj/effect/mapping_helpers/airlock/locked, +/turf/open/floor/plating, +/area/mafia) +"k" = ( +/obj/mafia_game_board, +/turf/open/floor/plating, +/area/mafia) +"l" = ( +/obj/structure/closet/syndicate{ + desc = "A storage closet for syndicate conflict resolution operatives."; + name = "red closet" + }, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/clothing/under/syndicate/tacticool/skirt, +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"m" = ( +/obj/structure/closet/syndicate{ + desc = "A storage closet for syndicate conflict resolution operatives."; + name = "red closet" + }, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/clothing/under/syndicate/tacticool/skirt, +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"n" = ( +/obj/effect/landmark/mafia, +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"o" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"p" = ( +/obj/machinery/door/poddoor/preopen{ + desc = "When it's time to sleep, the lights will go out. Remember - no one in space can hear you scream."; + id = "mafia"; + max_integrity = 99999; + name = "Station Night Shutters" + }, +/obj/effect/spawner/structure/window/plastitanium, +/turf/open/space/basic, +/area/mafia) +"q" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/structure/chair/office{ + dir = 1; + name = "tactical swivel chair" + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"r" = ( +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"s" = ( +/turf/open/floor/mineral/plastitanium/red, +/area/mafia) +"t" = ( +/turf/open/floor/circuit/red, +/area/mafia) +"u" = ( +/obj/effect/baseturf_helper/asteroid, +/obj/effect/landmark/mafia/town_center, +/obj/structure/chair, +/turf/open/floor/circuit/red, +/area/mafia) +"v" = ( +/obj/mafia_game_board, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/mafia) +"w" = ( +/turf/closed/indestructible/syndicate, +/area/mafia) +"x" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/structure/chair/office{ + dir = 4; + name = "tactical swivel chair" + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"y" = ( +/obj/structure/chair/office{ + dir = 2; + name = "tactical swivel chair" + }, +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"z" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/structure/chair/office{ + dir = 2; + name = "tactical swivel chair" + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"A" = ( +/obj/structure/chair/office{ + dir = 8; + name = "tactical swivel chair" + }, +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"B" = ( +/obj/structure/chair/office{ + dir = 4; + name = "tactical swivel chair" + }, +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"C" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/structure/chair/office{ + dir = 8; + name = "tactical swivel chair" + }, +/turf/open/floor/plasteel/dark, +/area/mafia) +"E" = ( +/obj/structure/chair/office{ + dir = 1; + name = "tactical swivel chair" + }, +/turf/open/floor/mineral/plastitanium, +/area/mafia) +"F" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/structure/closet/syndicate{ + desc = "A storage closet for syndicate conflict resolution operatives."; + name = "red closet" + }, +/obj/item/clothing/under/syndicate/tacticool, +/obj/item/clothing/under/syndicate/tacticool/skirt, +/turf/open/floor/plasteel/dark, +/area/mafia) +"G" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/item/clothing/under/syndicate/tacticool, +/obj/structure/closet/syndicate{ + desc = "A storage closet for syndicate conflict resolution operatives."; + name = "red closet" + }, +/obj/item/clothing/under/syndicate/tacticool/skirt, +/turf/open/floor/plasteel/dark, +/area/mafia) +"H" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/landmark/mafia, +/turf/open/floor/plasteel/dark, +/area/mafia) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +a +"} +(3,1,1) = {" +a +w +w +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +w +w +a +"} +(4,1,1) = {" +a +w +w +c +g +h +d +d +d +d +d +e +d +d +d +d +d +h +k +c +w +w +a +"} +(5,1,1) = {" +a +w +w +c +h +d +d +e +w +w +j +w +j +w +w +d +d +i +h +c +w +w +a +"} +(6,1,1) = {" +a +w +w +c +i +w +w +j +w +b +r +w +o +F +w +j +w +w +d +c +w +w +a +"} +(7,1,1) = {" +a +w +c +c +d +w +l +o +p +n +r +p +o +H +p +r +b +w +d +c +c +w +a +"} +(8,1,1) = {" +a +w +c +d +d +w +H +o +w +w +r +w +o +w +w +r +n +w +d +d +c +w +a +"} +(9,1,1) = {" +a +w +c +d +w +w +p +o +x +p +B +p +x +p +B +r +p +w +w +d +c +w +a +"} +(10,1,1) = {" +a +w +c +d +w +b +p +w +p +p +p +p +p +p +p +w +p +m +w +d +c +w +a +"} +(11,1,1) = {" +a +w +c +d +j +n +r +r +y +p +s +t +s +p +q +o +o +H +j +e +c +w +a +"} +(12,1,1) = {" +a +w +c +e +w +w +p +w +p +p +t +u +t +p +p +w +p +w +w +d +c +w +a +"} +(13,1,1) = {" +a +w +c +d +j +H +o +o +z +p +s +t +s +p +E +r +r +n +j +d +c +w +a +"} +(14,1,1) = {" +a +w +c +d +w +l +p +w +p +p +p +p +p +p +p +w +p +b +w +i +c +w +a +"} +(15,1,1) = {" +a +w +c +d +w +w +p +r +A +p +C +p +A +p +C +o +p +w +w +d +c +w +a +"} +(16,1,1) = {" +a +w +c +f +d +w +n +r +w +w +o +w +r +w +w +o +H +w +d +d +c +w +a +"} +(17,1,1) = {" +a +w +c +c +d +w +b +r +p +H +o +p +r +n +p +o +G +w +d +c +c +w +a +"} +(18,1,1) = {" +a +w +w +c +d +w +w +j +w +F +o +w +r +b +w +j +w +w +d +c +w +w +a +"} +(19,1,1) = {" +a +w +w +c +h +i +d +d +w +w +j +w +j +w +w +d +e +d +h +c +w +w +a +"} +(20,1,1) = {" +a +w +w +c +k +h +d +d +e +d +d +d +d +d +d +d +d +h +v +c +w +w +a +"} +(21,1,1) = {" +a +w +w +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +c +w +w +a +"} +(22,1,1) = {" +a +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +w +a +"} +(23,1,1) = {" +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +a +"} diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index c08670c2c0..fdc313c30a 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -226,7 +226,7 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /turf/open/floor/plasteel, @@ -245,7 +245,7 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/plasteel, /area/security/prison) "aaE" = ( @@ -793,10 +793,16 @@ /turf/open/floor/plating, /area/security/prison) "abN" = ( -/turf/open/floor/plating{ - icon_state = "platingdmg3" +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" }, -/area/security/prison) +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/plating, +/area/maintenance/solars/port/fore) "abO" = ( /obj/structure/cable{ icon_state = "1-4" @@ -922,7 +928,7 @@ /area/security/prison) "acb" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel, /area/security/prison) "acc" = ( @@ -954,6 +960,9 @@ /area/security/prison) "acg" = ( /obj/machinery/light/small, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, /turf/open/floor/plating{ icon_state = "panelscorched" }, @@ -962,18 +971,22 @@ /obj/effect/turf_decal/stripes/line{ dir = 4 }, -/turf/open/floor/plating, -/area/security/prison) -"aci" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, /obj/machinery/door/airlock/external{ name = "Security External Airlock"; req_access_txt = "1" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, /turf/open/floor/plating, /area/security/prison) +"aci" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/door/airlock/external{ + req_one_access_txt = "13,8" + }, +/turf/open/space, +/area/maintenance/starboard/fore) "acj" = ( /obj/machinery/light/small{ dir = 1 @@ -1224,7 +1237,7 @@ /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-13" }, /turf/open/floor/plasteel, @@ -2047,14 +2060,12 @@ /turf/open/floor/plating, /area/maintenance/solars/port/fore) "aef" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ icon_state = "1-2" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, /turf/open/floor/plating, /area/maintenance/solars/port/fore) "aeg" = ( @@ -2292,8 +2303,7 @@ /turf/open/floor/plating, /area/crew_quarters/fitness/recreation) "aeD" = ( -/obj/machinery/door/airlock/external, -/turf/open/floor/plating, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "aeE" = ( /obj/effect/spawner/structure/window/reinforced, @@ -2311,9 +2321,6 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, /turf/open/floor/plating, /area/maintenance/solars/port/fore) "aeH" = ( @@ -2668,7 +2675,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/structure/sign/warning/securearea{ @@ -2992,7 +2999,7 @@ /turf/open/floor/plating, /area/maintenance/solars/port/fore) "afF" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -3116,9 +3123,6 @@ }, /turf/open/floor/plasteel, /area/security/prison) -"afQ" = ( -/turf/open/floor/plating, -/area/hallway/primary/port) "afR" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 @@ -3188,8 +3192,14 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) "afZ" = ( -/obj/structure/girder, -/turf/open/floor/plating, +/obj/machinery/camera{ + c_tag = "Arrivals - Lounge"; + dir = 4 + }, +/obj/structure/chair/comfy{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "aga" = ( /obj/effect/turf_decal/tile/neutral{ @@ -3670,8 +3680,10 @@ /turf/open/floor/plasteel/dark, /area/security/prison) "agQ" = ( -/obj/item/electronics/airlock, -/turf/open/floor/plating, +/obj/machinery/holopad{ + pixel_y = -15 + }, +/turf/open/floor/carpet, /area/hallway/primary/port) "agR" = ( /obj/machinery/airalarm{ @@ -4281,9 +4293,7 @@ }, /area/maintenance/fore) "ahT" = ( -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, +/turf/open/floor/carpet, /area/hallway/primary/port) "ahU" = ( /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -4802,13 +4812,14 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) "aiT" = ( -/obj/effect/decal/cleanable/oil{ - icon_state = "floor5" +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/turf/open/floor/plating{ - icon_state = "panelscorched" +/obj/machinery/light{ + dir = 4 }, -/area/hallway/primary/port) +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) "aiU" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, /obj/effect/turf_decal/tile/neutral{ @@ -4830,9 +4841,13 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) "aiW" = ( -/turf/open/floor/plating{ - icon_state = "platingdmg1" +/obj/structure/chair/comfy{ + dir = 8 }, +/obj/machinery/light{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "aiX" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -4936,12 +4951,11 @@ /turf/open/floor/plating, /area/maintenance/port/fore) "ajk" = ( -/obj/structure/shuttle/engine/propulsion/right{ - dir = 4 - }, -/turf/open/floor/plating{ - icon_state = "platingdmg3" +/obj/structure/table/wood, +/obj/item/flashlight/lamp/green{ + pixel_y = 3 }, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "ajl" = ( /obj/item/soap/deluxe, @@ -5035,8 +5049,10 @@ /turf/open/floor/plasteel/dark, /area/security/warden) "ajs" = ( -/obj/item/stack/sheet/metal/ten, -/turf/open/floor/plating, +/obj/item/kirbyplants{ + icon_state = "plant-08" + }, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "ajt" = ( /obj/structure/closet{ @@ -5059,8 +5075,20 @@ /turf/open/floor/plasteel/dark, /area/security/warden) "aju" = ( -/obj/item/stack/sheet/mineral/wood/twenty, -/turf/open/floor/plating, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/cable/yellow{ + icon_state = "2-8" + }, +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel, /area/hallway/primary/port) "ajv" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ @@ -6921,9 +6949,17 @@ /turf/open/floor/plating, /area/maintenance/fore) "amv" = ( -/obj/item/stack/sheet/metal/ten, -/obj/item/wrench, -/turf/open/floor/plating, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel, /area/hallway/primary/port) "amw" = ( /obj/structure/window/reinforced, @@ -6961,10 +6997,6 @@ /obj/structure/window/reinforced, /turf/open/floor/plasteel/dark, /area/crew_quarters/fitness/recreation) -"amB" = ( -/obj/effect/decal/cleanable/blood/old, -/turf/open/floor/plating, -/area/hallway/primary/port) "amC" = ( /obj/structure/chair{ dir = 4 @@ -6982,15 +7014,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/crew_quarters/fitness/recreation) -"amG" = ( -/obj/machinery/light/small{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "amH" = ( /obj/machinery/door/airlock/external{ req_one_access_txt = "13,8" @@ -10300,6 +10323,7 @@ /turf/open/floor/carpet, /area/crew_quarters/dorms) "atd" = ( +/mob/living/simple_animal/opossum, /turf/open/floor/plating{ icon_state = "panelscorched" }, @@ -11528,19 +11552,15 @@ /turf/open/floor/plating/airless, /area/space/nearstation) "avJ" = ( -/obj/machinery/door/airlock/external, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 +/obj/structure/sign/warning/vacuum/external{ + pixel_x = 32 }, /turf/open/floor/plating, -/area/maintenance/port/fore) +/area/maintenance/starboard/fore) "avK" = ( /obj/structure/sign/warning/vacuum/external{ pixel_y = 32 }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, /turf/open/floor/plating, /area/maintenance/port/fore) "avL" = ( @@ -13096,7 +13116,7 @@ /turf/open/space, /area/space/nearstation) "aze" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/decal/cleanable/cobweb/cobweb2, @@ -14391,7 +14411,7 @@ /area/maintenance/starboard/fore) "aBD" = ( /obj/effect/decal/cleanable/cobweb, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20"; pixel_y = 3 }, @@ -15603,7 +15623,7 @@ /area/crew_quarters/dorms) "aDZ" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel, /area/crew_quarters/dorms) "aEa" = ( @@ -17087,8 +17107,8 @@ /obj/effect/turf_decal/bot{ dir = 1 }, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel{ dir = 1 }, @@ -18152,7 +18172,7 @@ name = "Law Office APC"; pixel_y = 24 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/wood, @@ -19168,7 +19188,7 @@ c_tag = "AI Upload Chamber - Fore"; network = list("aiupload") }, -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 10 }, /turf/open/floor/plasteel/dark, @@ -21182,7 +21202,7 @@ /area/crew_quarters/locker) "aPI" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel, /area/crew_quarters/locker) "aPJ" = ( @@ -21677,7 +21697,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = -27 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/effect/turf_decal/tile/neutral{ @@ -23960,7 +23980,7 @@ /turf/open/floor/plating, /area/hallway/secondary/entry) "aVt" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-13" }, /obj/effect/turf_decal/stripes/line{ @@ -24081,9 +24101,10 @@ icon_state = "map-right-MS"; pixel_y = 32 }, -/turf/open/floor/plasteel/white/corner{ +/obj/effect/turf_decal/tile/blue{ dir = 4 }, +/turf/open/floor/plasteel, /area/hallway/secondary/entry) "aVE" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -24308,7 +24329,7 @@ /obj/machinery/airalarm{ pixel_y = 23 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/effect/turf_decal/tile/neutral{ @@ -24419,7 +24440,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = 27 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/item/radio/intercom{ @@ -25668,7 +25689,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "aYF" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/effect/turf_decal/stripes/line{ @@ -26198,7 +26219,7 @@ charge = 100; maxcharge = 15000 }, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -31733,28 +31754,22 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, +/turf/open/floor/plasteel, /area/hallway/secondary/entry) "bjX" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/obj/machinery/door/firedoor, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/turf/open/floor/plasteel/cafeteria, +/area/hallway/secondary/entry) "bjY" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/light{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, /area/hallway/primary/port) "bjZ" = ( @@ -31814,6 +31829,12 @@ dir = 1 }, /obj/structure/cable, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/port) "bke" = ( @@ -31826,6 +31847,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/port) "bkf" = ( @@ -31845,6 +31869,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/port) "bkg" = ( @@ -32650,6 +32677,10 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/light{ + dir = 1; + light_color = "#cee5d2" + }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/foyer) "blC" = ( @@ -32823,39 +32854,23 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/corner, /obj/structure/cable/yellow{ icon_state = "1-2" }, /obj/structure/cable/yellow{ icon_state = "2-4" }, -/turf/open/floor/plasteel/white/corner, +/turf/open/floor/plasteel, /area/hallway/secondary/entry) "blU" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/door/firedoor, /obj/structure/cable/yellow{ icon_state = "4-8" }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) -"blV" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/obj/effect/turf_decal/stripes/line, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) "blW" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -32864,7 +32879,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, @@ -32875,7 +32889,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, @@ -32890,7 +32903,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, @@ -32904,7 +32916,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, @@ -32918,7 +32929,6 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, @@ -32931,10 +32941,13 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "bmc" = ( @@ -32944,8 +32957,8 @@ /obj/structure/cable/yellow{ icon_state = "4-8" }, -/obj/effect/turf_decal/stripes/corner{ - dir = 1 +/obj/effect/turf_decal/tile/neutral{ + dir = 8 }, /turf/open/floor/plasteel, /area/hallway/primary/port) @@ -32956,6 +32969,9 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/port) "bme" = ( @@ -33830,30 +33846,9 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) -"bnL" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/newscaster{ - pixel_x = 28; - pixel_y = 1 - }, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel/white/corner, -/area/hallway/secondary/entry) "bnR" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/bot, -/obj/structure/sign/mining, -/turf/open/floor/plasteel, +/obj/structure/chair/comfy, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "bnS" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -33863,7 +33858,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, /turf/open/floor/plasteel, @@ -33878,6 +33873,9 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/port) "bnU" = ( @@ -34956,29 +34954,19 @@ "bqc" = ( /obj/machinery/holopad, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/machinery/light{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel, /area/hallway/secondary/entry) "bqd" = ( -/obj/machinery/door/firedoor, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line, /obj/structure/cable/yellow{ icon_state = "4-8" }, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, /area/hallway/primary/port) "bqj" = ( @@ -34987,7 +34975,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, /turf/open/floor/plasteel, @@ -36130,13 +36118,9 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "bsf" = ( -/obj/machinery/light, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat/foyer) "bsg" = ( @@ -36217,16 +36201,10 @@ /area/hallway/secondary/entry) "bso" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, +/turf/open/floor/plasteel, /area/hallway/secondary/entry) "bsu" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ @@ -36236,7 +36214,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, /turf/open/floor/plasteel, @@ -36248,6 +36226,7 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "bsw" = ( @@ -36994,7 +36973,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "btR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /obj/effect/turf_decal/stripes/line{ @@ -37020,29 +36999,25 @@ /area/hallway/secondary/entry) "btY" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/disposalpipe/segment, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 +/obj/structure/disposalpipe/segment{ + dir = 9 }, -/obj/machinery/camera{ - c_tag = "Port Primary Hallway - Port"; - dir = 4 +/obj/effect/turf_decal/tile/neutral{ + dir = 8 }, /turf/open/floor/plasteel, /area/hallway/primary/port) "btZ" = ( -/obj/machinery/light{ - dir = 4 - }, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "bua" = ( @@ -37703,16 +37678,10 @@ /turf/closed/wall, /area/aisat) "bvu" = ( -/obj/structure/table/wood, /obj/machinery/light/small{ dir = 8 }, -/obj/item/radio/off{ - pixel_y = 4 - }, -/obj/item/screwdriver{ - pixel_y = 10 - }, +/obj/machinery/announcement_system, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bvv" = ( @@ -37778,7 +37747,7 @@ /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bvB" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20" }, /obj/effect/turf_decal/stripes/line{ @@ -37847,26 +37816,23 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bvK" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bvL" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 +/obj/structure/cable/yellow{ + icon_state = "2-4" }, /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, /area/hallway/secondary/entry) "bvT" = ( /obj/structure/disposalpipe/segment{ @@ -37878,15 +37844,16 @@ /turf/open/floor/plating, /area/maintenance/department/science/xenobiology) "bvV" = ( -/obj/structure/extinguisher_cabinet{ - pixel_x = 27 - }, /obj/effect/turf_decal/tile/neutral{ dir = 4 }, +/obj/structure/cable/yellow{ + icon_state = "1-8" + }, /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "bvW" = ( @@ -37987,12 +37954,8 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hop) "bwl" = ( -/obj/machinery/door/airlock/hatch{ - name = "MiniSat Space Access Airlock"; - req_one_access_txt = "32;19" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +/obj/effect/turf_decal/stripes/line{ + dir = 4 }, /turf/open/floor/plasteel/dark, /area/engine/break_room) @@ -38552,9 +38515,6 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /turf/open/floor/plasteel/dark, /area/engine/break_room) "bxn" = ( @@ -38677,28 +38637,36 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/floor/plasteel, +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bxC" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, -/turf/open/floor/plasteel, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bxD" = ( /obj/effect/turf_decal/tile/blue{ - dir = 4 + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/light{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 }, /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/structure/cable/yellow{ + icon_state = "2-8" + }, /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bxL" = ( @@ -38718,15 +38686,13 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, /obj/structure/cable/yellow{ icon_state = "1-4" }, -/obj/structure/cable/yellow{ - icon_state = "2-4" +/obj/effect/turf_decal/tile/neutral{ + dir = 8 }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "bxO" = ( @@ -39242,7 +39208,7 @@ dir = 4 }, /obj/machinery/computer/station_alert, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 4 }, /turf/open/floor/plasteel/dark/corner{ @@ -39262,7 +39228,7 @@ dir = 4 }, /obj/structure/closet/secure_closet/atmospherics, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 4 }, /turf/open/floor/plasteel/dark/corner{ @@ -39279,10 +39245,10 @@ dir = 4 }, /obj/structure/closet/secure_closet/atmospherics, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark/corner{ dir = 1 }, @@ -39295,9 +39261,6 @@ pixel_y = 24 }, /obj/machinery/computer/atmos_control, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, /turf/open/floor/plasteel/checker, /area/engine/atmos) "byW" = ( @@ -39311,7 +39274,7 @@ dir = 4 }, /obj/machinery/computer/atmos_control, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 4 }, /turf/open/floor/plasteel/checker, @@ -39330,12 +39293,12 @@ pixel_x = -26 }, /obj/machinery/pipedispenser/disposal/transit_tube, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, /obj/effect/turf_decal/stripes/line{ dir = 6 }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "byY" = ( @@ -39343,7 +39306,7 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 4 }, /turf/open/floor/plasteel, @@ -39356,14 +39319,14 @@ dir = 8 }, /obj/machinery/pipedispenser, -/obj/machinery/atmospherics/pipe/simple/orange/visible{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/camera{ c_tag = "Atmospherics - Entrance"; dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ + dir = 4 + }, /turf/open/floor/plasteel, /area/engine/atmos) "bza" = ( @@ -39609,23 +39572,14 @@ /turf/open/floor/plasteel/dark, /area/aisat) "bzw" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/door/firedoor, -/obj/machinery/newscaster{ - pixel_x = 28; - pixel_y = 1 +/obj/machinery/door/airlock{ + name = "Port Emergency Storage" }, /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, -/area/hallway/secondary/entry) +/turf/open/floor/plating, +/area/maintenance/port) "bzx" = ( /turf/closed/wall, /area/security/vacantoffice) @@ -40217,12 +40171,15 @@ /area/tcommsat/computer) "bAW" = ( /obj/structure/table/wood, -/obj/item/folder/blue, /obj/machinery/status_display/evac{ pixel_y = 31 }, -/obj/item/folder/blue, -/obj/item/pen, +/obj/item/radio/off{ + pixel_y = 4 + }, +/obj/item/screwdriver{ + pixel_y = 10 + }, /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bAX" = ( @@ -40285,45 +40242,22 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/hallway/secondary/entry) -"bBd" = ( -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/obj/structure/cable/yellow{ - icon_state = "2-4" - }, -/turf/open/floor/plasteel, -/area/hallway/secondary/entry) "bBf" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/structure/table/wood, +/obj/machinery/light_switch{ + pixel_x = -28 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/item/folder, +/turf/open/floor/wood, +/area/security/vacantoffice) "bBg" = ( /turf/open/floor/wood, /area/security/vacantoffice) "bBh" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/cable/yellow{ - icon_state = "2-8" - }, -/obj/structure/cable/yellow{ - icon_state = "2-4" - }, -/turf/open/floor/plasteel, +/obj/structure/table/wood, +/obj/item/reagent_containers/food/snacks/chips, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "bBi" = ( /obj/structure/table/wood, @@ -40424,7 +40358,7 @@ /turf/open/floor/wood, /area/library) "bBx" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/wood, @@ -41039,33 +40973,29 @@ /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, -/area/hallway/secondary/entry) -"bCI" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, /obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) +"bCI" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 }, /obj/structure/cable/yellow{ icon_state = "1-2" }, -/turf/open/floor/plasteel/white/corner, -/area/hallway/secondary/entry) +/turf/open/floor/plating, +/area/maintenance/port) "bCJ" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/item/storage/toolbox/emergency, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/turf/open/floor/plating{ + icon_state = "panelscorched" }, -/obj/machinery/door/firedoor, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/area/maintenance/port) "bCK" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -41074,66 +41004,35 @@ /turf/open/floor/plating, /area/maintenance/starboard) "bCL" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 1 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/machinery/firealarm{ - pixel_y = -24 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/turf/open/floor/wood, +/area/security/vacantoffice) "bCM" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/item/radio/intercom{ - pixel_y = -28 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/obj/structure/table/wood, +/turf/open/floor/wood, +/area/security/vacantoffice) "bCN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/stripes/line{ dir = 8 }, /obj/machinery/door/firedoor, -/obj/machinery/power/apc{ - areastring = "/area/hallway/secondary/entry"; - dir = 8; - name = "Arrivals APC"; - pixel_x = -26 - }, -/obj/structure/cable/yellow{ - icon_state = "0-4" - }, /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bCP" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/structure/sign/map/right{ - desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; - icon_state = "map-right-MS"; - pixel_y = -32 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/turf/open/floor/plating, +/area/crew_quarters/toilet/auxiliary) "bCQ" = ( /obj/machinery/door/firedoor, -/obj/structure/cable/yellow{ - icon_state = "2-8" +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/turf/open/floor/plasteel, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bCR" = ( /obj/machinery/power/apc/highcap/five_k{ @@ -41143,7 +41042,7 @@ }, /obj/structure/cable/yellow, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 + dir = 9 }, /turf/open/floor/plasteel, /area/crew_quarters/toilet/auxiliary) @@ -41152,9 +41051,6 @@ dir = 8; pixel_x = 24 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, /turf/open/floor/plasteel, /area/crew_quarters/toilet/auxiliary) "bCV" = ( @@ -41792,44 +41688,43 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bEo" = ( -/obj/machinery/door/airlock{ - name = "Port Emergency Storage" - }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/item/storage/box/lights/mixed, /obj/structure/cable/yellow{ icon_state = "1-2" }, /turf/open/floor/plating, /area/maintenance/port) "bEp" = ( -/obj/machinery/door/firedoor, -/turf/open/floor/plasteel, -/area/hallway/secondary/entry) +/obj/machinery/vending/coffee, +/turf/open/floor/plasteel/dark, +/area/hallway/primary/port) "bEq" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, -/area/security/vacantoffice) -"bEs" = ( -/obj/structure/table/wood, -/obj/item/paper_bin{ - pixel_x = -2; - pixel_y = 6 - }, -/obj/machinery/newscaster{ - pixel_y = 32 +/obj/structure/light_construct{ + dir = 8 }, /turf/open/floor/wood, /area/security/vacantoffice) -"bEt" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +"bEs" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/power/apc{ + areastring = "/area/hallway/secondary/entry"; + dir = 4; + name = "Arrivals APC"; + pixel_x = 26 + }, +/obj/structure/cable/yellow{ + icon_state = "0-8" + }, +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) +"bEt" = ( +/obj/structure/chair/comfy{ dir = 8 }, -/obj/machinery/door/firedoor, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/grimy, /area/hallway/primary/port) "bEu" = ( /obj/machinery/door/airlock{ @@ -42467,7 +42362,7 @@ dir = 10 }, /obj/structure/table/wood/poker, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/wood, /area/crew_quarters/bar) "bFt" = ( @@ -42693,7 +42588,7 @@ name = "Distribution Loop"; req_access_txt = "24" }, -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plasteel, /area/engine/atmos) "bFQ" = ( @@ -42807,18 +42702,18 @@ /turf/open/floor/carpet, /area/crew_quarters/theatre) "bGh" = ( -/obj/machinery/announcement_system, -/turf/open/floor/plasteel/grimy, -/area/tcommsat/computer) +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat/foyer) "bGj" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 4 +/obj/machinery/vending/cola/random, +/obj/machinery/newscaster{ + pixel_x = -30 }, -/obj/machinery/door/firedoor, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/dark, /area/hallway/primary/port) "bGk" = ( /obj/structure/cable/yellow{ @@ -42842,8 +42737,9 @@ /turf/open/floor/plasteel, /area/crew_quarters/toilet/auxiliary) "bGm" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/shower{ + dir = 8 }, /turf/open/floor/plasteel, /area/crew_quarters/toilet/auxiliary) @@ -43438,18 +43334,20 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bHJ" = ( -/obj/item/tank/internals/oxygen, -/obj/item/tank/internals/oxygen, -/obj/item/clothing/mask/breath, -/obj/item/clothing/mask/breath, -/obj/machinery/light/small{ +/obj/effect/turf_decal/tile/blue{ dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/newscaster{ + pixel_x = 28; + pixel_y = 1 + }, +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) "bHK" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 +/obj/structure/table/wood, +/obj/item/book/manual/wiki/security_space_law{ + pixel_x = -3; + pixel_y = 5 }, /turf/open/floor/wood, /area/security/vacantoffice) @@ -43463,9 +43361,11 @@ /turf/open/floor/carpet, /area/security/vacantoffice) "bHM" = ( -/obj/structure/table/wood, -/turf/open/floor/wood, -/area/security/vacantoffice) +/obj/structure/chair/comfy{ + dir = 4 + }, +/turf/open/floor/plasteel/grimy, +/area/hallway/primary/port) "bHN" = ( /obj/machinery/shower{ dir = 4 @@ -43960,7 +43860,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/yellow, @@ -44132,7 +44032,7 @@ /turf/open/floor/circuit/telecomms/mainframe, /area/tcommsat/server) "bJh" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/grimy, @@ -44151,9 +44051,10 @@ /turf/open/floor/plasteel/grimy, /area/tcommsat/computer) "bJj" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/machinery/door/airlock/maintenance{ + req_one_access_txt = "12;27;37" }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable/yellow{ icon_state = "1-2" }, @@ -44191,26 +44092,23 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bJp" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/turf/open/floor/plasteel, -/area/hallway/secondary/entry) +/obj/machinery/vending/snack/random, +/turf/open/floor/plasteel/dark, +/area/hallway/primary/port) "bJq" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/item/storage/box/lights/mixed, /obj/structure/cable/yellow{ icon_state = "1-2" }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, /turf/open/floor/plating, /area/maintenance/port) "bJr" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/obj/machinery/portable_atmospherics/canister/air, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/hallway/secondary/entry) "bJs" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 10 @@ -44224,9 +44122,6 @@ /obj/item/radio/intercom{ pixel_x = -29 }, -/obj/machinery/light/small{ - dir = 8 - }, /turf/open/floor/wood, /area/security/vacantoffice) "bJu" = ( @@ -44250,8 +44145,10 @@ /turf/open/floor/carpet, /area/security/vacantoffice) "bJw" = ( -/obj/structure/chair/office{ - dir = 8 +/obj/structure/table/wood, +/obj/item/paper_bin{ + pixel_x = -2; + pixel_y = 6 }, /turf/open/floor/carpet, /area/security/vacantoffice) @@ -44260,15 +44157,6 @@ dir = 8; pixel_x = 24 }, -/obj/structure/table/wood, -/obj/item/camera_film{ - pixel_x = 6; - pixel_y = 7 - }, -/obj/item/camera_film{ - pixel_x = -3; - pixel_y = 5 - }, /turf/open/floor/wood, /area/security/vacantoffice) "bJy" = ( @@ -44580,27 +44468,7 @@ }, /turf/open/floor/plating, /area/gateway) -"bJY" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/obj/effect/turf_decal/bot_white/right, -/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/gateway) "bJZ" = ( -/obj/machinery/gateway{ - dir = 1 - }, /obj/machinery/status_display/evac{ pixel_y = 32 }, @@ -44617,23 +44485,6 @@ }, /turf/open/floor/plasteel/dark, /area/gateway) -"bKa" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/obj/effect/turf_decal/bot_white/left, -/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/gateway) "bKb" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -44801,19 +44652,19 @@ /turf/open/floor/plasteel, /area/engine/atmos) "bKy" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 4 }, /turf/closed/wall, /area/engine/atmos) "bKz" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible{ +/obj/machinery/atmospherics/pipe/simple/orange/hidden{ dir = 10 }, /turf/closed/wall, /area/engine/atmos) "bKA" = ( -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/closed/wall, /area/engine/atmos) "bKB" = ( @@ -44916,7 +44767,7 @@ dir = 8 }, /turf/open/space, -/area/aisat) +/area/space/nearstation) "bKR" = ( /obj/structure/window/reinforced{ dir = 8 @@ -44940,7 +44791,7 @@ /turf/open/floor/plasteel/dark, /area/aisat) "bKS" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-06" }, /obj/effect/turf_decal/stripes/line{ @@ -44993,15 +44844,11 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bKX" = ( -/obj/machinery/door/airlock/maintenance{ - req_one_access_txt = "12;27;37" +/obj/structure/chair/comfy{ + dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/grimy, +/area/hallway/primary/port) "bKY" = ( /obj/machinery/power/apc{ areastring = "/area/security/vacantoffice"; @@ -45306,31 +45153,13 @@ /obj/structure/cable/yellow, /turf/open/floor/plating, /area/gateway) -"bLD" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/turf_decal/bot_white, -/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/gateway) "bLE" = ( -/obj/machinery/gateway/centerstation, +/obj/machinery/gateway/centerstation{ + dir = 0 + }, /turf/open/floor/plasteel/dark, /area/gateway) "bLF" = ( -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -45558,7 +45387,7 @@ /area/engine/atmos) "bMe" = ( /obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/orange/visible, +/obj/machinery/atmospherics/pipe/simple/orange/hidden, /turf/open/floor/plating, /area/engine/atmos) "bMf" = ( @@ -45770,7 +45599,7 @@ icon_state = "map-right-MS"; pixel_y = -32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/effect/turf_decal/tile/blue{ @@ -45785,7 +45614,7 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bMC" = ( -/obj/structure/chair/office, +/obj/structure/chair/office/dark, /turf/open/floor/wood, /area/security/vacantoffice) "bMD" = ( @@ -46048,19 +45877,15 @@ /turf/open/floor/carpet, /area/bridge/showroom/corporate) "bNd" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/item/tank/internals/oxygen, +/obj/item/tank/internals/oxygen, +/obj/item/clothing/mask/breath, +/obj/item/clothing/mask/breath, +/obj/machinery/light/small{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Port Primary Hallway - Mining Shuttle"; - dir = 1 - }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/turf/open/floor/plating, +/area/maintenance/port) "bNe" = ( /obj/structure/table/wood, /obj/item/phone{ @@ -46104,17 +45929,11 @@ /turf/open/floor/wood, /area/bridge/showroom/corporate) "bNh" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/obj/structure/table/wood, +/obj/item/folder/red, +/obj/item/pen/red, +/turf/open/floor/wood, +/area/security/vacantoffice) "bNi" = ( /obj/structure/window/reinforced{ dir = 8 @@ -46196,9 +46015,6 @@ }, /area/gateway) "bNp" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -46213,7 +46029,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "bNq" = ( -/obj/machinery/gateway, /obj/structure/cable/yellow{ icon_state = "0-2" }, @@ -46231,9 +46046,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "bNr" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -46384,12 +46196,17 @@ /turf/open/floor/wood, /area/crew_quarters/theatre) "bNK" = ( -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk{ - dir = 1 +/obj/machinery/airalarm{ + dir = 8; + pixel_x = 24 }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/obj/structure/table/wood, +/obj/item/paper_bin{ + pixel_x = -2; + pixel_y = 6 + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "bNL" = ( /obj/structure/table, /obj/item/stock_parts/subspace/transmitter, @@ -46829,6 +46646,9 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, +/obj/machinery/computer/gateway_control{ + dir = 8 + }, /turf/open/floor/plasteel, /area/gateway) "bOJ" = ( @@ -46964,11 +46784,11 @@ /turf/open/floor/plasteel/showroomfloor, /area/crew_quarters/kitchen) "bOY" = ( -/obj/structure/sign/warning/vacuum/external{ - pixel_x = 32 +/obj/machinery/door/airlock/external{ + req_access_txt = "13" }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 }, /turf/open/floor/plating, /area/maintenance/starboard/fore) @@ -47769,9 +47589,6 @@ dir = 8; pixel_x = 24 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, /turf/open/floor/plating, /area/crew_quarters/toilet/auxiliary) "bQQ" = ( @@ -51026,7 +50843,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = -27 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/effect/turf_decal/tile/blue{ @@ -51122,7 +50939,7 @@ dir = 8; pixel_x = 24 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/purple, @@ -53780,9 +53597,6 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /turf/open/floor/plating, /area/engine/atmos) "ccY" = ( @@ -54628,7 +54442,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "ceI" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-11" }, /obj/effect/turf_decal/tile/yellow, @@ -54723,7 +54537,7 @@ name = "Station Intercom (General)"; pixel_y = -30 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /obj/effect/turf_decal/tile/purple, @@ -55065,17 +54879,12 @@ /turf/open/space, /area/solar/port/aft) "cfA" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, +/obj/machinery/door/airlock/external, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 4 }, /turf/open/floor/plating, -/area/maintenance/port/aft) +/area/maintenance/port/fore) "cfB" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable/yellow{ @@ -59526,7 +59335,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "coj" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/purple, @@ -63344,12 +63153,9 @@ /turf/open/space, /area/solar/port/aft) "cvj" = ( -/obj/structure/closet/emcloset, -/obj/structure/sign/warning/vacuum/external{ - pixel_x = -32 - }, -/turf/open/floor/plating, -/area/maintenance/port/aft) +/obj/structure/lattice, +/turf/closed/wall/r_wall, +/area/engine/break_room) "cvk" = ( /obj/structure/closet/crate, /obj/item/crowbar/red, @@ -63835,7 +63641,10 @@ /turf/open/floor/plasteel, /area/science/circuit) "cwc" = ( -/obj/effect/turf_decal/stripes/line, +/obj/machinery/door/airlock/external{ + name = "Auxiliary Escape Airlock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating, /area/maintenance/aft) "cwd" = ( @@ -63864,9 +63673,14 @@ /obj/structure/cable/yellow{ icon_state = "4-8" }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "cwh" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -64235,7 +64049,7 @@ /obj/machinery/light_switch{ pixel_x = -23 }, -/obj/item/twohanded/required/kirbyplants/dead, +/obj/item/kirbyplants/dead, /turf/open/floor/plasteel/cafeteria{ dir = 5 }, @@ -65072,10 +64886,8 @@ /obj/machinery/light_switch{ pixel_y = 28 }, -/obj/structure/closet/l3closet/scientist{ - pixel_x = -2 - }, /obj/effect/turf_decal/stripes/line, +/obj/structure/closet/bombcloset, /turf/open/floor/plasteel, /area/science/mixing) "cyA" = ( @@ -65106,7 +64918,6 @@ "cyD" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible, /obj/effect/turf_decal/stripes/line, -/obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/science/mixing) "cyE" = ( @@ -65118,7 +64929,6 @@ network = list("ss13","rd") }, /obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/machinery/portable_atmospherics/canister, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/science/mixing) @@ -65151,7 +64961,9 @@ dir = 4 }, /obj/machinery/portable_atmospherics/canister, -/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, /turf/open/floor/plasteel, /area/science/mixing) "cyI" = ( @@ -65167,11 +64979,7 @@ /obj/machinery/light_switch{ pixel_y = 28 }, -/obj/machinery/portable_atmospherics/scrubber, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/white, /area/science/mixing) "cyK" = ( /turf/closed/wall/r_wall, @@ -65582,10 +65390,14 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "czB" = ( -/obj/machinery/portable_atmospherics/pump, -/obj/effect/turf_decal/stripes/line{ - dir = 8 +/obj/machinery/light{ + dir = 4 }, +/obj/structure/window/reinforced{ + dir = 1; + pixel_y = 2 + }, +/obj/machinery/portable_atmospherics/pump, /turf/open/floor/plasteel, /area/science/mixing) "czC" = ( @@ -66263,12 +66075,15 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "cAG" = ( -/obj/structure/window/reinforced, -/obj/machinery/portable_atmospherics/scrubber, -/obj/item/storage/firstaid/toxin, -/obj/effect/turf_decal/stripes/line{ - dir = 10 +/obj/structure/extinguisher_cabinet{ + pixel_x = 27 }, +/obj/machinery/camera{ + c_tag = "Toxins - Mixing Area"; + dir = 8; + network = list("ss13","rd") + }, +/obj/machinery/portable_atmospherics/scrubber, /turf/open/floor/plasteel, /area/science/mixing) "cAH" = ( @@ -66983,10 +66798,10 @@ /turf/open/floor/plasteel/white, /area/science/research) "cCt" = ( -/obj/structure/closet/bombcloset, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/portable_atmospherics/canister, /turf/open/floor/plasteel, /area/science/mixing) "cCu" = ( @@ -67172,8 +66987,7 @@ layer = 4; name = "Test Chamber Telescreen"; network = list("toxins"); - pixel_x = -32; - pixel_y = 0 + pixel_x = -32 }, /turf/open/floor/plasteel, /area/science/mixing) @@ -68144,19 +67958,14 @@ dir = 1; pixel_y = 2 }, -/obj/machinery/light{ - dir = 4 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, /turf/open/floor/plasteel, /area/science/mixing) "cEz" = ( -/obj/structure/closet/wardrobe/grey, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/obj/machinery/portable_atmospherics/scrubber, +/obj/item/storage/firstaid/toxin, +/turf/open/floor/plasteel, +/area/science/mixing) "cEA" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -68541,18 +68350,7 @@ /turf/open/floor/plasteel/white, /area/science/mixing) "cFs" = ( -/obj/structure/extinguisher_cabinet{ - pixel_x = 27 - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/camera{ - c_tag = "Toxins - Mixing Area"; - dir = 8; - network = list("ss13","rd") - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /turf/open/floor/plasteel, /area/science/mixing) "cFu" = ( @@ -68828,7 +68626,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/aft) "cFQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -69038,9 +68836,6 @@ dir = 8 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, /obj/machinery/portable_atmospherics/pump, /turf/open/floor/plasteel, /area/science/mixing) @@ -70271,9 +70066,7 @@ /obj/structure/cable/yellow{ icon_state = "1-4" }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, /area/maintenance/starboard/aft) "cIm" = ( @@ -70461,7 +70254,7 @@ pixel_x = -32 }, /turf/open/space, -/area/space/nearstation) +/area/space) "cIz" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -70745,18 +70538,20 @@ /obj/structure/cable/yellow{ icon_state = "4-8" }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /turf/open/floor/plating, /area/maintenance/starboard/aft) "cJf" = ( /obj/structure/cable/yellow{ - icon_state = "0-8" + icon_state = "4-8" }, -/obj/structure/lattice/catwalk, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "cJg" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/item/bedsheet/medical, @@ -71160,7 +70955,7 @@ /turf/open/floor/plasteel/white, /area/science/research) "cJQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/purple{ @@ -72005,6 +71800,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/aft) "cLA" = ( @@ -72340,7 +72136,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = 27 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /obj/effect/turf_decal/stripes/line{ @@ -72349,15 +72145,12 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "cMk" = ( -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/maintenance/aft"; - name = "Aft Maintenance APC"; - pixel_y = -24 +/obj/structure/window/reinforced{ + dir = 1; + pixel_y = 1 }, -/obj/structure/cable/yellow, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/maintenance/aft) +/turf/open/space, +/area/space) "cMl" = ( /obj/structure/table, /obj/item/stack/sheet/glass/fifty{ @@ -72942,10 +72735,6 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "cNe" = ( -/obj/machinery/door/airlock/external{ - name = "Auxiliary Escape Airlock" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, /turf/open/floor/plating, /area/maintenance/aft) "cNf" = ( @@ -74181,7 +73970,7 @@ /obj/structure/extinguisher_cabinet{ pixel_x = -27 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-04" }, /obj/effect/turf_decal/stripes/line{ @@ -74247,7 +74036,7 @@ name = "Station Intercom (General)"; pixel_x = 29 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/effect/turf_decal/stripes/line{ @@ -76823,9 +76612,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) "dbR" = ( @@ -79185,13 +78971,10 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/door/firedoor, /obj/structure/sign/poster/official/random{ pixel_y = 32 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, /area/hallway/primary/port) "dhQ" = ( @@ -79269,14 +79052,11 @@ /turf/open/floor/wood, /area/crew_quarters/theatre) "dhZ" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 4 +/obj/structure/urinal{ + pixel_y = 29 }, -/obj/structure/cable/yellow{ - icon_state = "1-8" - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/turf/open/floor/plating, +/area/crew_quarters/toilet/auxiliary) "dib" = ( /obj/structure/table/wood, /obj/item/lipstick{ @@ -79312,10 +79092,6 @@ /area/hallway/secondary/entry) "did" = ( /obj/structure/table/wood, -/obj/machinery/light_switch{ - pixel_x = -28 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/item/folder, /turf/open/floor/wood, /area/security/vacantoffice) @@ -79331,13 +79107,11 @@ /turf/open/floor/wood, /area/crew_quarters/theatre) "dig" = ( -/obj/machinery/airalarm{ - dir = 8; - pixel_x = 24 +/obj/item/kirbyplants{ + icon_state = "plant-03" }, -/obj/structure/table/wood, -/turf/open/floor/wood, -/area/security/vacantoffice) +/turf/open/floor/plasteel/grimy, +/area/hallway/primary/port) "dih" = ( /obj/machinery/light/small, /obj/structure/sign/poster/official/random{ @@ -79726,15 +79500,15 @@ }, /area/medical/medbay/aft) "diP" = ( -/obj/structure/cable/yellow{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, /obj/structure/sign/poster/contraband/random{ pixel_y = -32 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, /turf/open/floor/plating, /area/maintenance/starboard/aft) "diQ" = ( @@ -79798,7 +79572,7 @@ c_tag = "Departure Lounge - Port Fore"; dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-24" }, /obj/effect/turf_decal/stripes/line{ @@ -79910,20 +79684,10 @@ /turf/open/space/basic, /area/space) "djW" = ( -/obj/machinery/light{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plasteel, -/area/hallway/primary/port) +/area/maintenance/port) "djX" = ( /obj/structure/closet/crate/coffin, /obj/machinery/door/window/eastleft{ @@ -80458,9 +80222,7 @@ pixel_y = -24 }, /obj/structure/cable/yellow, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /turf/open/floor/plating, /area/maintenance/starboard/aft) "dAh" = ( @@ -81324,6 +81086,12 @@ }, /turf/closed/wall, /area/maintenance/starboard) +"dQg" = ( +/obj/machinery/door/airlock/maintenance{ + req_one_access_txt = "12;27;37" + }, +/turf/open/floor/plating, +/area/maintenance/port) "dYu" = ( /obj/machinery/door/airlock/external{ name = "Auxiliary Airlock" @@ -81334,9 +81102,16 @@ /turf/open/floor/plating, /area/hallway/secondary/entry) "eiS" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plasteel, -/area/crew_quarters/toilet/auxiliary) +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Port Primary Hallway - True Port"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/hallway/primary/port) "eoK" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -81374,10 +81149,6 @@ /obj/machinery/vr_sleeper, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) -"evy" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/space) "eEe" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 @@ -81440,6 +81211,12 @@ }, /turf/open/floor/plasteel/white, /area/science/circuit) +"fDG" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/toilet/auxiliary) "fFM" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -81510,12 +81287,32 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"gsT" = ( +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plating, +/area/solar/starboard/aft) "gEk" = ( /obj/structure/cable/yellow{ icon_state = "2-8" }, /turf/open/floor/plating, /area/maintenance/starboard/aft) +"gGH" = ( +/obj/structure/cable/yellow{ + icon_state = "2-4" + }, +/obj/effect/spawner/lootdrop/maintenance, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "gGT" = ( /obj/effect/landmark/start/scientist, /obj/structure/chair/office/light{ @@ -81540,9 +81337,7 @@ /turf/open/floor/plasteel, /area/science/misc_lab) "gNe" = ( -/obj/machinery/light/small{ - dir = 8 - }, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/maintenance/aft) "gRS" = ( @@ -81649,12 +81444,25 @@ /turf/open/floor/plasteel, /area/engine/atmos) "iSt" = ( -/obj/machinery/door/airlock/grunge, -/obj/structure/cable/yellow{ - icon_state = "1-2" +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) +"jdf" = ( +/obj/machinery/door/airlock{ + id_tag = "AuxShower"; + name = "Shower" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, -/area/security/vacantoffice) +/area/crew_quarters/toilet/auxiliary) "jeV" = ( /obj/machinery/conveyor/inverted{ dir = 10; @@ -81703,13 +81511,6 @@ /obj/structure/cable{ icon_state = "1-2" }, -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, /turf/open/floor/plating, /area/maintenance/solars/port/aft) "jAj" = ( @@ -81722,15 +81523,18 @@ /turf/open/floor/plasteel, /area/engine/atmos) "jBe" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/structure/sign/poster/official/random{ - pixel_y = -32 - }, /turf/open/floor/plasteel, /area/hallway/primary/port) "jKK" = ( @@ -81762,15 +81566,27 @@ /obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/door/firedoor, /obj/structure/cable/yellow{ icon_state = "4-8" }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, /area/hallway/primary/port) +"jQK" = ( +/obj/structure/lattice, +/turf/closed/wall/r_wall, +/area/aisat) +"jRo" = ( +/obj/structure/table/wood, +/obj/machinery/newscaster{ + pixel_y = 32 + }, +/obj/item/clipboard, +/obj/item/paper, +/turf/open/floor/wood, +/area/security/vacantoffice) "kfu" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/white, @@ -81818,17 +81634,15 @@ /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) "kDM" = ( -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/machinery/door/airlock/external{ - req_access_txt = "13" +/obj/machinery/door/airlock/hatch{ + name = "MiniSat Space Access Airlock"; + req_one_access_txt = "32;19" }, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/turf/open/floor/plasteel/dark, +/area/engine/break_room) "kJW" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 1; @@ -81849,15 +81663,18 @@ /turf/open/floor/plasteel/white, /area/science/circuit) "kQP" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/navbeacon{ + codes_txt = "patrol;next_patrol=6-Port-Central"; + location = "5-Customs" + }, +/obj/structure/cable/yellow{ + icon_state = "4-8" }, /obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/machinery/airalarm{ - dir = 1; - pixel_y = -22 + dir = 4 }, /turf/open/floor/plasteel, /area/hallway/primary/port) @@ -81903,6 +81720,9 @@ /turf/open/floor/plasteel/white, /area/science/circuit) "lws" = ( +/obj/structure/chair/office/dark{ + dir = 8 + }, /turf/open/floor/carpet, /area/security/vacantoffice) "lzk" = ( @@ -81931,14 +81751,9 @@ /turf/open/space/basic, /area/space/nearstation) "lNZ" = ( -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) +/obj/structure/lattice/catwalk, +/turf/closed/wall/r_wall, +/area/engine/atmos) "lOi" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -81980,31 +81795,34 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) "maP" = ( -/obj/item/storage/toolbox/emergency, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, -/turf/open/floor/plating{ - icon_state = "panelscorched" +/obj/structure/cable/yellow{ + icon_state = "4-8" }, -/area/maintenance/port) +/turf/open/floor/plasteel, +/area/hallway/primary/port) "mcS" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, -/obj/structure/disposalpipe/segment{ - dir = 9 + dir = 4 }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/structure/sign/map/left{ - desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; - icon_state = "map-left-MS"; - pixel_y = -32 +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_y = -28 + }, +/turf/open/floor/plasteel/white/corner, +/area/hallway/secondary/entry) "mjJ" = ( /obj/machinery/nuclearbomb/beer{ pixel_x = 2; @@ -82016,6 +81834,12 @@ /obj/structure/lattice, /turf/closed/wall, /area/crew_quarters/cryopod) +"mot" = ( +/obj/structure/chair/office/dark{ + dir = 8 + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "mvj" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -82049,6 +81873,12 @@ }, /turf/open/floor/plating, /area/maintenance/port) +"mSd" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "mWg" = ( /obj/structure/girder, /obj/structure/grille, @@ -82057,19 +81887,23 @@ }, /area/maintenance/port/aft) "nhy" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/disposalpipe/segment, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/corner{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, +/obj/effect/landmark/event_spawn, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, /area/hallway/primary/port) +"nix" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/turret_protected/aisat/foyer) "njd" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 8; @@ -82293,6 +82127,16 @@ /obj/structure/grille, /turf/open/floor/plating, /area/maintenance/port/aft) +"pbc" = ( +/obj/structure/light_construct/small{ + dir = 4 + }, +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_x = 30 + }, +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/wood, +/area/maintenance/port/aft) "pbF" = ( /obj/machinery/portable_atmospherics/canister, /obj/machinery/atmospherics/components/unary/portables_connector/visible{ @@ -82353,9 +82197,22 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) "pHS" = ( -/obj/structure/closet/firecloset, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) "pMX" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -82388,6 +82245,15 @@ }, /turf/open/floor/plating, /area/maintenance/aft) +"pVL" = ( +/obj/structure/cable/yellow{ + icon_state = "1-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/aft) "pZb" = ( /obj/structure/cable/yellow{ icon_state = "2-4" @@ -82400,6 +82266,13 @@ }, /turf/open/floor/plating, /area/maintenance/port) +"qkY" = ( +/obj/machinery/door/airlock/grunge, +/obj/structure/cable/yellow{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/security/vacantoffice) "qqg" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 @@ -82479,11 +82352,18 @@ /turf/open/floor/plasteel, /area/security/prison) "rbE" = ( -/obj/effect/turf_decal/tile/blue{ +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/turf/open/floor/plasteel/white/corner, -/area/hallway/secondary/entry) +/obj/machinery/firealarm{ + pixel_y = -24 + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel, +/area/hallway/primary/port) "roa" = ( /obj/structure/chair/stool, /obj/machinery/light/small{ @@ -82532,19 +82412,16 @@ /turf/closed/wall, /area/quartermaster/miningoffice) "rNX" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /obj/effect/turf_decal/tile/neutral{ - dir = 1 + dir = 8 }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/navbeacon{ - codes_txt = "patrol;next_patrol=6-Port-Central"; - location = "5-Customs" - }, -/obj/structure/cable/yellow{ - icon_state = "4-8" +/obj/structure/sign/poster/official/random{ + pixel_y = -32 }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "rQK" = ( @@ -82577,8 +82454,9 @@ /turf/open/floor/plasteel, /area/science/circuit) "sdw" = ( -/turf/open/space/basic, -/area/space/nearstation) +/obj/structure/window/reinforced, +/turf/open/space, +/area/space) "siF" = ( /obj/structure/grille, /turf/open/floor/plating/airless, @@ -82615,15 +82493,16 @@ /turf/open/floor/plasteel, /area/engine/atmos) "syk" = ( -/obj/machinery/door/airlock{ - id_tag = "AuxShower"; - name = "Shower" +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/structure/cable/yellow{ + icon_state = "1-2" }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, -/area/crew_quarters/toilet/auxiliary) +/area/hallway/primary/port) "sFv" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -82675,6 +82554,16 @@ }, /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) +"sUM" = ( +/obj/structure/sign/warning/vacuum/external{ + pixel_x = -32 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"sZN" = ( +/obj/structure/closet/firecloset, +/turf/open/floor/plating, +/area/maintenance/port) "tap" = ( /obj/machinery/power/apc/auto_name/east, /obj/structure/cable/yellow{ @@ -82683,33 +82572,14 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) "tre" = ( -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/stripes/corner{ - dir = 8 - }, -/obj/structure/cable/yellow{ - icon_state = "4-8" - }, -/obj/structure/cable/yellow{ - icon_state = "2-8" - }, -/obj/structure/cable/yellow{ - icon_state = "2-4" +/obj/effect/turf_decal/stripes/line{ + dir = 1 }, /obj/structure/cable/yellow{ icon_state = "1-2" }, -/obj/structure/cable/yellow{ - icon_state = "1-4" - }, -/obj/structure/cable/yellow{ - icon_state = "1-8" - }, -/turf/open/floor/plasteel/white/corner, -/area/hallway/secondary/entry) +/turf/open/floor/plating, +/area/maintenance/port) "tsx" = ( /obj/structure/cable/yellow{ icon_state = "4-8" @@ -82719,6 +82589,13 @@ }, /turf/open/floor/plating, /area/maintenance/starboard) +"txh" = ( +/obj/machinery/door/airlock/hatch{ + name = "Telecomms Control Room"; + req_one_access_txt = "19; 61" + }, +/turf/open/floor/plasteel/dark, +/area/tcommsat/computer) "txj" = ( /obj/structure/chair/office/light{ dir = 1 @@ -82742,6 +82619,13 @@ }, /turf/open/floor/plasteel/dark, /area/medical/morgue) +"tUa" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/machinery/portable_atmospherics/canister/air, +/turf/open/floor/plating, +/area/maintenance/port) "tVY" = ( /obj/structure/closet/crate, /obj/item/target/alien, @@ -82762,6 +82646,13 @@ /obj/machinery/cryopod, /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) +"uim" = ( +/obj/structure/cable/yellow{ + icon_state = "0-8" + }, +/obj/structure/lattice/catwalk, +/turf/open/space, +/area/space/nearstation) "uku" = ( /obj/machinery/atmospherics/pipe/manifold4w/general/visible, /turf/open/floor/plasteel, @@ -82832,7 +82723,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/white, @@ -82867,6 +82758,18 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) +"vuY" = ( +/obj/structure/table/wood, +/obj/item/camera_film{ + pixel_x = 6; + pixel_y = 7 + }, +/obj/item/camera_film{ + pixel_x = -3; + pixel_y = 5 + }, +/turf/open/floor/wood, +/area/security/vacantoffice) "vxG" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -82921,21 +82824,28 @@ /turf/open/floor/plating, /area/security/prison) "wlH" = ( -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/structure/reagent_dispensers/fueltank, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/item/radio/intercom{ + pixel_y = -28 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, /turf/open/floor/plasteel, -/area/maintenance/port) +/area/hallway/primary/port) "wmt" = ( /obj/effect/decal/cleanable/flour, /turf/open/floor/plating, /area/maintenance/port/aft) "wxc" = ( -/obj/machinery/door/airlock/external{ - name = "Atmospherics External Airlock"; - req_access_txt = "24" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +/obj/effect/turf_decal/stripes/line{ + dir = 4 }, /turf/open/floor/plating, /area/engine/atmos) @@ -82946,10 +82856,13 @@ /turf/open/floor/plating, /area/crew_quarters/cryopod) "wFH" = ( -/obj/structure/cable/yellow{ - icon_state = "1-2" +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/maintenance/aft"; + name = "Aft Maintenance APC"; + pixel_y = -24 }, -/obj/effect/landmark/blobstart, +/obj/structure/cable/yellow, +/obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/maintenance/starboard/aft) "wKo" = ( @@ -82957,8 +82870,15 @@ /turf/closed/wall, /area/science/circuit) "wOE" = ( +/obj/machinery/door/airlock/external{ + name = "Atmospherics External Airlock"; + req_access_txt = "24" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, /turf/open/floor/plating, -/area/maintenance/aft) +/area/engine/atmos) "wOY" = ( /obj/structure/fans/tiny/invisible, /turf/open/space/basic, @@ -82981,7 +82901,10 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/cryopod) "xfI" = ( -/obj/machinery/vending/cola/random, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, /area/hallway/primary/port) "xgC" = ( @@ -82996,25 +82919,29 @@ /turf/open/floor/plasteel/white, /area/science/circuit) "xmb" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/structure/cable/yellow{ - icon_state = "1-2" +/obj/structure/sign/map/left{ + desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; + icon_state = "map-left-MS"; + pixel_y = -32 }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) "xse" = ( -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +/obj/effect/turf_decal/stripes/line{ + dir = 4 }, /turf/open/floor/plating, /area/maintenance/solars/starboard/aft) @@ -83081,26 +83008,22 @@ /turf/open/floor/plasteel, /area/security/prison) "xLL" = ( -/obj/structure/table/wood, -/obj/item/folder/white{ - pixel_x = 4; - pixel_y = -3 +/obj/effect/turf_decal/tile/neutral{ + dir = 8 }, -/obj/item/book/manual/wiki/security_space_law{ - pixel_x = -3; - pixel_y = 5 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/structure/sign/map/right{ + desc = "A framed picture of the station. Clockwise from security at the top (red), you see engineering (yellow), science (purple), escape (red and white), medbay (green), arrivals (blue and white), and finally cargo (brown)."; + icon_state = "map-right-MS"; + pixel_y = -32 }, -/turf/open/floor/wood, -/area/security/vacantoffice) +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel, +/area/hallway/primary/port) "xTV" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/obj/structure/cable/yellow{ - icon_state = "1-2" - }, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall, +/area/security/vacantoffice) "xVl" = ( /turf/closed/wall, /area/hallway/secondary/service) @@ -83126,6 +83049,19 @@ }, /turf/open/floor/plating, /area/maintenance/port/aft) +"yfW" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/solars/port/aft) "ygk" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -95308,9 +95244,9 @@ anS anS aaf aaf -aqB -anS -aaf +dne +cfA +dne aaf aaf aaf @@ -95566,7 +95502,7 @@ aaa aaa aaf dne -avJ +avL dne aaf aaa @@ -96375,7 +96311,7 @@ bxL bvJ bxB bCQ -bBd +bCH bCH bEn dic @@ -96628,18 +96564,18 @@ bjV bnK bqb bbI -btT +bJr bvK bxC -bEp -bJp -rbE alK alK alK alK alK alK +dQg +alK +alK alK bPF asa @@ -96651,7 +96587,7 @@ bXt bYC bYC bYC -aaa +bYC aaa aaf aaa @@ -96882,7 +96818,7 @@ bgv biv bjW blT -bnL +bso bqc bso bso @@ -96893,9 +96829,9 @@ tre bCI bEo bJj -xTV +bbL bJq -bKX +bbL bbL bbL bPG @@ -96908,8 +96844,8 @@ bXu bYD bZN jyQ +yfW cda -cej cfz cED chY @@ -97139,20 +97075,20 @@ bbK biw bjX blU -baE -baE -baE -baE -baE -baE -baE -jPu -bCJ +aiT +bEs +bHJ +aiT +iSt +mcS alK auF -maP -bJr +bCJ +tUa alK +apz +aob +alC aqK aqO alC @@ -97165,7 +97101,7 @@ bXv bYC bYC bYC -aaa +bYC aaa aaf aaa @@ -97395,21 +97331,21 @@ beL bgw bix bjY -blV +bqd baE -afQ -afQ -afQ -afZ -afQ baE +baE +baE +bqd +nhy +alK djW bNd +sZN alK -wlH -bHJ -pHS -alK +amZ +aob +aob oWR aob bPH @@ -97653,15 +97589,15 @@ bgx biy bjZ blW -baE +ajk afZ -afQ +bHM ajs -afQ -afQ -baE -bBf -kQP +jBe +pHS +bzx +bzx +bzx bzx bzx bzx @@ -97910,13 +97846,13 @@ bgy biz bka blX -baE -afQ -afQ -afQ -afQ -afQ -baE +bnR +ahT +ahT +bKX +jPu +rbE +xTV bBf bCL bEq @@ -98165,19 +98101,19 @@ bda beO bgz biA -bnR +bka blY aeD agQ -afQ -afQ -afQ -afQ -baE +ahT +aeD +kQP rNX -jBe bzx bBg +bBg +bBg +bBg pZb bJu bKZ @@ -98424,16 +98360,16 @@ bgA biz bkb blZ -baE +bnR ahT -afQ -afQ +ahT +bKX aju -afQ -baE -bBh -xmb -iSt +syk +qkY +bGk +bGk +bGk bGk bKZ bHL @@ -98681,18 +98617,18 @@ bpt bcW bkc bma -baE -ahT +bBh +bEt aiW -afQ +dig amv -afQ -baE -bBf +wlH +bzx +bBi bCM -bzx -bzx -bHM +bBg +bBg +bBg bJv drp heE @@ -98939,21 +98875,21 @@ bcW dhP bqd baE -aiT -ajk -afQ -amB -afQ baE -djW -bsx +baE +baE +bqd xfI bzx -bEs +jRo +mot +bBg +bBg +bBg bJw lws bMC -xLL +bOg bzx bRe xDn @@ -99195,18 +99131,18 @@ bgC biB bkd bmb -baE -baE -baE -baE -baE -baE -baE -bBf +bEp +bGj +bJp +eiS +jBe +xmb +bzx +vuY bNh bNK -bzx -dig +bBg +bBg bJx bLa bMD @@ -99238,7 +99174,7 @@ ckN aaa aaf aaf -aaa +lMJ aaa aaf aaa @@ -99456,12 +99392,12 @@ bnS bqj bsu btY -bqj -bsu -bEt -nhy -mcS -bvW +maP +xLL +bzx +bzx +bzx +bzx bzx bzx bzx @@ -99493,7 +99429,7 @@ ckQ cjt ckN aaf -aaf +ack cwf ack aaf @@ -99715,7 +99651,7 @@ bsv btZ bvV bxN -bGj +bvW dhZ bCP bvW @@ -99750,10 +99686,10 @@ cjt diJ dux dux -ack +dux cwg -ack -ack +dux +dux aaf aaa aaa @@ -99973,9 +99909,9 @@ baE bvW bxO bvW -bvW -bvW -bvW +dhZ +fDG +jdf bGm bHO bvW @@ -100007,9 +99943,9 @@ crh dxv ctn dux -dux -cfA -dux +sUM +cwh +dyw dux aaf aaf @@ -100233,7 +100169,7 @@ bzA bBm bCR bvW -syk +bvW bvW bvW bLd @@ -100256,7 +100192,7 @@ csT dux cxQ ckS -cmi +pbc cnk ckP cmi @@ -100264,8 +100200,8 @@ dvt csf cto dux -cvj -cwh +cfF +mSd cxb dux aaa @@ -100489,7 +100425,7 @@ bxQ bzB bBn bCS -eiS +bBn bQN dih bvW @@ -101717,7 +101653,7 @@ aaa aaa acT aaa -aaf +aee aee aee aee @@ -101974,7 +101910,7 @@ aaf aaf acU aak -aak +abN aef aeG afE @@ -102231,7 +102167,7 @@ aaa aaa aaf aaa -aaf +aee aee aee aee @@ -108650,7 +108586,7 @@ aaa aaa aaa wOY -abN +abe ach aax acN @@ -108908,7 +108844,7 @@ urv abe abe abe -aci +abL aax acO adh @@ -112876,7 +112812,7 @@ cFh cKH cLz wFH -cMk +bTs bTs bTs bTs @@ -113133,8 +113069,8 @@ cJN cCq cgN cMl -wOE bTs +lMJ aaf aaf aaf @@ -113391,7 +113327,7 @@ cCq cLA bTs bTs -bTs +lMJ aaf aaa aaa @@ -113599,8 +113535,8 @@ bDj bFb bGQ bGM -bJY -bLD +bNr +bLF bNp bOK bQu @@ -114113,7 +114049,7 @@ bDw bFd bGS bGM -bKa +bNp bLF bNr bOM @@ -117230,16 +117166,16 @@ cvX cwY crR cyJ -czB -cAG +cBs +cBs cBB cCC cDp +czB +cAG +cEz cyK -cyK -cyK -cyK -cPe +dxQ dvY cJY cKM @@ -117493,9 +117429,9 @@ cBC cyK cyK cyK -dvY -dyc -cub +cyK +cyK +cyK diP dvY cJZ @@ -117751,9 +117687,9 @@ cCD uun rSL dvY -cEz -dxQ dyc +gGH +pVL dvY cKa cKO @@ -119555,7 +119491,7 @@ aaf aaa aaf dvY -kDM +cJd dvY aaa dbN @@ -119811,13 +119747,13 @@ cEA aaf aaa aaa -ack +dvY cJf -ack -aaa -aaf -dbR +dvY aaa +dbN +gsT +dbN aaa aaa aaa @@ -119963,7 +119899,7 @@ aaf aaa aaa aaa -sdw +aaa aaa acP acP @@ -120068,9 +120004,9 @@ blx aaa aaa aaa -aaa -aaf -aaa +ack +uim +ack aaa aaf dbR @@ -121336,7 +121272,7 @@ ciL cgs csc dvY -evy +dxk krD lsv txj @@ -121593,7 +121529,7 @@ cpK ciL csc dvY -vLD +lMJ krD jyv ohj @@ -121850,7 +121786,7 @@ cpL crb csd dvY -vLD +lMJ krD krD noG @@ -123571,7 +123507,7 @@ aaa aaa aaf dni -amG +asB amH anN dnS @@ -123828,7 +123764,7 @@ aaf aaf aaf dnh -amH +avG dnh apd dnS @@ -124084,8 +124020,8 @@ aaa aaf aaa aaf -aaa -ack +dnh +aci dnh ape dnS @@ -127210,8 +127146,8 @@ aaa aaf bpw aaf -aaf -ack +cvj +kDM bxc bzg bAP @@ -127468,7 +127404,7 @@ aaf bpw aaa aaf -aaf +ack bxc bzh bAQ @@ -128260,9 +128196,9 @@ gJs bFZ bAR aaf -bxc +lNZ wxc -bxc +lNZ aaf aaa aaf @@ -128517,9 +128453,9 @@ bVN bXr bAR aaf -aMr -ccY -bBb +lNZ +wOE +lNZ aaf aaa aaf @@ -128774,7 +128710,7 @@ bVO bUJ bAR aaf -aMq +sdw ccY bgo aTQ @@ -129231,8 +129167,8 @@ aaa ack ack atn -bOY -avG +anN +dnS dqT aaf aaa @@ -129288,7 +129224,7 @@ bAR bAR bAR aaf -aMq +sdw ccY aVk aNC @@ -129488,8 +129424,8 @@ aaf aaf aaf dnh -dnh -lNZ +avJ +avG dqT aaf aaa @@ -129744,9 +129680,9 @@ aaa aaa aaf aaa -aaa -aaf -ack +dnh +dnh +bOY dqT aaf anT @@ -135948,7 +135884,7 @@ blA bnu bpH brU -aOV +cMk aaa aMq bzm @@ -136190,7 +136126,7 @@ aOU aOY aOY aOY -aTT +aNC aaa aaa aaa @@ -136208,7 +136144,7 @@ brV aRy aaa aaa -aTT +aNC aOY aOY aOY @@ -136447,7 +136383,7 @@ aOV aaa aaa aaa -aTU +aaf aaa aRy aRy @@ -136463,16 +136399,16 @@ bnw bpJ brW aRy -bvt -aaa -aTU +aRy +aRy +jQK aaa aaa aaa aaa aaa aaa -aTU +aaf aaa aaa aaa @@ -136719,9 +136655,9 @@ blC bnx bpK bsf -aRy -aRy -aRy +bGh +nix +bGh aRy aRy aRy @@ -136978,7 +136914,7 @@ bpL brY btL btL -btL +txh btL btL bCD @@ -137235,7 +137171,7 @@ bpM brZ btL bvu -bGh +bxq bzn bAU bCD @@ -139531,7 +139467,7 @@ aOV aaa aaa aaa -aTU +aaf aaa aRy aRy @@ -139549,14 +139485,14 @@ bsh aRy bvt aaa -aTU +aaf aaa aaa aaa aaa aaa aaa -aTU +aaf aaa aaa aaa @@ -139788,7 +139724,7 @@ aOX aNw aNw aNw -aTY +bJl aaa aaa aaa @@ -139806,14 +139742,14 @@ bsi aRy aaa aaa -aTY +bJl aNw aNw aNw aNw aNw aNw -aTY +bJl aNw aNw aNw diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index d3a1012177..a772122491 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -192,14 +192,14 @@ /area/ruin/unpowered/ash_walkers) "ft" = ( /obj/structure/stone_tile/block, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) "fN" = ( /obj/structure/stone_tile{ dir = 4 }, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "fQ" = ( @@ -529,7 +529,7 @@ }, /obj/structure/table/wood, /obj/item/clothing/head/helmet/roman/legionnaire, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "iK" = ( @@ -1829,8 +1829,8 @@ "An" = ( /obj/structure/stone_tile/slab, /obj/structure/table/wood, -/obj/item/twohanded/bonespear, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, +/obj/item/spear/bonespear, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "AH" = ( @@ -1840,7 +1840,7 @@ /obj/structure/stone_tile/cracked{ dir = 8 }, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) "AU" = ( @@ -2069,7 +2069,7 @@ }, /obj/structure/table/wood, /obj/item/scythe, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "HX" = ( @@ -2198,7 +2198,7 @@ }, /obj/structure/table/wood, /obj/item/storage/belt, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "Qk" = ( @@ -2425,7 +2425,7 @@ /obj/structure/stone_tile/cracked{ dir = 1 }, -/obj/item/twohanded/bonespear, +/obj/item/spear/bonespear, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/ash_walkers) "WT" = ( diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index ebdda21c5e..db44dfb92a 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -545,7 +545,7 @@ dir = 4 }, /obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -601,7 +601,7 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral{ @@ -1244,15 +1244,7 @@ /turf/closed/wall, /area/maintenance/starboard/fore) "abM" = ( -/obj/effect/turf_decal/stripes/line, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, +/obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/maintenance/starboard/fore) "abN" = ( @@ -1288,17 +1280,31 @@ /turf/open/floor/plating, /area/engine/gravity_generator) "abR" = ( -/obj/structure/lattice, -/turf/open/space, -/area/asteroid/nearstation) +/obj/machinery/vr_sleeper{ + dir = 4 + }, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/security/prison) "abS" = ( /obj/item/stack/ore/glass, /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, /area/asteroid/nearstation) "abT" = ( -/turf/closed/wall, -/area/asteroid/nearstation) +/obj/machinery/door/airlock{ + name = "Unisex Restroom" + }, +/turf/open/floor/plasteel/freezer, +/area/security/prison) "abU" = ( /turf/closed/wall/r_wall, /area/crew_quarters/heads/hos) @@ -1716,11 +1722,15 @@ /turf/open/floor/plating/asteroid, /area/asteroid/nearstation) "acE" = ( -/obj/effect/decal/cleanable/blood/old, -/turf/open/floor/plating{ - icon_state = "platingdmg1" +/obj/structure/sink{ + dir = 4; + pixel_x = 12 }, -/area/asteroid/nearstation) +/obj/machinery/shower{ + pixel_y = 26 + }, +/turf/open/floor/plasteel/freezer, +/area/security/prison) "acF" = ( /turf/open/floor/plating, /area/asteroid/nearstation) @@ -1735,9 +1745,8 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hos) "acH" = ( -/obj/effect/decal/cleanable/cobweb/cobweb2, -/turf/open/floor/plating, -/area/asteroid/nearstation) +/turf/closed/wall/r_wall, +/area/security/prison) "acI" = ( /obj/structure/window/reinforced{ dir = 8 @@ -1754,18 +1763,9 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/hos) "acJ" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/turf/open/floor/plasteel, -/area/asteroid/nearstation) +/obj/structure/girder, +/turf/open/floor/plating, +/area/security/prison) "acK" = ( /obj/structure/dresser, /obj/structure/sign/warning/vacuum{ @@ -2220,21 +2220,21 @@ /turf/open/floor/plating, /area/asteroid/nearstation) "adw" = ( -/turf/open/floor/plating{ - icon_state = "panelscorched" +/obj/machinery/camera{ + c_tag = "Prison - VR Sleepers" }, -/area/asteroid/nearstation) +/turf/open/floor/plasteel, +/area/security/prison) "adx" = ( -/obj/item/clothing/suit/space/orange, -/obj/item/clothing/head/helmet/space/orange, -/turf/open/floor/plating, +/obj/structure/sign/warning/securearea, +/turf/closed/wall/r_wall, /area/asteroid/nearstation) "ady" = ( /turf/closed/wall/rust, /area/quartermaster/qm) "adz" = ( -/obj/structure/sign/warning/vacuum, -/turf/closed/wall, +/obj/structure/lattice/catwalk, +/turf/open/floor/plating/asteroid/airless, /area/asteroid/nearstation) "adA" = ( /obj/machinery/status_display, @@ -2351,7 +2351,7 @@ /obj/structure/cable/white{ icon_state = "4-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/atmospherics/components/unary/vent_pump/on{ @@ -2666,9 +2666,11 @@ /turf/open/floor/plating, /area/asteroid/nearstation) "aem" = ( -/turf/open/floor/plating{ - icon_state = "platingdmg3" +/obj/structure/lattice/catwalk, +/obj/structure/sign/warning/securearea{ + pixel_x = 32 }, +/turf/open/floor/plating/asteroid/airless, /area/asteroid/nearstation) "aen" = ( /obj/structure/cable/white{ @@ -2691,10 +2693,8 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hos) "aep" = ( -/turf/open/floor/plating{ - icon_state = "platingdmg2" - }, -/area/asteroid/nearstation) +/turf/open/floor/plasteel, +/area/security/prison) "aeq" = ( /obj/machinery/door/airlock/silver{ name = "Bathroom" @@ -3225,36 +3225,39 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hos) "afe" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Security Maintenance"; - req_access_txt = "63" - }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, /obj/effect/turf_decal/stripes/line{ dir = 4 }, +/obj/machinery/door/firedoor, +/obj/machinery/turnstile{ + name = "Genpop Exit Turnstile"; + req_access_txt = "70"; + dir = 8 + }, /turf/open/floor/plasteel, -/area/security/brig) +/area/security/prison) "aff" = ( /turf/closed/wall, /area/crew_quarters/heads/hos) "afg" = ( -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ +/obj/item/stack/ore/glass, +/turf/open/floor/plating/asteroid/airless, +/area/asteroid/nearstation) +"afh" = ( +/obj/machinery/vr_sleeper{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Security Maintenance"; - req_access_txt = "63" +/obj/effect/turf_decal/tile/red{ + dir = 8 }, /turf/open/floor/plasteel, -/area/security/brig) -"afh" = ( -/obj/structure/barricade/wooden, -/turf/open/floor/plating, -/area/asteroid/nearstation) +/area/security/prison) "afi" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 8 @@ -3287,7 +3290,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/captain/private) "afl" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/wood, /area/crew_quarters/heads/captain/private) "afm" = ( @@ -3324,7 +3327,7 @@ /obj/machinery/recharger{ pixel_x = 5 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-15"; pixel_x = -6; pixel_y = 12 @@ -3691,9 +3694,14 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "afL" = ( -/obj/structure/girder/reinforced, -/turf/open/floor/plating, -/area/asteroid/nearstation) +/obj/machinery/hydroponics/soil, +/obj/item/seeds/carrot, +/obj/machinery/camera{ + c_tag = "Prison - Main Room"; + dir = 4 + }, +/turf/open/floor/plating/asteroid, +/area/security/prison) "afM" = ( /obj/item/stack/ore/iron, /obj/structure/barricade/wooden, @@ -3719,20 +3727,10 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "afP" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/obj/item/poster/random_contraband{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/poster/random_contraband{ - pixel_x = -3; - pixel_y = -3 - }, -/obj/item/poster/random_contraband, -/turf/open/floor/plasteel, -/area/asteroid/nearstation) +/obj/machinery/hydroponics/soil, +/obj/item/seeds/grass, +/turf/open/floor/plating/asteroid, +/area/security/prison) "afQ" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -4251,22 +4249,20 @@ /turf/closed/wall/r_wall, /area/security/brig) "agG" = ( -/obj/structure/reagent_dispensers/peppertank{ +/obj/machinery/newscaster{ pixel_y = 32 }, -/turf/open/floor/plasteel/dark, -/area/security/brig) +/turf/open/floor/plasteel, +/area/security/prison) "agH" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 +/obj/machinery/light/small{ + dir = 1 }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/obj/effect/turf_decal/loading_area{ + dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/security/brig) +/turf/open/floor/plasteel, +/area/security/prison) "agI" = ( /obj/structure/table/wood, /obj/item/paper_bin, @@ -4290,8 +4286,7 @@ department = "Head of Security's Desk"; departmentType = 5; name = "Head of Security RC"; - pixel_x = 30; - pixel_y = 0 + pixel_x = 30 }, /obj/machinery/computer/security/hos{ icon_state = "computer"; @@ -4794,27 +4789,23 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "ahu" = ( -/turf/closed/wall/r_wall, -/area/asteroid/nearstation) -"ahv" = ( -/obj/machinery/door/firedoor, -/obj/structure/cable/white{ - icon_state = "2-8" - }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/machinery/door/airlock/security/glass{ - name = "Security E.V.A. Storage"; - req_access_txt = "63" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Security Maintenance"; + req_access_txt = "63" + }, +/obj/machinery/door/firedoor, /turf/open/floor/plasteel, -/area/security/brig) +/area/security/prison) +"ahv" = ( +/obj/effect/turf_decal/loading_area{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) "ahw" = ( /turf/open/floor/plasteel/grimy, /area/crew_quarters/heads/hos) @@ -4853,24 +4844,23 @@ /turf/open/floor/plasteel, /area/crew_quarters/heads/hos) "ahz" = ( -/obj/structure/sign/nanotrasen{ - pixel_x = -32 +/obj/structure/reagent_dispensers/peppertank{ + pixel_y = 32 }, -/obj/machinery/light{ - dir = 8 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 }, /turf/open/floor/plasteel/dark, /area/security/brig) "ahA" = ( -/obj/structure/rack, -/obj/item/clothing/suit/fire/firefighter, -/obj/item/clothing/mask/gas, -/obj/item/clothing/head/hardhat/red, -/obj/effect/turf_decal/stripes/line{ - dir = 6 +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/structure/chair{ + dir = 8 }, /turf/open/floor/plasteel, -/area/asteroid/nearstation) +/area/security/prison) "ahB" = ( /obj/effect/turf_decal/sand/plating, /obj/item/stack/ore/silver, @@ -4878,17 +4868,34 @@ /turf/open/floor/plating, /area/asteroid/nearstation) "ahC" = ( -/obj/machinery/status_display/ai{ - pixel_x = 32 +/obj/structure/sign/nanotrasen{ + pixel_x = -32 }, +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/closet{ + name = "Evidence Closet" + }, +/obj/item/poster/random_contraband{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/poster/random_contraband{ + pixel_x = -3; + pixel_y = -3 + }, +/obj/item/poster/random_contraband, /turf/open/floor/plasteel/dark, /area/security/brig) "ahD" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 9 +/obj/machinery/light/small{ + brightness = 3; + dir = 8 }, -/turf/open/floor/plasteel, -/area/asteroid/nearstation) +/obj/item/reagent_containers/glass/bucket, +/turf/open/floor/plating/asteroid, +/area/security/prison) "ahE" = ( /obj/structure/table/wood, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ @@ -5266,16 +5273,8 @@ /turf/open/floor/plating, /area/asteroid/nearstation) "ail" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/landmark/start/chief_medical_officer, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/turf/closed/wall, +/area/medical/genetics) "aim" = ( /obj/structure/chair/office/dark{ dir = 8 @@ -5387,16 +5386,9 @@ /turf/open/floor/plasteel/dark, /area/security/brig) "aiv" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/security/brig) +/obj/item/cultivator, +/turf/open/floor/plating/asteroid, +/area/security/prison) "aiw" = ( /obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, /obj/item/stack/cable_coil/white, @@ -5551,21 +5543,28 @@ /turf/open/floor/plasteel, /area/quartermaster/storage) "aiJ" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/tile/yellow{ +/obj/machinery/light{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/medical/chemistry"; + dir = 1; + name = "Chemistry Lab APC"; + pixel_y = 25 + }, +/obj/structure/cable/white{ + icon_state = "0-2" + }, +/obj/item/kirbyplants{ + icon_state = "plant-21" + }, +/obj/machinery/camera{ + c_tag = "Chemistry" }, /obj/effect/turf_decal/tile/yellow{ dir = 8 }, -/obj/effect/landmark/start/chemist, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "aiK" = ( /obj/structure/closet/crate/bin, @@ -5651,23 +5650,20 @@ /turf/open/floor/plasteel/white, /area/science/research) "aiQ" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/tile/blue{ +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/obj/structure/cable/white{ + icon_state = "2-4" }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 }, -/obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/area/hallway/primary/port/aft) "aiR" = ( /obj/machinery/suit_storage_unit/security, /obj/machinery/firealarm{ @@ -5687,15 +5683,14 @@ /turf/open/floor/plasteel/dark, /area/security/brig) "aiS" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 10 +/obj/structure/sign/poster/official/do_not_question{ + pixel_y = -32 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 }, -/obj/structure/table, -/obj/item/extinguisher/mini, -/obj/item/tank/internals/emergency_oxygen/engi, -/obj/item/clothing/mask/breath, /turf/open/floor/plasteel, -/area/asteroid/nearstation) +/area/security/prison) "aiT" = ( /obj/structure/rack, /obj/item/gun/energy/ionrifle, @@ -5775,51 +5770,24 @@ /turf/open/floor/plating, /area/security/brig) "aja" = ( -/obj/structure/closet/secure_closet/brig{ - id = "brig1"; - name = "Cell 1 Locker" +/obj/machinery/status_display/ai{ + pixel_x = 32 }, -/obj/machinery/light/small{ - dir = 1 +/obj/structure/closet{ + name = "Evidence Closet" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel, +/turf/open/floor/plasteel/dark, /area/security/brig) "ajb" = ( -/obj/machinery/flasher{ - id = "brig1"; - pixel_y = 26 +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_y = -26 }, -/obj/structure/chair, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Security - Cell 1" - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, /turf/open/floor/plasteel, -/area/security/brig) +/area/security/prison) "ajc" = ( /obj/structure/cable/white{ icon_state = "0-8" @@ -5832,7 +5800,7 @@ /turf/open/floor/plating, /area/security/brig) "ajd" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -6176,7 +6144,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 10 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/camera{ @@ -6188,21 +6156,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard/fore) "ajG" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/landmark/start/chief_medical_officer, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/turf/closed/wall/r_wall, +/area/crew_quarters/heads/cmo) "ajH" = ( /obj/structure/plasticflaps/opaque, /obj/effect/turf_decal/delivery, @@ -6314,10 +6269,14 @@ /turf/open/floor/plasteel, /area/science/mixing) "ajQ" = ( -/obj/item/stack/ore/iron, -/obj/effect/turf_decal/sand/plating, -/turf/open/floor/plating, -/area/asteroid/nearstation) +/obj/effect/turf_decal/loading_area{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) "ajR" = ( /obj/machinery/photocopier, /obj/machinery/firealarm{ @@ -6425,27 +6384,23 @@ /turf/open/floor/plasteel, /area/security/brig) "ajZ" = ( -/obj/structure/cable/white{ - icon_state = "1-4" +/obj/effect/turf_decal/stripes/line{ + dir = 8 }, -/obj/structure/cable/white{ - icon_state = "4-8" +/obj/effect/turf_decal/stripes/line{ + dir = 4 }, -/obj/machinery/door/window/brigdoor/security/cell/westright{ - id = "brig1"; - name = "Cell 1" +/obj/machinery/door/firedoor, +/obj/machinery/turnstile{ + name = "Genpop Entrance Turnstile"; + req_access_txt = "69"; + dir = 4 }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, /turf/open/floor/plasteel, -/area/security/brig) +/area/security/prison) "aka" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -6457,21 +6412,15 @@ /turf/open/floor/plasteel, /area/security/brig) "akb" = ( -/obj/structure/cable/white{ - icon_state = "1-4" - }, -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 +/obj/effect/turf_decal/stripes/line{ + dir = 9 }, +/obj/structure/rack, +/obj/item/clothing/suit/fire/firefighter, +/obj/item/clothing/mask/gas, +/obj/item/clothing/head/hardhat/red, /turf/open/floor/plasteel, -/area/security/brig) +/area/maintenance/port/fore) "akc" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/red{ @@ -7158,11 +7107,6 @@ /turf/open/floor/plasteel, /area/security/brig) "akZ" = ( -/obj/machinery/door_timer{ - id = "brig1"; - name = "Cell 1"; - pixel_x = 32 - }, /obj/structure/chair{ dir = 8 }, @@ -7170,6 +7114,9 @@ dir = 4 }, /obj/effect/turf_decal/tile/red, +/obj/machinery/status_display{ + pixel_x = 32 + }, /turf/open/floor/plasteel, /area/security/brig) "ala" = ( @@ -7273,7 +7220,7 @@ /turf/closed/wall, /area/hallway/primary/central) "alm" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/light{ @@ -7329,7 +7276,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "als" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light{ @@ -8019,7 +7966,7 @@ pixel_y = -24 }, /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/brown, @@ -8681,7 +8628,7 @@ /turf/open/floor/plasteel, /area/security/brig) "anF" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/door_timer{ @@ -8752,7 +8699,7 @@ name = "Station Intercom"; pixel_x = -26 }, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/chief) "anL" = ( @@ -9097,7 +9044,7 @@ /turf/open/floor/plasteel, /area/quartermaster/miningdock) "aon" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/cable/white{ @@ -10513,21 +10460,8 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard/fore) "aqo" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/turf/closed/wall/r_wall, +/area/maintenance/port/aft) "aqp" = ( /obj/machinery/autolathe, /obj/structure/extinguisher_cabinet{ @@ -10615,17 +10549,15 @@ /turf/open/floor/plating, /area/crew_quarters/heads/hos) "aqx" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 4 +/obj/structure/cable/white{ + icon_state = "2-4" }, -/obj/effect/landmark/xeno_spawn, -/obj/structure/sign/warning/vacuum{ - pixel_x = -32; - pixel_y = 32 +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 }, -/obj/effect/turf_decal/delivery, -/turf/open/floor/plasteel, -/area/maintenance/port) +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aqy" = ( /obj/structure/cable/white, /obj/effect/spawner/structure/window/reinforced, @@ -10813,7 +10745,7 @@ /turf/open/floor/plasteel, /area/security/brig) "aqP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/firealarm{ @@ -11151,11 +11083,18 @@ /turf/open/floor/plating, /area/maintenance/port/fore) "art" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 10 +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/obj/effect/turf_decal/loading_area{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, /turf/open/floor/plasteel, -/area/maintenance/port/fore) +/area/security/prison) "aru" = ( /obj/machinery/newscaster/security_unit{ pixel_x = -32 @@ -11740,7 +11679,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/bar/atrium) "ase" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -11800,7 +11739,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/bar/atrium) "asi" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/red{ @@ -12723,24 +12662,14 @@ /turf/open/floor/wood, /area/security/detectives_office) "atE" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 +/obj/structure/cable/white{ + icon_state = "4-8" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/door/airlock/external{ - name = "External Airlock"; - req_access_txt = "13" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/turf/open/floor/plating, +/area/maintenance/port/aft) "atF" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -13073,7 +13002,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -13317,7 +13246,6 @@ dir = 9 }, /obj/machinery/computer/security/wooden_tv{ - pixel_x = 0; pixel_y = 4 }, /turf/open/floor/wood, @@ -13712,7 +13640,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ @@ -14025,15 +13953,16 @@ /turf/open/floor/wood, /area/security/detectives_office) "avB" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/structure/sign/warning/vacuum{ - pixel_x = -32; - pixel_y = 32 +/turf/open/floor/plating{ + icon_state = "panelscorched" }, -/turf/open/floor/plating, -/area/maintenance/port) +/area/maintenance/port/aft) "avC" = ( /obj/structure/sign/poster/ripped, /turf/closed/wall/rust, @@ -14297,7 +14226,7 @@ dir = 8; pixel_x = 24 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral, @@ -14690,11 +14619,16 @@ /turf/open/floor/engine/o2, /area/engine/atmos) "awB" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/maintenance/port/aft) "awC" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 @@ -14730,27 +14664,46 @@ /area/maintenance/starboard/aft) "awE" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 }, /turf/open/floor/plating, -/area/maintenance/port) +/area/maintenance/port/aft) "awF" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible, /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/atmos) "awG" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/maintenance/port) -"awH" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, /obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"awH" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 }, -/obj/machinery/light/small, -/obj/structure/closet/emcloset/anchored, -/turf/open/floor/plasteel, -/area/maintenance/port) +/turf/closed/wall/r_wall, +/area/maintenance/port/aft) "awI" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 5 @@ -14778,11 +14731,15 @@ /turf/open/floor/plasteel/dark/corner, /area/engine/atmos) "awL" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, /turf/open/floor/plating, -/area/maintenance/port) +/area/maintenance/port/aft) "awM" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -15045,69 +15002,72 @@ /turf/open/floor/plasteel, /area/maintenance/starboard) "axh" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/structure/closet, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 3; + name = "3maintenance loot spawner" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plating/airless, -/area/maintenance/port) +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "axi" = ( /obj/machinery/air_sensor/atmos/oxygen_tank, /turf/open/floor/engine/o2, /area/engine/atmos) "axj" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/turf/open/floor/wood, +/area/library) "axk" = ( +/obj/structure/girder, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"axl" = ( +/obj/structure/closet/firecloset, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/structure/closet/crate, -/obj/item/stack/ore/silver, -/obj/item/stack/ore/iron, -/obj/item/stack/ore/iron, -/obj/item/stack/ore/iron, -/obj/item/pickaxe/emergency, /turf/open/floor/plasteel, -/area/maintenance/port) -"axl" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/area/maintenance/port/aft) "axm" = ( /obj/machinery/atmospherics/components/unary/thermomachine/freezer, /turf/open/floor/plasteel, /area/engine/atmos) "axn" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/rack, +/obj/item/reagent_containers/food/drinks/bottle/whiskey, +/obj/effect/spawner/lootdrop/maintenance, +/obj/machinery/light/small, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ dir = 1 }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "axo" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/effect/turf_decal/stripes/line{ @@ -15132,7 +15092,7 @@ /obj/machinery/status_display/ai{ pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/bot, @@ -15384,22 +15344,20 @@ /turf/open/floor/carpet, /area/crew_quarters/dorms) "axL" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" +/obj/structure/rack, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 2; + name = "2maintenance loot spawner" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, +/obj/effect/turf_decal/delivery, /obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 + dir = 1 }, /turf/open/floor/plasteel, -/area/maintenance/port) +/area/maintenance/port/aft) "axM" = ( /obj/structure/table/wood, /obj/item/lipstick/random{ @@ -15549,12 +15507,11 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/bar/atrium) "axU" = ( -/obj/structure/table/wood, -/obj/item/paper_bin, -/obj/item/pen, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/maintenance/port/aft) "axV" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/newscaster{ @@ -15571,19 +15528,82 @@ /turf/closed/wall, /area/hallway/secondary/exit) "axX" = ( -/obj/effect/landmark/xeno_spawn, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall/r_wall/rust, +/area/maintenance/port/aft) +"axY" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/landmark/event_spawn, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"axZ" = ( +/turf/closed/wall/r_wall/rust, +/area/security/prison) +"aya" = ( +/obj/machinery/door/firedoor, +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/door/airlock/security/glass{ + name = "Security E.V.A. Storage"; + req_access_txt = "63" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ dir = 1 }, -/turf/open/floor/wood, -/area/maintenance/port) -"axY" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/security/brig) +"ayb" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"ayc" = ( +/obj/effect/turf_decal/tile/red{ dir = 4 }, -/obj/item/cigbutt, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"ayd" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/closet/crate, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 2; + name = "2maintenance loot spawner" + }, +/turf/open/floor/plasteel, +/area/maintenance/port/fore) +"aye" = ( +/obj/machinery/hydroponics/soil, +/obj/item/seeds/ambrosia, +/turf/open/floor/plating/asteroid, +/area/security/prison) +"ayf" = ( +/obj/machinery/hydroponics/soil, +/obj/item/seeds/potato, +/turf/open/floor/plating/asteroid, +/area/security/prison) +"ayg" = ( +/obj/item/stack/ore/glass, +/turf/open/floor/plating/asteroid, +/area/asteroid/nearstation) "ayh" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ dir = 8 @@ -15746,6 +15766,16 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/dorms) +"ayy" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/closet/crate{ + icon_state = "crateopen" + }, +/obj/effect/spawner/lootdrop/maintenance, +/turf/open/floor/plasteel, +/area/maintenance/port/fore) "ayz" = ( /turf/open/floor/plasteel/grimy, /area/crew_quarters/dorms) @@ -15768,6 +15798,30 @@ /obj/item/bedsheet/red, /turf/open/floor/carpet, /area/crew_quarters/dorms) +"ayD" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/security/glass{ + id_tag = "secinterior"; + name = "Brig"; + req_access_txt = "63" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plasteel, +/area/security/brig) "ayE" = ( /obj/structure/table/wood, /obj/item/instrument/violin, @@ -16095,6 +16149,95 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/hallway/secondary/exit) +"azc" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/machinery/light/small, +/turf/open/floor/plasteel, +/area/security/brig) +"azd" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plasteel, +/area/security/brig) +"aze" = ( +/obj/machinery/door/poddoor/preopen{ + id = "brigfront"; + name = "Brig Blast door" + }, +/obj/machinery/turnstile{ + name = "Genpop Exit Turnstile"; + req_access_txt = "70"; + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/security/brig) +"azf" = ( +/obj/item/clothing/suit/space/orange, +/obj/item/clothing/head/helmet/space/orange, +/turf/open/floor/plating/asteroid, +/area/asteroid/nearstation) +"azg" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/fore) +"azh" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 10 + }, +/obj/structure/table, +/obj/item/extinguisher/mini, +/obj/item/tank/internals/emergency_oxygen/engi, +/obj/item/clothing/mask/breath, +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/fore) +"azi" = ( +/turf/closed/wall, +/area/security/prison) +"azj" = ( +/obj/machinery/light/small{ + brightness = 3; + dir = 8 + }, +/obj/structure/toilet{ + dir = 8 + }, +/turf/open/floor/plasteel/freezer, +/area/security/prison) +"azk" = ( +/obj/item/stack/ore/silver, +/obj/item/stack/ore/iron, +/turf/open/floor/plating/asteroid/airless, +/area/asteroid/nearstation) "azl" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/n2{ dir = 4 @@ -16123,6 +16266,15 @@ dir = 1 }, /area/engine/atmos) +"azn" = ( +/obj/machinery/door/airlock/public/glass, +/turf/open/floor/plasteel, +/area/security/prison) +"azo" = ( +/obj/machinery/holopad, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel, +/area/security/prison) "azp" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -16446,6 +16598,13 @@ icon_state = "platingdmg1" }, /area/maintenance/starboard/central) +"azQ" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/vending/sustenance, +/turf/open/floor/plasteel, +/area/security/prison) "azR" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -16558,6 +16717,43 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aAa" = ( +/obj/machinery/cryopod, +/obj/machinery/computer/cryopod{ + pixel_y = 26 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aAb" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/security/prison) +"aAc" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aAd" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aAe" = ( +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aAf" = ( +/obj/machinery/biogenerator, +/turf/open/floor/plasteel, +/area/security/prison) "aAg" = ( /turf/open/floor/engine/air, /area/engine/atmos) @@ -16582,6 +16778,31 @@ /obj/structure/grille, /turf/closed/wall/r_wall, /area/engine/atmos) +"aAk" = ( +/obj/machinery/seed_extractor, +/turf/open/floor/plasteel, +/area/security/prison) +"aAl" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/sink{ + dir = 8; + pixel_x = -12; + pixel_y = 2 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aAm" = ( +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/item/plant_analyzer, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) "aAn" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 6 @@ -16589,6 +16810,12 @@ /obj/machinery/meter, /turf/open/floor/plasteel, /area/engine/atmos) +"aAo" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) "aAp" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 @@ -16676,6 +16903,23 @@ }, /turf/open/floor/plasteel, /area/engine/atmos) +"aAw" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Security Maintenance"; + req_access_txt = "63" + }, +/turf/open/floor/plasteel, +/area/security/prison) "aAx" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /obj/effect/turf_decal/tile/neutral{ @@ -17017,6 +17261,12 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/central) +"aAU" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/security/prison) "aAV" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -17166,29 +17416,151 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aBi" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/turf/open/floor/plating, +/area/security/prison) +"aBj" = ( +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/obj/machinery/power/apc{ + areastring = "/area/security/prison"; + dir = 8; + name = "Prison Wing APC"; + pixel_x = -26 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/security/prison) +"aBk" = ( +/obj/structure/closet/secure_closet/genpop, +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aBl" = ( +/obj/machinery/airalarm/unlocked{ + dir = 4; + pixel_x = -23 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/security/prison) +"aBm" = ( +/obj/structure/closet/secure_closet/genpop, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aBn" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/wood, +/area/library) +"aBo" = ( +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/security/brig) "aBp" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/atmos/oxygen_output{ dir = 1 }, /turf/open/floor/engine/o2, /area/engine/atmos) +"aBq" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/security/brig) "aBr" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/atmos/nitrogen_output{ dir = 1 }, /turf/open/floor/engine/n2, /area/engine/atmos) +"aBs" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/security/prison) "aBt" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/nitrogen_input{ dir = 1 }, /turf/open/floor/engine/n2, /area/engine/atmos) +"aBu" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aBv" = ( +/obj/structure/closet/secure_closet/genpop, +/obj/machinery/camera{ + c_tag = "Prison - Entryway"; + dir = 8 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aBw" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/security/brig) +"aBx" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/dark, +/area/security/brig) "aBy" = ( /obj/effect/turf_decal/stripes/line, /obj/machinery/atmospherics/pipe/simple/cyan/visible, /turf/open/floor/plasteel, /area/engine/atmos) +"aBz" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/security/prison) "aBA" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -17548,7 +17920,7 @@ /obj/machinery/light{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/red{ @@ -17692,18 +18064,114 @@ /obj/structure/sign/warning/vacuum, /turf/open/floor/plating, /area/hallway/secondary/exit) +"aCo" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/security/prison) +"aCp" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/security/brig) +"aCq" = ( +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/security/brig) +"aCr" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/door/airlock/security/glass{ + name = "Gen-Pop Access"; + req_access_txt = "2" + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/security/prison) "aCs" = ( /obj/machinery/portable_atmospherics/canister/oxygen, /obj/machinery/light/small, /obj/machinery/atmospherics/miner/oxygen, /turf/open/floor/engine/o2, /area/engine/atmos) +"aCt" = ( +/obj/machinery/door/firedoor, +/obj/machinery/turnstile{ + name = "Genpop Exit Turnstile"; + icon_state = "turnstile_map"; + dir = 1; + req_access_txt = "70" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/security/prison) +"aCu" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/security/brig) +"aCv" = ( +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/security/brig) "aCw" = ( /obj/machinery/portable_atmospherics/canister/nitrogen, /obj/machinery/light/small, /obj/machinery/atmospherics/miner/nitrogen, /turf/open/floor/engine/n2, /area/engine/atmos) +"aCx" = ( +/turf/open/floor/wood, +/area/library) +"aCy" = ( +/turf/closed/wall, +/area/crew_quarters/heads/cmo) "aCz" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible{ dir = 1 @@ -17727,6 +18195,15 @@ }, /turf/open/floor/plasteel/white/corner, /area/engine/atmos) +"aCB" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/turf/open/floor/wood, +/area/library) "aCC" = ( /obj/machinery/firealarm{ dir = 1; @@ -18128,6 +18605,13 @@ dir = 1 }, /area/hallway/secondary/exit) +"aDf" = ( +/obj/effect/landmark/barthpot, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, +/turf/open/floor/wood, +/area/library) "aDg" = ( /obj/structure/cable/white{ icon_state = "1-8" @@ -18170,12 +18654,90 @@ }, /turf/open/space/basic, /area/space) +"aDk" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) "aDl" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 }, /turf/open/floor/plasteel, /area/engine/atmos) +"aDm" = ( +/obj/structure/bookcase/random/fiction, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/library) +"aDn" = ( +/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/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/library) +"aDo" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/library) +"aDp" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) +"aDq" = ( +/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/structure/closet/crate/bin, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/turf/open/floor/plasteel/dark, +/area/library) "aDr" = ( /obj/structure/sign/warning/nosmoking, /obj/machinery/atmospherics/pipe/simple/cyan/hidden{ @@ -18278,7 +18840,7 @@ }, /area/engine/break_room) "aDB" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/yellow{ @@ -18651,6 +19213,106 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aEg" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall/r_wall, +/area/maintenance/port/aft) +"aEh" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet{ + pixel_y = 26 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/camera{ + c_tag = "Aft Primary Hallway 4" + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) +"aEi" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_y = 24 + }, +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) +"aEj" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating{ + icon_state = "platingdmg2" + }, +/area/maintenance/port/aft) +"aEk" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/power/apc{ + areastring = "/area/hallway/primary/port/aft"; + dir = 1; + name = "Port Quarter Hallway APC"; + pixel_y = 24 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) +"aEl" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) +"aEm" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port/aft) "aEn" = ( /obj/machinery/shieldgen, /obj/structure/sign/warning/nosmoking{ @@ -18965,7 +19627,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/dorms) "aEL" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/status_display{ @@ -19308,6 +19970,17 @@ /obj/effect/landmark/blobstart, /turf/open/floor/plating, /area/maintenance/starboard/central) +"aFh" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/hallway/primary/port/aft) "aFi" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -19318,6 +19991,21 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"aFj" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/hallway/primary/port/aft) "aFk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -19341,6 +20029,10 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aFm" = ( +/obj/machinery/status_display, +/turf/closed/wall, +/area/medical/genetics) "aFn" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 @@ -19360,6 +20052,25 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aFo" = ( +/turf/closed/wall/rust, +/area/medical/genetics) +"aFp" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aFq" = ( /obj/machinery/power/emitter, /obj/machinery/light/small, @@ -19714,11 +20425,18 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/plasteel, /area/hallway/primary/port) +"aFM" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aFN" = ( /obj/structure/extinguisher_cabinet{ pixel_x = -26 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/camera{ @@ -19869,6 +20587,10 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"aFZ" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall, +/area/crew_quarters/heads/cmo) "aGa" = ( /obj/effect/landmark/event_spawn, /obj/item/beacon, @@ -19902,9 +20624,28 @@ }, /turf/open/floor/plating, /area/hallway/secondary/exit) +"aGd" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/hallway/primary/port/aft) "aGe" = ( /turf/closed/wall/r_wall, /area/engine/gravity_generator) +"aGf" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "geneticsbot"; + name = "Genetics Privacy Shutters" + }, +/turf/open/floor/plating, +/area/medical/genetics) "aGg" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -19961,6 +20702,29 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"aGl" = ( +/obj/machinery/door/firedoor, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/table/reinforced, +/obj/machinery/door/window/southleft{ + name = "Genetics Desk"; + req_access_txt = "5; 9; 68" + }, +/obj/item/folder/yellow, +/obj/item/pen, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "geneticsbot"; + name = "Genetics Privacy Shutters" + }, +/turf/open/floor/plasteel, +/area/medical/genetics) "aGm" = ( /obj/structure/sign/warning/radiation, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -20051,7 +20815,7 @@ /turf/open/floor/plasteel, /area/engine/break_room) "aGu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/yellow, @@ -20126,6 +20890,19 @@ }, /turf/open/floor/plasteel, /area/maintenance/port/central) +"aGC" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aGD" = ( /obj/machinery/power/apc/highcap/five_k{ areastring = "/area/maintenance/port/central"; @@ -20153,6 +20930,24 @@ }, /turf/open/floor/plating, /area/maintenance/port/central) +"aGF" = ( +/obj/structure/mirror{ + pixel_x = -28 + }, +/obj/machinery/shower{ + dir = 4; + name = "emergency shower" + }, +/obj/machinery/newscaster{ + pixel_y = 32 + }, +/obj/machinery/door/window/southleft, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aGG" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -20431,6 +21226,97 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"aGY" = ( +/obj/structure/bed/dogbed/runtime, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/structure/sign/poster/official/medical_green_cross{ + pixel_x = -32 + }, +/obj/machinery/camera{ + c_tag = "CMO's Office"; + dir = 4 + }, +/mob/living/simple_animal/pet/cat/Runtime, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/heads/cmo) +"aGZ" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/loading_area, +/obj/effect/turf_decal/stripes/corner{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) +"aHa" = ( +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -24 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/delivery, +/obj/structure/table/glass, +/obj/item/storage/firstaid/brute{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/storage/firstaid/brute{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/brute{ + pixel_x = -3; + pixel_y = -3 + }, +/obj/structure/window/reinforced/spawner/east, +/obj/structure/window/reinforced/spawner/north, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) +"aHb" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/closed/wall, +/area/medical/morgue) +"aHc" = ( +/obj/machinery/light{ + dir = 1 + }, +/obj/machinery/door/window/southright, +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_y = 26 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) +"aHd" = ( +/obj/structure/window/reinforced, +/obj/machinery/clonepod, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aHe" = ( /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/tile/neutral{ @@ -20445,6 +21331,15 @@ }, /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) +"aHf" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/door/poddoor/shutters/preopen{ + id = "geneticsbot"; + name = "Genetics Privacy Shutters" + }, +/turf/open/floor/plating, +/area/medical/genetics) "aHg" = ( /obj/machinery/camera{ c_tag = "Gravity Generator Room"; @@ -20467,6 +21362,17 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, /area/engine/engineering) +"aHi" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/door/airlock/grunge{ + name = "Morgue"; + req_access_txt = "5" + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aHj" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -20600,6 +21506,11 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aHs" = ( +/obj/effect/turf_decal/tile/blue, +/obj/machinery/vending/medical, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aHt" = ( /obj/structure/cable/white{ icon_state = "4-8" @@ -20619,7 +21530,7 @@ /obj/structure/cable/white{ icon_state = "2-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -20803,6 +21714,37 @@ }, /turf/open/floor/plating, /area/maintenance/port/central) +"aHG" = ( +/obj/machinery/power/apc{ + areastring = "/area/medical/genetics"; + dir = 8; + name = "Genetics Lab APC"; + pixel_x = -26; + pixel_y = 3 + }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/obj/structure/table, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/button/door{ + id = "geneticsbot"; + name = "Genetics Shutter Control"; + pixel_x = -24; + pixel_y = -8; + req_access_txt = "5; 9; 68" + }, +/obj/item/clothing/gloves/color/latex, +/obj/item/storage/box/disks{ + pixel_x = -2; + pixel_y = 4 + }, +/obj/item/storage/box/rxglasses, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aHH" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -20830,6 +21772,25 @@ }, /turf/open/floor/plating, /area/maintenance/port/central) +"aHJ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/obj/structure/chair/office/light{ + dir = 4 + }, +/obj/effect/landmark/start/geneticist, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/medical/genetics) +"aHK" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/medical/morgue) "aHL" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/closed/wall, @@ -20927,7 +21888,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/bar/atrium) "aHU" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/sign/poster/random{ @@ -20966,6 +21927,23 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/kitchen) +"aHX" = ( +/obj/structure/sign/warning/nosmoking{ + pixel_x = 32 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/scan_consolenew{ + dir = 8 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aHY" = ( /obj/structure/table, /obj/item/paper_bin, @@ -20980,7 +21958,7 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/starboard) "aHZ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/bot, @@ -21581,7 +22559,7 @@ /area/hallway/primary/starboard) "aJa" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/machinery/firealarm{ dir = 4; pixel_x = -24 @@ -21605,6 +22583,66 @@ }, /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/exit) +"aJd" = ( +/obj/machinery/computer/cloning{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aJe" = ( +/obj/structure/table, +/obj/machinery/airalarm/unlocked{ + dir = 4; + pixel_x = -23 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/item/clipboard, +/obj/item/folder/white, +/obj/item/storage/pill_bottle/mutadone{ + pixel_x = -8; + pixel_y = 8 + }, +/obj/item/storage/pill_bottle/mannitol{ + pixel_x = -8; + pixel_y = 2 + }, +/obj/item/radio/headset/headset_medsci, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) +"aJf" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/turf/open/floor/plasteel{ + heat_capacity = 1e+006 + }, +/area/medical/genetics) +"aJg" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/dna_scannernew, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/delivery, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aJh" = ( /obj/machinery/light{ dir = 8 @@ -21712,6 +22750,20 @@ }, /turf/open/floor/plasteel, /area/engine/gravity_generator) +"aJo" = ( +/obj/item/radio/intercom{ + name = "Station Intercom"; + pixel_x = -26 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/vending/wardrobe/gene_wardrobe, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "aJp" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -21758,6 +22810,20 @@ /obj/machinery/atmospherics/pipe/simple/green/visible, /turf/closed/wall/r_wall, /area/engine/supermatter) +"aJv" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/landmark/start/geneticist, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "aJw" = ( /obj/machinery/atmospherics/components/binary/pump{ dir = 1; @@ -21766,6 +22832,17 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"aJx" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aJy" = ( /obj/structure/cable{ icon_state = "1-2" @@ -21788,6 +22865,22 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aJA" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/requests_console{ + department = "Genetics"; + name = "Genetics RC"; + pixel_x = 28; + pixel_y = 0 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "aJB" = ( /obj/structure/table/reinforced, /obj/item/stack/sheet/metal/fifty, @@ -22004,6 +23097,28 @@ }, /turf/open/floor/plasteel, /area/hydroponics) +"aJN" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/landmark/blobstart, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aJO" = ( +/obj/machinery/camera{ + c_tag = "Genetics Cloning"; + dir = 4 + }, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "aJP" = ( /obj/effect/turf_decal/tile/blue{ dir = 1 @@ -22241,6 +23356,59 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aKk" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aKl" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating{ + icon_state = "panelscorched" + }, +/area/maintenance/port/aft) +"aKm" = ( +/turf/closed/wall, +/area/maintenance/port/aft) +"aKn" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/closed/wall, +/area/maintenance/port/aft) +"aKo" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aKp" = ( /obj/machinery/airalarm{ dir = 4; @@ -22277,6 +23445,18 @@ }, /turf/open/floor/plasteel/dark, /area/engine/gravity_generator) +"aKr" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/effect/landmark/xeno_spawn, +/obj/structure/sign/warning/vacuum{ + pixel_x = -32; + pixel_y = 32 + }, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aKs" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/command/glass{ @@ -22419,6 +23599,12 @@ }, /turf/open/floor/engine, /area/engine/supermatter) +"aKB" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aKC" = ( /obj/machinery/atmospherics/components/binary/pump{ name = "Gas to Chamber" @@ -22437,6 +23623,25 @@ /obj/effect/turf_decal/bot, /turf/open/floor/plasteel/dark, /area/engine/engineering) +"aKF" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aKG" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -22484,6 +23689,12 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"aKJ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aKK" = ( /obj/structure/table/reinforced, /obj/structure/cable/white{ @@ -22524,8 +23735,8 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/rcl/pre_loaded, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -22699,6 +23910,9 @@ }, /turf/open/floor/plasteel, /area/hydroponics) +"aKV" = ( +/turf/closed/wall/r_wall, +/area/medical/virology) "aKW" = ( /obj/machinery/seed_extractor, /obj/effect/turf_decal/bot, @@ -22953,6 +24167,56 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"aLn" = ( +/obj/machinery/smartfridge/chemistry/virology/preloaded, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aLo" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -26 + }, +/obj/structure/disposalpipe/trunk, +/obj/effect/turf_decal/stripes/red/full, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/machinery/disposal/bin{ + name = "corpse disposal unit" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aLp" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aLq" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aLr" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aLs" = ( +/turf/closed/wall/r_wall/rust, +/area/maintenance/port/aft) "aLt" = ( /obj/effect/turf_decal/tile/brown{ dir = 1 @@ -22963,6 +24227,77 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aLu" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/window/reinforced/spawner/north, +/obj/machinery/door/window/eastright{ + name = "Monkey Pen"; + req_access_txt = "5; 9; 68" + }, +/turf/open/floor/plasteel/freezer, +/area/medical/genetics) +"aLv" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aLw" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/medical/virology) +"aLx" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aLy" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/maintenance/port/aft) +"aLz" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/light/small, +/obj/structure/closet/emcloset/anchored, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aLA" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/tile/purple, +/obj/structure/chair/office/light, +/obj/effect/landmark/start/geneticist, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aLB" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aLC" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/item/cigbutt, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aLD" = ( /obj/machinery/power/port_gen/pacman, /obj/effect/turf_decal/stripes/line{ @@ -23060,6 +24395,12 @@ /obj/item/clothing/glasses/meson/engine, /turf/open/floor/plasteel, /area/engine/gravity_generator) +"aLL" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating/airless, +/area/maintenance/port/aft) "aLM" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -23154,6 +24495,11 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aLX" = ( +/obj/structure/table/wood, +/obj/item/gun/ballistic/automatic/toy/pistol/unrestricted, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aLY" = ( /obj/effect/turf_decal/tile/yellow{ dir = 1 @@ -23334,6 +24680,12 @@ }, /turf/open/floor/plasteel, /area/hydroponics) +"aMl" = ( +/obj/structure/disposalpipe/segment, +/obj/structure/window/reinforced/spawner/east, +/obj/item/storage/box/monkeycubes, +/turf/open/floor/plasteel/freezer, +/area/medical/genetics) "aMm" = ( /obj/structure/cable/white{ icon_state = "2-4" @@ -23415,7 +24767,7 @@ /turf/open/floor/grass, /area/hydroponics) "aMt" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light{ @@ -23453,6 +24805,48 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/bar/atrium) +"aMv" = ( +/obj/structure/table/wood, +/obj/item/clothing/gloves/color/black, +/obj/item/taperecorder, +/obj/machinery/light/small{ + dir = 1 + }, +/obj/structure/sign/poster/contraband/random{ + pixel_y = 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{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aMw" = ( +/obj/structure/rack, +/obj/item/storage/briefcase{ + pixel_x = -3; + pixel_y = 3 + }, +/obj/item/storage/secure/briefcase, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/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/maintenance/port/aft) "aMx" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 10 @@ -23463,7 +24857,7 @@ /turf/open/floor/plating, /area/maintenance/starboard/central) "aMy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/bot, @@ -23476,7 +24870,7 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/starboard) "aMz" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/brown{ @@ -23515,6 +24909,56 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aMD" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/structure/sign/poster/contraband/random, +/turf/closed/wall, +/area/maintenance/port/aft) +"aME" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aMF" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/closet/crate, +/obj/item/stack/ore/silver, +/obj/item/stack/ore/iron, +/obj/item/stack/ore/iron, +/obj/item/stack/ore/iron, +/obj/item/pickaxe/emergency, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aMG" = ( +/obj/structure/girder, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aMH" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aMI" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aMJ" = ( /turf/closed/wall/r_wall, /area/tcommsat/server) @@ -23579,6 +25023,22 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aMQ" = ( +/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/manifold/supply/hidden{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aMR" = ( /obj/machinery/camera{ c_tag = "Supermatter Chamber"; @@ -23637,6 +25097,17 @@ }, /turf/open/floor/engine, /area/engine/supermatter) +"aMY" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/dna_scannernew, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) "aMZ" = ( /obj/structure/cable{ icon_state = "1-8" @@ -23819,6 +25290,43 @@ }, /turf/open/floor/plasteel/dark, /area/hydroponics) +"aNo" = ( +/obj/machinery/light_switch{ + pixel_x = -24; + pixel_y = -38 + }, +/obj/machinery/button/door{ + desc = "A remote control switch for the medbay foyer."; + id = "cloningfoyer"; + name = "Cloning Doors Control"; + normaldoorcontrol = 1; + pixel_x = -24; + pixel_y = -24 + }, +/obj/structure/closet/crate/freezer/surplus_limbs, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aNp" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/door/airlock/medical/glass{ + name = "Genetics"; + req_access_txt = "5; 9; 68" + }, +/turf/open/floor/plasteel, +/area/medical/genetics) "aNq" = ( /obj/machinery/hydroponics/constructable, /obj/structure/cable/white, @@ -24036,6 +25544,94 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/hallway/secondary/exit) +"aNL" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aNM" = ( +/obj/machinery/holopad, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/bot, +/obj/effect/landmark/start/geneticist, +/turf/open/floor/plasteel, +/area/medical/genetics) +"aNN" = ( +/obj/machinery/dna_scannernew, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aNO" = ( +/obj/machinery/camera{ + c_tag = "Genetics Lab"; + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/computer/scan_consolenew{ + icon_state = "computer"; + dir = 1 + }, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/medical/genetics) +"aNP" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/medical/genetics) +"aNQ" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/medical/glass{ + id_tag = "cloningfoyer"; + name = "Cloning Lab"; + req_access_txt = "5" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/medical/genetics) +"aNR" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plating, +/area/medical/genetics) +"aNS" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/obj/structure/disposalpipe/segment, +/obj/effect/landmark/start/paramedic, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aNT" = ( /obj/machinery/announcement_system, /obj/machinery/status_display/ai{ @@ -24128,6 +25724,42 @@ /obj/machinery/power/supermatter_crystal/shard/engine, /turf/open/floor/engine, /area/engine/supermatter) +"aOb" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/machinery/requests_console{ + announcementConsole = 1; + department = "Chief Medical Officer's Desk"; + departmentType = 5; + name = "Chief Medical Officer RC"; + pixel_y = 28 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) +"aOc" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aOd" = ( /obj/machinery/power/apc{ areastring = "/area/engine/engineering"; @@ -24141,6 +25773,29 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aOe" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/command{ + name = "Chief Medical Officer's Office"; + req_access_txt = "40" + }, +/obj/machinery/door/firedoor, +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/turf/open/floor/plasteel, +/area/crew_quarters/heads/cmo) "aOf" = ( /obj/machinery/door/airlock{ name = "Custodial Closet"; @@ -24156,6 +25811,24 @@ }, /turf/open/floor/plasteel, /area/janitor) +"aOg" = ( +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/newscaster{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aOh" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -24182,8 +25855,21 @@ /obj/structure/sign/departments/botany, /turf/closed/wall, /area/hydroponics) +"aOl" = ( +/obj/structure/closet/secure_closet/CMO, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/bot, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/heads/cmo) "aOm" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -24230,7 +25916,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "aOq" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/red{ @@ -24255,6 +25941,13 @@ }, /turf/closed/wall, /area/hallway/primary/central) +"aOs" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/structure/rack, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aOt" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, @@ -24345,6 +26038,24 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aOA" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/medical/genetics) +"aOB" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/turf/open/floor/plasteel/white, +/area/medical/genetics) "aOC" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 5 @@ -24371,6 +26082,22 @@ }, /turf/open/floor/circuit/green, /area/engine/supermatter) +"aOE" = ( +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/landmark/event_spawn, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aOF" = ( /obj/structure/cable{ icon_state = "1-8" @@ -24392,60 +26119,101 @@ /turf/open/floor/engine, /area/engine/engineering) "aOH" = ( -/turf/closed/wall/r_wall, -/area/maintenance/port) -"aOI" = ( /obj/structure/cable/white{ - icon_state = "2-4" + icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/obj/effect/decal/cleanable/cobweb, -/turf/open/floor/plating, -/area/maintenance/port) -"aOL" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 }, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/port) -"aOM" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"aON" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, /obj/effect/turf_decal/stripes/line{ dir = 8 }, -/obj/effect/turf_decal/stripes/line{ +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aOI" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aOJ" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/blue{ dir = 4 }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) +"aOK" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/obj/machinery/computer/card/minor/cmo{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/keycard_auth{ + pixel_x = 24; + pixel_y = -24 + }, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24; + pixel_y = -6 + }, +/obj/machinery/computer/security/telescreen/cmo{ + dir = 1; + icon_state = "telescreen"; + pixel_y = -32 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) +"aOL" = ( +/obj/structure/table/wood, +/obj/item/flashlight/lamp, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aOM" = ( +/obj/structure/table/wood, +/obj/item/paper_bin, +/obj/item/pen, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aON" = ( +/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/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aOO" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -24484,49 +26252,49 @@ heat_capacity = 1e+006 }, /area/hallway/primary/port/aft) -"aOR" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, +"aOQ" = ( +/obj/machinery/suit_storage_unit/cmo, /obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/aft) -"aOS" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/aft) -"aOT" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/delivery, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/heads/cmo) +"aOR" = ( +/obj/structure/table/glass, +/obj/item/storage/box/bodybags{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/box/bodybags, +/obj/item/pen, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/obj/effect/turf_decal/tile/purple, +/turf/open/floor/plasteel/white, +/area/medical/genetics) +"aOS" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall, +/area/maintenance/port/aft) +"aOT" = ( /obj/structure/cable/white{ - icon_state = "1-8" + icon_state = "1-4" }, -/obj/structure/cable/white{ - icon_state = "4-8" +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/aft) +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aOU" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, @@ -24545,92 +26313,77 @@ /turf/open/floor/plasteel, /area/hallway/primary/port/aft) "aOV" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, -/obj/structure/extinguisher_cabinet{ - pixel_y = 26 +/obj/effect/landmark/blobstart, +/turf/open/floor/plating{ + icon_state = "panelscorched" }, -/obj/structure/cable/white{ - icon_state = "4-8" +/area/maintenance/port/aft) +"aOW" = ( +/obj/structure/disposalpipe/segment, +/turf/closed/wall, +/area/medical/genetics) +"aOX" = ( +/obj/machinery/requests_console{ + department = "Medbay"; + departmentType = 1; + name = "Medbay RC"; + pixel_x = -30 }, /obj/machinery/camera{ - c_tag = "Aft Primary Hallway 4" - }, -/obj/effect/turf_decal/tile/green{ - dir = 1 + c_tag = "Medbay Storage" }, +/obj/machinery/rnd/production/techfab/department/medical, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/box, +/obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, -/area/hallway/primary/port/aft) -"aOW" = ( -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/item/radio/intercom{ - name = "Station Intercom"; - pixel_y = 24 - }, +/area/medical/medbay/zone3) +"aOY" = ( /obj/structure/cable/white{ - icon_state = "2-8" + icon_state = "1-2" }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/tile/purple{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/blue{ dir = 1 }, +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/landmark/start/medical_doctor, /turf/open/floor/plasteel, -/area/hallway/primary/port/aft) -"aOX" = ( +/area/medical/medbay/zone3) +"aOZ" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, /obj/machinery/power/apc{ - areastring = "/area/hallway/primary/port/aft"; + areastring = "/area/crew_quarters/heads/cmo"; dir = 1; - name = "Port Quarter Hallway APC"; - pixel_y = 24 + name = "CMO's Office APC"; + pixel_y = 26 }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "0-8" - }, -/obj/effect/turf_decal/tile/green{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/aft) -"aOY" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/aft) -"aOZ" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port/aft) +/obj/effect/landmark/start/chief_medical_officer, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) "aPa" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -24713,6 +26466,21 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"aPg" = ( +/obj/item/kirbyplants{ + icon_state = "plant-22" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/zone3) "aPh" = ( /obj/machinery/light{ dir = 1 @@ -24916,6 +26684,34 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) +"aPv" = ( +/obj/structure/table/glass, +/obj/item/storage/firstaid/o2{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/storage/firstaid/o2{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/o2{ + pixel_x = -3; + pixel_y = -3 + }, +/obj/structure/cable/white, +/obj/effect/turf_decal/delivery, +/obj/machinery/power/apc{ + areastring = "/area/medical/medbay/zone3"; + name = "Medbay APC"; + pixel_y = -26 + }, +/obj/machinery/door/window/northleft{ + name = "First-Aid Supplies"; + req_access_txt = "5" + }, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) "aPw" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -24954,10 +26750,141 @@ }, /turf/open/floor/plasteel/dark, /area/hallway/primary/starboard) +"aPz" = ( +/obj/effect/turf_decal/delivery, +/obj/structure/window/reinforced/spawner/west, +/obj/structure/window/reinforced/spawner/north, +/obj/structure/table/glass, +/obj/item/storage/firstaid/toxin{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/storage/firstaid/toxin{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/toxin{ + pixel_x = -3; + pixel_y = -3 + }, +/obj/machinery/airalarm{ + dir = 1; + pixel_y = -22 + }, +/obj/structure/disposalpipe/segment, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) +"aPA" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/door/airlock/grunge{ + name = "Morgue"; + req_access_txt = "5" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aPB" = ( +/obj/structure/disposalpipe/segment, +/turf/closed/wall, +/area/medical/morgue) +"aPC" = ( +/obj/machinery/computer/security/telescreen/entertainment, +/obj/structure/bodycontainer/morgue{ + icon_state = "morgue1"; + dir = 2 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aPD" = ( +/obj/machinery/light, +/obj/structure/noticeboard{ + dir = 1; + pixel_y = -32 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, +/obj/effect/turf_decal/delivery, +/obj/structure/table/glass, +/obj/item/storage/firstaid/fire{ + pixel_x = 6; + pixel_y = 6 + }, +/obj/item/storage/firstaid/fire{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/fire{ + pixel_x = -3; + pixel_y = -3 + }, +/obj/machinery/door/window/northright{ + name = "First-Aid Supplies"; + req_access_txt = "5" + }, +/turf/open/floor/plasteel, +/area/medical/medbay/zone3) +"aPE" = ( +/obj/structure/bodycontainer/morgue{ + icon_state = "morgue1"; + dir = 2 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aPF" = ( +/obj/structure/chair/office/light{ + dir = 4 + }, +/obj/effect/landmark/start/chief_medical_officer, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) "aPG" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/tcommsat/server) +"aPH" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/firealarm{ + dir = 8; + pixel_x = 24 + }, +/obj/structure/disposaloutlet{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aPI" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -25019,89 +26946,69 @@ /turf/open/floor/engine, /area/engine/engineering) "aPO" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 1 }, -/turf/closed/wall/r_wall, -/area/maintenance/port) +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aPP" = ( /obj/structure/cable/white{ - icon_state = "1-2" + icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"aPQ" = ( -/obj/structure/closet, -/obj/effect/spawner/lootdrop/maintenance{ - lootcount = 3; - name = "3maintenance loot spawner" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/stripes/line{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"aPR" = ( -/obj/structure/girder, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /turf/open/floor/plating, -/area/maintenance/port) +/area/maintenance/port/aft) +"aPQ" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aPR" = ( +/turf/open/floor/wood{ + icon_state = "wood-broken5" + }, +/area/maintenance/port/aft) "aPS" = ( -/obj/structure/closet/firecloset, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/stripes/line{ +/obj/effect/landmark/xeno_spawn, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 1 }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/turf/open/floor/wood, +/area/maintenance/port/aft) "aPT" = ( -/obj/structure/rack, -/obj/item/reagent_containers/food/drinks/bottle/whiskey, -/obj/effect/spawner/lootdrop/maintenance, -/obj/machinery/light/small, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/turf/open/floor/wood{ + icon_state = "wood-broken6" }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) +/area/maintenance/port/aft) "aPU" = ( -/obj/structure/rack, -/obj/effect/spawner/lootdrop/maintenance{ - lootcount = 2; - name = "2maintenance loot spawner" - }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/delivery, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"aPV" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 + dir = 5 }, /turf/closed/wall, -/area/maintenance/port) +/area/maintenance/port/aft) +"aPV" = ( +/obj/structure/barricade/wooden, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aPW" = ( /obj/machinery/vending/snack/random, /obj/machinery/firealarm{ @@ -25125,7 +27032,7 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/port/aft) "aPX" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -25218,16 +27125,18 @@ }, /area/hallway/primary/port/aft) "aQe" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/table/glass, +/obj/effect/turf_decal/tile/blue{ dir = 8 }, -/turf/open/floor/plasteel{ - heat_capacity = 1e+006 +/obj/effect/turf_decal/tile/blue{ + dir = 4 }, -/area/hallway/primary/port/aft) +/obj/item/paper_bin, +/obj/item/pen, +/obj/item/stamp/cmo, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) "aQf" = ( /obj/machinery/firealarm{ dir = 1; @@ -25252,6 +27161,39 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"aQh" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aQi" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aQj" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/effect/turf_decal/tile/yellow{ @@ -25415,7 +27357,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/starboard) "aQA" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/newscaster{ @@ -25434,6 +27376,94 @@ }, /turf/open/floor/plasteel/dark, /area/hallway/primary/starboard) +"aQB" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/sign/poster/contraband/random, +/turf/closed/wall, +/area/maintenance/port/aft) +"aQC" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aQD" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/effect/landmark/blobstart, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aQE" = ( +/obj/machinery/light/small{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "0-8" + }, +/obj/structure/table/wood, +/obj/item/storage/box/bodybags{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/box/bodybags, +/obj/machinery/power/apc{ + areastring = "/area/medical/morgue"; + dir = 4; + name = "Morgue APC"; + pixel_x = 26 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Morgue"; + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aQF" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/closed/wall/rust, +/area/maintenance/port/aft) "aQG" = ( /obj/machinery/atmospherics/pipe/simple/general/visible{ dir = 6 @@ -25472,6 +27502,19 @@ }, /turf/open/floor/plasteel/grimy, /area/tcommsat/server) +"aQI" = ( +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aQJ" = ( /obj/machinery/meter, /obj/effect/turf_decal/stripes/corner{ @@ -25491,6 +27534,17 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aQL" = ( +/obj/structure/table/wood, +/obj/item/clothing/gloves/color/latex, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aQM" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -25532,6 +27586,14 @@ }, /turf/open/floor/engine, /area/engine/engineering) +"aQQ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/barricade/wooden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aQR" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -25560,9 +27622,39 @@ /turf/open/floor/engine, /area/engine/engineering) "aQU" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall/r_wall, -/area/maintenance/port) +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aQV" = ( +/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/computer/arcade{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aQW" = ( /turf/closed/wall, /area/library) @@ -25605,30 +27697,17 @@ /turf/closed/wall, /area/medical/morgue) "aRc" = ( -/obj/effect/spawner/structure/window/reinforced/tinted, -/turf/open/floor/plating, -/area/medical/morgue) +/obj/structure/chair/stool/bar, +/turf/open/floor/wood, +/area/maintenance/port/aft) "aRd" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/grunge{ - name = "Morgue"; - req_access_txt = "5" - }, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/medical/morgue) +/obj/effect/decal/cleanable/blood/splatter, +/turf/open/floor/wood, +/area/maintenance/port/aft) "aRe" = ( -/obj/effect/spawner/structure/window/reinforced/tinted, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, -/area/medical/morgue) +/turf/closed/wall/r_wall, +/area/medical/virology) "aRf" = ( /turf/closed/wall, /area/medical/chemistry) @@ -25660,6 +27739,11 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/medical/chemistry) +"aRj" = ( +/turf/open/floor/wood{ + icon_state = "wood-broken2" + }, +/area/maintenance/port/aft) "aRk" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/camera{ @@ -25675,6 +27759,44 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) +"aRl" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable/white, +/turf/open/floor/plating, +/area/crew_quarters/heads/cmo) +"aRm" = ( +/turf/open/floor/wood, +/area/maintenance/port/aft) +"aRn" = ( +/obj/structure/chair/stool/bar, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aRo" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/newscaster{ + pixel_y = -32 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/holopad, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/heads/cmo) +"aRp" = ( +/obj/structure/bodycontainer/morgue{ + icon_state = "morgue1"; + dir = 2 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/manifold4w/scrubbers/hidden, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aRq" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/purple, @@ -25736,6 +27858,20 @@ }, /turf/open/floor/plasteel, /area/science/research) +"aRw" = ( +/obj/structure/bodycontainer/morgue{ + icon_state = "morgue1"; + dir = 2 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) "aRx" = ( /obj/machinery/door/airlock/maintenance_hatch{ name = "Maintenance Hatch"; @@ -25758,6 +27894,38 @@ "aRz" = ( /turf/closed/wall, /area/maintenance/starboard) +"aRA" = ( +/obj/structure/table/glass, +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/obj/structure/reagent_dispensers/virusfood{ + pixel_x = -32 + }, +/obj/item/storage/box/beakers{ + pixel_x = -6; + pixel_y = 8 + }, +/obj/item/storage/box/monkeycubes{ + pixel_x = 4; + pixel_y = 6 + }, +/obj/item/storage/box/syringes{ + pixel_x = -3; + pixel_y = 2 + }, +/obj/item/reagent_containers/dropper{ + pixel_y = -8 + }, +/obj/item/reagent_containers/syringe/antiviral{ + pixel_x = 2; + pixel_y = -10 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) "aRB" = ( /obj/effect/turf_decal/bot, /obj/structure/table, @@ -25770,6 +27938,10 @@ }, /turf/open/floor/plasteel/dark, /area/tcommsat/server) +"aRC" = ( +/obj/machinery/computer/slot_machine, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aRD" = ( /obj/structure/cable{ icon_state = "1-2" @@ -25913,14 +28085,12 @@ /turf/open/floor/engine, /area/engine/engineering) "aRS" = ( -/obj/structure/cable/white{ - icon_state = "1-2" +/obj/machinery/vending/cigarette, +/obj/machinery/newscaster{ + pixel_x = -32 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating{ - icon_state = "platingdmg2" - }, -/area/maintenance/port) +/turf/open/floor/plating, +/area/maintenance/port/aft) "aRT" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp, @@ -25949,6 +28119,23 @@ }, /turf/open/floor/plasteel/dark, /area/library) +"aRV" = ( +/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/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aRW" = ( /obj/structure/chair/office/dark{ dir = 4 @@ -26040,44 +28227,31 @@ /turf/open/floor/plasteel/dark, /area/library) "aSe" = ( -/obj/structure/bodycontainer/morgue, -/obj/effect/decal/cleanable/cobweb, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/vending/wallmed{ + pixel_y = 32 + }, +/obj/effect/turf_decal/tile/green{ dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/obj/machinery/holopad, +/turf/open/floor/plasteel/white, +/area/medical/virology) "aSf" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/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{ +/obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aSg" = ( -/obj/structure/sign/warning/nosmoking{ - pixel_x = 32 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/obj/item/cigbutt, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aSh" = ( /turf/closed/wall, /area/medical/medbay/zone3) @@ -26104,26 +28278,11 @@ /turf/open/floor/plasteel, /area/medical/chemistry) "aSk" = ( -/obj/machinery/light{ - dir = 1 - }, -/obj/machinery/power/apc/highcap/five_k{ - areastring = "/area/medical/chemistry"; - dir = 1; - name = "Chemistry Lab APC"; - pixel_y = 25 - }, /obj/structure/cable/white{ - icon_state = "0-2" - }, -/obj/item/twohanded/required/kirbyplants{ - icon_state = "plant-21" - }, -/obj/machinery/camera{ - c_tag = "Chemistry" + icon_state = "1-2" }, /obj/effect/turf_decal/tile/yellow{ - dir = 1 + dir = 8 }, /turf/open/floor/plasteel/white, /area/medical/chemistry) @@ -26137,6 +28296,19 @@ /obj/item/storage/pill_bottle/mutadone, /turf/open/floor/plasteel, /area/medical/chemistry) +"aSm" = ( +/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/maintenance/port/aft) "aSn" = ( /obj/machinery/chem_dispenser, /obj/machinery/button/door{ @@ -26151,6 +28323,54 @@ }, /turf/open/floor/plasteel, /area/medical/chemistry) +"aSo" = ( +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/landmark/event_spawn, +/turf/open/floor/plasteel/dark, +/area/medical/morgue) +"aSp" = ( +/obj/structure/table/glass, +/obj/machinery/reagentgrinder{ + pixel_y = 5 + }, +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/obj/item/reagent_containers/spray/cleaner{ + pixel_x = -8; + pixel_y = 2 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aSq" = ( +/obj/structure/table/wood, +/obj/item/storage/briefcase, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aSr" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aSs" = ( +/obj/structure/chair/stool/bar, +/turf/open/floor/wood{ + icon_state = "wood-broken" + }, +/area/maintenance/port/aft) "aSt" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -26283,10 +28503,43 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/maintenance/starboard/aft) +"aSG" = ( +/turf/open/floor/plating, +/area/maintenance/port/aft) "aSH" = ( /obj/structure/sign/poster/contraband/random, /turf/closed/wall, /area/maintenance/starboard) +"aSI" = ( +/obj/structure/chair/stool/bar, +/turf/open/floor/wood{ + icon_state = "wood-broken5" + }, +/area/maintenance/port/aft) +"aSJ" = ( +/obj/structure/chair/office/light, +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aSK" = ( +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aSL" = ( +/obj/structure/chair/stool/bar, +/turf/open/floor/wood{ + icon_state = "wood-broken2" + }, +/area/maintenance/port/aft) "aSM" = ( /obj/machinery/door/airlock/command{ name = "Telecomms Server Room"; @@ -26332,6 +28585,22 @@ /obj/machinery/vending/wardrobe/engi_wardrobe, /turf/open/floor/engine, /area/engine/engineering) +"aSQ" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aSR" = ( /obj/structure/table/reinforced, /obj/item/tank/internals/plasma, @@ -26431,12 +28700,15 @@ /turf/open/floor/engine, /area/engine/engineering) "aTb" = ( -/obj/structure/cable/white{ - icon_state = "1-2" +/obj/structure/table/wood, +/obj/item/toy/cards/deck/syndicate{ + pixel_y = 6 + }, +/obj/machinery/light/small{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, -/area/maintenance/port) +/area/maintenance/port/aft) "aTc" = ( /obj/structure/chair/office/dark{ dir = 8 @@ -26467,7 +28739,7 @@ "aTf" = ( /obj/structure/table/wood, /obj/item/clipboard, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -26510,96 +28782,90 @@ /turf/open/floor/plasteel/dark, /area/library) "aTj" = ( -/obj/structure/table, -/obj/item/storage/box/bodybags{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/box/bodybags, -/obj/machinery/airalarm/unlocked{ - dir = 4; - pixel_x = -23 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aTk" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ +/obj/effect/turf_decal/tile/green{ 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/dark, -/area/medical/morgue) -"aTl" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) -"aTm" = ( -/obj/structure/mirror{ - pixel_x = -28 - }, -/obj/machinery/shower{ - dir = 4; - name = "emergency shower" - }, -/obj/machinery/newscaster{ - pixel_y = 32 - }, -/obj/machinery/door/window/southleft, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/medbay/zone3) -"aTn" = ( /obj/machinery/light{ dir = 1 }, -/obj/machinery/door/window/southright, -/obj/item/radio/intercom{ - name = "Station Intercom"; +/obj/structure/closet/secure_closet/medical1, +/obj/item/radio/headset/headset_med, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/obj/machinery/airalarm{ + pixel_y = 23 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aTl" = ( +/obj/machinery/vending/wardrobe/viro_wardrobe, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ pixel_y = 26 }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/medical/virology) +"aTm" = ( +/obj/structure/table/glass, +/obj/effect/turf_decal/tile/green{ dir = 8 }, -/turf/open/floor/plasteel/dark, -/area/medical/medbay/zone3) +/obj/effect/turf_decal/tile/green, +/obj/item/paper_bin, +/obj/item/pen, +/obj/item/book/manual/wiki/infections{ + pixel_x = -15; + pixel_y = 2 + }, +/obj/item/stack/sheet/mineral/plasma{ + pixel_x = -12 + }, +/obj/item/stack/sheet/mineral/plasma{ + pixel_x = -14; + pixel_y = 3 + }, +/obj/item/hand_labeler, +/obj/item/clothing/gloves/color/latex, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aTn" = ( +/obj/effect/landmark/start/virologist, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/power/apc/highcap/five_k{ + areastring = "/area/medical/virology"; + dir = 1; + name = "Virology APC"; + pixel_y = 24 + }, +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/obj/machinery/camera{ + c_tag = "Virology" + }, +/turf/open/floor/plasteel, +/area/medical/virology) "aTo" = ( -/obj/structure/window/reinforced, -/obj/machinery/clonepod, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/medbay/zone3) +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/closed/wall/r_wall, +/area/medical/virology) "aTp" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -26614,11 +28880,12 @@ /area/medical/chemistry) "aTr" = ( /obj/structure/cable/white{ - icon_state = "1-2" + icon_state = "1-4" }, /obj/effect/turf_decal/tile/yellow{ - dir = 1 + dir = 8 }, +/obj/effect/landmark/start/chemist, /turf/open/floor/plasteel/white, /area/medical/chemistry) "aTs" = ( @@ -26639,6 +28906,19 @@ /obj/machinery/chem_master, /turf/open/floor/plasteel, /area/medical/chemistry) +"aTv" = ( +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -22 + }, +/obj/machinery/light/small{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 1 + }, +/turf/open/floor/plasteel/freezer, +/area/medical/virology) "aTw" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/turf_decal/tile/blue{ @@ -26673,7 +28953,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/lounge) "aTA" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18" }, /obj/machinery/camera{ @@ -26847,6 +29127,12 @@ icon_state = "platingdmg1" }, /area/maintenance/starboard/aft) +"aTQ" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 + }, +/turf/closed/wall/r_wall, +/area/medical/virology) "aTR" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -26881,6 +29167,40 @@ icon_state = "panelscorched" }, /area/maintenance/starboard/aft) +"aTU" = ( +/obj/structure/sign/poster/contraband/random, +/turf/closed/wall/rust, +/area/maintenance/port/aft) +"aTV" = ( +/obj/structure/table/wood, +/obj/item/wrench, +/obj/item/storage/secure/briefcase{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/storage/briefcase, +/obj/machinery/light/small{ + 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/maintenance/port/aft) +"aTW" = ( +/obj/structure/bed, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 4 + }, +/turf/open/floor/plasteel/freezer, +/area/medical/virology) "aTX" = ( /obj/machinery/light{ dir = 8 @@ -26943,13 +29263,23 @@ /turf/closed/wall/r_wall/rust, /area/engine/engineering) "aUb" = ( +/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/supply/hidden, +/obj/effect/landmark/event_spawn, /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/landmark/blobstart, -/turf/open/floor/plating, -/area/maintenance/port) +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aUc" = ( /obj/machinery/power/apc{ areastring = "/area/library"; @@ -27000,74 +29330,114 @@ /turf/open/floor/wood, /area/library) "aUh" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/turf/open/floor/wood, -/area/library) +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/turf/closed/wall/r_wall, +/area/medical/virology) "aUi" = ( -/obj/structure/cable/white{ - icon_state = "2-8" - }, -/turf/open/floor/wood, -/area/library) +/turf/closed/wall/rust, +/area/maintenance/port/aft) "aUj" = ( /obj/machinery/photocopier, /turf/open/floor/plasteel/dark, /area/library) "aUk" = ( -/obj/structure/bodycontainer/morgue, -/obj/item/radio/intercom{ - name = "Station Intercom"; - pixel_x = -26 +/obj/structure/table/wood, +/obj/item/storage/pill_bottle, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aUl" = ( +/obj/machinery/computer/slot_machine, +/obj/machinery/light/small, +/obj/structure/sign/poster/contraband/random{ + pixel_y = -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{ + dir = 8 + }, /turf/open/floor/plasteel/dark, -/area/medical/morgue) +/area/maintenance/port/aft) +"aUm" = ( +/obj/machinery/computer/slot_machine, +/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/maintenance/port/aft) "aUn" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /turf/open/floor/plating, /area/medical/medbay/zone3) "aUo" = ( -/obj/machinery/camera{ - c_tag = "Genetics Cloning"; - dir = 4 +/obj/structure/table/wood, +/obj/item/coin/iron{ + icon_state = "coin_bananium_heads"; + name = "arcade coin"; + pixel_x = 6 }, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -22 +/obj/item/coin/iron{ + icon_state = "coin_bananium_heads"; + name = "arcade coin"; + pixel_x = -6 }, -/obj/effect/turf_decal/tile/blue{ - dir = 1 +/obj/item/coin/iron{ + icon_state = "coin_bananium_heads"; + name = "arcade coin"; + pixel_y = 6 }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/obj/item/instrument/guitar, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aUp" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/effect/turf_decal/tile/blue{ +/obj/structure/table/wood, +/obj/item/reagent_containers/blood/random, +/obj/item/reagent_containers/syringe{ + pixel_y = 5 + }, +/obj/item/reagent_containers/syringe, +/obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/obj/effect/turf_decal/tile/blue{ +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) -"aUq" = ( -/obj/machinery/computer/cloning{ +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aUq" = ( +/obj/structure/table/wood, +/obj/item/clipboard, +/obj/item/toy/syndicateballoon, +/obj/item/newspaper, +/obj/item/clothing/head/bowler, +/obj/machinery/power/apc{ + areastring = "/area/maintenance/port/aft"; + dir = 8; + name = "Port Quarter Maintenance APC"; + pixel_x = -26; + pixel_y = 3 }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/obj/structure/cable/white{ + icon_state = "0-4" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aUr" = ( /obj/machinery/status_display, /turf/closed/wall, @@ -27085,27 +29455,41 @@ /turf/open/floor/plasteel/dark, /area/medical/chemistry) "aUt" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/holopad, /obj/structure/cable/white{ - icon_state = "1-4" + icon_state = "4-8" }, -/obj/effect/turf_decal/tile/yellow{ +/turf/open/floor/plasteel, +/area/medical/chemistry) +"aUu" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aUv" = ( -/obj/machinery/holopad, /obj/structure/cable/white{ icon_state = "2-8" }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/effect/landmark/start/chemist, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "aUw" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /obj/effect/turf_decal/tile/yellow{ dir = 4 }, +/obj/structure/closet/crate/bin, /turf/open/floor/plasteel/white, /area/medical/chemistry) "aUx" = ( @@ -27244,6 +29628,73 @@ }, /turf/closed/wall/r_wall, /area/science/research) +"aUJ" = ( +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_y = -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{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aUK" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/door/airlock/virology{ + name = "Virology Access"; + req_access_txt = "39" + }, +/obj/machinery/door/firedoor, +/turf/open/floor/plasteel, +/area/medical/virology) +"aUL" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aUM" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Medbay Maintenance"; + req_access_txt = "5" + }, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aUN" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aUO" = ( /obj/structure/cable{ icon_state = "4-8" @@ -27346,18 +29797,22 @@ /turf/open/floor/wood, /area/library) "aUZ" = ( -/obj/effect/landmark/barthpot, -/turf/open/floor/wood, -/area/library) -"aVa" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 + dir = 4 }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aVa" = ( /obj/structure/cable/white{ - icon_state = "1-2" + icon_state = "1-4" }, -/turf/open/floor/wood, -/area/library) +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aVb" = ( /obj/structure/table/wood, /obj/item/storage/crayons, @@ -27382,117 +29837,109 @@ /turf/open/floor/plasteel/dark, /area/library) "aVc" = ( -/obj/structure/bodycontainer/morgue, -/obj/machinery/light{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) -"aVd" = ( /obj/structure/cable/white{ - icon_state = "1-2" + icon_state = "2-8" + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/structure/cable/white{ + icon_state = "2-4" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - 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/stripes/line, +/turf/open/floor/plating{ + icon_state = "panelscorched" }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/area/maintenance/port/aft) +"aVd" = ( +/obj/structure/cable/white{ + icon_state = "4-8" }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/obj/structure/cable/white{ + icon_state = "2-8" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aVe" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/turf/open/floor/plating, +/area/maintenance/port/aft) "aVf" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/grunge{ - name = "Morgue"; - req_access_txt = "5" +/obj/structure/cable/white{ + icon_state = "4-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 +/obj/structure/cable/white{ + icon_state = "1-8" }, +/obj/structure/cable/white{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, /obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) -"aVg" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aVg" = ( +/obj/structure/cable/white{ + icon_state = "4-8" }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/maintenance/port/aft) "aVh" = ( -/obj/machinery/holopad, -/obj/effect/landmark/start/medical_doctor, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 +/obj/structure/cable/white{ + icon_state = "2-8" }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aVi" = ( -/obj/machinery/dna_scannernew, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 +/turf/open/floor/plating{ + icon_state = "panelscorched" }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/area/maintenance/port/aft) "aVj" = ( -/obj/structure/table/glass, -/obj/item/stack/sheet/mineral/plasma, -/obj/item/stack/sheet/mineral/plasma, -/obj/item/stack/sheet/mineral/plasma, -/obj/item/reagent_containers/glass/bottle/charcoal{ - pixel_x = 6 +/obj/machinery/chem_master, +/obj/effect/turf_decal/stripes/line{ + dir = 9 }, -/obj/item/reagent_containers/glass/bottle/epinephrine, -/obj/item/reagent_containers/dropper, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel, /area/medical/chemistry) -"aVl" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 8 +"aVk" = ( +/obj/structure/closet/emcloset, +/obj/effect/turf_decal/stripes/line{ + dir = 10 }, -/turf/open/floor/plasteel/white, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aVl" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, /area/medical/chemistry) "aVm" = ( /obj/structure/cable/white{ @@ -27503,16 +29950,11 @@ /turf/open/floor/plasteel/white, /area/medical/chemistry) "aVn" = ( -/obj/structure/closet/crate/bin, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/requests_console{ - department = "Chemistry Lab"; - name = "Chemistry RC"; - pixel_x = 32; - receive_ore_updates = 1 +/obj/effect/turf_decal/stripes/line{ + dir = 5 }, -/obj/effect/turf_decal/tile/yellow, -/turf/open/floor/plasteel/white, +/obj/machinery/chem_heater, +/turf/open/floor/plasteel, /area/medical/chemistry) "aVo" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ @@ -27701,6 +30143,39 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall, /area/science/research) +"aVF" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 5 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aVG" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aVH" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aVI" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aVJ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/structure/cable/white{ + icon_state = "2-4" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aVK" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 6 @@ -27716,14 +30191,14 @@ /turf/open/space, /area/asteroid/nearstation) "aVM" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, /obj/structure/cable/white{ - icon_state = "1-2" + icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/port) +/turf/open/floor/plating, +/area/maintenance/port/aft) "aVN" = ( /obj/structure/table/wood, /obj/item/storage/bag/books, @@ -27767,9 +30242,15 @@ /turf/open/floor/plasteel/dark, /area/library) "aVR" = ( -/obj/structure/bookcase/random/fiction, -/turf/open/floor/plasteel/dark, -/area/library) +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/structure/reagent_dispensers/watertank, +/obj/machinery/light/small{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aVS" = ( /obj/structure/bookcase/random/fiction, /obj/effect/turf_decal/tile/neutral{ @@ -27809,22 +30290,15 @@ /turf/open/floor/plasteel/dark, /area/library) "aVW" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/rack, +/obj/item/storage/toolbox/mechanical, +/obj/item/clothing/head/welding, +/obj/machinery/light/small, +/obj/effect/turf_decal/stripes/line{ 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) +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aVX" = ( /obj/structure/easel, /obj/item/canvas/twentythreeXnineteen, @@ -27836,24 +30310,18 @@ /turf/open/floor/plasteel/dark, /area/library) "aVY" = ( -/obj/structure/table, -/obj/item/clothing/gloves/color/latex, -/obj/structure/extinguisher_cabinet{ - pixel_x = -26 +/obj/machinery/door/airlock/grunge{ + name = "Crematorium"; + req_access_txt = "27" }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) -"aVZ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable/white{ icon_state = "1-2" }, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -27865,19 +30333,39 @@ dir = 8 }, /turf/open/floor/plasteel/dark, -/area/medical/morgue) -"aWa" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 +/area/maintenance/port/aft) +"aVZ" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" }, -/obj/effect/turf_decal/tile/neutral{ +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aWa" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 10 }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/item/storage/backpack, +/obj/item/crowbar, +/obj/item/wrench, +/obj/structure/rack, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aWb" = ( /obj/effect/spawner/structure/window/reinforced/tinted, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ @@ -27886,123 +30374,78 @@ /turf/open/floor/plating, /area/medical/medbay/zone3) "aWc" = ( -/obj/machinery/light_switch{ - pixel_x = -24; - pixel_y = -38 +/obj/structure/cable/white{ + icon_state = "1-4" }, -/obj/machinery/button/door{ - desc = "A remote control switch for the medbay foyer."; - id = "cloningfoyer"; - name = "Cloning Doors Control"; - normaldoorcontrol = 1; - pixel_x = -24; - pixel_y = -24 +/obj/structure/cable/white{ + icon_state = "1-2" }, -/obj/structure/closet/crate/freezer/surplus_limbs, -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) -"aWd" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +/obj/effect/landmark/blobstart, +/turf/open/floor/plating{ + icon_state = "platingdmg1" + }, +/area/maintenance/port/aft) +"aWd" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/landmark/event_spawn, +/obj/item/tank/internals/oxygen/red, +/obj/item/clothing/mask/gas, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aWe" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ dir = 4 }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 8 +/turf/open/floor/plating{ + icon_state = "panelscorched" }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) -"aWe" = ( -/obj/structure/table/glass, -/obj/item/storage/box/bodybags{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/box/bodybags, -/obj/item/pen, -/obj/machinery/firealarm{ - dir = 8; - pixel_x = 24 - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, -/obj/effect/turf_decal/tile/blue, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/area/maintenance/port/aft) "aWf" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/requests_console{ + department = "Chemistry Lab"; + name = "Chemistry RC"; + pixel_x = 32; + receive_ore_updates = 1 + }, +/obj/effect/turf_decal/tile/yellow, /obj/structure/table/glass, -/obj/item/folder/white, -/obj/item/reagent_containers/glass/beaker/large{ - pixel_x = -3 - }, -/obj/item/reagent_containers/glass/beaker{ - pixel_x = 3 +/obj/item/stack/sheet/mineral/plasma, +/obj/item/stack/sheet/mineral/plasma, +/obj/item/stack/sheet/mineral/plasma, +/obj/item/reagent_containers/glass/bottle/charcoal{ + pixel_x = 6 }, +/obj/item/reagent_containers/glass/bottle/epinephrine, /obj/item/reagent_containers/dropper, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral, -/turf/open/floor/plasteel/dark, +/obj/item/reagent_containers/dropper, +/turf/open/floor/plasteel/white, /area/medical/chemistry) "aWg" = ( -/obj/structure/table/glass, -/obj/item/assembly/igniter, -/obj/item/assembly/igniter, -/obj/item/assembly/igniter, -/obj/item/assembly/timer{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/assembly/timer{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/assembly/timer{ - pixel_x = 3; - pixel_y = 3 +/obj/effect/turf_decal/stripes/line{ + dir = 8 }, +/obj/machinery/chem_dispenser, +/turf/open/floor/plasteel, +/area/medical/chemistry) +"aWh" = ( /obj/machinery/firealarm{ dir = 1; pixel_y = -24 }, /obj/machinery/light, +/obj/structure/chair/office/light{ + dir = 8 + }, +/obj/effect/landmark/start/chemist, /obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/medical/chemistry) -"aWh" = ( -/obj/structure/table/glass, -/obj/item/clothing/glasses/science{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/clothing/glasses/science, -/obj/item/stack/cable_coil/white{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/stack/cable_coil/white, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/item/grenade/chem_grenade, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel, /area/medical/chemistry) "aWi" = ( /obj/structure/cable/white{ @@ -28020,21 +30463,39 @@ /area/medical/chemistry) "aWj" = ( /obj/structure/table/glass, -/obj/item/clipboard, -/obj/item/toy/figure/chemist, -/obj/machinery/light_switch{ - pixel_x = 24; - pixel_y = -24 +/obj/item/clothing/glasses/science{ + pixel_x = 3; + pixel_y = 3 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 +/obj/item/clothing/glasses/science, +/obj/item/stack/cable_coil/white{ + pixel_x = 3; + pixel_y = 3 }, -/obj/effect/turf_decal/tile/neutral{ +/obj/item/stack/cable_coil/white, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/grenade/chem_grenade, +/obj/item/assembly/igniter, +/obj/item/assembly/igniter, +/obj/item/assembly/igniter, +/obj/item/assembly/timer{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/assembly/timer{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/item/assembly/timer{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/effect/turf_decal/stripes/line{ dir = 4 }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plasteel, /area/medical/chemistry) "aWk" = ( /obj/structure/table, @@ -28149,6 +30610,46 @@ }, /turf/open/floor/circuit/green/telecomms/mainframe, /area/science/research) +"aWv" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aWw" = ( +/obj/structure/sign/warning/biohazard{ + pixel_x = -32 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aWx" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/landmark/blobstart, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aWy" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aWz" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple, /obj/structure/lattice, @@ -28211,12 +30712,13 @@ /turf/open/floor/plasteel/dark, /area/library) "aWF" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable/white{ icon_state = "1-2" }, -/turf/open/floor/plasteel/dark, -/area/library) +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aWG" = ( /obj/machinery/bookbinder, /obj/machinery/status_display{ @@ -28235,68 +30737,72 @@ /turf/open/floor/plasteel/dark, /area/library) "aWH" = ( -/obj/structure/bodycontainer/morgue, -/obj/machinery/power/apc{ - areastring = "/area/medical/morgue"; - name = "Morgue APC"; - pixel_y = -26 - }, -/obj/structure/cable/white{ - icon_state = "0-4" - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) -"aWI" = ( -/obj/effect/decal/cleanable/blood/old, -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/turf/open/floor/plating, -/area/medical/morgue) -"aWJ" = ( -/obj/structure/closet/crate/bin, -/obj/machinery/camera{ - c_tag = "Medbay Morgue"; - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ +/obj/structure/closet/firecloset, +/obj/effect/turf_decal/stripes/line{ dir = 1 }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aWI" = ( +/obj/structure/cable/white{ + icon_state = "4-8" }, -/turf/open/floor/plasteel/dark, -/area/medical/morgue) +/obj/effect/turf_decal/delivery, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aWJ" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/effect/turf_decal/delivery, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) "aWK" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/medical/medbay/zone3) "aWL" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/medical/glass{ - id_tag = "cloningfoyer"; - name = "Cloning Lab"; - req_access_txt = "5" +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/newscaster{ + pixel_x = 32 }, /turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/area/medical/virology) "aWM" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, -/area/medical/medbay/zone3) +/obj/machinery/door/airlock/virology{ + name = "Virology Access"; + req_access_txt = "39" + }, +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) "aWN" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/medical/glass{ @@ -28339,7 +30845,7 @@ /turf/open/floor/plasteel/grimy, /area/crew_quarters/lounge) "aWR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -28464,6 +30970,27 @@ /obj/structure/lattice/catwalk, /turf/open/space, /area/asteroid/nearstation) +"aXd" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/light/small, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aXe" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/stripes/line, +/obj/structure/cable/white{ + icon_state = "1-8" + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aXf" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/closed/wall, @@ -28488,13 +31015,19 @@ /turf/open/floor/plasteel/dark, /area/library) "aXi" = ( -/obj/machinery/airalarm{ - dir = 1; - pixel_y = -22 +/obj/structure/bonfire, +/obj/item/reagent_containers/food/drinks/bottle/orangejuice{ + desc = "For the weary spacemen on their quest to rekindle the first plasma fire."; + name = "Carton of Estus" }, -/obj/structure/closet/crate/bin, -/turf/open/floor/plasteel/dark, -/area/library) +/obj/item/nullrod/claymore/glowing{ + desc = "Don't tell anyone you put any points into dex, though."; + force = 10; + name = "moonlight greatsword" + }, +/obj/effect/decal/remains/human, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aXj" = ( /obj/structure/bookcase/random/reference, /obj/effect/turf_decal/tile/neutral{ @@ -28602,7 +31135,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/zone3) "aXu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/button/door{ @@ -28625,6 +31158,21 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/zone3) +"aXv" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/cable/white{ + icon_state = "1-2" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aXw" = ( /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 @@ -28709,6 +31257,19 @@ }, /turf/open/floor/plasteel/white, /area/science/research) +"aXD" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/firealarm{ + dir = 1; + pixel_y = -26 + }, +/turf/open/floor/plasteel, +/area/medical/virology) "aXE" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -28835,53 +31396,21 @@ /turf/open/floor/wood, /area/library) "aXN" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/door/airlock/maintenance_hatch{ name = "Maintenance Hatch"; req_access_txt = "12" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "1-2" - }, /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/stripes/line{ dir = 1 }, -/turf/open/floor/plating, -/area/maintenance/port) -"aXO" = ( -/obj/structure/table/glass, -/obj/item/storage/firstaid/toxin{ - pixel_x = 6; - pixel_y = 6 - }, -/obj/item/storage/firstaid/toxin{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/firstaid/regular, -/obj/item/storage/firstaid/toxin{ - pixel_x = -3; - pixel_y = -3 - }, -/obj/machinery/requests_console{ - department = "Medbay"; - departmentType = 1; - name = "Medbay RC"; - pixel_x = -30 - }, -/obj/machinery/camera{ - c_tag = "Medbay Storage" - }, -/obj/effect/turf_decal/delivery, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/window/reinforced{ - dir = 1 - }, /turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/area/maintenance/port/aft) +"aXO" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/wood, +/area/maintenance/port/aft) "aXP" = ( /obj/structure/extinguisher_cabinet{ pixel_y = 32 @@ -28978,6 +31507,12 @@ }, /turf/open/floor/plasteel, /area/medical/medbay/zone3) +"aXY" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 1 + }, +/turf/closed/wall/r_wall, +/area/medical/virology) "aXZ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/closet/crate/bin, @@ -29324,85 +31859,77 @@ /turf/open/floor/wood, /area/library) "aYz" = ( -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/turf/open/floor/plating{ - icon_state = "platingdmg3" - }, -/area/maintenance/port) -"aYA" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating{ - icon_state = "platingdmg1" - }, -/area/maintenance/port) -"aYC" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/maintenance/port) -"aYE" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "1-8" +/obj/structure/closet/l3closet/virology, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 8 }, /obj/effect/turf_decal/stripes/line{ - dir = 1 + dir = 10 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aYA" = ( +/obj/machinery/atmospherics/pipe/simple/general/visible{ + dir = 10 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/obj/machinery/airalarm{ + pixel_y = 23 }, /turf/open/floor/plating, -/area/maintenance/port) -"aYF" = ( -/obj/structure/cable/white{ - icon_state = "2-8" +/area/maintenance/port/aft) +"aYB" = ( +/obj/machinery/shower{ + desc = "From what you understand it was put in rather recently, but the design looks right out of the 2510's. Weird."; + dir = 1; + icon_state = "shower"; + name = "Emergency Shower" }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/machinery/camera{ + c_tag = "Virology Access"; + dir = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aYC" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/landmark/event_spawn, +/turf/open/floor/wood, +/area/maintenance/port/aft) +"aYD" = ( +/obj/machinery/atmospherics/components/unary/tank/air, +/obj/effect/turf_decal/stripes/line{ dir = 10 }, /turf/open/floor/plating, -/area/maintenance/port) +/area/maintenance/port/aft) +"aYE" = ( +/obj/machinery/computer/pandemic, +/obj/effect/turf_decal/tile/green, +/obj/item/healthanalyzer, +/obj/machinery/requests_console{ + department = "Virology"; + name = "Virology RC"; + pixel_x = 0; + pixel_y = -32; + receive_ore_updates = 1 + }, +/turf/open/floor/plasteel/white, +/area/medical/virology) +"aYF" = ( +/obj/structure/chair/comfy/black, +/turf/open/floor/wood, +/area/maintenance/port/aft) "aYG" = ( -/obj/structure/table/glass, -/obj/item/storage/firstaid/fire{ - pixel_x = 6; - pixel_y = 6 - }, -/obj/item/storage/firstaid/fire{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/firstaid/regular, -/obj/item/storage/firstaid/fire{ - pixel_x = -3; - pixel_y = -3 - }, -/obj/machinery/airalarm{ - dir = 4; - pixel_x = -22 - }, -/obj/effect/turf_decal/delivery, -/obj/machinery/door/window/eastleft{ - name = "First-Aid Supplies"; - req_access_txt = "5" - }, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/structure/chair/comfy/black, +/turf/open/floor/wood, +/area/maintenance/port/aft) "aYH" = ( /obj/effect/landmark/start/medical_doctor, /obj/effect/turf_decal/tile/blue{ @@ -29611,6 +32138,14 @@ heat_capacity = 1e+006 }, /area/hallway/primary/aft) +"aYX" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/window/reinforced/spawner/north, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aYY" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -29710,62 +32245,80 @@ }, /turf/closed/wall/r_wall/rust, /area/science/robotics/lab) +"aZn" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/structure/window/reinforced/spawner/north, +/obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1 + }, +/obj/effect/landmark/xeno_spawn, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aZo" = ( -/obj/structure/girder, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/door/window/northright{ + name = "Theatre Stage" + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aZp" = ( -/obj/structure/table/wood, -/obj/item/gun/ballistic/automatic/toy/pistol/unrestricted, -/turf/open/floor/plating, -/area/maintenance/port) +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aZq" = ( -/obj/structure/table/wood, -/obj/item/clothing/gloves/color/black, -/obj/item/taperecorder, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Maintenance Hatch"; + req_access_txt = "12" + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) +"aZr" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, /obj/machinery/light/small{ dir = 1 }, -/obj/structure/sign/poster/contraband/random{ - pixel_y = 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{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"aZr" = ( -/obj/structure/rack, -/obj/item/storage/briefcase{ - pixel_x = -3; - pixel_y = 3 - }, -/obj/item/storage/secure/briefcase, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/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/maintenance/port) +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aZs" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/structure/sign/poster/contraband/random, -/turf/closed/wall, -/area/maintenance/port) +/obj/machinery/vending/autodrobe, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aZt" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/clothing/suit/syndicatefake, +/obj/item/clothing/head/syndicatefake, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) "aZu" = ( /obj/machinery/status_display{ pixel_y = -32 @@ -29806,88 +32359,119 @@ }, /turf/open/floor/wood, /area/library) -"aZy" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, -/turf/closed/wall/rust, -/area/maintenance/port) -"aZz" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ +"aZx" = ( +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/structure/sign/poster/contraband/random, -/turf/closed/wall, -/area/maintenance/port) -"aZA" = ( -/obj/structure/barricade/wooden, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ +/obj/effect/turf_decal/tile/neutral{ dir = 1 }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"aZB" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, -/turf/closed/wall, -/area/maintenance/port) -"aZC" = ( -/obj/structure/table/glass, -/obj/item/storage/firstaid/brute{ - pixel_x = 6; - pixel_y = 6 - }, -/obj/item/storage/firstaid/brute{ +/obj/machinery/light/small, +/obj/structure/table/wood, +/obj/item/lipstick/random{ pixel_x = 3; pixel_y = 3 }, -/obj/item/storage/firstaid/regular, -/obj/item/storage/firstaid/brute{ +/obj/item/lipstick/random{ pixel_x = -3; pixel_y = -3 }, -/obj/machinery/newscaster{ - pixel_x = -32 - }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/effect/turf_decal/delivery, -/obj/machinery/door/window/eastright{ - name = "First-Aid Supplies"; - req_access_txt = "5" - }, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) -"aZD" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/effect/turf_decal/loading_area{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/corner, -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ +/obj/item/lipstick/random, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aZy" = ( +/obj/effect/turf_decal/tile/neutral{ dir = 4 }, -/obj/effect/turf_decal/tile/blue{ +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/clothing/suit/justice, +/obj/item/clothing/head/helmet/justice/escape{ + name = "justice helmet" + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aZz" = ( +/obj/structure/dresser, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/zone3) +/turf/open/floor/plasteel/dark, +/area/maintenance/port/aft) +"aZA" = ( +/obj/structure/table/glass, +/obj/item/clipboard, +/obj/machinery/light_switch{ + pixel_x = 24; + pixel_y = -24 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/item/folder/white, +/obj/item/toy/figure/chemist, +/obj/item/reagent_containers/glass/beaker/large{ + pixel_x = -3; + pixel_y = 6 + }, +/obj/item/reagent_containers/glass/beaker{ + pixel_x = 3; + pixel_y = 6 + }, +/turf/open/floor/plasteel/dark, +/area/medical/chemistry) +"aZB" = ( +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/door/airlock/virology/glass{ + name = "Isolation Room"; + req_access_txt = "39" + }, +/turf/open/floor/plasteel/freezer, +/area/medical/virology) +"aZC" = ( +/obj/structure/table/wood, +/obj/structure/sign/poster/random{ + pixel_x = 32 + }, +/turf/open/floor/wood, +/area/maintenance/port/aft) +"aZD" = ( +/obj/machinery/atmospherics/components/binary/valve/on{ + dir = 4 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) +"aZE" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/atmos/abandoned{ + name = "Atmospherics Maintenance"; + req_access_txt = "12;24" + }, +/obj/effect/turf_decal/stripes/line{ + dir = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/maintenance/port/aft) "aZF" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/medical/glass{ @@ -29948,6 +32532,21 @@ }, /turf/open/floor/plasteel, /area/medical/medbay/zone3) +"aZJ" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 6 + }, +/obj/structure/sign/warning/nosmoking{ + pixel_y = -32 + }, +/obj/structure/sign/warning/fire{ + pixel_x = 32 + }, +/turf/open/floor/plating, +/area/maintenance/port/aft) "aZK" = ( /obj/machinery/holopad, /obj/structure/cable/white{ @@ -30296,113 +32895,6 @@ icon_state = "platingdmg1" }, /area/maintenance/starboard) -"baj" = ( -/turf/closed/wall, -/area/maintenance/port) -"bam" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"bao" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bap" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall, -/area/maintenance/port) -"baq" = ( -/obj/structure/table/wood, -/obj/item/clothing/suit/syndicatefake, -/obj/item/clothing/head/syndicatefake, -/obj/effect/decal/cleanable/cobweb, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"bar" = ( -/turf/open/floor/plating, -/area/maintenance/port) -"bas" = ( -/obj/structure/dresser, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"bat" = ( -/obj/structure/table/glass, -/obj/item/storage/firstaid/o2{ - pixel_x = 6; - pixel_y = 6 - }, -/obj/item/storage/firstaid/o2{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/firstaid/regular, -/obj/item/storage/firstaid/o2{ - pixel_x = -3; - pixel_y = -3 - }, -/obj/machinery/power/apc{ - areastring = "/area/medical/medbay/zone3"; - dir = 8; - name = "Medbay APC"; - pixel_x = -26 - }, -/obj/structure/cable/white, -/obj/effect/turf_decal/delivery, -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) -"bau" = ( -/obj/machinery/light, -/obj/structure/noticeboard{ - dir = 1; - pixel_y = -32 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/stripes/box, -/obj/machinery/rnd/production/techfab/department/medical, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) -"bav" = ( -/obj/machinery/vending/medical, -/obj/machinery/firealarm{ - dir = 1; - pixel_y = -24 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/bot, -/turf/open/floor/plasteel, -/area/medical/medbay/zone3) "baw" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/departments/medbay/alt, @@ -30800,101 +33292,6 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) -"bbc" = ( -/obj/structure/table/wood, -/obj/item/flashlight/lamp, -/turf/open/floor/plating, -/area/maintenance/port) -"bbe" = ( -/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/maintenance/port) -"bbf" = ( -/obj/structure/cable/white{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/maintenance/port) -"bbg" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bbh" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/landmark/blobstart, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/port) -"bbj" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/maintenance/port) -"bbk" = ( -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bbl" = ( -/obj/structure/table/wood, -/obj/item/clipboard, -/obj/item/toy/syndicateballoon, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"bbm" = ( -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bbn" = ( -/obj/machinery/vending/autodrobe, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "bbp" = ( /obj/machinery/light{ dir = 8 @@ -30914,7 +33311,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/zone3) "bbr" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue, @@ -31208,92 +33605,6 @@ }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) -"bbQ" = ( -/turf/open/floor/wood{ - icon_state = "wood-broken5" - }, -/area/maintenance/port) -"bbR" = ( -/turf/open/floor/wood, -/area/maintenance/port) -"bbS" = ( -/turf/open/floor/wood{ - icon_state = "wood-broken6" - }, -/area/maintenance/port) -"bbT" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 5 - }, -/turf/closed/wall, -/area/maintenance/port) -"bbV" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/barricade/wooden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bbW" = ( -/obj/structure/barricade/wooden, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bbX" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, -/turf/closed/wall, -/area/maintenance/port) -"bbY" = ( -/obj/machinery/computer/security/telescreen/entertainment, -/turf/closed/wall, -/area/maintenance/port) -"bbZ" = ( -/obj/structure/barricade/wooden, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bca" = ( -/obj/structure/sign/poster/contraband/random, -/turf/closed/wall, -/area/maintenance/port) -"bcb" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating{ - icon_state = "platingdmg1" - }, -/area/maintenance/port) -"bcc" = ( -/obj/structure/reagent_dispensers/watertank, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "bcd" = ( /obj/item/retractor, /obj/item/hemostat, @@ -31618,129 +33929,6 @@ }, /turf/open/floor/plasteel, /area/science/mixing) -"bcF" = ( -/obj/machinery/computer/slot_machine, -/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/maintenance/port) -"bcG" = ( -/obj/structure/chair/stool/bar, -/turf/open/floor/wood, -/area/maintenance/port) -"bcH" = ( -/obj/effect/decal/cleanable/blood/splatter, -/turf/open/floor/wood, -/area/maintenance/port) -"bcI" = ( -/turf/open/floor/wood{ - icon_state = "wood-broken2" - }, -/area/maintenance/port) -"bcJ" = ( -/obj/structure/chair/stool/bar, -/turf/open/floor/plating, -/area/maintenance/port) -"bcK" = ( -/obj/machinery/computer/slot_machine, -/turf/open/floor/plating, -/area/maintenance/port) -"bcL" = ( -/obj/machinery/vending/cigarette, -/obj/machinery/newscaster{ - pixel_x = -32 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bcM" = ( -/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/maintenance/port) -"bcN" = ( -/obj/structure/chair/comfy/black{ - 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/dark, -/area/maintenance/port) -"bcO" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/structure/sign/warning/nosmoking{ - pixel_y = 32 - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bcR" = ( -/obj/structure/table/wood, -/obj/item/instrument/guitar, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/turf/open/floor/plating, -/area/maintenance/port) -"bcS" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/landmark/blobstart, -/turf/open/floor/plating, -/area/maintenance/port) -"bcT" = ( -/obj/structure/rack, -/obj/item/storage/toolbox/mechanical, -/obj/item/clothing/head/welding, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/structure/cable/white{ - icon_state = "0-8" - }, -/obj/machinery/power/apc{ - areastring = "/area/maintenance/port"; - dir = 4; - name = "Port Maintenance APC"; - pixel_x = 26 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "bcU" = ( /obj/item/circular_saw, /obj/item/surgicaldrill{ @@ -32192,160 +34380,6 @@ /obj/structure/sign/warning/fire, /turf/closed/wall, /area/science/mixing) -"bdD" = ( -/obj/structure/table/wood, -/obj/item/storage/briefcase, -/turf/open/floor/plating, -/area/maintenance/port) -"bdE" = ( -/obj/structure/chair/stool/bar, -/turf/open/floor/wood{ - icon_state = "wood-broken" - }, -/area/maintenance/port) -"bdF" = ( -/obj/structure/chair/stool/bar, -/turf/open/floor/wood{ - icon_state = "wood-broken5" - }, -/area/maintenance/port) -"bdG" = ( -/obj/structure/chair/stool/bar, -/turf/open/floor/wood{ - icon_state = "wood-broken2" - }, -/area/maintenance/port) -"bdH" = ( -/obj/structure/table/wood, -/obj/item/toy/cards/deck/syndicate{ - pixel_y = 6 - }, -/obj/machinery/light/small{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bdI" = ( -/obj/structure/table/wood, -/obj/item/wrench, -/obj/item/storage/secure/briefcase{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/storage/briefcase, -/obj/machinery/light/small{ - 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/maintenance/port) -"bdJ" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - 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/dark, -/area/maintenance/port) -"bdK" = ( -/obj/structure/chair/comfy/black{ - dir = 4 - }, -/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/dark, -/area/maintenance/port) -"bdL" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bdM" = ( -/obj/effect/landmark/xeno_spawn, -/obj/machinery/atmospherics/components/unary/vent_pump/on{ - dir = 8 - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bdN" = ( -/obj/structure/table/wood, -/obj/item/clothing/suit/justice, -/obj/item/clothing/head/helmet/justice/escape{ - name = "justice helmet" - }, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/structure/sign/poster/contraband/random{ - 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{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"bdO" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/maintenance/port) -"bdP" = ( -/obj/structure/reagent_dispensers/fueltank, -/obj/effect/turf_decal/stripes/line{ - dir = 10 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "bdQ" = ( /obj/structure/closet/secure_closet/medical2, /obj/machinery/airalarm{ @@ -32756,148 +34790,10 @@ /obj/machinery/door/poddoor/incinerator_toxmix, /turf/open/floor/engine/vacuum, /area/science/mixing) -"beu" = ( -/obj/structure/table/wood, -/obj/item/storage/pill_bottle, -/turf/open/floor/plating, -/area/maintenance/port) -"bev" = ( -/obj/machinery/computer/slot_machine, -/obj/machinery/light/small, -/obj/structure/sign/poster/contraband/random{ - pixel_y = -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{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"bew" = ( -/obj/structure/table/wood, -/obj/item/coin/iron{ - icon_state = "coin_bananium_heads"; - name = "arcade coin"; - pixel_x = 6 - }, -/obj/item/coin/iron{ - icon_state = "coin_bananium_heads"; - name = "arcade coin"; - pixel_x = -6 - }, -/obj/item/coin/iron{ - icon_state = "coin_bananium_heads"; - name = "arcade coin"; - pixel_y = 6 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bex" = ( -/obj/structure/table/wood, -/obj/item/reagent_containers/blood/random, -/obj/item/reagent_containers/syringe{ - pixel_y = 5 - }, -/obj/item/reagent_containers/syringe, -/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/maintenance/port) -"bey" = ( -/obj/structure/table/wood, -/obj/item/newspaper, -/obj/item/clothing/head/bowler, -/turf/open/floor/plating, -/area/maintenance/port) -"bez" = ( -/obj/structure/sign/poster/contraband/random{ - pixel_y = -32 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"beA" = ( -/obj/machinery/computer/security/telescreen/entertainment{ - pixel_y = -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{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) -"beB" = ( -/obj/machinery/door/window{ - dir = 8; - name = "Theatre Stage" - }, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) -"beC" = ( -/obj/structure/table/wood, -/obj/item/lipstick/random{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/item/lipstick/random{ - pixel_x = -3; - pixel_y = -3 - }, -/obj/item/lipstick/random, -/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/maintenance/port) "beE" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/medical/medbay/zone3) -"beF" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Medbay Maintenance"; - req_access_txt = "5" - }, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "beG" = ( /obj/structure/sign/departments/medbay/alt, /turf/closed/wall, @@ -33034,93 +34930,6 @@ }, /turf/closed/wall/r_wall, /area/science/robotics/lab) -"beR" = ( -/obj/structure/cable/white{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"beS" = ( -/obj/structure/cable/white{ - icon_state = "2-8" - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/port) -"beV" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "2-4" - }, -/obj/structure/cable/white{ - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/plating, -/area/maintenance/port) -"beZ" = ( -/obj/structure/cable/white{ - 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) -"bfa" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/structure/cable/white{ - icon_state = "1-8" - }, -/obj/structure/cable/white{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plating, -/area/maintenance/port) -"bfb" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating{ - icon_state = "platingdmg3" - }, -/area/maintenance/port) -"bfd" = ( -/obj/structure/closet/emcloset, -/obj/effect/turf_decal/stripes/line{ - dir = 10 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "bfe" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/airalarm/unlocked{ @@ -33254,22 +35063,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on, /turf/open/floor/plasteel/white, /area/chapel/main) -"bfw" = ( -/obj/structure/bonfire, -/obj/item/reagent_containers/food/drinks/bottle/orangejuice{ - desc = "For the weary spacemen on their quest to rekindle the first plasma fire."; - name = "Carton of Estus" - }, -/obj/item/nullrod/claymore/glowing{ - desc = "Don't tell anyone you put any points into dex, though."; - force = 10; - name = "moonlight greatsword" - }, -/obj/effect/decal/remains/human, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/chapel/main) "bfx" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 5 @@ -33282,122 +35075,16 @@ }, /turf/closed/wall, /area/chapel/main) -"bfz" = ( -/obj/machinery/door/airlock/grunge{ - name = "Crematorium"; - req_access_txt = "27" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/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/maintenance/port) "bfA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, /turf/closed/wall, /area/chapel/main) -"bfB" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plating, -/area/maintenance/port) "bfC" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/closed/wall/rust, /area/chapel/main) -"bfD" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 - }, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/stripes/line{ - dir = 5 - }, -/obj/item/storage/backpack, -/obj/item/crowbar, -/obj/item/wrench, -/obj/structure/rack, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bfE" = ( -/obj/structure/cable/white{ - icon_state = "1-4" - }, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/landmark/blobstart, -/turf/open/floor/plating{ - icon_state = "platingdmg1" - }, -/area/maintenance/port) -"bfF" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/landmark/event_spawn, -/obj/item/tank/internals/oxygen/red, -/obj/item/clothing/mask/gas, -/turf/open/floor/plating, -/area/maintenance/port) -"bfG" = ( -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/port) -"bfH" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/structure/cable/white{ - icon_state = "4-8" - }, -/obj/effect/turf_decal/stripes/line{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/port) "bfI" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/structure/cable/white{ @@ -33680,22 +35367,6 @@ }, /turf/open/floor/plasteel/dark, /area/chapel/main) -"bgc" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/effect/turf_decal/bot, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/machinery/portable_atmospherics/canister/oxygen, -/turf/open/floor/plasteel, -/area/maintenance/port) -"bgd" = ( -/obj/structure/closet/firecloset, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "bge" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 8 @@ -33813,7 +35484,7 @@ /turf/open/floor/plasteel/dark, /area/maintenance/starboard/aft) "bgw" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/airalarm{ @@ -33836,7 +35507,7 @@ /turf/open/floor/plasteel/dark, /area/maintenance/starboard/aft) "bgy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -34022,21 +35693,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/hallway/secondary/entry) -"bgO" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Maintenance Hatch"; - req_access_txt = "12" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/maintenance/port) "bgP" = ( /turf/closed/wall, /area/hallway/secondary/entry) @@ -34532,7 +36188,7 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/entry) "bhL" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -34643,7 +36299,7 @@ /turf/open/floor/plasteel/dark, /area/maintenance/starboard/aft) "bhU" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -35939,7 +37595,7 @@ /turf/closed/wall/r_wall, /area/engine/atmos) "bkt" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light{ @@ -35982,7 +37638,7 @@ /turf/open/floor/plasteel, /area/hallway/secondary/entry) "bkE" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -37437,14 +39093,6 @@ heat_capacity = 1e+006 }, /area/hallway/primary/port/aft) -"bxR" = ( -/obj/structure/cable/white{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plating, -/area/maintenance/port) "bxS" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -37868,22 +39516,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"dEa" = ( -/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/computer/arcade{ - dir = 4 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "dFV" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 @@ -37964,9 +39596,17 @@ /turf/open/floor/plasteel, /area/engine/atmos) "edA" = ( -/obj/structure/lattice, -/turf/open/space/basic, -/area/space) +/obj/effect/turf_decal/stripes/line, +/obj/machinery/door/airlock/external{ + name = "External Airlock"; + req_access_txt = "13" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/maintenance/starboard/fore) "eew" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/structure/cable{ @@ -39607,9 +41247,6 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/hallway/primary/starboard/fore) -"nxA" = ( -/turf/closed/wall, -/area/hallway/primary/port/aft) "nFG" = ( /obj/machinery/atmospherics/pipe/manifold/yellow/visible{ dir = 8 @@ -40347,6 +41984,16 @@ }, /turf/open/floor/plasteel, /area/hydroponics) +"saI" = ( +/obj/structure/cable/white{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/mob/living/simple_animal/opossum, +/turf/open/floor/plating, +/area/maintenance/starboard) "scn" = ( /obj/structure/cable{ icon_state = "4-8" @@ -40456,10 +42103,6 @@ "swC" = ( /turf/closed/wall/r_wall/rust, /area/crew_quarters/heads/captain/private) -"swF" = ( -/obj/structure/sign/warning/securearea, -/turf/closed/wall/rust, -/area/asteroid/nearstation) "swG" = ( /turf/closed/wall/rust, /area/security/detectives_office) @@ -40498,9 +42141,6 @@ /obj/machinery/status_display/supply, /turf/closed/wall/rust, /area/quartermaster/storage) -"swN" = ( -/turf/closed/wall/rust, -/area/asteroid/nearstation) "swZ" = ( /turf/closed/wall/r_wall/rust, /area/security/brig) @@ -40592,12 +42232,6 @@ /obj/structure/sign/warning/vacuum, /turf/closed/wall/rust, /area/maintenance/starboard) -"sCb" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/closed/wall, -/area/medical/medbay/zone3) "sCr" = ( /obj/structure/cable/white{ icon_state = "1-2" @@ -41238,9 +42872,6 @@ /obj/structure/sign/warning/securearea, /turf/closed/wall/rust, /area/maintenance/starboard) -"sIO" = ( -/turf/open/space/basic, -/area/space/nearstation) "sIP" = ( /obj/machinery/vending/cola/random, /obj/effect/turf_decal/bot, @@ -41431,10 +43062,6 @@ "sJG" = ( /turf/closed/wall/r_wall/rust, /area/engine/supermatter) -"sJH" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall/r_wall/rust, -/area/maintenance/port) "sJI" = ( /turf/closed/wall/rust, /area/library) @@ -41495,9 +43122,6 @@ icon_state = "wood-broken7" }, /area/library) -"sJT" = ( -/turf/closed/wall/rust, -/area/medical/morgue) "sJV" = ( /turf/closed/wall/r_wall/rust, /area/tcommsat/server) @@ -41575,33 +43199,13 @@ "sKp" = ( /turf/closed/wall/rust, /area/medical/medbay/zone3) -"sKx" = ( -/turf/closed/wall/r_wall/rust, -/area/maintenance/port) "sKB" = ( /turf/closed/wall/rust, /area/security/checkpoint) -"sKE" = ( -/turf/closed/wall/rust, -/area/maintenance/port) -"sKH" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/closed/wall/rust, -/area/maintenance/port) -"sKI" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/closed/wall/rust, -/area/maintenance/port) "sKJ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall/r_wall/rust, /area/science/robotics/lab) -"sKL" = ( -/obj/structure/sign/poster/contraband/random, -/turf/closed/wall/rust, -/area/maintenance/port) "sKP" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -41614,11 +43218,6 @@ }, /turf/closed/wall/r_wall/rust, /area/science/robotics/lab) -"sKW" = ( -/turf/open/floor/plating{ - icon_state = "panelscorched" - }, -/area/maintenance/port) "sKZ" = ( /turf/closed/wall/r_wall/rust, /area/science/xenobiology) @@ -41626,7 +43225,7 @@ /turf/closed/wall/rust, /area/chapel/main) "sLg" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/delivery, @@ -43609,6 +45208,10 @@ /obj/effect/landmark/carpspawn, /turf/open/space, /area/space/station_ruins) +"uXV" = ( +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/wood, +/area/maintenance/port/aft) "ver" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ dir = 10 @@ -69851,7 +71454,7 @@ aaa aaa aaa aaa -aaa +sdX uhz uhz oxn @@ -70108,7 +71711,7 @@ aac aac aac aac -aaa +sdX uhz iye mJP @@ -72190,10 +73793,10 @@ aad aad aad aad -baj -aqo -baj -baj +aKm +aKo +aKm +aKm aaa aaa aaa @@ -72448,9 +74051,9 @@ aMJ aMJ sJV aMJ -aqx -awH -baj +aKr +aLz +aKm aaa aaa aaa @@ -72705,9 +74308,9 @@ buJ buO sKn aMJ -atE -sKx -baj +aKB +aLs +aKm aac aaa aaa @@ -72962,8 +74565,8 @@ buK sKj buR aMJ -avB -aOH +aKF +aqo aad aac aaa @@ -73219,8 +74822,8 @@ buL buP buS aMJ -awB -baj +aKJ +aKm aad aad aaa @@ -73476,8 +75079,8 @@ buK sKj buR aMJ -awB -baj +aKJ +aKm aad aad aaa @@ -73733,8 +75336,8 @@ buN buQ buU sJV -awB -aOH +aKJ +aqo aad aaa aaa @@ -73990,9 +75593,9 @@ sJV aMJ aMJ sJV -awB -aOH -sKx +aKJ +aqo +aLs aac aaa aaa @@ -74246,10 +75849,10 @@ bvo aad bvo aad -baj -awE -awL -baj +aKm +aLp +aLB +aKm aac aac aac @@ -74464,7 +76067,7 @@ aik aaW abj abj -abu +ahB abu pNE gap @@ -74503,10 +76106,10 @@ aUQ aVK aUQ aXc -baj -aOH -axY -awG +aKm +aqo +aLC +aLv aac aac aac @@ -74761,9 +76364,9 @@ aVL aUR aUQ bvo -sKx -awB -baj +aLs +aKJ +aKm aac aad aac @@ -74966,7 +76569,7 @@ aaa aac aac aad -aah +adx aad aac aac @@ -75018,9 +76621,9 @@ aUU aWz aVL bvo -aOH -axh -baj +aqo +aLL +aKm aad aad aad @@ -75223,7 +76826,7 @@ aaa aaa aaa aac -aac +adz aad aad aad @@ -75235,7 +76838,7 @@ agK abu aad aad -abj +azf abi pNE aoq @@ -75275,10 +76878,10 @@ aUU aWz aUQ bvg -baj -awB -baj -baj +aKm +aKJ +aKm +aKm aad aad aad @@ -75480,7 +77083,7 @@ aaa aaa aaa aac -aac +adz aac aac aad @@ -75532,10 +77135,10 @@ aUU aWz aVL bvg -awG -awB -axj -baj +aLv +aKJ +aME +aKm aad aad aad @@ -75737,7 +77340,7 @@ aaa aaa aaa aaa -aac +adz aac aac aac @@ -75747,7 +77350,7 @@ aad aad adv aaW -abj +ayg ahB abu acF @@ -75789,17 +77392,17 @@ aUU aUU aUQ bvg -baj -awB -axk -baj -aad -aad -aad -aad -aad -aad +aKm +aKJ +aMF +aKm +aac +aac aad +aKm +aKm +aKm +aKm aad aad aaa @@ -75994,7 +77597,7 @@ aaa aaa aaa aaa -abR +aXc aac aac aad @@ -76003,7 +77606,7 @@ aad aad abi ael -abj +abu abu abu alG @@ -76046,21 +77649,21 @@ aUU aWz aVL bvg -baj -awB -aZo -baj -aad -aad -aad -aad -aad -aad -aad -aad -aac -aac -aaa +aKm +aKJ +aMG +aKm +aKm +aKm +aKm +aKm +aOs +aSf +aKV +aKV +aKV +aLw +aLw aaa aaa aaa @@ -76251,17 +77854,17 @@ aaa aaa aaa aaa -abR +aXc aac aac aad aad -aad -aad -abT -abi -aaV -ajQ +aro +aro +aro +aro +azg +aro aro aro asm @@ -76303,21 +77906,21 @@ aUU aWz aUQ bvo -baj -awE -awL -baj -aad -aad -aad -aad -aad -aad -aad -aad -aad -aac -aac +aKm +aLp +aLB +aOI +aPQ +aPQ +aPQ +aPQ +aPQ +aVF +aKV +aLn +aRA +aSp +aLw aaa aaa aaa @@ -76508,17 +78111,17 @@ aaa aaa aac aac -aac +adz aac aac aad aad -aad -aad -aaW -abj -abj -abu +aro +ars +ars +ars +ars +ars arp ars ars @@ -76560,21 +78163,21 @@ aUU aWz aVL bvo -aOH -baj -axl -sKE -baj -aZo -aZo -sKE -baj -aad -aad -aad -aad -aad -aac +aqo +aKm +aMH +axU +aKm +aMG +aMG +aUi +aKm +aVG +aKV +aSe +aSJ +aTm +aLw aaa aaa aaa @@ -76765,19 +78368,19 @@ aac aac aad aac -aac +aem aad aad aad aad -abi -agE -abj -abi -aad -aad +aro +ars +akb +asu +ayd +ayy arq -art +azh ars asy ars @@ -76817,21 +78420,21 @@ aUU aWz aUQ aad -sKx -aZp -bam -bbc -bbQ -dEa -bdD -beu -sKE -aad -aad -aad -aad -aad -aac +aLs +aLX +aMI +aOL +aPR +aQV +aSq +aUk +aUi +aVG +aKV +aTk +aSK +aYE +aKV aad aaa aaa @@ -77021,14 +78624,14 @@ aaa aac aad aad -aad -swF -aad -aad -aad -aad -aad -abj +acH +acH +acH +acH +acH +acH +acH +ars agF agF agF @@ -77074,23 +78677,23 @@ aUU aUU aVL aad -aOH -aZq -axn -axU -axX -bcG -bdE -bev -baj -aad -aad -aad -aad -aad -aad -aad -aad +aqo +aMv +aMQ +aOM +aPS +aRc +aSs +aUl +aKm +aVG +aKV +aTl +aXD +aKV +aKV +aKV +aKV aaa aaa aaa @@ -77278,14 +78881,14 @@ aac aac aad aad -aad -aad -aad -aad -aad -aad -aad -abu +acH +afL +ahD +aye +aAl +aAf +acH +ars agF apw aqB @@ -77331,23 +78934,23 @@ bvg bvg bvo bvo -aOH -aZr -bam -bbe -bbS -bcH -bcG -bcF -baj -aad -aad -aad -aad -aad -aad -aad -aad +aqo +aMw +aMI +aON +aPT +aRd +aRc +aUm +aKm +aVH +aRe +aTn +aWL +aZB +aTv +aTW +aLw aac aaa aaa @@ -77535,14 +79138,14 @@ aac aac aad aad -aad -aad -aad -aad -aad -aad -abT -agE +acH +afP +aiv +ayf +aAd +aAk +acH +ars swZ apR aqD @@ -77577,34 +79180,34 @@ aKH acB aEt aEt -aOH -aPO -sJH -aQU -aQU -sJH -sJH -aQU -aQU -sJH -aQU -aQU -aZs -axL -bap -bbT -bcI -bar -bew -aZo -aad -aad -aad -aad -aad -aad -aad -aad +aqo +awH +axX +aEg +aEg +axX +axX +aEg +aEg +axX +aEg +aEg +aMD +aOc +aOS +aPU +aRj +aSG +aUo +aMG +aSg +aKV +aUK +aXY +aTo +aTQ +aUh +aKV aac aac aaa @@ -77792,14 +79395,14 @@ aad aad aad aad -aad -aad -aad -aad -aad -ahu -afL -aaW +acH +azQ +aAc +aAc +aAm +acH +acH +ars swZ ain aqG @@ -77834,34 +79437,34 @@ aKI aLY aNa aEt -aOI -aPP -bxR -aRS -aTb -aUb -aVM -aVM -aTb -aTb -aTb -aVM -aTb -bao -bbf -aZA -bbR -bdF -bcK -baj -aad -aad -aad -aad -aad -aad -aad -aad +aqx +awL +axY +aEj +aFM +aJN +aKl +aKl +aFM +aFM +aFM +aKl +aFM +aOH +aOT +aPV +uXV +aSI +aRC +aKm +aSr +aKV +aWI +aYz +aKV +aZD +aYD +aKm aad aac aac @@ -78046,17 +79649,17 @@ aaa aad aad aad -aad -aad -aad -aad -aad -aad -aad -aad -ahu -abu -abj +acH +acH +acH +acH +aAa +aep +azo +aAo +acH +ars +ars agF aio aiT @@ -78091,8 +79694,8 @@ apt aLZ aNb aEt -bbg -aPQ +atE +axh aQW aQW aQW @@ -78105,20 +79708,20 @@ sJI aQW sJI aQW -bbg -aZz -bcJ -bdG -bev -baj -aad -aad -aad -aad -aad -aad -aad -aad +atE +aQB +aRn +aSL +aUl +aKm +aSQ +aKV +aWJ +aYB +aKV +aYA +aZJ +aKm aad aad aac @@ -78303,15 +79906,15 @@ aac aad aad aad -aad -aad -aad -aad -abi -abi -swN -abi -agF +acH +abR +afh +azi +agG +aiS +acH +aAw +acH afT agF agF @@ -78348,8 +79951,8 @@ aKK aMa aNc aEt -bbg -aPR +atE +axk aQW aRT aRU @@ -78362,23 +79965,23 @@ jnK aYw aZu aQW -aYA -sKH -bcK -bdH -bex -sKE -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad +awB +aQF +aRC +aTb +aUp +aUi +aTj +aKV +aWM +aKV +aKV +aZE +aKm +aKm +aKm +aKm +aKm aad aad aad @@ -78560,17 +80163,17 @@ aac aad aad aad -aad -aad -aad -aaV -aaW -abj -adv -ael -agF +acH +adw +aep +azn +aep +ajb +acH +aAU +acH afU -ahz +ahC aiu aiq aiV @@ -78605,8 +80208,8 @@ aKL aMb aNd sHV -aOL -aPS +avB +axl sJI aSc aTc @@ -78619,23 +80222,23 @@ aXL aYx aZv aQW -bbh -aPV -baj -sKL -baj -aZo -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad +aOV +axU +aKm +aTU +aKm +aMG +aVI +aWw +aXd +aKm +aRm +aRm +aYF +aYX +aZp +aZt +aKm aad aad aad @@ -78817,18 +80420,18 @@ aad aad aad aad -aad -aaV -abi -abj -abj -abS -abu -acF -agF -agG -afU -aiv +acH +abT +azi +azi +aep +ajQ +acH +aAU +acH +ahz +aBw +aCp air aiW ajW @@ -78862,8 +80465,8 @@ aKM aMa aNe aEt -aYA -aPT +awB +axn aQW amH aTd @@ -78876,23 +80479,23 @@ aXM aYy aZw aQW -bbg -bbV -bcL -bdI -bey -aZo -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad +atE +aQQ +aRS +aTV +aUq +aMG +aVJ +aWx +aXe +aXN +aXO +aYC +aYG +aZn +aZp +aZx +aKm aad aad aad @@ -79074,19 +80677,19 @@ aad aad aad aad -aad -aaW -abj -abj -abS -acD -acF -aem -afg -afU -afU -agH -ahv +acH +acE +azj +acH +afe +ajZ +acH +aBi +ahu +aBo +aBx +aCq +aya aiX agm akY @@ -79119,8 +80722,8 @@ aKN aMc aNf aEt -aOM -aPU +awE +axL aQW aRW aTe @@ -79133,23 +80736,23 @@ aQW aQW aQW sJI -bbj -bbW -bcM -bdJ -bez -baj -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad -aad +aPO +aQU +aRV +aUb +aUu +aUN +aVM +aKm +aKm +aKm +aZC +aRm +aRm +aZo +aZp +aZy +aKm aad aad aac @@ -79331,17 +80934,17 @@ aad aad aad aad -aad -aad -abi -abj -abu -acE -adx -acF -agF -afU -ahC +acH +acH +acH +acH +agH +art +acH +acJ +acH +aBq +aja aiR ait aiY @@ -79376,37 +80979,37 @@ aKO aMd aNg aEt -aON -aPV +awG +axU aQW aRX aTf -sJX -aUX +axj +aCB +aDm +aDn +aDo +aKn +aLy +aFM +aFM +aPP +aQQ +aSm +aSm +aUJ +aKm aVR -aVQ -aXg -aQW -aYz -aTb -aTb -bbk -bbV -bcN -bdK -beA -baj -aad -aad -aad +aKm +aXi bfu bfu sLf bfu bfu -aad -aad -aad +aZq +aKm +aKm aac aac aaa @@ -79589,20 +81192,20 @@ aad aad aad aad -aad -aad -aaW -abu -acF -acF -acF -agF +aac +azk +acH afe -agF -swZ -agF -aiZ ajZ +acH +acH +acH +aBs +acH +axZ +acH +aiZ +ayD ala aiZ amN @@ -79643,16 +81246,16 @@ bxS aVS aWE aXh -aQW -bbg -aZy -bap -bap -bbX -bcO -bdL -beB -sKE +ajG +ajG +ajG +ajG +ajG +aHK +aRb +aRb +aUL +sLf bfu bfu sLf @@ -79661,9 +81264,9 @@ bhZ biF bjf bfu -aad -aad -aac +aZr +aZp +aLv aac aaa aaa @@ -79846,20 +81449,20 @@ aad aad aad aad -aad -aad -abi -abi -acJ -adz -swN -abT -acF -ahD -aiS -agF -aja -aka +afg +aac +acH +ahv +ayb +aAb +aBj +aBl +aBu +aBz +aBz +aCr +aCu +azc ala alP aka @@ -79899,17 +81502,17 @@ sJX aUY aVT aVQ -aXi -aQW -bbg -aZz -baq -bbl -bbY -bbm -bdM -bbm -sKE +aXg +ajG +aGY +aOl +aOQ +aCy +aPC +aQh +aRb +aKJ +sLf bfv bfS bgB @@ -79918,9 +81521,9 @@ bia biG bjg bfu -aad -aad -aac +aZs +aZz +aKm aaa aaa aaa @@ -80104,19 +81707,19 @@ aad aad aad aad -aad -aad -abT +bvI acH -adw -aep -afh -aem -afP ahA -swZ -ajb -akb +ayc +aAe +aBk +aBm +aBv +aCo +aCo +aCt +aCv +azd ala alQ bxA @@ -80157,16 +81760,16 @@ sKe aVU aWE aXj -sJI -aYC -aZA -bar -bbm -bbZ -bbm -bbm -bbm -baj +ajG +aOb +aPF +aRo +aFZ +aRp +aQi +aRb +aKJ +bfu bfu bfu bfu @@ -80177,7 +81780,7 @@ bjh bfu sLf bfu -aac +aKm aaa aaa aaa @@ -80362,7 +81965,7 @@ aad aad aad aad -aad +acH abU abU abU @@ -80373,7 +81976,7 @@ abU abU abU ajc -ajc +aze aip ajc ajc @@ -80404,27 +82007,27 @@ aIB aIB aIB aIB -aOR +aiQ aPZ aQZ aSb sJS -aUh -aUZ +aBn +aDf aVV aVQ aXk -aQW -bbg -aPV -bas -bbn -bca -bcR -bdN -beC -baj -bfw +ajG +aOZ +aQe +aOK +aCy +aPE +aSo +aRb +aLp +aLB +aVW bfu bgC bhp @@ -80661,26 +82264,26 @@ aKP aMe aNj aIB -aOS +aDk aQa aQX aSc aTi -aUi -aVa -aVW -aWF -aVW -aXN -aYE -aZB -bap -bap -sKI -bap -bap -bap -bap +aCx +aCx +aVQ +aWE +aDq +ajG +aOe +aRl +aCy +aCy +aRw +aQC +aHb +aHb +aUZ bfx bfu bfu @@ -80918,7 +82521,7 @@ aKQ aMf aNk aOf -aOT +aDp aQb aRa aSd @@ -80928,16 +82531,16 @@ aVb aVX aWG aXl -aQW -aYF -bxR -aRS -aTb -bcb -bcS -aTb -aVM -beR +aSh +aOg +aGC +aGC +aPA +aJx +aQD +aQI +aHi +aVa bfy bfT bgD @@ -81177,25 +82780,25 @@ aNl aID aOU aQc -aRb -aRb -sJT -aRb -aRb -aRb -aRb +ail +ail +aFo +ail +ail +ail +ail +ail aSh -aSh -aSh -aSh -aSh -sKp -bcc -bcT -bdP -aZo -beS -bfz +aPg +aNS +aPz +aPB +aPH +aQE +aQL +aRb +aVc +aVY bfU bgE bhr @@ -81432,26 +83035,26 @@ aKS aMh aNm aIB -aOV -aQd -aRc -aSe -aTj -aUk -aVc -aVY -aWH -sKp -aXO -aYG -aZC -bat +aEh +aFh +aGf +aHG +aJe +aJo +aLo +aLu +aMl +aOW +aOX +aGZ +aOE +aPv aSh aSh aSh aSh aSh -bbg +atE bfA bfu bgF @@ -81689,26 +83292,26 @@ aIB sIK aIB aIB -aOW -aPZ -aRd -aSf -aTk -aSf -aVd -aVZ -aWI -aSh +aEi +aFj +aGl +aHJ +aJf +aJv +aLq +aLx +aMY +ail aXP aYH -aZD -bau +aFp +aPD aSh bcd bcU bdQ aSh -bbg +atE bfA bfV bgG @@ -81946,27 +83549,27 @@ aKT aMi aNn aHM -aOX -aQe -aRe -aSg -aTl +aEk +aGd +aHf +aHX +aJg +aJA +aLr +aLA +aNO ail -aVe -aWa -aWJ -aSh aXQ aYI -ajG -bav +aOJ +aHa aSh bce bcV bdR sKp -beV -bfB +aVd +aVZ bfW bgH bht @@ -82203,16 +83806,16 @@ aKU aMj aNt csX -aOY +aEl aQf -nxA -aSh -aSh -aSh -aVf -sCb -aSh -aSh +ail +ail +ail +ail +aNp +aOA +ail +ail aXR aYJ aZF @@ -82222,7 +83825,7 @@ bcf bcW blt ooX -aOL +avB bfA bfX bgI @@ -82460,15 +84063,15 @@ aKX lyp bIJ aOj -aOZ +aEm bxQ sJJ -aSh -aTm -aUo -aVg -aWc -aWK +ail +aGF +aJO +aNL +aNo +aNP aXm aXS aYK @@ -82479,7 +84082,7 @@ bcg bcX bdS aSh -aOL +avB bfy bfY bgJ @@ -82720,12 +84323,12 @@ aHM aPa aQb aKg -aSh -aTn -aUp -aVh -aWd -aWL +ail +aHc +aKk +aNM +aOB +aNQ aXn bxT aYL @@ -82736,7 +84339,7 @@ aUn aWb bdT aSh -bbg +atE bfA bfZ bgK @@ -82977,12 +84580,12 @@ aOh vsL aQd sJK -aSi -aTo -aUq -aVi -aWe -aWM +aFm +aHd +aJd +aNN +aOR +aNR aXo aXT aYM @@ -82993,7 +84596,7 @@ bch bcY bdU beE -beZ +aVe bfC bga bgL @@ -83249,8 +84852,8 @@ bbq bbq bbq bdV -beF -bfa +aUM +aVf bfA bgb bgM @@ -83495,7 +85098,7 @@ aSj aTq aUs aVj -aWf +aWg aTp aXq aXV @@ -83507,7 +85110,7 @@ bci bcZ bdW aSh -bbg +atE bfA bfu bfu @@ -83748,25 +85351,25 @@ aHM aPd aQc aRf +aiJ aSk aTr -aUt aVl -aWg +aWh aRf aXr aXW aYP aZL baC -bbs +aHs aSi aWK aWK aSh -bfb -bfD -bgc +aVg +aWa +aWy bgN bhz bip @@ -84007,24 +85610,24 @@ aQg aRh aSl aTs -aiJ -aVl -aWh +aUt +aVn +aWj aRh aXs aXX aYQ aZM baD -bbr +bbs aWK bda bdX aSh -aYF -bfE -bdO -bgO +aVh +aWc +aWF +aXv bhA biq biV @@ -84269,7 +85872,7 @@ aVm aWi aWN aXt -aiQ +aOY aYR aZN ajO @@ -84278,9 +85881,9 @@ bcj bdb bdY aSh -sKW -bfF -aZo +aVi +aWd +aMG bgP bhB bir @@ -84522,8 +86125,8 @@ aRg aSn aTu aUw -aVn -aWj +aWf +aZA aWO aXu aXZ @@ -84535,9 +86138,9 @@ bck bdc bdZ aSh -bfd -bfG -bgd +aVk +aWe +aWH bgP bhC bis @@ -84792,9 +86395,9 @@ aSh aWK bea beG -sKE -bfH -baj +aUi +aWv +aKm bgQ bhD bit @@ -89610,7 +91213,7 @@ aaa aae aaa aaa -aac +bxZ abL bxZ swz @@ -89867,7 +91470,7 @@ aaa aae aad aac -bvg +edA abM acu adt @@ -90124,7 +91727,7 @@ aad aah aad aad -aad +bxZ bxZ adq bxZ @@ -90930,7 +92533,7 @@ aSD aRz aRz aRz -sGY +saI aRz sIb bsD @@ -91449,7 +93052,7 @@ aRz sIc sIv sFs -sIO +aaa sIU sJe sIU @@ -96867,9 +98470,9 @@ aac aaa aaa aaa -edA +sdX aaa -edA +sdX aac aac aac @@ -97124,9 +98727,9 @@ aac aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aac aaa @@ -97381,9 +98984,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -97638,9 +99241,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -97895,9 +99498,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -98152,9 +99755,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -98409,9 +100012,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -98666,9 +100269,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -98923,9 +100526,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -99180,9 +100783,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -99437,9 +101040,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -99694,9 +101297,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -99951,9 +101554,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -100208,9 +101811,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -100465,9 +102068,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -100722,9 +102325,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -100979,9 +102582,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -101236,9 +102839,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -101493,9 +103096,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -101750,9 +103353,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -102007,9 +103610,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -102264,9 +103867,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -102521,9 +104124,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -102778,9 +104381,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -103035,9 +104638,9 @@ jFP aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -103292,9 +104895,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -103549,9 +105152,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa @@ -103806,9 +105409,9 @@ aaa aaa aaa aaa -edA +sdX aaa -edA +sdX aaa aaa aaa diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 18d1b115a4..263cb44144 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -263,15 +263,484 @@ }, /turf/open/floor/plasteel, /area/maintenance/department/engine) +"aaD" = ( +/obj/structure/cable{ + icon_state = "2-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 10 + }, +/obj/structure/closet/crate{ + icon_state = "crateopen" + }, +/obj/effect/spawner/lootdrop/maintenance{ + lootcount = 2; + name = "2maintenance loot spawner" + }, +/obj/item/clothing/mask/balaclava, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"aaE" = ( +/obj/machinery/light/small, +/obj/machinery/space_heater, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"aaF" = ( +/turf/closed/wall, +/area/crew_quarters/fitness/pool) +"aaG" = ( +/obj/structure/closet, +/obj/item/weldingtool, +/obj/item/crowbar, +/obj/effect/spawner/lootdrop/maintenance, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"aaH" = ( +/obj/machinery/door/airlock/maintenance{ + req_access_txt = "12" + }, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"aaI" = ( +/obj/structure/closet/secure_closet/personal, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/fitness/pool) +"aaJ" = ( +/obj/effect/spawner/structure/window/reinforced, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"aaK" = ( +/obj/machinery/light{ + dir = 1; + light_color = "#706891" + }, +/obj/structure/closet/secure_closet/personal, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/fitness/pool) +"aaL" = ( +/turf/open/floor/plasteel/yellowsiding, +/area/crew_quarters/fitness/pool) +"aaM" = ( +/turf/open/floor/plasteel/yellowsiding/corner{ + dir = 8; + icon_state = "yellowcornersiding" + }, +/area/crew_quarters/fitness/pool) +"aaN" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 6 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/pool) +"aaO" = ( +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"aaP" = ( +/turf/open/floor/plasteel/yellowsiding{ + dir = 8; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"aaQ" = ( +/obj/structure/table, +/obj/effect/spawner/lootdrop/maintenance, +/obj/item/storage/box/lights/mixed, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"aaR" = ( +/obj/machinery/airalarm{ + pixel_y = 22 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/pool) +"aaS" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/pool) +"aaT" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Pool" + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/pool) +"aaU" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/sign/poster/official/walk{ + pixel_y = 32 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/pool) +"aaV" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/structure/extinguisher_cabinet{ + pixel_y = 30 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/pool) +"aaW" = ( +/turf/open/floor/plasteel/yellowsiding{ + dir = 1; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"aaX" = ( +/obj/structure/bed, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/fitness/pool) +"aaY" = ( +/obj/effect/spawner/structure/window, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"aaZ" = ( +/obj/structure/bed, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/crew_quarters/fitness/pool) +"aba" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/recreation) +"abb" = ( +/obj/machinery/camera{ + c_tag = "Fitness Room" + }, +/obj/machinery/computer/security/telescreen/entertainment{ + pixel_y = 32 + }, +/obj/machinery/light{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/recreation) +"abc" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/yellowsiding/corner, +/area/crew_quarters/fitness/pool) +"abd" = ( +/obj/structure/closet/lasertag/red, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abe" = ( +/obj/machinery/vending/kink, +/obj/machinery/status_display/evac{ + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) "abf" = ( /obj/structure/bed, /turf/open/floor/plating, /area/maintenance/department/science) +"abg" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abh" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/closet/lasertag/blue, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abi" = ( +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abj" = ( +/obj/machinery/pool/controller, +/turf/open/floor/plasteel/yellowsiding, +/area/crew_quarters/fitness/pool) +"abk" = ( +/obj/machinery/light{ + dir = 4; + light_color = "#e8eaff" + }, +/obj/structure/bed, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/crew_quarters/fitness/pool) +"abl" = ( +/obj/machinery/airalarm{ + dir = 4; + pixel_x = -23 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/recreation) +"abm" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abn" = ( +/obj/machinery/pool/filter{ + pixel_y = 24 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abo" = ( +/obj/structure/pool/ladder{ + dir = 2; + pixel_y = 24 + }, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abp" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/crew_quarters/fitness/pool) +"abq" = ( +/obj/machinery/light{ + dir = 8; + light_color = "#e8eaff" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abr" = ( +/obj/machinery/pool/drain, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abs" = ( +/obj/structure/pool/Lboard, +/turf/open/pool, +/area/crew_quarters/fitness/pool) +"abt" = ( +/obj/structure/pool/Rboard, +/turf/open/floor/plasteel/yellowsiding{ + dir = 8; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abu" = ( +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_x = 28 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/crew_quarters/fitness/pool) +"abv" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/item/cigbutt, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"abw" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/structure/table/glass, +/obj/item/storage/firstaid/regular, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/pool) +"abx" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/structure/closet/athletic_mixed, +/obj/item/toy/poolnoodle/blue, +/obj/item/toy/poolnoodle/red, +/obj/item/toy/poolnoodle/yellow, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/crew_quarters/fitness/pool) "aby" = ( /obj/structure/lattice, /obj/structure/grille, /turf/open/space, /area/space/nearstation) +"abz" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/structure/extinguisher_cabinet{ + pixel_x = -24 + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/fitness/pool) +"abA" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/yellowsiding/corner{ + dir = 4; + icon_state = "yellowcornersiding" + }, +/area/crew_quarters/fitness/pool) +"abB" = ( +/obj/machinery/firealarm{ + dir = 1; + pixel_x = -2; + pixel_y = -27 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 1; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abC" = ( +/obj/machinery/light, +/turf/open/floor/plasteel/yellowsiding{ + dir = 1; + icon_state = "yellowsiding" + }, +/area/crew_quarters/fitness/pool) +"abD" = ( +/turf/open/floor/plasteel/yellowsiding/corner{ + dir = 1; + icon_state = "yellowcornersiding" + }, +/area/crew_quarters/fitness/pool) +"abE" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 5 + }, +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/machinery/power/apc{ + areastring = "/area/crew_quarters/fitness/pool"; + name = "Pool APC"; + pixel_y = -24 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/turf/open/floor/plasteel/white/corner, +/area/crew_quarters/fitness/pool) +"abF" = ( +/obj/machinery/door/airlock/maintenance{ + req_access_txt = "12" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "4-8" + }, +/turf/open/floor/plating, +/area/crew_quarters/fitness/pool) +"abG" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 4 + }, +/obj/structure/cable{ + icon_state = "2-8" + }, +/turf/open/floor/plating, +/area/maintenance/department/crew_quarters/dorms) +"abH" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/door/airlock/public/glass{ + name = "Pool" + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/fitness/pool) "abI" = ( /obj/structure/lattice, /turf/open/space, @@ -285,6 +754,26 @@ }, /turf/open/space, /area/space/nearstation) +"abK" = ( +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/crew_quarters/fitness/recreation) +"abL" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abM" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) "abN" = ( /obj/effect/landmark/carpspawn, /turf/open/space, @@ -292,6 +781,42 @@ "abO" = ( /turf/closed/wall/r_wall, /area/ai_monitored/turret_protected/ai) +"abP" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abQ" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abR" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abS" = ( +/obj/structure/weightmachine/stacklifter, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness/recreation) +"abT" = ( +/obj/machinery/door/firedoor, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/door/airlock/public/glass{ + name = "Pool" + }, +/turf/open/floor/plasteel/cafeteria, +/area/crew_quarters/fitness/pool) "abV" = ( /obj/effect/turf_decal/stripes/corner, /turf/open/floor/plasteel/white, @@ -1321,7 +1846,7 @@ network = list("minisat") }, /turf/open/space, -/area/ai_monitored/turret_protected/AIsatextAS) +/area/ai_monitored/turret_protected/AIsatextAP) "aeA" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 @@ -1537,7 +2062,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "afe" = ( -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 10 }, /obj/structure/cable/yellow{ @@ -1567,7 +2092,7 @@ /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/aisat_interior) "afg" = ( -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 10 }, /obj/structure/cable/yellow{ @@ -1665,7 +2190,7 @@ /turf/open/floor/plasteel/dark, /area/security/prison) "afp" = ( -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/structure/table, /turf/open/floor/plasteel/dark, /area/security/prison) @@ -2097,9 +2622,6 @@ /obj/machinery/light/small{ dir = 8 }, -/obj/structure/sign/warning/vacuum/external{ - pixel_x = 32 - }, /obj/structure/sign/warning/vacuum/external{ pixel_x = -32 }, @@ -2219,12 +2741,8 @@ /turf/open/floor/plating, /area/security/main) "agR" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, -/obj/machinery/door/airlock/external{ - name = "MiniSat External Access"; - req_access_txt = "65" +/obj/structure/sign/warning/vacuum/external{ + pixel_x = 32 }, /turf/open/floor/plating, /area/ai_monitored/turret_protected/aisat_interior) @@ -2296,12 +2814,15 @@ /turf/open/floor/plasteel/showroomfloor, /area/security/main) "ahh" = ( -/obj/structure/lattice/catwalk, -/obj/structure/showcase/cyborg/old{ - pixel_y = 20 +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 }, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + name = "MiniSat External Access"; + req_access_txt = "65" + }, +/turf/open/floor/plating, +/area/ai_monitored/turret_protected/aisat_interior) "ahi" = ( /obj/structure/lattice/catwalk, /turf/open/space, @@ -2402,13 +2923,15 @@ /turf/open/floor/plasteel/showroomfloor, /area/security/main) "ahr" = ( -/obj/structure/lattice, -/obj/machinery/camera/motion{ - c_tag = "MiniSat Entrance"; - network = list("minisat") +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 }, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + name = "Security External Airlock"; + req_access_txt = "63" + }, +/turf/open/floor/plating, +/area/maintenance/fore) "ahs" = ( /obj/structure/lattice/catwalk, /obj/structure/transit_tube, @@ -3820,18 +4343,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/crew_quarters/dorms) -"akq" = ( -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "akr" = ( /obj/machinery/washing_machine, /obj/item/radio/intercom{ @@ -4177,8 +4688,12 @@ /turf/open/space/basic, /area/space/nearstation) "alb" = ( -/turf/open/floor/wood, -/area/maintenance/department/crew_quarters/dorms) +/obj/structure/lattice/catwalk, +/obj/structure/showcase/cyborg/old{ + pixel_y = 20 + }, +/turf/open/space, +/area/space/nearstation) "alc" = ( /obj/structure/table, /obj/item/storage/fancy/cigarettes/cigars, @@ -5230,16 +5745,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/crew_quarters/dorms) -"anp" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/effect/decal/cleanable/robot_debris{ - icon_state = "gib6" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "anq" = ( /obj/structure/grille/broken, /turf/open/floor/plating, @@ -5479,7 +5984,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/dark, @@ -5810,27 +6315,7 @@ "aoz" = ( /turf/closed/wall, /area/maintenance/fore) -"aoA" = ( -/obj/machinery/gateway{ - dir = 9 - }, -/obj/effect/turf_decal/bot_white/right, -/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/gateway) "aoB" = ( -/obj/machinery/gateway{ - dir = 1 - }, /obj/machinery/light{ dir = 1 }, @@ -5847,23 +6332,6 @@ }, /turf/open/floor/plasteel/dark, /area/gateway) -"aoC" = ( -/obj/machinery/gateway{ - dir = 5 - }, -/obj/effect/turf_decal/bot_white/left, -/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/gateway) "aoH" = ( /obj/structure/lattice, /obj/structure/grille, @@ -6168,13 +6636,6 @@ /turf/open/floor/plating, /area/maintenance/fore) "apn" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external{ - name = "Security External Airlock"; - req_access_txt = "63" - }, /turf/open/floor/plating, /area/maintenance/fore) "apo" = ( @@ -6189,44 +6650,10 @@ }, /turf/open/space, /area/space/nearstation) -"apq" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/turf_decal/bot_white, -/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/gateway) "apr" = ( /obj/machinery/gateway/centerstation, /turf/open/floor/plasteel/dark, /area/gateway) -"aps" = ( -/obj/machinery/gateway{ - dir = 4 - }, -/obj/effect/turf_decal/bot_white, -/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/gateway) "apt" = ( /obj/structure/chair{ dir = 4 @@ -6413,9 +6840,6 @@ /turf/closed/wall/r_wall, /area/ai_monitored/nuke_storage) "apU" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/effect/turf_decal/bot_white/left, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -6430,7 +6854,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "apV" = ( -/obj/machinery/gateway, /obj/effect/turf_decal/bot_white, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -6445,9 +6868,6 @@ /turf/open/floor/plasteel/dark, /area/gateway) "apW" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -6932,10 +7352,6 @@ }, /turf/open/space/basic, /area/space) -"aqZ" = ( -/obj/machinery/space_heater, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "ara" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -7377,32 +7793,7 @@ /turf/open/floor/plasteel, /area/gateway) "arY" = ( -/obj/structure/closet/crate/internals, -/obj/item/clothing/suit/hazardvest{ - desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; - name = "emergency lifejacket" - }, -/obj/item/clothing/suit/hazardvest{ - desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; - name = "emergency lifejacket" - }, -/obj/item/clothing/suit/hazardvest{ - desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; - name = "emergency lifejacket" - }, -/obj/item/clothing/suit/hazardvest{ - desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; - name = "emergency lifejacket" - }, -/obj/item/clothing/suit/hazardvest{ - desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; - name = "emergency lifejacket" - }, -/obj/item/flashlight, -/obj/item/flashlight, -/obj/item/flashlight, -/obj/item/flashlight, -/obj/item/flashlight, +/obj/machinery/computer/gateway_control, /turf/open/floor/plasteel, /area/gateway) "arZ" = ( @@ -7525,35 +7916,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/crew_quarters/dorms) -"asl" = ( -/obj/structure/grille/broken, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) -"asm" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/light{ - dir = 1 - }, -/obj/item/cigbutt, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) -"asn" = ( -/obj/structure/cable{ - icon_state = "2-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 10 - }, -/obj/effect/decal/cleanable/cobweb{ - icon_state = "cobweb2" - }, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "aso" = ( /obj/structure/cable{ icon_state = "1-2" @@ -8021,26 +8383,9 @@ /obj/structure/closet/emcloset/anchored, /turf/open/floor/plating, /area/crew_quarters/dorms) -"atm" = ( -/obj/structure/closet, -/obj/item/weldingtool, -/obj/item/crowbar, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "atn" = ( /turf/closed/wall, /area/crew_quarters/fitness/recreation) -"ato" = ( -/obj/structure/closet/crate{ - icon_state = "crateopen" - }, -/obj/effect/spawner/lootdrop/maintenance{ - lootcount = 2; - name = "2maintenance loot spawner" - }, -/obj/item/clothing/mask/balaclava, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "atp" = ( /obj/structure/cable{ icon_state = "1-2" @@ -8353,13 +8698,18 @@ /turf/closed/wall, /area/bridge) "atZ" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, /obj/machinery/door/airlock/external{ - name = "Bridge External Access"; - req_access_txt = "10;13" + name = "Solar Maintenance"; + req_access_txt = "10; 13" }, /turf/open/floor/plating, -/area/ai_monitored/turret_protected/aisat_interior) +/area/maintenance/solars/starboard) "aua" = ( /obj/structure/closet/secure_closet/freezer/money, /obj/item/reagent_containers/food/drinks/bottle/vodka/badminka, @@ -8451,6 +8801,32 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 }, +/obj/structure/closet/crate/internals, +/obj/item/clothing/suit/hazardvest{ + desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; + name = "emergency lifejacket" + }, +/obj/item/clothing/suit/hazardvest{ + desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; + name = "emergency lifejacket" + }, +/obj/item/clothing/suit/hazardvest{ + desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; + name = "emergency lifejacket" + }, +/obj/item/clothing/suit/hazardvest{ + desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; + name = "emergency lifejacket" + }, +/obj/item/clothing/suit/hazardvest{ + desc = "A high-visibility lifejacket complete with whistle and slot for oxygen tanks."; + name = "emergency lifejacket" + }, +/obj/item/flashlight, +/obj/item/flashlight, +/obj/item/flashlight, +/obj/item/flashlight, +/obj/item/flashlight, /turf/open/floor/plasteel, /area/gateway) "auh" = ( @@ -8506,41 +8882,6 @@ }, /turf/open/floor/plating, /area/crew_quarters/dorms) -"aun" = ( -/obj/structure/table, -/obj/effect/spawner/lootdrop/maintenance, -/obj/item/storage/box/lights/mixed, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) -"auo" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 5 - }, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) -"aup" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/grille/broken, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) -"auq" = ( -/obj/effect/spawner/lootdrop/maintenance, -/obj/structure/cable{ - icon_state = "1-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, -/turf/open/floor/plating, -/area/maintenance/department/crew_quarters/dorms) "aur" = ( /turf/open/floor/engine{ name = "Holodeck Projector Floor" @@ -8783,9 +9124,6 @@ /obj/structure/sign/warning/vacuum/external{ pixel_x = -32 }, -/obj/machinery/light/small{ - dir = 1 - }, /turf/open/floor/plating, /area/bridge) "auV" = ( @@ -9400,7 +9738,7 @@ /area/hallway/primary/central) "awe" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/plasteel, /area/hallway/primary/central) "awf" = ( @@ -9481,7 +9819,7 @@ /obj/machinery/light{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/stripes/corner{ dir = 4 }, @@ -9564,57 +9902,6 @@ }, /turf/open/floor/plating, /area/crew_quarters/fitness/recreation) -"awy" = ( -/obj/structure/closet/lasertag/blue, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/airalarm{ - pixel_y = 22 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel/white/corner{ - dir = 1 - }, -/area/crew_quarters/fitness/recreation) -"awz" = ( -/obj/structure/closet/lasertag/red, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/status_display/evac{ - pixel_y = 32 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel/white/corner{ - dir = 1 - }, -/area/crew_quarters/fitness/recreation) -"awA" = ( -/obj/machinery/disposal/bin, -/obj/machinery/light{ - dir = 1 - }, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Fitness Room" - }, -/obj/machinery/computer/security/telescreen/entertainment{ - pixel_y = 32 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel/white/corner{ - dir = 1 - }, -/area/crew_quarters/fitness/recreation) "awB" = ( /obj/machinery/vending/clothing, /obj/effect/turf_decal/tile/blue{ @@ -9625,7 +9912,7 @@ }, /area/crew_quarters/fitness/recreation) "awC" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/machinery/power/apc{ @@ -10025,10 +10312,6 @@ "axw" = ( /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) -"axx" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness/recreation) "axy" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -10071,7 +10354,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "axF" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel, @@ -10163,7 +10446,7 @@ /obj/structure/cable{ icon_state = "0-2" }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/carpet, /area/crew_quarters/heads/captain) "axT" = ( @@ -10373,7 +10656,7 @@ /area/crew_quarters/dorms) "ayo" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/carpet, /area/crew_quarters/dorms) "ayq" = ( @@ -10406,13 +10689,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/fitness/recreation) -"ayv" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, -/obj/structure/weightmachine/stacklifter, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness/recreation) "ayw" = ( /obj/machinery/computer/holodeck{ dir = 4 @@ -11161,7 +11437,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "aAo" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /obj/effect/turf_decal/tile/red, @@ -11857,7 +12133,7 @@ /turf/open/floor/plasteel/white/corner, /area/crew_quarters/fitness/recreation) "aBY" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /turf/open/floor/plasteel, @@ -11924,7 +12200,7 @@ /area/maintenance/department/security/brig) "aCi" = ( /obj/structure/table/wood, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18"; pixel_y = 12 }, @@ -12011,7 +12287,7 @@ /obj/structure/extinguisher_cabinet{ pixel_y = 30 }, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -13234,7 +13510,7 @@ /turf/open/floor/wood, /area/crew_quarters/heads/hop) "aEM" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-24" }, /obj/structure/cable{ @@ -13410,14 +13686,13 @@ /turf/open/floor/plating, /area/maintenance/department/cargo) "aFj" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +/obj/structure/lattice, +/obj/machinery/camera/motion{ + c_tag = "MiniSat Entrance"; + network = list("minisat") }, -/obj/machinery/door/airlock/external{ - req_access_txt = "13" - }, -/turf/open/floor/plating, -/area/maintenance/department/cargo) +/turf/open/space, +/area/space/nearstation) "aFk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/spawner/lootdrop/minor/bowler_or_that, @@ -13916,7 +14191,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/captain) "aGn" = ( -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ layer = 3.1 }, /obj/structure/window/reinforced/fulltile, @@ -15468,7 +15743,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "aKg" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-04" }, /turf/open/floor/plasteel/white/corner{ @@ -16031,7 +16306,7 @@ /obj/machinery/airalarm{ pixel_y = 22 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /turf/open/floor/plasteel, @@ -17480,13 +17755,13 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plating, /area/maintenance/department/crew_quarters/bar) "aPy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plating{ @@ -21277,7 +21552,7 @@ /area/crew_quarters/bar) "aYe" = ( /obj/structure/table/reinforced, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18"; pixel_y = 10 }, @@ -21326,7 +21601,7 @@ "aYi" = ( /obj/structure/table/reinforced, /obj/structure/disposalpipe/segment, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18"; pixel_y = 10 }, @@ -21777,9 +22052,12 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/kitchen) "aYY" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, +/obj/machinery/light/small{ + dir = 1 + }, /turf/open/floor/plasteel/dark, /area/crew_quarters/bar) "aYZ" = ( @@ -22582,11 +22860,13 @@ /turf/closed/wall, /area/maintenance/solars/starboard) "baH" = ( -/obj/structure/rack, -/obj/item/clothing/mask/gas, -/obj/item/multitool, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/airlock/external{ + name = "Bridge External Access"; + req_access_txt = "10;13" + }, /turf/open/floor/plating, -/area/maintenance/solars/starboard) +/area/ai_monitored/turret_protected/aisat_interior) "baI" = ( /obj/structure/cable{ icon_state = "0-8" @@ -22808,7 +23088,7 @@ /turf/open/floor/plasteel, /area/hydroponics) "bbd" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/green, @@ -23033,13 +23313,6 @@ /turf/open/floor/plasteel, /area/quartermaster/miningdock) "bbL" = ( -/obj/machinery/power/smes, -/obj/structure/cable{ - icon_state = "0-2" - }, -/turf/open/floor/plating, -/area/maintenance/solars/starboard) -"bbM" = ( /obj/machinery/power/terminal{ dir = 8 }, @@ -23051,17 +23324,10 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard) -"bbO" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 4 - }, -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, +"bbM" = ( +/obj/structure/rack, +/obj/item/clothing/mask/gas, +/obj/item/multitool, /turf/open/floor/plating, /area/maintenance/solars/starboard) "bbP" = ( @@ -23475,16 +23741,6 @@ /turf/open/floor/plating, /area/maintenance/department/cargo) "bcJ" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/door/airlock/engineering{ - name = "Starboard Solar Access"; - req_access_txt = "10" - }, -/turf/open/floor/plating, -/area/maintenance/solars/starboard) -"bcK" = ( /obj/structure/cable{ icon_state = "1-2" }, @@ -23493,27 +23749,35 @@ }, /turf/open/floor/plating, /area/maintenance/solars/starboard) -"bcL" = ( +"bcK" = ( /obj/structure/cable{ icon_state = "1-4" }, /turf/open/floor/plating, /area/maintenance/solars/starboard) -"bcN" = ( -/obj/machinery/power/solar_control{ - dir = 8; - id = "starboardsolar"; - name = "Starboard Solar Control" +"bcL" = ( +/obj/structure/cable{ + icon_state = "2-4" }, -/obj/structure/cable, -/turf/open/floor/plating, -/area/maintenance/solars/starboard) -"bcO" = ( /obj/structure/cable{ icon_state = "4-8" }, /turf/open/floor/plating, /area/maintenance/solars/starboard) +"bcN" = ( +/obj/machinery/light/small{ + dir = 1 + }, +/obj/effect/decal/cleanable/cobweb, +/turf/open/floor/plating, +/area/bridge) +"bcO" = ( +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 9 + }, +/turf/open/space, +/area/space/nearstation) "bcQ" = ( /obj/structure/lattice/catwalk, /obj/structure/cable{ @@ -23874,17 +24138,17 @@ }, /area/maintenance/department/cargo) "bdR" = ( -/obj/structure/cable, -/obj/machinery/power/apc{ - dir = 8; - name = "Starboard Solar APC"; - pixel_x = -24 - }, +/obj/structure/chair/stool, +/obj/item/cigbutt/cigarbutt, /turf/open/floor/plating, /area/maintenance/solars/starboard) "bdS" = ( -/obj/structure/chair/stool, -/obj/item/cigbutt/cigarbutt, +/obj/machinery/power/solar_control{ + dir = 8; + id = "starboardsolar"; + name = "Starboard Solar Control" + }, +/obj/structure/cable, /turf/open/floor/plating, /area/maintenance/solars/starboard) "bdU" = ( @@ -24508,7 +24772,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bfp" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/button/door{ @@ -24949,7 +25213,7 @@ /turf/open/floor/plasteel, /area/crew_quarters/bar) "bgv" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-14" }, /obj/effect/turf_decal/tile/neutral{ @@ -25911,7 +26175,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "biP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/structure/disposalpipe/segment{ @@ -26030,7 +26294,7 @@ /turf/open/floor/plasteel, /area/medical/medbay/central) "bji" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/blue, @@ -26083,7 +26347,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "bjn" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/purple, @@ -27332,7 +27596,7 @@ /turf/open/floor/plasteel, /area/security/checkpoint/medical) "bmw" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05" }, /obj/effect/turf_decal/tile/blue{ @@ -27704,14 +27968,14 @@ dir = 8 }, /turf/open/floor/plasteel/white, -/area/storage/emergency/port) +/area/medical/medbay/zone3) "bny" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/machinery/firealarm{ dir = 8; pixel_x = 28 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-11" }, /obj/machinery/light/small{ @@ -27723,7 +27987,7 @@ dir = 4 }, /turf/open/floor/plasteel/white, -/area/storage/emergency/port) +/area/medical/medbay/zone3) "bnz" = ( /obj/structure/table, /obj/item/folder/white, @@ -27962,7 +28226,7 @@ /turf/open/floor/engine, /area/science/explab) "bnZ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/neutral{ @@ -28330,7 +28594,7 @@ /turf/open/floor/plasteel/dark, /area/hallway/primary/aft) "boT" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/bot, @@ -28357,7 +28621,7 @@ dir = 1 }, /obj/machinery/light, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/neutral{ @@ -30326,7 +30590,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bsW" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -30715,7 +30979,7 @@ /turf/open/floor/grass, /area/medical/genetics) "btU" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/blue, @@ -30980,7 +31244,7 @@ /area/science/robotics/lab) "buw" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 10 }, /obj/effect/turf_decal/tile/purple{ @@ -30999,7 +31263,7 @@ /turf/open/floor/plasteel/dark, /area/science/explab) "buy" = ( -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 10 }, /obj/effect/turf_decal/tile/purple, @@ -31038,7 +31302,7 @@ /turf/open/floor/plasteel, /area/science/explab) "buD" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-11" }, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -32562,15 +32826,10 @@ /obj/machinery/light/small{ dir = 1 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, /turf/open/floor/plasteel/white, /area/hallway/secondary/entry) "bxZ" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 4 - }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/white, /area/hallway/secondary/entry) "bya" = ( @@ -33011,7 +33270,7 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants/photosynthetic{ +/obj/item/kirbyplants/photosynthetic{ pixel_y = 4 }, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -33403,7 +33662,7 @@ /turf/open/floor/plasteel/white, /area/medical/genetics) "bzM" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/green, @@ -33843,9 +34102,8 @@ /obj/structure/transit_tube/curved/flipped{ dir = 4 }, -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/hallway/secondary/entry) +/turf/open/space/basic, +/area/space/nearstation) "bAJ" = ( /obj/structure/transit_tube/horizontal, /obj/structure/window/reinforced/fulltile, @@ -34198,7 +34456,7 @@ /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/hor) "bBu" = ( -/obj/item/twohanded/required/kirbyplants/dead, +/obj/item/kirbyplants/dead, /obj/structure/disposalpipe/segment{ dir = 10 }, @@ -34295,7 +34553,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bBB" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-20"; pixel_y = 3 }, @@ -34515,6 +34773,7 @@ /area/science/xenobiology) "bBV" = ( /obj/structure/transit_tube/curved, +/obj/structure/lattice/catwalk, /turf/open/space, /area/space/nearstation) "bBW" = ( @@ -35994,7 +36253,7 @@ /turf/open/floor/plasteel/white, /area/crew_quarters/heads/cmo) "bEH" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/machinery/light_switch{ @@ -38135,10 +38394,12 @@ /turf/open/floor/plasteel/dark, /area/chapel/dock) "bIY" = ( -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 +/obj/structure/window/reinforced{ + dir = 8; + layer = 2.9 }, -/area/hallway/secondary/entry) +/turf/open/space/basic, +/area/space) "bIZ" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -38240,7 +38501,7 @@ /turf/open/floor/plasteel/dark, /area/maintenance/department/engine) "bJi" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plating, @@ -38686,7 +38947,6 @@ /area/chapel/dock) "bKe" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/structure/closet/emcloset, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -39182,9 +39442,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/dock) "bLp" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ - dir = 8 - }, +/obj/machinery/atmospherics/pipe/manifold4w/supply/hidden, /turf/open/floor/plasteel/dark, /area/chapel/dock) "bLq" = ( @@ -39207,20 +39465,17 @@ /turf/open/floor/plasteel/dark, /area/chapel/dock) "bLr" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 9 + }, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, /area/chapel/dock) "bLs" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/light, -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 - }, -/area/hallway/secondary/entry) +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/chapel/dock) "bLt" = ( /obj/effect/decal/cleanable/oil{ icon_state = "floor6" @@ -39422,7 +39677,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bLT" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /obj/machinery/airalarm{ @@ -39636,12 +39891,6 @@ /area/science/mixing) "bMp" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 1 - }, -/obj/machinery/door/airlock/external{ - req_access_txt = "8" - }, /turf/open/floor/plating, /area/science/mixing) "bMq" = ( @@ -39693,6 +39942,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 4 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/tile/neutral{ dir = 8 }, @@ -39725,24 +39975,24 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 8 }, -/obj/machinery/light/small{ - dir = 4 - }, -/obj/structure/chair{ - dir = 1 - }, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, /area/chapel/dock) "bMy" = ( -/obj/structure/window/reinforced{ - dir = 8; - layer = 2.9 +/obj/effect/turf_decal/tile/neutral{ + dir = 1 }, -/obj/structure/lattice, -/turf/open/space, -/area/space/nearstation) +/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/supply/hidden, +/turf/open/floor/plasteel/dark, +/area/chapel/dock) "bMA" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/engine, @@ -40120,11 +40370,10 @@ /turf/open/floor/engine/vacuum, /area/science/mixing) "bNq" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 6 +/obj/machinery/atmospherics/components/unary/outlet_injector/on{ + dir = 1 }, -/turf/open/space, +/turf/open/floor/plating/airless, /area/science/mixing) "bNr" = ( /obj/structure/window/reinforced{ @@ -40164,12 +40413,12 @@ /turf/open/floor/plasteel/dark, /area/chapel/dock) "bNu" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/chapel/dock) "bNv" = ( @@ -40328,7 +40577,7 @@ /turf/open/floor/plasteel/white, /area/medical/virology) "bNR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green, @@ -40560,10 +40809,11 @@ /turf/open/floor/engine/vacuum, /area/science/mixing) "bOu" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/on{ - dir = 1 +/obj/structure/lattice/catwalk, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 6 }, -/turf/open/floor/plating/airless, +/turf/open/space, /area/science/mixing) "bOv" = ( /obj/structure/window/reinforced{ @@ -40589,6 +40839,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/chapel/dock) "bOy" = ( @@ -40602,6 +40853,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, /turf/open/floor/plasteel/dark, /area/chapel/dock) "bOz" = ( @@ -40847,12 +41101,15 @@ /turf/open/floor/engine/n2o, /area/engine/atmos) "bPl" = ( -/obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ - dir = 9 +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 }, -/turf/open/space, -/area/space/nearstation) +/obj/machinery/door/airlock/external{ + req_access_txt = "8" + }, +/turf/open/floor/plating, +/area/science/mixing) "bPn" = ( /obj/machinery/door/airlock/grunge{ name = "Chapel" @@ -40870,6 +41127,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/chapel/dock) "bPo" = ( @@ -40886,6 +41144,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plasteel/dark, /area/chapel/dock) "bPp" = ( @@ -41182,6 +41441,7 @@ icon_state = "1-2" }, /obj/effect/turf_decal/sand, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, /area/chapel/asteroid/monastery) "bQg" = ( @@ -42445,7 +42705,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "bSP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-02" }, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -42985,7 +43245,7 @@ /obj/structure/closet/firecloset, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, -/area/engine/atmos) +/area/engine/break_room) "bTR" = ( /obj/machinery/atmospherics/pipe/simple/yellow/visible{ dir = 4 @@ -43174,7 +43434,7 @@ /obj/effect/turf_decal/delivery, /obj/structure/closet/firecloset, /turf/open/floor/plasteel, -/area/engine/atmos) +/area/engine/break_room) "bUp" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plasteel, @@ -43567,7 +43827,7 @@ /obj/effect/turf_decal/delivery, /obj/machinery/atmospherics/pipe/manifold4w/scrubbers, /turf/open/floor/plasteel, -/area/engine/atmos) +/area/engine/break_room) "bVd" = ( /obj/machinery/door/airlock/atmos{ name = "Atmospherics"; @@ -44378,14 +44638,14 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/chapel/main/monastery) "bWX" = ( -/obj/machinery/door/airlock/grunge{ - name = "Chapel" - }, -/turf/open/floor/plasteel/dark, -/area/chapel/main/monastery) +/obj/effect/turf_decal/sand, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/plasteel, +/area/chapel/asteroid/monastery) "bWZ" = ( /turf/open/floor/plating{ icon_state = "panelscorched" @@ -44715,6 +44975,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel/dark, /area/chapel/main/monastery) "bXJ" = ( @@ -44734,10 +44995,6 @@ /turf/open/floor/plating, /area/chapel/asteroid/monastery) "bXN" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external, /turf/open/floor/plating, /area/chapel/asteroid/monastery) "bXS" = ( @@ -44964,7 +45221,7 @@ /turf/open/floor/plating, /area/maintenance/department/engine) "bYI" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_y = 3 }, @@ -45420,6 +45677,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/carpet, /area/chapel/main/monastery) "bZo" = ( @@ -45643,12 +45901,21 @@ /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/incinerator_input{ dir = 8 }, +/obj/machinery/air_sensor/atmos/incinerator_tank{ + pixel_x = 32; + pixel_y = -32 + }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) "bZV" = ( -/obj/structure/sign/warning/fire, -/turf/closed/wall/r_wall, -/area/maintenance/disposal/incinerator) +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/external{ + req_access_txt = "13" + }, +/turf/open/floor/plating, +/area/maintenance/department/cargo) "bZY" = ( /turf/closed/wall, /area/chapel/office) @@ -45731,7 +45998,7 @@ /area/engine/engineering) "caw" = ( /obj/structure/table, -/obj/item/twohanded/rcl/pre_loaded, +/obj/item/rcl/pre_loaded, /turf/open/floor/plasteel, /area/engine/engineering) "cax" = ( @@ -45866,13 +46133,15 @@ icon_state = "4-8" }, /obj/machinery/igniter/incinerator_atmos, -/obj/machinery/air_sensor/atmos/incinerator_tank{ - pixel_x = 32; - pixel_y = -32 - }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) "caP" = ( +/obj/structure/cable/yellow{ + icon_state = "4-8" + }, +/turf/open/floor/engine, +/area/maintenance/disposal/incinerator) +"caQ" = ( /obj/structure/cable/yellow{ icon_state = "0-8" }, @@ -45884,13 +46153,9 @@ dir = 8; luminosity = 2 }, -/obj/machinery/camera{ - c_tag = "Turbine Chamber"; - network = list("turbine") - }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) -"caQ" = ( +"caR" = ( /obj/structure/cable/yellow{ icon_state = "0-8" }, @@ -45900,10 +46165,6 @@ }, /turf/open/floor/engine, /area/maintenance/disposal/incinerator) -"caR" = ( -/obj/machinery/door/poddoor/incinerator_atmos_main, -/turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) "caS" = ( /turf/closed/wall, /area/chapel/asteroid/monastery) @@ -46174,6 +46435,7 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/carpet, /area/chapel/main/monastery) "cbO" = ( @@ -46181,6 +46443,7 @@ /obj/item/reagent_containers/food/drinks/trophy{ pixel_y = 8 }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/carpet, /area/chapel/main/monastery) "cbP" = ( @@ -46326,9 +46589,9 @@ /turf/open/floor/plasteel/dark, /area/maintenance/disposal/incinerator) "ccs" = ( -/obj/machinery/door/poddoor/incinerator_atmos_aux, -/turf/open/floor/engine/vacuum, -/area/maintenance/disposal/incinerator) +/obj/structure/lattice, +/turf/closed/wall, +/area/maintenance/department/cargo) "ccu" = ( /obj/structure/flora/ausbushes/leafybush, /turf/open/floor/plating/asteroid, @@ -46337,15 +46600,15 @@ /obj/structure/cable{ icon_state = "1-8" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 10 +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 4 }, /turf/open/floor/carpet, /area/chapel/main/monastery) "ccF" = ( /obj/effect/landmark/start/chaplain, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 +/obj/machinery/atmospherics/pipe/manifold/supply/hidden{ + dir = 8 }, /turf/open/floor/carpet, /area/chapel/main/monastery) @@ -46501,13 +46764,6 @@ /turf/open/floor/plating, /area/maintenance/disposal/incinerator) "cdl" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external{ - name = "Atmospherics External Access"; - req_access_txt = "24" - }, /turf/open/floor/plating, /area/maintenance/disposal/incinerator) "cdm" = ( @@ -46864,7 +47120,7 @@ /turf/open/floor/plasteel/dark, /area/chapel/main/monastery) "ceK" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /turf/open/floor/plasteel/dark, @@ -46904,7 +47160,7 @@ "ceT" = ( /obj/effect/turf_decal/stripes/line, /obj/structure/closet/emcloset, -/turf/open/floor/plating/airless, +/turf/open/floor/plating, /area/engine/engineering) "ceU" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ @@ -47043,6 +47299,9 @@ /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) "cfu" = ( @@ -47161,14 +47420,12 @@ /turf/open/floor/plasteel/dark, /area/engine/engineering) "cfQ" = ( -/obj/structure/chair{ - dir = 8 +/obj/machinery/power/smes, +/obj/structure/cable{ + icon_state = "0-2" }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 9 - }, -/turf/open/floor/plasteel/dark, -/area/engine/engineering) +/turf/open/floor/plating, +/area/maintenance/solars/starboard) "cfS" = ( /obj/structure/table/reinforced, /obj/item/tank/internals/emergency_oxygen/engi, @@ -47294,14 +47551,12 @@ /turf/open/floor/plating, /area/engine/engineering) "cgs" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper, -/obj/machinery/door/airlock/external{ - name = "Engineering External Access"; - req_access_txt = "61" - }, /obj/structure/cable{ icon_state = "1-2" }, +/obj/machinery/light/small{ + dir = 8 + }, /turf/open/floor/plating, /area/engine/engineering) "cgu" = ( @@ -47393,9 +47648,6 @@ /turf/open/floor/plating/airless, /area/space/nearstation) "cgQ" = ( -/obj/machinery/light/small{ - dir = 8 - }, /obj/structure/sign/warning/vacuum/external{ pixel_x = -32 }, @@ -48021,7 +48273,7 @@ /turf/open/floor/plating, /area/maintenance/department/chapel/monastery) "cjP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/item/radio/intercom{ @@ -49168,7 +49420,7 @@ /obj/structure/lattice, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/space/basic, -/area/ai_monitored/turret_protected/AIsatextAS) +/area/ai_monitored/turret_protected/AIsatextAP) "cnJ" = ( /obj/effect/turf_decal/delivery, /obj/machinery/vending/wardrobe/sec_wardrobe, @@ -49777,7 +50029,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "cpT" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ dir = 8 @@ -49785,7 +50037,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/central) "cpU" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ dir = 8 @@ -49982,7 +50234,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/aft) "cqE" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-18"; layer = 3 }, @@ -50035,9 +50287,11 @@ /turf/open/floor/plasteel, /area/crew_quarters/heads/chief) "cqW" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/closed/mineral, -/area/chapel/asteroid/monastery) +/obj/structure/chair, +/turf/open/floor/plasteel/white{ + heat_capacity = 1e+006 + }, +/area/chapel/dock) "cqX" = ( /obj/structure/disposalpipe/segment, /obj/structure/lattice, @@ -50147,6 +50401,15 @@ /turf/open/floor/plating, /area/maintenance/department/engine) "crB" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/light/small{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/department/engine) +"crC" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 8 }, @@ -50158,15 +50421,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/engine) -"crC" = ( -/obj/machinery/light/small{ - dir = 1 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plating, -/area/maintenance/department/engine) "crD" = ( /obj/structure/table/wood/fancy, /obj/item/storage/box/bodybags, @@ -50634,7 +50888,7 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/dark, @@ -50726,7 +50980,7 @@ /obj/machinery/atmospherics/pipe/manifold/supply/hidden{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/dark, @@ -51277,7 +51531,7 @@ icon_state = "1-4" }, /obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/dark, @@ -51536,7 +51790,7 @@ /turf/open/floor/plating, /area/maintenance/department/chapel/monastery) "cwr" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/structure/cable{ @@ -51981,7 +52235,7 @@ /turf/open/floor/plasteel/dark, /area/library) "cyQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/camera{ @@ -51994,7 +52248,7 @@ /turf/open/floor/plasteel/dark, /area/library) "cyR" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/dark, @@ -52246,7 +52500,7 @@ /area/library) "cAs" = ( /obj/structure/table/wood, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05"; pixel_y = 10 }, @@ -52624,7 +52878,7 @@ /turf/open/floor/plasteel/dark, /area/security/main) "cCT" = ( -/obj/machinery/rnd/production/protolathe/department/cargo, +/obj/machinery/rnd/production/techfab/department/cargo, /turf/open/floor/plasteel, /area/quartermaster/storage) "cCU" = ( @@ -53009,15 +53263,16 @@ }, /area/hallway/secondary/exit/departure_lounge) "dpb" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_y = 3 }, /turf/open/floor/plasteel/dark, /area/chapel/office) "dpc" = ( -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/turf/open/floor/carpet, +/area/chapel/main/monastery) "dps" = ( /obj/machinery/status_display/ai, /turf/closed/wall, @@ -53292,13 +53547,15 @@ /turf/open/floor/plating, /area/maintenance/department/engine) "dWp" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/obj/machinery/door/airlock/external{ + name = "Engineering External Access"; + req_access_txt = "61" }, /obj/structure/cable{ icon_state = "1-2" }, -/turf/open/floor/plasteel/dark, +/turf/open/floor/plating, /area/engine/engineering) "dYe" = ( /obj/structure/cable{ @@ -53381,13 +53638,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/engine) -"eit" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/lattice, -/turf/open/space/basic, -/area/space/nearstation) "eiV" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 4 @@ -53405,10 +53655,6 @@ /obj/structure/chair/office/dark, /turf/open/floor/wood, /area/lawoffice) -"epg" = ( -/obj/structure/lattice, -/turf/open/space, -/area/space) "epj" = ( /obj/machinery/cryopod{ dir = 8 @@ -53682,14 +53928,11 @@ /obj/effect/turf_decal/arrows{ dir = 8 }, +/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ + dir = 4 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"eVT" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on{ - dir = 1 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "eWi" = ( /obj/structure/cable{ icon_state = "0-4" @@ -53775,6 +54018,20 @@ }, /turf/open/floor/plasteel, /area/construction/mining/aux_base) +"fgS" = ( +/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 + }, +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/plasteel/dark, +/area/maintenance/department/engine) "fhM" = ( /obj/item/storage/secure/safe{ pixel_x = -22 @@ -54075,6 +54332,9 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"fRr" = ( +/turf/open/floor/engine/vacuum, +/area/maintenance/disposal/incinerator) "fRs" = ( /turf/closed/wall, /area/crew_quarters/heads/hor) @@ -54124,15 +54384,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/kitchen) -"gcj" = ( -/obj/machinery/vending/kink, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/turf/open/floor/plasteel/white/corner{ - dir = 1 - }, -/area/crew_quarters/fitness/recreation) "gdJ" = ( /obj/structure/table/glass, /obj/item/folder/blue, @@ -54230,7 +54481,7 @@ /turf/open/floor/plating, /area/maintenance/department/security/brig) "gkR" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/structure/extinguisher_cabinet{ pixel_y = 30 }, @@ -54296,6 +54547,16 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) +"gmZ" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/external{ + name = "Atmospherics External Access"; + req_access_txt = "24" + }, +/turf/open/floor/plating, +/area/maintenance/disposal/incinerator) "gna" = ( /turf/open/floor/plasteel/stairs/medium, /area/maintenance/department/crew_quarters/dorms) @@ -54529,7 +54790,7 @@ /area/science/xenobiology) "gKz" = ( /obj/structure/table/wood, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22"; pixel_y = 8 }, @@ -54613,14 +54874,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/cargo) -"gTy" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/lattice, -/obj/structure/lattice, -/turf/open/space/basic, -/area/space/nearstation) "gUb" = ( /obj/structure/chair/office/dark{ dir = 4 @@ -54664,6 +54917,10 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/engineering) +"hbl" = ( +/obj/machinery/door/poddoor/incinerator_atmos_main, +/turf/open/floor/engine/vacuum, +/area/space) "heC" = ( /obj/machinery/power/apc/highcap/five_k{ dir = 8; @@ -54871,14 +55128,6 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port) -"hCb" = ( -/obj/machinery/door/airlock/public/glass{ - name = "Monastery Transit" - }, -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 - }, -/area/hallway/secondary/entry) "hDG" = ( /obj/machinery/door/airlock/engineering{ name = "Auxillary Base Construction"; @@ -55019,14 +55268,15 @@ /turf/open/floor/engine, /area/engine/engineering) "hSM" = ( -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 +/obj/structure/cable{ + icon_state = "4-8" }, -/obj/machinery/door/airlock/external{ - req_access_txt = "13" +/obj/machinery/door/airlock/engineering{ + name = "Starboard Solar Access"; + req_access_txt = "10" }, /turf/open/floor/plating, -/area/maintenance/department/science) +/area/maintenance/solars/starboard) "hTl" = ( /obj/structure/sink{ dir = 4; @@ -55135,6 +55385,13 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/engine, /area/engine/engineering) +"igB" = ( +/obj/machinery/camera{ + c_tag = "Turbine Chamber"; + network = list("turbine") + }, +/turf/open/floor/engine, +/area/maintenance/disposal/incinerator) "igE" = ( /obj/structure/table/reinforced, /obj/machinery/button/door{ @@ -55336,11 +55593,11 @@ /turf/open/floor/plating, /area/crew_quarters/dorms) "izF" = ( -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 +/obj/structure/closet/emcloset, +/turf/open/floor/plasteel/white{ + heat_capacity = 1e+006 }, -/area/maintenance/department/science) +/area/chapel/dock) "iAx" = ( /obj/structure/cable{ icon_state = "4-8" @@ -55407,7 +55664,7 @@ dir = 9 }, /turf/open/floor/plasteel/white, -/area/storage/emergency/port) +/area/medical/medbay/zone3) "iJi" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 @@ -55667,7 +55924,7 @@ /obj/structure/sign/plaques/deempisi{ pixel_y = 28 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_y = 3 }, @@ -56067,10 +56324,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/aft) -"koE" = ( -/obj/structure/lattice, -/turf/open/space/basic, -/area/space) "kpK" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 5 @@ -56125,7 +56378,7 @@ /turf/open/floor/carpet, /area/lawoffice) "kxs" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plating, @@ -56255,12 +56508,7 @@ /turf/open/floor/plating, /area/hallway/secondary/entry) "kIc" = ( -/obj/machinery/door/airlock/public/glass{ - name = "Monastery Transit" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, +/obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plasteel/white{ heat_capacity = 1e+006 }, @@ -56405,12 +56653,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, /area/engine/engineering) -"kVy" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 9 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "kWQ" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible, /obj/structure/cable/yellow{ @@ -56436,7 +56678,7 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/dark, @@ -56878,11 +57120,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plasteel, /area/engine/engineering) -"mgU" = ( -/obj/effect/landmark/carpspawn, -/obj/structure/lattice, -/turf/open/space/basic, -/area/space) "mhl" = ( /obj/machinery/power/emitter, /obj/machinery/light{ @@ -57029,6 +57266,15 @@ }, /turf/open/floor/plasteel, /area/science/xenobiology) +"mvm" = ( +/obj/structure/cable, +/obj/machinery/power/apc{ + dir = 8; + name = "Starboard Solar APC"; + pixel_x = -24 + }, +/turf/open/floor/plating, +/area/maintenance/solars/starboard) "mwg" = ( /obj/structure/closet/crate{ icon_state = "crateopen" @@ -57185,14 +57431,6 @@ /obj/machinery/space_heater, /turf/open/floor/plating, /area/maintenance/department/science) -"mSY" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 - }, -/area/chapel/dock) "mTS" = ( /obj/structure/cable{ icon_state = "4-8" @@ -57202,12 +57440,6 @@ }, /turf/open/floor/plasteel/dark, /area/science/xenobiology) -"mVD" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "mVM" = ( /turf/open/floor/plating/airless, /area/space/nearstation) @@ -57233,6 +57465,10 @@ /obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"nbu" = ( +/obj/structure/sign/warning/fire, +/turf/closed/wall/r_wall, +/area/space) "ncm" = ( /obj/machinery/atmospherics/pipe/simple/cyan/visible{ dir = 4 @@ -57289,12 +57525,6 @@ /obj/item/chair/stool, /turf/open/floor/carpet, /area/maintenance/department/crew_quarters/dorms) -"nho" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "nih" = ( /obj/structure/closet, /obj/effect/spawner/lootdrop/costume, @@ -57438,7 +57668,7 @@ /turf/open/floor/plasteel/white/corner, /area/hallway/primary/central) "nyO" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light/small{ @@ -57450,10 +57680,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 6 }, -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 - }, +/turf/open/floor/plating, /area/maintenance/department/science) "nAs" = ( /obj/machinery/door/airlock/engineering/glass{ @@ -57616,7 +57843,7 @@ /obj/structure/disposalpipe/trunk{ dir = 8 }, -/turf/open/floor/plating, +/turf/open/floor/plating/airless, /area/space/nearstation) "nOY" = ( /obj/effect/turf_decal/stripes/line{ @@ -57678,7 +57905,7 @@ /turf/open/floor/engine, /area/engine/supermatter) "nVU" = ( -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/plating, /area/maintenance/department/engine) "nWP" = ( @@ -57719,10 +57946,7 @@ /obj/structure/table, /obj/item/paper_bin, /obj/item/pen, -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 - }, +/turf/open/floor/plating, /area/maintenance/department/science) "odM" = ( /obj/effect/landmark/barthpot, @@ -57821,6 +58045,10 @@ }, /turf/open/floor/plasteel/dark, /area/tcommsat/computer) +"ore" = ( +/obj/structure/closet/firecloset, +/turf/open/floor/plating, +/area/engine/engineering) "ost" = ( /obj/structure/table/glass, /obj/item/paper_bin{ @@ -57932,13 +58160,6 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/effect/mapping_helpers/airlock/cyclelink_helper{ - dir = 8 - }, -/obj/machinery/door/airlock/external{ - name = "Solar Maintenance"; - req_access_txt = "10; 13" - }, /turf/open/floor/plating, /area/maintenance/solars/starboard) "oDP" = ( @@ -58007,6 +58228,12 @@ /obj/item/stack/sheet/mineral/wood, /turf/open/floor/plasteel, /area/maintenance/department/engine) +"oGw" = ( +/obj/item/clothing/mask/gas, +/turf/open/floor/plating{ + icon_state = "platingdmg3" + }, +/area/maintenance/disposal/incinerator) "oHa" = ( /obj/machinery/power/emitter/anchored{ dir = 8; @@ -58380,17 +58607,6 @@ }, /turf/open/floor/plasteel/white/corner, /area/hallway/secondary/exit/departure_lounge) -"ppY" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/door/airlock/public/glass{ - name = "Monastery Transit" - }, -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 - }, -/area/chapel/dock) "prQ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ dir = 4 @@ -58456,6 +58672,10 @@ "pyw" = ( /turf/open/space/basic, /area/hallway/secondary/entry) +"pzF" = ( +/mob/living/simple_animal/opossum, +/turf/open/floor/wood, +/area/maintenance/department/crew_quarters/dorms) "pBD" = ( /obj/structure/cable{ icon_state = "0-8" @@ -58663,7 +58883,7 @@ /turf/open/floor/plasteel/white, /area/science/xenobiology) "pXT" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /obj/machinery/power/apc{ areastring = "/area/lawoffice"; dir = 8; @@ -58678,7 +58898,7 @@ /turf/closed/wall/r_wall, /area/engine/engineering) "pYw" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-03" }, /obj/structure/extinguisher_cabinet{ @@ -59048,6 +59268,10 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) +"qVk" = ( +/obj/machinery/door/poddoor/incinerator_atmos_aux, +/turf/open/space/basic, +/area/maintenance/disposal/incinerator) "qVP" = ( /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -59255,14 +59479,13 @@ /turf/open/floor/plating/airless, /area/space/nearstation) "ros" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ +/obj/machinery/light/small{ dir = 4 }, -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 +/turf/open/floor/plasteel/white{ + heat_capacity = 1e+006 }, -/area/maintenance/department/science) +/area/chapel/dock) "rrb" = ( /obj/structure/cable{ icon_state = "1-2" @@ -59357,6 +59580,13 @@ icon_state = "panelscorched" }, /area/maintenance/department/engine) +"rzF" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/external, +/turf/open/floor/plating, +/area/chapel/asteroid/monastery) "rBh" = ( /obj/structure/mopbucket, /obj/item/mop, @@ -59861,7 +60091,6 @@ /turf/open/floor/plasteel/dark, /area/chapel/office) "tap" = ( -/obj/structure/reagent_dispensers/keg/aphro, /turf/open/floor/wood, /area/maintenance/department/crew_quarters/dorms) "taA" = ( @@ -59875,22 +60104,6 @@ }, /turf/open/floor/plasteel, /area/science/xenobiology) -"tbF" = ( -/obj/structure/window/reinforced, -/obj/structure/window/reinforced{ - dir = 4 - }, -/obj/structure/lattice, -/obj/structure/lattice, -/turf/open/space/basic, -/area/space/nearstation) -"tbY" = ( -/obj/structure/closet/emcloset, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 6 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "tcY" = ( /obj/structure/cable{ icon_state = "4-8" @@ -60406,10 +60619,7 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 9 }, -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 - }, +/turf/open/floor/plating, /area/maintenance/department/science) "uos" = ( /obj/machinery/computer/camera_advanced/base_construction, @@ -60509,10 +60719,6 @@ /obj/machinery/field/generator, /turf/open/floor/plating, /area/maintenance/department/engine) -"uxI" = ( -/obj/machinery/light, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "uxP" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -60695,12 +60901,16 @@ /turf/open/floor/plasteel, /area/science/xenobiology) "uXH" = ( -/obj/structure/cable{ - icon_state = "2-4" - }, /obj/structure/cable{ icon_state = "4-8" }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, +/obj/machinery/door/airlock/external{ + name = "Solar Maintenance"; + req_access_txt = "10; 13" + }, /turf/open/floor/plating, /area/maintenance/solars/starboard) "uZb" = ( @@ -60717,10 +60927,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/engine) -"vaB" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "vco" = ( /obj/machinery/light/small{ dir = 8 @@ -60846,13 +61052,6 @@ /obj/structure/lattice, /turf/open/space/basic, /area/space/nearstation) -"vpz" = ( -/obj/structure/girder, -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 - }, -/area/maintenance/department/science) "vsk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 @@ -60931,12 +61130,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"vxZ" = ( -/obj/machinery/light{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "vzz" = ( /obj/machinery/door/firedoor, /obj/machinery/door/airlock/public/glass{ @@ -61015,6 +61208,15 @@ }, /turf/open/floor/plating, /area/maintenance/department/engine) +"vHf" = ( +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/obj/machinery/door/airlock/external{ + req_access_txt = "13" + }, +/turf/open/floor/plating, +/area/maintenance/department/science) "vIc" = ( /obj/structure/cable{ icon_state = "2-4" @@ -61373,14 +61575,6 @@ }, /turf/open/floor/plating, /area/maintenance/department/crew_quarters/bar) -"wDe" = ( -/obj/machinery/door/airlock/public/glass{ - name = "Monastery Transit" - }, -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 - }, -/area/chapel/dock) "wDl" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, /obj/effect/turf_decal/stripes/corner, @@ -61563,10 +61757,6 @@ icon_state = "platingdmg3" }, /area/maintenance/department/science) -"wUc" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "wUf" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, @@ -61601,25 +61791,10 @@ }, /turf/open/floor/plating, /area/maintenance/department/security/brig) -"wYJ" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/light{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "wYK" = ( /obj/machinery/power/supermatter_crystal/engine, /turf/open/floor/engine, /area/engine/supermatter) -"wZs" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel/white{ - heat_capacity = 1e+006 - }, -/area/hallway/secondary/entry) "xah" = ( /obj/structure/cable{ icon_state = "1-2" @@ -61678,10 +61853,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood, /area/lawoffice) -"xeN" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plasteel/white, -/area/hallway/secondary/entry) "xgh" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -61816,10 +61987,7 @@ /area/maintenance/department/science) "xsO" = ( /obj/item/ectoplasm, -/turf/open/floor/plating{ - initial_gas_mix = "o2=0.01;n2=0.01"; - luminosity = 2 - }, +/turf/open/floor/plating, /area/maintenance/department/science) "xuv" = ( /obj/item/broken_bottle, @@ -62114,7 +62282,9 @@ /obj/structure/chair{ dir = 8 }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 9 + }, /turf/open/floor/plasteel/dark, /area/engine/engineering) @@ -75644,8 +75814,8 @@ aaa bGI bNs cfN -cqW -cqW +cfN +cfN cfN cfN bZY @@ -76157,7 +76327,7 @@ aaa aaa bGI bNs -cqW +cfN bOw cfN bOw @@ -77369,9 +77539,9 @@ rLi tlc aiu aht -aaa -azH -aaa +axB +rKr +axB aaa aaa aaa @@ -77627,9 +77797,9 @@ aiu aiu axC axB -rKr +azN axB -axC +aaa aaa aaa aaa @@ -77886,7 +78056,7 @@ axC ayz azN axB -axC +aaa aaa aaa aaa @@ -79230,26 +79400,26 @@ bIW bKc bOy bMt -bLn -bOy +bLs +bMy bPo -bQg -bQg -bQg -bQg -bQg -bQg -bQg -bQg -bQg bWX -bXJ -bZo -bZo -bZo -bZo -bZo -bZo +bWX +bWX +bWX +bWX +bWX +bWX +bWX +bWX +cek +cdx +dpc +dpc +dpc +dpc +dpc +dpc cbO ccF cdx @@ -79741,7 +79911,7 @@ aaa bGI bHM bHM -bHM +bNw bLq bMv bNw @@ -80252,11 +80422,11 @@ aaa aaa aaa aaa -koE +aht aqG bGE +cqW bKf -mSY bMw bNy bNw @@ -80508,12 +80678,12 @@ aaa aaa aaa aaa -koE -koE +aht +aht aqG bGE -bKf -mSY +izF +ros bMx bNz bHM @@ -80764,13 +80934,13 @@ aaa aaa aaa aaa -koE -koE -koE +aaa +aaa +aaa aqG bGE -wDe -ppY +bGE +bHM bHM bNA bHM @@ -81014,23 +81184,23 @@ aZx aaa aaa aaa -mZE -bVp -bVp -bVp -bVp -bVp -eit -gTy -eit -eit -tbF -aZx +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa bIY -bLs -aZx +bIY +aht +aht bNB -bMy +abI abI aby abI @@ -81271,21 +81441,21 @@ aZx aaa aaa aaa -bGI -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -bIY -wZs -aZx +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aht amC aaa aht @@ -81528,21 +81698,21 @@ aZx aaa aaa aaa -bGI -aZx -tbY -wYJ -xeN -xeN -xeN -wYJ -xeN -eVT -dpc -vxZ -bIY -nho -aZx +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa amB aht aht @@ -81722,7 +81892,7 @@ ahB ahZ aiB ajc -agy +ajM akB alq alZ @@ -81785,21 +81955,21 @@ aZx aaa aaa aaa -bGI -aZx -mVD -dpc -dpc -dpc -wUc -vaB -vaB -vaB -vaB -vaB -vaB -kVy -aZx +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aht amC aaa aht @@ -81979,7 +82149,7 @@ ahC aia aiC ajc -agy +ajM akC alr ama @@ -82042,21 +82212,21 @@ aZx aaa aaa aaa -bGI -aZx -mVD -dpc -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx -aZx +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aht +aht amB aht aht @@ -82236,7 +82406,7 @@ ahD aib aiD ajc -agy +ajM akD als amb @@ -82299,21 +82469,21 @@ aZx aaa aaa aaa -aqG -aZx -mVD -dpc -aZx -koE -koE -koE -koE -koE -koE -koE -koE -koE -koE +aaa +aaa +aaa +aaa +aaa +aht +aaa +aaa +aaa +aaa +aht +aht +aht +aht +aht amD aaa aht @@ -82327,9 +82497,9 @@ aht aaa aaa abI -aaa -bSZ -ahi +bGI +bNs +rzF bNs bOw bOw @@ -82493,7 +82663,7 @@ ahB aic aiE agy -agy +ajM akE alt amc @@ -82555,12 +82725,12 @@ bon aZx aaa aaa -koE -aqG -aZx -mVD -dpc -aZx +aaa +aaa +aaa +aaa +aaa +aht bBV bDf bDf @@ -82585,7 +82755,7 @@ abI abI abI aaa -aht +bSZ ahi bNs bNs @@ -82815,12 +82985,12 @@ aZx aZx aZx aZx -mVD -uxI +aaa +aht bAI -epg abI -koE +abI +aht abI aaa bva @@ -83073,7 +83243,7 @@ bbR bbR aZx kIc -hCb +kIc bAJ bBX bBX @@ -83123,7 +83293,7 @@ cfN cfN xYV cjm -koE +aht aaa aaa aaa @@ -83341,7 +83511,7 @@ bHP bJb bJb bJb -bJb +fgS bJb bJb bPp @@ -83381,7 +83551,7 @@ cfN qWo cjm cjm -koE +aht aaa aaa aaa @@ -84136,8 +84306,8 @@ bva bNK bva bva -koE -mgU +aht +aht kSb kSb aht @@ -84395,6 +84565,7 @@ bQl cqX xNx ctS +cFB aaa aaa aaa @@ -84404,11 +84575,10 @@ aaa aaa aaa aaa -aaa -kSb -kSb -koE -koE +fon +fon +aht +aht nKo aaa aaa @@ -87989,7 +88159,7 @@ bDi bDi bDi bIZ -mZE +aaa aaa aaa aaa @@ -88246,8 +88416,8 @@ wNq bva gMO bBX -mZE -mZE +aaa +aaa aaa aaa aaa @@ -88504,7 +88674,7 @@ bBX fdS bBX bBX -mZE +aaa aaa aaa aaa @@ -90305,7 +90475,7 @@ gnq bXk ceU eVy -cfP +bXk bXk bXk bXk @@ -90466,9 +90636,9 @@ aaa aaa aaa aaa -aaa -ahi -ahi +aoz +ahr +aoz aqG arD asO @@ -90724,8 +90894,8 @@ aaa aaa aaa aaa -aaa -aaa +cdm +cdm aqG arE arA @@ -90819,8 +90989,8 @@ cdM bXq xmE ymb -cfQ bXk +ore qWG bXk paU @@ -94567,7 +94737,7 @@ ags adX adX adX -aaa +adX aaa aaa aaa @@ -94823,8 +94993,8 @@ cnC adX adX adX -ahh -aaa +adX +alb aaa aaa aaa @@ -94839,9 +95009,9 @@ aaa aaa aaa aaa -aaa ahi atY +bcN auU atY lQQ @@ -95080,6 +95250,7 @@ bIK agt agD agR +ahh ahi aaa aaa @@ -95087,7 +95258,6 @@ aaa aaa aaa aaa -aaa aht amC aht @@ -95096,9 +95266,9 @@ aaa aaa aaa aaa -aaa ahi -atZ +baH +auV auV awc axg @@ -95337,8 +95507,8 @@ agg adX adX adX -ahh -aaa +adX +alb aaa aaa aaa @@ -95353,11 +95523,11 @@ aaa aaa aaa aaa -aaa ahi atY atY atY +atY axh axh axh @@ -95595,8 +95765,8 @@ ags adX adX adX -ahr -aht +adX +aFj aht aht aht @@ -97662,8 +97832,8 @@ aaa aaa aaa lcZ -aoA -apq +apW +apV apU aqQ arX @@ -98176,8 +98346,8 @@ aiT aiS aaa lcZ -aoC -aps +apU +apV apW aqS arZ @@ -98683,7 +98853,7 @@ iqc ngp cBr cBs -alb +tap gna klV xbJ @@ -99453,7 +99623,7 @@ aju ajt alQ mnG -alb +tap tap aiS anY @@ -99710,8 +99880,8 @@ akh alc alR amF -alb -alb +pzF +tap anm ajv ajv @@ -101609,7 +101779,7 @@ caN bZT bYw cdl -bYw +oGw bYw aaa mau @@ -101864,9 +102034,9 @@ bYw bZU caO cbF -ccs -cdm -cdm +bYw +gmZ +bYw bYw aht fon @@ -102118,13 +102288,13 @@ bVo bJP aht bYw -bYw +igB caP +fRr +qVk +cdm +cdm bYw -bYw -aaa -aaa -aaa aaa aaa aaa @@ -102374,11 +102544,11 @@ bWg bVo bJP aaa -aaa +bYw bYw caQ bYw -aaa +bYw aaa aaa aaa @@ -102547,11 +102717,11 @@ aaa aaa aaa aaa -apX -apX -apX -apX -apX +aaF +aaF +aaF +aaF +atn atn aww axv @@ -102631,10 +102801,10 @@ bJP bJP bJP abI -abI -bZV +aaa +bYw caR -bZV +bYw aaa aaa aaa @@ -102798,19 +102968,19 @@ aaa aiS cBy aiS -aiS -aiS -aiT -aiT -aiT -aiS -aiS -aiS -aiS -atm -aun -atn -awz +aaF +aaF +aaJ +aaJ +aaJ +aaF +aaF +abw +abz +abH +abl +axw +abg axw ayu azC @@ -102888,10 +103058,10 @@ aaa aaa abI aaa -aaa -aaa -aaa -aaa +abI +nbu +hbl +nbu aaa aaa aaa @@ -103053,23 +103223,23 @@ aaa aaa aaa aiT -akq -ale -ale -ale -anp -ale -ale -ale -ale -ale -ale -ale -auo -atn -awy -axw -ayu +akn +ajv +aaH +aaN +abc +abm +abm +abq +abm +abm +abA +abT +abK +abL +abM +abP +abR azC axw aBU @@ -103310,23 +103480,23 @@ aaa aaa aaa aiS -aiS -aiS -aiS -aiS -aiT -aiT -aiT -aiS -aiS -aiS -asl -aiS -aup -atn -awA -axx -ayv +akn +aaE +aaF +aaR +aaL +aaO +aaO +aaO +aaO +aaO +aaW +aaF +abb +abd +abh +abQ +abS azD aAS aat @@ -103566,22 +103736,22 @@ rmC aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa aiS -apu -ale -auq -atn -awB +akn +aaG +aaF +aaS +aaL +abn +aaO +aaO +aaO +aaO +aaW +aaY +aba +axw +abg axw axw axw @@ -103823,22 +103993,22 @@ rmC aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa aiS akn -ajv -aqZ -atn -gcj +aaF +aaF +aaS +abj +aaO +aaO +aaO +aaO +aaO +aaW +aaY +awB +abe +abi axw axw axw @@ -104080,18 +104250,18 @@ rmC aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa aiS akn +aaF +aaI +aaS +aaL +abo +aaO +abr +aaO +aaO +abB atn atn avm @@ -104337,18 +104507,18 @@ rmC aaa aaa aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aaa -aiT +aiS akn +aaF +aaK +aaS +aaL +aaO +aaO +aaO +aaO +aaO +abC atn aur aur @@ -104591,22 +104761,22 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC aaa aaa aaa -aaa -aiT +aiS akn -atn +aaF +aaI +aaS +aaL +aaO +aaO +aaO +aaO +aaO +aaW +avm aur aur aur @@ -104848,22 +105018,22 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiS -asm -atn +akn +aaF +aaF +aaT +aaL +aaO +aaO +aaO +aaO +aaO +aaW +avm aur aur aur @@ -105105,22 +105275,22 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiT akn -atn +ajv +aaF +aaU +aaL +aaO +aaO +abs +aaO +aaO +aaW +avm aur aur aur @@ -105362,21 +105532,21 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiT akn +aaQ +aaF +aaV +aaM +aaP +aaP +abt +aaP +aaP +abD atn aur aur @@ -105443,9 +105613,9 @@ bIN dAF bCV bCV -bNq +bCV bOu -aht +bNq aaa aaa aaa @@ -105619,21 +105789,21 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiS akn +sbk +aaF +aaX +aaZ +aaZ +abk +abp +abu +abx +abE atn atn avm @@ -105701,8 +105871,8 @@ bJT wOS bMp bPl -mZE -aht +bcO +aaa aaa aaa aaa @@ -105876,22 +106046,22 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiS akn -ato +ajv +aaF +aaF +aaF +aaF +aaF +aaF +aaF +aaF +abF +aaF aiS atn awC @@ -105957,9 +106127,9 @@ fBz bCV bCV bCV +bCV ahi aht -aht abI abI abI @@ -106133,21 +106303,21 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiS -asn +aaD +ale +ale +ale +ale +ale +ale +ale +abv +ale +abG ale ale avn @@ -106390,20 +106560,20 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -aaa aaa aaa aaa aiS +aiS +aiS +aiS +aiS +aiT +aiS +aiS +aiS +aiS +aiS aiT aiS aiS @@ -106647,15 +106817,15 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -106691,7 +106861,7 @@ aEl aEj aEj aht -aht +ccs aEj aEl aEl @@ -106904,15 +107074,15 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -106948,10 +107118,10 @@ aTu aUB aEl aaa -aaa -aEl +aEj aZv aUC +aUC bcH aUC aZw @@ -107161,15 +107331,15 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa aaa aaa aaa @@ -107206,8 +107376,8 @@ aGO aEj aEj aEj -aEj aTx +aFi aGO bcI aFi @@ -107418,15 +107588,6 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC aaa aaa aaa @@ -107443,10 +107604,19 @@ aaa aaa aaa aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aEl +aFi aEj -aFj -aEj -aEj +aaa aEj aEl aEj @@ -107463,12 +107633,12 @@ aUC aVE aUC aUC -aUC aZw -aFi -bcI -aFi -aFi +aEj +aEj +hSM +aEj +aEj kIo bfN aEj @@ -107501,7 +107671,7 @@ aht bwm ikB iVJ -izF +lWy typ bwm aht @@ -107675,15 +107845,6 @@ rmC rmC rmC rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC -rmC aaa aaa aaa @@ -107700,9 +107861,18 @@ aaa aaa aaa aaa -ahi -ahi -ahi +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aaa +aEj +bZV +aEj aaa aaa aaa @@ -107722,9 +107892,9 @@ aEj aEj aYC baG -baG +cfQ bcJ -baG +mvm baG aEj aEj @@ -107957,9 +108127,9 @@ aaa aaa aaa aaa -aaa -aaa -aaa +ahi +ahi +ahi aaa aaa aaa @@ -108011,7 +108181,7 @@ bwm svN bIQ uek -izF +lWy bwm qnT lJr @@ -108266,9 +108436,9 @@ dMO lWy rxQ lWy -ros -izF -izF +bIQ +lWy +lWy mES lWy lWy @@ -108493,9 +108663,9 @@ aFi aFi aYD baG -baH +rWE uXH -bcN +rWE baG eZA tDn @@ -108525,7 +108695,7 @@ bwm nzD uoj bwm -izF +lWy bwm dMI lWy @@ -108751,7 +108921,7 @@ aXC aYE baG rWE -bbO +oCX rWE baG vzT @@ -108779,7 +108949,7 @@ bkF bwm bwm bwm -ros +bIQ bwm bwm bwm @@ -109008,7 +109178,7 @@ aXC aYF baG sut -bcO +oCX rWE baG dsv @@ -109036,8 +109206,8 @@ bkF qIO jXA bwm -ros -vpz +bIQ +hXt bwm aht bwm @@ -109265,7 +109435,7 @@ aEl aEl baG rWE -oCX +atZ rWE baG aEj @@ -109771,7 +109941,7 @@ aaa aaa aaa aaa -mZE +aaa aaa aaa aaa @@ -112373,7 +112543,7 @@ qcH bnd nNN bwm -hSM +lWy bwm bwm aaa @@ -112629,10 +112799,10 @@ riW jtf bnd aht -ahi -ahi -ahi -aht +bwm +vHf +bwm +aaa aht aby aht @@ -112886,9 +113056,9 @@ cOp lGS bnd aaa -aaa -aaa -aaa +ahi +ahi +ahi aht aaa aed diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm index 37576ef011..45e6e4dee0 100644 --- a/_maps/map_files/Snaxi/Snaxi.dmm +++ b/_maps/map_files/Snaxi/Snaxi.dmm @@ -1,4 +1,317 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aaa" = ( +/obj/effect/landmark/event_spawn, +/mob/living/simple_animal/hostile/retaliate/goat{ + name = "Pete" + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/kitchen) +"aab" = ( +/obj/structure/curtain, +/obj/machinery/shower{ + pixel_y = 20 + }, +/turf/open/floor/plasteel/white, +/area/crew_quarters/dorms) +"aac" = ( +/obj/machinery/shower{ + pixel_y = 20 + }, +/obj/structure/curtain, +/turf/open/floor/plasteel/white, +/area/crew_quarters/dorms) +"aad" = ( +/obj/item/radio/intercom{ + name = "Station Intercom (General)"; + pixel_x = 30 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) +"aae" = ( +/obj/machinery/button/door{ + id = "Bath1"; + name = "Door Bolt Control"; + normaldoorcontrol = 1; + pixel_x = 24; + pixel_y = -5; + specialfunctions = 4 + }, +/obj/machinery/light/small{ + dir = 8 + }, +/obj/structure/toilet/secret/low_loot{ + pixel_y = 14 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) +"aaf" = ( +/obj/machinery/light, +/obj/structure/urinal{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/freezer, +/area/crew_quarters/dorms) +"aag" = ( +/obj/structure/table/reinforced, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" + }, +/mob/living/carbon/monkey/punpun, +/turf/open/floor/plasteel/grimy, +/area/crew_quarters/bar) +"aah" = ( +/obj/structure/table/reinforced, +/obj/item/clothing/glasses/meson{ + pixel_y = 4 + }, +/obj/item/cartridge/atmos, +/obj/item/cartridge/engineering{ + pixel_x = -3; + pixel_y = 2 + }, +/obj/item/cartridge/engineering{ + pixel_x = -3; + pixel_y = 2 + }, +/obj/item/cartridge/engineering{ + pixel_x = -3; + pixel_y = 2 + }, +/obj/item/radio/intercom{ + dir = 4; + name = "Station Intercom (General)"; + pixel_x = 27 + }, +/obj/machinery/keycard_auth{ + pixel_y = -28 + }, +/mob/living/simple_animal/parrot/Poly, +/turf/open/floor/plasteel, +/area/crew_quarters/heads/chief) +"aai" = ( +/obj/effect/turf_decal/bot, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/mob/living/simple_animal/sloth/paperwork, +/turf/open/floor/plasteel, +/area/quartermaster/storage) +"aaj" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/light{ + dir = 4 + }, +/obj/effect/turf_decal/bot, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=8"; + dir = 8; + freq = 1400; + location = "QM #1" + }, +/obj/machinery/power/apc{ + areastring = "/area/maintenance/starboard"; + dir = 4; + name = "Starboard Maintenance APC"; + pixel_x = 26 + }, +/mob/living/simple_animal/bot/mulebot{ + beacon_freq = 1400; + home_destination = "QM #1"; + suffix = "#1" + }, +/turf/open/floor/pod/dark, +/area/maintenance/starboard) +"aak" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/navbeacon{ + codes_txt = "delivery;dir=8"; + dir = 8; + freq = 1400; + location = "QM #2" + }, +/obj/machinery/camera{ + c_tag = "Cargo Garage"; + dir = 8 + }, +/mob/living/simple_animal/bot/mulebot{ + home_destination = "QM #2"; + suffix = "#2" + }, +/turf/open/floor/pod/dark, +/area/maintenance/starboard) +"aal" = ( +/obj/structure/chair{ + dir = 8 + }, +/obj/item/radio/intercom{ + pixel_x = 28 + }, +/obj/machinery/light_switch{ + pixel_y = 26 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Chief Medical Office"; + dir = 8; + network = list("ss13","medbay"); + pixel_y = -22 + }, +/mob/living/simple_animal/pet/cat/Runtime, +/turf/open/floor/plasteel/white, +/area/crew_quarters/heads/cmo) +"aam" = ( +/obj/structure/chair/comfy/brown{ + color = "#596479"; + dir = 1 + }, +/mob/living/simple_animal/mouse/brown/Tom, +/turf/open/floor/plasteel/dark, +/area/security/prison) +"aan" = ( +/obj/machinery/camera{ + c_tag = "Head of Security's Office"; + dir = 8 + }, +/obj/structure/bed/dogbed{ + desc = "A comfy-looking pet bed. You can even strap your pet in, in case the gravity turns off."; + name = "pet bed" + }, +/obj/item/storage/secure/safe/HoS{ + pixel_x = 35 + }, +/mob/living/simple_animal/hostile/retaliate/bat/secbat{ + desc = "An adorable fruit bat with a cute little hat, may or may not have a reputation for biting out eyeballs, or at least that's what the HoS'd tell you."; + name = "Colonel Chomps" + }, +/turf/open/floor/carpet, +/area/crew_quarters/heads/hos) +"aao" = ( +/obj/structure/closet/emcloset/anchored, +/obj/structure/sign/directions/medical{ + dir = 8; + icon_state = "direction_med"; + pixel_y = 36 + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "direction_sci"; + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) +"aap" = ( +/obj/machinery/quantumpad{ + map_pad_id = "5"; + map_pad_link_id = "6"; + name = "South Sector Pad" + }, +/obj/structure/sign/directions/evac{ + pixel_y = 40 + }, +/obj/structure/sign/directions/security{ + pixel_y = 32 + }, +/obj/structure/sign/directions/command{ + pixel_y = 24 + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "pad_s"; + layer = 4.1; + name = "south sector"; + pixel_y = 13 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) +"aaq" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 6 + }, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/structure/sign/directions/supply{ + pixel_x = 32; + pixel_y = -36 + }, +/obj/structure/sign/directions/engineering{ + dir = 4; + icon_state = "direction_eng"; + pixel_x = 32; + pixel_y = -28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) +"aar" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/sign/departments/botany, +/turf/open/floor/plating, +/area/hydroponics) +"aas" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/sign/departments/engineering, +/turf/open/floor/plating, +/area/engine/engineering) +"aat" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/structure/cable{ + icon_state = "0-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/machinery/power/apc{ + areastring = "/area/hallway/primary/fore"; + dir = 1; + name = "Fore Primary Hallway APC"; + pixel_y = 24 + }, +/obj/structure/sign/directions/engineering{ + dir = 4; + icon_state = "direction_eng"; + pixel_x = 0; + pixel_y = 40 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/fore) +"aau" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/sign/departments/custodian{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness) +"aav" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/structure/disposalpipe/trunk{ + dir = 1 + }, +/obj/machinery/disposal/bin, +/turf/open/floor/plasteel, +/area/crew_quarters/fitness) "aaw" = ( /obj/structure/cable{ icon_state = "4-8" @@ -11,10 +324,198 @@ }, /turf/open/floor/plasteel/white, /area/science/misc_lab) +"aax" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/sign/departments/cargo, +/turf/open/floor/plating, +/area/quartermaster/storage) +"aay" = ( +/obj/structure/disposalpipe/junction/yjunction{ + dir = 1 + }, +/obj/structure/sign/departments/cargo{ + pixel_x = -32; + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/fore) +"aaz" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/structure/disposalpipe/segment, +/obj/structure/sign/directions/engineering{ + dir = 1; + icon_state = "direction_eng"; + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/fore) +"aaA" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/structure/sign/warning/pods{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 4 + }, +/area/hallway/primary/port) +"aaB" = ( +/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/structure/sign/departments/chemistry{ + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"aaC" = ( +/obj/structure/sign/directions/medical{ + dir = 8; + icon_state = "direction_med"; + pixel_y = 36 + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "direction_sci"; + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"aaD" = ( +/obj/structure/sign/directions/engineering{ + dir = 4; + icon_state = "direction_eng"; + pixel_y = 36 + }, +/obj/structure/sign/directions/supply{ + dir = 4; + icon_state = "direction_supply"; + pixel_x = 0; + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"aaE" = ( +/obj/structure/sign/directions/evac{ + pixel_x = -32; + pixel_y = -24 + }, +/obj/structure/sign/directions/security{ + pixel_x = -32; + pixel_y = -32 + }, +/obj/structure/sign/directions/command{ + pixel_x = -32; + pixel_y = -40 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"aaF" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/obj/structure/sign/departments/science{ + pixel_x = -32; + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"aaG" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/obj/structure/sign/directions/medical{ + dir = 8; + icon_state = "direction_med"; + pixel_y = 40 + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "direction_sci"; + pixel_y = 32 + }, +/obj/structure/sign/directions/security{ + pixel_y = 24 + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) "aaH" = ( /obj/machinery/smartfridge/chemistry/preloaded, /turf/closed/wall, /area/medical/chemistry) +"aaI" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/visible{ + dir = 4 + }, +/obj/structure/sign/directions/engineering{ + dir = 4; + icon_state = "direction_eng"; + pixel_y = 40 + }, +/obj/structure/sign/directions/supply{ + dir = 4; + icon_state = "direction_supply"; + pixel_x = 0; + pixel_y = 32 + }, +/obj/structure/sign/directions/evac{ + pixel_y = 24 + }, +/turf/open/floor/plating/snowed/smoothed/icemoon, +/area/icemoon/surface/outdoors) +"aaJ" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/sign/departments/evac, +/turf/open/floor/plating, +/area/hallway/secondary/exit/departure_lounge) +"aaK" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/machinery/light{ + dir = 1 + }, +/obj/item/radio/intercom{ + pixel_y = 25 + }, +/obj/structure/sign/directions/evac{ + dir = 4; + pixel_x = 0; + pixel_y = 40 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 4 + }, +/area/hallway/secondary/exit/departure_lounge) +"aaL" = ( +/obj/structure/sign/departments/restroom{ + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plasteel/grimy, +/area/crew_quarters/fitness/recreation) "aaM" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /obj/machinery/atmospherics/components/binary/valve{ @@ -22,6 +523,32 @@ }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) +"aaN" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/machinery/quantumpad{ + map_pad_id = "1"; + map_pad_link_id = "2"; + name = "Northwest Sector Pad" + }, +/obj/structure/sign/directions/medical{ + dir = 8; + icon_state = "direction_med"; + pixel_y = 36 + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "direction_sci"; + pixel_y = 28 + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "pad_nw"; + layer = 4.1; + name = "northwest sector"; + pixel_y = 13 + }, +/turf/open/floor/plasteel, +/area/quartermaster/miningdock) "aaO" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 9 @@ -36,13 +563,155 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) +"aaQ" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/machinery/computer/shuttle/snow_taxi, +/obj/structure/sign/directions/supply{ + dir = 4; + icon_state = "direction_supply"; + pixel_x = 0; + pixel_y = 36 + }, +/obj/structure/sign/directions/engineering{ + dir = 4; + icon_state = "direction_eng"; + pixel_y = 28 + }, +/turf/open/floor/plasteel, +/area/quartermaster/miningdock) +"aaR" = ( +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "aaS" = ( /turf/closed/wall/r_wall, /area/medical/surgery) +"aaT" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"aaU" = ( +/obj/structure/sign/departments/restroom{ + pixel_x = 32 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) +"aaV" = ( +/obj/structure/sign/directions/evac{ + dir = 1; + icon_state = "direction_evac"; + pixel_y = 8 + }, +/obj/structure/sign/directions/security{ + dir = 8; + icon_state = "direction_sec"; + pixel_x = 0; + pixel_y = 0 + }, +/obj/structure/sign/directions/command{ + dir = 8; + icon_state = "direction_bridge"; + pixel_y = -8 + }, +/turf/closed/wall/r_wall, +/area/hallway/primary/central) +"aaW" = ( +/obj/effect/spawner/structure/window/reinforced, +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/sign/departments/security, +/turf/open/floor/plating, +/area/hallway/primary/central) +"aaX" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"aaY" = ( +/obj/machinery/atmospherics/pipe/manifold/supply/hidden, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"aaZ" = ( +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/sign/mining{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "aba" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/medical/surgery) +"abb" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abc" = ( +/obj/structure/sign/directions/command{ + pixel_x = 32; + pixel_y = -40 + }, +/obj/structure/sign/directions/supply{ + dir = 4; + icon_state = "direction_supply"; + pixel_x = 32; + pixel_y = -24 + }, +/obj/structure/sign/directions/science{ + dir = 4; + pixel_x = 32; + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abd" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "abe" = ( /obj/structure/table/wood, /obj/machinery/computer/security/wooden_tv, @@ -52,14 +721,307 @@ }, /turf/open/floor/wood, /area/maintenance/bar) +"abf" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abg" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abh" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/sign/departments/xenobio{ + pixel_x = 32 + }, +/obj/structure/closet/bombcloset{ + anchored = 1 + }, +/turf/open/floor/plasteel/white, +/area/science/misc_lab) +"abi" = ( +/obj/machinery/airalarm{ + dir = 8; + pixel_x = 24 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abj" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/sign/departments/holy{ + pixel_x = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "abk" = ( /obj/machinery/light, /turf/open/floor/plasteel/dark, /area/ai_monitored/security/armory) +"abl" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/sign/departments/holy{ + pixel_x = -32; + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abm" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/structure/sign/directions/evac{ + dir = 8; + icon_state = "direction_evac"; + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abn" = ( +/obj/structure/sign/poster/official/ian, +/turf/closed/wall, +/area/crew_quarters/heads/hop) +"abo" = ( +/obj/effect/landmark/start/assistant, +/obj/structure/sign/poster/official/build{ + pixel_x = -32; + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/storage/primary) +"abp" = ( +/obj/structure/cable{ + icon_state = "4-8" + }, +/obj/effect/turf_decal/tile/brown, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/filingcabinet, +/turf/open/floor/plasteel, +/area/quartermaster/storage) +"abq" = ( +/obj/structure/toilet{ + contents = newlist(/obj/item/toy/snappop/phoenix); + dir = 4 + }, +/obj/machinery/light/small{ + dir = 1; + light_color = "#ffc1c1" + }, +/turf/open/floor/plasteel/freezer, +/area/hallway/primary/port) +"abr" = ( +/obj/structure/sink/kitchen{ + pixel_y = 28 + }, +/turf/open/floor/plasteel/freezer, +/area/hallway/primary/port) "abs" = ( /obj/structure/table/optable, /turf/open/floor/plasteel/freezer, /area/medical/surgery) +"abt" = ( +/obj/machinery/door/airlock{ + name = "Unisex Restroom" + }, +/turf/open/floor/plasteel/freezer, +/area/hallway/primary/port) +"abu" = ( +/obj/structure/cable{ + icon_state = "2-4" + }, +/obj/machinery/light{ + dir = 1 + }, +/obj/structure/sign/departments/restroom{ + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"abv" = ( +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Hydroponics North" + }, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, +/obj/machinery/disposal/bin, +/obj/structure/sign/poster/official/hydro_ad{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/dark, +/area/hydroponics) +"abw" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/effect/turf_decal/tile/bar, +/obj/structure/disposalpipe/segment, +/obj/structure/sign/poster/official/high_class_martini{ + pixel_x = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/aft) +"abx" = ( +/obj/machinery/light{ + dir = 8 + }, +/obj/structure/table/wood, +/obj/structure/sign/poster/official/soft_cap_pop_art{ + pixel_x = -32 + }, +/turf/open/floor/wood, +/area/crew_quarters/bar) +"aby" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/machinery/computer/arcade/minesweeper{ + dir = 8 + }, +/obj/structure/sign/poster/official/nanomichi_ad{ + pixel_x = 32 + }, +/turf/open/floor/wood, +/area/crew_quarters/bar) +"abz" = ( +/obj/structure/chair/sofa/right{ + dir = 1 + }, +/obj/structure/sign/poster/official/fruit_bowl{ + pixel_y = -32 + }, +/turf/open/floor/wood, +/area/crew_quarters/bar) +"abA" = ( +/obj/structure/cable{ + icon_state = "1-4" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/structure/sign/poster/official/fashion{ + pixel_y = -32 + }, +/turf/open/floor/carpet, +/area/crew_quarters/dorms) +"abB" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/atmospherics/pipe/simple/supply/hidden, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/structure/sign/poster/official/report_crimes{ + pixel_x = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/fore) +"abC" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/external{ + req_one_access_txt = "13,8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/mapping_helpers/airlock/cyclelink_helper, +/turf/open/floor/plating, +/area/maintenance/port/fore) +"abD" = ( +/obj/structure/cable{ + icon_state = "1-2" + }, +/obj/machinery/door/airlock/external{ + req_one_access_txt = "13,8" + }, +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/port/fore) +"abE" = ( +/obj/machinery/atmospherics/components/unary/thermomachine/freezer, +/obj/effect/turf_decal/tile/blue{ + dir = 1 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 4 + }, +/obj/machinery/camera{ + c_tag = "Medbay Cryogenics"; + network = list("ss13","medbay") + }, +/obj/structure/sign/poster/official/help_others{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"abF" = ( +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/structure/closet/secure_closet/security/engine, +/obj/item/radio/intercom{ + pixel_y = -26 + }, +/obj/machinery/camera{ + c_tag = "Security Post - Cargo"; + dir = 1 + }, +/obj/structure/sign/poster/official/do_not_question{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/security/checkpoint/supply) "abG" = ( /obj/effect/turf_decal/stripes/corner{ dir = 4 @@ -67,11 +1029,160 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on, /turf/open/floor/plasteel, /area/engine/atmospherics_engine) +"abH" = ( +/obj/structure/table, +/obj/item/storage/firstaid/brute, +/obj/item/storage/firstaid/brute{ + pixel_x = 3; + pixel_y = 3 + }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/obj/effect/turf_decal/tile/blue, +/obj/structure/sign/poster/official/medical_green_cross{ + pixel_y = -32 + }, +/turf/open/floor/plasteel/white, +/area/medical/medbay/central) +"abI" = ( +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/obj/effect/turf_decal/tile/yellow, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/structure/sign/poster/official/safety_eye_protection{ + pixel_y = -32 + }, +/turf/open/floor/plasteel/white, +/area/medical/chemistry) +"abJ" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 4 + }, +/obj/structure/sign/poster/official/walk{ + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"abK" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ + dir = 4 + }, +/obj/structure/sign/poster/official/build{ + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/port) +"abL" = ( +/obj/structure/table, +/obj/item/mmi, +/obj/item/mmi, +/obj/item/mmi, +/obj/structure/sign/poster/official/state_laws{ + pixel_y = -32 + }, +/turf/open/floor/plasteel/white, +/area/science/robotics/lab) +"abM" = ( +/obj/structure/closet/secure_closet/security/med, +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/machinery/camera{ + c_tag = "Security Post - Medbay"; + dir = 1 + }, +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/sign/poster/official/here_for_your_safety{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/security/checkpoint/medical) +"abN" = ( +/obj/machinery/light, +/obj/machinery/camera{ + c_tag = "Escape Arm Southwest"; + dir = 1 + }, +/obj/structure/closet/crate/bin, +/obj/structure/sign/directions/security{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/secondary/exit/departure_lounge) +"abO" = ( +/obj/machinery/light, +/obj/structure/closet/crate/bin, +/obj/structure/sign/directions/command{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/secondary/exit/departure_lounge) +"abP" = ( +/obj/structure/chair{ + dir = 1 + }, +/obj/structure/sign/poster/official/cohiba_robusto_ad{ + pixel_y = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/secondary/exit/departure_lounge) "abQ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/effect/landmark/event_spawn, /turf/open/floor/wood, /area/crew_quarters/theatre) +"abR" = ( +/obj/structure/chair/stool, +/obj/structure/sign/poster/official/foam_force_ad{ + pixel_x = 32 + }, +/turf/open/floor/plasteel/grimy, +/area/crew_quarters/fitness/recreation) +"abS" = ( +/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, +/obj/machinery/door/firedoor/border_only{ + name = "south facing firelock" + }, +/obj/structure/sign/poster/official/no_erp{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/quartermaster/miningoffice) +"abT" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on, +/obj/structure/disposalpipe/segment, +/obj/structure/sign/directions/evac{ + dir = 8; + icon_state = "direction_evac"; + pixel_x = 32; + pixel_y = 40 + }, +/obj/structure/sign/directions/engineering{ + dir = 4; + icon_state = "direction_eng"; + pixel_x = 32; + pixel_y = 24 + }, +/obj/structure/sign/directions/medical{ + dir = 4; + pixel_x = 32; + pixel_y = 32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) "abU" = ( /obj/structure/cable{ icon_state = "4-8" @@ -81,6 +1192,25 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) +"abV" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/structure/sign/poster/official/obey{ + pixel_x = -32 + }, +/turf/open/floor/plasteel, +/area/hallway/primary/central) +"abW" = ( +/obj/structure/tank_dispenser/oxygen, +/obj/machinery/camera/motion{ + c_tag = "Armory Motion Sensor North" + }, +/obj/structure/sign/poster/official/ion_rifle{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/dark, +/area/ai_monitored/security/armory) "abX" = ( /obj/machinery/airalarm{ pixel_y = 28 @@ -98,6 +1228,15 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) +"abY" = ( +/obj/machinery/computer/camera_advanced/xenobio{ + dir = 1 + }, +/obj/structure/sign/poster/official/anniversary_vintage_reprint{ + pixel_y = -32 + }, +/turf/open/floor/plasteel/white, +/area/science/xenobiology) "abZ" = ( /obj/effect/landmark/start/medical_doctor, /obj/machinery/atmospherics/pipe/simple/supply/hidden{ @@ -105,6 +1244,35 @@ }, /turf/open/floor/plasteel/freezer, /area/medical/surgery) +"aca" = ( +/obj/structure/cable{ + icon_state = "0-4" + }, +/obj/machinery/camera{ + c_tag = "Brig Evidence Storage" + }, +/obj/structure/sign/poster/official/space_cops{ + pixel_y = 32 + }, +/turf/open/floor/plasteel/dark, +/area/security/main) +"acb" = ( +/turf/open/floor/plasteel/dark, +/area/hydroponics) +"acc" = ( +/obj/structure/sign/poster/contraband/lusty_xenomorph{ + pixel_x = -32; + pixel_y = -32 + }, +/turf/open/floor/plating, +/area/maintenance/aft/secondary) +"acd" = ( +/obj/structure/reagent_dispensers/watertank, +/obj/structure/sign/poster/contraband/bountyhunters{ + pixel_x = 32 + }, +/turf/open/floor/plating, +/area/maintenance/central) "ace" = ( /obj/structure/cable{ icon_state = "4-8" @@ -114,6 +1282,19 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) +"acf" = ( +/obj/structure/chair/stool, +/obj/structure/sign/poster/official/bless_this_spess{ + pixel_x = -32 + }, +/turf/open/floor/carpet, +/area/chapel/main) +"acg" = ( +/obj/structure/sign/poster/official/wtf_is_co2{ + pixel_x = 32 + }, +/turf/open/floor/plasteel, +/area/science/storage) "acj" = ( /obj/effect/landmark/blobstart, /turf/open/floor/plating, @@ -471,8 +1652,8 @@ "aiS" = ( /obj/structure/closet/secure_closet/CMO, /obj/machinery/keycard_auth{ - pixel_y = 4; - pixel_x = -24 + pixel_x = -24; + pixel_y = 4 }, /obj/effect/turf_decal/tile/blue{ dir = 4 @@ -772,16 +1953,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"aon" = ( -/obj/effect/turf_decal/tile/yellow{ - dir = 8 - }, -/obj/effect/turf_decal/tile/yellow, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/medical/chemistry) "aoo" = ( /obj/structure/table/glass, /obj/machinery/reagentgrinder{ @@ -915,9 +2086,6 @@ }, /turf/open/floor/plasteel/dark, /area/tcommsat/computer) -"arG" = ( -/turf/open/floor/plating, -/area/medical/medbay/central) "arH" = ( /obj/structure/cable{ icon_state = "4-8" @@ -1548,7 +2716,7 @@ /turf/open/floor/plasteel/white, /area/science/lab) "ayu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-16" }, /obj/effect/turf_decal/tile/purple{ @@ -1991,8 +3159,8 @@ dir = 4 }, /obj/machinery/conveyor{ - id = "packageSort2"; - dir = 1 + dir = 1; + id = "packageSort2" }, /obj/machinery/disposal/deliveryChute, /obj/structure/window/reinforced{ @@ -2905,9 +4073,9 @@ /area/crew_quarters/dorms) "aNS" = ( /obj/machinery/turnstile{ + dir = 4; name = "Genpop Entrance Turnstile"; - req_access_txt = "69"; - dir = 4 + req_access_txt = "69" }, /obj/machinery/door/poddoor/preopen{ id = "permacell1"; @@ -2950,24 +4118,6 @@ /obj/effect/turf_decal/stripes/line, /turf/open/floor/plating, /area/engine/engineering) -"aOl" = ( -/obj/structure/closet/secure_closet/security/med, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Security Post - Medbay"; - dir = 1 - }, -/obj/machinery/light{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/security/checkpoint/medical) "aOm" = ( /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ @@ -3023,7 +4173,7 @@ /area/engine/supermatter) "aOP" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel/dark, /area/security/prison) "aPw" = ( @@ -3416,9 +4566,9 @@ /area/maintenance/solars/port/fore) "bcc" = ( /obj/machinery/door/window/brigdoor/security/cell{ + dir = 1; id = "Cell 2"; - name = "Cell 2"; - dir = 1 + name = "Cell 2" }, /obj/effect/turf_decal/vg_decals/numbers/two, /obj/machinery/door/poddoor/preopen{ @@ -3545,8 +4695,8 @@ name = "supply dock loading door" }, /obj/machinery/conveyor{ - id = "QMLoad2"; - dir = 1 + dir = 1; + id = "QMLoad2" }, /turf/open/floor/plating, /area/quartermaster/storage) @@ -3893,9 +5043,9 @@ "brE" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /obj/machinery/door/window/southleft{ + dir = 1; name = "Court Cell"; - req_access_txt = "2"; - dir = 1 + req_access_txt = "2" }, /obj/structure/window/reinforced{ dir = 8 @@ -4031,7 +5181,7 @@ /turf/open/floor/plasteel/dark, /area/hallway/secondary/exit/departure_lounge) "bum" = ( -/turf/open/openspace/icemoon, +/turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors) "buF" = ( /obj/machinery/light, @@ -4071,7 +5221,15 @@ "buO" = ( /obj/machinery/quantumpad{ map_pad_id = "3"; - map_pad_link_id = "4" + map_pad_link_id = "4"; + name = "Northeast Sector Pad" + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "pad_ne"; + layer = 4.1; + name = "northeast sector"; + pixel_y = 13 }, /turf/open/floor/plasteel, /area/hallway/primary/port) @@ -4146,9 +5304,9 @@ dir = 1 }, /obj/machinery/turnstile{ + dir = 4; name = "Genpop Entrance Turnstile"; - req_access_txt = "69"; - dir = 4 + req_access_txt = "69" }, /turf/open/floor/plasteel/dark, /area/security/brig) @@ -4558,7 +5716,6 @@ department = "Mining"; pixel_x = -30 }, -/obj/structure/closet/crate/bin, /turf/open/floor/plasteel, /area/quartermaster/miningdock) "bzj" = ( @@ -4938,13 +6095,6 @@ }, /turf/open/floor/carpet, /area/hallway/primary/central) -"bBB" = ( -/obj/machinery/atmospherics/pipe/manifold/supply/hidden, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "bBH" = ( /obj/structure/cable{ icon_state = "0-4" @@ -5827,9 +6977,9 @@ name = "west facing firelock" }, /obj/machinery/door/window/southleft{ + dir = 8; name = "Test Chamber"; - req_access_txt = "55"; - dir = 8 + req_access_txt = "55" }, /obj/machinery/door/poddoor/preopen{ id = "xenobio2"; @@ -5845,9 +6995,9 @@ dir = 10 }, /obj/machinery/door/window/southleft{ + dir = 4; name = "Test Chamber"; - req_access_txt = "55"; - dir = 4 + req_access_txt = "55" }, /turf/open/floor/plasteel, /area/science/xenobiology) @@ -5942,9 +7092,9 @@ dir = 4 }, /obj/machinery/door/window/brigdoor{ + dir = 1; name = "Reception Desk"; - req_access_txt = "63"; - dir = 1 + req_access_txt = "63" }, /obj/machinery/door/window/brigdoor{ dir = 8; @@ -6056,9 +7206,6 @@ dir = 5 }, /obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/machinery/firealarm{ - pixel_y = 24 - }, /turf/open/floor/plasteel, /area/science/mixing) "bKO" = ( @@ -6345,8 +7492,8 @@ }, /obj/structure/table/wood, /obj/machinery/recharger{ - pixel_y = 4; - pixel_x = -7 + pixel_x = -7; + pixel_y = 4 }, /obj/item/book/manual/wiki/security_space_law{ pixel_x = 6; @@ -6490,10 +7637,6 @@ /obj/machinery/holopad, /turf/open/floor/carpet, /area/hallway/secondary/exit/departure_lounge) -"bQf" = ( -/obj/structure/closet/emcloset/anchored, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) "bQg" = ( /obj/structure/cable{ icon_state = "1-2" @@ -7162,15 +8305,6 @@ /obj/structure/closet/crate/coffin, /turf/open/floor/wood, /area/chapel/office) -"cbz" = ( -/obj/structure/cable{ - icon_state = "0-4" - }, -/obj/machinery/camera{ - c_tag = "Brig Evidence Storage" - }, -/turf/open/floor/plasteel/dark, -/area/security/main) "cbL" = ( /obj/structure/cable{ icon_state = "4-8" @@ -7758,7 +8892,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/carpet, @@ -7841,7 +8975,15 @@ "cpC" = ( /obj/machinery/quantumpad{ map_pad_id = "2"; - map_pad_link_id = "1" + map_pad_link_id = "1"; + name = "South Sector Pad" + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "pad_s"; + layer = 4.1; + name = "south sector"; + pixel_y = 13 }, /turf/open/floor/plasteel, /area/hallway/primary/port) @@ -8179,8 +9321,8 @@ }, /obj/machinery/camera{ c_tag = "Medbay West"; - network = list("ss13","medbay"); - dir = 4 + dir = 4; + network = list("ss13","medbay") }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) @@ -8297,9 +9439,9 @@ req_access_txt = "10" }, /obj/machinery/door/window/northright{ + dir = 4; name = "Engineering Delivery"; - req_access_txt = "10"; - dir = 4 + req_access_txt = "10" }, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel/dark, @@ -8467,15 +9609,6 @@ }, /turf/open/floor/plasteel, /area/storage/primary) -"cGQ" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/machinery/light{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "cGZ" = ( /obj/machinery/light{ dir = 8 @@ -8710,7 +9843,15 @@ "cQa" = ( /obj/machinery/quantumpad{ map_pad_id = "6"; - map_pad_link_id = "5" + map_pad_link_id = "5"; + name = "Northeast Sector Pad" + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "pad_ne"; + layer = 4.1; + name = "northeast sector"; + pixel_y = 13 }, /turf/open/floor/plasteel, /area/quartermaster/miningdock) @@ -8830,18 +9971,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/visible, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"cSv" = ( -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/structure/disposalpipe/trunk{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/fitness) "cSC" = ( /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel/white, @@ -9032,7 +10161,7 @@ /obj/structure/cable{ icon_state = "2-8" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/dark, @@ -9291,8 +10420,8 @@ dir = 4 }, /obj/machinery/shower{ - pixel_y = 20; - pixel_x = 11 + pixel_x = 11; + pixel_y = 20 }, /obj/structure/disposalpipe/segment{ dir = 4 @@ -9410,7 +10539,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/fore) "dij" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/carpet, @@ -9664,8 +10793,8 @@ /obj/structure/table/wood, /obj/item/book/manual/wiki/security_space_law, /obj/item/flashlight/lamp/green{ - pixel_y = 1; - pixel_x = -7 + pixel_x = -7; + pixel_y = 1 }, /turf/open/floor/wood, /area/security/courtroom) @@ -9807,14 +10936,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"dvh" = ( -/obj/structure/table/reinforced, -/mob/living/carbon/monkey/punpun, -/obj/machinery/door/firedoor/border_only{ - name = "south facing firelock" - }, -/turf/open/floor/plasteel/grimy, -/area/crew_quarters/bar) "dvs" = ( /obj/machinery/door/airlock/public/glass{ name = "Snow Airlock" @@ -9966,6 +11087,13 @@ "dAV" = ( /turf/closed/wall/r_wall, /area/ai_monitored/turret_protected/ai_upload_foyer) +"dBA" = ( +/obj/machinery/portable_atmospherics/pump, +/obj/item/radio/intercom{ + pixel_y = -26 + }, +/turf/open/floor/plasteel/white, +/area/science/mixing) "dBL" = ( /obj/structure/closet/secure_closet/medical1, /obj/structure/extinguisher_cabinet{ @@ -10026,21 +11154,9 @@ pixel_x = 32 }, /obj/effect/turf_decal/tile/brown, +/obj/machinery/rnd/production/techfab/department/cargo, /turf/open/floor/plasteel, /area/quartermaster/storage) -"dDf" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/fore) "dDC" = ( /obj/effect/turf_decal/tile/neutral, /obj/effect/turf_decal/tile/neutral{ @@ -10131,9 +11247,9 @@ dir = 4 }, /obj/machinery/turnstile{ + dir = 8; name = "Genpop Exit Turnstile"; - req_access_txt = "70"; - dir = 8 + req_access_txt = "70" }, /turf/open/floor/plasteel/dark, /area/security/brig) @@ -10876,15 +11992,6 @@ }, /turf/open/floor/plasteel, /area/science/robotics/lab) -"eeh" = ( -/obj/machinery/light, -/obj/machinery/camera{ - c_tag = "Escape Arm Southwest"; - dir = 1 - }, -/obj/structure/closet/crate/bin, -/turf/open/floor/plasteel, -/area/hallway/secondary/exit/departure_lounge) "eex" = ( /obj/machinery/atmospherics/pipe/simple/general/visible, /obj/machinery/meter, @@ -11106,8 +12213,8 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/button/flasher{ id = "PCell 1"; - pixel_y = 9; - pixel_x = -37 + pixel_x = -37; + pixel_y = 9 }, /turf/open/floor/plasteel/dark, /area/security/brig) @@ -11289,9 +12396,9 @@ dir = 4 }, /obj/machinery/turnstile{ + dir = 8; name = "Genpop Exit Turnstile"; - req_access_txt = "70"; - dir = 8 + req_access_txt = "70" }, /obj/effect/turf_decal/tile/red{ dir = 1 @@ -11321,7 +12428,7 @@ /turf/open/floor/plasteel, /area/hallway/primary/port) "esY" = ( -/turf/open/openspace/icemoon, +/turf/open/transparent/openspace/icemoon, /area/engine/atmos) "ets" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ @@ -11361,7 +12468,7 @@ /turf/open/floor/plasteel, /area/janitor) "eue" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-04" }, /obj/effect/turf_decal/tile/blue{ @@ -11404,13 +12511,6 @@ dir = 8 }, /area/hallway/primary/fore) -"evr" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/obj/machinery/door/firedoor/border_only{ - name = "south facing firelock" - }, -/turf/open/floor/plasteel, -/area/quartermaster/miningoffice) "evI" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/n2{ dir = 1 @@ -11633,10 +12733,6 @@ }, /turf/open/floor/plating, /area/engine/storage) -"eEa" = ( -/obj/machinery/light, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/dorms) "eEy" = ( /obj/machinery/doorButtons/access_button{ idDoor = "virology_airlock_interior"; @@ -11666,17 +12762,11 @@ /obj/structure/disposalpipe/segment{ dir = 9 }, -/turf/open/floor/plasteel/dark, -/area/teleporter) -"eFy" = ( -/obj/machinery/light{ - dir = 4 - }, -/obj/machinery/computer/arcade/minesweeper{ +/obj/machinery/computer/gateway_control{ dir = 8 }, -/turf/open/floor/wood, -/area/crew_quarters/bar) +/turf/open/floor/plasteel/dark, +/area/teleporter) "eFB" = ( /obj/structure/table/wood, /obj/item/reagent_containers/rag, @@ -12084,19 +13174,6 @@ }, /turf/open/floor/wood, /area/crew_quarters/bar) -"eOK" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plating, -/area/hallway/primary/central) "eOO" = ( /obj/structure/weightmachine/weightlifter, /turf/open/floor/plasteel, @@ -12377,13 +13454,6 @@ /obj/structure/table, /turf/open/floor/plasteel, /area/hallway/secondary/entry) -"eZn" = ( -/obj/structure/tank_dispenser/oxygen, -/obj/machinery/camera/motion{ - c_tag = "Armory Motion Sensor North" - }, -/turf/open/floor/plasteel/dark, -/area/ai_monitored/security/armory) "eZA" = ( /obj/structure/cable{ icon_state = "0-4" @@ -12398,8 +13468,8 @@ /area/bridge/meeting_room) "eZU" = ( /obj/machinery/conveyor{ - id = "QMLoad2"; - dir = 1 + dir = 1; + id = "QMLoad2" }, /turf/open/floor/plating, /area/quartermaster/storage) @@ -12480,9 +13550,9 @@ icon_state = "1-4" }, /obj/machinery/door/window/brigdoor/security/cell{ + dir = 8; id = "Cell 1"; - name = "Cell 1"; - dir = 8 + name = "Cell 1" }, /obj/effect/turf_decal/vg_decals/numbers/one, /obj/machinery/door/poddoor/preopen{ @@ -12736,7 +13806,6 @@ dir = 4; pixel_x = -24 }, -/obj/structure/closet/crate/bin, /turf/open/floor/plasteel/white, /area/science/misc_lab) "fjS" = ( @@ -12854,14 +13923,6 @@ }, /turf/open/floor/engine/co2, /area/engine/atmos) -"fnu" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/machinery/quantumpad{ - map_pad_id = "1"; - map_pad_link_id = "2" - }, -/turf/open/floor/plasteel, -/area/quartermaster/miningdock) "fnx" = ( /obj/machinery/light{ dir = 1 @@ -12945,24 +14006,6 @@ }, /turf/open/floor/plasteel/white, /area/science/robotics/lab) -"fpW" = ( -/obj/effect/turf_decal/bot, -/mob/living/simple_animal/bot/mulebot{ - home_destination = "QM #2"; - suffix = "#2" - }, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=8"; - dir = 8; - freq = 1400; - location = "QM #2" - }, -/obj/machinery/camera{ - c_tag = "Cargo Garage"; - dir = 8 - }, -/turf/open/floor/pod/dark, -/area/maintenance/starboard) "fqj" = ( /obj/machinery/field/generator, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, @@ -13095,11 +14138,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/closed/wall, /area/storage/eva) -"fuy" = ( -/obj/machinery/light, -/obj/structure/closet/crate/bin, -/turf/open/floor/plasteel, -/area/hallway/secondary/exit/departure_lounge) "fuB" = ( /obj/machinery/camera{ c_tag = "Auxiliary Bridge North"; @@ -13346,8 +14384,8 @@ name = "Door Bolt Control"; normaldoorcontrol = 1; pixel_x = 24; - specialfunctions = 4; - pixel_y = -5 + pixel_y = -5; + specialfunctions = 4 }, /obj/machinery/light/small{ dir = 8 @@ -13696,13 +14734,6 @@ }, /turf/open/floor/plating, /area/storage/atmos) -"fNd" = ( -/obj/effect/spawner/structure/window/reinforced, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plating, -/area/engine/engineering) "fNh" = ( /obj/structure/cable, /turf/open/floor/plating/snowed/smoothed/icemoon, @@ -13844,8 +14875,8 @@ /obj/structure/table/wood, /obj/item/book/manual/wiki/security_space_law, /obj/item/flashlight/lamp/green{ - pixel_y = 1; - pixel_x = -7 + pixel_x = -7; + pixel_y = 1 }, /turf/open/floor/wood, /area/security/courtroom) @@ -14175,7 +15206,15 @@ "gct" = ( /obj/machinery/quantumpad{ map_pad_id = "4"; - map_pad_link_id = "3" + map_pad_link_id = "3"; + name = "Northwest Sector Pad" + }, +/obj/structure/sign/directions/science{ + dir = 8; + icon_state = "pad_nw"; + layer = 4.1; + name = "northwest sector"; + pixel_y = 13 }, /turf/open/floor/plasteel, /area/hallway/primary/aft) @@ -14546,9 +15585,9 @@ /obj/machinery/button/door{ id = "Secure Gate"; name = "Cell Shutters"; + pixel_x = 3; pixel_y = 24; - req_access_txt = "2"; - pixel_x = 3 + req_access_txt = "2" }, /turf/open/floor/plasteel/dark, /area/security/brig) @@ -14580,6 +15619,10 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk{ + dir = 8 + }, /turf/open/floor/plasteel/white, /area/medical/genetics) "goM" = ( @@ -14938,8 +15981,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on{ dir = 4 }, -/obj/machinery/portable_atmospherics/scrubber, -/obj/item/storage/firstaid/toxin, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -15074,18 +16115,6 @@ /obj/machinery/power/port_gen/pacman, /turf/open/floor/plating, /area/engine/storage) -"gEz" = ( -/obj/structure/cable{ - icon_state = "1-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/turf/open/floor/carpet, -/area/crew_quarters/dorms) "gFb" = ( /obj/machinery/vending/wardrobe/law_wardrobe, /obj/item/radio/intercom{ @@ -15270,19 +16299,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/port) -"gKB" = ( -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/machinery/light{ - dir = 4 - }, -/obj/structure/reagent_dispensers/watertank, -/obj/item/radio/intercom{ - pixel_y = -26 - }, -/turf/open/floor/plasteel/white, -/area/science/misc_lab) "gKR" = ( /obj/machinery/mineral/equipment_vendor, /obj/structure/disposalpipe/segment{ @@ -15473,6 +16489,9 @@ /area/storage/atmos) "gPE" = ( /obj/machinery/portable_atmospherics/pump, +/obj/machinery/firealarm{ + pixel_y = 24 + }, /turf/open/floor/plasteel/white, /area/science/mixing) "gPF" = ( @@ -15582,13 +16601,6 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port/aft) -"gRS" = ( -/obj/machinery/light{ - dir = 8 - }, -/obj/structure/table/wood, -/turf/open/floor/wood, -/area/crew_quarters/bar) "gSh" = ( /obj/structure/cable{ icon_state = "1-8" @@ -15871,9 +16883,9 @@ /obj/machinery/button/door{ id = "kitchen"; name = "Kitchen Shutters Control"; - req_access_txt = "28"; pixel_x = 24; - pixel_y = -4 + pixel_y = -4; + req_access_txt = "28" }, /turf/open/floor/plasteel/cafeteria, /area/crew_quarters/kitchen) @@ -16132,8 +17144,8 @@ dir = 8 }, /obj/machinery/computer/monitor{ - name = "bridge power monitoring console"; - dir = 1 + dir = 1; + name = "bridge power monitoring console" }, /obj/structure/cable{ icon_state = "0-2" @@ -16183,31 +17195,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/port) -"hnB" = ( -/obj/structure/chair{ - dir = 8 - }, -/obj/item/radio/intercom{ - pixel_x = 28 - }, -/obj/machinery/light_switch{ - pixel_y = 26 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/mob/living/simple_animal/pet/cat/Runtime, -/obj/machinery/camera{ - c_tag = "Chief Medical Office"; - dir = 8; - network = list("ss13","medbay"); - pixel_y = -22 - }, -/turf/open/floor/plasteel/white, -/area/crew_quarters/heads/cmo) "hnO" = ( /obj/machinery/atmospherics/components/unary/cryo_cell, /turf/open/floor/plasteel/white, @@ -16296,8 +17283,8 @@ /obj/item/folder/blue, /obj/item/stamp/law, /obj/item/flashlight/lamp/green{ - pixel_y = 1; - pixel_x = -7 + pixel_x = -7; + pixel_y = 1 }, /turf/open/floor/plasteel/cult, /area/lawoffice) @@ -16869,12 +17856,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"hGM" = ( -/obj/structure/urinal{ - pixel_y = 32 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/dorms) "hGU" = ( /obj/structure/closet/secure_closet/personal/cabinet{ pixel_x = -8 @@ -17387,7 +18368,7 @@ /obj/machinery/light{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/wood, @@ -17413,9 +18394,8 @@ /turf/open/floor/carpet, /area/security/detectives_office) "hTL" = ( -/obj/effect/spawner/structure/window/plasma/reinforced, /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, +/turf/open/floor/plasteel/white, /area/science/mixing) "hTO" = ( /obj/structure/cable{ @@ -17493,9 +18473,9 @@ /area/engine/engineering) "hVH" = ( /obj/machinery/atmospherics/components/unary/vent_pump/siphon/on{ + dir = 1; external_pressure_bound = 120; - name = "killroom vent"; - dir = 1 + name = "killroom vent" }, /turf/open/floor/circuit/telecomms, /area/science/xenobiology) @@ -17533,8 +18513,8 @@ }, /obj/machinery/camera{ c_tag = "Surgery Observation"; - network = list("ss13","medbay"); - dir = 8 + dir = 8; + network = list("ss13","medbay") }, /turf/open/floor/plasteel/dark, /area/medical/surgery) @@ -17683,8 +18663,8 @@ /area/security/main) "iam" = ( /obj/machinery/computer/slot_machine{ - pixel_y = 2; - pixel_x = -7 + pixel_x = -7; + pixel_y = 2 }, /turf/open/floor/wood, /area/maintenance/bar) @@ -17869,14 +18849,6 @@ /obj/structure/closet/crate/coffin, /turf/open/floor/wood, /area/chapel/office) -"ifQ" = ( -/mob/living/simple_animal/mouse/brown/Tom, -/obj/structure/chair/comfy/brown{ - color = "#596479"; - dir = 1 - }, -/turf/open/floor/plasteel/dark, -/area/security/prison) "ifT" = ( /obj/structure/cable{ icon_state = "0-4" @@ -17987,6 +18959,10 @@ }, /turf/open/floor/plasteel, /area/storage/primary) +"ihL" = ( +/mob/living/simple_animal/opossum, +/turf/open/floor/plating, +/area/maintenance/aft/secondary) "ihX" = ( /obj/structure/cable{ icon_state = "0-2" @@ -18882,8 +19858,8 @@ /obj/machinery/button/door{ id = "hos"; name = "HoS Office Shutters"; - pixel_y = -26; - pixel_x = -6 + pixel_x = -6; + pixel_y = -26 }, /turf/open/floor/carpet, /area/crew_quarters/heads/hos) @@ -19707,19 +20683,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"jiV" = ( -/obj/structure/table, -/obj/item/storage/firstaid/brute, -/obj/item/storage/firstaid/brute{ - pixel_x = 3; - pixel_y = 3 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/obj/effect/turf_decal/tile/blue, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "jiY" = ( /obj/effect/turf_decal/tile/brown{ dir = 1 @@ -19920,7 +20883,6 @@ /obj/structure/cable{ icon_state = "0-2" }, -/obj/machinery/gateway, /obj/effect/turf_decal/bot_white, /turf/open/floor/plasteel/dark, /area/teleporter) @@ -20459,10 +21421,6 @@ "jJu" = ( /turf/closed/wall/r_wall, /area/medical/medbay/zone3) -"jKb" = ( -/obj/effect/landmark/start/assistant, -/turf/open/floor/plasteel, -/area/storage/primary) "jKF" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 @@ -20476,8 +21434,8 @@ pixel_y = -22 }, /obj/machinery/button/door/incinerator_vent_toxmix{ - pixel_y = -22; - pixel_x = 9 + pixel_x = 9; + pixel_y = -22 }, /obj/machinery/meter, /turf/open/floor/plasteel/white, @@ -20689,13 +21647,6 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) -"jPP" = ( -/obj/machinery/gateway{ - dir = 8 - }, -/obj/effect/turf_decal/bot_white, -/turf/open/floor/plasteel/dark, -/area/teleporter) "jQj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable{ @@ -21090,8 +22041,8 @@ "kdM" = ( /obj/effect/turf_decal/stripes, /obj/machinery/conveyor{ - id = "QMLoad2"; - dir = 1 + dir = 1; + id = "QMLoad2" }, /turf/open/floor/plasteel, /area/quartermaster/storage) @@ -21742,6 +22693,8 @@ c_tag = "Testing Lab East"; network = list("ss13","rd") }, +/obj/machinery/portable_atmospherics/scrubber, +/obj/item/storage/firstaid/toxin, /turf/open/floor/plasteel/white, /area/science/misc_lab) "kxI" = ( @@ -22195,19 +23148,6 @@ }, /turf/open/floor/engine, /area/engine/atmospherics_engine) -"kPj" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ - dir = 4 - }, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "kPn" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plasteel, @@ -22643,7 +23583,7 @@ /turf/open/floor/engine, /area/engine/engineering) "lfs" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-08" }, /turf/open/floor/plasteel, @@ -23166,6 +24106,10 @@ "luo" = ( /turf/open/floor/plasteel/white, /area/science/misc_lab) +"lwl" = ( +/mob/living/simple_animal/opossum/poppy, +/turf/open/floor/plating, +/area/engine/engineering) "lwH" = ( /obj/structure/cable{ icon_state = "1-4" @@ -23690,8 +24634,8 @@ "lMF" = ( /obj/machinery/camera{ c_tag = "Virology Module"; - network = list("ss13","medbay"); - dir = 1 + dir = 1; + network = list("ss13","medbay") }, /obj/structure/disposalpipe/segment{ dir = 4 @@ -24382,24 +25326,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"mkm" = ( -/obj/structure/cable{ - icon_state = "4-8" - }, -/obj/structure/cable{ - icon_state = "0-8" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/power/apc{ - areastring = "/area/hallway/primary/fore"; - dir = 1; - name = "Fore Primary Hallway APC"; - pixel_y = 24 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/fore) "mkr" = ( /obj/structure/cable{ icon_state = "4-8" @@ -24800,13 +25726,6 @@ /obj/machinery/telecomms/processor/preset_four, /turf/open/floor/plasteel/dark/telecomms, /area/tcommsat/server) -"mzB" = ( -/obj/structure/table, -/obj/item/mmi, -/obj/item/mmi, -/obj/item/mmi, -/turf/open/floor/plasteel/white, -/area/science/robotics/lab) "mAk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 10 @@ -25150,8 +26069,8 @@ /obj/machinery/button/door{ id = "engsm"; name = "Radiation Shutters Control"; - req_access_txt = "10"; - pixel_y = 25 + pixel_y = 25; + req_access_txt = "10" }, /obj/machinery/atmospherics/pipe/manifold/cyan/visible, /obj/effect/turf_decal/stripes/line{ @@ -25297,9 +26216,9 @@ dir = 4 }, /obj/machinery/turnstile{ + dir = 8; name = "Genpop Exit Turnstile"; - req_access_txt = "70"; - dir = 8 + req_access_txt = "70" }, /obj/structure/cable{ icon_state = "4-8" @@ -25363,22 +26282,6 @@ }, /turf/open/floor/plasteel/freezer, /area/crew_quarters/dorms) -"mQo" = ( -/obj/effect/turf_decal/tile/green{ - dir = 1 - }, -/obj/effect/turf_decal/tile/green{ - dir = 8 - }, -/obj/machinery/camera{ - c_tag = "Hydroponics North" - }, -/obj/structure/disposalpipe/trunk{ - dir = 8 - }, -/obj/machinery/disposal/bin, -/turf/open/floor/plasteel/dark, -/area/hydroponics) "mQC" = ( /obj/machinery/airalarm{ dir = 1; @@ -26013,13 +26916,6 @@ /obj/effect/landmark/start/paramedic, /turf/open/floor/plasteel/white, /area/medical/medbay/zone3) -"nhO" = ( -/obj/machinery/airalarm/server{ - dir = 1; - pixel_y = -22 - }, -/turf/open/floor/circuit/telecomms/mainframe, -/area/tcommsat/server) "nij" = ( /obj/machinery/light{ dir = 1 @@ -26132,12 +27028,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /turf/open/floor/plating, /area/medical/genetics) -"nmY" = ( -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "nnj" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -26170,14 +27060,6 @@ }, /turf/open/floor/plasteel, /area/hydroponics) -"noB" = ( -/obj/effect/turf_decal/bot, -/mob/living/simple_animal/sloth/paperwork, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/quartermaster/storage) "noQ" = ( /obj/effect/spawner/structure/window/plasma/reinforced, /turf/open/floor/plating, @@ -26791,39 +27673,11 @@ /area/bridge) "nFM" = ( /obj/machinery/atmospherics/components/binary/pump{ - name = "Port Mix to Engine"; - dir = 1 + dir = 1; + name = "Port Mix to Engine" }, /turf/open/floor/plasteel, /area/engine/atmos) -"nGa" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 4 - }, -/obj/machinery/light{ - dir = 4 - }, -/obj/effect/turf_decal/bot, -/mob/living/simple_animal/bot/mulebot{ - beacon_freq = 1400; - home_destination = "QM #1"; - suffix = "#1" - }, -/obj/machinery/navbeacon{ - codes_txt = "delivery;dir=8"; - dir = 8; - freq = 1400; - location = "QM #1" - }, -/obj/machinery/power/apc{ - areastring = "/area/maintenance/starboard"; - dir = 4; - name = "Starboard Maintenance APC"; - pixel_x = 26 - }, -/turf/open/floor/pod/dark, -/area/maintenance/starboard) "nGd" = ( /obj/effect/turf_decal/delivery, /obj/machinery/portable_atmospherics/canister/toxins, @@ -26894,7 +27748,7 @@ "nIM" = ( /obj/structure/table/wood/poker, /obj/item/toy/cards/deck, -/obj/item/storage/pill_bottle/dice{ +/obj/item/storage/box/dice{ pixel_x = 8 }, /obj/structure/sign/poster/contraband/random{ @@ -26941,9 +27795,9 @@ "nJI" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/southleft{ + dir = 4; name = "Reception Desk"; - req_access_txt = "63"; - dir = 4 + req_access_txt = "63" }, /obj/structure/cable{ icon_state = "1-2" @@ -27181,7 +28035,6 @@ /obj/effect/turf_decal/tile/purple{ dir = 1 }, -/obj/structure/closet/crate/bin, /turf/open/floor/plasteel/white, /area/medical/genetics) "nSf" = ( @@ -27193,8 +28046,8 @@ /area/engine/engineering) "nSX" = ( /obj/machinery/atmospherics/components/binary/pump/on{ - name = "Gas to Cooling Loop"; - dir = 1 + dir = 1; + name = "Gas to Cooling Loop" }, /turf/open/floor/plating, /area/engine/atmospherics_engine) @@ -27495,6 +28348,12 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel, /area/maintenance/starboard) +"odf" = ( +/obj/structure/closet/bombcloset{ + anchored = 1 + }, +/turf/open/floor/plasteel/white, +/area/science/mixing) "odg" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 4 @@ -27645,9 +28504,6 @@ /turf/closed/wall, /area/quartermaster/sorting) "ohf" = ( -/obj/machinery/gateway{ - dir = 5 - }, /obj/effect/turf_decal/bot_white/left, /turf/open/floor/plasteel/dark, /area/teleporter) @@ -27765,9 +28621,6 @@ }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/engine/atmospherics_engine) -"oiX" = ( -/turf/closed/wall, -/area/crew_quarters/heads/hop) "oje" = ( /obj/structure/cable{ icon_state = "4-8" @@ -27870,7 +28723,7 @@ /turf/open/floor/carpet, /area/quartermaster/miningoffice) "old" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /turf/open/floor/wood, @@ -28206,7 +29059,9 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/structure/disposalpipe/segment, +/obj/structure/disposalpipe/sorting/mail/flip{ + sortType = 23 + }, /turf/open/floor/plasteel/white, /area/medical/genetics) "ouE" = ( @@ -28541,7 +29396,7 @@ /turf/open/floor/carpet, /area/crew_quarters/heads/hop) "oGU" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/wood, @@ -28745,23 +29600,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/plasteel/dark, /area/ai_monitored/turret_protected/ai_upload_foyer) -"oLT" = ( -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/machinery/light{ - dir = 1 - }, -/obj/item/radio/intercom{ - pixel_y = 25 - }, -/turf/open/floor/plasteel/white/corner{ - dir = 4 - }, -/area/hallway/secondary/exit/departure_lounge) "oME" = ( /obj/structure/cable{ icon_state = "4-8" @@ -29361,8 +30199,8 @@ /area/quartermaster/storage) "pfb" = ( /obj/machinery/atmospherics/components/binary/pump/on{ - name = "Gas to Cooling Loop"; - dir = 1 + dir = 1; + name = "Gas to Cooling Loop" }, /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -29582,13 +30420,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"pkh" = ( -/mob/living/simple_animal/hostile/retaliate/goat{ - name = "Pete" - }, -/obj/effect/landmark/event_spawn, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/kitchen) "pkJ" = ( /turf/open/floor/wood{ icon_state = "wood-broken6" @@ -29612,7 +30443,7 @@ c_tag = "Courtroom East"; dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "applebush" }, /turf/open/floor/wood, @@ -30077,10 +30908,10 @@ /area/ai_monitored/security/armory) "pvY" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on{ + dir = 1; external_pressure_bound = 140; name = "killroom vent"; - pressure_checks = 0; - dir = 1 + pressure_checks = 0 }, /turf/open/floor/circuit/telecomms, /area/science/xenobiology) @@ -30313,20 +31144,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/central) -"pCj" = ( -/obj/structure/sink{ - dir = 8; - pixel_x = -12; - pixel_y = 2 - }, -/obj/structure/mirror{ - pixel_x = -28 - }, -/obj/structure/urinal{ - pixel_y = 32 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/dorms) "pCo" = ( /obj/machinery/atmospherics/pipe/simple/orange/visible{ dir = 9 @@ -30631,9 +31448,9 @@ dir = 4 }, /obj/machinery/turnstile{ + dir = 8; name = "Genpop Exit Turnstile"; - req_access_txt = "70"; - dir = 8 + req_access_txt = "70" }, /obj/machinery/door/firedoor/border_only{ dir = 8; @@ -30919,12 +31736,6 @@ }, /turf/open/floor/plasteel, /area/quartermaster/storage) -"pUz" = ( -/obj/structure/disposalpipe/junction/yjunction{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/fore) "pUP" = ( /obj/machinery/door/airlock/public/glass{ name = "Chapel" @@ -31093,15 +31904,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"qbh" = ( -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/machinery/light{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) "qbr" = ( /obj/effect/turf_decal/tile/red{ dir = 4 @@ -31826,8 +32628,8 @@ }, /obj/machinery/button/ignition{ id = "testigniter"; - pixel_y = -30; - pixel_x = -1 + pixel_x = -1; + pixel_y = -30 }, /obj/structure/disposalpipe/trunk{ dir = 1 @@ -31887,13 +32689,6 @@ }, /turf/open/floor/plating/asteroid/snow/icemoon, /area/icemoon/surface/outdoors) -"qAq" = ( -/obj/machinery/quantumpad{ - map_pad_id = "5"; - map_pad_link_id = "6" - }, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) "qAx" = ( /obj/structure/disposalpipe/segment{ dir = 9 @@ -32018,9 +32813,9 @@ /area/maintenance/bar) "qEz" = ( /obj/machinery/door/window/brigdoor/security/cell{ + dir = 1; id = "Cell 3"; - name = "Cell 3"; - dir = 1 + name = "Cell 3" }, /obj/effect/turf_decal/vg_decals/numbers/three, /obj/machinery/door/poddoor/preopen{ @@ -32100,8 +32895,8 @@ /area/hallway/secondary/exit/departure_lounge) "qGt" = ( /obj/structure/bodycontainer/crematorium{ - id = "crematoriumChapel"; - dir = 8 + dir = 8; + id = "crematoriumChapel" }, /obj/machinery/button/crematorium{ id = "crematoriumChapel"; @@ -32163,7 +32958,7 @@ /turf/open/floor/carpet, /area/crew_quarters/dorms) "qHO" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -32353,7 +33148,7 @@ /area/bridge) "qMN" = ( /obj/structure/table, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel/grimy, /area/crew_quarters/fitness/recreation) "qNB" = ( @@ -32952,8 +33747,8 @@ "rgQ" = ( /obj/machinery/camera{ c_tag = "Xenobiology Test Chamber"; - network = list("xeno","rd"); - dir = 4 + dir = 4; + network = list("xeno","rd") }, /turf/open/floor/engine, /area/science/xenobiology) @@ -32971,7 +33766,7 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/plasteel, /area/crew_quarters/fitness) "rhX" = ( @@ -33374,7 +34169,6 @@ /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 4 }, -/obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plasteel/white, /area/science/misc_lab) "rqE" = ( @@ -33719,8 +34513,8 @@ }, /obj/machinery/camera{ c_tag = "AI Chamber - Core"; - network = list("aicore"); - dir = 4 + dir = 4; + network = list("aicore") }, /turf/open/floor/circuit/off, /area/ai_monitored/turret_protected/ai) @@ -33787,35 +34581,6 @@ }, /turf/open/floor/plasteel, /area/engine/engineering) -"rFQ" = ( -/obj/structure/table/reinforced, -/mob/living/simple_animal/parrot/Poly, -/obj/item/clothing/glasses/meson{ - pixel_y = 4 - }, -/obj/item/cartridge/atmos, -/obj/item/cartridge/engineering{ - pixel_x = -3; - pixel_y = 2 - }, -/obj/item/cartridge/engineering{ - pixel_x = -3; - pixel_y = 2 - }, -/obj/item/cartridge/engineering{ - pixel_x = -3; - pixel_y = 2 - }, -/obj/item/radio/intercom{ - dir = 4; - name = "Station Intercom (General)"; - pixel_x = 27 - }, -/obj/machinery/keycard_auth{ - pixel_y = -28 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/heads/chief) "rGc" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 6 @@ -33839,9 +34604,9 @@ dir = 4 }, /obj/machinery/turnstile{ + dir = 8; name = "Genpop Exit Turnstile"; - req_access_txt = "70"; - dir = 8 + req_access_txt = "70" }, /obj/machinery/door/firedoor/border_only{ dir = 4; @@ -34076,6 +34841,10 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) +"rQB" = ( +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plasteel/white, +/area/science/mixing) "rQH" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/simple/supply/hidden, @@ -34180,7 +34949,7 @@ /turf/open/floor/plasteel, /area/engine/engineering) "rUd" = ( -/turf/open/openspace/icemoon, +/turf/open/transparent/openspace/icemoon, /area/science/mixing) "rUl" = ( /obj/structure/cable{ @@ -34308,10 +35077,6 @@ }, /turf/open/floor/plasteel/dark, /area/medical/morgue) -"rYN" = ( -/obj/structure/chair/stool, -/turf/open/floor/carpet, -/area/chapel/main) "rYQ" = ( /obj/machinery/atmospherics/pipe/heat_exchanging/simple{ dir = 10 @@ -34356,7 +35121,7 @@ /area/engine/engineering) "saN" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel, @@ -34529,16 +35294,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"seR" = ( -/obj/machinery/airalarm{ - dir = 8; - pixel_x = 24 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "seZ" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{ dir = 6 @@ -34795,15 +35550,6 @@ /obj/machinery/computer/card, /turf/open/floor/wood, /area/crew_quarters/heads/captain) -"soN" = ( -/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ - dir = 1 - }, -/obj/effect/turf_decal/tile/yellow{ - dir = 4 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/port) "spa" = ( /obj/structure/disposalpipe/segment{ dir = 10 @@ -34847,7 +35593,7 @@ dir = 8 }, /obj/effect/turf_decal/tile/blue, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/dark, @@ -35312,16 +36058,6 @@ /obj/effect/turf_decal/stripes/corner, /turf/open/floor/engine, /area/engine/engineering) -"sIn" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/door/airlock/external{ - req_one_access_txt = "13,8" - }, -/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, -/turf/open/floor/plating, -/area/maintenance/port/fore) "sIT" = ( /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/pod/dark, @@ -35405,9 +36141,6 @@ /turf/open/floor/plating, /area/hallway/secondary/exit/departure_lounge) "sLr" = ( -/obj/machinery/gateway{ - dir = 6 - }, /obj/effect/turf_decal/bot_white/right, /obj/effect/turf_decal/stripes/corner{ dir = 1 @@ -35663,7 +36396,7 @@ /turf/open/floor/plasteel/white, /area/medical/medbay/central) "sTq" = ( -/turf/open/openspace/icemoon, +/turf/open/transparent/openspace/icemoon, /area/engine/atmospherics_engine) "sTz" = ( /obj/effect/turf_decal/bot_white, @@ -36250,7 +36983,7 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/plasteel/dark, @@ -36575,9 +37308,9 @@ /obj/effect/turf_decal/delivery, /obj/structure/table/reinforced, /obj/machinery/door/window/eastleft{ + dir = 8; name = "Hydroponics Desk"; - req_access_txt = "35"; - dir = 8 + req_access_txt = "35" }, /obj/machinery/door/firedoor/border_only{ dir = 8; @@ -36983,7 +37716,6 @@ /area/icemoon/surface/outdoors) "tDO" = ( /obj/machinery/atmospherics/components/unary/portables_connector/visible, -/obj/machinery/portable_atmospherics/canister/toxins, /obj/machinery/computer/security/telescreen{ name = "Test Chamber Monitor"; network = list("test"); @@ -37103,8 +37835,8 @@ }, /obj/machinery/camera{ c_tag = "Genetics Research"; - network = list("ss13","medbay"); - dir = 8 + dir = 8; + network = list("ss13","medbay") }, /turf/open/floor/plasteel/white, /area/medical/genetics) @@ -37173,18 +37905,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/carpet, /area/hallway/secondary/exit/departure_lounge) -"tJL" = ( -/obj/structure/cable{ - icon_state = "2-4" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden{ - dir = 6 - }, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) "tKa" = ( /obj/machinery/door/airlock/security/glass{ id_tag = "innerbrig"; @@ -37277,9 +37997,9 @@ /obj/machinery/button/door{ id = "Secure Brig Control"; name = "Brig Control Shutters"; + pixel_x = -6; pixel_y = -3; - req_access_txt = "2"; - pixel_x = -6 + req_access_txt = "2" }, /turf/open/floor/plasteel/dark, /area/security/warden) @@ -37443,24 +38163,6 @@ }, /turf/open/floor/plasteel, /area/hallway/secondary/exit/departure_lounge) -"tQd" = ( -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/obj/structure/closet/secure_closet/security/engine, -/obj/item/radio/intercom{ - pixel_y = -26 - }, -/obj/machinery/camera{ - c_tag = "Security Post - Cargo"; - dir = 1 - }, -/turf/open/floor/plasteel, -/area/security/checkpoint/supply) "tQv" = ( /obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ @@ -37707,11 +38409,6 @@ }, /turf/open/floor/plasteel, /area/science/robotics/mechbay) -"tWx" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "tXn" = ( /obj/structure/cable{ icon_state = "4-8" @@ -38025,23 +38722,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/carpet, /area/crew_quarters/dorms) -"ugr" = ( -/obj/machinery/button/door{ - id = "Bath1"; - name = "Door Bolt Control"; - normaldoorcontrol = 1; - pixel_x = 24; - pixel_y = -5; - specialfunctions = 4 - }, -/obj/machinery/shower{ - pixel_y = 20 - }, -/obj/machinery/light/small{ - dir = 8 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/dorms) "uha" = ( /obj/structure/cable{ icon_state = "4-8" @@ -38399,8 +39079,8 @@ "uuY" = ( /obj/machinery/camera{ c_tag = "Toxins Lab West"; - network = list("ss13","rd"); - dir = 4 + dir = 4; + network = list("ss13","rd") }, /obj/structure/table/reinforced, /obj/item/assembly/prox_sensor{ @@ -38791,9 +39471,9 @@ pixel_y = 23 }, /obj/machinery/door/window/southright{ + dir = 8; name = "Bar Door"; - req_one_access_txt = "25;28"; - dir = 8 + req_one_access_txt = "25;28" }, /obj/machinery/door/firedoor/border_only{ dir = 8; @@ -38945,8 +39625,8 @@ dir = 4 }, /obj/machinery/computer/security/telescreen/prison{ - pixel_x = 29; - dir = 8 + dir = 8; + pixel_x = 29 }, /turf/open/floor/plasteel/cult, /area/lawoffice) @@ -39249,8 +39929,8 @@ name = "supply dock loading door" }, /obj/machinery/conveyor{ - id = "QMLoad2"; - dir = 1 + dir = 1; + id = "QMLoad2" }, /turf/open/floor/plating, /area/quartermaster/storage) @@ -39353,8 +40033,8 @@ dir = 8 }, /obj/structure/chair{ - name = "Judge"; - dir = 4 + dir = 4; + name = "Judge" }, /turf/open/floor/wood, /area/security/courtroom) @@ -39697,8 +40377,8 @@ /area/security/checkpoint/supply) "vgX" = ( /obj/machinery/conveyor{ - id = "QMLoad2"; - dir = 1 + dir = 1; + id = "QMLoad2" }, /turf/open/floor/plasteel, /area/quartermaster/storage) @@ -39826,16 +40506,6 @@ /obj/machinery/meter, /turf/open/floor/engine, /area/engine/engineering) -"vlz" = ( -/obj/structure/urinal{ - pixel_y = 32 - }, -/obj/item/radio/intercom{ - name = "Station Intercom (General)"; - pixel_x = 30 - }, -/turf/open/floor/plasteel/freezer, -/area/crew_quarters/dorms) "vlC" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{ dir = 1 @@ -40078,8 +40748,8 @@ }, /obj/machinery/button/ignition{ id = "Incinerator"; - pixel_y = 35; - pixel_x = -1 + pixel_x = -1; + pixel_y = 35 }, /turf/open/floor/plasteel, /area/engine/atmospherics_engine) @@ -40098,9 +40768,6 @@ /turf/open/floor/plasteel, /area/engine/engineering) "vse" = ( -/obj/machinery/gateway{ - dir = 10 - }, /obj/machinery/light{ dir = 8 }, @@ -41640,13 +42307,6 @@ }, /turf/open/floor/engine, /area/engine/engineering) -"wie" = ( -/obj/machinery/gateway{ - dir = 1 - }, -/obj/effect/turf_decal/bot_white, -/turf/open/floor/plasteel/dark, -/area/teleporter) "wje" = ( /turf/open/floor/plasteel, /area/hallway/primary/port) @@ -41996,8 +42656,8 @@ "wtt" = ( /obj/structure/table/wood, /obj/item/flashlight/lamp/green{ - pixel_y = 13; - pixel_x = -7 + pixel_x = -7; + pixel_y = 13 }, /obj/item/camera/detective, /obj/item/hand_labeler{ @@ -42005,8 +42665,8 @@ }, /obj/item/storage/briefcase, /obj/item/storage/secure/safe{ - pixel_y = 36; - pixel_x = 6 + pixel_x = 6; + pixel_y = 36 }, /turf/open/floor/carpet, /area/security/detectives_office) @@ -42942,9 +43602,6 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) "xcd" = ( -/obj/machinery/gateway{ - dir = 4 - }, /obj/effect/turf_decal/bot_white, /turf/open/floor/plasteel/dark, /area/teleporter) @@ -43001,24 +43658,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel, /area/hallway/primary/central) -"xdr" = ( -/obj/machinery/camera{ - c_tag = "Head of Security's Office"; - dir = 8 - }, -/obj/structure/bed/dogbed{ - desc = "A comfy-looking pet bed. You can even strap your pet in, in case the gravity turns off."; - name = "pet bed" - }, -/mob/living/simple_animal/hostile/retaliate/bat/secbat{ - desc = "An adorable fruit bat with a cute little hat, may or may not have a reputation for biting out eyeballs, or at least that's what the HoS'd tell you."; - name = "Colonel Chomps" - }, -/obj/item/storage/secure/safe/HoS{ - pixel_x = 35 - }, -/turf/open/floor/carpet, -/area/crew_quarters/heads/hos) "xdD" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/visible{ dir = 4 @@ -43145,9 +43784,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"xhH" = ( -/turf/closed/wall/r_wall, -/area/hallway/primary/central) "xhV" = ( /obj/effect/turf_decal/bot_white, /obj/structure/window/reinforced{ @@ -43208,7 +43844,7 @@ /obj/structure/cable{ icon_state = "0-4" }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/machinery/power/apc{ @@ -43227,20 +43863,6 @@ /obj/machinery/vending/snack/random, /turf/open/floor/plasteel, /area/crew_quarters/fitness) -"xlg" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/machinery/camera{ - c_tag = "Medbay Cryogenics"; - network = list("ss13","medbay") - }, -/turf/open/floor/plasteel/white, -/area/medical/medbay/central) "xlm" = ( /obj/machinery/vending/wardrobe/atmos_wardrobe, /turf/open/floor/plasteel, @@ -43344,11 +43966,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/grimy, /area/crew_quarters/bar) -"xou" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on, -/obj/machinery/computer/shuttle/snow_taxi, -/turf/open/floor/plasteel, -/area/quartermaster/miningdock) "xow" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden, /obj/machinery/door/airlock/security/glass{ @@ -43522,18 +44139,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/visible, /turf/open/floor/plating, /area/maintenance/department/electrical) -"xve" = ( -/obj/structure/cable{ - icon_state = "1-2" - }, -/obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/obj/effect/turf_decal/tile/bar, -/obj/structure/disposalpipe/segment, -/turf/open/floor/plasteel, -/area/hallway/primary/aft) "xvj" = ( /obj/structure/cable{ icon_state = "4-8" @@ -43707,10 +44312,6 @@ }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) -"xCr" = ( -/obj/effect/landmark/blobstart, -/turf/open/floor/plating, -/area/medical/medbay/central) "xCC" = ( /obj/effect/turf_decal/tile/red{ dir = 1 @@ -43876,9 +44477,6 @@ /turf/open/floor/plating/snowed/smoothed/icemoon, /area/engine/atmos) "xHk" = ( -/obj/machinery/gateway{ - dir = 9 - }, /obj/effect/turf_decal/bot_white/right, /turf/open/floor/plasteel/dark, /area/teleporter) @@ -44114,8 +44712,8 @@ areastring = "/area/engine/engineering"; dir = 8; name = "Engineering APC"; - pixel_y = -1; - pixel_x = -27 + pixel_x = -27; + pixel_y = -1 }, /obj/machinery/firealarm{ dir = 1; @@ -44340,10 +44938,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/central) -"xXX" = ( -/obj/structure/reagent_dispensers/watertank, -/turf/open/floor/plating, -/area/maintenance/central) "xYD" = ( /obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden, /turf/open/floor/carpet, @@ -44398,10 +44992,6 @@ }, /turf/open/floor/plating/snowed/smoothed/icemoon, /area/icemoon/surface/outdoors) -"yae" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/on, -/turf/open/floor/plasteel, -/area/hallway/primary/central) "ybp" = ( /obj/structure/chair{ dir = 8 @@ -44682,14 +45272,6 @@ /area/medical/medbay/central) "ykk" = ( /obj/machinery/atmospherics/pipe/simple/supply/hidden, -/obj/machinery/door/firedoor/border_only{ - dir = 1; - name = "north facing firelock" - }, -/obj/machinery/door/airlock/research{ - name = "Toxins Lab"; - req_access_txt = "7" - }, /obj/structure/disposalpipe/segment, /turf/open/floor/plasteel/white, /area/science/mixing) @@ -56146,7 +56728,7 @@ won evJ fsQ mxo -nhO +pTw apJ apJ apJ @@ -56915,7 +57497,7 @@ avT avT gLH xHk -jPP +xcd vse mSs qQH @@ -57171,7 +57753,7 @@ bBh avT avT gLH -wie +xcd ePa jrR nTQ @@ -58980,8 +59562,8 @@ ash ash nQr ash -ash -ash +tmO +tmO wje ahC nOK @@ -59237,9 +59819,9 @@ rbW aoR apO ash -arG -ash -qbh +abq +tmO +abu auY hEf eGO @@ -59494,8 +60076,8 @@ rRV aoT pWz ash -xCr -ash +abr +abt lxF rbo ioG @@ -59748,11 +60330,11 @@ tUi ash tVS anm -jiV -ash -ash +abH ash ash +tmO +tmO dXR hOA irg @@ -60012,7 +60594,7 @@ arI syN atr rbo -jwo +aaF azq azq azq @@ -60251,7 +60833,7 @@ ash cxX sXJ sXJ -hnB +aal qhU vCE gIm @@ -61311,7 +61893,7 @@ aPB oqL aLG aNk -aOl +abM aPA avT avT @@ -62565,7 +63147,7 @@ vvH vvH fsA gZX -xlg +abE jUu xGP anm @@ -63348,7 +63930,7 @@ mAx ndm rQN aoX -soN +aaB ojv oTu oTu @@ -64631,7 +65213,7 @@ aoX ali yds yds -aon +abI aoX rJw tkr @@ -64866,10 +65448,10 @@ avT avT xUL rTG -sIn +abC kxU sdH -sIn +abD kxU pyw nYZ @@ -65147,7 +65729,7 @@ yds yds qWL aoX -gsM +abJ tkr iPX rQJ @@ -65672,7 +66254,7 @@ ayA sNK xmo rqW -mzB +abL rQJ szG aHG @@ -66419,7 +67001,7 @@ xUL xUL xUL tmO -fYx +aaA oDm tmO rhX @@ -66689,7 +67271,7 @@ nrJ iAR rik xWq -aAL +abK gxi wEP wJH @@ -67718,7 +68300,7 @@ xWq xWq xWq tmO -wje +aaC wje tmO ydp @@ -68232,7 +68814,7 @@ xUL xUL xUL tmO -wje +aaD iPX tmO tmO @@ -68490,7 +69072,7 @@ xUL xUL usE buO -wje +aaE cpC tmO ydp @@ -71358,7 +71940,7 @@ avT kfv kfv ilb -ifQ +aam rlG wSb wav @@ -72140,7 +72722,7 @@ wDk pmK dbB nxv -eZn +abW xBv nQM lZi @@ -74713,7 +75295,7 @@ oJF piv nre bWR -xdr +aan uKb fKC rVN @@ -75233,7 +75815,7 @@ cBD bQj gCG sdN -xXX +acd ubL diH uPJ @@ -75483,7 +76065,7 @@ bDr alG fmt cBD -cbz +aca jae bNS pST @@ -75748,7 +76330,7 @@ giT bZF xkT bVR -rYN +acf qOb bSd bXO @@ -77263,7 +77845,7 @@ xZg xZg xZg uBa -eeh +abN grV cTD cTD @@ -77273,7 +77855,7 @@ cTD grV lbp knn -eOK +aaW bBz lbp cBD @@ -77493,7 +78075,7 @@ gky ptY cgH ktw -xZL +aaG lzB avT avT @@ -77528,30 +78110,30 @@ vPQ vPQ vPQ bwu +aaR +aaT +aaX +aaY +abb lhQ -yae -kPj -bBB -lhQ -lhQ -vPQ -cGQ -vPQ -vPQ +abV +abf +abb +abb bNn vPQ qQt vPQ bJF bVX -cGQ +abj hhz vPQ vPQ vPQ haj pjn -tNf +abl sAw vPQ mdG @@ -78264,7 +78846,7 @@ cPI kxP vAs ktw -xZL +aaI lzB avT avT @@ -78279,7 +78861,7 @@ wxT bUP fLK rmN -oLT +aaK ljL uBa uBa @@ -78300,19 +78882,19 @@ fXU ffm jBl fmw -tWx +abT pBU reS +abc lhQ -lhQ -ceA -vun -ceA -ceA -ceA -seR -ceA -ceA +abd +abg +abd +abd +abd +abi +abd +abd bmP bQs vun @@ -78324,7 +78906,7 @@ ceA vun lhQ lhQ -ceA +abm bPc ceA bUL @@ -78548,7 +79130,7 @@ piX hJw kop uBa -fuy +abO bwx bwx bwx @@ -79062,7 +79644,7 @@ fWE wbE wbE uBa -rcH +abP bwx iSo bpM @@ -80608,8 +81190,8 @@ tHU bBL guv bpO -bDR -gfF +aaL +abR bDR jOl bBL @@ -80621,7 +81203,7 @@ bDW bEl bDE bFK -bJC +rQB prL fiN hmX @@ -80847,13 +81429,13 @@ iaO dnm hHC dnm -unA +aaJ unA unA unA unA dnm -unA +aaJ dnm unA unA @@ -80870,7 +81452,7 @@ bsx bLT bLT bLT -xhH +aaV rle cSG bCQ @@ -80878,7 +81460,7 @@ bDW bIn bQP wOK -bJC +fjU gzZ gSu ipY @@ -81125,7 +81707,7 @@ vAs vAs vAs bLT -fnu +aaN bxR mPM ohK @@ -81145,7 +81727,7 @@ bQC gsK wuB pyI -bXW +acg eqZ wpN vOV @@ -81303,7 +81885,7 @@ dvs mtP naE mtP -mtP +aaU nOY mtP naE @@ -81382,7 +81964,7 @@ vAs vAs vAs bLT -xou +aaQ jkL fcJ cqd @@ -81555,7 +82137,7 @@ ydp avT avT iHM -iHM +pgp pgp pgp pgp @@ -81649,7 +82231,7 @@ bDW mOv jOB lYy -bJC +fjU ihE fJO eex @@ -81810,11 +82392,11 @@ xUL ydp ydp ydp -avT bmX avT pgp -pCj +aab +dZV dZV gLk pgp @@ -81900,13 +82482,13 @@ bEi bEi lbp bAs -nmY +aaZ bCL bDW gpp wbT nHi -bJC +fjU rDA fjU dvO @@ -82069,9 +82651,9 @@ ydp ydp ydp avT -avT pgp -hGM +aac +gLk gLk gLk pgp @@ -82163,7 +82745,7 @@ bEa kxj aaw rqx -qJV +fjU bKL fJO jKT @@ -82325,10 +82907,10 @@ ydp ydp ydp ydp -ydp avT pgp -vlz +aab +aad gLk fBs pgp @@ -82419,8 +83001,8 @@ aGl bEa pHl aaw -gKB -qJV +abh +odf fjU fjU fjU @@ -82583,7 +83165,7 @@ ydp ydp ydp avT -avT +pgp pgp pgp pgp @@ -82680,7 +83262,7 @@ cBt tRe gPE syy -gPE +dBA qJV goM gxF @@ -82842,7 +83424,7 @@ ydp avT ydp pgp -ugr +aae pBh gLk pgp @@ -82941,7 +83523,7 @@ tRe tRe tRe bWf -bVa +ihL kXG sqx owj @@ -83101,7 +83683,7 @@ ydp pgp pgp pgp -eEa +aaf pgp pgp pgp @@ -83374,8 +83956,8 @@ skZ mSt geO cQv -nGa -fpW +aaj +aak oyf dzS dSQ @@ -83622,7 +84204,7 @@ mWy pgp uEG dKn -gEz +abA pax sdq iux @@ -83706,13 +84288,13 @@ dFp wTK tDY oXn -cSg +abY tRe egg cbQ iXG bWf -bVa +acc bVa bWf ftV @@ -84207,7 +84789,7 @@ bvq oCZ lxV dGP -evr +abS lxV hJE cmC @@ -84651,7 +85233,7 @@ iML kFr vuO vaj -rTv +aau mSt dWt fyr @@ -85402,7 +85984,7 @@ xUL xUL xUL kVO -bQf +aao qgm qgm qgm @@ -85419,7 +86001,7 @@ xJB hyK vVN qeL -oiX +abn trU knI oIb @@ -85661,7 +86243,7 @@ xUL qaO gct sGE -tJL +aaq ixf ixf giv @@ -86194,7 +86776,7 @@ iqZ seG tYT qKA -cSv +aav pJS pJS tQG @@ -86443,8 +87025,8 @@ now mKv sAh sAh -sAh -urI +acb +aar uEz uEz hrS @@ -86687,7 +87269,7 @@ xUL xUL xUL kVO -qAq +aap acq fJc lfy @@ -86700,7 +87282,7 @@ qss mKv sAh sAh -sAh +acb urI qkO uEz @@ -87208,13 +87790,13 @@ wAx wuQ vnM wAx -mQo +abv mbE qss sYv sAh sAh -sAh +acb urI uoV uEz @@ -87471,7 +88053,7 @@ qss sYv sAh sAh -sAh +acb urI uoV uEz @@ -87485,7 +88067,7 @@ mhq bNF wIA hTO -noB +aai wIA kti nrg @@ -88491,7 +89073,7 @@ hAw skK vKa gdg -pkh +aaa loM vKa nsv @@ -88512,7 +89094,7 @@ pJS leq qxT wIA -iCO +abp pJS pJS pJS @@ -89016,12 +89598,12 @@ fTy jvb xZp dVr -gRS +abx msK cKk dNB rmV -dDf +abB gaf pMD shN @@ -89274,7 +89856,7 @@ stW iKV hFj oNv -guV +abz cKk meG mcU @@ -90307,7 +90889,7 @@ jHT rkd mcU rNS -vyf +aax vyf hLQ nsf @@ -90324,7 +90906,7 @@ gwY pdD hMM qKP -tQd +abF jIt avT avT @@ -90570,7 +91152,7 @@ vkk qSi vkk vkk -pUz +aay pqj mcU pqj @@ -91063,7 +91645,7 @@ pCU ixf kcn llu -xve +abw gJP eGi mIe @@ -91341,7 +91923,7 @@ uqy yes iqH iqH -iqH +aaz iqH yes iqH @@ -92097,10 +92679,10 @@ gcY xop fbq lFv -dvh +aag gkl eOt -eFy +aby rYc hbb rkd @@ -92360,7 +92942,7 @@ cKk cKk cKk cKk -mkm +aat lpl xcA srk @@ -93904,7 +94486,7 @@ fPd eYu xOj jKF -jKb +abo wdR sda pAC @@ -94929,7 +95511,7 @@ wTe sPt iBL bnU -fNd +aas bDg fKE bnU @@ -96982,7 +97564,7 @@ ulr jJb xfH puE -rFQ +aah iiY piR tty @@ -97499,7 +98081,7 @@ xUL xUL dKF ijZ -ijZ +lwl bnU oJa cNE @@ -99546,11 +100128,11 @@ xUL xUL xUL xUL -xUL -xUL -xUL rGc jls +rGc +cly +jls odg ucC gUL @@ -99802,12 +100384,12 @@ bum bum bum bum -bum -bum -bum rGc tdX tdX +tdX +cly +tdX jPj ucC gUL @@ -100059,12 +100641,12 @@ bum bum bum bum -bum -bum -bum dQW tdX tdX +tdX +cly +tdX jls ucC gUL @@ -100316,12 +100898,12 @@ bum bum bum bum -bum -bum -bum rGc tdX tdX +tdX +cly +tdX jPj ucC cfs @@ -100573,12 +101155,12 @@ bum bum bum bum -bum -bum -bum dQW tdX tdX +tdX +cly +tdX jls ucC cfs @@ -100830,11 +101412,11 @@ bum bum bum bum -bum -bum -bum -xUL +rGc +jPj dQW +jPj +rGc flw flw lFN @@ -101087,11 +101669,11 @@ bum bum bum bum -bum -bum -bum -xUL -xUL +dQW +cly +cly +cly +jPj dQW jPj bnU @@ -101344,9 +101926,9 @@ bum bum bum bum -bum -bum -bum +xUL +xUL +xUL bDA bYY bYY @@ -101601,9 +102183,9 @@ bum bum bum bum -bum -bum -bum +xUL +xUL +xUL gjW xUL xUL @@ -101858,9 +102440,9 @@ bum bum bum bum -bum -bum -bum +xUL +xUL +xUL xUL xUL bum @@ -102115,9 +102697,9 @@ bum bum bum bum -bum -bum -bum +xUL +xUL +xUL xUL xUL sTq diff --git a/_maps/map_files/debug/multiz.dmm b/_maps/map_files/debug/multiz.dmm index 3f7cacd1a8..5a18682129 100644 --- a/_maps/map_files/debug/multiz.dmm +++ b/_maps/map_files/debug/multiz.dmm @@ -102,7 +102,7 @@ /turf/open/floor/plasteel, /area/engine/gravity_generator) "au" = ( -/turf/open/openspace, +/turf/open/transparent/openspace, /area/space) "av" = ( /obj/structure/stairs{ @@ -1300,7 +1300,7 @@ "dO" = ( /obj/structure/table, /obj/machinery/light, -/obj/item/twohanded/fireaxe, +/obj/item/fireaxe, /obj/item/extinguisher, /turf/open/floor/plasteel, /area/storage/primary) @@ -1407,7 +1407,7 @@ }, /area/hallway/secondary/service) "eC" = ( -/turf/open/openspace, +/turf/open/transparent/openspace, /area/maintenance/department/bridge) "eD" = ( /obj/effect/turf_decal/stripes/asteroid/line{ @@ -1542,7 +1542,7 @@ /turf/open/floor/plating, /area/space) "iu" = ( -/turf/open/openspace, +/turf/open/transparent/openspace, /area/hallway/secondary/service) "iK" = ( /turf/open/floor/plasteel{ @@ -1593,7 +1593,7 @@ }, /area/hallway/secondary/service) "nx" = ( -/turf/open/openspace, +/turf/open/transparent/openspace, /area/space/nearstation) "nz" = ( /obj/machinery/light{ @@ -1633,7 +1633,7 @@ /turf/open/floor/plating, /area/maintenance/department/bridge) "qo" = ( -/turf/open/openspace, +/turf/open/transparent/openspace, /area/engine/storage) "qR" = ( /obj/effect/turf_decal/stripes/white/line{ @@ -1646,7 +1646,7 @@ /obj/machinery/light{ dir = 8 }, -/turf/open/openspace, +/turf/open/transparent/openspace, /area/engine/storage) "sh" = ( /turf/open/floor/plasteel{ @@ -1746,7 +1746,7 @@ /area/construction) "Bk" = ( /obj/structure/grille, -/turf/open/openspace, +/turf/open/transparent/openspace, /area/space/nearstation) "Bm" = ( /obj/machinery/light{ @@ -1876,7 +1876,7 @@ "Ob" = ( /obj/structure/lattice, /obj/structure/grille, -/turf/open/openspace, +/turf/open/transparent/openspace, /area/space/nearstation) "Og" = ( /obj/machinery/airalarm/directional/north, diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index f82ba2d735..020017c3fe 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -58,7 +58,7 @@ /obj/structure/table/wood{ layer = 3.3 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05"; pixel_y = 4 }, @@ -294,7 +294,7 @@ /area/holodeck/rec_center/winterwonderland) "aT" = ( /obj/structure/table/wood, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-05"; pixel_y = 10 }, @@ -1686,19 +1686,19 @@ /obj/item/melee/chainofcommand{ name = "chain whip" }, -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/holofloor/asteroid, /area/holodeck/rec_center/thunderdome1218) "ez" = ( /obj/structure/table/wood, /obj/item/scythe, -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/holofloor/asteroid, /area/holodeck/rec_center/thunderdome1218) "eA" = ( /obj/structure/table/wood, /obj/item/tailclub, -/obj/item/twohanded/spear, +/obj/item/spear, /turf/open/floor/holofloor/asteroid, /area/holodeck/rec_center/thunderdome1218) "eB" = ( @@ -2916,11 +2916,11 @@ /turf/open/floor/circuit/green/anim, /area/ctf) "hE" = ( -/obj/item/twohanded/ctf/blue, +/obj/item/ctf/blue, /turf/open/floor/circuit/green/anim, /area/ctf) "hF" = ( -/obj/item/twohanded/ctf/red, +/obj/item/ctf/red, /turf/open/floor/circuit/green/anim, /area/ctf) "hG" = ( @@ -4002,7 +4002,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/control) "ke" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -4106,7 +4106,7 @@ /turf/open/floor/plasteel, /area/centcom/supply) "kk" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral{ @@ -4211,7 +4211,7 @@ /turf/open/floor/plasteel/grimy, /area/centcom/control) "kB" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/firealarm{ @@ -4234,7 +4234,7 @@ /obj/structure/window/reinforced{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/grimy, @@ -4243,7 +4243,7 @@ /obj/structure/window/reinforced{ dir = 1 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/grimy, @@ -4284,13 +4284,13 @@ /obj/structure/window/reinforced{ dir = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel/grimy, /area/centcom/control) "kJ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/airalarm{ @@ -4733,7 +4733,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "lQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/firealarm{ @@ -5168,7 +5168,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "mL" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green{ @@ -5180,7 +5180,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "mM" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -5957,7 +5957,7 @@ /obj/machinery/status_display/ai{ pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-15"; pixel_x = -6; pixel_y = 12 @@ -6171,7 +6171,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "oy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -6517,7 +6517,7 @@ /turf/open/floor/plasteel/grimy, /area/centcom/ferry) "ph" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/light{ @@ -6751,7 +6751,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/control) "pw" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/structure/extinguisher_cabinet{ @@ -6998,13 +6998,13 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "qd" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/wood, /area/centcom/ferry) "qe" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light_switch{ @@ -7525,7 +7525,7 @@ /turf/open/floor/plasteel, /area/centcom/ferry) "rt" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/newscaster{ @@ -7550,7 +7550,7 @@ /turf/open/floor/wood, /area/centcom/ferry) "rv" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/light{ @@ -7732,7 +7732,7 @@ /turf/open/floor/grass, /area/centcom/control) "rL" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/extinguisher_cabinet{ @@ -8429,7 +8429,7 @@ /area/centcom/ferry) "tx" = ( /obj/structure/table/wood, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /turf/open/floor/plasteel/grimy, /area/centcom/ferry) "ty" = ( @@ -8611,7 +8611,7 @@ /turf/open/floor/plasteel, /area/centcom/ferry) "tJ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green{ @@ -8650,7 +8650,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "tO" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green{ @@ -8667,7 +8667,7 @@ /turf/closed/indestructible/riveted, /area/centcom/evac) "tS" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/stripes/line{ @@ -9109,7 +9109,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "uT" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral{ @@ -9139,7 +9139,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "uV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -10077,7 +10077,7 @@ /turf/open/floor/plating, /area/centcom/ferry) "xi" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/delivery, @@ -10147,7 +10147,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "xp" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green{ @@ -10159,7 +10159,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "xq" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green, @@ -10178,7 +10178,7 @@ /turf/open/floor/plating, /area/centcom/evac) "xs" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/stripes/line{ @@ -10217,7 +10217,7 @@ /area/wizard_station) "xy" = ( /obj/structure/table/wood/fancy, -/obj/item/storage/pill_bottle/dice{ +/obj/item/storage/box/dice{ icon_state = "magicdicebag" }, /turf/open/floor/carpet, @@ -10741,7 +10741,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "zd" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light{ @@ -11247,7 +11247,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "Am" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -11268,7 +11268,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "Ap" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/blue, @@ -11541,7 +11541,7 @@ /turf/open/floor/plasteel, /area/centcom/evac) "Ba" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/stripes/line, @@ -12161,7 +12161,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "Cw" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/power/apc{ @@ -12198,7 +12198,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "Cy" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/machinery/light, @@ -12219,7 +12219,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/ferry) "Cz" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/extinguisher_cabinet{ @@ -12616,7 +12616,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/evac) "Df" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/structure/extinguisher_cabinet{ @@ -13008,7 +13008,7 @@ /turf/open/floor/plasteel/dark, /area/centcom/control) "DV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green{ @@ -13017,7 +13017,7 @@ /turf/open/floor/plasteel, /area/centcom/control) "DW" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green, @@ -13490,6 +13490,9 @@ /obj/structure/table/wood, /obj/item/instrument/piano_synth, /obj/item/instrument/guitar, +/obj/structure/sign/painting{ + pixel_x = -32 + }, /turf/open/indestructible/hotelwood, /area/centcom/holding) "Fg" = ( @@ -13571,7 +13574,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Fs" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green{ @@ -13585,7 +13588,7 @@ }, /area/tdome/tdomeobserve) "Fu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green, @@ -13670,7 +13673,7 @@ /turf/open/floor/plasteel/white, /area/tdome/tdomeobserve) "FG" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red, @@ -13750,7 +13753,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "FQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green{ @@ -13794,6 +13797,9 @@ /turf/open/indestructible/hotelwood, /area/centcom/holding) "FX" = ( +/obj/structure/sign/painting{ + pixel_x = 32 + }, /turf/open/floor/plasteel/stairs, /area/centcom/holding) "FZ" = ( @@ -13848,7 +13854,7 @@ }, /area/tdome/tdomeobserve) "Gg" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/neutral{ @@ -13862,7 +13868,7 @@ }, /area/tdome/tdomeobserve) "Gh" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -13871,7 +13877,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Gi" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/red{ @@ -13884,7 +13890,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Gj" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/red, @@ -13913,7 +13919,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Gn" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green, @@ -13923,7 +13929,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Go" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green, @@ -13936,7 +13942,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Gp" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/green{ @@ -14421,6 +14427,9 @@ dir = 8 }, /obj/structure/musician/piano, +/obj/structure/sign/painting{ + pixel_x = -32 + }, /turf/open/indestructible/hotelwood, /area/centcom/holding) "Hk" = ( @@ -14876,7 +14885,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "HZ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral, @@ -14966,7 +14975,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeobserve) "Ig" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -15790,7 +15799,7 @@ /turf/open/floor/plasteel, /area/tdome/tdomeadmin) "JZ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/firealarm{ @@ -15822,7 +15831,7 @@ /turf/open/floor/plasteel/dark, /area/tdome/tdomeadmin) "Kc" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -16225,6 +16234,12 @@ dir = 1 }, /obj/structure/table/wood, +/obj/item/storage/crayons, +/obj/item/storage/crayons, +/obj/item/storage/crayons, +/obj/structure/sign/painting{ + pixel_x = -32 + }, /turf/open/indestructible/hotelwood, /area/centcom/holding) "KU" = ( @@ -16304,6 +16319,14 @@ /obj/item/storage/box/bodybags, /turf/open/floor/plasteel/white, /area/centcom/holding) +"Ll" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/easel, +/obj/item/canvas/twentythreeXtwentythree, +/turf/open/indestructible/hotelwood, +/area/centcom/holding) "Lm" = ( /obj/machinery/shower{ dir = 4 @@ -16808,6 +16831,22 @@ }, /turf/open/floor/plasteel, /area/centcom/supplypod/loading/two) +"NA" = ( +/obj/structure/window/reinforced{ + dir = 1 + }, +/obj/structure/table/wood, +/obj/item/canvas/twentythreeXtwentythree, +/obj/item/canvas/twentythreeXtwentythree, +/obj/item/canvas/twentythreeXtwentythree, +/obj/item/canvas/twentythreeXnineteen, +/obj/item/canvas/twentythreeXnineteen, +/obj/item/canvas/twentythreeXnineteen, +/obj/item/canvas/nineteenXnineteen, +/obj/item/canvas/nineteenXnineteen, +/obj/item/canvas/nineteenXnineteen, +/turf/open/indestructible/hotelwood, +/area/centcom/holding) "NE" = ( /obj/machinery/light{ dir = 4 @@ -16924,6 +16963,12 @@ }, /turf/open/floor/plasteel, /area/centcom/supplypod/loading/three) +"On" = ( +/obj/structure/sign/painting{ + pixel_x = 32 + }, +/turf/open/indestructible/hotelwood, +/area/centcom/holding) "Op" = ( /obj/structure/sink{ dir = 8; @@ -17249,6 +17294,10 @@ }, /turf/open/floor/mineral/titanium, /area/centcom/evac) +"Qc" = ( +/obj/effect/landmark/mafia_game_area, +/turf/open/space/basic, +/area/space) "Qe" = ( /turf/open/ai_visible, /area/ai_multicam_room) @@ -17577,7 +17626,7 @@ /turf/open/floor/wood, /area/centcom/holding) "RQ" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -17906,6 +17955,15 @@ /obj/machinery/light, /turf/open/floor/plasteel/freezer, /area/centcom/holding) +"TD" = ( +/obj/machinery/light{ + dir = 4 + }, +/obj/structure/sign/painting{ + pixel_x = 32 + }, +/turf/open/indestructible/hotelwood, +/area/centcom/holding) "TF" = ( /obj/effect/turf_decal/tile/red{ dir = 8 @@ -18850,7 +18908,7 @@ /turf/open/indestructible/binary, /area/space) "Zh" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/indestructible/hotelwood, @@ -45453,8 +45511,8 @@ Nd AE CV Sd -KT -Sd +Ll +CV Sd Sd Sd @@ -45710,7 +45768,7 @@ Nd QJ Sd Sd -KT +NA Sd Sd Sd @@ -46222,8 +46280,8 @@ Fh Fh Wl Sd -MR -Sd +TD +On FX Sd Sd @@ -58911,7 +58969,7 @@ aa aa aa aa -aa +Qc aa aa aa diff --git a/_maps/map_files/generic/City_of_Cogs.dmm b/_maps/map_files/generic/City_of_Cogs.dmm index 1195ad62c5..9ef765aa28 100644 --- a/_maps/map_files/generic/City_of_Cogs.dmm +++ b/_maps/map_files/generic/City_of_Cogs.dmm @@ -10,20 +10,10 @@ /obj/structure/grille/ratvar, /turf/open/indestructible/reebe_void, /area/reebe) -"ad" = ( -/obj/structure/lattice/clockwork, -/obj/item/clockwork/component/belligerent_eye/blind_eye, -/turf/open/indestructible/reebe_void, -/area/reebe) "ae" = ( /obj/structure/lattice/clockwork, /turf/open/indestructible/reebe_void, /area/reebe) -"af" = ( -/obj/structure/lattice/clockwork, -/obj/item/clockwork/component/geis_capacitor/antennae, -/turf/open/indestructible/reebe_void, -/area/reebe) "ag" = ( /obj/structure/lattice/catwalk/clockwork, /turf/open/indestructible/reebe_void, @@ -39,14 +29,6 @@ "aj" = ( /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"ak" = ( -/obj/structure/destructible/clockwork/massive/celestial_gateway, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) -"al" = ( -/obj/machinery/sleeper/clockwork, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) "an" = ( /obj/structure/noticeboard, /obj/item/paper/fluff/ruins/djstation{ @@ -64,10 +46,6 @@ }, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"aq" = ( -/obj/machinery/computer/camera_advanced/ratvar, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) "ar" = ( /obj/structure/closet/wardrobe/mixed, /turf/open/floor/clockwork/reebe, @@ -96,12 +74,6 @@ }, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"ax" = ( -/obj/structure/chair/brass{ - dir = 1 - }, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) "ay" = ( /obj/machinery/door/airlock/clockwork/brass{ name = "Dressing Room" @@ -109,7 +81,7 @@ /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) "az" = ( -/obj/structure/destructible/clockwork/heralds_beacon, +/obj/structure/destructible/clockwork/eminence_spire, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) "aA" = ( @@ -118,17 +90,6 @@ }, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"aB" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/construct_chassis/cogscarab, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) -"aC" = ( -/obj/machinery/sleeper/clockwork{ - dir = 1 - }, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) "aD" = ( /obj/machinery/door/airlock/clockwork/brass{ name = "Listening Station" @@ -149,15 +110,6 @@ opacity = 0 }, /area/reebe/city_of_cogs) -"aH" = ( -/obj/effect/landmark/servant_of_ratvar, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) -"aI" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/slab, -/turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) "aJ" = ( /obj/structure/table/reinforced/brass, /obj/item/screwdriver/brass, @@ -182,162 +134,22 @@ /obj/item/weldingtool/experimental/brass, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"aO" = ( -/obj/structure/lattice/catwalk/clockwork, -/obj/item/clockwork/component/belligerent_eye/lens_gem, -/turf/open/indestructible/reebe_void, -/area/reebe) -"aP" = ( -/obj/structure/lattice/catwalk/clockwork, -/obj/item/clockwork/component/hierophant_ansible/obelisk, -/turf/open/indestructible/reebe_void, -/area/reebe) -"aQ" = ( -/obj/structure/lattice/clockwork, -/obj/item/clockwork/alloy_shards/clockgolem_remains, -/turf/open/indestructible/reebe_void, -/area/reebe) -"aR" = ( -/obj/effect/landmark/city_of_cogs, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) "aS" = ( -/obj/effect/clockwork/servant_blocker{ - dir = 1 - }, -/obj/structure/lattice/catwalk/clockwork, -/turf/open/indestructible/reebe_void, -/area/reebe/city_of_cogs) -"aT" = ( -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"aU" = ( -/obj/structure/grille/ratvar, -/obj/structure/window/reinforced/clockwork/fulltile, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"aV" = ( -/obj/machinery/door/airlock/clockwork/brass, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"aW" = ( -/obj/item/clockwork/component/replicant_alloy/replication_plate, -/turf/open/indestructible/reebe_void/spawning/lattices, -/area/reebe) -"aX" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/belligerent_eye, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"aY" = ( -/obj/effect/clockwork/servant_blocker{ - dir = 1 - }, -/obj/structure/lattice/clockwork, -/turf/open/indestructible/reebe_void, -/area/reebe) -"aZ" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/belligerent_eye/blind_eye, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"ba" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/belligerent_eye/lens_gem, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bb" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/geis_capacitor, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bc" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/geis_capacitor/antennae, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bd" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/geis_capacitor/fallen_armor, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"be" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/hierophant_ansible, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bf" = ( -/obj/structure/table/reinforced/brass, /obj/item/clockwork/component/hierophant_ansible/obelisk, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bg" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/replicant_alloy, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bh" = ( -/obj/structure/lattice/catwalk/clockwork, -/obj/item/clockwork/integration_cog, -/turf/open/indestructible/reebe_void, -/area/reebe) -"bi" = ( -/obj/structure/lattice/catwalk/clockwork, -/obj/item/clockwork/component/vanguard_cogwheel/onyx_prism, -/turf/open/indestructible/reebe_void, -/area/reebe) -"bj" = ( -/obj/structure/destructible/clockwork/eminence_spire, /turf/open/floor/clockwork/reebe, -/area/reebe/city_of_cogs) -"bk" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/replicant_alloy/replication_plate, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bl" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bm" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/vanguard_cogwheel, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bn" = ( -/obj/structure/table/reinforced/brass, -/obj/item/clockwork/component/vanguard_cogwheel/onyx_prism, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bo" = ( -/obj/structure/window/reinforced/clockwork/fulltile, -/obj/structure/grille/ratvar, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bp" = ( -/obj/structure/window/reinforced/clockwork/fulltile, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) +/area/reebe) +"aT" = ( +/obj/item/clockwork/component/geis_capacitor/antennae, +/turf/open/floor/clockwork/reebe, +/area/reebe) "bt" = ( /obj/structure/table/bronze, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"bu" = ( -/obj/structure/table/reinforced/brass, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bw" = ( -/obj/structure/chair/brass{ - dir = 8 - }, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"bx" = ( -/obj/structure/chair/brass{ - dir = 4 - }, -/turf/open/indestructible/clock_spawn_room, +"bC" = ( +/obj/structure/table/bronze, +/obj/item/storage/belt/utility/servant, +/turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) "bE" = ( /obj/structure/table/reinforced/brass, @@ -348,53 +160,114 @@ /obj/item/healthanalyzer/advanced, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"eV" = ( -/obj/structure/chair/stool/bar/brass, -/turf/open/indestructible/clock_spawn_room, +"dl" = ( +/turf/open/floor/clockwork/reebe, +/area/reebe) +"dx" = ( +/obj/structure/destructible/clockwork/powered/clockwork_obelisk, +/obj/effect/clockwork/sigil/transmission, +/turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"nj" = ( -/obj/structure/table/bronze, -/turf/open/indestructible/clock_spawn_room, +"ew" = ( +/obj/structure/table/reinforced/brass, +/obj/item/clockwork/construct_chassis/cogscarab{ + pixel_y = 20 + }, +/obj/item/clockwork/construct_chassis/cogscarab{ + pixel_x = -7; + pixel_y = 6 + }, +/obj/item/clockwork/construct_chassis/cogscarab{ + pixel_x = 7; + pixel_y = 6 + }, +/turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"ww" = ( -/obj/structure/table/bronze, -/obj/item/camera_film, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"xH" = ( -/obj/structure/chair/stool/brass, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"ym" = ( -/obj/structure/table/bronze, +"hY" = ( +/obj/item/clockwork/alloy_shards/pinion_lock, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"nX" = ( +/obj/item/clockwork/alloy_shards/clockgolem_remains, +/obj/item/clockwork/weapon/ratvarian_spear, +/obj/item/clockwork/alloy_shards/pinion_lock, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"om" = ( +/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment, +/obj/item/clockwork/component/geis_capacitor/fallen_armor, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"sW" = ( +/obj/structure/table/reinforced/brass, +/obj/item/storage/belt/utility/servant, +/obj/item/storage/belt/utility/servant, +/obj/item/storage/belt/utility/servant, +/obj/item/storage/belt/utility/servant, /obj/item/storage/belt/utility/servant, /obj/item/storage/belt/utility/servant, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) +"vx" = ( +/obj/effect/clockwork/sigil/transmission, +/turf/open/floor/clockwork/reebe, +/area/reebe/city_of_cogs) +"wV" = ( +/obj/item/clockwork/alloy_shards/large, +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/reebe) +"xR" = ( +/obj/item/clockwork/alloy_shards/medium, +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/reebe) +"yY" = ( +/obj/item/clockwork/alloy_shards/small, +/turf/open/floor/clockwork/reebe, +/area/reebe) "zb" = ( /turf/open/space/basic, /area/space) -"EE" = ( -/obj/structure/table/bronze, -/obj/item/camera, -/turf/open/indestructible/clock_spawn_room, +"Fd" = ( +/obj/item/clockwork/alloy_shards/clockgolem_remains, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"Fj" = ( +/obj/machinery/sleeper/syndie/fullupgrade{ + desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch."; + enter_message = "You hear the gentle hum and click of machinery, and are lulled into a sense of peace."; + icon_state = "sleeper_clockwork"; + name = "soothing sleeper" + }, +/turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) -"NH" = ( -/obj/structure/table/bronze, -/obj/item/taperecorder, -/turf/open/indestructible/clock_spawn_room, -/area/reebe/city_of_cogs) -"VP" = ( +"Ia" = ( +/obj/item/clockwork/alloy_shards/small, +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/reebe) +"OB" = ( +/obj/item/clockwork/component/geis_capacitor/fallen_armor, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"Rw" = ( /obj/structure/table/reinforced/brass, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, -/obj/item/clockwork/slab, +/obj/item/clockwork/replica_fabricator, +/obj/item/clockwork/replica_fabricator, +/turf/open/floor/clockwork/reebe, +/area/reebe/city_of_cogs) +"Sr" = ( +/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"TH" = ( +/obj/structure/lattice/catwalk/clockwork, +/turf/open/indestructible/reebe_void/spawning/lattices, +/area/reebe/city_of_cogs) +"Wv" = ( +/obj/item/clockwork/component/belligerent_eye/blind_eye, +/turf/open/floor/clockwork/reebe, +/area/reebe) +"WA" = ( +/obj/effect/clockwork/sigil/vitality, /turf/open/floor/clockwork/reebe, /area/reebe/city_of_cogs) "WT" = ( @@ -24671,7 +24544,7 @@ aa aa aa aa -ab +aa aa aa aa @@ -24908,58 +24781,58 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 aa @@ -25155,76 +25028,76 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -25411,78 +25284,78 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -25668,79 +25541,79 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -25925,80 +25798,80 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ac -ae -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -aW -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -26182,81 +26055,81 @@ aa aa aa aa -ab -ab -ab -ae -af -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ab -aP -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -26439,82 +26312,82 @@ aa aa aa aa -ab -ab -ab -ab -ac -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +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 @@ -26696,83 +26569,83 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +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 @@ -26953,84 +26826,84 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ae -ae -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ab -ab -ab -ab -ab -ab +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 +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 +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 @@ -27210,85 +27083,85 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ag -ag -ag -ae -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aG -aY -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ah -ah -bo -bo -bo -bo -bo -bo -bo -ah -ah -ae -ae -ae -ab -ab -ab -ab -ab +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 +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 +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 aa @@ -27467,85 +27340,85 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ag -ag -ag -ae -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aG -aS -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -aT -aT -aT -aT -aT -aT -aT -nj -nj -ah -ah -ah -ae -ae -ab -ab -ab -ab +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 +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 +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 aa @@ -27724,6 +27597,31 @@ 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 +aa +aa ab ab ab @@ -27733,76 +27631,51 @@ ab ab ab ab -ab -ab -ab -ah -ah -ai -ah -ah -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aj -aS -bu -bu -bu -bu -bu -bu -bu -bu -bu -bu -bu -bu -aU -aT -aT -aT -aT -aT -aT -aT -xH -EE -bo -aX -bo -ag +ae +ae ae ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aF +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -27974,6 +27847,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -27982,84 +27887,52 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -ar -aj -bt -ah -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -bw -bw -bw -bw -bw -bw -bw -bw -bw -bw -bw -bw -aU -aT -aT -aR -aT -aR -aT -aR -eV -NH -bo -aZ -bo +ae +ag +ag ag ae ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -28231,6 +28104,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -28239,84 +28144,52 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -as -aj -aj -ay -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bo -aT -aT -aT -aT -aT -aT -aT -xH -nj -bo -ba -bo +ae +ag +ag ag ae -bi -ab +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF ab ab +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -28488,17 +28361,38 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa +aa +aa ab ab ab @@ -28508,72 +28402,51 @@ ab ab ab ah -VP -aj -ym ah -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aV -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -bb -bo -ag -ae +ai +ah +ah +aG +aG +aG +aG +aG +aG +aG +aF ab -ae -ac ab +ab +ab +ab +ab +aa +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -28745,17 +28618,38 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa +aa +aa ab ab ab @@ -28765,9 +28659,9 @@ ab ab ab ah -ah -ay -ah +ar +aj +bt ah aj aj @@ -28775,62 +28669,41 @@ aj aj aj aj +TH aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bo -aT -aT -aT -aT -aT -aT -aT -xH -ww -bo -bc -bo -ag -ae +aa +dl +ab +aa ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -29002,6 +28875,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -29010,84 +28915,52 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -an -au -aj -au ah +as +aj +aj +ay aj aj aj aj aj aj +TH aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -bd -bo -ag -ae +aa +dl +aa +aa +ab +dl +ab +dl +dl +dl +ab +ab +dl ab ab ab ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -29259,16 +29132,38 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa +aa +aa ab ab ab @@ -29278,10 +29173,9 @@ ab ab ab ah -ah -av +aL aj -av +bC ah aj aj @@ -29289,62 +29183,41 @@ aj aj aj aj +TH +ab aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aT -aT -aT -aT -aT -xH -nj -bo -be -bo -ag -ae +aa +dl +aa +Wv +ab +Fd +yY +yY +dl +dl +dl ab ab ab ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -29516,6 +29389,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -29524,84 +29429,52 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ai -ao -aj -aj -aj -aD -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bp -bp -ah -aT -aT -aT -aT -aT -aT -aT -EE -nj ah ah +ay ah -ae -ae +ah +aj +aj +aj +aj +aj +aj +aj +aj +aa +dl +ab +aa +Fd +ab +hY +Sr +dl +ab +ab +dl ab ab ab ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -29773,6 +29646,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -29781,23 +29686,11 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae +an +au +aj +au ah -ah -aw -aj -aw -ai -aH aj aj aj @@ -29806,59 +29699,39 @@ aj aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bp -bg -ah -ah -bo -bo -bo -bo -bo -bo -bo -ah -ah -ae -ae -ae +aa +dl +aa +ab +ab +OB +ab +yY +dl ab ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -30030,6 +29903,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -30037,85 +29942,53 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ae -ag -ag -an -au -aj -au -ai -aI -aK -aH -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bp -bp -ah -aT -aT -aT -aT -aT -aT -aT -ww -nj ah ah +av +aj +av ah -ae -ae +aj +aj +aj +aj +aj +aj +aj +aa +dl +dl +aa +aa +om +Fd ab ab ab ab +dl +dl +dl +dl +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -30287,92 +30160,92 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ah -ah -ah -ai -ah -ah -ah -ai -ap -ai -ah -aJ -aH -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aT -aT -aT -aT -aT -xH -nj -bo -bf -bo -ag ae +ai +ao +aj +aj +aj +aD +aj +aj +aj +aj +aj +aj +TH +aa +aa +aa +aT +Wv ab ab ab ab +ab +ab +ab +dl +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -30544,92 +30417,92 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab ab ab ab -ab -ab -ab -ab -ab -ab -ac -ah -aj -aj -aj -aj -aj -ai -aj -aj -aj -ai -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -bg -bo -ag ae +ah +ah +aw +aj +aw +ai +aj +aj +aj +aj +aj +aj +aj +aj +aj +aa +ab +ab +ab +Ia +ab +yY +ab +ab +dl ab ab ab ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -30801,92 +30674,92 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa +aa +aa ab ab ab ab ae -ah -aj -aj -aj -aj -aj -ai -aj -az -aj -ai -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -ai -aT -aT -aT -aT -aT -aT -aT -xH -EE -bo -bk -bo +ae ag -ae +ag +an +au +aj +au +ai +aL +aK +aj +aj +aj +aj +aj +ab +ab +aa +Fd +ab +Ia +ab +ab +ab +Wv ab ab ab ab +dl +ab +dl +ab +dl +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -31058,30 +30931,52 @@ 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 +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ag +ah +ah +ah +ai +ah +ah +ah ai -aj -aj -ak -aj -aj -ap -aj -aj -aj ap +ai +ah +aJ aj aj aj @@ -31090,60 +30985,38 @@ aj aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aV -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -bl -bo -ag -ae +aa +ab +ab +ab +Ia ab ab ab ab +ab +ab +ab +dl +ab +dl +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -31317,17 +31190,38 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae +ac ah aj aj @@ -31336,7 +31230,7 @@ aj aj ai aj -bj +aj aj ai aj @@ -31345,62 +31239,41 @@ aj aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -ai -aT -aT -aT -aT -aT -aT -aT -xH -nj -bo -bm -bo -ag -ae +TH +aa +aa +ab +ab +Sr +ab +ab +Ia +ab +ab +dl ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -31574,15 +31447,36 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa ab ae ah @@ -31598,66 +31492,45 @@ aj ai aj aj -aH -aH -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj aj aj aj aj aj aj +aa aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -bn -bo -ag -ae +ab +aa ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -31831,90 +31704,90 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -ah -ah -ai -ah -ah -ah -ai -ap -ai -ah -aj -aH -aL -aN -aH -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aT -aT -aT -aT -aT -xH -nj -bo -aX -bo -ag +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 +aa +aa +aa ae +ag +ai +aj +aj +dx +aj +aj +ap +aj +aj +aj +ap +aj +aj +aj +aj +aj +aj +aj +ab +aa +ab +aa +xR +nX ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -32088,33 +31961,49 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa ab ae -ae -ag ah -aq -ax +aj +aj +aj aj aj ai aj -aH -aM -aL -aH +aj +aj +ai aj aj aj @@ -32124,54 +32013,38 @@ aj aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bp -bp -ah -aT -aT -aT -aT -aT -aT -aT -NH -EE -ah -ah -ah -ae -ae +aa +ab +aa +ab +ab +ab +wV ab ab ab ab +ab +ab +dl +dl +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -32345,32 +32218,49 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa ab ae -ai -aq -ax +ah +aj +aj +aj aj aj ai aj aj -aH -aH +aj +ai aj aj aj @@ -32378,50 +32268,11 @@ aj aj aj aj +ab aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bp -bk -ah -ah -bo -bo -bo -bo -bo -bo -bo -ah -ah -ae +ab +aa +xR ab ab ab @@ -32429,6 +32280,28 @@ ab ab ab ab +ab +ab +dl +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -32602,90 +32475,90 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae +ah +ah +ah ai -aq -ax -aj -aj -aE -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bp -bp -ah -aT -aT -aT -aT -aT -aT -aT -nj -nj ah ah ah -ae -ae +ai +ap +ai +ah +aj +aj +aL +aN +aj +aj +aj +ab +aa +dl +aa +ab +OB ab ab ab ab +ab +dl +ab +dl +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -32859,90 +32732,90 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab ab ab ab -ab -ad -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ai -aq -ax -aj -aB -ah -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aT -aT -aT -aT -aT -xH -EE -bo -aZ -bo -ag ae +ae +ag +ah +ew +aj +aj +aj +ai +aj +aj +aM +aL +aj +aj +aj +aa +aa +aa ab ab ab ab +ab +ab +ab +ab +dl +ab +ab +dl +ab +dl +ab +ab +ab +dl +dl +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -33116,90 +32989,90 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab ab ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -aq -ax -aj -aB -ah -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aU -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -ba -bo -ag ae +ai +aj +aj +aj +aj +ai +aj +aj +aj +aj +aj +aj +TH +aa +dl +hY ab ab ab ab +ab +ab +ab +ab +dl +ab +ab +ab +ab +dl +ab +dl +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -33373,90 +33246,90 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab ab ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -ah -ah -ah -aA -ah -ah -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bo -aT -aT -aT -aT -aT -aT -aT -xH -NH -bo -bb -bo -ag ae +ai +az +vx +aj +aj +aE +aj +aj +aj +aj +aj +aj +aj +aa +aa +ab +ab +ab +aT +Wv +ab +ab +ab +dl ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -33630,6 +33503,36 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -33637,20 +33540,11 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ah -al +ai aj aj aj -aC +sW ah aj aj @@ -33661,59 +33555,38 @@ aj aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS +aa aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aV -aT -aT -aR -aT -aR -aT -aR -eV -nj -bo -bc -bo -ag -ae ab ab ab ab +ab +dl +ab +ab +dl +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -33887,6 +33760,68 @@ 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 +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +ab +ab +ah +aj +aj +aj +Rw +ah +aj +aj +aj +aj +aj +aj +aj +ab +ab +aa +ab +ab +ab +ab +ab +ab +ab +ab +dl ab ab ab @@ -33897,80 +33832,18 @@ ab ab ab ab -ab -ab -ab -ab -ab -ai -bE -aj -aj -aj -aj -aA -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aS -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -aT -bo -aT -aT -aT -aT -aT -aT -aT -xH -ww -bo -bd -bo -ag -ae -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -34144,15 +34017,36 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa ab ab ab @@ -34160,11 +34054,11 @@ ab ab ab ah -al -aj -aj -aj -aC +ah +ah +ah +aA +ah ah aj aj @@ -34175,59 +34069,38 @@ aj aj aj aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aj -aG -aS -bx -bx -bx -bx -bx -bx -bx -bx -bx -bx -bx -bx -aU -aT -aT -aR -aT -aR -aT -aR -eV -EE -bo -be -bo -ag -ae +aa +hY +ab +ab +dl +ab +dl ab ab ab ab +ab +dl +ab +ab +dl +dl +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -34401,15 +34274,36 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +aa +aa +aa ab ab ab @@ -34417,74 +34311,53 @@ ab ab ab ah +Fj +aj +aj +aj +WA ah -ah -ai -ah -ah -ah -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aG -aS -bu -bu -bu -bu -bu -bu -bu -bu -bu -bu -bu -bu -aU -aT -aT -aT -aT -aT -aT -aT -xH -nj -bo -bf -bo -ag -ae +aj +aj +aj +aj +aj +aj +aj +ab +ab +aa +aa ab ab ab ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -34658,6 +34531,62 @@ 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 +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +ab +ai +bE +aj +aj +aj +aj +aA +aj +aj +aj +aj +aj +aj +TH +aj +aj +aj +ab +aa +Fd ab ab ab @@ -34669,79 +34598,23 @@ ab ab ab ab +dl ab ab +dl ab -ab -ab -ab -ae -ae -ag -ae -ae -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -aF -ab -aS -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -ah -aT -aT -aT -aT -aT -aT -aT -nj -nj -ah -ah -ah -ae -ae -ab -ab -ab -ab +dl +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -34915,11 +34788,61 @@ 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 +aa +aa +aa +aa +aa +aa +aa ab ab ab ab ab +ab +ah +Fj +aj +aj +aj +WA +ah +aj +aj +aj +aj +aj +aj +aj +ab +ab +ab +dl +ab aa ab ab @@ -34937,68 +34860,18 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aY -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ah -ah -bo -bo -bo -bo -bo -bo -bo -ah -ah -ae -ab -ab -ab -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -35178,6 +35051,50 @@ 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 +aa +ab +ab +ab +ab +ab +ab +ah +ah +ah +ai +ah +ah +ah +aG +aG +aG +aG +aG +aG +aG ab ab ab @@ -35200,61 +35117,17 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ae -ab -ab -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -35435,6 +35308,30 @@ 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 +aa ab ab ab @@ -35443,74 +35340,50 @@ ab ab ab ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +ae +ae +ag +ae +ae +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF aF ab +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF +aF ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -35692,6 +35565,30 @@ 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 +aa ab ab ab @@ -35735,38 +35632,14 @@ ab ab ab ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -35949,6 +35822,30 @@ 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 +aa ab ab ab @@ -35969,37 +35866,6 @@ ab ab ab ab -aO -ac -ab -ab -ab -ab -ab -ab -ab -aQ -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab ab ab ab @@ -36041,6 +35907,13 @@ aa aa aa aa +aa +aa +aa +aa +aa +aa +aa WT zb zb @@ -36206,10 +36079,30 @@ aa aa aa aa -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa ab ab ab @@ -36253,32 +36146,12 @@ ab ab ab aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +aa +aa +aa +aa +aa +aa aa aa aa @@ -36463,78 +36336,78 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ac -bh -ae -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -36720,77 +36593,77 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -36977,76 +36850,76 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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 +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa aa aa aa @@ -37244,58 +37117,58 @@ aa aa aa aa -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab aa -aF -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab -ab +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 +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/multiz_debug.json b/_maps/multiz_debug.json index 7e39981e23..e916a77d1d 100644 --- a/_maps/multiz_debug.json +++ b/_maps/multiz_debug.json @@ -2,5 +2,5 @@ "map_name": "MultiZ Debug", "map_path": "map_files/debug", "map_file": "multiz.dmm", - "traits": [{"Up": 1}, {"Up": 1, "Down": -1}, {"Down": -1}] + "traits": [{"Up" : 1, "Linkage" : "Cross"}, {"Up" : 1, "Down" : -1, "Baseturf" : "/turf/open/transparent/openspace", "Linkage" : "Cross"}, {"Down" : -1, "Baseturf" : "/turf/open/transparent/openspace", "Linkage" : "Cross"}] } diff --git a/_maps/shuttles/arrival_delta.dmm b/_maps/shuttles/arrival_delta.dmm index 62e30ef335..c7d331e368 100644 --- a/_maps/shuttles/arrival_delta.dmm +++ b/_maps/shuttles/arrival_delta.dmm @@ -203,7 +203,7 @@ /obj/machinery/status_display/evac{ pixel_x = -32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -226,7 +226,7 @@ /obj/machinery/status_display/ai{ pixel_x = 32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral, @@ -277,7 +277,7 @@ /turf/closed/wall/mineral/titanium, /area/shuttle/arrival) "A" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -307,12 +307,12 @@ "D" = ( /obj/structure/table/reinforced, /obj/item/folder, -/obj/item/storage/pill_bottle/dice, +/obj/item/storage/box/dice, /obj/effect/turf_decal/delivery, /turf/open/floor/plasteel, /area/shuttle/arrival) "E" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral, diff --git a/_maps/shuttles/arrival_omega.dmm b/_maps/shuttles/arrival_omega.dmm index f580149163..9285a4a716 100644 --- a/_maps/shuttles/arrival_omega.dmm +++ b/_maps/shuttles/arrival_omega.dmm @@ -138,7 +138,7 @@ /turf/open/floor/plasteel, /area/shuttle/arrival) "o" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /obj/effect/turf_decal/tile/neutral{ dir = 1 }, @@ -237,7 +237,7 @@ /area/shuttle/arrival) "C" = ( /obj/structure/table/reinforced, -/obj/item/storage/pill_bottle/dice{ +/obj/item/storage/box/dice{ pixel_x = -2; pixel_y = 8 }, diff --git a/_maps/shuttles/emergency_bar.dmm b/_maps/shuttles/emergency_bar.dmm index 7bc7de9bf1..55fd4bd56a 100644 --- a/_maps/shuttles/emergency_bar.dmm +++ b/_maps/shuttles/emergency_bar.dmm @@ -175,7 +175,7 @@ pixel_x = 6; pixel_y = 24 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -385,7 +385,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "bc" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -424,7 +424,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "bg" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /obj/effect/turf_decal/tile/bar, @@ -557,7 +557,7 @@ /turf/open/floor/plating/airless, /area/shuttle/escape) "bG" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 diff --git a/_maps/shuttles/emergency_birdboat.dmm b/_maps/shuttles/emergency_birdboat.dmm index 43a6a85bf7..dcffda7ba2 100644 --- a/_maps/shuttles/emergency_birdboat.dmm +++ b/_maps/shuttles/emergency_birdboat.dmm @@ -47,7 +47,7 @@ /turf/open/floor/mineral/titanium/blue, /area/shuttle/escape) "k" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/mineral/titanium/blue, @@ -144,7 +144,7 @@ /turf/open/floor/mineral/titanium/white, /area/shuttle/escape) "B" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/mineral/titanium, diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm index f49e70aeb9..9608f7f28a 100644 --- a/_maps/shuttles/emergency_cere.dmm +++ b/_maps/shuttles/emergency_cere.dmm @@ -420,7 +420,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "aM" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/item/radio/intercom{ @@ -446,7 +446,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "aP" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/item/radio/intercom{ @@ -968,7 +968,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "ca" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, @@ -994,7 +994,7 @@ /obj/machinery/light{ dir = 4 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /turf/open/floor/plasteel, diff --git a/_maps/shuttles/emergency_delta.dmm b/_maps/shuttles/emergency_delta.dmm index 564115443d..b4b22b2ff6 100644 --- a/_maps/shuttles/emergency_delta.dmm +++ b/_maps/shuttles/emergency_delta.dmm @@ -167,7 +167,7 @@ /turf/open/floor/plasteel/white, /area/shuttle/escape) "an" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -196,7 +196,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "ap" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -800,7 +800,7 @@ /turf/open/floor/mineral/plastitanium/red/brig, /area/shuttle/escape) "bz" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/machinery/button/flasher{ @@ -814,7 +814,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "bA" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21" }, /obj/effect/turf_decal/tile/neutral{ @@ -1018,7 +1018,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "cb" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -1338,7 +1338,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "cA" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 diff --git a/_maps/shuttles/emergency_discoinferno.dmm b/_maps/shuttles/emergency_discoinferno.dmm index e142208e12..92b515f17e 100644 --- a/_maps/shuttles/emergency_discoinferno.dmm +++ b/_maps/shuttles/emergency_discoinferno.dmm @@ -94,7 +94,7 @@ /turf/open/floor/light/colour_cycle, /area/shuttle/escape) "r" = ( -/turf/open/floor/mineral/plasma, +/turf/open/floor/mineral/plasma/disco, /area/shuttle/escape) "s" = ( /turf/open/floor/mineral/silver, @@ -112,7 +112,7 @@ resistance_flags = 2 }, /obj/structure/fans/tiny, -/turf/open/floor/mineral/plasma, +/turf/open/floor/mineral/plasma/disco, /area/shuttle/escape) "v" = ( /obj/machinery/jukebox/disco/indestructible, diff --git a/_maps/shuttles/emergency_imfedupwiththisworld.dmm b/_maps/shuttles/emergency_imfedupwiththisworld.dmm index 349918ef29..ca2e6059ec 100644 --- a/_maps/shuttles/emergency_imfedupwiththisworld.dmm +++ b/_maps/shuttles/emergency_imfedupwiththisworld.dmm @@ -155,7 +155,7 @@ /turf/open/floor/carpet, /area/shuttle/escape) "y" = ( -/obj/item/twohanded/required/kirbyplants, +/obj/item/kirbyplants, /turf/open/floor/wood, /area/shuttle/escape) "z" = ( diff --git a/_maps/shuttles/emergency_luxury.dmm b/_maps/shuttles/emergency_luxury.dmm index a7faface75..8a16763007 100644 --- a/_maps/shuttles/emergency_luxury.dmm +++ b/_maps/shuttles/emergency_luxury.dmm @@ -305,7 +305,7 @@ /turf/open/floor/carpet/royalblue, /area/shuttle/escape/luxury) "bg" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/carpet/red, @@ -320,7 +320,7 @@ /turf/open/floor/carpet/royalblue, /area/shuttle/escape/luxury) "bj" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -328,13 +328,13 @@ /turf/open/floor/wood, /area/shuttle/escape/luxury) "bk" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/carpet/royalblue, /area/shuttle/escape/luxury) "bl" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -437,7 +437,7 @@ dir = 4; light_range = 8 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-10" }, /turf/open/floor/carpet/red, diff --git a/_maps/shuttles/emergency_omega.dmm b/_maps/shuttles/emergency_omega.dmm index bd99f35bb5..83b9c28305 100644 --- a/_maps/shuttles/emergency_omega.dmm +++ b/_maps/shuttles/emergency_omega.dmm @@ -194,7 +194,7 @@ /turf/open/floor/mineral/plastitanium/red/brig, /area/shuttle/escape) "as" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -317,7 +317,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "aC" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -530,7 +530,7 @@ /turf/open/floor/plasteel, /area/shuttle/escape) "aS" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 diff --git a/_maps/shuttles/emergency_pubby.dmm b/_maps/shuttles/emergency_pubby.dmm index 0eea5ab1c8..7c43bef2ce 100644 --- a/_maps/shuttles/emergency_pubby.dmm +++ b/_maps/shuttles/emergency_pubby.dmm @@ -110,7 +110,7 @@ /obj/machinery/computer/security/telescreen/entertainment{ pixel_y = 32 }, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-21"; pixel_x = -3; pixel_y = 3 @@ -183,7 +183,7 @@ /area/shuttle/escape) "aB" = ( /obj/structure/window/reinforced, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-11" }, /obj/effect/turf_decal/tile/green, @@ -589,7 +589,7 @@ /turf/open/floor/mineral/titanium/blue, /area/shuttle/escape) "bu" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/mineral/plastitanium/red/brig, diff --git a/_maps/shuttles/emergency_raven.dmm b/_maps/shuttles/emergency_raven.dmm index 05446968e7..daba49a238 100644 --- a/_maps/shuttles/emergency_raven.dmm +++ b/_maps/shuttles/emergency_raven.dmm @@ -1014,7 +1014,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "bV" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green{ @@ -1029,7 +1029,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "bW" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green{ @@ -1094,7 +1094,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "cd" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green{ @@ -1107,7 +1107,7 @@ /turf/open/floor/plasteel/dark, /area/shuttle/escape) "ce" = ( -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /obj/effect/turf_decal/tile/green, diff --git a/_maps/shuttles/emergency_scrapheap.dmm b/_maps/shuttles/emergency_scrapheap.dmm index 4bd8f07c8e..cc51c2b8f8 100644 --- a/_maps/shuttles/emergency_scrapheap.dmm +++ b/_maps/shuttles/emergency_scrapheap.dmm @@ -194,7 +194,7 @@ /turf/open/floor/mineral/plastitanium/red/brig, /area/shuttle/escape) "aF" = ( -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/mineral/titanium/blue, /area/shuttle/escape) "aG" = ( diff --git a/_maps/shuttles/emergency_syndicate.dmm b/_maps/shuttles/emergency_syndicate.dmm index 85048b9d89..3c2c3cb19b 100644 --- a/_maps/shuttles/emergency_syndicate.dmm +++ b/_maps/shuttles/emergency_syndicate.dmm @@ -1351,7 +1351,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/dark, @@ -1842,7 +1842,7 @@ dir = 1 }, /obj/effect/turf_decal/tile/neutral, -/obj/item/twohanded/required/kirbyplants{ +/obj/item/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/dark, diff --git a/_maps/shuttles/ferry_lighthouse.dmm b/_maps/shuttles/ferry_lighthouse.dmm index a12e8858cb..1b4e685bd0 100644 --- a/_maps/shuttles/ferry_lighthouse.dmm +++ b/_maps/shuttles/ferry_lighthouse.dmm @@ -236,7 +236,7 @@ /turf/open/floor/wood, /area/shuttle/transport) "bd" = ( -/obj/item/twohanded/required/kirbyplants/dead{ +/obj/item/kirbyplants/dead{ desc = "It doesn't look very healthy..."; name = "potted plant" }, diff --git a/_maps/shuttles/whiteship_box.dmm b/_maps/shuttles/whiteship_box.dmm index 0404cede34..3ac1d18ac4 100644 --- a/_maps/shuttles/whiteship_box.dmm +++ b/_maps/shuttles/whiteship_box.dmm @@ -2690,7 +2690,7 @@ /obj/structure/rack, /obj/item/storage/box/zipties, /obj/item/assembly/flash/handheld, -/obj/item/melee/classic_baton/telescopic, +/obj/item/melee/classic_baton, /obj/machinery/light/small/built{ dir = 8 }, diff --git a/_maps/shuttles/whiteship_cog.dmm b/_maps/shuttles/whiteship_cog.dmm index 9410682219..9e4463df6b 100644 --- a/_maps/shuttles/whiteship_cog.dmm +++ b/_maps/shuttles/whiteship_cog.dmm @@ -32,11 +32,6 @@ "g" = ( /turf/closed/wall/mineral/titanium/nodiagonal, /area/shuttle/abandoned) -"h" = ( -/obj/machinery/door/airlock/external, -/obj/structure/fans/tiny, -/turf/open/floor/plating, -/area/shuttle/abandoned) "i" = ( /obj/machinery/suit_storage_unit/security, /obj/machinery/light/small{ @@ -64,6 +59,7 @@ /area/shuttle/abandoned) "m" = ( /obj/structure/bed, +/obj/item/bedsheet/orange, /turf/open/floor/plasteel, /area/shuttle/abandoned) "n" = ( @@ -130,7 +126,6 @@ /area/shuttle/abandoned) "x" = ( /obj/machinery/door/firedoor/border_only/closed{ - icon_state = "door_closed"; dir = 4 }, /obj/machinery/door/window/eastright, @@ -174,12 +169,12 @@ dir = 8 }, /obj/structure/closet/crate/secure/weapon, -/obj/item/gun/energy/laser/carbine, /obj/machinery/button/flasher{ id = "cogws"; pixel_x = -24; pixel_y = 8 }, +/obj/item/gun/energy/laser/retro, /turf/open/floor/plasteel, /area/shuttle/abandoned) "D" = ( @@ -191,7 +186,7 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, -/obj/item/gun/energy/e_gun/stun, +/obj/item/gun/energy/laser/retro, /turf/open/floor/plasteel, /area/shuttle/abandoned) "E" = ( @@ -228,12 +223,14 @@ "I" = ( /obj/structure/table/reinforced, /obj/item/clothing/glasses/sunglasses, +/obj/item/gps{ + gpstag = "NTPRS" + }, /turf/open/floor/plasteel/grimy, /area/shuttle/abandoned) "J" = ( /obj/structure/curtain, /obj/machinery/shower{ - name = "shower"; pixel_y = 12 }, /obj/item/soap/nanotrasen, @@ -329,13 +326,13 @@ d "} (5,1,1) = {" d -h +g n n B H n -h +g d "} (6,1,1) = {" diff --git a/_maps/snaxi.json b/_maps/snaxi.json index cb1917b6f6..3fc8eba15d 100644 --- a/_maps/snaxi.json +++ b/_maps/snaxi.json @@ -33,7 +33,7 @@ "Linkage":null, "Gravity":true, "Ice Ruins Underground":true, - "Baseturf":"/turf/open/openspace/icemoon" + "Baseturf":"/turf/open/transparent/openspace/icemoon" }, { "Down":-1, diff --git a/_maps/templates/shelter_2.dmm b/_maps/templates/shelter_2.dmm index 825cb26e3a..0a25527358 100644 --- a/_maps/templates/shelter_2.dmm +++ b/_maps/templates/shelter_2.dmm @@ -93,7 +93,7 @@ /area/survivalpod) "q" = ( /obj/structure/tubes, -/obj/item/twohanded/required/kirbyplants/random, +/obj/item/kirbyplants/random, /turf/open/floor/pod, /area/survivalpod) "r" = ( diff --git a/byond-extools.dll b/byond-extools.dll index a83ea1e543..bd6b34c48e 100644 Binary files a/byond-extools.dll and b/byond-extools.dll differ diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 2f42ff52cf..f7d608dfdc 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -108,6 +108,8 @@ #define TR_KEEPSE (1<<5) // changelings shouldn't edit the DNA's SE when turning into a monkey #define TR_DEFAULTMSG (1<<6) #define TR_KEEPORGANS (1<<8) +#define TR_KEEPREAGENTS (1<<10) +#define TR_KEEPSTUNS (1<<9) #define CLONER_FRESH_CLONE "fresh" @@ -141,7 +143,10 @@ #define HORNCOLOR 25 #define WINGCOLOR 26 #define ROBOTIC_LIMBS 27 //has robotic limbs that render like organic ones - +#define CAN_SCAR 28 // If this species can be scarred (fleshy) +/// Used for determining which wounds are applicable to this species. +#define HAS_FLESH 29 /// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD) +#define HAS_BONE 30 /// if we have bones (can suffer bone wounds) //organ slots #define ORGAN_SLOT_BRAIN "brain" @@ -186,4 +191,4 @@ #define G_MALE 1 #define G_FEMALE 2 #define G_PLURAL 3 -#define G_NEUTER 4 \ No newline at end of file +#define G_NEUTER 4 diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm index b1324000b8..ffa3f1c751 100644 --- a/code/__DEFINES/_flags/_flags.dm +++ b/code/__DEFINES/_flags/_flags.dm @@ -98,7 +98,7 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define ZAP_MOB_DAMAGE (1<<3) #define ZAP_MOB_STUN (1<<4) -#define ZAP_DEFAULT_FLAGS ALL +#define ZAP_DEFAULT_FLAGS ZAP_MOB_STUN | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE #define ZAP_FUSION_FLAGS ZAP_OBJ_DAMAGE | ZAP_MOB_DAMAGE | ZAP_MOB_STUN #define ZAP_SUPERMATTER_FLAGS NONE @@ -138,11 +138,22 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define MOBILITY_FLAGS_DEFAULT (MOBILITY_MOVE | MOBILITY_STAND | MOBILITY_PICKUP | MOBILITY_USE | MOBILITY_UI | MOBILITY_STORAGE | MOBILITY_PULL | MOBILITY_RESIST) #define MOBILITY_FLAGS_ANY_INTERACTION (MOBILITY_USE | MOBILITY_PICKUP | MOBILITY_UI | MOBILITY_STORAGE) -// melee_attack_chain() attackchain_flags -/// The attack is from a parry counterattack. -#define ATTACKCHAIN_PARRY_COUNTERATTACK (1<<0) - /// If the thing can reflect light (lasers/energy) #define RICOCHET_SHINY (1<<0) /// If the thing can reflect matter (bullets/bomb shrapnel) -#define RICOCHET_HARD (1<<1) \ No newline at end of file +#define RICOCHET_HARD (1<<1) + +#define KEEP_TOGETHER_ORIGINAL "keep_together_original" + +//setter for KEEP_TOGETHER to allow for multiple sources to set and unset it +#define ADD_KEEP_TOGETHER(x, source)\ + if ((x.appearance_flags & KEEP_TOGETHER) && !HAS_TRAIT(x, TRAIT_KEEP_TOGETHER)) ADD_TRAIT(x, TRAIT_KEEP_TOGETHER, KEEP_TOGETHER_ORIGINAL); \ + ADD_TRAIT(x, TRAIT_KEEP_TOGETHER, source);\ + x.appearance_flags |= KEEP_TOGETHER + +#define REMOVE_KEEP_TOGETHER(x, source)\ + REMOVE_TRAIT(x, TRAIT_KEEP_TOGETHER, source);\ + if(HAS_TRAIT_FROM_ONLY(x, TRAIT_KEEP_TOGETHER, KEEP_TOGETHER_ORIGINAL))\ + REMOVE_TRAIT(x, TRAIT_KEEP_TOGETHER, KEEP_TOGETHER_ORIGINAL);\ + else if(!HAS_TRAIT(x, TRAIT_KEEP_TOGETHER))\ + x.appearance_flags &= ~KEEP_TOGETHER diff --git a/code/__DEFINES/flags/do_after.dm b/code/__DEFINES/_flags/do_after.dm similarity index 100% rename from code/__DEFINES/flags/do_after.dm rename to code/__DEFINES/_flags/do_after.dm diff --git a/code/__DEFINES/_flags/item_flags.dm b/code/__DEFINES/_flags/item_flags.dm index c6a3886ed3..26e764c45b 100644 --- a/code/__DEFINES/_flags/item_flags.dm +++ b/code/__DEFINES/_flags/item_flags.dm @@ -52,3 +52,4 @@ #define ORGAN_VITAL (1<<4) //Currently only the brain #define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances #define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment. +#define ORGAN_EDIBLE (1<<7) //is a snack? :D diff --git a/code/__DEFINES/_flags/obj_flags.dm b/code/__DEFINES/_flags/obj_flags.dm index ebb9b4bda0..a936a5cef5 100644 --- a/code/__DEFINES/_flags/obj_flags.dm +++ b/code/__DEFINES/_flags/obj_flags.dm @@ -12,4 +12,9 @@ #define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check. #define BLOCK_Z_FALL (1<<10) +/// Integrity defines for clothing (not flags but close enough) +#define CLOTHING_PRISTINE 0 // We have no damage on the clothing +#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart and can be equipped +#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first + // If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support diff --git a/code/__DEFINES/_flags/return_values.dm b/code/__DEFINES/_flags/return_values.dm new file mode 100644 index 0000000000..28606265b3 --- /dev/null +++ b/code/__DEFINES/_flags/return_values.dm @@ -0,0 +1,22 @@ +/////////// ATTACKCHAIN_FLAGS //////////// +// melee_attack_chain(), attackby(), pre_attack(), afterattack(), and tool_act(), attack() and **anything that is called by ClickOn()** return values. +// These are all passed down through the attack chain and are binary OR'd into each other! +/// Stop the attack chain if still in melee_attack_chain() +#define STOP_ATTACK_PROC_CHAIN (1<<0) +/// This attack should discard last_action instead of flushing (storing) it). You should probably know what you're doing if you use this considering this is how clickdelay is enforced. +#define DISCARD_LAST_ACTION (1<<1) +/// There are a number of "safety nets" intended to default-handle clickdelay. Return this flag to bypass ALL of them. Be sure +/// you know EXACTLY what you are doing! +#define NO_AUTO_CLICKDELAY_HANDLING (1<<2) +/// Only used with UnarmedAttack(). Interrupts unarmed attack from progressing. +#define INTERRUPT_UNARMED_ATTACK (1<<3) +/// Attack should not set next action even if the atom wants it to be an action +#define ATTACK_IGNORE_ACTION (1<<4) +/// Attack should not at all check last_action/attack_hand_speed even if the atom wants to +#define ATTACK_IGNORE_CLICKDELAY (1<<5) +/// This attack is from a parry counterattack +#define ATTACK_IS_PARRY_COUNTERATTACK (1<<6) + +// obj/item/dropped() +/// dropped() relocated this item, return FALSE for doUnEquip. +#define ITEM_RELOCATED_BY_DROPPED "relocated_by_dropped" diff --git a/code/__DEFINES/flags/shields.dm b/code/__DEFINES/_flags/shields.dm similarity index 100% rename from code/__DEFINES/flags/shields.dm rename to code/__DEFINES/_flags/shields.dm diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index e8e75c132a..97f07acc05 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -74,6 +74,13 @@ #define ADMIN_PUNISHMENT_MAZING "Puzzle" #define ADMIN_PUNISHMENT_PIE "Cream Pie" #define ADMIN_PUNISHMENT_CUSTOM_PIE "Custom Cream Pie" +#define ADMIN_PUNISHMENT_SHOES "Knot Shoes" +#define ADMIN_PUNISHMENT_CRACK ":B:oneless" +#define ADMIN_PUNISHMENT_BLEED ":B:loodless" +#define ADMIN_PUNISHMENT_SCARIFY "Scarify" +#define ADMIN_PUNISHMENT_PICKLE "Pickle-ify" +#define ADMIN_PUNISHMENT_FRY "Fry" +#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate" #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 diff --git a/code/__DEFINES/admin/keybindings.dm b/code/__DEFINES/admin/keybindings.dm index 3efc26c7d5..fcfe7c5e58 100644 --- a/code/__DEFINES/admin/keybindings.dm +++ b/code/__DEFINES/admin/keybindings.dm @@ -1,6 +1,6 @@ // 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 +#define MAX_KEYPRESS_COMMANDLENGTH 32 /// Maximum keys that can be bound to one button #define MAX_COMMANDS_PER_KEY 5 /// Maximum keys per keybind diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm index b883a54209..a3e5423753 100644 --- a/code/__DEFINES/antagonists.dm +++ b/code/__DEFINES/antagonists.dm @@ -63,6 +63,16 @@ #define CONTRACT_UPLINK_PAGE_CONTRACTS "CONTRACTS" #define CONTRACT_UPLINK_PAGE_HUB "HUB" + +///Heretics -- +#define IS_HERETIC(mob) (mob.mind?.has_antag_datum(/datum/antagonist/heretic)) + +#define PATH_SIDE "Side" + +#define PATH_ASH "Ash" +#define PATH_RUST "Rust" +#define PATH_FLESH "Flesh" + //Overthrow time to update heads obj #define OBJECTIVE_UPDATING_TIME 300 @@ -91,4 +101,4 @@ #define BLOB_REROLL_TIME 2400 // blob gets a free reroll every X time #define BLOB_SPREAD_COST 4 #define BLOB_ATTACK_REFUND 2 //blob refunds this much if it attacks and doesn't spread -#define BLOB_REFLECTOR_COST 15 \ No newline at end of file +#define BLOB_REFLECTOR_COST 15 diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 2b19b557b2..621af2c811 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -136,7 +136,7 @@ #define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold #define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3) #define TANK_MIN_RELEASE_PRESSURE 0 -#define TANK_DEFAULT_RELEASE_PRESSURE 16 +#define TANK_DEFAULT_RELEASE_PRESSURE 17 //CANATMOSPASS #define ATMOS_PASS_YES 1 @@ -270,16 +270,9 @@ T.pixel_x = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_X;\ T.pixel_y = (PipingLayer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_P_Y; -#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity()) #define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */ -//prefer this to gas_mixture/total_moles in performance critical areas -#define TOTAL_MOLES(cached_gases, out_var)\ - out_var = 0;\ - for(var/total_moles_id in cached_gases){\ - out_var += cached_gases[total_moles_id];\ - } #ifdef TESTING GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) @@ -288,6 +281,19 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) #define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1 #endif +#define EXTOOLS (world.system_type == MS_WINDOWS ? "byond-extools.dll" : "libbyond-extools.so") + +GLOBAL_VAR(atmos_extools_initialized) // this must be an uninitialized (null) one or init_monstermos will be called twice because reasons +#define ATMOS_EXTOOLS_CHECK if(!GLOB.atmos_extools_initialized){\ + GLOB.atmos_extools_initialized=TRUE;\ + if(fexists(EXTOOLS)){\ + var/result = call(EXTOOLS,"init_monstermos")();\ + if(result != "ok") {CRASH(result);}\ + } else {\ + CRASH("[EXTOOLS] does not exist!");\ + }\ +} + //Unomos - So for whatever reason, garbage collection actually drastically decreases the cost of atmos later in the round. Turning this into a define yields massively improved performance. #define GAS_GARBAGE_COLLECT(GASGASGAS)\ var/list/CACHE_GAS = GASGASGAS;\ @@ -296,10 +302,6 @@ GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) CACHE_GAS -= id;\ } -#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/atom_hud.dm b/code/__DEFINES/atom_hud.dm index 01f14c748e..386473a3ae 100644 --- a/code/__DEFINES/atom_hud.dm +++ b/code/__DEFINES/atom_hud.dm @@ -60,6 +60,7 @@ #define ANTAG_HUD_BROTHER 23 #define ANTAG_HUD_BLOODSUCKER 24 #define ANTAG_HUD_FUGITIVE 25 +#define ANTAG_HUD_HERETIC 26 // Notification action types #define NOTIFY_JUMP "jump" diff --git a/code/__DEFINES/cargo.dm b/code/__DEFINES/cargo.dm index 52a2d56697..bba5b5c5ed 100644 --- a/code/__DEFINES/cargo.dm +++ b/code/__DEFINES/cargo.dm @@ -32,4 +32,8 @@ list("", "\improper S.T.E.A.L.T.H. pod MKVII", "A supply pod that, under normal circumstances, is completely invisible to conventional methods of detection. How are you even seeing this?"),\ list("gondolapod", "gondola", "The silent walker. This one seems to be part of a delivery agency."),\ list("", "", "")\ -) \ No newline at end of file +) + +#define PACK_GOODY_NONE 0 +#define PACK_GOODY_PUBLIC 1 //can be bought by both privates and cargo +#define PACK_GOODY_PRIVATE 2 //can be bought only by privates \ No newline at end of file diff --git a/code/__DEFINES/chemistry/reactions.dm b/code/__DEFINES/chemistry/reactions.dm new file mode 100644 index 0000000000..0deadcbfe0 --- /dev/null +++ b/code/__DEFINES/chemistry/reactions.dm @@ -0,0 +1,4 @@ +// Reaction priorities, higher makes it checked first. Otherwise, it goes based on reaction temperature requirements. + +#define CHEMICAL_REACTION_PRIORITY_DEFAULT 100 +#define CHEMICAL_REACTION_PRIORITY_SMOKE 1000 diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 07f24fd8a3..585e8da7d7 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -98,6 +98,7 @@ #define NO_APHRO (1<<9) #define NO_ASS_SLAP (1<<10) #define BIMBOFICATION (1<<11) +#define NO_AUTO_WAG (1<<12) #define TOGGLES_CITADEL 0 diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index 2f2f94413b..5f4317060d 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -8,6 +8,7 @@ GLOBAL_VAR_INIT(clockwork_construction_value, 0) //The total value of all structures built by the clockwork cult GLOBAL_VAR_INIT(clockwork_vitality, 0) //How much Vitality is stored, total GLOBAL_VAR_INIT(clockwork_power, 0) //How many watts of power are globally available to the clockwork cult +GLOBAL_LIST_EMPTY(active_daemons) //A list of all active tinkerer's daemons GLOBAL_VAR_INIT(neovgre_exists, 0) //Does neovgre exist? GLOBAL_LIST_EMPTY(all_clockwork_objects) //All clockwork items, structures, and effects in existence @@ -19,21 +20,23 @@ GLOBAL_VAR_INIT(ark_of_the_clockwork_justiciar, FALSE) //The Ark on the Reebe z- GLOBAL_VAR_INIT(clockwork_gateway_activated, FALSE) //if a gateway to the celestial derelict has ever been successfully activated GLOBAL_VAR_INIT(script_scripture_unlocked, FALSE) //If script scripture is available, through converting at least one crewmember -GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE) //If script scripture is available +GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE) //If application scripture is available +GLOBAL_VAR_INIT(judgement_scripture_unlocked, FALSE) //If judgement scripture is available GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not used to track existing scripture +GLOBAL_LIST_EMPTY(all_clockwork_rites) //a list containing all clockwork rites. Filled the first time any cultist interacts with a sigil of rites. //Scripture tiers and requirements; peripherals should never be used #define SCRIPTURE_PERIPHERAL "Peripheral" #define SCRIPTURE_DRIVER "Driver" #define SCRIPTURE_SCRIPT "Script" #define SCRIPTURE_APPLICATION "Application" +#define SCRIPTURE_JUDGEMENT "Judgement" //Various costs related to power. #define MAX_CLOCKWORK_POWER 80000 //The max power in W that the cult can stockpile #define SCRIPT_UNLOCK_THRESHOLD 35000 //Scripts will unlock if the total power reaches this amount -#define APPLICATION_UNLOCK_THRESHOLD 50000 //Applications will unlock if the total powre reaches this amount - -#define ABSCOND_ABDUCTION_COST 95 +#define APPLICATION_UNLOCK_THRESHOLD 50000 //Applications will unlock if the total power reaches this amount +#define JUDGEMENT_UNLOCK_THRESHOLD 80000 //might as well have this unlock at a power amount like the other scriptures, Judgement unlocks at this amount. //clockcult power defines #define MIN_CLOCKCULT_POWER 25 //the minimum amount of power clockcult machines will handle gracefully @@ -59,11 +62,11 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us //Ark defines #define GATEWAY_SUMMON_RATE 1 //the time amount the Gateway to the Celestial Derelict gets each process tick; defaults to 1 per tick -#define GATEWAY_REEBE_FOUND 240 //when progress is at or above this, the gateway finds reebe and begins drawing power +#define GATEWAY_REEBE_FOUND 120 //when progress is at or above this, the gateway finds reebe and begins drawing power -#define GATEWAY_RATVAR_COMING 480 //when progress is at or above this, ratvar has entered and is coming through the gateway +#define GATEWAY_RATVAR_COMING 240 //when progress is at or above this, ratvar has entered and is coming through the gateway -#define GATEWAY_RATVAR_ARRIVAL 600 //when progress is at or above this, game over ratvar's here everybody go home +#define GATEWAY_RATVAR_ARRIVAL 300 //when progress is at or above this, game over ratvar's here everybody go home //Objective text define #define CLOCKCULT_OBJECTIVE "Construct the Ark of the Clockwork Justicar and free Ratvar." @@ -81,7 +84,7 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us #define CLOCKWORK_ARMOR_COOLDOWN 1800 //The cooldown period between summoning suits of clockwork armor -#define RATVARIAN_SPEAR_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear +#define RATVARIAN_WEAPON_COOLDOWN 300 //The cooldown period between summoning another Ratvarian spear #define MARAUDER_SCRIPTURE_SCALING_THRESHOLD 600 //The amount of deciseconds that must pass before marauder scripture will not gain a recital penalty @@ -89,4 +92,8 @@ GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not us #define MARAUDER_SCRIPTURE_SCALING_MAX 300 //The maximum extra time applied to the marauder scripture -#define ARK_SCREAM_COOLDOWN 600 //This much time has to pass between instances of the Ark taking damage before it will "scream" again +#define GUARDIAN_EMERGE_THRESHOLD 65 //guardian cannot emerge unless host is at this% or less health + +#define ARK_SCREAM_COOLDOWN 300 //This much time has to pass between instances of the Ark taking damage before it will "scream" again + +#define PRISM_DELAY_DURATION 1200 //how long prolonging prisms delay the shuttle for; defaults to 2 minutes \ No newline at end of file diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 3cb60b1143..14d62f7978 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -108,7 +108,6 @@ #define CLICK_CD_RANGE 4 #define CLICK_CD_RAPID 2 #define CLICK_CD_CLICK_ABILITY 6 -#define CLICK_CD_BREAKOUT 100 #define CLICK_CD_HANDCUFFED 10 #define CLICK_CD_RESIST 20 #define CLICK_CD_GRABBING 10 @@ -155,9 +154,10 @@ #define SHOVE_KNOCKDOWN_HUMAN 30 #define SHOVE_KNOCKDOWN_TABLE 30 #define SHOVE_KNOCKDOWN_COLLATERAL 10 -//for the shove slowdown, see __DEFINES/movespeed_modification.dm -#define SHOVE_SLOWDOWN_LENGTH 30 -#define SHOVE_SLOWDOWN_STRENGTH 0.85 //multiplier +/// how long they're staggered for +#define SHOVE_STAGGER_DURATION 35 +/// how long they're off balance for +#define SHOVE_OFFBALANCE_DURATION 30 //Shove disarming item list GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( /obj/item/gun))) @@ -209,9 +209,9 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define GUN_AIMING_TIME (2 SECONDS) //Object/Item sharpness -#define IS_BLUNT 0 -#define IS_SHARP 1 -#define IS_SHARP_ACCURATE 2 +#define SHARP_NONE 0 +#define SHARP_EDGED 1 +#define SHARP_POINTY 2 //His Grace. #define HIS_GRACE_SATIATED 0 //He hungers not. If bloodthirst is set to this, His Grace is asleep. @@ -269,21 +269,28 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( //stamina cost defines. #define STAM_COST_ATTACK_OBJ_MULT 1.2 -#define STAM_COST_ATTACK_MOB_MULT 0.8 +#define STAM_COST_ATTACK_MOB_MULT 1 #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 +#define STAM_COST_THROW_MOB 2.5 //multiplied by (mob size + 1)^2. ///Multiplier of the (STAMINA_NEAR_CRIT - user current stamina loss) : (STAMINA_NEAR_CRIT - STAMINA_SOFTCRIT) ratio used in damage penalties when stam soft-critted. #define STAM_CRIT_ITEM_ATTACK_PENALTY 0.66 /// changeNext_move penalty multiplier of the above. #define STAM_CRIT_ITEM_ATTACK_DELAY 1.75 /// Damage penalty when fighting prone. -#define LYING_DAMAGE_PENALTY 0.5 +#define LYING_DAMAGE_PENALTY 0.7 /// Added delay when firing guns stam-softcritted. Summed with a hardset CLICK_CD_RANGE delay, similar to STAM_CRIT_DAMAGE_DELAY otherwise. #define STAM_CRIT_GUN_DELAY 2.75 +//stamina recovery defines. Blocked if combat mode is on. +#define STAM_RECOVERY_STAM_CRIT -7.5 +#define STAM_RECOVERY_RESTING -6 +#define STAM_RECOVERY_NORMAL -3 +#define STAM_RECOVERY_LIMB 4 //limbs recover stamina separately from handle_status_effects(), and aren't blocked by combat mode. + /** * should the current-attack-damage be lower than the item force multiplied by this value, * a "inefficiently" prefix will be added to the message. diff --git a/code/__DEFINES/configuration.dm b/code/__DEFINES/configuration.dm index 6b70eb1e0f..a4bf69b2ad 100644 --- a/code/__DEFINES/configuration.dm +++ b/code/__DEFINES/configuration.dm @@ -8,3 +8,12 @@ //flags #define CONFIG_ENTRY_LOCKED 1 //can't edit #define CONFIG_ENTRY_HIDDEN 2 //can't see value + +// Policy config keys +// MAKE SURE THESE ARE UPPERCASE +/// Displayed to cloned patients +#define POLICYCONFIG_ON_CLONE "ON_CLONE" +/// Displayed to defibbed/revival surgery'd patients before the memory loss time threshold +#define POLICYCONFIG_ON_DEFIB_INTACT "ON_DEFIB_INTACT" +/// Displayed to defibbed/revival surgery'd patients after the memory loss time threshold +#define POLICYCONFIG_ON_DEFIB_LATE "ON_DEFIB_LATE" diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm new file mode 100644 index 0000000000..29c7a25dad --- /dev/null +++ b/code/__DEFINES/cooldowns.dm @@ -0,0 +1,71 @@ +//// COOLDOWN SYSTEMS +/* + * We have 2 cooldown systems: timer cooldowns (divided between stoppable and regular) and world.time cooldowns. + * + * When to use each? + * + * * Adding a commonly-checked cooldown, like on a subsystem to check for processing + * * * Use the world.time ones, as they are cheaper. + * + * * Adding a rarely-used one for special situations, such as giving an uncommon item a cooldown on a target. + * * * Timer cooldown, as adding a new variable on each mob to track the cooldown of said uncommon item is going too far. + * + * * Triggering events at the end of a cooldown. + * * * Timer cooldown, registering to its signal. + * + * * Being able to check how long left for the cooldown to end. + * * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this. + * + * * Being able to stop the timer before it ends. + * * * Either world.time or stoppable timer cooldowns, depending on the other factors. Regular timer cooldowns do not support this. +*/ + + +/* + * Cooldown system based on an datum-level associative lazylist using timers. +*/ + +//INDEXES +#define COOLDOWN_EMPLOYMENT_CABINET "employment cabinet" + + +//TIMER COOLDOWN MACROS + +#define COMSIG_CD_STOP(cd_index) "cooldown_[cd_index]" +#define COMSIG_CD_RESET(cd_index) "cd_reset_[cd_index]" + +#define TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time)) + +#define TIMER_COOLDOWN_CHECK(cd_source, cd_index) LAZYACCESS(cd_source.cooldowns, cd_index) + +#define TIMER_COOLDOWN_END(cd_source, cd_index) LAZYREMOVE(cd_source.cooldowns, cd_index) + +/* + * Stoppable timer cooldowns. + * Use indexes the same as the regular tiemr cooldowns. + * They make use of the TIMER_COOLDOWN_CHECK() and TIMER_COOLDOWN_END() macros the same, just not the TIMER_COOLDOWN_START() one. + * A bit more expensive than the regular timers, but can be reset before they end and the time left can be checked. +*/ + +#define S_TIMER_COOLDOWN_START(cd_source, cd_index, cd_time) LAZYSET(cd_source.cooldowns, cd_index, addtimer(CALLBACK(GLOBAL_PROC, /proc/end_cooldown, cd_source, cd_index), cd_time, TIMER_STOPPABLE)) + +#define S_TIMER_COOLDOWN_RESET(cd_source, cd_index) reset_cooldown(cd_source, cd_index) + +#define S_TIMER_COOLDOWN_TIMELEFT(cd_source, cd_index) (timeleft(TIMER_COOLDOWN_CHECK(cd_source, cd_index))) + + +/* + * Cooldown system based on storing world.time on a variable, plus the cooldown time. + * Better performance over timer cooldowns, lower control. Same functionality. +*/ + +#define COOLDOWN_DECLARE(cd_index) var/##cd_index = 0 + +#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + cd_time) + +//Returns true if the cooldown has run its course, false otherwise +#define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time) + +#define COOLDOWN_RESET(cd_source, cd_index) cd_source.cd_index = 0 + +#define COOLDOWN_TIMELEFT(cd_source, cd_index) (max(0, cd_source.cd_index - world.time)) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 141f5626b2..65994dda5a 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -15,33 +15,47 @@ ////////////////////////////////////////////////////////////////// // /datum signals -#define COMSIG_COMPONENT_ADDED "component_added" //sent to the new datum parent when a component is added to them: (/datum/component) -#define COMSIG_COMPONENT_REMOVING "component_removing" //sent to the datum parent before a component is removed from them because of RemoveComponent: (/datum/component) -#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" //sent to the component itself when unregistered from a parent -#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent" //sent to the component itself when registered to a parent -#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" //before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation -#define COMSIG_PARENT_QDELETING "parent_qdeleting" //just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called - -/// Trait signals -#define COMPONENT_ADD_TRAIT (1<<0) -#define COMPONENT_REMOVE_TRAIT (1<<1) +/// when a component is added to a datum: (/datum/component) +#define COMSIG_COMPONENT_ADDED "component_added" +/// before a component is removed from a datum because of RemoveComponent: (/datum/component) +#define COMSIG_COMPONENT_REMOVING "component_removing" +/// before a datum's Destroy() is called: (force), returning a nonzero value will cancel the qdel operation +#define COMSIG_PARENT_PREQDELETED "parent_preqdeleted" +/// just before a datum's Destroy() is called: (force), at this point none of the other components chose to interrupt qdel and Destroy will be called +#define COMSIG_PARENT_QDELETING "parent_qdeleting" +/// generic topic handler (usr, href_list) +#define COMSIG_TOPIC "handle_topic" /// fires on the target datum when an element is attached to it (/datum/element) #define COMSIG_ELEMENT_ATTACH "element_attach" /// fires on the target datum when an element is attached to it (/datum/element) #define COMSIG_ELEMENT_DETACH "element_detach" +/// sent to the component itself when unregistered from a parent +#define COMSIG_COMPONENT_UNREGISTER_PARENT "component_unregister_parent" +/// sent to the component itself when registered to a parent +#define COMSIG_COMPONENT_REGISTER_PARENT "component_register_parent" + +/// Trait signals +#define COMPONENT_ADD_TRAIT (1<<0) +#define COMPONENT_REMOVE_TRAIT (1<<1) + // /atom signals +//from base of atom/proc/Initialize(): sent any time a new atom is created +#define COMSIG_ATOM_CREATED "atom_created" #define COMSIG_PARENT_ATTACKBY "atom_attackby" //from base of atom/attackby(): (/obj/item, /mob/living, params) #define COMPONENT_NO_AFTERATTACK 1 //Return this in response if you don't want afterattack to be called #define COMSIG_ATOM_HULK_ATTACK "hulk_attack" //from base of atom/attack_hulk(): (/mob/living/carbon/human) +#define COMSIG_ATOM_ATTACK_ANIMAL "attack_animal" //from base of atom/animal_attack(): (/mob/user) #define COMSIG_PARENT_EXAMINE "atom_examine" //from base of atom/examine(): (/mob, list/examine_return_text) -#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" //from base of atom/get_examine_name(): (/mob, list/overrides) +///from base of atom/get_examine_name(): (/mob, list/overrides) +#define COMSIG_ATOM_GET_EXAMINE_NAME "atom_examine_name" +#define COMSIG_PARENT_EXAMINE_MORE "atom_examine_more" ///from base of atom/examine_more(): (/mob) //Positions for overrides list - #define EXAMINE_POSITION_ARTICLE 1 - #define EXAMINE_POSITION_BEFORE 2 + #define EXAMINE_POSITION_ARTICLE (1<<0) + #define EXAMINE_POSITION_BEFORE (1<<1) //End positions - #define COMPONENT_EXNAME_CHANGED 1 + #define COMPONENT_EXNAME_CHANGED (1<<0) #define COMSIG_ATOM_UPDATE_ICON "atom_update_icon" //from base of atom/update_icon(): () #define COMSIG_ATOM_NO_UPDATE_ICON_STATE 1 #define COMSIG_ATOM_NO_UPDATE_OVERLAYS 2 @@ -51,30 +65,54 @@ #define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) #define COMPONENT_ATOM_BLOCK_EXIT 1 #define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc) -#define COMSIG_ATOM_EX_ACT "atom_ex_act" //from base of atom/ex_act(): (severity, target) -#define COMSIG_ATOM_EMP_ACT "atom_emp_act" //from base of atom/emp_act(): (severity) -#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" //from base of atom/fire_act(): (exposed_temperature, exposed_volume) -#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" //from base of atom/bullet_act(): (/obj/item/projectile, def_zone) -#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" //from base of atom/blob_act(): (/obj/structure/blob) -#define COMSIG_ATOM_ACID_ACT "atom_acid_act" //from base of atom/acid_act(): (acidpwr, acid_volume) -#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" //from base of atom/emag_act(): () -#define COMSIG_ATOM_RAD_ACT "atom_rad_act" //from base of atom/rad_act(intensity) -#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" //from base of atom/narsie_act(): () -#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): () -#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" //from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) -#define COMSIG_ATOM_SING_PULL "atom_sing_pull" //from base of atom/singularity_pull(): (S, current_size) -#define COMSIG_ATOM_SET_LIGHT "atom_set_light" //from base of atom/set_light(): (l_range, l_power, l_color) -#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" //from base of atom/setDir(): (old_dir, new_dir) -#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" //from base of atom/handle_atom_del(): (atom/deleted) -#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" //from base of atom/has_gravity(): (turf/location, list/forced_gravities) -#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" //from proc/get_rad_contents(): () - #define COMPONENT_BLOCK_RADIATION 1 -#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" //from base of datum/radiation_wave/radiate(): (strength) - #define COMPONENT_BLOCK_CONTAMINATION 1 -#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" //from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width) - #define COMPONENT_RAD_WAVE_HANDLED 1 -#define COMSIG_ATOM_CANREACH "atom_can_reach" //from internal loop in atom/movable/proc/CanReach(): (list/next) - #define COMPONENT_BLOCK_REACH 1 +///from base of atom/ex_act(): (severity, target) +#define COMSIG_ATOM_EX_ACT "atom_ex_act" +///from base of atom/emp_act(): (severity) +#define COMSIG_ATOM_EMP_ACT "atom_emp_act" +///from base of atom/fire_act(): (exposed_temperature, exposed_volume) +#define COMSIG_ATOM_FIRE_ACT "atom_fire_act" +///from base of atom/bullet_act(): (/obj/projectile, def_zone) +#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act" +///from base of atom/blob_act(): (/obj/structure/blob) +#define COMSIG_ATOM_BLOB_ACT "atom_blob_act" +///from base of atom/acid_act(): (acidpwr, acid_volume) +#define COMSIG_ATOM_ACID_ACT "atom_acid_act" +///from base of atom/emag_act(): (/mob/user) +#define COMSIG_ATOM_EMAG_ACT "atom_emag_act" +///from base of atom/rad_act(intensity) +#define COMSIG_ATOM_RAD_ACT "atom_rad_act" +///from base of atom/narsie_act(): () +#define COMSIG_ATOM_NARSIE_ACT "atom_narsie_act" +///from base of atom/ratvar_act(): () +#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" +///from base of atom/rcd_act(): (/mob, /obj/item/construction/rcd, passed_mode) +#define COMSIG_ATOM_RCD_ACT "atom_rcd_act" +///from base of atom/singularity_pull(): (S, current_size) +#define COMSIG_ATOM_SING_PULL "atom_sing_pull" +///from obj/machinery/bsa/full/proc/fire(): () +#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass" + #define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0) +///from base of atom/set_light(): (l_range, l_power, l_color) +#define COMSIG_ATOM_SET_LIGHT "atom_set_light" +///from base of atom/setDir(): (old_dir, new_dir). Called before the direction changes. +#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change" +///from base of atom/handle_atom_del(): (atom/deleted) +#define COMSIG_ATOM_CONTENTS_DEL "atom_contents_del" +///from base of atom/has_gravity(): (turf/location, list/forced_gravities) +#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity" +///from proc/get_rad_contents(): () +#define COMSIG_ATOM_RAD_PROBE "atom_rad_probe" + #define COMPONENT_BLOCK_RADIATION (1<<0) +///from base of datum/radiation_wave/radiate(): (strength) +#define COMSIG_ATOM_RAD_CONTAMINATING "atom_rad_contam" + #define COMPONENT_BLOCK_CONTAMINATION (1<<0) +///from base of datum/radiation_wave/check_obstructions(): (datum/radiation_wave, width) +#define COMSIG_ATOM_RAD_WAVE_PASSING "atom_rad_wave_pass" + #define COMPONENT_RAD_WAVE_HANDLED (1<<0) +///from internal loop in atom/movable/proc/CanReach(): (list/next) +#define COMSIG_ATOM_CANREACH "atom_can_reach" + #define COMPONENT_BLOCK_REACH (1<<0) + #define COMSIG_ATOM_SCREWDRIVER_ACT "atom_screwdriver_act" //from base of atom/screwdriver_act(): (mob/living/user, obj/item/I) #define COMSIG_ATOM_INTERCEPT_TELEPORT "intercept_teleport" //called when teleporting into a protected turf: (channel, turf/origin, turf/destination) #define COMPONENT_BLOCK_TELEPORT 1 @@ -140,10 +178,10 @@ #define HEARING_SPEAKER 2 // #define HEARING_LANGUAGE 3 #define HEARING_RAW_MESSAGE 4 - /* #define HEARING_RADIO_FREQ 5 - #define HEARING_SPANS 6 +// #define HEARING_RADIO_FREQ 5 +// #define HEARING_SPANS 6 #define HEARING_MESSAGE_MODE 7 - #define HEARING_SOURCE 8*/ +// #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) @@ -178,6 +216,10 @@ #define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target) #define COMSIG_MOB_KEY_CHANGE "mob_key_change" //from base of /mob/transfer_ckey(): (new_character, old_character) #define COMSIG_MOB_PRE_PLAYER_CHANGE "mob_pre_player_change" //sent to the target mob from base of /mob/transfer_ckey() and /mind/transfer_to(): (our_character, their_character) +///from /mob/living/handle_eye_contact(): (mob/living/other_mob) +#define COMSIG_MOB_EYECONTACT "mob_eyecontact" + /// return this if you want to block printing this message to this person, if you want to print your own (does not affect the other person's message) + #define COMSIG_BLOCK_EYECONTACT (1<<0) // #define COMPONENT_STOP_MIND_TRANSFER 1 #define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): () #define COMSIG_MOB_ON_NEW_MIND "mob_on_new_mind" //called when a new mind is assigned to a mob: () @@ -197,6 +239,10 @@ #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" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell) +#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item) + #define COMPONENT_BLOCK_SWAP 1 + +#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge" // /client signals #define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) @@ -221,6 +267,11 @@ #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) #define COMSIG_LIVING_GET_BLOCKING_ITEMS "get_blocking_items" //from base of mob/living/get_blocking_items(): (list/items) +#define COMSIG_LIVING_ACTIVE_BLOCK_START "active_block_start" //from base of mob/living/keybind_start_active_blocking(): (obj/item/blocking_item, list/backup_items) + #define COMPONENT_PREVENT_BLOCK_START 1 +#define COMSIG_LIVING_ACTIVE_PARRY_START "active_parry_start" //from base of mob/living/initiate_parry_sequence(): (parrying_method, datum/parrying_item_mob_or_art, list/backup_items) + #define COMPONENT_PREVENT_PARRY_START 1 + //ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! #define COMSIG_LIVING_STATUS_STUN "living_stun" //from base of mob/living/Stun() (amount, update, ignore) #define COMSIG_LIVING_STATUS_KNOCKDOWN "living_knockdown" //from base of mob/living/Knockdown() (amount, update, ignore) @@ -232,7 +283,18 @@ #define COMSIG_LIVING_STATUS_STAGGER "living_stagger" //from base of mob/living/Stagger() (amount, update, ignore) #define COMPONENT_NO_STUN 1 //For all of them -// /mob/living/carbon signals +#define COMSIG_LIVING_LIFE "life_tick" //from base of mob/living/Life() (seconds, times_fired) + #define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes + #define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling + +// /mob/living/carbon physiology signals +#define COMSIG_CARBON_GAIN_WOUND "carbon_gain_wound" //from /datum/wound/proc/apply_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L) +#define COMSIG_CARBON_LOSE_WOUND "carbon_lose_wound" //from /datum/wound/proc/remove_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L) +///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment +#define COMSIG_CARBON_ATTACH_LIMB "carbon_attach_limb" + #define COMPONENT_NO_ATTACH (1<<0) +#define COMSIG_CARBON_REMOVE_LIMB "carbon_remove_limb" //from base of /obj/item/bodypart/proc/drop_limb(special, dismembered) + #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) #define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE) #define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion @@ -250,6 +312,10 @@ #define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) #define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag) #define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value) +#define COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH "obj_default_unfasten_wrench" //called exclusively in plumbing, for now +#define COMSIG_OBJ_ATTACK_GENERIC "obj_attack_generic" //from base of atom/animal_attack(): (/mob/user) + #define COMPONENT_STOP_GENERIC_ATTACK 1 + // /machinery signals #define COMSIG_MACHINE_EJECT_OCCUPANT "eject_occupant" //from base of obj/machinery/dropContents() (occupant) @@ -275,7 +341,13 @@ #define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone) #define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user) #define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args) -#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable) +#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable) +#define COMSIG_ITEM_SHARPEN_ACT "sharpen_act" //from base of item/sharpener/attackby(): (amount, max) + #define COMPONENT_BLOCK_SHARPEN_APPLIED 1 + #define COMPONENT_BLOCK_SHARPEN_BLOCKED 2 + #define COMPONENT_BLOCK_SHARPEN_ALREADY 4 + #define COMPONENT_BLOCK_SHARPEN_MAXED 8 +#define COMSIG_ITEM_MICROWAVE_ACT "microwave_act" //called on item when microwaved (): (obj/machinery/microwave/M) #define COMSIG_ITEM_WORN_OVERLAYS "item_worn_overlays" //from base of obj/item/worn_overlays(): (isinhands, icon_file, used_state, style_flags, list/overlays) // 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) @@ -320,10 +392,10 @@ #define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) // /obj/item/projectile signals (sent to the firer) -#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) -#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb) +#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb) #define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target) -#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/projectile/proc/fire(): () +#define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/item/projectile/proc/fire(): () #define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" // sent to targets during the process_hit proc of projectiles #define COMSIG_EMBED_TRY_FORCE "item_try_embed" // sent when trying to force an embed (mainly for projectiles, only used in the embed element) #define COMSIG_PROJECTILE_PREHIT "com_proj_prehit" ///sent to targets during the process_hit proc of projectiles @@ -333,6 +405,7 @@ // /mob/living/carbon/human signals #define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) #define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker) +#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack" #define COMSIG_HUMAN_DISARM_HIT "human_disarm_hit" //Hit by successful disarm attack (mob/living/carbon/human/attacker,zone_targeted) #define COMSIG_HUMAN_PREFS_COPIED_TO "human_prefs_copied_to" //from datum/preferences/copy_to(): (datum/preferences, icon_updates, roundstart_checks) #define COMSIG_HUMAN_HARDSET_DNA "human_hardset_dna" //from mob/living/carbon/human/hardset_dna(): (ui, list/mutation_index, newreal_name, newblood_type, datum/species, newfeatures) @@ -410,6 +483,14 @@ #define COMSIG_TRY_STORAGE_RETURN_INVENTORY "storage_return_inventory" //(list/list_to_inject_results_into, recursively_search_inside_storages = TRUE) #define COMSIG_TRY_STORAGE_CAN_INSERT "storage_can_equip" //(obj/item/insertion_candidate, mob/user, silent) - returns bool +// /datum/component/two_handed signals +#define COMSIG_TWOHANDED_WIELD "twohanded_wield" //from base of datum/component/two_handed/proc/wield(mob/living/carbon/user): (/mob/user) + #define COMPONENT_TWOHANDED_BLOCK_WIELD 1 +#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" //from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user) + +// /datum/component/squeak signals +#define COMSIG_CROSS_SQUEAKED "cross_squeaked" // sent when a squeak component squeaks from crossing something, to delay anything else crossing that might squeak to prevent ear hurt. + // /datum/action signals #define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) #define COMPONENT_ACTION_BLOCK_TRIGGER 1 diff --git a/code/__DEFINES/exosuit_fabs.dm b/code/__DEFINES/exosuit_fabs.dm new file mode 100644 index 0000000000..d951a7bc28 --- /dev/null +++ b/code/__DEFINES/exosuit_fabs.dm @@ -0,0 +1,35 @@ +/// Module is compatible with Security Cyborg models +#define BORG_MODULE_SECURITY (1<<0) +/// Module is compatible with Miner Cyborg models +#define BORG_MODULE_MINER (1<<1) +/// Module is compatible with Janitor Cyborg models +#define BORG_MODULE_JANITOR (1<<2) +/// Module is compatible with Medical Cyborg models +#define BORG_MODULE_MEDICAL (1<<3) +/// Module is compatible with Engineering Cyborg models +#define BORG_MODULE_ENGINEERING (1<<4) + +/// Module is compatible with Ripley Exosuit models +#define EXOSUIT_MODULE_RIPLEY (1<<0) +/// Module is compatible with Odyseeus Exosuit models +#define EXOSUIT_MODULE_ODYSSEUS (1<<1) +/// Module is compatible with Clarke Exosuit models. Rebranded to firefighter because tg nerfed it to this. +#define EXOSUIT_MODULE_FIREFIGHTER (1<<2) +// #define EXOSUIT_MODULE_CLARKE (1<<2) +/// Module is compatible with Gygax Exosuit models +#define EXOSUIT_MODULE_GYGAX (1<<3) +/// Module is compatible with Durand Exosuit models +#define EXOSUIT_MODULE_DURAND (1<<4) +/// Module is compatible with H.O.N.K Exosuit models +#define EXOSUIT_MODULE_HONK (1<<5) +/// Module is compatible with Phazon Exosuit models +#define EXOSUIT_MODULE_PHAZON (1<<6) +/// Module is compatable with N models +#define EXOSUIT_MODULE_GYGAX_MED (1<<7) + +/// Module is compatible with "Working" Exosuit models - Ripley and Clarke +#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_FIREFIGHTER // | EXOSUIT_MODULE_CLARKE +/// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon +#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON +/// Module is compatible with "Medical" Exosuit modelsm - Odysseus +#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS | EXOSUIT_MODULE_GYGAX_MED diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm index a347fd7327..77e8d82aca 100644 --- a/code/__DEFINES/food.dm +++ b/code/__DEFINES/food.dm @@ -18,4 +18,8 @@ #define DRINK_VERYGOOD 3 #define DRINK_FANTASTIC 4 #define FOOD_AMAZING 5 -#define RACE_DRINK 6 \ No newline at end of file +#define RACE_DRINK 6 + +#define FOOD_IN_CONTAINER (1<<0) + +#define STOP_SERVING_BREAKFAST (15 MINUTES) diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm index 5acda2274c..215e287adf 100644 --- a/code/__DEFINES/footsteps.dm +++ b/code/__DEFINES/footsteps.dm @@ -6,6 +6,9 @@ #define FOOTSTEP_GRASS "grass" #define FOOTSTEP_WATER "water" #define FOOTSTEP_LAVA "lava" +#define FOOTSTEP_MEAT "meat" +#define FOOTSTEP_RUST "rust" + //barefoot sounds #define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot" #define FOOTSTEP_WOOD_CLAW "woodclaw" @@ -89,6 +92,10 @@ GLOBAL_LIST_INIT(footstep, list( 'sound/effects/footstep/lava1.ogg', 'sound/effects/footstep/lava2.ogg', 'sound/effects/footstep/lava3.ogg'), 100, 0), + FOOTSTEP_MEAT = list(list( + 'sound/effects/meatslap.ogg'), 100, 0), + FOOTSTEP_RUST = list(list( + 'sound/effects/footstep/rustystep1.ogg'), 100, 0) )) //bare footsteps lists @@ -131,6 +138,10 @@ GLOBAL_LIST_INIT(barefootstep, list( 'sound/effects/footstep/lava1.ogg', 'sound/effects/footstep/lava2.ogg', 'sound/effects/footstep/lava3.ogg'), 100, 0), + FOOTSTEP_MEAT = list(list( + 'sound/effects/meatslap.ogg'), 100, 0), + FOOTSTEP_RUST = list(list( + 'sound/effects/footstep/rustystep1.ogg'), 100, 0) )) //claw footsteps lists @@ -173,6 +184,10 @@ GLOBAL_LIST_INIT(clawfootstep, list( 'sound/effects/footstep/lava1.ogg', 'sound/effects/footstep/lava2.ogg', 'sound/effects/footstep/lava3.ogg'), 100, 0), + FOOTSTEP_MEAT = list(list( + 'sound/effects/meatslap.ogg'), 100, 0), + FOOTSTEP_RUST = list(list( + 'sound/effects/footstep/rustystep1.ogg'), 100, 0) )) //heavy footsteps list @@ -189,4 +204,8 @@ GLOBAL_LIST_INIT(heavyfootstep, list( 'sound/effects/footstep/lava1.ogg', 'sound/effects/footstep/lava2.ogg', 'sound/effects/footstep/lava3.ogg'), 100, 0), + FOOTSTEP_MEAT = list(list( + 'sound/effects/meatslap.ogg'), 100, 0), + FOOTSTEP_RUST = list(list( + 'sound/effects/footstep/rustystep1.ogg'), 150, 2) )) diff --git a/code/__DEFINES/integrated_electronics.dm b/code/__DEFINES/integrated_electronics.dm index 727314abc6..71bdfb37ea 100644 --- a/code/__DEFINES/integrated_electronics.dm +++ b/code/__DEFINES/integrated_electronics.dm @@ -7,10 +7,10 @@ #define PULSE_CHANNEL "pulse channel" // Methods of obtaining a circuit. -#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and able to be printed in the IC printer. +#define IC_SPAWN_DEFAULT 1 // If the circuit comes in the default circuit box and is able to be printed in the IC printer. #define IC_SPAWN_RESEARCH 2 // If the circuit design will be available in the IC printer after upgrading it. -// Categories that help differentiate circuits that can do different tipes of actions +// Categories that help differentiate circuits that can do different types of actions #define IC_ACTION_MOVEMENT (1<<0) // If the circuit can move the assembly #define IC_ACTION_COMBAT (1<<1) // If the circuit can cause harm #define IC_ACTION_LONG_RANGE (1<<2) // If the circuit communicate with something outside of the assembly diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index a0975f8ecd..66f741b2c7 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -17,7 +17,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( /turf/open/chasm, /turf/open/lava, /turf/open/water, - /turf/open/openspace + /turf/open/transparent/openspace ))) #define isgroundlessturf(A) (is_type_in_typecache(A, GLOB.turfs_without_ground)) @@ -44,6 +44,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isplatingturf(A) (istype(A, /turf/open/floor/plating)) +#define istransparentturf(A) (istype(A, /turf/open/transparent)) + //Mobs #define isliving(A) (istype(A, /mob/living)) @@ -65,9 +67,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isslimeperson(A) (is_species(A, /datum/species/jelly/slime)) #define isluminescent(A) (is_species(A, /datum/species/jelly/luminescent)) #define iszombie(A) (is_species(A, /datum/species/zombie)) -#define ismoth(A) (is_species(A, /datum/species/insect)) #define ishumanbasic(A) (is_species(A, /datum/species/human)) -#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid) ) +#define iscatperson(A) (ishumanbasic(A) && istype(A.dna.species, /datum/species/human/felinid)) #define isdwarf(A) (is_species(A, /datum/species/dwarf)) #define isdullahan(A) (is_species(A, /datum/species/dullahan)) #define isangel(A) (is_species(A, /datum/species/angel)) @@ -76,13 +77,12 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isshadow(A) (is_species(A, /datum/species/shadow)) #define isskeleton(A) (is_species(A, /datum/species/skeleton)) #define isrobotic(A) (is_species(A, /datum/species/ipc) || is_species(A, /datum/species/synthliz)) +#define isethereal(A) (is_species(A, /datum/species/ethereal)) // Citadel specific species #define isipcperson(A) (is_species(A, /datum/species/ipc)) #define issynthliz(A) (is_species(A, /datum/species/synthliz)) #define ismammal(A) (is_species(A, /datum/species/mammal)) -#define isavian(A) (is_species(A, /datum/species/avian)) -#define isaquatic(A) (is_species(A, /datum/species/aquatic)) #define isinsect(A) (is_species(A, /datum/species/insect)) #define isxenoperson(A) (is_species(A, /datum/species/xeno)) #define isstartjelly(A) (is_species(A, /datum/species/jelly/roundstartslime)) @@ -136,6 +136,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define iscat(A) (istype(A, /mob/living/simple_animal/pet/cat)) +#define isdog(A) (istype(A, /mob/living/simple_animal/pet/dog)) + #define iscorgi(A) (istype(A, /mob/living/simple_animal/pet/dog/corgi)) #define ishostile(A) (istype(A, /mob/living/simple_animal/hostile)) @@ -201,21 +203,13 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isclothing(A) (istype(A, /obj/item/clothing)) -GLOBAL_LIST_INIT(pointed_types, typecacheof(list( - /obj/item/pen, - /obj/item/screwdriver, - /obj/item/reagent_containers/syringe, - /obj/item/kitchen/fork))) - -#define is_pointed(W) (is_type_in_typecache(W, GLOB.pointed_types)) - #define isbodypart(A) (istype(A, /obj/item/bodypart)) #define isprojectile(A) (istype(A, /obj/item/projectile)) #define isgun(A) (istype(A, /obj/item/gun)) -#define isfood(A) (istype(A, /obj/item/reagent_containers/food)) +#define isfood(A) (istype(A, /obj/item/reagent_containers/food/snacks)) //Assemblies #define isassembly(O) (istype(O, /obj/item/assembly)) diff --git a/code/__DEFINES/layers_planes.dm b/code/__DEFINES/layers_planes.dm index 6f33bb1a0e..9188efacfd 100644 --- a/code/__DEFINES/layers_planes.dm +++ b/code/__DEFINES/layers_planes.dm @@ -131,6 +131,8 @@ #define LIGHTING_LAYER 15 #define LIGHTING_RENDER_TARGET "LIGHT_PLANE" +#define RAD_TEXT_LAYER 15.1 + #define ABOVE_LIGHTING_PLANE 16 #define ABOVE_LIGHTING_LAYER 16 #define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE" diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm new file mode 100644 index 0000000000..94059c0880 --- /dev/null +++ b/code/__DEFINES/loadout.dm @@ -0,0 +1,56 @@ +//defines for loadout categories +//no category defines +#define LOADOUT_CATEGORY_NONE "ERROR" +#define LOADOUT_SUBCATEGORY_NONE "Miscellaneous" +#define LOADOUT_SUBCATEGORIES_NONE list("Miscellaneous") + +//backpack +#define LOADOUT_CATEGORY_BACKPACK "In backpack" +#define LOADOUT_SUBCATEGORY_BACKPACK_GENERAL "General" //basically anything that there's not enough of to have its own subcategory +#define LOADOUT_SUBCATEGORY_BACKPACK_TOYS "Toys" +//neck +#define LOADOUT_CATEGORY_NECK "Neck" +#define LOADOUT_SUBCATEGORY_NECK_GENERAL "General" +#define LOADOUT_SUBCATEGORY_NECK_TIE "Ties" +#define LOADOUT_SUBCATEGORY_NECK_SCARVES "Scarves" + +//mask +#define LOADOUT_CATEGORY_MASK "Mask" + +//hands +#define LOADOUT_CATEGORY_HANDS "Hands" + +//uniform +#define LOADOUT_CATEGORY_UNIFORM "Uniform" //there's so many types of uniform it's best to have lots of categories +#define LOADOUT_SUBCATEGORY_UNIFORM_GENERAL "General" +#define LOADOUT_SUBCATEGORY_UNIFORM_JOBS "Jobs" +#define LOADOUT_SUBCATEGORY_UNIFORM_SUITS "Suits" +#define LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS "Skirts" +#define LOADOUT_SUBCATEGORY_UNIFORM_DRESSES "Dresses" +#define LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS "Sweaters" +#define LOADOUT_SUBCATEGORY_UNIFORM_PANTS "Pants" +#define LOADOUT_SUBCATEGORY_UNIFORM_SHORTS "Shorts" + +//suit +#define LOADOUT_CATEGORY_SUIT "Suit" +#define LOADOUT_SUBCATEGORY_SUIT_GENERAL "General" +#define LOADOUT_SUBCATEGORY_SUIT_COATS "Coats" +#define LOADOUT_SUBCATEGORY_SUIT_JACKETS "Jackets" +#define LOADOUT_SUBCATEGORY_SUIT_JOBS "Jobs" + +//head +#define LOADOUT_CATEGORY_HEAD "Head" +#define LOADOUT_SUBCATEGORY_HEAD_GENERAL "General" +#define LOADOUT_SUBCATEGORY_HEAD_JOBS "Jobs" + +//shoes +#define LOADOUT_CATEGORY_SHOES "Shoes" + +//gloves +#define LOADOUT_CATEGORY_GLOVES "Gloves" + +//glasses +#define LOADOUT_CATEGORY_GLASSES "Glasses" + +//donator items +#define LOADOUT_CATEGORY_DONATOR "Donator" diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index 7e1559cede..ecb58f1291 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -19,6 +19,7 @@ #define INVESTIGATE_FERMICHEM "fermichem" #define INVESTIGATE_RCD "rcd" #define INVESTIGATE_CRYOGENICS "cryogenics" +#define INVESTIGATE_GHOST "ghost" // Logging types for log_message() #define LOG_ATTACK (1 << 0) @@ -38,6 +39,7 @@ #define LOG_ADMIN_PRIVATE (1 << 14) #define LOG_ASAY (1 << 15) #define LOG_VIRUS (1 << 16) +#define LOG_SHUTTLE (1 << 18) //Individual logging panel pages #define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK) diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm index 5a26feb624..0e8e34d20e 100644 --- a/code/__DEFINES/machines.dm +++ b/code/__DEFINES/machines.dm @@ -115,3 +115,7 @@ //these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified. #define PLANT_GENE_REMOVABLE (1<<0) #define PLANT_GENE_EXTRACTABLE (1<<1) + +#define CLONEPOD_GET_MIND 1 +#define CLONEPOD_POLL_MIND 2 +#define CLONEPOD_NO_MIND 3 \ No newline at end of file diff --git a/code/__DEFINES/materials.dm b/code/__DEFINES/materials.dm index e2ae22345f..72e827a7c8 100644 --- a/code/__DEFINES/materials.dm +++ b/code/__DEFINES/materials.dm @@ -4,8 +4,12 @@ /// Hard materials, such as iron or metal #define MAT_CATEGORY_RIGID "rigid material" +///Use this flag on TRUE if you want the basic recipes +#define MAT_CATEGORY_BASE_RECIPES "basic recipes" + /// Flag for atoms, this flag ensures it isn't re-colored by materials. Useful for snowflake icons such as default toolboxes. #define MATERIAL_COLOR (1<<0) #define MATERIAL_ADD_PREFIX (1<<1) -#define MATERIAL_EFFECTS (1<<2) -#define MATERIAL_AFFECT_STATISTICS (1<<3) \ No newline at end of file +#define MATERIAL_AFFECT_STATISTICS (1<<2) + +#define MATERIAL_SOURCE(mat) "[mat.name]_material" \ No newline at end of file diff --git a/code/__DEFINES/maths.dm b/code/__DEFINES/maths.dm index 24726b8058..370f869c48 100644 --- a/code/__DEFINES/maths.dm +++ b/code/__DEFINES/maths.dm @@ -46,6 +46,8 @@ // Cosecant #define CSC(x) (1 / sin(x)) +#define ATAN2(x, y) ( !(x) && !(y) ? 0 : (y) >= 0 ? arccos((x) / sqrt((x)*(x) + (y)*(y))) : -arccos((x) / sqrt((x)*(x) + (y)*(y))) ) + // Greatest Common Divisor - Euclid's algorithm /proc/Gcd(a, b) return b ? Gcd(b, (a) % (b)) : a diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index a39ebf36ba..927b661898 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -341,10 +341,11 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are. //Endgame Results -#define NUKE_MISS_STATION 1 -#define NUKE_SYNDICATE_BASE 2 -#define STATION_DESTROYED_NUKE 3 -#define STATION_EVACUATED 4 +#define NUKE_NEAR_MISS 1 +#define NUKE_MISS_STATION 2 +#define NUKE_SYNDICATE_BASE 3 +#define STATION_DESTROYED_NUKE 4 +#define STATION_EVACUATED 5 #define BLOB_WIN 8 #define BLOB_NUKE 9 #define BLOB_DESTROYED 10 @@ -432,7 +433,11 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S //text files #define BRAIN_DAMAGE_FILE "traumas.json" #define ION_FILE "ion_laws.json" +#define REDPILL_FILE "redpill.json" #define PIRATE_NAMES_FILE "pirates.json" +#define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json" +#define BONE_SCAR_FILE "wounds/bone_scar_desc.json" +#define SCAR_LOC_FILE "wounds/scar_loc.json" //Fullscreen overlay resolution in tiles. @@ -461,7 +466,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define EGG_LAYING_MESSAGES list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.") // list of all null rod weapons -#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/twohanded/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/clothing/gloves/fingerless/pugilist/chaplain, /obj/item/melee/baseball_bat/chaplain +#define HOLY_WEAPONS /obj/item/nullrod, /obj/item/dualsaber/hypereutactic/chaplain, /obj/item/gun/energy/laser/redtag/hitscan/chaplain, /obj/item/multitool/chaplain, /obj/item/clothing/gloves/fingerless/pugilist/chaplain, /obj/item/melee/baseball_bat/chaplain // Used by PDA and cartridge code to reduce repetitiveness of spritesheets #define PDAIMG(what) {""} @@ -533,3 +538,10 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define LOOT_RESTRICTION_CKEY 2 #define LOOT_RESTRICTION_MIND_PILE 3 //limited to the current pile. #define LOOT_RESTRICTION_CKEY_PILE 4 //Idem + +//stages of shoe tying-ness +#define SHOES_UNTIED 0 +#define SHOES_TIED 1 +#define SHOES_KNOTTED 2 + +#define WANTED_FILE "wanted_message.json" diff --git a/code/__DEFINES/misc/return_values.dm b/code/__DEFINES/misc/return_values.dm deleted file mode 100644 index d55f603de9..0000000000 --- a/code/__DEFINES/misc/return_values.dm +++ /dev/null @@ -1,3 +0,0 @@ -// obj/item/dropped -/// dropped() relocated this item, return FALSE for doUnEquip. -#define ITEM_RELOCATED_BY_DROPPED "relocated_by_dropped" diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 8d8b9f47ae..9c39446a67 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -12,6 +12,8 @@ #define MOVE_INTENT_RUN "run" //Blood levels +#define BLOOD_VOLUME_MAX_LETHAL 2150 +#define BLOOD_VOLUME_EXCESS 2100 #define BLOOD_VOLUME_MAXIMUM 2000 #define BLOOD_VOLUME_SLIME_SPLIT 1120 #define BLOOD_VOLUME_NORMAL 560 @@ -57,11 +59,11 @@ #define BODYPART_NOT_DISABLED 0 #define BODYPART_DISABLED_DAMAGE 1 #define BODYPART_DISABLED_PARALYSIS 2 +#define BODYPART_DISABLED_WOUND 3 #define DEFAULT_BODYPART_ICON 'icons/mob/human_parts.dmi' #define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi' #define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi' -#define DEFAULT_BODYPART_ICON_CITADEL 'modular_citadel/icons/mob/mutant_bodyparts.dmi' #define MONKEY_BODYPART "monkey" #define ALIEN_BODYPART "alien" @@ -98,16 +100,19 @@ #define BRAIN_TRAUMA_MILD /datum/brain_trauma/mild #define BRAIN_TRAUMA_SEVERE /datum/brain_trauma/severe #define BRAIN_TRAUMA_SPECIAL /datum/brain_trauma/special +#define BRAIN_TRAUMA_MAGIC /datum/brain_trauma/magic #define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems #define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery #define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy -#define TRAUMA_RESILIENCE_MAGIC 4 //Curable only with magic -#define TRAUMA_RESILIENCE_ABSOLUTE 5 //This is here to stay +#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound +#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic +#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay //Limit of traumas for each resilience tier #define TRAUMA_LIMIT_BASIC 3 #define TRAUMA_LIMIT_SURGERY 2 +#define TRAUMA_LIMIT_WOUND 2 #define TRAUMA_LIMIT_LOBOTOMY 3 #define TRAUMA_LIMIT_MAGIC 3 #define TRAUMA_LIMIT_ABSOLUTE INFINITY @@ -170,6 +175,15 @@ #define DISGUST_LEVEL_VERYGROSS 50 #define DISGUST_LEVEL_GROSS 25 +//Charge levels for Ethereals +#define ETHEREAL_CHARGE_NONE 0 +#define ETHEREAL_CHARGE_LOWPOWER 20 +#define ETHEREAL_CHARGE_NORMAL 50 +#define ETHEREAL_CHARGE_ALMOSTFULL 75 +#define ETHEREAL_CHARGE_FULL 100 +#define ETHEREAL_CHARGE_OVERLOAD 125 +#define ETHEREAL_CHARGE_DANGEROUS 150 + //Slime evolution threshold. Controls how fast slimes can split/grow #define SLIME_EVOLUTION_THRESHOLD 10 @@ -278,6 +292,7 @@ #define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you #define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases +#define ETHEREAL_CHARGE_FACTOR 0.08 //factor at which ethereal's charge decreases #define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default. #define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism @@ -304,8 +319,17 @@ #define GRAB_PIXEL_SHIFT_NECK 16 #define SLEEP_CHECK_DEATH(X) sleep(X); if(QDELETED(src) || stat == DEAD) return; +#define INTERACTING_WITH(X, Y) (Y in X.do_afters) /// Field of vision defines. #define FOV_90_DEGREES 90 #define FOV_180_DEGREES 180 #define FOV_270_DEGREES 270 + +/// How far away you can be to make eye contact with someone while examining +#define EYE_CONTACT_RANGE 5 + +/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine() +#define EXAMINE_MORE_TIME 1 SECONDS + +#define SILENCE_RANGED_MESSAGE (1<<0) diff --git a/code/__DEFINES/mobs/slowdowns.dm b/code/__DEFINES/mobs/slowdowns.dm index 2d858e9509..4d9b4a0259 100644 --- a/code/__DEFINES/mobs/slowdowns.dm +++ b/code/__DEFINES/mobs/slowdowns.dm @@ -3,7 +3,7 @@ /// How much someone is slowed from fireman carrying a human #define FIREMAN_CARRY_SLOWDOWN 0 /// How much someone is slowed by piggybacking a human -#define PIGGYBACK_CARRY_SLOWDOWN 1 +#define PIGGYBACK_CARRY_SLOWDOWN 0 /// slowdown when in softcrit. Note that crawling slowdown will also apply at the same time! #define SOFTCRIT_ADD_SLOWDOWN 2 /// slowdown when crawling diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm index 699f39e79f..5e7d0a2cca 100644 --- a/code/__DEFINES/movespeed_modification.dm +++ b/code/__DEFINES/movespeed_modification.dm @@ -63,7 +63,6 @@ #define MOVESPEED_ID_TASED_STATUS "TASED" #define MOVESPEED_ID_ELECTROSTAFF "ELECTROSTAFF" -#define MOVESPEED_ID_SHOVE "SHOVE" #define MOVESPEED_ID_FAT "FAT" #define MOVESPEED_ID_COLD "COLD" #define MOVESPEED_ID_HUNGRY "HUNGRY" diff --git a/code/__DEFINES/plumbing.dm b/code/__DEFINES/plumbing.dm new file mode 100644 index 0000000000..5ea7c46b42 --- /dev/null +++ b/code/__DEFINES/plumbing.dm @@ -0,0 +1,9 @@ +#define FIRST_DUCT_LAYER 1 +#define SECOND_DUCT_LAYER 2 +#define THIRD_DUCT_LAYER 4 +#define FOURTH_DUCT_LAYER 8 +#define FIFTH_DUCT_LAYER 16 + +#define DUCT_LAYER_DEFAULT THIRD_DUCT_LAYER + +#define MACHINE_REAGENT_TRANSFER 10 diff --git a/code/__DEFINES/pool.dm b/code/__DEFINES/pool.dm index 1e66109dc7..1bf39dcb1d 100644 --- a/code/__DEFINES/pool.dm +++ b/code/__DEFINES/pool.dm @@ -8,6 +8,5 @@ GLOBAL_LIST_INIT(blacklisted_pool_reagents, list( /datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases /datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc. - /datum/reagent/drug/aphrodisiac, /datum/reagent/drug/anaphrodisiac, /datum/reagent/drug/aphrodisiacplus, /datum/reagent/drug/anaphrodisiacplus, //literally asking for prefbreaks - /datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO. + /datum/reagent/consumable/semen //NO. )) diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm index 4296e3c2e9..63259774fa 100644 --- a/code/__DEFINES/qdel.dm +++ b/code/__DEFINES/qdel.dm @@ -6,10 +6,17 @@ #define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it. #define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference. #define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste. -#define QDEL_HINT_FINDREFERENCE 5 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm. - //if TESTING is enabled, qdel will call this object's find_references() verb. -#define QDEL_HINT_IFFAIL_FINDREFERENCE 6 //Above but only if gc fails. -//defines for the gc_destroyed var + +#ifdef LEGACY_REFERENCE_TRACKING +/** If LEGACY_REFERENCE_TRACKING is enabled, qdel will call this object's find_references() verb. + * + * Functionally identical to QDEL_HINT_QUEUE if GC_FAILURE_HARD_LOOKUP is not enabled in _compiler_options.dm. +*/ +#define QDEL_HINT_FINDREFERENCE 5 +/// Behavior as QDEL_HINT_FINDREFERENCE, but only if the GC fails and a hard delete is forced. +#define QDEL_HINT_IFFAIL_FINDREFERENCE 6 +#endif + #define GC_QUEUE_CHECK 1 #define GC_QUEUE_HARDDELETE 2 diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm index f4beef7ee8..44e97ef345 100644 --- a/code/__DEFINES/reagents.dm +++ b/code/__DEFINES/reagents.dm @@ -57,6 +57,10 @@ #define ADD_REAGENT 2 // reagent added #define REM_REAGENT 3 // reagent removed (may still exist) + +#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die (literally, we'll toss a nuke at whever your ip turns up) +#define RANDOM_PILL_STYLE 22 //Dont change this one though + #define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone //reagent bitflags, used for altering how they works diff --git a/code/__DEFINES/rockpaperscissors.dm b/code/__DEFINES/rockpaperscissors.dm new file mode 100644 index 0000000000..77ba81938d --- /dev/null +++ b/code/__DEFINES/rockpaperscissors.dm @@ -0,0 +1,7 @@ +#define ROCKPAPERSCISSORS_RANGE 3 +#define ROCKPAPERSCISSORS_TIME_LIMIT 20 SECONDS + +#define ROCKPAPERSCISSORS_LOSE "lose" +#define ROCKPAPERSCISSORS_WIN "win" +#define ROCKPAPERSCISSORS_TIE "tie" +#define ROCKPAPERSCISSORS_NOT_DECIDED "not_decided" \ No newline at end of file diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index 7fabb74157..d7487eb54b 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -17,6 +17,7 @@ #define ROLE_ALIEN "xenomorph" #define ROLE_PAI "pAI" #define ROLE_CULTIST "cultist" +#define ROLE_HERETIC "Heretic" #define ROLE_BLOB "blob" #define ROLE_NINJA "space ninja" #define ROLE_MONKEY "monkey" @@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs, ROLE_SENTIENCE, ROLE_GANG = /datum/game_mode/gang, + ROLE_HERETIC = /datum/game_mode/heretics, ROLE_BLOODSUCKER = /datum/game_mode/bloodsucker //ROLE_MONSTERHUNTER Disabled for now )) diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm index aeacdb7c51..20e7975ec4 100644 --- a/code/__DEFINES/rust_g.dm +++ b/code/__DEFINES/rust_g.dm @@ -6,7 +6,7 @@ #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_dmi_create_png(path, width, height, data) call(RUST_G, "dmi_create_png")(path, 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) @@ -14,14 +14,12 @@ #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_METHOD_POST "post" #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 index 659c0fe11b..47aaeeb1dc 100644 --- a/code/__DEFINES/skills/defines.dm +++ b/code/__DEFINES/skills/defines.dm @@ -8,12 +8,6 @@ /// 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 @@ -26,6 +20,13 @@ #define DEF_SKILL_GAIN 1 #define SKILL_GAIN_SURGERY_PER_STEP 0.25 +#define STD_USE_TOOL_MULT 1 +#define EASY_USE_TOOL_MULT 0.75 +#define TRIVIAL_USE_TOOL_MULT 0.5 +#define BARE_USE_TOOL_MULT 0.25 + +//multiplier of the difference of max_value and min_value. Mostly for balance purposes between numerical and level-based skills. +#define STD_NUM_SKILL_ITEM_GAIN_MULTI 0.002 //An extra point for each few seconds of delay when using a tool. Before the multiplier. #define SKILL_GAIN_DELAY_DIVISOR 3 SECONDS @@ -100,4 +101,10 @@ ///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 +#define MODIFIER_SKILL_PRIORITY_MAX 1 //max priority, meant for job/antag modifiers so they don't null out other (de)buffs + +// UI Defines +///Categories of skills, these will be displayed alphabetically. +#define SKILL_UI_CAT_ENG "Engineering" +#define SKILL_UI_CAT_MED "Medical" +#define SKILL_UI_CAT_MISC "Misc" diff --git a/code/__DEFINES/spaceman_dmm.dm b/code/__DEFINES/spaceman_dmm.dm index b9c0544bc1..e21f3dc1c1 100644 --- a/code/__DEFINES/spaceman_dmm.dm +++ b/code/__DEFINES/spaceman_dmm.dm @@ -6,13 +6,28 @@ #define RETURN_TYPE(X) set SpacemanDMM_return_type = X #define SHOULD_CALL_PARENT(X) set SpacemanDMM_should_call_parent = X #define UNLINT(X) SpacemanDMM_unlint(X) + #define SHOULD_NOT_OVERRIDE(X) set SpacemanDMM_should_not_override = X + #define SHOULD_NOT_SLEEP(X) set SpacemanDMM_should_not_sleep = X + #define SHOULD_BE_PURE(X) set SpacemanDMM_should_be_pure = X + #define PRIVATE_PROC(X) set SpacemanDMM_private_proc = X + #define PROTECTED_PROC(X) set SpacemanDMM_protected_proc = X + #define VAR_FINAL var/SpacemanDMM_final + #define VAR_PRIVATE var/SpacemanDMM_private + #define VAR_PROTECTED var/SpacemanDMM_protected #else #define RETURN_TYPE(X) #define SHOULD_CALL_PARENT(X) #define UNLINT(X) X + #define SHOULD_NOT_OVERRIDE(X) + #define SHOULD_NOT_SLEEP(X) + #define SHOULD_BE_PURE(X) + #define PRIVATE_PROC(X) + #define PROTECTED_PROC(X) + #define VAR_FINAL var + #define VAR_PRIVATE var + #define VAR_PROTECTED var #endif /world/proc/enable_debugger() - var/dll = world.GetConfig("env", "EXTOOLS_DLL") - if (dll) - call(dll, "debug_initialize")() + if (fexists(EXTOOLS)) + call(EXTOOLS, "debug_initialize")() diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 4225581018..bfff1dc629 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -36,6 +36,8 @@ #define STATUS_EFFECT_REGENERATIVE_CORE /datum/status_effect/regenerative_core //removes damage slowdown while giving a slow regenerating effect +#define STATUS_EFFECT_DETERMINED /datum/status_effect/determined //currently in a combat high from being seriously wounded + ///////////// // DEBUFFS // ///////////// @@ -107,6 +109,15 @@ #define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim +#define STATUS_EFFECT_LIMP /datum/status_effect/limp //For when you have a busted leg (or two!) and want additional slowdown when walking on that leg + +#define STATUS_EFFECT_AMOK /datum/status_effect/amok //Makes the target automatically strike out at adjecent non-heretics. + +#define STATUS_EFFECT_CLOUDSTRUCK /datum/status_effect/cloudstruck //blinds and applies an overlay. + +/// shoves inflict this to indicate the next shove while this is in effect should disarm guns +#define STATUS_EFFECT_OFF_BALANCE /datum/status_effect/off_balance + ///////////// // NEUTRAL // ///////////// diff --git a/code/__DEFINES/storage/_storage.dm b/code/__DEFINES/storage/_storage.dm index 3a05293d2d..6eb613b423 100644 --- a/code/__DEFINES/storage/_storage.dm +++ b/code/__DEFINES/storage/_storage.dm @@ -19,7 +19,7 @@ /// 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 +#define MINIMUM_PIXELS_PER_ITEM 16 /// 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 diff --git a/code/__DEFINES/storage/volumetrics.dm b/code/__DEFINES/storage/volumetrics.dm index c3f45976ce..e6b732e083 100644 --- a/code/__DEFINES/storage/volumetrics.dm +++ b/code/__DEFINES/storage/volumetrics.dm @@ -24,7 +24,10 @@ GLOBAL_LIST_INIT(default_weight_class_to_volume, list( // Let's keep all of this in one place. given what we put above anyways.. // volume amount for items +/// volume for a data disk #define ITEM_VOLUME_DISK 1 +/// volume for a shotgun stripper clip holding 4 shells +#define ITEM_VOLUME_STRIPPER_CLIP (DEFAULT_VOLUME_NORMAL * 0.5) // #define SAMPLE_VOLUME_AMOUNT 2 diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 8c423ad09c..81b5c5620f 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -107,6 +107,7 @@ #define FIRE_PRIORITY_INSTRUMENTS 30 #define FIRE_PRIORITY_FIELDS 30 #define FIRE_PRIOTITY_SMOOTHING 35 +#define FIRE_PRIORITY_HUDS 40 #define FIRE_PRIORITY_NETWORKS 40 #define FIRE_PRIORITY_OBJ 40 #define FIRE_PRIORITY_ACID 40 @@ -137,28 +138,26 @@ // SSair run section #define SSAIR_PIPENETS 1 #define SSAIR_ATMOSMACHINERY 2 -#define SSAIR_REACTQUEUE 3 -#define SSAIR_EXCITEDGROUPS 4 -#define SSAIR_HIGHPRESSURE 5 -#define SSAIR_HOTSPOTS 6 -#define SSAIR_SUPERCONDUCTIVITY 7 -#define SSAIR_REBUILD_PIPENETS 8 +#define SSAIR_EXCITEDGROUPS 3 +#define SSAIR_HIGHPRESSURE 4 +#define SSAIR_HOTSPOTS 5 +#define SSAIR_SUPERCONDUCTIVITY 6 +#define SSAIR_REBUILD_PIPENETS 7 +#define SSAIR_EQUALIZE 8 +#define SSAIR_ACTIVETURFS 9 +// |= on overlays is not actually guaranteed to not add same appearances but we're optimistically using it anyway. #define COMPILE_OVERLAYS(A)\ if (TRUE) {\ var/list/ad = A.add_overlays;\ var/list/rm = A.remove_overlays;\ - var/list/po = A.priority_overlays;\ if(LAZYLEN(rm)){\ A.overlays -= rm;\ - rm.Cut();\ + A.remove_overlays = null;\ }\ if(LAZYLEN(ad)){\ A.overlays |= ad;\ - ad.Cut();\ - }\ - if(LAZYLEN(po)){\ - A.overlays |= po;\ + A.add_overlays = null;\ }\ A.flags_1 &= ~OVERLAY_QUEUED_1;\ } diff --git a/code/__DEFINES/tgui.dm b/code/__DEFINES/tgui.dm index 5ba0096d1b..f5adeadade 100644 --- a/code/__DEFINES/tgui.dm +++ b/code/__DEFINES/tgui.dm @@ -1,4 +1,28 @@ -#define UI_INTERACTIVE 2 // Green/Interactive -#define UI_UPDATE 1 // Orange/Updates Only -#define UI_DISABLED 0 // Red/Disabled -#define UI_CLOSE -1 // Closed \ No newline at end of file +/// Green eye; fully interactive +#define UI_INTERACTIVE 2 +/// Orange eye; updates but is not interactive +#define UI_UPDATE 1 +/// Red eye; disabled, does not update +#define UI_DISABLED 0 +/// UI Should close +#define UI_CLOSE -1 + +/// Maximum number of windows that can be suspended/reused +#define TGUI_WINDOW_SOFT_LIMIT 5 +/// Maximum number of open windows +#define TGUI_WINDOW_HARD_LIMIT 9 + +/// Maximum ping timeout allowed to detect zombie windows +#define TGUI_PING_TIMEOUT 4 SECONDS + +/// Window does not exist +#define TGUI_WINDOW_CLOSED 0 +/// Window was just opened, but is still not ready to be sent data +#define TGUI_WINDOW_LOADING 1 +/// Window is free and ready to receive data +#define TGUI_WINDOW_READY 2 + +/// Get a window id based on the provided pool index +#define TGUI_WINDOW_ID(index) "tgui-window-[index]" +/// Get a pool index of the provided window id +#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13)) diff --git a/code/__DEFINES/tools.dm b/code/__DEFINES/tools.dm index 7e391caaed..a472e83795 100644 --- a/code/__DEFINES/tools.dm +++ b/code/__DEFINES/tools.dm @@ -17,6 +17,7 @@ //Glasswork Tools #define TOOL_BLOW "blowing_rod" #define TOOL_GLASS_CUT "glasskit" +#define TOOL_BONESET "bonesetter" // If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY, // tool sound is only played when op is started. If not, it's played twice. diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index cd96b054c5..f054f163b5 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -61,6 +61,12 @@ } while (0) #define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE) #define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE) +#define HAS_TRAIT_FROM_ONLY(target, trait, source) (\ + target.status_traits ?\ + (target.status_traits[trait] ?\ + ((source in target.status_traits[trait]) && (length(target.status_traits) == 1))\ + : FALSE)\ + : FALSE) #define HAS_TRAIT_NOT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (length(target.status_traits[trait] - source) > 0) : FALSE) : FALSE) //mob traits @@ -98,7 +104,9 @@ #define TRAIT_RESISTCOLD "resist_cold" #define TRAIT_RESISTHIGHPRESSURE "resist_high_pressure" #define TRAIT_RESISTLOWPRESSURE "resist_low_pressure" +#define TRAIT_BOMBIMMUNE "bomb_immunity" #define TRAIT_RADIMMUNE "rad_immunity" +#define TRAIT_GENELESS "geneless" #define TRAIT_VIRUSIMMUNE "virus_immunity" #define TRAIT_PIERCEIMMUNE "pierce_immunity" #define TRAIT_NODISMEMBER "dismember_immunity" @@ -172,6 +180,7 @@ #define TRAIT_FREERUNNING "freerunning" #define TRAIT_SKITTISH "skittish" #define TRAIT_POOR_AIM "poor_aim" +#define TRAIT_INSANE_AIM "insane_aim" //they don't miss. they never miss. it was all part of their immaculate plan. #define TRAIT_PROSOPAGNOSIA "prosopagnosia" #define TRAIT_DRUNK_HEALING "drunk_healing" #define TRAIT_TAGGER "tagger" @@ -197,7 +206,7 @@ #define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing. #define TRAIT_FAST_PUMP "fast_pump" #define TRAIT_NO_PROCESS_FOOD "no-process-food" // You don't get benefits from nutriment, nor nutrition from reagent consumables -#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good.... +#define TRAIT_NICE_SHOT "nice_shot" //hnnnnnnnggggg..... you're pretty good... // mobility flag traits // IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it) @@ -223,10 +232,12 @@ #define TRAIT_SPRINT_LOCKED "sprint_locked" //non-mob traits -#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it +#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it #define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles #define INNATE_TRAIT "innate" +///Used for managing KEEP_TOGETHER in [appearance_flags] +#define TRAIT_KEEP_TOGETHER "keep-together" // item traits #define TRAIT_NODROP "nodrop" @@ -249,6 +260,7 @@ #define CURSED_ITEM_TRAIT "cursed-item" // The item is magically cursed #define ABSTRACT_ITEM_TRAIT "abstract-item" #define STATUS_EFFECT_TRAIT "status-effect" +#define CLOTHING_TRAIT "clothing" #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention #define GHOSTROLE_TRAIT "ghostrole" #define APHRO_TRAIT "aphro" @@ -303,4 +315,4 @@ #define ACTIVE_BLOCK_TRAIT "active_block" /// This trait is added by the parry system. #define ACTIVE_PARRY_TRAIT "active_parry" -#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name \ No newline at end of file +#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm index 889e1bb1c0..fe46fdc710 100644 --- a/code/__DEFINES/vv.dm +++ b/code/__DEFINES/vv.dm @@ -75,6 +75,14 @@ #define VV_HK_MARK "mark" #define VV_HK_ADDCOMPONENT "addcomponent" #define VV_HK_MODIFY_TRAITS "modtraits" +#define VV_HK_VIEW_REFERENCES "viewreferences" + +// /datum/gas_mixture +#define VV_HK_SET_MOLES "set_moles" +#define VV_HK_EMPTY "empty" +#define VV_HK_SET_TEMPERATURE "set_temp" +#define VV_HK_PARSE_GASSTRING "parse_gasstring" +#define VV_HK_SET_VOLUME "set_volume" // /atom #define VV_HK_MODIFY_TRANSFORM "atom_transform" diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm new file mode 100644 index 0000000000..73ada71423 --- /dev/null +++ b/code/__DEFINES/wounds.dm @@ -0,0 +1,119 @@ + +#define WOUND_DAMAGE_EXPONENT 1.225 + +/// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply) +#define WOUND_MINIMUM_DAMAGE 5 +/// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart +#define DISMEMBER_MINIMUM_DAMAGE 10 +/// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145) +#define WOUND_MAX_CONSIDERED_DAMAGE 35 + + +#define WOUND_SEVERITY_TRIVIAL 0 // for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds +#define WOUND_SEVERITY_MODERATE 1 +#define WOUND_SEVERITY_SEVERE 2 +#define WOUND_SEVERITY_CRITICAL 3 +#define WOUND_SEVERITY_LOSS 4 // theoretical total limb loss, like dismemberment for cuts + +/// any brute weapon/attack that doesn't have sharpness. rolls for blunt bone wounds +#define WOUND_BLUNT 1 +/// any brute weapon/attack with sharpness = SHARP_EDGED. rolls for slash wounds +#define WOUND_SLASH 2 +/// any brute weapon/attack with sharpness = SHARP_POINTY. rolls for piercing wounds +#define WOUND_PIERCE 3 +/// any concentrated burn attack (lasers really). rolls for burning wounds +#define WOUND_BURN 4 + +// How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind()] +#define WOUND_DETERMINATION_MODERATE 1 +#define WOUND_DETERMINATION_SEVERE 2.5 +#define WOUND_DETERMINATION_CRITICAL 5 +#define WOUND_DETERMINATION_LOSS 7.5 + +/// the max amount of determination you can have +#define WOUND_DETERMINATION_MAX 10 + +/// set wound_bonus on an item or attack to this to disable checking wounding for the attack +#define CANT_WOUND -100 + +// list in order of highest severity to lowest +GLOBAL_LIST_INIT(global_wound_types, list(WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate), + WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate), + WOUND_PIERCE = list(/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate), + WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate) + )) + +GLOBAL_LIST_INIT(global_all_wound_types, list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate, + /datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate, + /datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate, + /datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate)) + +// Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse +/// below this has no ill effects from infection +#define WOUND_INFECTION_MODERATE 4 +/// then below here, you ooze some pus and suffer minor tox damage, but nothing serious +#define WOUND_INFECTION_SEVERE 8 +/// then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad +#define WOUND_INFECTION_CRITICAL 12 +/// below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb +#define WOUND_INFECTION_SEPTIC 20 +// above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed + + +/// how quickly sanitization removes infestation and decays per tick +#define WOUND_BURN_SANITIZATION_RATE 0.15 +/// how much blood you can lose per tick per slash max. 8 is a LOT of blood for one cut so don't worry about hitting it easily +#define WOUND_SLASH_MAX_BLOODFLOW 8 +/// dead people don't bleed, but they can clot! this is the minimum amount of clotting per tick on dead people, so even critical cuts will slowly clot in dead people +#define WOUND_SLASH_DEAD_CLOT_MIN 0.05 +/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100) +#define WOUND_BONE_HEAD_TIME_VARIANCE 20 + +// The following are for persistent scar save formats +/// The version number of the scar we're saving +#define SCAR_SAVE_VERS 1 +/// The body_zone we're applying to on granting +#define SCAR_SAVE_ZONE 2 +/// The description we're loading +#define SCAR_SAVE_DESC 3 +/// The precise location we're loading +#define SCAR_SAVE_PRECISE_LOCATION 4 +/// The severity the scar had +#define SCAR_SAVE_SEVERITY 5 +///how many fields there are above (NOT INCLUDING THIS OBVIOUSLY) +#define SCAR_SAVE_LENGTH 5 + +// increment this number when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc) +/// saved scars with a version lower than this will be discarded +#define SCAR_CURRENT_VERSION 1 + + +// With the wounds pt. 2 update, general dismemberment now requires 2 things for a limb to be dismemberable (bone only creatures just need the second): +// 1. Skin is mangled: A critical slash or pierce wound on that limb +// 2. Bone is mangled: At least a severe bone wound on that limb +// see [/obj/item/bodypart/proc/get_mangled_state] for more information +#define BODYPART_MANGLED_NONE 0 +#define BODYPART_MANGLED_BONE 1 +#define BODYPART_MANGLED_FLESH 2 +#define BODYPART_MANGLED_BOTH 3 + +// What kind of biology we have, and what wounds we can suffer, mostly relies on the HAS_FLESH and HAS_BONE species traits on human species +/// golems and androids, cannot suffer any wounds +#define BIO_INORGANIC 0 +/// skeletons and plasmemes, can only suffer bone wounds, only needs mangled bone to be able to dismember +#define BIO_JUST_BONE 1 +/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds +#define BIO_JUST_FLESH 2 +/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember +#define BIO_FLESH_BONE 3 + +/// If this wound requires having the HAS_FLESH flag for humanoids +#define FLESH_WOUND (1<<0) +/// If this wound requires having the HAS_BONE flag for humanaoids +#define BONE_WOUND (1<<1) +/// If having this wound counts as mangled flesh for dismemberment +#define MANGLES_FLESH (1<<2) +/// If having this wound counts as mangled bone for dismemberment +#define MANGLES_BONE (1<<3) +/// If this wound marks the limb as being allowed to have gauze applied +#define ACCEPTS_GAUZE (1<<4) diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index ba29205452..719735392d 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -69,7 +69,7 @@ /proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" ) var/total = input.len if (!total) - return "[nothing_text]" + return nothing_text else if (total == 1) return "[input[1]]" else if (total == 2) diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 48f54fd60f..62e6c4daf9 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -55,7 +55,7 @@ WRITE_LOG(GLOB.world_game_log, "ADMIN: DSAY: [text]") /proc/log_consent(text) - WRITE_LOG(GLOB.world_game_log,"CONSENT: [text]") + WRITE_LOG(GLOB.world_game_log, "CONSENT: [text]") /* All other items are public. */ /proc/log_game(text) @@ -66,6 +66,9 @@ if (CONFIG_GET(flag/log_virus)) WRITE_LOG(GLOB.world_virus_log, "VIRUS: [text]") +/proc/log_asset(text) + WRITE_LOG(GLOB.world_asset_log, "ASSET: [text]") + /proc/log_access(text) if (CONFIG_GET(flag/log_access)) WRITE_LOG(GLOB.world_game_log, "ACCESS: [text]") @@ -78,6 +81,10 @@ if (CONFIG_GET(flag/log_attack)) WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]") +/proc/log_wounded(text) + if (CONFIG_GET(flag/log_attack)) + WRITE_LOG(GLOB.world_attack_log, "WOUND: [text]") + /proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE) if (CONFIG_GET(flag/log_manifest)) WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]") @@ -115,6 +122,9 @@ //reusing the PDA option because I really don't think news comments are worth a config option WRITE_LOG(GLOB.world_pda_log, "COMMENT: [text]") +/proc/log_paper(text) + WRITE_LOG(GLOB.world_paper_log, "PAPER: [text]") + /proc/log_telecomms(text) if (CONFIG_GET(flag/log_telecomms)) WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]") @@ -128,6 +138,10 @@ if (CONFIG_GET(flag/log_vote)) WRITE_LOG(GLOB.world_game_log, "VOTE: [text]") +/proc/log_shuttle(text) + if (CONFIG_GET(flag/log_shuttle)) + WRITE_LOG(GLOB.world_shuttle_log, "SHUTTLE: [text]") + /proc/log_craft(text) if (CONFIG_GET(flag/log_craft)) WRITE_LOG(GLOB.world_crafting_log, "CRAFT: [text]") @@ -187,9 +201,18 @@ WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") /* ui logging */ - -/proc/log_tgui(text) - WRITE_LOG(GLOB.tgui_log, text) +/proc/log_tgui(user_or_client, text) + var/entry = "" + if(!user_or_client) + entry += "no user" + else if(istype(user_or_client, /mob)) + var/mob/user = user_or_client + entry += "[user.ckey] (as [user])" + else if(istype(user_or_client, /client)) + var/client/client = user_or_client + entry += "[client.ckey]" + entry += ":\n[text]" + WRITE_LOG(GLOB.tgui_log, entry) /* Close open log handles. This should be called as late as possible, and no logging should hapen after. */ /proc/shutdown_logging() diff --git a/code/__HELPERS/_string_lists.dm b/code/__HELPERS/_string_lists.dm index 7d694c1844..43d45594e0 100644 --- a/code/__HELPERS/_string_lists.dm +++ b/code/__HELPERS/_string_lists.dm @@ -1,4 +1,5 @@ #define pick_list(FILE, KEY) (pick(strings(FILE, KEY))) +#define pick_list_weighted(FILE, KEY) (pickweight(strings(FILE, KEY))) #define pick_list_replacements(FILE, KEY) (strings_replacement(FILE, KEY)) #define json_load(FILE) (json_decode(file2text(FILE))) diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 5fb4d05d42..4ee622961a 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -85,9 +85,6 @@ GLOBAL_VAR_INIT(cmp_field, "name") /proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B) return A.totalResistance() - B.totalResistance() -/proc/cmp_job_display_asc(datum/job/A, datum/job/B) - return A.display_order - B.display_order - /proc/cmp_uplink_items_dsc(datum/uplink_item/A, datum/uplink_item/B) return sorttext(initial(B.name), initial(A.name)) @@ -97,9 +94,6 @@ GLOBAL_VAR_INIT(cmp_field, "name") /proc/cmp_numbered_displays_name_dsc(datum/numbered_display/A, datum/numbered_display/B) return sorttext(B.sample_object.name, A.sample_object.name) -/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b) - return sorttext(initial(b.name),initial(a.name)) - /proc/cmp_quirk_asc(datum/quirk/A, datum/quirk/B) var/a_sign = num2sign(initial(A.value) * -1) var/b_sign = num2sign(initial(B.value) * -1) @@ -120,3 +114,29 @@ GLOBAL_VAR_INIT(cmp_field, "name") /proc/cmp_item_block_priority_asc(obj/item/A, obj/item/B) return A.block_priority - B.block_priority + +/proc/cmp_skill_categories(datum/skill/A, datum/skill/B) + if(A.ui_category == B.ui_category) + return sorttext(A.name, B.name) + return sorttext(A.ui_category, B.ui_category) + +/proc/cmp_chemical_reactions_default(datum/chemical_reaction/A, datum/chemical_reaction/B) + if(A.priority != B.priority) + return B.priority - A.priority + else if(A.is_cold_recipe) + return A.required_temp - B.required_temp //return coldest + else + return B.required_temp - A.required_temp //return hottest + + +/proc/cmp_mob_realname_dsc(mob/A,mob/B) + return sorttext(A.real_name,B.real_name) + +/proc/cmp_job_display_asc(datum/job/A, datum/job/B) + return A.display_order - B.display_order + +/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b) + return sorttext(initial(b.name),initial(a.name)) + +/proc/cmp_typepaths_asc(A, B) + return sorttext("[B]","[A]") diff --git a/code/__HELPERS/dna.dm b/code/__HELPERS/dna.dm index bb0c89d1f3..b74dacdc09 100644 --- a/code/__HELPERS/dna.dm +++ b/code/__HELPERS/dna.dm @@ -5,8 +5,9 @@ #define GET_INITIALIZED_MUTATION(A) GLOB.all_mutations[A] #define GET_GENE_STRING(A, B) (B.mutation_index[A]) #define GET_SEQUENCE(A) (GLOB.full_sequences[A]) +#define GET_MUTATION_TYPE_FROM_ALIAS(A) (GLOB.alias_mutations[A]) #define GET_MUTATION_STABILIZER(A) ((A.stabilizer_coeff < 0) ? 1 : A.stabilizer_coeff) #define GET_MUTATION_SYNCHRONIZER(A) ((A.synchronizer_coeff < 0) ? 1 : A.synchronizer_coeff) #define GET_MUTATION_POWER(A) ((A.power_coeff < 0) ? 1 : A.power_coeff) -#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff) \ No newline at end of file +#define GET_MUTATION_ENERGY(A) ((A.energy_coeff < 0) ? 1 : A.energy_coeff) diff --git a/code/__HELPERS/do_after.dm b/code/__HELPERS/do_after.dm index f1f483c345..30d40f3867 100644 --- a/code/__HELPERS/do_after.dm +++ b/code/__HELPERS/do_after.dm @@ -166,6 +166,9 @@ var/target_loc = target.loc + LAZYADD(user.do_afters, target) + LAZYADD(target.targeted_by, user) + var/holding = user.get_active_held_item() var/datum/progressbar/progbar if (progress) @@ -183,6 +186,13 @@ break if(uninterruptible) continue + if(!(target in user.do_afters)) + . = FALSE + break + + if(!(target in user.do_afters)) + . = FALSE + break if(drifting && !user.inertia_dir) drifting = 0 @@ -191,13 +201,16 @@ if((!drifting && user.loc != user_loc) || target.loc != target_loc || (!ignorehelditem && user.get_active_held_item() != holding) || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke())) . = 0 break - if (progress) + if(progress) qdel(progbar) + if(!QDELETED(target)) + LAZYREMOVE(user.do_afters, target) + LAZYREMOVE(target.targeted_by, user) //some additional checks as a callback for for do_afters that want to break on losing health or on the mob taking action /mob/proc/break_do_after_checks(list/checked_health, check_clicks) - if(check_clicks && next_move > world.time) + if(check_clicks && !CheckActionCooldown()) return FALSE return TRUE @@ -216,6 +229,10 @@ if(target && !isturf(target)) Tloc = target.loc + if(target) + LAZYADD(user.do_afters, target) + LAZYADD(target.targeted_by, user) + var/atom/Uloc = user.loc var/drifting = 0 @@ -260,6 +277,10 @@ . = 0 break + if(target && !(target in user.do_afters)) + . = FALSE + break + if(needhand) //This might seem like an odd check, but you can still need a hand even when it's empty //i.e the hand is used to pull some item/tool out of the construction @@ -270,8 +291,14 @@ if(user.get_active_held_item() != holding) . = 0 break - if (progress) + if(progress) qdel(progbar) + if(!QDELETED(target)) + LAZYREMOVE(user.do_afters, target) + + if(!QDELETED(target)) + LAZYREMOVE(user.do_afters, target) + LAZYREMOVE(target.targeted_by, user) /mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1 . = 1 @@ -291,6 +318,8 @@ var/list/originalloc = list() for(var/atom/target in targets) originalloc[target] = target.loc + LAZYADD(user.do_afters, target) + LAZYADD(target.targeted_by, user) var/holding = user.get_active_held_item() var/datum/progressbar/progbar @@ -321,3 +350,8 @@ break mainloop if(progbar) qdel(progbar) + for(var/thing in targets) + var/atom/target = thing + if(!QDELETED(target)) + LAZYREMOVE(user.do_afters, target) + LAZYREMOVE(target.targeted_by, user) diff --git a/code/__HELPERS/donator_groupings.dm b/code/__HELPERS/donator_groupings.dm index bdff20553a..4305fb1ed5 100644 --- a/code/__HELPERS/donator_groupings.dm +++ b/code/__HELPERS/donator_groupings.dm @@ -17,9 +17,9 @@ For fast lookups, this is generated using regenerate_donator_grouping_list() /proc/regenerate_donator_grouping_list() GLOB.donators_by_group = list() //reinit everything var/list/donator_list = GLOB.donators_by_group //cache - var/list/tier_1 = TIER_1_DONATORS - donator_list[DONATOR_GROUP_TIER_1] = tier_1.Copy() //The .Copy() is to "decouple"/make a new list, rather than letting the global list impact the config list. - var/list/tier_2 = tier_1 + TIER_2_DONATORS //Using + on lists implies making new lists, so we don't need to manually Copy(). + var/list/tier_3 = TIER_3_DONATORS + donator_list[DONATOR_GROUP_TIER_3] = tier_3.Copy() //The .Copy() is to "decouple"/make a new list, rather than letting the global list impact the config list. + var/list/tier_2 = tier_3 + TIER_2_DONATORS //Using + on lists implies making new lists, so we don't need to manually Copy(). donator_list[DONATOR_GROUP_TIER_2] = tier_2 - var/list/tier_3 = tier_2 + TIER_3_DONATORS - donator_list[DONATOR_GROUP_TIER_3] = tier_3 + var/list/tier_1 = tier_2 + TIER_1_DONATORS + donator_list[DONATOR_GROUP_TIER_1] = tier_1 diff --git a/code/__HELPERS/files.dm b/code/__HELPERS/files.dm index 7c6c186bca..8b4f8d5b54 100644 --- a/code/__HELPERS/files.dm +++ b/code/__HELPERS/files.dm @@ -3,7 +3,7 @@ for(var/file in args) src << browse_rsc(file) -/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html", "md")) +/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list("txt","log","htm", "html", "md", "json")) var/path = root for(var/i=0, i" var/atom/A = thing if (isnull(dir)) @@ -1160,9 +1161,10 @@ GLOBAL_LIST_INIT(freon_color_matrix, list("#2E5E69", "#60A2A8", "#A1AFB1", rgb(0 I = icon(I, icon_state, dir, frame, moving) key = "[generate_asset_name(I)].png" - register_asset(key, I) + if(!SSassets.cache[key]) + register_asset(key, I) for (var/thing2 in targets) - send_asset(thing2, key, FALSE) + send_asset(thing2, key) return "" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 91826ee314..52e26b67e7 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -93,16 +93,16 @@ if(!GLOB.mam_body_markings_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list) if(!GLOB.mam_tails_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list) if(!GLOB.mam_ears_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list) if(!GLOB.mam_snouts_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_snouts, GLOB.mam_snouts_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts/mam_snouts, GLOB.mam_snouts_list) //snowflake check so people's ckey features don't get randomly put on unmonkeys/spawns var/list/snowflake_mam_tails_list = list() for(var/mtpath in GLOB.mam_tails_list) - var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[mtpath] + var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[mtpath] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies)) @@ -120,7 +120,7 @@ snowflake_markings_list[S.name] = mmpath var/list/snowflake_ears_list = list() for(var/mepath in GLOB.mam_ears_list) - var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[mepath] + var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[mepath] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies)) @@ -129,7 +129,7 @@ snowflake_ears_list[S.name] = mepath var/list/snowflake_mam_snouts_list = list() for(var/mspath in GLOB.mam_snouts_list) - var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[mspath] + var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[mspath] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies)) @@ -138,16 +138,16 @@ snowflake_mam_snouts_list[S.name] = mspath var/list/snowflake_ipc_antenna_list = list() for(var/mspath in GLOB.ipc_antennas_list) - var/datum/sprite_accessory/mam_snouts/instance = GLOB.ipc_antennas_list[mspath] + var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.ipc_antennas_list[mspath] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(intendedspecies && S.recommended_species && !S.recommended_species.Find(intendedspecies)) continue if(!S.ckeys_allowed) snowflake_ipc_antenna_list[S.name] = mspath - var/color1 = random_short_color() - var/color2 = random_short_color() - var/color3 = random_short_color() + var/color1 = random_color() + var/color2 = random_color() + var/color3 = random_color() var/body_model = MALE switch(intended_gender) @@ -264,6 +264,13 @@ if(!findname(.)) break +/proc/random_unique_ethereal_name(attempts_to_find_unique_name=10) + for(var/i in 1 to attempts_to_find_unique_name) + . = capitalize(ethereal_name()) + + if(!findname(.)) + break + /proc/random_unique_moth_name(attempts_to_find_unique_name=10) for(var/i in 1 to attempts_to_find_unique_name) . = capitalize(pick(GLOB.moth_first)) + " " + capitalize(pick(GLOB.moth_last)) @@ -375,6 +382,8 @@ GLOBAL_LIST_EMPTY(species_list) override = TRUE if(HAS_TRAIT(M, TRAIT_SIXTHSENSE)) override = TRUE + if(SSticker.current_state == GAME_STATE_FINISHED) + override = TRUE if(isnewplayer(M) && !override) continue if(M.stat != DEAD && !override) diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 8b699e3eee..e1848b21a2 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -4,6 +4,12 @@ else return "[pick(GLOB.lizard_names_female)]-[pick(GLOB.lizard_names_female)]" +/proc/ethereal_name() + var/tempname = "[pick(GLOB.ethereal_names)] [random_capital_letter()]" + if(prob(65)) + tempname += random_capital_letter() + return tempname + /proc/plasmaman_name() return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]" diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index aa388d7413..045ca2c519 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -174,7 +174,7 @@ to_chat(world, "


The round has ended.") if(LAZYLEN(GLOB.round_end_notifiees)) - send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.") + world.TgsTargetedChatBroadcast("[GLOB.round_end_notifiees.Join(", ")] the round has ended.", FALSE) for(var/I in round_end_events) var/datum/callback/cb = I @@ -233,6 +233,7 @@ for(var/antag_name in total_antagonists) var/list/L = total_antagonists[antag_name] log_game("[antag_name]s :[L.Join(", ")].") + set_observer_default_invisibility(0, "The round is over! You are now visible to the living.") CHECK_TICK SSdbcore.SetRoundEnd() diff --git a/code/__HELPERS/sanitize_values.dm b/code/__HELPERS/sanitize_values.dm index cbe1817233..0441e0bcb7 100644 --- a/code/__HELPERS/sanitize_values.dm +++ b/code/__HELPERS/sanitize_values.dm @@ -51,40 +51,111 @@ return default return default -/proc/sanitize_hexcolor(color, desired_format=3, include_crunch=0, default) +#define RGB_FORMAT_INVALID 0 +#define RGB_FORMAT_SHORT 1 +#define RGB_FORMAT_LONG 2 + +/** + * Sanitizes a hexadecimal color. Always outputs lowercase. + * + * @params + * * color - input color, 3 or 6 characters without the #. + * * desired_format - 3 or 6 characters without the potential #. can only put in 3 or 6 here. + * * include_crunch - do we put a # at the start + * * default - default color. must be 3 or 6 characters with or without #. + * * default_replacement - what we replace broken letters with. + */ +/proc/sanitize_hexcolor(color, desired_format = 3, include_crunch = 0, default = rgb(218, 72, 255), default_replacement = "f") + if(!istext(default) || (length(default) < 3)) + CRASH("Default should be a text string of RGB format, with or without the crunch, 3 or 6 characters. Default was instead [default]") + if(!istext(default_replacement) || (length(default_replacement) != 1)) + CRASH("Invalid default_replacement: [default_replacement]") + default_replacement = lowertext(default_replacement) + switch(text2ascii(default_replacement)) + if(48 to 57) + if(97 to 102) + if(65 to 70) + else // yeah yeah i know 3 empty if's.. + CRASH("Invalid default_replacement: [default_replacement]") var/crunch = include_crunch ? "#" : "" if(!istext(color)) - color = "" + color = default - var/start = 1 + (text2ascii(color, 1) == 35) var/len = length(color) - var/char = "" - // RRGGBB -> RGB but awful - var/convert_to_shorthand = desired_format == 3 && length_char(color) > 3 + // get rid of crunch + if(len && color[1] == "#") + if(len >= 2) + color = copytext(color, 2) + else + color = "" + len = length(color) - . = "" - var/i = start - while(i <= len) + switch(desired_format) + if(3) + desired_format = RGB_FORMAT_SHORT + if(6) + desired_format = RGB_FORMAT_LONG + else + CRASH("Invalid desired_format: [desired_format]. Must be 3 or 6.") + var/current_format = RGB_FORMAT_INVALID + switch(length(color)) + if(3) + current_format = RGB_FORMAT_SHORT + if(6) + current_format = RGB_FORMAT_LONG + else + current_format = RGB_FORMAT_INVALID + + if(current_format == RGB_FORMAT_INVALID) // nah + color = default // process default + if(color[1] == "#") // we checked default was at least 3 chars long earlier + color = copytext(color, 2) + len = length(color) + switch(len) + if(3) + current_format = RGB_FORMAT_SHORT + if(6) + current_format = RGB_FORMAT_LONG + else + CRASH("Default was not 3 or 6 RGB hexadecimal characters: [default]") + + var/sanitized = "" + var/char = "" + // first, sanitize hex + for(var/i in 1 to len) char = color[i] switch(text2ascii(char)) - if(48 to 57) //numbers 0 to 9 - . += char - if(97 to 102) //letters a to f - . += char - if(65 to 70) //letters A to F - . += lowertext(char) + if(48 to 57) // 0 to 9 + sanitized += char + if(97 to 102) // a to f + sanitized += char + if(65 to 70) // A to F (capitalized!) + sanitized += lowertext(char) else - break - i += length(char) - if(convert_to_shorthand && i <= len) //skip next one - i += length(color[i]) + sanitized += default_replacement + // do we need to convert? + if(desired_format == current_format) + return crunch + sanitized // no + // yes + if((desired_format == RGB_FORMAT_SHORT) && (current_format == RGB_FORMAT_LONG)) // downconvert + var/temp = "" + // we could do some math but we're lazy and in practice floor()ing this. + for(var/i in 1 to 6 step 2) + temp += sanitized[i] + sanitized = temp + else if((desired_format == RGB_FORMAT_LONG) && (current_format == RGB_FORMAT_SHORT)) // upconvert + var/temp = "" + for(var/i in 1 to 3) + temp += sanitized[i] + temp += sanitized[i] + sanitized = temp + else + CRASH("Invalid desired_format and current_format pair: [desired_format], [current_format]. Could not determine which way to convert.") + return crunch + sanitized - if(length_char(.) != desired_format) - if(default) - return default - return crunch + repeat_string(desired_format, "0") - - return crunch + . +#undef RGB_FORMAT_INVALID +#undef RGB_FORMAT_SHORT +#undef RGB_FORMAT_LONG /proc/sanitize_ooccolor(color) if(length(color) != length_char(color)) diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 9c71cfeb69..7c251edd88 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -113,6 +113,22 @@ else return trim(html_encode(name), max_length) +/** + * stripped_multiline_input but reflects to the user instead if it's too big and returns null. + */ +/proc/stripped_multiline_input_or_reflect(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN, no_trim=FALSE) + var/name = input(user, message, title, default) as message|null + if(isnull(name)) // Return null if canceled. + return null + if(length(name) > max_length) + to_chat(user, name) + to_chat(user, "^^^----- The preceeding message has been DISCARDED for being over the maximum length of [max_length]. It has NOT been sent! -----^^^") + return null + if(no_trim) + return copytext(html_encode(name), 1, max_length) + else + return trim(html_encode(name), max_length) + #define NO_CHARS_DETECTED 0 #define SPACES_DETECTED 1 #define SYMBOLS_DETECTED 2 @@ -760,6 +776,10 @@ GLOBAL_LIST_INIT(binary, list("0","1")) else return "[number]\th" + +/proc/random_capital_letter() + return uppertext(pick(GLOB.alphabet)) + /proc/unintelligize(message) var/regex/word_boundaries = regex(@"\b[\S]+\b", "g") var/prefix = message[1] @@ -811,4 +831,4 @@ GLOBAL_LIST_INIT(binary, list("0","1")) corrupted_text += pick(corruption_options) if(prob(15)) corrupted_text += pick(corruption_options) - return corrupted_text \ No newline at end of file + return corrupted_text diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm index 2c8497d5ed..7a18d2ce01 100644 --- a/code/__HELPERS/type2type.dm +++ b/code/__HELPERS/type2type.dm @@ -339,10 +339,24 @@ /proc/isLeap(y) return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0)) - +/// For finding out what body parts a body zone covers, the inverse of the below basically +/proc/zone2body_parts_covered(def_zone) + switch(def_zone) + if(BODY_ZONE_CHEST) + return list(CHEST, GROIN) + if(BODY_ZONE_HEAD) + return list(HEAD) + if(BODY_ZONE_L_ARM) + return list(ARM_LEFT, HAND_LEFT) + if(BODY_ZONE_R_ARM) + return list(ARM_RIGHT, HAND_RIGHT) + if(BODY_ZONE_L_LEG) + return list(LEG_LEFT, FOOT_LEFT) + if(BODY_ZONE_R_LEG) + return list(LEG_RIGHT, FOOT_RIGHT) //Turns a Body_parts_covered bitfield into a list of organ/limb names. -//(I challenge you to find a use for this) +//(I challenge you to find a use for this) -I found a use for it!! /proc/body_parts_covered2organ_names(bpc) var/list/covered_parts = list() diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 337d44aa1e..4addae3ac4 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1437,7 +1437,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) /obj/item/reagent_containers/food/snacks/grown, /obj/item/reagent_containers/food/snacks/grown/mushroom, /obj/item/reagent_containers/food/snacks/grown/nettle, // base type - /obj/item/reagent_containers/food/snacks/deepfryholder, /obj/item/reagent_containers/food/snacks/grown/shell, /obj/item/reagent_containers/food/snacks/clothing, /obj/item/reagent_containers/food/snacks/store/bread @@ -1509,6 +1508,8 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) set waitfor = FALSE return call(source, proctype)(arglist(arguments)) +#define TURF_FROM_COORDS_LIST(List) (locate(List[1], List[2], List[3])) + /proc/num2sign(numeric) if(numeric > 0) return 1 diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 9a36c626ba..0e0bd4ffaa 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -11,15 +11,28 @@ #ifdef TESTING #define DATUMVAR_DEBUGGING_MODE -//#define GC_FAILURE_HARD_LOOKUP //makes paths that fail to GC call find_references before del'ing. - //implies FIND_REF_NO_CHECK_TICK +/* +* Enables extools-powered reference tracking system, letting you see what is referencing objects that refuse to hard delete. +* +* * Requires TESTING to be defined to work. +*/ +//#define REFERENCE_TRACKING -//#define FIND_REF_NO_CHECK_TICK //Sets world.loop_checks to false and prevents find references from sleeping +///Method of tracking references without using extools. Slower, kept to avoid over-reliance on extools. +//#define LEGACY_REFERENCE_TRACKING +#ifdef LEGACY_REFERENCE_TRACKING +///Use the legacy reference on things hard deleting by default. +//#define GC_FAILURE_HARD_LOOKUP +#ifdef GC_FAILURE_HARD_LOOKUP +#define FIND_REF_NO_CHECK_TICK +#endif //ifdef GC_FAILURE_HARD_LOOKUP + +#endif //ifdef LEGACY_REFERENCE_TRACKING //#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green -#endif +#endif //ifdef TESTING //#define UNIT_TESTS //Enables unit tests via TEST_RUN_PARAMETER #ifndef PRELOAD_RSC //set to: diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm index 01a34c2ab7..960e1f8d59 100644 --- a/code/_globalvars/game_modes.dm +++ b/code/_globalvars/game_modes.dm @@ -9,4 +9,8 @@ GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report //TODO clear this one up too -GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult) \ No newline at end of file +GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult) + + +///We want reality_smash_tracker to exist only once and be accesable from anywhere. +GLOBAL_DATUM_INIT(reality_smash_track, /datum/reality_smash_tracker, new) diff --git a/code/_globalvars/genetics.dm b/code/_globalvars/genetics.dm index 39702fd62f..cebeab7a78 100644 --- a/code/_globalvars/genetics.dm +++ b/code/_globalvars/genetics.dm @@ -27,5 +27,6 @@ GLOBAL_LIST_EMPTY(full_sequences) GLOBAL_LIST_EMPTY(bad_mutations) GLOBAL_LIST_EMPTY(good_mutations) GLOBAL_LIST_EMPTY(not_good_mutations) +GLOBAL_LIST_EMPTY(alias_mutations) //alias = type -GLOBAL_LIST_EMPTY(mutation_recipes) \ No newline at end of file +GLOBAL_LIST_EMPTY(mutation_recipes) diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 598fde2bc3..71c2b2e13b 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -40,6 +40,46 @@ GLOBAL_LIST_EMPTY(insect_fluffs_list) GLOBAL_LIST_EMPTY(insect_markings_list) GLOBAL_LIST_EMPTY(caps_list) +//a way to index the right bodypart list given the type of bodypart +GLOBAL_LIST_INIT(mutant_reference_list, list( + "tail_lizard" = GLOB.tails_list_lizard, + "waggingtail_lizard" = GLOB.animated_tails_list_lizard, + "tail_human" = GLOB.tails_list_human, + "waggingtail_human" = GLOB.animated_tails_list_human, + "spines" = GLOB.spines_list, + "waggingspines" = GLOB.animated_spines_list, + "snout" = GLOB.snouts_list, + "frills" = GLOB.frills_list, + "horns" = GLOB.horns_list, + "ears" = GLOB.ears_list, + "body_markings" = GLOB.body_markings_list, + "wings" = GLOB.wings_list, + "wingsopen" = GLOB.wings_open_list, + "deco_wings" = GLOB.deco_wings_list, + "legs" = GLOB.legs_list, + "insect_wings" = GLOB.insect_wings_list, + "insect_fluff" = GLOB.insect_fluffs_list, + "insect_markings" = GLOB.insect_markings_list, + "caps" = GLOB.caps_list, + "ipc_screen" = GLOB.ipc_screens_list, + "ipc_antenna" = GLOB.ipc_antennas_list, + "mam_tail" = GLOB.mam_tails_list, + "mam_waggingtail" = GLOB.mam_tails_animated_list, + "mam_body_markings" = GLOB.mam_body_markings_list, + "mam_ears" = GLOB.mam_ears_list, + "mam_snouts" = GLOB.mam_snouts_list, + "taur" = GLOB.taur_list, + "xenodorsal" = GLOB.xeno_dorsal_list, + "xenohead" = GLOB.xeno_head_list, + "xenotail" = GLOB.xeno_tail_list)) + +//references wag types to regular types, wings open to wings, etc +GLOBAL_LIST_INIT(mutant_transform_list, list("wingsopen" = "wings", + "waggingtail_human" = "tail_human", + "waggingtail_lizard" = "tail_lizard", + "waggingspines" = "spines", + "mam_waggingtail" = "mam_tail")) + GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list("ghost")) //stores the ghost forms that support hair and other such things @@ -116,15 +156,16 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list( GLOBAL_LIST_INIT(security_depts_prefs, list(SEC_DEPT_RANDOM, SEC_DEPT_NONE, SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, SEC_DEPT_SCIENCE, SEC_DEPT_SUPPLY)) - //Backpacks -#define GBACKPACK "Grey Backpack" -#define GSATCHEL "Grey Satchel" -#define GDUFFELBAG "Grey Duffel Bag" -#define LSATCHEL "Leather Satchel" +//Backpacks #define DBACKPACK "Department Backpack" #define DSATCHEL "Department Satchel" #define DDUFFELBAG "Department Duffel Bag" -GLOBAL_LIST_INIT(backbaglist, list(DBACKPACK, DSATCHEL, DDUFFELBAG, GBACKPACK, GSATCHEL, GDUFFELBAG, LSATCHEL)) +GLOBAL_LIST_INIT(backbaglist, list(DBACKPACK, DSATCHEL, DDUFFELBAG, //everything after this point is a non-department backpack + "Grey Backpack" = /obj/item/storage/backpack, + "Grey Satchel" = /obj/item/storage/backpack/satchel, + "Grey Duffel Bag" = /obj/item/storage/backpack/duffelbag, + "Leather Satchel" = /obj/item/storage/backpack/satchel/leather, + "Snail Shell" = /obj/item/storage/backpack/snail)) //Suit/Skirt #define PREF_SUIT "Jumpsuit" @@ -224,5 +265,21 @@ GLOBAL_LIST_INIT(admiral_messages, list("Do you know how expensive these station 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\]")) - GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt")) + +GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "declares", "bellows", "buzzes" ,"beeps", "chirps" ,"hisses" ,"poofs" ,"rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters")) + +GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc)) + +//locked parts are those that your picked species requires to have +//unlocked parts are those that anyone can choose on customisation regardless +//parts not in unlocked, but in all, are thus locked +GLOBAL_LIST_INIT(all_mutant_parts, list("tail_lizard" = "Tail", "mam_tail" = "Tail", "tail_human" = "Tail", "snout" = "Snout", "frills" = "Frills", "spines" = "Spines", "body_markings" = "Body Markings", "mam_body_markings" = "Species Markings" , "mam_ears" = "Ears", "ears" = "Ears", "mam_snouts" = "Snout", "legs" = "Legs", "deco_wings" = "Decorative Wings", "insect_wings" = "Insect Wings", "insect_fluff" = "Insect Fluff", "taur" = "Tauric Body", "insect_markings" = "Insect Markings", "wings" = "Wings", "xenohead" = "Caste Head", "xenotail" = "Tail", "xenodorsal" = "Dorsal Spines", "ipc_screen" = "Screen", "ipc_antenna" = "Antenna", "meat_type" = "Meat Type", "horns" = "Horns")) +GLOBAL_LIST_INIT(unlocked_mutant_parts, list("horns", "insect_fluff")) +//parts in either of the above two lists that require a second option that allows them to be coloured +GLOBAL_LIST_INIT(colored_mutant_parts, list("insect_wings" = "wings_color", "deco_wings" = "wings_color", "horns" = "horns_color")) + +//species ids that have greyscale sprites +GLOBAL_LIST_INIT(greyscale_limb_types, list("human","moth","lizard","pod","plant","jelly","slime","golem","lum","stargazer","mush","ethereal","snail","c_golem","b_golem","mammal","xeno","ipc","insect","synthliz","avian","aquatic")) + +//species ids that need snowflake coloring applied diff --git a/code/_globalvars/lists/loadout_categories.dm b/code/_globalvars/lists/loadout_categories.dm new file mode 100644 index 0000000000..0f0ac52214 --- /dev/null +++ b/code/_globalvars/lists/loadout_categories.dm @@ -0,0 +1,13 @@ +GLOBAL_LIST_INIT(loadout_categories, list( + LOADOUT_CATEGORY_BACKPACK = list(LOADOUT_SUBCATEGORY_BACKPACK_GENERAL, LOADOUT_SUBCATEGORY_BACKPACK_TOYS), + LOADOUT_CATEGORY_NECK = list(LOADOUT_SUBCATEGORY_NECK_GENERAL, LOADOUT_SUBCATEGORY_NECK_TIE, LOADOUT_SUBCATEGORY_NECK_SCARVES), + LOADOUT_CATEGORY_MASK = LOADOUT_SUBCATEGORIES_NONE, + LOADOUT_CATEGORY_HANDS = LOADOUT_SUBCATEGORIES_NONE, + LOADOUT_CATEGORY_UNIFORM = list(LOADOUT_SUBCATEGORY_UNIFORM_GENERAL, LOADOUT_SUBCATEGORY_UNIFORM_JOBS, LOADOUT_SUBCATEGORY_UNIFORM_SUITS, LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS, LOADOUT_SUBCATEGORY_UNIFORM_DRESSES, LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS, LOADOUT_SUBCATEGORY_UNIFORM_PANTS, LOADOUT_SUBCATEGORY_UNIFORM_SHORTS), + LOADOUT_CATEGORY_SUIT = list(LOADOUT_SUBCATEGORY_SUIT_GENERAL, LOADOUT_SUBCATEGORY_SUIT_COATS, LOADOUT_SUBCATEGORY_SUIT_JACKETS, LOADOUT_SUBCATEGORY_SUIT_JOBS), + LOADOUT_CATEGORY_HEAD = list(LOADOUT_SUBCATEGORY_HEAD_GENERAL, LOADOUT_SUBCATEGORY_HEAD_JOBS), + LOADOUT_CATEGORY_SHOES = LOADOUT_SUBCATEGORIES_NONE, + LOADOUT_CATEGORY_GLOVES = LOADOUT_SUBCATEGORIES_NONE, + LOADOUT_CATEGORY_GLASSES = LOADOUT_SUBCATEGORIES_NONE, + LOADOUT_CATEGORY_DONATOR = LOADOUT_SUBCATEGORIES_NONE +)) diff --git a/code/_globalvars/lists/mapping.dm b/code/_globalvars/lists/mapping.dm index d214ec94ef..94b0338412 100644 --- a/code/_globalvars/lists/mapping.dm +++ b/code/_globalvars/lists/mapping.dm @@ -38,8 +38,7 @@ GLOBAL_LIST_EMPTY(servant_spawns) //Servants of Ratvar spawn here GLOBAL_LIST_EMPTY(city_of_cogs_spawns) //Anyone entering the City of Cogs spawns here GLOBAL_LIST_EMPTY(ruin_landmarks) - //away missions -GLOBAL_LIST_EMPTY(awaydestinations) //a list of landmarks that the warpgate can take you to +//away missions GLOBAL_LIST_EMPTY(vr_spawnpoints) //used by jump-to-area etc. Updated by area/updateName() diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 959a62ebf8..134f9d9cbe 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY(joined_player_list) //all clients that have joined the game a GLOBAL_LIST_EMPTY(silicon_mobs) //all silicon mobs GLOBAL_LIST_EMPTY(mob_living_list) //all instances of /mob/living and subtypes GLOBAL_LIST_EMPTY(carbon_list) //all instances of /mob/living/carbon and subtypes, notably does not contain brains or simple animals +GLOBAL_LIST_EMPTY(human_list) //all instances of /mob/living/carbon/human and subtypes GLOBAL_LIST_EMPTY(ai_list) GLOBAL_LIST_EMPTY(pai_list) GLOBAL_LIST_EMPTY(available_ai_shells) diff --git a/code/_globalvars/lists/names.dm b/code/_globalvars/lists/names.dm index e334d08040..b80fcf0bbf 100644 --- a/code/_globalvars/lists/names.dm +++ b/code/_globalvars/lists/names.dm @@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt")) GLOBAL_LIST_INIT(moth_first, world.file2list("strings/names/moth_first.txt")) GLOBAL_LIST_INIT(moth_last, world.file2list("strings/names/moth_last.txt")) GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt")) +GLOBAL_LIST_INIT(ethereal_names, world.file2list("strings/names/ethereal.txt")) GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt")) GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")) GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt")) diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index 4de7c88bf7..fee70ee3d5 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -41,3 +41,6 @@ GLOBAL_LIST_EMPTY(ai_status_displays) GLOBAL_LIST_EMPTY(mob_spawners) // All mob_spawn objects GLOBAL_LIST_EMPTY(alert_consoles) // Station alert consoles, /obj/machinery/computer/station_alert + +//list of everyone playing rock paper scissors +GLOBAL_LIST_EMPTY(rockpaperscissors_players) diff --git a/code/_globalvars/logging.dm b/code/_globalvars/logging.dm index 65fd772dfe..e9f98f836e 100644 --- a/code/_globalvars/logging.dm +++ b/code/_globalvars/logging.dm @@ -28,8 +28,12 @@ GLOBAL_VAR(world_job_debug_log) GLOBAL_PROTECT(world_job_debug_log) GLOBAL_VAR(world_virus_log) GLOBAL_PROTECT(world_virus_log) +GLOBAL_VAR(world_asset_log) +GLOBAL_PROTECT(world_asset_log) GLOBAL_VAR(world_map_error_log) GLOBAL_PROTECT(world_map_error_log) +GLOBAL_VAR(world_paper_log) +GLOBAL_PROTECT(world_paper_log) GLOBAL_VAR(subsystem_log) GLOBAL_PROTECT(subsystem_log) GLOBAL_VAR(reagent_log) @@ -47,10 +51,10 @@ GLOBAL_LIST_EMPTY(lastsignalers) //keeps last 100 signals here in format: "[src] GLOBAL_PROTECT(lastsignalers) GLOBAL_LIST_EMPTY(lawchanges) //Stores who uploaded laws to which silicon-based lifeform, and what the law was GLOBAL_PROTECT(lawchanges) - GLOBAL_VAR(tgui_log) GLOBAL_PROTECT(tgui_log) - +GLOBAL_VAR(world_shuttle_log) +GLOBAL_PROTECT(world_shuttle_log) GLOBAL_LIST_EMPTY(combatlog) GLOBAL_PROTECT(combatlog) GLOBAL_LIST_EMPTY(IClog) diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index 8d8b8820b2..605b20a4f3 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -37,7 +37,9 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD, "TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE, "TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE, + "TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE, "TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE, + "TRAIT_GENELESS" = TRAIT_GENELESS, "TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE, "TRAIT_PIERCEIMMUNE" = TRAIT_PIERCEIMMUNE, "TRAIT_NODISMEMBER" = TRAIT_NODISMEMBER, diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index 02cbd6bea5..18aaf66659 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -19,10 +19,6 @@ A.move_camera_by_click() /mob/living/silicon/ai/ClickOn(var/atom/A, params) - if(world.time <= next_click) - return - next_click = world.time + 1 - if(!can_interact_with(A)) return @@ -74,16 +70,16 @@ CtrlClickOn(A) return - if(world.time <= next_move) + if(!CheckActionCooldown(immediate = TRUE)) return if(aicamera.in_camera_mode) aicamera.camera_mode_off() - aicamera.captureimage(pixel_turf, usr) + INVOKE_ASYNC(aicamera, /obj/item/camera.proc/captureimage, pixel_turf, usr) return if(waypoint_mode) - waypoint_mode = 0 - set_waypoint(A) + waypoint_mode = FALSE + INVOKE_ASYNC(src, .proc/set_waypoint, A) return A.attack_ai(src) @@ -94,8 +90,9 @@ The below is only really for safety, or you can alter the way it functions and re-insert it above. */ -/mob/living/silicon/ai/UnarmedAttack(atom/A) +/mob/living/silicon/ai/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) A.attack_ai(src) + /mob/living/silicon/ai/RangedAttack(atom/A) A.attack_ai(src) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index ecbcb6ec01..042ab3aaee 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -1,38 +1,3 @@ -/* - Click code cleanup - ~Sayu -*/ - -// 1 decisecond click delay (above and beyond mob/next_move) -//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move() -/mob/var/next_click = 0 - -// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK -/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or - -/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by - - -//Delays the mob's next click/action by num deciseconds -// eg: 10-3 = 7 deciseconds of delay -// eg: 10*0.5 = 5 deciseconds of delay -// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK - -/mob/proc/timeToNextMove() - return max(0, next_move - world.time) - -/mob/proc/changeNext_move(num) - next_move = world.time + ((num+next_move_adjust)*next_move_modifier) - -/mob/living/changeNext_move(num) - last_click_move = next_move - var/mod = next_move_modifier - var/adj = next_move_adjust - for(var/i in status_effects) - var/datum/status_effect/S = i - mod *= S.nextmove_modifier() - adj += S.nextmove_adjust() - next_move = world.time + ((num + adj)*mod) - /* Before anything else, defer these calls to a per-mobtype handler. This allows us to remove istype() spaghetti code, but requires the addition of other handler procs to simplify it. @@ -45,7 +10,7 @@ /atom/Click(location,control,params) if(flags_1 & INITIALIZED_1) SEND_SIGNAL(src, COMSIG_CLICK, location, control, params, usr) - usr.ClickOn(src, params) + usr.CommonClickOn(src, params) /atom/DblClick(location,control,params) if(flags_1 & INITIALIZED_1) @@ -55,6 +20,21 @@ if(flags_1 & INITIALIZED_1) usr.MouseWheelOn(src, delta_x, delta_y, params) +/** + * Common mob click code + */ +/mob/proc/CommonClickOn(atom/A, params) + SHOULD_NOT_SLEEP(TRUE) + if(mob_transforming) + return + if(SEND_SIGNAL(src, COMSIG_MOB_CLICKON, A, params) & COMSIG_MOB_CANCEL_CLICKON) + return + . = ClickOn(A, params) + if(!(. & DISCARD_LAST_ACTION)) + FlushCurrentAction() + else + DiscardCurrentAction() + /* Standard mob ClickOn() Handles exceptions: Buildmode, middle click, modified clicks, mech actions @@ -68,50 +48,34 @@ * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed */ -/mob/proc/ClickOn( atom/A, params ) - if(world.time <= next_click) - return - next_click = world.time + world.tick_lag - +/mob/proc/ClickOn(atom/A, params) + SHOULD_NOT_SLEEP(TRUE) if(check_click_intercept(params,A)) return - if(notransform) - return - - 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) - return + return ShiftMiddleClickOn(A) if(modifiers["shift"] && modifiers["ctrl"]) - CtrlShiftClickOn(A) - return + return CtrlShiftClickOn(A) if(modifiers["middle"]) - MiddleClickOn(A) - return + return MiddleClickOn(A) if(modifiers["shift"] && (client && client.show_popup_menus || modifiers["right"])) //CIT CHANGE - makes shift-click examine use right click instead of left click in combat mode - ShiftClickOn(A) - return + return ShiftClickOn(A) if(modifiers["alt"]) // alt and alt-gr (rightalt) - AltClickOn(A) - return + return AltClickOn(A) if(modifiers["ctrl"]) - CtrlClickOn(A) - return + return CtrlClickOn(A) if(modifiers["right"]) //CIT CHANGE - allows right clicking to perform actions - RightClickOn(A,params) //CIT CHANGE - ditto - return //CIT CHANGE - ditto + return RightClickOn(A, params) //CIT CHANGE - ditto if(incapacitated(ignore_restraints = 1)) return face_atom(A) - if(next_move > world.time) // in the year 2000... + if(!CheckActionCooldown(immediate = TRUE)) return if(!modifiers["catcher"] && A.IsObscured()) @@ -119,12 +83,12 @@ if(ismecha(loc)) var/obj/mecha/M = loc - return M.click_action(A,src,params) + M.click_action(A,src,params) + return TRUE if(restrained()) - changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow - RestrainedClickOn(A) - return + DelayNextAction(CLICK_CD_HANDCUFFED) + return RestrainedClickOn(A) if(in_throw_mode) throw_item(A) @@ -141,12 +105,12 @@ //User itself, current loc, and user inventory if(A in DirectAccess()) if(W) - W.melee_attack_chain(src, A, params) + return W.melee_attack_chain(src, A, params) else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - UnarmedAttack(A) - return + . = UnarmedAttack(A, TRUE, a_intent) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A)) + DelayNextAction(CLICK_CD_MELEE) + return //Can't reach anything else in lockers or other weirdness if(!loc.AllowClick()) @@ -155,16 +119,17 @@ //Standard reach turf to turf or reaching inside storage if(CanReach(A,W)) if(W) - W.melee_attack_chain(src, A, params) + return W.melee_attack_chain(src, A, params) else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - UnarmedAttack(A, 1) + . = UnarmedAttack(A, TRUE, a_intent) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A)) + DelayNextAction(CLICK_CD_MELEE) + return else if(W) - W.ranged_attack_chain(src, A, params) + return W.ranged_attack_chain(src, A, params) else - RangedAttack(A,params) + return RangedAttack(A,params) //Is the atom obscured by a PREVENT_CLICK_UNDER_1 object above it /atom/proc/IsObscured() @@ -269,10 +234,7 @@ proximity_flag is not currently passed to attack_hand, and is instead used in human click code to allow glove touches only at melee range. */ -/mob/proc/UnarmedAttack(atom/A, proximity_flag) - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - return +/mob/proc/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) /* Ranged unarmed attack: @@ -305,7 +267,6 @@ var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling) if(C && C.chosen_sting) C.chosen_sting.try_to_sting(src,A) - next_click = world.time + 5 return swap_hand() @@ -338,24 +299,24 @@ */ /mob/proc/CtrlClickOn(atom/A) - A.CtrlClick(src) - return + return A.CtrlClick(src) /atom/proc/CtrlClick(mob/user) SEND_SIGNAL(src, COMSIG_CLICK_CTRL, user) var/mob/living/ML = user if(istype(ML)) - ML.pulled(src) + INVOKE_ASYNC(ML, /mob/living.verb/pulled, src) /mob/living/carbon/human/CtrlClick(mob/user) if(ishuman(user) && Adjacent(user) && !user.incapacitated()) - if(world.time < user.next_move) + if(!user.CheckActionCooldown()) return FALSE var/mob/living/carbon/human/H = user H.dna.species.grab(H, src, H.mind.martial_art) - H.changeNext_move(CLICK_CD_MELEE) + H.DelayNextAction(CLICK_CD_MELEE) + return TRUE else - ..() + return ..() /* Alt click Unused except for AI @@ -378,8 +339,8 @@ var/datum/antagonist/changeling/C = mind.has_antag_datum(/datum/antagonist/changeling) if(C && C.chosen_sting) C.chosen_sting.try_to_sting(src,A) - next_click = world.time + 5 - return + DelayNextAction(CLICK_CD_RANGE) + return TRUE ..() /atom/proc/AltClick(mob/user) @@ -414,9 +375,11 @@ return /mob/living/LaserEyes(atom/A, params) - changeNext_move(CLICK_CD_RANGE) + if(!CheckActionCooldown(CLICK_CD_RANGE)) + return + DelayNextAction() - var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc ) + var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam(loc) LE.icon = 'icons/effects/genetics.dmi' LE.icon_state = "eyelasers" playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) @@ -425,6 +388,7 @@ LE.def_zone = get_organ_target() LE.preparePixelProjectile(A, src, params) LE.fire() + return TRUE // 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, ismousemovement = FALSE) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 9fcccedf1a..372fe46046 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -7,10 +7,6 @@ */ /mob/living/silicon/robot/ClickOn(var/atom/A, var/params) - if(world.time <= next_click) - return - next_click = world.time + 1 - if(check_click_intercept(params,A)) return @@ -19,25 +15,19 @@ var/list/modifiers = params2list(params) if(modifiers["shift"] && modifiers["ctrl"]) - CtrlShiftClickOn(A) - return + return CtrlShiftClickOn(A) if(modifiers["shift"] && modifiers["middle"]) - ShiftMiddleClickOn(A) - return + return ShiftMiddleClickOn(A) if(modifiers["middle"]) - MiddleClickOn(A) - return + return MiddleClickOn(A) if(modifiers["shift"]) - ShiftClickOn(A) - return + return ShiftClickOn(A) if(modifiers["alt"]) // alt and alt-gr (rightalt) - AltClickOn(A) - return + return AltClickOn(A) if(modifiers["ctrl"]) - CtrlClickOn(A) - return + return CtrlClickOn(A) - if(next_move >= world.time) + if(!CheckActionCooldown(immediate = TRUE)) return face_atom(A) // change direction to face what you clicked on @@ -50,7 +40,7 @@ */ if(aicamera.in_camera_mode) //Cyborg picture taking aicamera.camera_mode_off() - aicamera.captureimage(A, usr) + INVOKE_ASYNC(aicamera, /obj/item/camera.proc/captureimage, A, usr) return var/obj/item/W = get_active_held_item() @@ -58,13 +48,8 @@ if(!W && A.Adjacent(src) && (isobj(A) || ismob(A))) var/atom/movable/C = A if(C.can_buckle && C.has_buckled_mobs()) - if(C.buckled_mobs.len > 1) - var/unbuckled = input(src, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in C.buckled_mobs - if(C.user_unbuckle_mob(unbuckled,src)) - return - else - if(C.user_unbuckle_mob(C.buckled_mobs[1],src)) - return + INVOKE_ASYNC(C, /atom/movable.proc/precise_user_unbuckle_mob, src) + return if(!W && (get_dist(src,A) <= interaction_range)) A.attack_robot(src) @@ -81,7 +66,9 @@ // cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents) if(A == loc || (A in loc) || (A in contents)) - W.melee_attack_chain(src, A, params) + . = W.melee_attack_chain(src, A, params) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A)) + DelayNextAction(CLICK_CD_MELEE) return if(!isturf(loc)) @@ -90,11 +77,12 @@ // cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc)) if(isturf(A) || isturf(A.loc)) if(A.Adjacent(src)) // see adjacent.dm - W.melee_attack_chain(src, A, params) + . = W.melee_attack_chain(src, A, params) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A)) + DelayNextAction(CLICK_CD_MELEE) return else - W.afterattack(A, src, 0, params) - return + return W.afterattack(A, src, 0, params) //Middle click cycles through selected modules. /mob/living/silicon/robot/MiddleClickOn(atom/A) @@ -175,8 +163,9 @@ clicks, you can do so here, but you will have to change attack_robot() above to the proper function */ -/mob/living/silicon/robot/UnarmedAttack(atom/A) +/mob/living/silicon/robot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) A.attack_robot(src) + /mob/living/silicon/robot/RangedAttack(atom/A) A.attack_robot(src) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 4b963c730d..467c67e0c3 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -168,6 +168,8 @@ //UI position overrides for 1:1 screen layout. (default is 7:5) #define ui_stamina "EAST-1:28,CENTER:17" // replacing internals button #define ui_overridden_resist "EAST-3:24,SOUTH+1:7" +#define ui_clickdelay "CENTER,SOUTH+1:-31" +#define ui_resistdelay "EAST-3:24,SOUTH+1:4" #define ui_combat_toggle "EAST-4:22,SOUTH:5" #define ui_boxcraft "EAST-4:22,SOUTH+1:6" diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index 0ed3a9cf26..8a66374029 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -56,9 +56,6 @@ if(id && usr.client) //try to (un)remember position usr.client.prefs.action_buttons_screen_locs["[name]_[id]"] = locked ? moved : null return TRUE - if(usr.next_click > world.time) - return - usr.next_click = world.time + 1 linked_action.Trigger() return TRUE diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 11531a701e..6dc1433bc8 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -22,7 +22,7 @@ if(alerts[category]) thealert = alerts[category] if(thealert.override_alerts) - return 0 + return thealert if(new_master && new_master != thealert.master) WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [thealert.master]") @@ -36,7 +36,7 @@ clear_alert(category) return .() else //no need to update - return 0 + return thealert else thealert = new type() thealert.override_alerts = override @@ -272,7 +272,7 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." var/mob/living/L = usr if(!istype(L) || !L.can_resist()) return - L.changeNext_move(CLICK_CD_RESIST) + L.MarkResistTime() if(CHECK_MOBILITY(L, MOBILITY_MOVE)) return L.resist_fire() //I just want to start a flame in your hearrrrrrtttttt. @@ -447,8 +447,6 @@ or shoot a gun to move around via Newton's 3rd Law of Motion." var/time_name if(G.seconds_until_activation) time_name = "until the Ark activates" - else if(G.grace_period) - time_name = "of grace period remaining" else if(G.progress_in_seconds) time_name = "until the Ark finishes summoning" if(time_info) @@ -495,6 +493,16 @@ Recharging stations are available in robotics, the dormitory bathrooms, and the desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite." icon_state = "lowcell" +/obj/screen/alert/etherealcharge + name = "Low Blood Charge" + desc = "Your blood's electric charge is running low, find a source of charge for your blood. Use a recharging station found in robotics or the dormitory bathrooms, or eat some Ethereal-friendly food." + icon_state = "etherealcharge" + +/obj/screen/alert/ethereal_overcharge + name = "Blood Overcharge" + desc = "Your blood's electric charge is becoming dangerously high, find an outlet for your energy. Use Grab Intent on an APC to channel your energy into it." + icon_state = "ethereal_overcharge" + //Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg /obj/screen/alert/hacked name = "Hacked" @@ -600,17 +608,32 @@ so as to remain in compliance with the most up-to-date laws." var/mob/living/L = usr if(!istype(L) || !L.can_resist()) return - L.changeNext_move(CLICK_CD_RESIST) - if(CHECK_MOBILITY(L, MOBILITY_MOVE) && (L.last_special <= world.time)) - return L.resist_restraints() + L.MarkResistTime() + return L.resist_restraints() /obj/screen/alert/restrained/buckled/Click() var/mob/living/L = usr if(!istype(L) || !L.can_resist()) return - L.changeNext_move(CLICK_CD_RESIST) - if(L.last_special <= world.time) - return L.resist_buckle() + L.MarkResistTime() + return L.resist_buckle() + +/obj/screen/alert/shoes/untied + name = "Untied Shoes" + desc = "Your shoes are untied! Click the alert or your shoes to tie them." + icon_state = "shoealert" + +/obj/screen/alert/shoes/knotted + name = "Knotted Shoes" + desc = "Someone tied your shoelaces together! Click the alert or your shoes to undo the knot." + icon_state = "shoealert" + +/obj/screen/alert/shoes/Click() + var/mob/living/carbon/C = usr + if(!istype(C) || !C.can_resist() || C != mob_viewer || !C.shoes) + return + C.MarkResistTime() + C.shoes.handle_tying(C) // PRIVATE = only edit, use, or override these if you're editing the system as a whole diff --git a/code/_onclick/hud/clockwork_marauder.dm b/code/_onclick/hud/clockwork_marauder.dm new file mode 100644 index 0000000000..09f85db574 --- /dev/null +++ b/code/_onclick/hud/clockwork_marauder.dm @@ -0,0 +1,45 @@ +/datum/hud/marauder + var/obj/screen/hosthealth + var/obj/screen/blockchance + var/obj/screen/counterchance + +/datum/hud/marauder/New(mob/living/simple_animal/hostile/clockwork/marauder/guardian/owner) + ..() + var/obj/screen/using + + healths = new /obj/screen/healths/clock() + infodisplay += healths + + hosthealth = new /obj/screen/healths/clock() + hosthealth.screen_loc = ui_internal + infodisplay += hosthealth + + using = new /obj/screen/marauder/emerge() + using.screen_loc = ui_zonesel + static_inventory += using + +/datum/hud/marauder/Destroy() + blockchance = null + counterchance = null + hosthealth = null + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/marauder(src, ui_style2icon(client.prefs.UI_style)) + +/obj/screen/marauder + icon = 'icons/mob/clockwork_mobs.dmi' + +/obj/screen/marauder/emerge + icon_state = "clockguard_emerge" + name = "Emerge/Return" + desc = "Emerge or Return." + +/obj/screen/marauder/emerge/Click() + if(istype(usr, /mob/living/simple_animal/hostile/clockwork/marauder/guardian)) + var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/G = usr + if(G.is_in_host()) + G.try_emerge() + else + G.return_to_host() diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 9380cf98aa..04141becf2 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -140,6 +140,17 @@ sprint_buffer.hud = src static_inventory += sprint_buffer + // clickdelay + clickdelay = new + clickdelay.hud = src + clickdelay.screen_loc = ui_clickdelay + static_inventory += clickdelay + + // resistdelay + resistdelay = new + resistdelay.hud = src + resistdelay.screen_loc = ui_resistdelay + static_inventory += resistdelay using = new /obj/screen/drop() using.icon = ui_style diff --git a/code/_onclick/hud/map_popups.dm b/code/_onclick/hud/map_popups.dm new file mode 100644 index 0000000000..777ebb0718 --- /dev/null +++ b/code/_onclick/hud/map_popups.dm @@ -0,0 +1,165 @@ +/client + /** + * Assoc list with all the active maps - when a screen obj is added to + * a map, it's put in here as well. + * + * Format: list( = list(/obj/screen)) + */ + var/list/screen_maps = list() + +/** + * A screen object, which acts as a container for turfs and other things + * you want to show on the map, which you usually attach to "vis_contents". + */ +/obj/screen + /** + * Map name assigned to this object. + * Automatically set by /client/proc/add_obj_to_map. + */ + var/assigned_map + /** + * Mark this object as garbage-collectible after you clean the map + * it was registered on. + * + * This could probably be changed to be a proc, for conditional removal. + * But for now, this works. + */ + var/del_on_map_removal = TRUE + +/** + * A generic background object. + * It is also implicitly used to allocate a rectangle on the map, which will + * be used for auto-scaling the map. + */ +/obj/screen/background + name = "background" + icon = 'icons/mob/map_backgrounds.dmi' + icon_state = "clear" + layer = GAME_PLANE + plane = GAME_PLANE + +/** + * Sets screen_loc of this screen object, in form of point coordinates, + * with optional pixel offset (px, py). + * + * If applicable, "assigned_map" has to be assigned before this proc call. + */ +/obj/screen/proc/set_position(x, y, px = 0, py = 0) + if(assigned_map) + screen_loc = "[assigned_map]:[x]:[px],[y]:[py]" + else + screen_loc = "[x]:[px],[y]:[py]" + +/** + * Sets screen_loc to fill a rectangular area of the map. + * + * If applicable, "assigned_map" has to be assigned before this proc call. + */ +/obj/screen/proc/fill_rect(x1, y1, x2, y2) + if(assigned_map) + screen_loc = "[assigned_map]:[x1],[y1] to [x2],[y2]" + else + screen_loc = "[x1],[y1] to [x2],[y2]" + +/** + * Registers screen obj with the client, which makes it visible on the + * assigned map, and becomes a part of the assigned map's lifecycle. + */ +/client/proc/register_map_obj(obj/screen/screen_obj) + if(!screen_obj.assigned_map) + CRASH("Can't register [screen_obj] without 'assigned_map' property.") + if(!screen_maps[screen_obj.assigned_map]) + screen_maps[screen_obj.assigned_map] = list() + // NOTE: Possibly an expensive operation + var/list/screen_map = screen_maps[screen_obj.assigned_map] + if(!screen_map.Find(screen_obj)) + screen_map += screen_obj + if(!screen.Find(screen_obj)) + screen += screen_obj + +/** + * Clears the map of registered screen objects. + * + * Not really needed most of the time, as the client's screen list gets reset + * on relog. any of the buttons are going to get caught by garbage collection + * anyway. they're effectively qdel'd. + */ +/client/proc/clear_map(map_name) + if(!map_name || !(map_name in screen_maps)) + return FALSE + for(var/obj/screen/screen_obj in screen_maps[map_name]) + screen_maps[map_name] -= screen_obj + if(screen_obj.del_on_map_removal) + qdel(screen_obj) + screen_maps -= map_name + +/** + * Clears all the maps of registered screen objects. + */ +/client/proc/clear_all_maps() + for(var/map_name in screen_maps) + clear_map(map_name) + +/** + * Creates a popup window with a basic map element in it, without any + * further initialization. + * + * Ratio is how many pixels by how many pixels (keep it simple). + * + * Returns a map name. + */ +/client/proc/create_popup(name, ratiox = 100, ratioy = 100) + winclone(src, "popupwindow", name) + var/list/winparams = list() + winparams["size"] = "[ratiox]x[ratioy]" + winparams["on-close"] = "handle-popup-close [name]" + winset(src, "[name]", list2params(winparams)) + winshow(src, "[name]", 1) + + var/list/params = list() + params["parent"] = "[name]" + params["type"] = "map" + params["size"] = "[ratiox]x[ratioy]" + params["anchor1"] = "0,0" + params["anchor2"] = "[ratiox],[ratioy]" + winset(src, "[name]_map", list2params(params)) + + return "[name]_map" + +/** + * Create the popup, and get it ready for generic use by giving + * it a background. + * + * Width and height are multiplied by 64 by default. + */ +/client/proc/setup_popup(popup_name, width = 9, height = 9, \ + tilesize = 2, bg_icon) + if(!popup_name) + return + clear_map("[popup_name]_map") + var/x_value = world.icon_size * tilesize * width + var/y_value = world.icon_size * tilesize * height + var/map_name = create_popup(popup_name, x_value, y_value) + + var/obj/screen/background/background = new + background.assigned_map = map_name + background.fill_rect(1, 1, width, height) + if(bg_icon) + background.icon_state = bg_icon + register_map_obj(background) + + return map_name + +/** + * Closes a popup. + */ +/client/proc/close_popup(popup) + winshow(src, popup, 0) + handle_popup_close(popup) + +/** + * When the popup closes in any way (player or proc call) it calls this. + */ +/client/verb/handle_popup_close(window_id as text) + set hidden = TRUE + clear_map("[window_id]_map") diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm index d8ef1c525a..9050bcb5f0 100755 --- a/code/_onclick/hud/parallax.dm +++ b/code/_onclick/hud/parallax.dm @@ -128,7 +128,7 @@ deltimer(C.parallax_animate_timer) var/datum/callback/CB = CALLBACK(src, .proc/update_parallax_motionblur, C, animatedir, new_parallax_movedir, newtransform) if(skip_windups) - CB.Invoke() + CB.InvokeAsync() else C.parallax_animate_timer = addtimer(CB, min(shortesttimer, PARALLAX_LOOP_TIME), TIMER_CLIENT_TIME|TIMER_STOPPABLE) @@ -219,6 +219,7 @@ L.screen_loc = "CENTER-7:[round(L.offset_x,1)],CENTER-7:[round(L.offset_y,1)]" /atom/movable/proc/update_parallax_contents() + set waitfor = FALSE if(length(client_mobs_in_contents)) for(var/thing in client_mobs_in_contents) var/mob/M = thing diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 4ed286eb08..126cc18907 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -47,17 +47,7 @@ name = "swap hand" /obj/screen/swap_hand/Click() - // At this point in client Click() code we have passed the 1/10 sec check and little else - // We don't even know if it's a middle click - if(world.time <= usr.next_move) - return 1 - - if(usr.incapacitated()) - return 1 - - if(ismob(usr)) - var/mob/M = usr - M.swap_hand() + usr.swap_hand() return 1 /obj/screen/craft @@ -101,15 +91,9 @@ plane = HUD_PLANE /obj/screen/inventory/Click(location, control, params) - // At this point in client Click() code we have passed the 1/10 sec check and little else - // We don't even know if it's a middle click - if(world.time <= usr.next_move) - return TRUE - - if(usr.incapacitated()) - return TRUE - if(ismecha(usr.loc)) // stops inventory actions in a mech - return TRUE + if(hud?.mymob && (hud.mymob != usr)) + return + // just redirect clicks if(hud?.mymob && slot_id) var/obj/item/inv_item = hud.mymob.get_item_by_slot(slot_id) @@ -153,7 +137,7 @@ var/image/item_overlay = image(holding) item_overlay.alpha = 92 - if(!user.can_equip(holding, slot_id, TRUE)) + if(!user.can_equip(holding, slot_id, TRUE, TRUE, TRUE)) item_overlay.color = "#FF0000" else item_overlay.color = "#00ff00" @@ -190,17 +174,10 @@ /obj/screen/inventory/hand/Click(location, control, params) - // At this point in client Click() code we have passed the 1/10 sec check and little else - // We don't even know if it's a middle click - var/mob/user = hud?.mymob - if(usr != user) - return TRUE - if(world.time <= user.next_move) - return TRUE - if(user.incapacitated()) - return TRUE - if (ismecha(user.loc)) // stops inventory actions in a mech - return TRUE + if(hud?.mymob && (hud.mymob != usr)) + return + var/mob/user = hud.mymob + // just redirect clicks if(user.active_hand_index == held_index) var/obj/item/I = user.get_active_held_item() diff --git a/code/_onclick/hud/screen_objects/clickdelay.dm b/code/_onclick/hud/screen_objects/clickdelay.dm new file mode 100644 index 0000000000..e0ad039cdf --- /dev/null +++ b/code/_onclick/hud/screen_objects/clickdelay.dm @@ -0,0 +1,58 @@ +/obj/screen/action_bar + +/obj/screen/action_bar/Destroy() + STOP_PROCESSING(SShuds, src) + return ..() + +/obj/screen/action_bar/proc/mark_dirty() + var/mob/living/L = hud?.mymob + if(L?.client && update_to_mob(L)) + START_PROCESSING(SShuds, src) + +/obj/screen/action_bar/process() + var/mob/living/L = hud?.mymob + if(!L?.client || !update_to_mob(L)) + return PROCESS_KILL + +/obj/screen/action_bar/proc/update_to_mob(mob/living/L) + return FALSE + +/datum/hud/var/obj/screen/action_bar/clickdelay/clickdelay + +/obj/screen/action_bar/clickdelay + name = "click delay" + icon = 'icons/effects/progessbar.dmi' + icon_state = "prog_bar_100" + layer = 20 // under hand buttons + +/obj/screen/action_bar/clickdelay/Initialize() + . = ..() + var/matrix/M = new + M.Scale(2, 1) + transform = M + +/obj/screen/action_bar/clickdelay/update_to_mob(mob/living/L) + var/estimated = L.EstimatedNextActionTime() + var/diff = estimated - L.last_action + var/left = estimated - world.time + if(left < 0 || diff < 0) + icon_state = "prog_bar_100" + return FALSE + icon_state = "prog_bar_[round(clamp(((diff - left)/diff) * 100, 0, 100), 5)]" + return TRUE + +/datum/hud/var/obj/screen/action_bar/resistdelay/resistdelay + +/obj/screen/action_bar/resistdelay + name = "resist delay" + icon = 'icons/effects/progessbar.dmi' + icon_state = "prog_bar_100" + +/obj/screen/action_bar/resistdelay/update_to_mob(mob/living/L) + var/diff = L.next_resist - L.last_resist + var/left = L.next_resist - world.time + if(left < 0 || diff < 0) + icon_state = "prog_bar_100" + return FALSE + icon_state = "prog_bar_[round(clamp(((diff - left)/diff) * 100, 0, 100), 5)]" + return TRUE diff --git a/modular_citadel/code/_onclick/hud/sprint.dm b/code/_onclick/hud/screen_objects/sprint.dm similarity index 100% rename from modular_citadel/code/_onclick/hud/sprint.dm rename to code/_onclick/hud/screen_objects/sprint.dm diff --git a/modular_citadel/code/_onclick/hud/stamina.dm b/code/_onclick/hud/screen_objects/stamina.dm similarity index 100% rename from modular_citadel/code/_onclick/hud/stamina.dm rename to code/_onclick/hud/screen_objects/stamina.dm diff --git a/code/_onclick/hud/screen_objects/storage.dm b/code/_onclick/hud/screen_objects/storage.dm index 7e8bfe12ab..72b2d035a3 100644 --- a/code/_onclick/hud/screen_objects/storage.dm +++ b/code/_onclick/hud/screen_objects/storage.dm @@ -9,12 +9,9 @@ /obj/screen/storage/Click(location, control, params) if(!insertion_click) return ..() - if(world.time <= usr.next_move) - return TRUE - if(usr.incapacitated()) - return TRUE - if (ismecha(usr.loc)) // stops inventory actions in a mech - return TRUE + if(hud?.mymob && (hud.mymob != usr)) + return + // just redirect clicks if(master) var/obj/item/I = usr.get_active_held_item() if(I) @@ -125,13 +122,13 @@ if(pixel_size == pixels) return pixel_size = pixels - cut_overlays(TRUE) + cut_overlays() //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, TRUE) - add_overlay(right, TRUE) + add_overlay(left) + add_overlay(right) /obj/screen/storage/volumetric_edge layer = VOLUMETRIC_STORAGE_BOX_LAYER diff --git a/modular_citadel/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects/vore.dm similarity index 100% rename from modular_citadel/code/_onclick/hud/screen_objects.dm rename to code/_onclick/hud/screen_objects/vore.dm diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 106db7f40a..9e88476513 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -7,21 +7,22 @@ *and lastly *afterattack. The return value does not matter. */ -/obj/item/proc/melee_attack_chain(mob/user, atom/target, params, flags, damage_multiplier = 1) +/obj/item/proc/melee_attack_chain(mob/user, atom/target, params, attackchain_flags, damage_multiplier = 1) if(isliving(user)) var/mob/living/L = user - if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(flags & ATTACKCHAIN_PARRY_COUNTERATTACK)) + if(!CHECK_MOBILITY(L, MOBILITY_USE) && !(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)) to_chat(L, "You are unable to swing [src] right now!") return - if(tool_behaviour && target.tool_act(user, src, tool_behaviour)) + . = attackchain_flags + if(tool_behaviour && ((. = target.tool_act(user, src, tool_behaviour)) & STOP_ATTACK_PROC_CHAIN)) return - if(pre_attack(target, user, params)) + if((. |= pre_attack(target, user, params, ., damage_multiplier)) & STOP_ATTACK_PROC_CHAIN) return - if(target.attackby(src, user, params, flags, damage_multiplier)) + if((. |= target.attackby(src, user, params, ., damage_multiplier)) & STOP_ATTACK_PROC_CHAIN) return if(QDELETED(src) || QDELETED(target)) return - afterattack(target, user, TRUE, params) + . |= afterattack(target, user, TRUE, params) /// Like melee_attack_chain but for ranged. /obj/item/proc/ranged_attack_chain(mob/user, atom/target, params) @@ -30,7 +31,7 @@ if(!CHECK_MOBILITY(L, MOBILITY_USE)) to_chat(L, "You are unable to raise [src] right now!") return - afterattack(target, user, FALSE, params) + return afterattack(target, user, FALSE, params) // Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user) @@ -38,28 +39,43 @@ return interact(user) -/obj/item/proc/pre_attack(atom/A, mob/living/user, params) //do stuff before attackby! +/obj/item/proc/pre_attack(atom/A, mob/living/user, params, attackchain_flags, damage_multiplier) //do stuff before attackby! if(SEND_SIGNAL(src, COMSIG_ITEM_PRE_ATTACK, A, user, params) & COMPONENT_NO_ATTACK) - return TRUE - return FALSE //return TRUE to avoid calling attackby after this proc does stuff + return STOP_ATTACK_PROC_CHAIN + if(!(attackchain_flags & ATTACK_IGNORE_CLICKDELAY) && !CheckAttackCooldown(user, A)) + return STOP_ATTACK_PROC_CHAIN // No comment /atom/proc/attackby(obj/item/W, mob/user, params) if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, W, user, params) & COMPONENT_NO_AFTERATTACK) - return TRUE - return FALSE + return STOP_ATTACK_PROC_CHAIN /obj/attackby(obj/item/I, mob/living/user, params) - return ..() || ((obj_flags & CAN_BE_HIT) && I.attack_obj(src, user)) + . = ..() + if(. & STOP_ATTACK_PROC_CHAIN) + return + if(obj_flags & CAN_BE_HIT) + . |= I.attack_obj(src, user) /mob/living/attackby(obj/item/I, mob/living/user, params, attackchain_flags, damage_multiplier) - if(..()) - return TRUE - I.attack_delay_done = FALSE //Should be set TRUE in pre_attacked_by() - . = I.attack(src, user, attackchain_flags, damage_multiplier) - if(!I.attack_delay_done) //Otherwise, pre_attacked_by() should handle it. - user.changeNext_move(I.click_delay) + . = ..() + if(. & STOP_ATTACK_PROC_CHAIN) + return + . |= I.attack(src, user, attackchain_flags, damage_multiplier) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING)) // SAFETY NET - unless the proc tells us we should not handle this, give them the basic melee cooldown! + I.ApplyAttackCooldown(user, src, attackchain_flags) +/** + * Called when someone uses us to attack a mob in melee combat. + * + * This proc respects CheckAttackCooldown() default clickdelay handling. + * + * @params + * * mob/living/M - target + * * mob/living/user - attacker + * * attackchain_Flags - see [code/__DEFINES/_flags/return_values.dm] + * * damage_multiplier - what to multiply the damage by + */ /obj/item/proc/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK, M, user) & COMPONENT_ITEM_NO_ATTACK) return @@ -88,6 +104,17 @@ if(weight) user.adjustStaminaLossBuffered(weight) + // CIT SCREENSHAKE + if(force >= 15) + shake_camera(user, ((force - 10) * 0.01 + 1), ((force - 10) * 0.01)) + if(M.client) + switch (M.client.prefs.damagescreenshake) + if (1) + shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015)) + if (2) + if(!CHECK_MOBILITY(M, MOBILITY_MOVE)) + shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015)) + //the equivalent of the standard version of attack() but for object targets. /obj/item/proc/attack_obj(obj/O, mob/living/user) if(SEND_SIGNAL(src, COMSIG_ITEM_ATTACK_OBJ, O, user) & COMPONENT_NO_ATTACK_OBJ) @@ -95,8 +122,7 @@ if(item_flags & NOBLUDGEON) return user.do_attack_animation(O) - if(!O.attacked_by(src, user)) - user.changeNext_move(click_delay) + O.attacked_by(src, user) var/weight = getweight(user, STAM_COST_ATTACK_OBJ_MULT) if(weight) user.adjustStaminaLossBuffered(weight)//CIT CHANGE - makes attacking things cause stamina loss @@ -109,12 +135,9 @@ var/bad_trait var/stamloss = user.getStaminaLoss() - var/next_move_mult = 1 if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do. var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY totitemdamage *= 1 - penalty - next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY - user.changeNext_move(I.click_delay*next_move_mult) if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. @@ -123,21 +146,21 @@ 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)) + if(!(SKILL_TRAIN_ATTACK_OBJ in I.used_skills[skill])) continue user.mind.auto_gain_experience(skill, I.skill_gain) - + if(!(attackchain_flags & NO_AUTO_CLICKDELAY_HANDLING)) + I.ApplyAttackCooldown(user, src, attackchain_flags) 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(totitemdamage, I.damtype, "melee", 1) - return TRUE /mob/living/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) var/list/block_return = list() var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier - if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, null, block_return) & BLOCK_SUCCESS) + if((user != src) && mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_IS_PARRY_COUNTERATTACK : NONE) | 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, null, totitemdamage) @@ -155,8 +178,7 @@ /mob/living/simple_animal/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) if(I.force < force_threshold || I.damtype == STAMINA) - playsound(loc, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1) - user.changeNext_move(I.click_delay) //pre_attacked_by not called + playsound(src, 'sound/weapons/tap.ogg', I.get_clamped_volume(), 1, -1) else return ..() @@ -167,37 +189,44 @@ var/stamloss = user.getStaminaLoss() var/stam_mobility_mult = 1 - var/next_move_mult = 1 if(stamloss > STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do. var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_ITEM_ATTACK_PENALTY stam_mobility_mult -= penalty - next_move_mult += penalty*STAM_CRIT_ITEM_ATTACK_DELAY if(stam_mobility_mult > LYING_DAMAGE_PENALTY && !CHECK_MOBILITY(user, MOBILITY_STAND)) //damage penalty for fighting prone, doesn't stack with the above. stam_mobility_mult = LYING_DAMAGE_PENALTY . *= stam_mobility_mult - user.changeNext_move(I.click_delay*next_move_mult) - I.attack_delay_done = TRUE var/bad_trait if(!(I.item_flags & NO_COMBAT_MODE_FORCE_MODIFIER)) if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) - . *= 0.5 + . *= 0.8 else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) - . *= 1.5 + . *= 1.2 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)) + if(!(SKILL_TRAIN_ATTACK_MOB in I.used_skills[skill])) continue - user.mind.auto_gain_experience(skill, I.skill_gain) + var/datum/skill/S = GLOB.skill_datums[skill] + user.mind.auto_gain_experience(skill, I.skill_gain*S.item_skill_gain_multi) -// 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. +/** + * Called after attacking something if the melee attack chain isn't interrupted before. + * Also called when clicking on something with an item without being in melee range + * + * WARNING: This does not automatically check clickdelay if not in a melee attack! Be sure to account for this! + * + * @params + * * target - The thing we clicked + * * user - mob of person clicking + * * proximity_flag - are we in melee range/doing it in a melee attack + * * click_parameters - mouse control parameters, check BYOND ref. + */ /obj/item/proc/afterattack(atom/target, mob/user, proximity_flag, click_parameters) SEND_SIGNAL(src, COMSIG_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters) SEND_SIGNAL(user, COMSIG_MOB_ITEM_AFTERATTACK, target, user, proximity_flag, click_parameters) @@ -209,25 +238,24 @@ else return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100 -/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, current_force) +/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart) var/message_verb = "attacked" - if(I.attack_verb && I.attack_verb.len) + if(length(I.attack_verb)) message_verb = "[pick(I.attack_verb)]" - if(current_force < I.force * FEEBLE_ATTACK_MSG_THRESHOLD) - message_verb = "[pick("feebly", "limply", "saplessly")] [message_verb]" else if(!I.force) return var/message_hit_area = "" if(hit_area) message_hit_area = " in the [hit_area]" - var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]." + var/attack_message = "[src] is [message_verb][message_hit_area] with [I]!" + var/attack_message_local = "You're [message_verb][message_hit_area] with [I]!" if(user in viewers(src, null)) - attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!" + attack_message = "[user] [message_verb] [src][message_hit_area] with [I]!" + attack_message_local = "[user] [message_verb] you[message_hit_area] with [I]!" + if(user == src) + attack_message_local = "You [message_verb] yourself[message_hit_area] with [I]" visible_message("[attack_message]",\ - "[attack_message]", null, COMBAT_MESSAGE_RANGE) - if(hit_area == BODY_ZONE_HEAD) - if(prob(2)) - playsound(src, 'sound/weapons/dink.ogg', 30, 1) + "[attack_message_local]", null, COMBAT_MESSAGE_RANGE) return 1 /// How much stamina this takes to swing this is not for realism purposes hecc off. diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index 9f9870a9e5..8a1e745308 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -37,7 +37,7 @@ CtrlClickOn(A) return - if(world.time <= next_move) + if(!CheckActionCooldown()) return // You are responsible for checking config.ghost_interaction when you override this function // Not all of them require checking, see below @@ -63,18 +63,9 @@ // And here are some good things for free: // Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu -/obj/machinery/gateway/centerstation/attack_ghost(mob/user) - if(awaygate) - user.forceMove(awaygate.loc) - else - to_chat(user, "[src] has no destination.") - return ..() - -/obj/machinery/gateway/centeraway/attack_ghost(mob/user) - if(stationgate) - user.forceMove(stationgate.loc) - else - to_chat(user, "[src] has no destination.") +/obj/effect/gateway_portal_bumper/attack_ghost(mob/user) + if(gateway) + gateway.Transfer(user) return ..() /obj/machinery/teleport/hub/attack_ghost(mob/user) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index d4ec44a641..975c6e62d4 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -4,39 +4,57 @@ Otherwise pretty standard. */ -/mob/living/carbon/human/UnarmedAttack(atom/A, proximity) + +/mob/living/carbon/human/UnarmedAttack(atom/A, proximity, intent = a_intent, attackchain_flags = NONE) if(!has_active_hand()) //can't attack without a hand. to_chat(src, "You look at your arm and sigh.") return + var/obj/item/bodypart/check_arm = get_active_hand() + if(check_arm && check_arm.is_disabled() == BODYPART_DISABLED_WOUND) + to_chat(src, "The damage in your [check_arm.name] is preventing you from using it! Get it fixed, or at least splinted!") + return + + . = attackchain_flags // Special glove functions: // If the gloves do anything, have them return 1 to stop // normal attack_hand() here. var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines - if(proximity && istype(G) && G.Touch(A,1)) - return - - var/override = 0 + if(proximity && istype(G)) + . |= G.Touch(A, TRUE) + if(. & INTERRUPT_UNARMED_ATTACK) + return for(var/datum/mutation/human/HM in dna.mutations) - override += HM.on_attack_hand(A, proximity) + . |= HM.on_attack_hand(A, proximity, intent, .) - if(override) + if(. & INTERRUPT_UNARMED_ATTACK) return SEND_SIGNAL(src, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, A) - A.attack_hand(src) + return . | A.attack_hand(src, intent, .) -//Return TRUE to cancel other attack hand effects that respect it. -/atom/proc/attack_hand(mob/user) - . = FALSE +/atom/proc/attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags) + SHOULD_NOT_SLEEP(TRUE) if(!(interaction_flags_atom & INTERACT_ATOM_NO_FINGERPRINT_ATTACK_HAND)) add_fingerprint(user) if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_HAND, user) & COMPONENT_NO_ATTACK_HAND) - . = TRUE + return + . = attackchain_flags + if(attack_hand_speed && !(. & ATTACK_IGNORE_CLICKDELAY)) + if(!user.CheckActionCooldown(attack_hand_speed)) + return if(interaction_flags_atom & INTERACT_ATOM_ATTACK_HAND) . = _try_interact(user) + INVOKE_ASYNC(src, .proc/on_attack_hand, user, act_intent, .) + if(!(. & ATTACK_IGNORE_ACTION)) + if(attack_hand_unwieldlyness) + user.DelayNextAction(attack_hand_unwieldlyness, considered_action = attack_hand_is_action) + else if(attack_hand_is_action) + user.DelayNextAction() + +/atom/proc/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) //Return a non FALSE value to cancel whatever called this from propagating, if it respects it. /atom/proc/_try_interact(mob/user) @@ -44,7 +62,6 @@ return interact(user) if(can_interact(user)) return interact(user) - return FALSE /atom/proc/can_interact(mob/user) if(!user.can_interact_with(src)) @@ -74,8 +91,7 @@ else add_fingerprint(user) if(interaction_flags_atom & INTERACT_ATOM_UI_INTERACT) - return ui_interact(user) - return FALSE + ui_interact(user) /* /mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this @@ -89,13 +105,19 @@ . = ..() if(gloves) var/obj/item/clothing/gloves/G = gloves - if(istype(G) && G.Touch(A,0)) // for magic gloves + . |= G.Touch(A, FALSE) + if(. & INTERRUPT_UNARMED_ATTACK) + return + if(istype(glasses)) + . |= glasses.ranged_attack(src, A, mouseparams) + if(. & INTERRUPT_UNARMED_ATTACK) return - if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams)) - return for(var/datum/mutation/human/HM in dna.mutations) - HM.on_ranged_attack(A, mouseparams) + . |= HM.on_ranged_attack(A, mouseparams) + + if(. & INTERRUPT_UNARMED_ATTACK) + return if(isturf(A) && get_dist(src,A) <= 1) src.Move_Pulled(A) @@ -104,11 +126,11 @@ /* Animals & All Unspecified */ -/mob/living/UnarmedAttack(atom/A) - A.attack_animal(src) +/mob/living/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) + A.attack_animal(src, intent, flags) /atom/proc/attack_animal(mob/user) - return + SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_ANIMAL, user) /mob/living/RestrainedClickOn(atom/A) return @@ -116,8 +138,10 @@ /* Monkeys */ -/mob/living/carbon/monkey/UnarmedAttack(atom/A) - A.attack_paw(src) +/mob/living/carbon/monkey/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) + if(!CheckActionCooldown(CLICK_CD_MELEE)) + return + return !isnull(A.attack_paw(src, intent, flags)) /atom/proc/attack_paw(mob/user) if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user) & COMPONENT_NO_ATTACK_HAND) @@ -138,6 +162,8 @@ return if(is_muzzled()) return + if(!CheckActionCooldown(CLICK_CD_MELEE)) + return var/mob/living/carbon/ML = A if(istype(ML)) var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) @@ -157,13 +183,14 @@ ML.ForceContractDisease(D) else ML.visible_message("[src] has attempted to bite [ML]!") + DelayNextAction() /* Aliens Defaults to same as monkey in most places */ -/mob/living/carbon/alien/UnarmedAttack(atom/A) - A.attack_alien(src) +/mob/living/carbon/alien/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) + A.attack_alien(src, intent, flags) /atom/proc/attack_alien(mob/living/carbon/alien/user) attack_paw(user) @@ -173,29 +200,29 @@ return // Babby aliens -/mob/living/carbon/alien/larva/UnarmedAttack(atom/A) - A.attack_larva(src) +/mob/living/carbon/alien/larva/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) + A.attack_larva(src, intent, flags) + /atom/proc/attack_larva(mob/user) return - /* Slimes Nothing happening here */ -/mob/living/simple_animal/slime/UnarmedAttack(atom/A) - A.attack_slime(src) +/mob/living/simple_animal/slime/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) + A.attack_slime(src, intent, flags) + /atom/proc/attack_slime(mob/user) return /mob/living/simple_animal/slime/RestrainedClickOn(atom/A) return - /* Drones */ -/mob/living/simple_animal/drone/UnarmedAttack(atom/A) - A.attack_drone(src) +/mob/living/simple_animal/drone/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) + A.attack_drone(src, intent, flags) /atom/proc/attack_drone(mob/living/simple_animal/drone/user) attack_hand(user) //defaults to attack_hand. Override it when you don't want drones to do same stuff as humans. @@ -203,55 +230,44 @@ /mob/living/simple_animal/slime/RestrainedClickOn(atom/A) return - /* True Devil */ - -/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity) +/mob/living/carbon/true_devil/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) A.attack_hand(src) /* Brain */ - -/mob/living/brain/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default +/mob/living/brain/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) return - /* pAI */ - -/mob/living/silicon/pai/UnarmedAttack(atom/A)//Stops runtimes due to attack_animal being the default +/mob/living/silicon/pai/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) return - /* Simple animals */ - -/mob/living/simple_animal/UnarmedAttack(atom/A, proximity) +/mob/living/simple_animal/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(!dextrous) return ..() if(!ismob(A)) - A.attack_hand(src) + A.attack_hand(src, intent, flags) update_inv_hands() - /* Hostile animals */ - -/mob/living/simple_animal/hostile/UnarmedAttack(atom/A) +/mob/living/simple_animal/hostile/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) target = A if(dextrous && !ismob(A)) - ..() + return ..() else AttackingTarget() - - /* New Players: Have no reason to click on anything at all. diff --git a/code/_onclick/overmind.dm b/code/_onclick/overmind.dm index 8ace273dd8..419524c871 100644 --- a/code/_onclick/overmind.dm +++ b/code/_onclick/overmind.dm @@ -32,4 +32,4 @@ /mob/camera/blob/AltClickOn(atom/A) //Remove a blob var/turf/T = get_turf(A) if(T) - remove_blob(T) \ No newline at end of file + remove_blob(T) diff --git a/modular_citadel/code/_onclick/click.dm b/code/_onclick/right_click.dm similarity index 60% rename from modular_citadel/code/_onclick/click.dm rename to code/_onclick/right_click.dm index 004cc2fe80..4b2480eb8c 100644 --- a/modular_citadel/code/_onclick/click.dm +++ b/code/_onclick/right_click.dm @@ -5,7 +5,7 @@ face_atom(A) - if(next_move > world.time) // in the year 2000... + if(!CheckActionCooldown()) return if(!modifiers["catcher"] && A.IsObscured()) @@ -16,9 +16,8 @@ return M.click_action(A,src,params) if(restrained()) - changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow - RestrainedClickOn(A) - return + DelayNextAction(CLICK_CD_HANDCUFFED) + return RestrainedClickOn(A) if(in_throw_mode) throw_item(A)//todo: make it plausible to lightly toss items via right-click @@ -36,13 +35,14 @@ //User itself, current loc, and user inventory if(A in DirectAccess()) if(W) - W.rightclick_melee_attack_chain(src, A, params) + return W.rightclick_melee_attack_chain(src, A, params) else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - if(!AltUnarmedAttack(A)) - UnarmedAttack(A) - return + if(!AltUnarmedAttack(A, TRUE)) + . = UnarmedAttack(A, TRUE, a_intent) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A)) + DelayNextAction(CLICK_CD_MELEE) + return + return //Can't reach anything else in lockers or other weirdness if(!loc.AllowClick()) @@ -51,23 +51,25 @@ //Standard reach turf to turf or reaching inside storage if(CanReach(A,W)) if(W) - W.rightclick_melee_attack_chain(src, A, params) + return W.rightclick_melee_attack_chain(src, A, params) else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - if(!AltUnarmedAttack(A,1)) - UnarmedAttack(A,1) + if(!AltUnarmedAttack(A, TRUE)) + . = UnarmedAttack(A, TRUE, a_intent) + if(!(. & NO_AUTO_CLICKDELAY_HANDLING) && ismob(A)) + DelayNextAction(CLICK_CD_MELEE) + return + return else if(W) if(!W.altafterattack(A, src, FALSE, params)) - W.afterattack(A, src, FALSE, params) + return W.afterattack(A, src, FALSE, params) else - if(!AltRangedAttack(A,params)) - RangedAttack(A,params) + if(!AltRangedAttack(A, params)) + return RangedAttack(A, params) /mob/proc/AltUnarmedAttack(atom/A, proximity_flag) if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) + DelayNextAction(CLICK_CD_MELEE) return FALSE /mob/proc/AltRangedAttack(atom/A, params) diff --git a/modular_citadel/code/_onclick/item_attack.dm b/code/_onclick/right_item_attack.dm similarity index 82% rename from modular_citadel/code/_onclick/item_attack.dm rename to code/_onclick/right_item_attack.dm index bba3b14e2e..4ac9c96c8e 100644 --- a/modular_citadel/code/_onclick/item_attack.dm +++ b/code/_onclick/right_item_attack.dm @@ -1,10 +1,9 @@ /obj/item/proc/rightclick_melee_attack_chain(mob/user, atom/target, params) if(!alt_pre_attack(target, user, params)) //Hey, does this item have special behavior that should override all normal right-click functionality? if(!target.altattackby(src, user, params)) //Does the target do anything special when we right-click on it? - melee_attack_chain(user, target, params) //Ugh. Lame! I'm filing a legal complaint about the discrimination against the right mouse button! + . = melee_attack_chain(user, target, params) //Ugh. Lame! I'm filing a legal complaint about the discrimination against the right mouse button! else - altafterattack(target, user, TRUE, params) - return + . = altafterattack(target, user, TRUE, params) /obj/item/proc/alt_pre_attack(atom/A, mob/living/user, params) return FALSE //return something other than false if you wanna override attacking completely diff --git a/modular_citadel/code/_onclick/other_mobs.dm b/code/_onclick/right_other_mobs.dm similarity index 93% rename from modular_citadel/code/_onclick/other_mobs.dm rename to code/_onclick/right_other_mobs.dm index ec740f023b..2dc9fddeef 100644 --- a/modular_citadel/code/_onclick/other_mobs.dm +++ b/code/_onclick/right_other_mobs.dm @@ -3,15 +3,14 @@ to_chat(src, "You look at the state of the universe and sigh.") //lets face it, people rarely ever see this message in its intended condition. return TRUE - if(!A.alt_attack_hand(src)) - A.attack_hand(src) - return TRUE - return TRUE + return A.alt_attack_hand(src) /mob/living/carbon/human/AltRangedAttack(atom/A, params) if(isturf(A) || incapacitated()) // pretty annoying to wave your fist at floors and walls. And useless. - return TRUE - changeNext_move(CLICK_CD_RANGE) + return + if(!CheckActionCooldown(CLICK_CD_RANGE)) + return + DelayNextAction() 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 diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 6cf01ec8ff..f8a14b8c30 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -102,9 +102,8 @@ //stops TK grabs being equipped anywhere but into hands /obj/item/tk_grab/equipped(mob/user, slot) if(slot == SLOT_HANDS) - return + return ..() qdel(src) - return /obj/item/tk_grab/examine(user) if (focus) @@ -124,7 +123,8 @@ . = ..() if(!target || !user) return - + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return if(!focus) focus_object(target) return @@ -146,7 +146,7 @@ else apply_focus_overlay() focus.throw_at(target, 10, 1,user) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(considered_action = TRUE, flush = TRUE) update_icon() /proc/tkMaxRangeCheck(mob/user, atom/target) diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm index 4647b83cd7..259082a6ba 100644 --- a/code/controllers/configuration/config_entry.dm +++ b/code/controllers/configuration/config_entry.dm @@ -83,7 +83,7 @@ var/auto_trim = TRUE /datum/config_entry/string/vv_edit_var(var_name, var_value) - return var_name != "auto_trim" && ..() + return var_name != NAMEOF(src, auto_trim) && ..() /datum/config_entry/string/ValidateAndSet(str_val, during_load) if(!VASProcCallGuard(str_val)) @@ -110,7 +110,7 @@ return FALSE /datum/config_entry/number/vv_edit_var(var_name, var_value) - var/static/list/banned_edits = list("max_val", "min_val", "integer") + var/static/list/banned_edits = list(NAMEOF(src, max_val), NAMEOF(src, min_val), NAMEOF(src, integer)) return !(var_name in banned_edits) && ..() /datum/config_entry/flag @@ -209,12 +209,20 @@ new_value = new_list continue_check_value = new_list.len if(continue_check_value && continue_check_key && ValidateListEntry(new_key, new_value)) + new_key = preprocess_key(new_key) + new_value = preprocess_value(new_value) config_entry_value[new_key] = new_value return TRUE return FALSE /datum/config_entry/keyed_list/vv_edit_var(var_name, var_value) - return var_name != "splitter" && ..() + return var_name != NAMEOF(src, splitter) && ..() + +/datum/config_entry/keyed_list/proc/preprocess_key(key) + return key + +/datum/config_entry/keyed_list/proc/preprocess_value(value) + return value //snowflake for donator things being on one line smh /datum/config_entry/multi_keyed_flag diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 8f34901d46..1c6e96f9e4 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -14,6 +14,7 @@ var/list/modes // allowed modes var/list/gamemode_cache var/list/votable_modes // votable modes + // var/list/ic_filter_regex var/list/storyteller_cache var/list/mode_names var/list/mode_reports @@ -104,7 +105,9 @@ var/list/lines = world.file2list("[directory]/[filename]") var/list/_entries = entries var/list/postload_required = list() + var/linenumber = 0 for(var/L in lines) + linenumber++ L = trim(L) if(!L) continue @@ -132,7 +135,7 @@ if(entry == "$include") if(!value) - log_config("Warning: Invalid $include directive: [value]") + log_config("LINE [linenumber]: Invalid $include directive: [value]") else LoadEntries(value, stack) ++. @@ -140,7 +143,7 @@ var/datum/config_entry/E = _entries[entry] if(!E) - log_config("Unknown setting in configuration: '[entry]'") + log_config("LINE [linenumber]: Unknown setting: '[entry]'") continue if(lockthis) @@ -150,7 +153,7 @@ var/datum/config_entry/new_ver = entries_by_type[E.deprecated_by] var/new_value = E.DeprecationUpdate(value) var/good_update = istext(new_value) - log_config("Entry [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]") + log_config("LINE [linenumber]: [entry] is deprecated and will be removed soon. Migrate to [new_ver.name]![good_update ? " Suggested new value is: [new_value]" : ""]") if(!warned_deprecated_configs) addtimer(CALLBACK(GLOBAL_PROC, /proc/message_admins, "This server is using deprecated configuration settings. Please check the logs and update accordingly."), 0) warned_deprecated_configs = TRUE @@ -162,10 +165,10 @@ var/validated = E.ValidateAndSet(value, TRUE) if(!validated) - log_config("Failed to validate setting \"[value]\" for [entry]") + log_config("LINE [linenumber]: Failed to validate setting \"[value]\" for [entry]") else if(E.modified && !E.dupes_allowed) - log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.") + log_config("LINE [linenumber]: Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.") if(E.postload_required) postload_required[E] = TRUE @@ -412,3 +415,21 @@ continue runnable_modes[M] = probabilities[M.config_tag] return runnable_modes +/* +/datum/controller/configuration/proc/LoadChatFilter() + var/list/in_character_filter = list() + + if(!fexists("[directory]/in_character_filter.txt")) + return + log_config("Loading config file in_character_filter.txt...") + for(var/line in world.file2list("[directory]/in_character_filter.txt")) + if(!line) + continue + if(findtextEx(line,"#",1,2)) + continue + in_character_filter += REGEX_QUOTE(line) + + ic_filter_regex = in_character_filter.len ? regex("\\b([jointext(in_character_filter, "|")])\\b", "i") : null + + syncChatRegexes() +*/ diff --git a/code/controllers/configuration/entries/comms.dm b/code/controllers/configuration/entries/comms.dm index 012c3ec9fe..e56ff3f0d1 100644 --- a/code/controllers/configuration/entries/comms.dm +++ b/code/controllers/configuration/entries/comms.dm @@ -25,4 +25,23 @@ /datum/config_entry/string/medal_hub_address /datum/config_entry/string/medal_hub_password - protection = CONFIG_ENTRY_HIDDEN \ No newline at end of file + protection = CONFIG_ENTRY_HIDDEN + +/datum/config_entry/keyed_list/cross_server_bunker_override + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_TEXT + protection = CONFIG_ENTRY_LOCKED + +/datum/config_entry/keyed_list/cross_server_bunker_override/ValidateAndSet(str_val) + . = ..() + if(.) + var/list/newv = list() + for(var/I in config_entry_value) + newv[replacetext(I, "+", " ")] = config_entry_value[I] + config_entry_value = newv + +/datum/config_entry/keyed_list/cross_server_bunker_override/ValidateListEntry(key_name, key_value) + return key_value != "byond:\\address:port" && ..() + +/datum/config_entry/flag/allow_cross_server_bunker_override + protection = CONFIG_ENTRY_LOCKED diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 435a35c05e..2e3cb1ea46 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -98,6 +98,11 @@ config_entry_value = 6 min_val = 1 +/datum/config_entry/number/ecult_scaling_coeff //how much does the amount of players get divided by to determine e_cult + config_entry_value = 6 + integer = FALSE + min_val = 1 + /datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions config_entry_value = 8 min_val = 1 @@ -168,12 +173,14 @@ /datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game -/datum/config_entry/flag/no_summon_guns //No +/datum/config_entry/flag/no_summon_guns //No /datum/config_entry/flag/no_summon_magic //Fun /datum/config_entry/flag/no_summon_events //Allowed +/datum/config_entry/flag/no_summon_traumas //! + /datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overridden by gamemodes. /datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station @@ -527,4 +534,4 @@ config_entry_value = 6 /datum/config_entry/number/max_shuttle_size - config_entry_value = 250 + config_entry_value = 500 diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index a1f8f098d3..2d5e69f149 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -56,6 +56,8 @@ /datum/config_entry/flag/log_adminchat // log admin chat messages protection = CONFIG_ENTRY_LOCKED +/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console + /datum/config_entry/flag/log_pda // log pda messages /datum/config_entry/flag/log_telecomms // log telecomms messages @@ -468,3 +470,5 @@ /datum/config_entry/flag/minimaps_enabled config_entry_value = TRUE + +/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API diff --git a/code/controllers/configuration/entries/policy.dm b/code/controllers/configuration/entries/policy.dm new file mode 100644 index 0000000000..de611e1813 --- /dev/null +++ b/code/controllers/configuration/entries/policy.dm @@ -0,0 +1,11 @@ +/// Seconds for CMD on defib-with-memory-loss policy config to display instead of defib-intact config +/datum/config_entry/number/defib_cmd_time_limit + config_entry_value = 300 + integer = TRUE + +/datum/config_entry/keyed_list/policyconfig + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_TEXT + +/datum/config_entry/keyed_list/policyconfig/preprocess_key(key) + return uppertext(..()) diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm index a16de2ba4c..4ee3a01956 100644 --- a/code/controllers/subsystem.dm +++ b/code/controllers/subsystem.dm @@ -210,10 +210,10 @@ /datum/controller/subsystem/vv_edit_var(var_name, var_value) switch (var_name) - if ("can_fire") + if (NAMEOF(src, can_fire)) //this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag if (var_value) next_fire = world.time + wait - if ("queued_priority") //editing this breaks things. - return 0 + if (NAMEOF(src, queued_priority)) //editing this breaks things. + return FALSE . = ..() diff --git a/code/controllers/subsystem/acid.dm b/code/controllers/subsystem/acid.dm index e3c415960b..7c9e7634ab 100644 --- a/code/controllers/subsystem/acid.dm +++ b/code/controllers/subsystem/acid.dm @@ -29,7 +29,7 @@ SUBSYSTEM_DEF(acid) if(O.acid_level && O.acid_processing()) else - O.cut_overlay(GLOB.acid_overlay, TRUE) + O.update_icon() processing -= O if (MC_TICK_CHECK) diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 4d8bc3b1f6..baceb4d055 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -6,7 +6,7 @@ SUBSYSTEM_DEF(air) flags = SS_BACKGROUND runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - var/cost_turf_reactions = 0 + var/cost_turfs = 0 var/cost_groups = 0 var/cost_highpressure = 0 var/cost_hotspots = 0 @@ -14,10 +14,9 @@ SUBSYSTEM_DEF(air) var/cost_pipenets = 0 var/cost_rebuilds = 0 var/cost_atmos_machinery = 0 + var/cost_equalize = 0 - var/list/excited_groups = list() var/list/active_turfs = list() - var/list/turf_react_queue = list() var/list/hotspots = list() var/list/networks = list() var/list/pipenets_needing_rebuilt = list() @@ -38,20 +37,25 @@ SUBSYSTEM_DEF(air) var/map_loading = TRUE var/list/queued_for_activation + var/log_explosive_decompression = TRUE // If things get spammy, admemes can turn this off. + + var/monstermos_turf_limit = 10 + var/monstermos_hard_turf_limit = 2000 + var/monstermos_enabled = TRUE + /datum/controller/subsystem/air/stat_entry(msg) msg += "C:{" - msg += "RQ:[round(cost_turf_reactions,1)]|" + msg += "EQ:[round(cost_equalize,1)]|" + msg += "AT:[round(cost_turfs,1)]|" msg += "EG:[round(cost_groups,1)]|" msg += "HP:[round(cost_highpressure,1)]|" msg += "HS:[round(cost_hotspots,1)]|" msg += "SC:[round(cost_superconductivity,1)]|" msg += "PN:[round(cost_pipenets,1)]|" - msg += "RB:[round(cost_rebuilds,1)]|" msg += "AM:[round(cost_atmos_machinery,1)]" msg += "} " msg += "AT:[active_turfs.len]|" - msg += "RQ:[turf_react_queue.len]|" - msg += "EG:[excited_groups.len]|" + msg += "EG:[get_amt_excited_groups()]|" msg += "HS:[hotspots.len]|" msg += "PN:[networks.len]|" msg += "HP:[high_pressure_delta.len]|" @@ -59,8 +63,8 @@ SUBSYSTEM_DEF(air) msg += "AT/MS:[round((cost ? active_turfs.len/cost : 0),0.1)]" ..(msg) - /datum/controller/subsystem/air/Initialize(timeofday) + extools_update_ssair() map_loading = FALSE setup_allturfs() setup_atmos_machinery() @@ -68,6 +72,7 @@ SUBSYSTEM_DEF(air) gas_reactions = init_gas_reactions() return ..() +/datum/controller/subsystem/air/proc/extools_update_ssair() /datum/controller/subsystem/air/fire(resumed = 0) var/timer = TICK_USAGE_REAL @@ -101,12 +106,21 @@ SUBSYSTEM_DEF(air) if(state != SS_RUNNING) return resumed = 0 - currentpart = SSAIR_REACTQUEUE + currentpart = monstermos_enabled ? SSAIR_EQUALIZE : SSAIR_ACTIVETURFS - if(currentpart == SSAIR_REACTQUEUE) + if(currentpart == SSAIR_EQUALIZE) timer = TICK_USAGE_REAL - process_react_queue(resumed) - cost_turf_reactions = MC_AVERAGE(cost_turf_reactions, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + process_turf_equalize(resumed) + cost_equalize = MC_AVERAGE(cost_equalize, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) + if(state != SS_RUNNING) + return + resumed = 0 + currentpart = SSAIR_ACTIVETURFS + + if(currentpart == SSAIR_ACTIVETURFS) + timer = TICK_USAGE_REAL + process_active_turfs(resumed) + cost_turfs = MC_AVERAGE(cost_turfs, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer)) if(state != SS_RUNNING) return resumed = 0 @@ -148,6 +162,8 @@ SUBSYSTEM_DEF(air) resumed = 0 currentpart = SSAIR_REBUILD_PIPENETS + + /datum/controller/subsystem/air/proc/process_pipenets(resumed = 0) if (!resumed) src.currentrun = networks.Copy() @@ -182,19 +198,6 @@ SUBSYSTEM_DEF(air) return -/datum/controller/subsystem/air/proc/process_react_queue(resumed = 0) - if(!resumed) - src.currentrun = turf_react_queue.Copy() - var/list/currentrun = src.currentrun - while(currentrun.len) - var/turf/open/T = currentrun[currentrun.len] - currentrun.len-- - if(T) - T.process_cell_reaction() - if(MC_TICK_CHECK) - return - - /datum/controller/subsystem/air/proc/process_super_conductivity(resumed = 0) if (!resumed) src.currentrun = active_super_conductivity.Copy() @@ -229,10 +232,45 @@ SUBSYSTEM_DEF(air) high_pressure_delta.len-- T.high_pressure_movements() T.pressure_difference = 0 + T.pressure_specific_target = null if(MC_TICK_CHECK) return +/datum/controller/subsystem/air/proc/process_turf_equalize(resumed = 0) + //cache for sanic speed + var/fire_count = times_fired + if (!resumed) + src.currentrun = active_turfs.Copy() + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + while(currentrun.len) + var/turf/open/T = currentrun[currentrun.len] + currentrun.len-- + if (T) + T.equalize_pressure_in_zone(fire_count) + //equalize_pressure_in_zone(T, fire_count) + if (MC_TICK_CHECK) + return + +/datum/controller/subsystem/air/proc/process_active_turfs(resumed = 0) + //cache for sanic speed + var/fire_count = times_fired + if (!resumed) + src.currentrun = active_turfs.Copy() + //cache for sanic speed (lists are references anyways) + var/list/currentrun = src.currentrun + while(currentrun.len) + var/turf/open/T = currentrun[currentrun.len] + currentrun.len-- + if (T) + T.process_cell(fire_count) + if (MC_TICK_CHECK) + return + /datum/controller/subsystem/air/proc/process_excited_groups(resumed = 0) + if(process_excited_groups_extools(resumed, (Master.current_ticklimit - TICK_USAGE) * 0.01 * world.tick_lag)) + sleep() + /* if (!resumed) src.currentrun = excited_groups.Copy() //cache for sanic speed (lists are references anyways) @@ -248,29 +286,33 @@ SUBSYSTEM_DEF(air) EG.dismantle() if (MC_TICK_CHECK) return + */ + +/datum/controller/subsystem/air/proc/process_excited_groups_extools() +/datum/controller/subsystem/air/proc/get_amt_excited_groups() /datum/controller/subsystem/air/proc/remove_from_active(turf/open/T) active_turfs -= T - SSair_turfs.currentrun -= T + if(currentpart == SSAIR_ACTIVETURFS) + currentrun -= T #ifdef VISUALIZE_ACTIVE_TURFS T.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#00ff00") #endif if(istype(T)) - T.excited = 0 - if(T.excited_group) - T.excited_group.garbage_collect() - remove_from_react_queue(T) + T.set_excited(FALSE) + T.eg_garbage_collect() /datum/controller/subsystem/air/proc/add_to_active(turf/open/T, blockchanges = 1) if(istype(T) && T.air) #ifdef VISUALIZE_ACTIVE_TURFS T.add_atom_colour("#00ff00", TEMPORARY_COLOUR_PRIORITY) #endif - T.excited = TRUE - active_turfs[T] = SSair_turfs.currentrun[T] = TRUE - if(blockchanges && T.excited_group) - T.excited_group.garbage_collect() - add_to_react_queue(T) + T.set_excited(TRUE) + active_turfs |= T + if(currentpart == SSAIR_ACTIVETURFS) + currentrun |= T + if(blockchanges) + T.eg_garbage_collect() else if(T.flags_1 & INITIALIZED_1) for(var/turf/S in T.atmos_adjacent_turfs) add_to_active(S) @@ -281,17 +323,6 @@ SUBSYSTEM_DEF(air) else T.requires_activation = TRUE -/datum/controller/subsystem/air/proc/add_to_react_queue(turf/open/T) - if(istype(T) && T.air) - turf_react_queue[T] = TRUE - if(currentpart == SSAIR_REACTQUEUE) - currentrun[T] = TRUE - -/datum/controller/subsystem/air/proc/remove_from_react_queue(turf/open/T) - turf_react_queue -= T - if(currentpart == SSAIR_REACTQUEUE) - currentrun -= T - /datum/controller/subsystem/air/StartLoadingMap() LAZYINITLIST(queued_for_activation) map_loading = TRUE @@ -339,11 +370,11 @@ SUBSYSTEM_DEF(air) while (turfs_to_check.len) var/ending_ats = active_turfs.len - for(var/thing in excited_groups) + /*for(var/thing in excited_groups) var/datum/excited_group/EG = thing - EG.self_breakdown(space_is_all_consuming = 1) - EG.dismantle() - CHECK_TICK + //EG.self_breakdown(space_is_all_consuming = 1) + //EG.dismantle() + CHECK_TICK*/ var/msg = "HEY! LISTEN! [DisplayTimeText(world.timeofday - timer)] were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start." to_chat(world, "[msg]") @@ -351,6 +382,7 @@ SUBSYSTEM_DEF(air) /turf/open/proc/resolve_active_graph() . = list() + /* var/datum/excited_group/EG = excited_group if (blocks_air || !air) return @@ -371,7 +403,8 @@ SUBSYSTEM_DEF(air) EG.add_turf(ET) if (!ET.excited) ET.excited = 1 - . += ET + . += ET*/ + /turf/open/space/resolve_active_graph() return list() @@ -389,9 +422,8 @@ SUBSYSTEM_DEF(air) CHECK_TICK /datum/controller/subsystem/air/proc/setup_template_machinery(list/atmos_machines) - if(!initialized) - return - + if(!initialized) // yogs - fixes randomized bars + return // yogs for(var/A in atmos_machines) var/obj/machinery/atmospherics/AM = A AM.atmosinit() @@ -415,6 +447,7 @@ SUBSYSTEM_DEF(air) #undef SSAIR_PIPENETS #undef SSAIR_ATMOSMACHINERY +#undef SSAIR_ACTIVETURFS #undef SSAIR_EXCITEDGROUPS #undef SSAIR_HIGHPRESSURE #undef SSAIR_HOTSPOTS diff --git a/code/controllers/subsystem/air_turfs.dm b/code/controllers/subsystem/air_turfs.dm index 9dd41aede5..7320defcae 100644 --- a/code/controllers/subsystem/air_turfs.dm +++ b/code/controllers/subsystem/air_turfs.dm @@ -1,5 +1,5 @@ //WHAT IF WE TAKE THE ACTIVE TURF PROCESSING AND PUSH IT SOMEWHERE ELSE!!! - +/* SUBSYSTEM_DEF(air_turfs) name = "Atmospherics - Turfs" init_order = INIT_ORDER_AIR_TURFS @@ -24,3 +24,4 @@ SUBSYSTEM_DEF(air_turfs) return resumed = 0 return +*/ diff --git a/code/controllers/subsystem/assets.dm b/code/controllers/subsystem/assets.dm index 7b6554bd3f..7285298283 100644 --- a/code/controllers/subsystem/assets.dm +++ b/code/controllers/subsystem/assets.dm @@ -6,17 +6,7 @@ SUBSYSTEM_DEF(assets) var/list/preload = list() /datum/controller/subsystem/assets/Initialize(timeofday) - - var/list/priority_assets = list( - /datum/asset/simple/oui_theme_nano, - /datum/asset/simple/goonchat - ) - - for(var/type in priority_assets) - var/datum/asset/A = new type() - A.register() - - for(var/type in typesof(/datum/asset) - (priority_assets | list(/datum/asset, /datum/asset/simple))) + for(var/type in typesof(/datum/asset)) var/datum/asset/A = type if (type != initial(A._abstract)) get_asset_datum(type) diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index c1644df9c9..db1fced637 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -16,6 +16,7 @@ SUBSYSTEM_DEF(atoms) /datum/controller/subsystem/atoms/Initialize(timeofday) GLOB.fire_overlay.appearance_flags = RESET_COLOR + setupGenetics() initialized = INITIALIZATION_INNEW_MAPLOAD InitializeAtoms() return ..() @@ -106,6 +107,29 @@ SUBSYSTEM_DEF(atoms) old_initialized = SSatoms.old_initialized BadInitializeCalls = SSatoms.BadInitializeCalls +/datum/controller/subsystem/atoms/proc/setupGenetics() + var/list/mutations = subtypesof(/datum/mutation/human) + shuffle_inplace(mutations) + for(var/A in subtypesof(/datum/generecipe)) + var/datum/generecipe/GR = A + GLOB.mutation_recipes[initial(GR.required)] = initial(GR.result) + for(var/i in 1 to LAZYLEN(mutations)) + var/path = mutations[i] //byond gets pissy when we do it in one line + var/datum/mutation/human/B = new path () + B.alias = "Mutation [i]" + GLOB.all_mutations[B.type] = B + GLOB.full_sequences[B.type] = generate_gene_sequence(B.blocks) + GLOB.alias_mutations[B.alias] = B.type + if(B.locked) + continue + if(B.quality == POSITIVE) + GLOB.good_mutations |= B + else if(B.quality == NEGATIVE) + GLOB.bad_mutations |= B + else if(B.quality == MINOR_NEGATIVE) + GLOB.not_good_mutations |= B + CHECK_TICK + /datum/controller/subsystem/atoms/proc/InitLog() . = "" for(var/path in BadInitializeCalls) diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index d6991a40b4..dc1f246e3d 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -60,9 +60,9 @@ SUBSYSTEM_DEF(blackbox) /datum/controller/subsystem/blackbox/vv_edit_var(var_name, var_value) switch(var_name) - if("feedback") + if(NAMEOF(src, feedback)) return FALSE - if("sealed") + if(NAMEOF(src, sealed)) if(var_value) return Seal() return FALSE diff --git a/code/controllers/subsystem/chat.dm b/code/controllers/subsystem/chat.dm index 8d4de0c091..ba2794d00f 100644 --- a/code/controllers/subsystem/chat.dm +++ b/code/controllers/subsystem/chat.dm @@ -4,6 +4,7 @@ SUBSYSTEM_DEF(chat) wait = 1 priority = FIRE_PRIORITY_CHAT init_order = INIT_ORDER_CHAT + var/list/payload = list() @@ -17,7 +18,7 @@ SUBSYSTEM_DEF(chat) return -/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE) +/datum/controller/subsystem/chat/proc/queue(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = TRUE) if(!target || !message) return @@ -30,30 +31,35 @@ SUBSYSTEM_DEF(chat) //Some macros remain in the string even after parsing and fuck up the eventual output var/original_message = message - message = replacetext(message, "\improper", "") - message = replacetext(message, "\proper", "") - if(handle_whitespace) - message = replacetext(message, "\n", "
") - message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") - message += "
" - //url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript. //Do the double-encoding here to save nanoseconds - var/twiceEncoded = url_encode(url_encode(message)) + var/twiceEncoded if(islist(target)) + var/sanitized_message = FALSE for(var/I in target) var/client/C = CLIENT_FROM_VAR(I) //Grab us a client if possible if(!C) - return + continue //Send it to the old style output window. SEND_TEXT(C, original_message) if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file. continue + + if(!sanitized_message) + message = replacetext(message, "\improper", "") + message = replacetext(message, "\proper", "") + if(handle_whitespace) + message = replacetext(message, "\n", "
") + message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") + if (trailing_newline) + message += "
" + twiceEncoded = url_encode(url_encode(message)) + sanitized_message = TRUE if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue C.chatOutput.messageQueue += message @@ -73,6 +79,15 @@ SUBSYSTEM_DEF(chat) if(!C?.chatOutput || C.chatOutput.broken) //A player who hasn't updated his skin file. return + message = replacetext(message, "\improper", "") + message = replacetext(message, "\proper", "") + if(handle_whitespace) + message = replacetext(message, "\n", "
") + message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") + if (trailing_newline) + message += "
" + twiceEncoded = url_encode(url_encode(message)) + if(!C.chatOutput.loaded) //Client still loading, put their messages in a queue C.chatOutput.messageQueue += message return diff --git a/code/controllers/subsystem/events.dm b/code/controllers/subsystem/events.dm index abc46cba25..2e4e728191 100644 --- a/code/controllers/subsystem/events.dm +++ b/code/controllers/subsystem/events.dm @@ -12,7 +12,7 @@ SUBSYSTEM_DEF(events) var/frequency_upper = 6000 //10 minutes upper bound. Basically an event will happen every 3 to 10 minutes. var/list/holidays //List of all holidays occuring today or null if no holidays - var/wizardmode = 0 + var/wizardmode = FALSE /datum/controller/subsystem/events/Initialize(time, zlevel) for(var/type in typesof(/datum/round_event_control)) @@ -91,6 +91,7 @@ SUBSYSTEM_DEF(events) if(. == EVENT_CANT_RUN)//we couldn't run this event for some reason, set its max_occurrences to 0 E.max_occurrences = 0 else if(. == EVENT_READY) + E.random = TRUE E.runEvent(TRUE) //allows a client to trigger an event diff --git a/code/controllers/subsystem/fluid.dm b/code/controllers/subsystem/fluid.dm new file mode 100644 index 0000000000..c4fa13d693 --- /dev/null +++ b/code/controllers/subsystem/fluid.dm @@ -0,0 +1,5 @@ +PROCESSING_SUBSYSTEM_DEF(fluids) + name = "Fluids" + wait = 20 + stat_tag = "FD" //its actually Fluid Ducts + flags = SS_NO_INIT | SS_TICKER diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 8a1c08bc35..b46e22c1fa 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -25,7 +25,7 @@ SUBSYSTEM_DEF(garbage) //Queue var/list/queues - #ifdef TESTING + #ifdef LEGACY_REFERENCE_TRACKING var/list/reference_find_on_fail = list() var/list/reference_find_on_fail_types = list() #endif @@ -134,7 +134,7 @@ SUBSYSTEM_DEF(garbage) ++gcedlasttick ++totalgcs pass_counts[level]++ - #ifdef TESTING + #ifdef LEGACY_REFERENCE_TRACKING reference_find_on_fail -= refID //It's deleted we don't care anymore. #endif if (MC_TICK_CHECK) @@ -145,7 +145,9 @@ SUBSYSTEM_DEF(garbage) fail_counts[level]++ switch (level) if (GC_QUEUE_CHECK) - #ifdef TESTING + #ifdef REFERENCE_TRACKING + D.find_references() + #elif defined(LEGACY_REFERENCE_TRACKING) if(reference_find_on_fail[refID]) D.find_references() #ifdef GC_FAILURE_HARD_LOOKUP @@ -156,7 +158,19 @@ SUBSYSTEM_DEF(garbage) #endif var/type = D.type var/datum/qdel_item/I = items[type] + #ifdef TESTING + log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --") + for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage + var/client/admin = c + if(!check_rights_for(admin, R_ADMIN)) + continue + to_chat(admin, "## TESTING: GC: -- [ADMIN_VV(D)] | [type] was unable to be GC'd --") testing("GC: -- \ref[src] | [type] was unable to be GC'd --") + #endif + #ifdef REFERENCE_TRACKING + GLOB.deletion_failures += D //It should no longer be bothered by the GC, manual deletion only. + continue + #endif I.failures++ if (GC_QUEUE_HARDDELETE) HardDelete(D) @@ -181,7 +195,7 @@ SUBSYSTEM_DEF(garbage) var/gctime = world.time var/refid = "\ref[D]" -#ifdef TESTING +#ifdef LEGACY_REFERENCE_TRACKING if(reference_find_on_fail_types[D.type]) reference_find_on_fail["\ref[D]"] = TRUE #endif @@ -193,7 +207,7 @@ SUBSYSTEM_DEF(garbage) queue[refid] = gctime -#ifdef TESTING +#ifdef LEGACY_REFERENCE_TRACKING /datum/controller/subsystem/garbage/proc/add_type_to_findref(type) if(!ispath(type)) return "NOT A VAILD PATH" @@ -260,12 +274,6 @@ SUBSYSTEM_DEF(garbage) /datum/qdel_item/New(mytype) name = "[mytype]" -#ifdef TESTING -/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE) - SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE - qdel(D, force) -#endif - // Should be treated as a replacement for the 'del' keyword. // Datums passed to this will be given a chance to clean up references to allow the GC to collect them. /proc/qdel(datum/D, force=FALSE, ...) @@ -319,16 +327,13 @@ SUBSYSTEM_DEF(garbage) SSgarbage.Queue(D, GC_QUEUE_HARDDELETE) if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste. SSgarbage.HardDelete(D) - if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion. + #ifdef LEGACY_REFERENCE_TRACKING + if (QDEL_HINT_FINDREFERENCE) //qdel will, if LEGACY_REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion. SSgarbage.Queue(D) - #ifdef TESTING - D.find_references() - #endif if (QDEL_HINT_IFFAIL_FINDREFERENCE) SSgarbage.Queue(D) - #ifdef TESTING SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE - #endif + #endif else #ifdef TESTING if(!I.no_hint) @@ -339,119 +344,6 @@ SUBSYSTEM_DEF(garbage) else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED) CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic") -#ifdef TESTING - -/datum/verb/find_refs() - set category = "Debug" - set name = "Find References" - set src in world - - find_references(FALSE) - -/datum/proc/find_references(skip_alert) - running_find_references = type - if(usr && usr.client) - if(usr.client.running_find_references) - testing("CANCELLED search for references to a [usr.client.running_find_references].") - usr.client.running_find_references = null - running_find_references = null - //restart the garbage collector - SSgarbage.can_fire = 1 - SSgarbage.next_fire = world.time + world.tick_lag - return - - if(!skip_alert) - if(alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") == "No") - running_find_references = null - return - - //this keeps the garbage collector from failing to collect objects being searched for in here - SSgarbage.can_fire = 0 - - if(usr && usr.client) - usr.client.running_find_references = type - - testing("Beginning search for references to a [type].") - last_find_references = world.time - - DoSearchVar(GLOB) //globals - for(var/datum/thing in world) //atoms (don't beleive it's lies) - DoSearchVar(thing, "World -> [thing]") - - for (var/datum/thing) //datums - DoSearchVar(thing, "World -> [thing]") - - for (var/client/thing) //clients - DoSearchVar(thing, "World -> [thing]") - - testing("Completed search for references to a [type].") - if(usr && usr.client) - usr.client.running_find_references = null - running_find_references = null - - //restart the garbage collector - SSgarbage.can_fire = 1 - SSgarbage.next_fire = world.time + world.tick_lag - -/datum/verb/qdel_then_find_references() - set category = "Debug" - set name = "qdel() then Find References" - set src in world - - qdel(src, TRUE) //Force. - if(!running_find_references) - find_references(TRUE) - -/datum/verb/qdel_then_if_fail_find_references() - set category = "Debug" - set name = "qdel() then Find References if GC failure" - set src in world - - qdel_and_find_ref_if_fail(src, TRUE) - -/datum/proc/DoSearchVar(X, Xname, recursive_limit = 64) - if(usr && usr.client && !usr.client.running_find_references) - return - if (!recursive_limit) - return - - if(istype(X, /datum)) - var/datum/D = X - if(D.last_find_references == last_find_references) - return - - D.last_find_references = last_find_references - var/list/L = D.vars - - for(var/varname in L) - if (varname == "vars") - continue - var/variable = L[varname] - - if(variable == src) - testing("Found [src.type] \ref[src] in [D.type]'s [varname] var. [Xname]") - - else if(islist(variable)) - DoSearchVar(variable, "[Xname] -> list", recursive_limit-1) - - else if(islist(X)) - var/normal = IS_NORMAL_LIST(X) - for(var/I in X) - if (I == src) - testing("Found [src.type] \ref[src] in list [Xname].") - - else if (I && !isnum(I) && normal && X[I] == src) - testing("Found [src.type] \ref[src] in list [Xname]\[[I]\]") - - else if (islist(I)) - DoSearchVar(I, "[Xname] -> list", recursive_limit-1) - -#ifndef FIND_REF_NO_CHECK_TICK - CHECK_TICK -#endif - -#endif - #ifdef TESTING /proc/writeDatumCount() var/list/datums = list() diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm index 7c51ba4506..32936af9e9 100644 --- a/code/controllers/subsystem/input.dm +++ b/code/controllers/subsystem/input.dm @@ -64,19 +64,33 @@ SUBSYSTEM_DEF(input) // 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=\\\"\\\"\\\"\"" - + // FINALLY, WE CAN DO SOMETHING MORE NORMAL FOR THE SNOWFLAKE-BUT-LESS KEYSET. + + // HAHA - SIKE. Because of BYOND weirdness (tl;dr not specifically binding this way results in potentially duplicate chatboxes when + // conflicts occur with something like say indicator vs say), we're going to snowflake this anyways + var/list/hard_binds = list( + "O" = "ooc", + "T" = "say", + "L" = "looc", + "M" = "me" + ) + var/list/hard_bind_anti_collision = list() + var/list/anti_collision_modifiers = list("Ctrl", "Alt", "Shift", "Ctrl+Alt", "Ctrl+Shift", "Alt+Shift", "Ctrl+Alt+Shift") + for(var/key in hard_binds) + for(var/modifier in anti_collision_modifiers) + hard_bind_anti_collision["[modifier]+[key]"] = ".NONSENSICAL_VERB_THAT_DOES_NOTHING" + 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" ) + + macroset_classic_hotkey |= hard_binds + macroset_classic_hotkey |= hard_bind_anti_collision // And finally, the modern set. macroset_hotkey = list( @@ -85,11 +99,10 @@ SUBSYSTEM_DEF(input) "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" ) + + macroset_hotkey |= hard_binds + macroset_hotkey |= hard_bind_anti_collision // Badmins just wanna have fun ♪ /datum/controller/subsystem/input/proc/refresh_client_macro_sets() @@ -104,3 +117,8 @@ SUBSYSTEM_DEF(input) for(var/i in 1 to clients.len) var/client/C = clients[i] C.keyLoop() + +/// *sigh +/client/verb/NONSENSICAL_VERB_THAT_DOES_NOTHING() + set name = ".NONSENSICAL_VERB_THAT_DOES_NOTHING" + set hidden = TRUE diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 4b2cf24f1e..4f59992ace 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -674,7 +674,7 @@ SUBSYSTEM_DEF(job) return for(var/i in the_mob.client.prefs.chosen_gear) var/datum/gear/G = i - G = GLOB.loadout_items[slot_to_string(initial(G.category))][initial(G.name)] + G = GLOB.loadout_items[initial(G.category)][initial(G.subcategory)][initial(G.name)] if(!G) continue var/permitted = TRUE @@ -682,14 +682,14 @@ SUBSYSTEM_DEF(job) permitted = FALSE if(G.donoritem && !G.donator_ckey_check(the_mob.client.ckey)) permitted = FALSE - if(!equipbackpackstuff && G.category == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs + if(!equipbackpackstuff && G.slot == SLOT_IN_BACKPACK)//snowflake check since plopping stuff in the backpack doesnt work for pre-job equip loadout stuffs permitted = FALSE - if(equipbackpackstuff && G.category != SLOT_IN_BACKPACK)//ditto + if(equipbackpackstuff && G.slot != SLOT_IN_BACKPACK)//ditto permitted = FALSE if(!permitted) continue var/obj/item/I = new G.path - if(!M.equip_to_slot_if_possible(I, G.category, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first + if(!M.equip_to_slot_if_possible(I, G.slot, disable_warning = TRUE, bypass_equip_delay_self = TRUE)) // If the job's dresscode compliant, try to put it in its slot, first if(iscarbon(M)) var/mob/living/carbon/C = M var/obj/item/storage/backpack/B = C.back diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index b234c4c4f2..617004646a 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -113,7 +113,7 @@ SUBSYSTEM_DEF(mapping) // needs to be whitelisted for underground too so place_below ruins work seedRuins(ice_ruins, CONFIG_GET(number/icemoon_budget), list(/area/icemoon/surface/outdoors/unexplored, /area/icemoon/underground/unexplored), ice_ruins_templates) for (var/ice_z in ice_ruins) - spawn_rivers(ice_z, 4, /turf/open/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers) + spawn_rivers(ice_z, 4, /turf/open/transparent/openspace/icemoon, /area/icemoon/surface/outdoors/unexplored/rivers) var/list/ice_ruins_underground = levels_by_trait(ZTRAIT_ICE_RUINS_UNDERGROUND) if (ice_ruins_underground.len) @@ -334,6 +334,7 @@ GLOBAL_LIST_EMPTY(the_station_areas) for (var/map in mapvotes) if (!map) mapvotes.Remove(map) + continue if (!(map in global.config.maplist)) mapvotes.Remove(map) continue @@ -468,11 +469,10 @@ GLOBAL_LIST_EMPTY(the_station_areas) else return - possible_options += "Custom" - var/lvl_name - var/datum/space_level/level + var/away_name + var/datum/space_level/away_level - var/answer = input("What kind ? ","Away/VR") as null|anything in possible_options + var/answer = input("What kind ? ","Away/VR") as null|anything in list(possible_options + "Custom") switch(answer) if(null) return @@ -480,34 +480,22 @@ GLOBAL_LIST_EMPTY(the_station_areas) var/mapfile = input("Pick file:", "File") as null|file if(!mapfile) return - lvl_name = "[mapfile] custom" - to_chat(usr,"Loading [lvl_name]...") + away_name = "[mapfile] custom" + to_chat(usr,"Loading [away_name]...") var/datum/map_template/template = new(mapfile, choice, ztraits) - level = template.load_new_z(ztraits) + away_level = template.load_new_z(ztraits) else - lvl_name = answer - to_chat(usr,"Loading [lvl_name]...") - var/datum/map_template/template = new(lvl_name, choice) - level = template.load_new_z(ztraits) + away_name = answer + to_chat(usr,"Loading [away_name]...") + var/datum/map_template/template = new(away_name, choice) + away_level = template.load_new_z(ztraits) - message_admins("Admin [key_name_admin(usr)] has loaded [lvl_name] [choice].") - log_admin("Admin [key_name(usr)] has loaded [lvl_name] [choice].") - if(!level) - message_admins("Loading [lvl_name] failed!") + message_admins("Admin [key_name_admin(usr)] has loaded [away_name] away mission.") + log_admin("Admin [key_name(usr)] has loaded [away_name] away mission.") + if(!away_level) + message_admins("Loading [away_name] failed!") return - - if(choice == AWAY_MISSION_NAME && GLOB.the_gateway) - //Link any found away gate with station gate - var/obj/machinery/gateway/centeraway/new_gate - for(var/obj/machinery/gateway/centeraway/G in GLOB.machines) - if(G.z == level.z_value) //I'll have to refactor gateway shitcode before multi-away support. - new_gate = G - break - //Link station gate with away gate and remove wait time. - GLOB.the_gateway.awaygate = new_gate - GLOB.the_gateway.wait = world.time - /datum/controller/subsystem/mapping/proc/RequestBlockReservation(width, height, z, type = /datum/turf_reservation, turf_type_override, border_type_override) UNTIL((!z || reservation_ready["[z]"]) && !clearing_reserved_turfs) var/datum/turf_reservation/reserve = new type diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index 96d733e8da..23d5a7a2b7 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -10,24 +10,52 @@ SUBSYSTEM_DEF(materials) var/list/materials ///Dictionary of category || list of material refs var/list/materials_by_category + ///Dictionary of category || list of material types, mostly used by rnd machines like autolathes. + var/list/materialtypes_by_category + ///A cache of all material combinations that have been used + var/list/list/material_combos ///List of stackcrafting recipes for materials using rigid materials var/list/rigid_stack_recipes = list( new /datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), new /datum/stack_recipe("toilet", /obj/structure/toilet/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), new /datum/stack_recipe("sink", /obj/structure/sink/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + new /datum/stack_recipe("Floor tile", /obj/item/stack/tile/material, 1, 4, 20, applies_mats = TRUE) ) ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) /datum/controller/subsystem/materials/proc/InitializeMaterials() materials = list() materials_by_category = list() + materialtypes_by_category = list() + material_combos = list() for(var/type in subtypesof(/datum/material)) var/datum/material/ref = new type materials[type] = ref for(var/c in ref.categories) materials_by_category[c] += list(ref) + materialtypes_by_category[c] += list(type) /datum/controller/subsystem/materials/proc/GetMaterialRef(datum/material/fakemat) if(!materials) InitializeMaterials() - return materials[fakemat] || fakemat \ No newline at end of file + return materials[fakemat] || fakemat + + +///Returns a list to be used as an object's custom_materials. Lists will be cached and re-used based on the parameters. +/datum/controller/subsystem/materials/proc/FindOrCreateMaterialCombo(list/materials_declaration, multiplier) + if(!material_combos) + InitializeMaterials() + var/list/combo_params = list() + for(var/x in materials_declaration) + var/datum/material/mat = x + var/path_name = ispath(mat) ? "[mat]" : "[mat.type]" + combo_params += "[path_name]=[materials_declaration[mat] * multiplier]" + sortTim(combo_params, /proc/cmp_text_asc) // We have to sort now in case the declaration was not in order + var/combo_index = combo_params.Join("-") + var/list/combo = material_combos[combo_index] + if(!combo) + combo = list() + for(var/mat in materials_declaration) + combo[GetMaterialRef(mat)] = materials_declaration[mat] * multiplier + material_combos[combo_index] = combo + return combo diff --git a/code/controllers/subsystem/minimaps.dm b/code/controllers/subsystem/minimaps.dm index 75de71ca96..c25036a47d 100644 --- a/code/controllers/subsystem/minimaps.dm +++ b/code/controllers/subsystem/minimaps.dm @@ -1,8 +1,8 @@ SUBSYSTEM_DEF(minimaps) name = "Minimaps" flags = SS_NO_FIRE - var/list/station_minimaps - var/datum/minimap_group/station_minimap + var/list/station_minimaps = list() + var/datum/minimap_group/station_minimap = null /datum/controller/subsystem/minimaps/Initialize() if(!CONFIG_GET(flag/minimaps_enabled)) @@ -12,9 +12,9 @@ SUBSYSTEM_DEF(minimaps) return ..() /datum/controller/subsystem/minimaps/proc/build_minimaps() - station_minimaps = list() for(var/z in SSmapping.levels_by_trait(ZTRAIT_STATION)) var/datum/space_level/SL = SSmapping.get_level(z) var/name = (SL.name == initial(SL.name))? "[z] - Station" : "[z] - [SL.name]" station_minimaps += new /datum/minimap(z, name = name) + station_minimap = new(station_minimaps, "Station") diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm index 7fd3512448..2d2fbb0704 100644 --- a/code/controllers/subsystem/npcpool.dm +++ b/code/controllers/subsystem/npcpool.dm @@ -23,7 +23,7 @@ SUBSYSTEM_DEF(npcpool) var/mob/living/simple_animal/SA = currentrun[currentrun.len] --currentrun.len - if(!SA.ckey && !SA.notransform) + if(!SA.ckey && !SA.mob_transforming) if(SA.stat != DEAD) SA.handle_automated_movement() if(SA.stat != DEAD) diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm index 20eb2af001..ea0f82436c 100644 --- a/code/controllers/subsystem/overlays.dm +++ b/code/controllers/subsystem/overlays.dm @@ -114,67 +114,47 @@ SUBSYSTEM_DEF(overlays) #define NOT_QUEUED_ALREADY (!(flags_1 & OVERLAY_QUEUED_1)) #define QUEUE_FOR_COMPILE flags_1 |= OVERLAY_QUEUED_1; SSoverlays.queue += src; -/atom/proc/cut_overlays(priority = FALSE) - LAZYINITLIST(priority_overlays) +/atom/proc/cut_overlays() LAZYINITLIST(remove_overlays) LAZYINITLIST(add_overlays) remove_overlays = overlays.Copy() add_overlays.Cut() - if(priority) - priority_overlays.Cut() - //If not already queued for work and there are overlays to remove if(NOT_QUEUED_ALREADY && remove_overlays.len) QUEUE_FOR_COMPILE -/atom/proc/cut_overlay(list/overlays, priority) +/atom/proc/cut_overlay(list/overlays) if(!overlays) return overlays = build_appearance_list(overlays) LAZYINITLIST(add_overlays) //always initialized after this point - LAZYINITLIST(priority_overlays) LAZYINITLIST(remove_overlays) var/a_len = add_overlays.len var/r_len = remove_overlays.len - var/p_len = priority_overlays.len remove_overlays += overlays add_overlays -= overlays - - if(priority) - var/list/cached_priority = priority_overlays - LAZYREMOVE(cached_priority, overlays) - var/fa_len = add_overlays.len var/fr_len = remove_overlays.len - var/fp_len = priority_overlays.len //If not already queued and there is work to be done - if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len || fp_len != p_len)) + if(NOT_QUEUED_ALREADY && (fa_len != a_len || fr_len != r_len)) QUEUE_FOR_COMPILE -/atom/proc/add_overlay(list/overlays, priority = FALSE) +/atom/proc/add_overlay(list/overlays) if(!overlays) return overlays = build_appearance_list(overlays) LAZYINITLIST(add_overlays) //always initialized after this point - LAZYINITLIST(priority_overlays) var/a_len = add_overlays.len - var/p_len = priority_overlays.len - if(priority) - priority_overlays += overlays //or in the image. Can we use [image] = image? - var/fp_len = priority_overlays.len - if(NOT_QUEUED_ALREADY && fp_len != p_len) - QUEUE_FOR_COMPILE - else - add_overlays += overlays - var/fa_len = add_overlays.len - if(NOT_QUEUED_ALREADY && fa_len != a_len) - QUEUE_FOR_COMPILE + add_overlays += overlays + var/fa_len = add_overlays.len + if(NOT_QUEUED_ALREADY && fa_len != a_len) + QUEUE_FOR_COMPILE /atom/proc/copy_overlays(atom/other, cut_old) //copys our_overlays from another atom if(!other) diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index cd577e4ac6..5b60747725 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -268,6 +268,7 @@ SUBSYSTEM_DEF(persistence) SaveRandomizedRecipes() SavePanicBunker() SavePaintings() + SaveScars() /datum/controller/subsystem/persistence/proc/LoadPanicBunker() var/bunker_path = file("data/bunker_passthrough.json") @@ -547,3 +548,24 @@ SUBSYSTEM_DEF(persistence) var/json_file = file("data/paintings.json") fdel(json_file) WRITE_FILE(json_file, json_encode(paintings)) + +/datum/controller/subsystem/persistence/proc/SaveScars() + for(var/i in GLOB.joined_player_list) + var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i) + if(!istype(ending_human) || !ending_human.mind || !ending_human.client || !ending_human.client.prefs || !ending_human.client.prefs.persistent_scars) + continue + + var/mob/living/carbon/human/original_human = ending_human.mind.original_character + if(!original_human || original_human.stat == DEAD || !original_human.all_scars || !(original_human == ending_human)) + if(ending_human.client) // i was told if i don't check this every step of the way byond might decide a client ceases to exist mid proc so here we go + ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = "" + else + for(var/k in ending_human.all_wounds) + var/datum/wound/iter_wound = k + iter_wound.remove_wound() // so we can get the scars for open wounds + if(!ending_human.client) + return + ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars() + if(!ending_human.client) + return + ending_human.client.prefs.save_character() diff --git a/code/controllers/subsystem/processing/circuit.dm b/code/controllers/subsystem/processing/circuit.dm index 880e7a16a8..ac720a7fb4 100644 --- a/code/controllers/subsystem/processing/circuit.dm +++ b/code/controllers/subsystem/processing/circuit.dm @@ -50,20 +50,17 @@ PROCESSING_SUBSYSTEM_DEF(circuit) /obj/item/electronic_assembly/simple, /obj/item/electronic_assembly/hook, /obj/item/electronic_assembly/pda, - /obj/item/electronic_assembly/dildo, /obj/item/electronic_assembly/small/default, /obj/item/electronic_assembly/small/cylinder, /obj/item/electronic_assembly/small/scanner, /obj/item/electronic_assembly/small/hook, /obj/item/electronic_assembly/small/box, - /obj/item/electronic_assembly/small/dildo, /obj/item/electronic_assembly/medium/default, /obj/item/electronic_assembly/medium/box, /obj/item/electronic_assembly/medium/clam, /obj/item/electronic_assembly/medium/medical, /obj/item/electronic_assembly/medium/gun, /obj/item/electronic_assembly/medium/radio, - /obj/item/electronic_assembly/medium/dildo, /obj/item/electronic_assembly/large/default, /obj/item/electronic_assembly/large/scope, /obj/item/electronic_assembly/large/terminal, diff --git a/code/controllers/subsystem/processing/huds.dm b/code/controllers/subsystem/processing/huds.dm new file mode 100644 index 0000000000..aea23d2400 --- /dev/null +++ b/code/controllers/subsystem/processing/huds.dm @@ -0,0 +1,6 @@ +// Smooth HUD updates, but low priority +PROCESSING_SUBSYSTEM_DEF(huds) + name = "HUD updates" + wait = 0.5 + priority = FIRE_PRIORITY_HUDS + stat_tag = "HUDS" diff --git a/code/controllers/subsystem/processing/instruments.dm b/code/controllers/subsystem/processing/instruments.dm index a4e0d7703f..ee0fd1ea00 100644 --- a/code/controllers/subsystem/processing/instruments.dm +++ b/code/controllers/subsystem/processing/instruments.dm @@ -4,16 +4,26 @@ PROCESSING_SUBSYSTEM_DEF(instruments) init_order = INIT_ORDER_INSTRUMENTS flags = SS_KEEP_TIMING priority = FIRE_PRIORITY_INSTRUMENTS - var/static/list/datum/instrument/instrument_data = list() //id = datum + /// List of all instrument data, associative id = datum + var/static/list/datum/instrument/instrument_data = list() + /// List of all song datums. var/static/list/datum/song/songs = list() + /// Max lines in songs var/static/musician_maxlines = 600 + /// Max characters per line in songs var/static/musician_maxlinechars = 300 + /// Deciseconds between hearchecks. Too high and instruments seem to lag when people are moving around in terms of who can hear it. Too low and the server lags from this. var/static/musician_hearcheck_mindelay = 5 + /// Maximum instrument channels total instruments are allowed to use. This is so you don't have instruments deadlocking all sound channels. var/static/max_instrument_channels = MAX_INSTRUMENT_CHANNELS + /// Current number of channels allocated for instruments var/static/current_instrument_channels = 0 + /// Single cached list for synthesizer instrument ids, so you don't have to have a new list with every synthesizer. + var/static/list/synthesizer_instrument_ids /datum/controller/subsystem/processing/instruments/Initialize() initialize_instrument_data() + synthesizer_instrument_ids = get_allowed_instrument_ids() return ..() /datum/controller/subsystem/processing/instruments/proc/on_song_new(datum/song/S) @@ -29,7 +39,10 @@ PROCESSING_SUBSYSTEM_DEF(instruments) continue I = new path I.Initialize() - instrument_data[I.id || "[I.type]"] = I + if(!I.id) + qdel(I) + continue + instrument_data[I.id] = I CHECK_TICK /datum/controller/subsystem/processing/instruments/proc/get_instrument(id_or_path) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index 532eb19bc9..c802448536 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -7,10 +7,9 @@ SUBSYSTEM_DEF(shuttle) flags = SS_KEEP_TIMING|SS_NO_TICK_CHECK runlevels = RUNLEVEL_SETUP | RUNLEVEL_GAME - var/obj/machinery/shuttle_manipulator/manipulator - var/list/mobile = list() var/list/stationary = list() + var/list/beacons = list() var/list/transit = list() var/list/transit_requesters = list() @@ -57,6 +56,15 @@ SUBSYSTEM_DEF(shuttle) var/realtimeofstart = 0 + var/datum/map_template/shuttle/selected + + var/obj/docking_port/mobile/existing_shuttle + + var/obj/docking_port/mobile/preview_shuttle + var/datum/map_template/shuttle/preview_template + + var/datum/turf_reservation/preview_reservation + /datum/controller/subsystem/shuttle/Initialize(timeofday) ordernum = rand(1, 9000) @@ -76,13 +84,10 @@ SUBSYSTEM_DEF(shuttle) WARNING("No /obj/docking_port/mobile/emergency/backup placed on the map!") if(!supply) WARNING("No /obj/docking_port/mobile/supply placed on the map!") - realtimeofstart = world.realtime + realtimeofstart = world.realtime return ..() /datum/controller/subsystem/shuttle/proc/initial_load() - if(!istype(manipulator)) - CRASH("No shuttle manipulator found.") - for(var/s in stationary) var/obj/docking_port/stationary/S = s S.load_roundstart() @@ -143,11 +148,13 @@ SUBSYSTEM_DEF(shuttle) ++alive var/total = GLOB.joined_player_list.len + if(total <= 0) + return //no players no autoevac if(alive / total <= threshold) - var/msg = "Automatically dispatching shuttle due to crew death." + var/msg = "Automatically dispatching emergency shuttle due to crew death." message_admins(msg) - log_game("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]") + log_shuttle("[msg] Alive: [alive], Roundstart: [total], Threshold: [threshold]") emergencyNoRecall = TRUE priority_announce("Catastrophic casualties detected: crisis shuttle protocols activated - jamming recall signals across all frequencies.") if(emergency.timeLeft(1) > emergencyCallTime * 0.4) @@ -172,6 +179,34 @@ SUBSYSTEM_DEF(shuttle) return S WARNING("couldn't find dock with id: [id]") +/datum/controller/subsystem/shuttle/proc/canEvac(mob/user) + var/srd = CONFIG_GET(number/shuttle_refuel_delay) + if(world.time - SSticker.round_start_time < srd) + to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.") + return FALSE + + switch(emergency.mode) + if(SHUTTLE_RECALL) + to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") + return FALSE + if(SHUTTLE_CALL) + to_chat(user, "The emergency shuttle is already on its way.") + return FALSE + if(SHUTTLE_DOCKED) + to_chat(user, "The emergency shuttle is already here.") + return FALSE + if(SHUTTLE_IGNITING) + to_chat(user, "The emergency shuttle is firing its engines to leave.") + return FALSE + if(SHUTTLE_ESCAPE) + to_chat(user, "The emergency shuttle is moving away to a safe distance.") + return FALSE + if(SHUTTLE_STRANDED) + to_chat(user, "The emergency shuttle has been disabled by CentCom.") + return FALSE + + return TRUE + /datum/controller/subsystem/shuttle/proc/requestEvac(mob/user, call_reason) if(!emergency) WARNING("requestEvac(): There is no emergency shuttle, but the \ @@ -185,35 +220,14 @@ SUBSYSTEM_DEF(shuttle) manually, and then calling register() on the mobile docking port. \ Good luck.") emergency = backup_shuttle - var/srd = CONFIG_GET(number/shuttle_refuel_delay) - if(world.time - SSticker.round_start_time < srd) - to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.") - return - switch(emergency.mode) - if(SHUTTLE_RECALL) - to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") - return - if(SHUTTLE_CALL) - to_chat(user, "The emergency shuttle is already on its way.") - return - if(SHUTTLE_DOCKED) - to_chat(user, "The emergency shuttle is already here.") - return - if(SHUTTLE_IGNITING) - to_chat(user, "The emergency shuttle is firing its engines to leave.") - return - if(SHUTTLE_ESCAPE) - to_chat(user, "The emergency shuttle is moving away to a safe distance.") - return - if(SHUTTLE_STRANDED) - to_chat(user, "The emergency shuttle has been disabled by CentCom.") - return + if(!canEvac(user)) + return call_reason = trim(html_encode(call_reason)) if(length(call_reason) < CALL_SHUTTLE_REASON_LENGTH && GLOB.security_level > SEC_LEVEL_GREEN) - to_chat(user, "You must provide a reason.") + to_chat(user, "You must provide a reason.") return var/area/signal_origin = get_area(user) @@ -235,11 +249,11 @@ SUBSYSTEM_DEF(shuttle) var/area/A = get_area(user) - log_game("[key_name(user)] has called the shuttle.") - deadchat_broadcast("[user.real_name] has called the shuttle at [A.name].", user) + log_shuttle("[key_name(user)] has called the emergency shuttle.") + deadchat_broadcast(" has called the shuttle at [A.name].", "[user.real_name]", user) if(call_reason) SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]") - log_game("Shuttle call reason: [call_reason]") + log_shuttle("Shuttle call reason: [call_reason]") message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (TRIGGER CENTCOM RECALL)") /datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message) @@ -272,9 +286,9 @@ SUBSYSTEM_DEF(shuttle) /datum/controller/subsystem/shuttle/proc/cancelEvac(mob/user) if(canRecall()) emergency.cancel(get_area(user)) - log_game("[key_name(user)] has recalled the shuttle.") + log_shuttle("[key_name(user)] has recalled the shuttle.") message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.") - deadchat_broadcast("[user.real_name] has recalled the shuttle from [get_area_name(user, TRUE)].", user) + deadchat_broadcast(" has recalled the shuttle from [get_area_name(user, TRUE)].", "[user.real_name]", user) return 1 /datum/controller/subsystem/shuttle/proc/canRecall() @@ -294,7 +308,7 @@ SUBSYSTEM_DEF(shuttle) else if(emergency.timeLeft(1) < emergencyCallTime * 0.25) return - return 1 + return TRUE /datum/controller/subsystem/shuttle/proc/autoEvac() if (!SSticker.IsRoundInProgress()) @@ -322,7 +336,7 @@ SUBSYSTEM_DEF(shuttle) if(callShuttle) if(EMERGENCY_IDLE_OR_RECALLED) emergency.request(null, set_coefficient = 2.5) - log_game("There is no means of calling the shuttle anymore. Shuttle automatically called.") + log_shuttle("There is no means of calling the emergency shuttle anymore. Shuttle automatically called.") message_admins("All the communications consoles were destroyed and all AIs are inactive. Shuttle called.") /datum/controller/subsystem/shuttle/proc/registerHostileEnvironment(datum/bad) @@ -559,6 +573,14 @@ SUBSYSTEM_DEF(shuttle) shuttle_purchased = SSshuttle.shuttle_purchased lockdown = SSshuttle.lockdown + selected = SSshuttle.selected + + existing_shuttle = SSshuttle.existing_shuttle + + preview_shuttle = SSshuttle.preview_shuttle + preview_template = SSshuttle.preview_template + + preview_reservation = SSshuttle.preview_reservation /datum/controller/subsystem/shuttle/proc/is_in_shuttle_bounds(atom/A) var/area/current = get_area(A) @@ -641,3 +663,254 @@ SUBSYSTEM_DEF(shuttle) message_admins("Round end vote passed. Shuttle has been auto-called.") emergencyNoRecall = TRUE endvote_passed = TRUE + +/datum/controller/subsystem/shuttle/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port) + // Check for an existing preview + if(preview_shuttle && (loading_template != preview_template)) + preview_shuttle.jumpToNullSpace() + preview_shuttle = null + preview_template = null + QDEL_NULL(preview_reservation) + + if(!preview_shuttle) + if(load_template(loading_template)) + preview_shuttle.linkup(loading_template, destination_port) + preview_template = loading_template + + // get the existing shuttle information, if any + var/timer = 0 + var/mode = SHUTTLE_IDLE + var/obj/docking_port/stationary/D + + if(istype(destination_port)) + D = destination_port + else if(existing_shuttle) + timer = existing_shuttle.timer + mode = existing_shuttle.mode + D = existing_shuttle.get_docked() + + if(!D) + D = generate_transit_dock(preview_shuttle) + + if(!D) + CRASH("No dock found for preview shuttle ([preview_template.name]), aborting.") + + var/result = preview_shuttle.canDock(D) + // truthy value means that it cannot dock for some reason + // but we can ignore the someone else docked error because we'll + // be moving into their place shortly + if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED)) + WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).") + return + + if(existing_shuttle) + existing_shuttle.jumpToNullSpace() + + var/list/force_memory = preview_shuttle.movement_force + preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0) + preview_shuttle.initiate_docking(D) + preview_shuttle.movement_force = force_memory + + . = preview_shuttle + + // Shuttle state involves a mode and a timer based on world.time, so + // plugging the existing shuttles old values in works fine. + preview_shuttle.timer = timer + preview_shuttle.mode = mode + + preview_shuttle.register() + + // TODO indicate to the user that success happened, rather than just + // blanking the modification tab + preview_shuttle = null + preview_template = null + existing_shuttle = null + selected = null + QDEL_NULL(preview_reservation) + +/datum/controller/subsystem/shuttle/proc/load_template(datum/map_template/shuttle/S) + . = FALSE + // load shuttle template, centred at shuttle import landmark, + preview_reservation = SSmapping.RequestBlockReservation(S.width, S.height, SSmapping.transit.z_value, /datum/turf_reservation/transit) + if(!preview_reservation) + CRASH("failed to reserve an area for shuttle template loading") + var/turf/BL = TURF_FROM_COORDS_LIST(preview_reservation.bottom_left_coords) + S.load(BL, centered = FALSE, register = FALSE) + + var/affected = S.get_affected_turfs(BL, centered=FALSE) + + var/found = 0 + // Search the turfs for docking ports + // - We need to find the mobile docking port because that is the heart of + // the shuttle. + // - We need to check that no additional ports have slipped in from the + // template, because that causes unintended behaviour. + for(var/T in affected) + for(var/obj/docking_port/P in T) + if(istype(P, /obj/docking_port/mobile)) + found++ + if(found > 1) + qdel(P, force=TRUE) + log_world("Map warning: Shuttle Template [S.mappath] has multiple mobile docking ports.") + else + preview_shuttle = P + if(istype(P, /obj/docking_port/stationary)) + log_world("Map warning: Shuttle Template [S.mappath] has a stationary docking port.") + if(!found) + var/msg = "load_template(): Shuttle Template [S.mappath] has no mobile docking port. Aborting import." + for(var/T in affected) + var/turf/T0 = T + T0.empty() + + message_admins(msg) + WARNING(msg) + return + //Everything fine + S.post_load(preview_shuttle) + return TRUE + +/datum/controller/subsystem/shuttle/proc/unload_preview() + if(preview_shuttle) + preview_shuttle.jumpToNullSpace() + preview_shuttle = null + + +/datum/controller/subsystem/shuttle/ui_state(mob/user) + return GLOB.admin_state + +/datum/controller/subsystem/shuttle/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ShuttleManipulator") + ui.open() + +/datum/controller/subsystem/shuttle/ui_data(mob/user) + var/list/data = list() + data["tabs"] = list("Status", "Templates", "Modification") + + // Templates panel + data["templates"] = list() + var/list/templates = data["templates"] + data["templates_tabs"] = list() + data["selected"] = list() + + for(var/shuttle_id in SSmapping.shuttle_templates) + var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id] + + if(!templates[S.port_id]) + data["templates_tabs"] += S.port_id + templates[S.port_id] = list( + "port_id" = S.port_id, + "templates" = list()) + + var/list/L = list() + L["name"] = S.name + L["shuttle_id"] = S.shuttle_id + L["port_id"] = S.port_id + L["description"] = S.description + L["admin_notes"] = S.admin_notes + + if(selected == S) + data["selected"] = L + + templates[S.port_id]["templates"] += list(L) + + data["templates_tabs"] = sortList(data["templates_tabs"]) + + data["existing_shuttle"] = null + + // Status panel + data["shuttles"] = list() + for(var/i in mobile) + var/obj/docking_port/mobile/M = i + var/timeleft = M.timeLeft(1) + var/list/L = list() + L["name"] = M.name + L["id"] = M.id + L["timer"] = M.timer + L["timeleft"] = M.getTimerStr() + if (timeleft > 1 HOURS) + L["timeleft"] = "Infinity" + L["can_fast_travel"] = M.timer && timeleft >= 50 + L["can_fly"] = TRUE + if(istype(M, /obj/docking_port/mobile/emergency)) + L["can_fly"] = FALSE + else if(!M.destination) + L["can_fast_travel"] = FALSE + if (M.mode != SHUTTLE_IDLE) + L["mode"] = capitalize(M.mode) + L["status"] = M.getDbgStatusText() + if(M == existing_shuttle) + data["existing_shuttle"] = L + + data["shuttles"] += list(L) + + return data + +/datum/controller/subsystem/shuttle/ui_act(action, params) + if(..()) + return + + var/mob/user = usr + + // Preload some common parameters + var/shuttle_id = params["shuttle_id"] + var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id] + + switch(action) + if("select_template") + if(S) + existing_shuttle = getShuttle(S.port_id) + selected = S + . = TRUE + if("jump_to") + if(params["type"] == "mobile") + for(var/i in mobile) + var/obj/docking_port/mobile/M = i + if(M.id == params["id"]) + user.forceMove(get_turf(M)) + . = TRUE + break + + if("fly") + for(var/i in mobile) + var/obj/docking_port/mobile/M = i + if(M.id == params["id"]) + . = TRUE + M.admin_fly_shuttle(user) + break + + if("fast_travel") + for(var/i in mobile) + var/obj/docking_port/mobile/M = i + if(M.id == params["id"] && M.timer && M.timeLeft(1) >= 50) + M.setTimer(50) + . = TRUE + message_admins("[key_name_admin(usr)] fast travelled [M]") + log_admin("[key_name(usr)] fast travelled [M]") + SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[M.name]") + break + + if("preview") + if(S) + . = TRUE + unload_preview() + load_template(S) + if(preview_shuttle) + preview_template = S + user.forceMove(get_turf(preview_shuttle)) + if("load") + if(existing_shuttle == backup_shuttle) + // TODO make the load button disabled + WARNING("The shuttle that the selected shuttle will replace \ + is the backup shuttle. Backup shuttle is required to be \ + intact for round sanity.") + else if(S) + . = TRUE + // If successful, returns the mobile docking port + var/obj/docking_port/mobile/mdp = action_load(S) + if(mdp) + user.forceMove(get_turf(mdp)) + message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.") + log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.") + SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]") diff --git a/code/controllers/subsystem/tgui.dm b/code/controllers/subsystem/tgui.dm index dacbac409d..a5526d2c03 100644 --- a/code/controllers/subsystem/tgui.dm +++ b/code/controllers/subsystem/tgui.dm @@ -1,3 +1,12 @@ +/** + * tgui subsystem + * + * Contains all tgui state and subsystem code. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + SUBSYSTEM_DEF(tgui) name = "tgui" wait = 9 @@ -5,33 +14,338 @@ SUBSYSTEM_DEF(tgui) priority = FIRE_PRIORITY_TGUI runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT - var/list/currentrun = list() - var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key. - var/list/processing_uis = list() // A list of processing UIs, ungrouped. - var/basehtml // The HTML base used for all UIs. + /// A list of UIs scheduled to process + var/list/current_run = list() + /// A list of open UIs + var/list/open_uis = list() + /// A list of open UIs, grouped by src_object. + var/list/open_uis_by_src = list() + /// The HTML base used for all UIs. + var/basehtml /datum/controller/subsystem/tgui/PreInit() - basehtml = file2text('tgui-next/packages/tgui/public/tgui-main.html') + basehtml = file2text('tgui/packages/tgui/public/tgui.html') /datum/controller/subsystem/tgui/Shutdown() close_all_uis() /datum/controller/subsystem/tgui/stat_entry() - ..("P:[processing_uis.len]") + ..("P:[open_uis.len]") /datum/controller/subsystem/tgui/fire(resumed = 0) - if (!resumed) - src.currentrun = processing_uis.Copy() - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - - while(currentrun.len) - var/datum/tgui/ui = currentrun[currentrun.len] - currentrun.len-- + if(!resumed) + src.current_run = open_uis.Copy() + // Cache for sanic speed (lists are references anyways) + var/list/current_run = src.current_run + while(current_run.len) + var/datum/tgui/ui = current_run[current_run.len] + current_run.len-- + // TODO: Move user/src_object check to process() if(ui && ui.user && ui.src_object) ui.process() else - processing_uis.Remove(ui) - if (MC_TICK_CHECK) + open_uis.Remove(ui) + if(MC_TICK_CHECK) return +/** + * public + * + * Requests a usable tgui window from the pool. + * Returns null if pool was exhausted. + * + * required user mob + * return datum/tgui + */ +/datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user) + if(!user.client) + return null + var/list/windows = user.client.tgui_windows + var/window_id + var/datum/tgui_window/window + var/window_found = FALSE + // Find a usable window + for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT) + window_id = TGUI_WINDOW_ID(i) + window = windows[window_id] + // As we are looping, create missing window datums + if(!window) + window = new(user.client, window_id, pooled = TRUE) + // Skip windows with acquired locks + if(window.locked) + continue + if(window.status == TGUI_WINDOW_READY) + return window + if(window.status == TGUI_WINDOW_CLOSED) + window.status = TGUI_WINDOW_LOADING + window_found = TRUE + break + if(!window_found) + log_tgui(user, "Error: Pool exhausted") + return null + return window + +/** + * public + * + * Force closes all tgui windows. + * + * required user mob + */ +/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user) + log_tgui(user, "force_close_all_windows") + if(user.client) + user.client.tgui_windows = list() + for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT) + var/window_id = TGUI_WINDOW_ID(i) + user << browse(null, "window=[window_id]") + +/** + * public + * + * Force closes the tgui window by window_id. + * + * required user mob + * required window_id string + */ +/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id) + log_tgui(user, "force_close_window") + // Close all tgui datums based on window_id. + for(var/datum/tgui/ui in user.tgui_open_uis) + if(ui.window && ui.window.id == window_id) + ui.close(can_be_suspended = FALSE) + // Unset machine just to be sure. + user.unset_machine() + // Close window directly just to be sure. + user << browse(null, "window=[window_id]") + +/** + * public + * + * Try to find an instance of a UI, and push an update to it. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object/datum which owns the UI. + * optional ui datum/tgui The UI to be updated, if it exists. + * optional force_open bool If the UI should be re-opened instead of updated. + * + * return datum/tgui The found UI. + */ +/datum/controller/subsystem/tgui/proc/try_update_ui( + mob/user, + datum/src_object, + datum/tgui/ui) + // Look up a UI if it wasn't passed + if(isnull(ui)) + ui = get_open_ui(user, src_object) + // Couldn't find a UI. + if(isnull(ui)) + return null + ui.process_status() + // UI ended up with the closed status + // or is actively trying to close itself. + // FIXME: Doesn't actually fix the paper bug. + if(ui.status <= UI_CLOSE) + ui.close() + return null + ui.send_update() + return ui + +/** + * public + * + * Get a open UI given a user and src_object. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object/datum which owns the UI. + * + * return datum/tgui The found UI. + */ +/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object) + var/key = "[REF(src_object)]" + // No UIs opened for this src_object + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return null + for(var/datum/tgui/ui in open_uis_by_src[key]) + // Make sure we have the right user + if(ui.user == user) + return ui + return null + +/** + * public + * + * Update all UIs attached to src_object. + * + * required src_object datum The object/datum which owns the UIs. + * + * return int The number of UIs updated. + */ +/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object) + var/count = 0 + var/key = "[REF(src_object)]" + // No UIs opened for this src_object + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return count + for(var/datum/tgui/ui in open_uis_by_src[key]) + // Check if UI is valid. + if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) + ui.process(force = 1) + count++ + return count + +/** + * public + * + * Close all UIs attached to src_object. + * + * required src_object datum The object/datum which owns the UIs. + * + * return int The number of UIs closed. + */ +/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object) + var/count = 0 + var/key = "[REF(src_object)]" + // No UIs opened for this src_object + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return count + for(var/datum/tgui/ui in open_uis_by_src[key]) + // Check if UI is valid. + if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) + ui.close() + count++ + return count + +/** + * public + * + * Close all UIs regardless of their attachment to src_object. + * + * return int The number of UIs closed. + */ +/datum/controller/subsystem/tgui/proc/close_all_uis() + var/count = 0 + for(var/key in open_uis_by_src) + for(var/datum/tgui/ui in open_uis_by_src[key]) + // Check if UI is valid. + if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) + ui.close() + count++ + return count + +/** + * public + * + * Update all UIs belonging to a user. + * + * required user mob The mob who opened/is using the UI. + * optional src_object datum If provided, only update UIs belonging this src_object. + * + * return int The number of UIs updated. + */ +/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object) + var/count = 0 + if(length(user?.tgui_open_uis) == 0) + return count + for(var/datum/tgui/ui in user.tgui_open_uis) + if(isnull(src_object) || ui.src_object == src_object) + ui.process(force = 1) + count++ + return count + +/** + * public + * + * Close all UIs belonging to a user. + * + * required user mob The mob who opened/is using the UI. + * optional src_object datum If provided, only close UIs belonging this src_object. + * + * return int The number of UIs closed. + */ +/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object) + var/count = 0 + if(length(user?.tgui_open_uis) == 0) + return count + for(var/datum/tgui/ui in user.tgui_open_uis) + if(isnull(src_object) || ui.src_object == src_object) + ui.close() + count++ + return count + +/** + * private + * + * Add a UI to the list of open UIs. + * + * required ui datum/tgui The UI to be added. + */ +/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui) + var/key = "[REF(ui.src_object)]" + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + open_uis_by_src[key] = list() + ui.user.tgui_open_uis |= ui + var/list/uis = open_uis_by_src[key] + uis |= ui + open_uis |= ui + +/** + * private + * + * Remove a UI from the list of open UIs. + * + * required ui datum/tgui The UI to be removed. + * + * return bool If the UI was removed or not. + */ +/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui) + var/key = "[REF(ui.src_object)]" + if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list)) + return FALSE + // Remove it from the list of processing UIs. + open_uis.Remove(ui) + // If the user exists, remove it from them too. + if(ui.user) + ui.user.tgui_open_uis.Remove(ui) + var/list/uis = open_uis_by_src[key] + uis.Remove(ui) + if(length(uis) == 0) + open_uis_by_src.Remove(key) + return TRUE + +/** + * private + * + * Handle client logout, by closing all their UIs. + * + * required user mob The mob which logged out. + * + * return int The number of UIs closed. + */ +/datum/controller/subsystem/tgui/proc/on_logout(mob/user) + close_user_uis(user) + +/** + * private + * + * Handle clients switching mobs, by transferring their UIs. + * + * required user source The client's original mob. + * required user target The client's new mob. + * + * return bool If the UIs were transferred. + */ +/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target) + // The old mob had no open UIs. + if(length(source?.tgui_open_uis) == 0) + return FALSE + if(isnull(target.tgui_open_uis) || !istype(target.tgui_open_uis, /list)) + target.tgui_open_uis = list() + // Transfer all the UIs. + for(var/datum/tgui/ui in source.tgui_open_uis) + // Inform the UIs of their new owner. + ui.user = target + target.tgui_open_uis.Add(ui) + // Clear the old list. + source.tgui_open_uis.Cut() + return TRUE diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 8042631b7b..0bc4e6665a 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -409,7 +409,7 @@ SUBSYSTEM_DEF(ticker) var/mob/living = player.transfer_character() if(living) qdel(player) - living.notransform = TRUE + living.mob_transforming = TRUE if(living.client) if (living.client.prefs && living.client.prefs.auto_ooc) if (living.client.prefs.chat_toggles & CHAT_OOC) @@ -423,7 +423,7 @@ SUBSYSTEM_DEF(ticker) /datum/controller/subsystem/ticker/proc/release_characters(list/livings) for(var/I in livings) var/mob/living/L = I - L.notransform = FALSE + L.mob_transforming = FALSE /datum/controller/subsystem/ticker/proc/send_tip_of_the_round() var/m @@ -711,7 +711,8 @@ SUBSYSTEM_DEF(ticker) 'sound/roundend/yeehaw.ogg', 'sound/roundend/disappointed.ogg', 'sound/roundend/gondolabridge.ogg', - 'sound/roundend/haveabeautifultime.ogg'\ + 'sound/roundend/haveabeautifultime.ogg', + 'sound/roundend/CitadelStationHasSeenBetterDays.ogg'\ ) SEND_SOUND(world, sound(round_end_sound)) diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm index b19cf47693..bd843f959d 100644 --- a/code/controllers/subsystem/title.dm +++ b/code/controllers/subsystem/title.dm @@ -47,7 +47,7 @@ SUBSYSTEM_DEF(title) . = ..() if(.) switch(var_name) - if("icon") + if(NAMEOF(src, icon)) if(splash_turf) splash_turf.icon = icon @@ -66,4 +66,4 @@ SUBSYSTEM_DEF(title) icon = SStitle.icon splash_turf = SStitle.splash_turf file_path = SStitle.file_path - previous_icon = SStitle.previous_icon \ No newline at end of file + previous_icon = SStitle.previous_icon diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm index 87158f021e..f556f7dee7 100644 --- a/code/controllers/subsystem/traumas.dm +++ b/code/controllers/subsystem/traumas.dm @@ -79,7 +79,7 @@ SUBSYSTEM_DEF(traumas) /obj/item/pda/clown, /obj/item/grown/bananapeel)), "greytide" = typecacheof(list(/obj/item/clothing/under/color/grey, /obj/item/melee/baton/cattleprod, - /obj/item/twohanded/spear, /obj/item/clothing/mask/gas)), + /obj/item/spear, /obj/item/clothing/mask/gas)), "lizards" = typecacheof(list(/obj/item/toy/plush/lizardplushie, /obj/item/reagent_containers/food/snacks/kebab/tail, /obj/item/organ/tail/lizard, /obj/item/reagent_containers/food/drinks/bottle/lizardwine)), @@ -120,7 +120,7 @@ SUBSYSTEM_DEF(traumas) /obj/item/card/id/captains_spare, /obj/item/card/id/centcom, /obj/machinery/door/airlock/command)), "the supernatural" = typecacheof(list(/obj/structure/destructible/cult, /obj/item/tome, - /obj/item/melee/cultblade, /obj/item/twohanded/required/cult_bastard, /obj/item/restraints/legcuffs/bola/cult, + /obj/item/melee/cultblade, /obj/item/cult_bastard, /obj/item/restraints/legcuffs/bola/cult, /obj/item/clothing/suit/cultrobes, /obj/item/clothing/suit/space/hardsuit/cult, /obj/item/clothing/suit/hooded/cultrobes, /obj/item/clothing/head/hooded/cult_hoodie, /obj/effect/rune, /obj/item/stack/sheet/runed_metal, /obj/machinery/door/airlock/cult, /obj/singularity/narsie, @@ -151,7 +151,7 @@ SUBSYSTEM_DEF(traumas) "anime" = typecacheof(list(/obj/item/clothing/under/costume/schoolgirl, /obj/item/katana, /obj/item/reagent_containers/food/snacks/sashimi, /obj/item/reagent_containers/food/snacks/chawanmushi, /obj/item/reagent_containers/food/drinks/bottle/sake, /obj/item/throwing_star, /obj/item/clothing/head/kitty/genuine, /obj/item/clothing/suit/space/space_ninja, - /obj/item/clothing/mask/gas/space_ninja, /obj/item/clothing/shoes/space_ninja, /obj/item/clothing/gloves/space_ninja, /obj/item/twohanded/vibro_weapon, + /obj/item/clothing/mask/gas/space_ninja, /obj/item/clothing/shoes/space_ninja, /obj/item/clothing/gloves/space_ninja, /obj/item/vibro_weapon, /obj/item/nullrod/scythe/vibro, /obj/item/energy_katana, /obj/item/toy/katana, /obj/item/nullrod/claymore/katana, /obj/structure/window/paperframe, /obj/structure/mineral_door/paperframe)), "mimes" = typecacheof(list(/obj/item/pda/mime, /obj/item/clothing/under/rank/civilian/mime, /obj/item/clothing/mask/gas/mime, @@ -168,7 +168,7 @@ SUBSYSTEM_DEF(traumas) /obj/machinery/porta_turret/syndicate, /obj/structure/closet/syndicate, /obj/machinery/suit_storage_unit/syndicate, /obj/item/clothing/under/syndicate, /obj/item/folder/syndicate, /obj/item/documents/syndicate, /obj/item/clothing/glasses/phantomthief/syndicate, /obj/item/antag_spawner/nuke_ops, /obj/item/storage/box/syndicate, /obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow, - /obj/item/melee/transforming/energy/sword/saber, /obj/item/twohanded/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm, + /obj/item/melee/transforming/energy/sword/saber, /obj/item/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm, /obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate, /obj/item/cartridge/virus/frame, /obj/item/chameleon, /obj/item/storage/box/syndie_kit/cutouts, /obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/card/emag, /obj/item/storage/toolbox/syndicate, /obj/item/storage/book/bible/syndicate, /obj/item/encryptionkey/binary, /obj/item/encryptionkey/syndicate, /obj/item/aiModule/syndicate, /obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited, @@ -176,7 +176,7 @@ SUBSYSTEM_DEF(traumas) /obj/machinery/computer/pod/old/syndicate, /obj/machinery/vending/medical/syndicate_access, /obj/item/mmi/syndie, /obj/item/target/syndicate, /obj/machinery/vending/cigarette/syndicate, /obj/item/robot_module/syndicate, /obj/item/clothing/mask/gas/syndicate, /obj/machinery/power/singularity_beacon/syndicate, /obj/item/clothing/head/syndicatefake, /obj/item/radio/headset/syndicate, /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate, /obj/item/pda/syndicate, /obj/item/clothing/suit/armor/vest/capcarapace/syndicate, /obj/item/gun/ballistic/automatic/flechette, /obj/item/ammo_box/magazine/flechette, /obj/item/clothing/suit/toggle/lawyer/black/syndie, /obj/item/melee/transforming/energy/sword/cx/traitor, /obj/structure/sign/poster/contraband/syndicate_pistol, /obj/structure/sign/poster/contraband/syndicate_recruitment, /obj/item/bedsheet/syndie, /obj/item/borg/upgrade/syndicate, /obj/item/tank/jetpack/oxygen/harness, /obj/item/firing_pin/implant/pindicate, /obj/item/reagent_containers/glass/bottle/traitor, /obj/item/storage/belt/military, - /obj/item/twohanded/shockpaddles/syndicate, /obj/item/clothing/mask/cigarette/syndicate, /obj/item/toy/plush/nukeplushie)), + /obj/item/shockpaddles/syndicate, /obj/item/clothing/mask/cigarette/syndicate, /obj/item/toy/plush/nukeplushie)), "eye" = typecacheof(list(/obj/item/organ/eyes, /obj/item/reagent_containers/syringe)) ) diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm index 97a5ec2c2b..a93aff7d2b 100644 --- a/code/controllers/subsystem/vote.dm +++ b/code/controllers/subsystem/vote.dm @@ -15,6 +15,8 @@ SUBSYSTEM_DEF(vote) var/vote_system = PLURALITY_VOTING var/question = null var/list/choices = list() + /// List of choice = object for statclick objects for statpanel voting + var/list/choice_statclicks = list() var/list/scores = list() var/list/choice_descs = list() // optional descriptions var/list/voted = list() @@ -47,7 +49,33 @@ SUBSYSTEM_DEF(vote) client_popup.open(0) next_pop = world.time+VOTE_COOLDOWN - +/** + * Renders a statpanel. Directly uses statpanel/stat calls since this is called from base of mob/Stat(). + */ +/datum/controller/subsystem/vote/proc/render_statpanel(mob/M) + if(!mode) // check if vote is running + return + if(!statpanel("Status")) // don't bother if they're not focused on this panel + return + var/static/list/supported = list(PLURALITY_VOTING, APPROVAL_VOTING) + stat("Vote active!", "There is currently a vote running. Question: [question]") + if(!(vote_system in supported)) + stat("", "The current vote system is not supported by statpanel rendering. Please vote manually by opening the vote popup using the action button or chat link.") + return + stat("Time Left:", "[round(end_time - world.time)] seconds") + stat(null, null) + stat("Choices:", null) + stat(null, null) + for(var/i in 1 to choice_statclicks.len) + var/choice = choice_statclicks[i] + var/ivotedforthis = FALSE + switch(vote_system) + if(APPROVAL_VOTING) + ivotedforthis = voted[usr.ckey] && (i in voted[usr.ckey]) + if(PLURALITY_VOTING) + ivotedforthis = voted[usr.ckey] == i + stat(ivotedforthis? "\[X\]" : "\[ \]", choice_statclicks[choice]) + stat(null, null) /datum/controller/subsystem/vote/proc/reset() initiator = null @@ -59,9 +87,26 @@ SUBSYSTEM_DEF(vote) voted.Cut() voting.Cut() scores.Cut() + cleanup_statclicks() display_votes = initial(display_votes) //CIT CHANGE - obfuscated votes remove_action_buttons() +/datum/controller/subsystem/vote/proc/cleanup_statclicks() + for(var/choice in choice_statclicks) + qdel(choice_statclicks[choice]) + choice_statclicks = list() + +/obj/effect/statclick/vote + name = "ERROR" + var/choice + +/obj/effect/statclick/vote/Click() + SSvote.submit_vote(choice) + +/obj/effect/statclick/vote/New(loc, choice, name) + src.choice = choice + src.name = name + /datum/controller/subsystem/vote/proc/get_result() //get the highest number of votes var/greatest_votes = 0 @@ -536,6 +581,12 @@ SUBSYSTEM_DEF(vote) vp = CONFIG_GET(number/vote_period) to_chat(world, "\n[text]\nType vote or click here to place your votes.\nYou have [DisplayTimeText(vp)] to vote.") end_time = started_time+vp + // generate statclick list + cleanup_statclicks() + for(var/i in 1 to choices.len) + var/choice = choices[i] + choice_statclicks[choice] = new /obj/effect/statclick/vote(null, i, choice) + // for(var/c in GLOB.clients) SEND_SOUND(c, sound('sound/misc/server-ready.ogg')) var/client/C = c diff --git a/code/datums/action.dm b/code/datums/action.dm index 0033df09d7..fbf7487e4d 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -157,7 +157,7 @@ /datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button, force = FALSE) if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force)) - current_button.cut_overlays(TRUE) + current_button.cut_overlays() current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state)) current_button.button_icon_state = button_icon_state diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index 9c6bb2ebfd..15115b62c0 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -431,25 +431,31 @@ if(!owner) owner = M -/datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1) +/** + * Generates a list of all laws on this datum, including rendered HTML tags if required + * + * Arguments: + * * include_zeroth - Operator that controls if law 0 or law 666 is returned in the set + * * show_numbers - Operator that controls if law numbers are prepended to the returned laws + * * render_html - Operator controlling if HTML tags are rendered on the returned laws + */ +/datum/ai_laws/proc/get_law_list(include_zeroth = FALSE, show_numbers = TRUE, render_html = TRUE) var/list/data = list() - if (include_zeroth && devillaws && devillaws.len) - for(var/i in devillaws) - data += "[show_numbers ? "666:" : ""] [i]" + if (include_zeroth && devillaws) + for(var/law in devillaws) + data += "[show_numbers ? "666:" : ""] [render_html ? "[law]" : law]" if (include_zeroth && zeroth) - data += "[show_numbers ? "0:" : ""] [zeroth]" + data += "[show_numbers ? "0:" : ""] [render_html ? "[zeroth]" : zeroth]" for(var/law in hacked) if (length(law) > 0) - var/num = ionnum() - data += "[show_numbers ? "[num]:" : ""] [law]" + data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "[law]" : law]" for(var/law in ion) if (length(law) > 0) - var/num = ionnum() - data += "[show_numbers ? "[num]:" : ""] [law]" + data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "[law]" : law]" var/number = 1 for(var/law in inherent) @@ -459,6 +465,7 @@ for(var/law in supplied) if (length(law) > 0) - data += "[show_numbers ? "[number]:" : ""] [law]" + data += "[show_numbers ? "[number]:" : ""] [render_html ? "[law]" : law]" number++ return data + diff --git a/code/datums/armor.dm b/code/datums/armor.dm index 85915395f8..88170541c6 100644 --- a/code/datums/armor.dm +++ b/code/datums/armor.dm @@ -1,9 +1,9 @@ -#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]" +#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]" -/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0) +/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0) . = locate(ARMORID) if (!.) - . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic) + . = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound) /datum/armor datum_flags = DF_USE_TAG @@ -17,8 +17,9 @@ var/fire var/acid var/magic + var/wound -/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0) +/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0) src.melee = melee src.bullet = bullet src.laser = laser @@ -29,15 +30,16 @@ src.fire = fire src.acid = acid src.magic = magic + src.wound = wound tag = ARMORID -/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0) - return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic) +/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0) + return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound) /datum/armor/proc/modifyAllRatings(modifier = 0) - return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier) + return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier) -/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic) +/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound) return getArmor((isnull(melee) ? src.melee : melee),\ (isnull(bullet) ? src.bullet : bullet),\ (isnull(laser) ? src.laser : laser),\ @@ -47,19 +49,20 @@ (isnull(rad) ? src.rad : rad),\ (isnull(fire) ? src.fire : fire),\ (isnull(acid) ? src.acid : acid),\ - (isnull(magic) ? src.magic : magic)) + (isnull(magic) ? src.magic : magic),\ + (isnull(wound) ? src.wound : wound)) /datum/armor/proc/getRating(rating) return vars[rating] /datum/armor/proc/getList() - return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic) + return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic, "wound" = wound) /datum/armor/proc/attachArmor(datum/armor/AA) - return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic) + return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound) /datum/armor/proc/detachArmor(datum/armor/AA) - return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic) + return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound) /datum/armor/vv_edit_var(var_name, var_value) if (var_name == NAMEOF(src, tag)) diff --git a/code/datums/beepsky_fashion.dm b/code/datums/beepsky_fashion.dm new file mode 100644 index 0000000000..1156822c93 --- /dev/null +++ b/code/datums/beepsky_fashion.dm @@ -0,0 +1,221 @@ +//similar to dog_fashion, but for beepsky, who has far more refined fashion tastes +/datum/beepsky_fashion + var/name //not setting the name and desc makes them go to the default + var/desc + + var/icon_file = 'icons/mob/secbot_accessories.dmi' //we sell secbots and secbot accessories + var/obj_icon_state + var/obj_alpha + var/obj_color + + var/list/stun_sounds //sound that replaces the stun attack when set + var/ignore_sound = FALSE //whether to ignore sounds entirely or not + + //emotes (don't set them if you want the default value) + var/death_emote //what is said when beepsky dies + var/capture_one //what is said when cuffing someone + var/capture_two //what is said when cuffing someone, directly to the person being cuffed + var/infraction //the level of threat detected + var/taunt // beepsky pointing at a criminal + var/attack_one //text when attacking criminal + var/attack_two //text when attacking criminal, but directly to the criminal + var/patrol_emote //engaging patrol text + var/patrol_fail_emote //failing to engage patrol text + var/list/arrest_texts //first is for not-cuffing, second is for cuffing + var/arrest_emote //text stating that you're cuffing some criminal C with a threat of level X in location Y + + //for reference, the following words are replaced when processed before speech: + //LOCATION = the location passed, if any (this is only used by arrest_emote) + //CRIMINAL = the name of the criminal (this is used by everything but patrol_emote and infraction) + //BOT = the name of the bot (this can be used on any of the emotes) + //THREAT_LEVEL = the level of the threat detected (can be used on arrest_emote and infraction) + +/datum/beepsky_fashion/proc/get_overlay(var/dir) + if(icon_file && obj_icon_state) + var/image/beepsky_overlay = image(icon_file, obj_icon_state, dir = dir) + beepsky_overlay.alpha = obj_alpha + beepsky_overlay.color = obj_color + return beepsky_overlay + +/datum/beepsky_fashion/proc/stun_attack(mob/living/carbon/C) //fired when beepsky does a stun attack with the fashion worn, for sounds/overlays/etc + return + +//actual fashions from here on out +/datum/beepsky_fashion/wizard + obj_icon_state = "wizard" + name = "Archmage Beepsky" + desc = "A secbot stolen from the wizard federation." + death_emote = "BOT casts EI NATH on themselves!" + capture_one = "BOT is casting cable ties on CRIMINAL!" + capture_two = "BOT is casting cable ties on you!" + infraction = "Magical disturbance of magnitude THREAT_LEVEL detected!" + taunt = "BOT points his staff towards CRIMINAL!" + attack_one = "BOT casts magic missile on CRIMINAL!" + attack_two = "BOT casts magic missile on you!" + patrol_emote = "Beginning search for magical disturbances." + patrol_fail_emote = "Failure to find magical disturbances. Recallibrating." + arrest_emote = "ARREST_TYPE level THREAT_LEVEL magical practitioner CRIMINAL in LOCATION." + stun_sounds = list('sound/magic/lightningbolt.ogg', + 'sound/magic/fireball.ogg', + 'sound/weapons/zapbang.ogg', + 'sound/magic/knock.ogg', + 'sound/magic/fleshtostone.ogg', + 'sound/effects/magic.ogg', + 'sound/magic/disintegrate.ogg') + +/datum/beepsky_fashion/cowboy + obj_icon_state = "cowboy" + name = "Sheriff Beepsky" + desc = "The sheriff of this here station." + capture_one = "BOT is tying CRIMINAL up!" + capture_two = "BOT is tying you up!" + infraction = "Outlaws with a bounty of THREAT_LEVEL000 space dollars detected!" + taunt = "BOT aims his revolver towards CRIMINAL!" + attack_one = "BOT unloads his revolver onto CRIMINAL!" + attack_two = "BOT unloads his revolver onto you!" + patrol_emote = "Engaging bounty hunting protocols." + patrol_fail_emote = "Unable to find any bounties due to error. Rebooting." + arrest_emote = "ARREST_TYPE outlaw CRIMINAL with a bounty of THREAT_LEVEL000 in LOCATION." + stun_sounds = list('sound/weapons/Gunshot.ogg', + 'sound/weapons/Gunshot2.ogg', + 'sound/weapons/Gunshot3.ogg', + 'sound/weapons/Gunshot4.ogg') + +/datum/beepsky_fashion/chef + obj_icon_state = "chef" + name = "Chef Beepsky" + desc = "Cooking up the finest foods the station has ever seen." + death_emote = "Mamma-mia!" + infraction = "Grade THREAT_LEVEL prosciutto detected!" + taunt = "BOT glares at CRIMINAL." + attack_one = "BOT CQCs CRIMINAL!" + attack_two = "BOT CQCs you!" + patrol_emote = "Beginning search for the bad prosciutto." + patrol_fail_emote = "All prosciutto is stale. Rebooting." + arrest_texts = list("Frying", "Grilling") //any good secoff knows the difference + arrest_emote = "ARREST_TYPE grade THREAT_LEVEL prosciutto CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/cqchit1.ogg', + 'sound/weapons/cqchit2.ogg') + +/datum/beepsky_fashion/cat + obj_icon_state = "cat" + name = "OwOfficer Bweepskwee" + desc = "A beepsky unit with cat ears. Catgirl science has gone too far." + death_emote = "Nya!" + capture_one = "BOT is tying CRIMINAL up!!" + capture_two = "BOT is tying you up!" + infraction = "Wevel THREAT_LEVEL infwactwion awert!!!" + taunt = "BOT points at CRIMINAL and nyas!" + attack_one = "BOT shoves CRIMINAL onto a table!" + attack_two = "BOT shoves you onto a table!" + patrol_emote = "Enwgagwing patwol mwodies.." + patrol_fail_emote = "Unawbwle two stwawt patwollies. Nya." + arrest_texts = list("Dwetwaining", "Awwesting") + arrest_emote = "ARREST_TYPE wevel THREAT_LEVEL scwumbwag CRIMINAL in LOCATION. Nya." + ignore_sound = TRUE //we instead make the stunned person fire the nya emote + +/datum/beepsky_fashion/cat/stun_attack(var/mob/living/carbon/C) //makes a fake table under you on hit, makes cat people nya when hit + if(iscatperson(C)) + C.emote("nya") + var/turf/target_turf = get_turf(C) + if(target_turf) //slams you on a fake table + playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, 1) + var/obj/effect/overlay_holder = new(target_turf) + overlay_holder.name = "Catboy Table" + overlay_holder.desc = "Where bad catboys go." + var/image/table_overlay = image('icons/obj/smooth_structures/table.dmi', "table") + overlay_holder.add_overlay(table_overlay) + QDEL_IN(overlay_holder, 10) + +/datum/beepsky_fashion/cake //nothing else. it's just beepsky. with a cake on his head. + obj_icon_state = "cake" + name = "Cakesky" + desc = "It's a secbot, wearing a cake on his head!" + +/datum/beepsky_fashion/captain + obj_icon_state = "captain" + name = "Captainsky" + desc = "The real captain of this station." + capture_one = "BOT is lecturing CRIMINAL on why he is the captain!" + capture_two = "BOT is lecturing you on why he is the captain!" + infraction = "Level THREAT_LEVEL greytider detected." + attack_one = "BOT beats CRIMINAL with the chain of command!" + attack_two = "BOT beats you with the chain of command!" + patrol_emote = "Uselessness protocols engaged." + patrol_fail_emote = "Unit has been found as useless. Rebooting." + arrest_texts = list("Demoting", "Firing") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL lesser crewmember CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/chainhit.ogg') + +/datum/beepsky_fashion/king + obj_icon_state = "king" + name = "King Beepsky" + desc = "He who has ascended to bare the right of king, sits atop the throne." + capture_one = "BOT is calling the guards onto CRIMINAL!" + capture_two = "BOT is calling the guards onto you!" + infraction = "Treason of level THREAT_LEVEL detected!" + attack_one = "BOT strikes CRIMINAL with his kingly authority!" + attack_two = "BOT strikes you with his kingly authority!" + patrol_emote = "Searching for peasants to beat up." + patrol_fail_emote = "Peasants are using dark magic. Recallibrating." + arrest_texts = list("Knighting", "Executing") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL peasant CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/punch1.ogg', + 'sound/weapons/punch2.ogg', + 'sound/weapons/punch3.ogg', + 'sound/weapons/punch4.ogg') + +/datum/beepsky_fashion/pirate + obj_icon_state = "pirate" + name = "Beepsbeard the Pirate" + desc = "Sailor of the seven seas, all sea-faring bots fear the one known as Beepsbeard." + capture_one = "BOT is making CRIMINAL walk the plank!" + capture_two = "BOT is making you walk the plank!" + infraction = "Enemy vessel spotted with threat level THREAT_LEVEL!" + attack_one = "BOT strikes CRIMINAL with his cutlass!" + attack_two = "BOT strikes you with his cutlass!" + patrol_emote = "Searching for enemy vessels to board." + patrol_fail_emote = "No way to engage enemy vessels. Rebooting." + arrest_texts = list("Boarding", "Sinking") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL vessel CRIMINAL in LOCATION." + stun_sounds = list('sound/weapons/bladeslice.ogg') + +/datum/beepsky_fashion/engineer + obj_icon_state = "engineer" + name = "Chief Engineer Beepsky" + desc = "He fixes criminals with a wrench to the face." + capture_one = "BOT is tying CRIMINAL up!" + capture_two = "BOT is tying you up!" + infraction = "Structural integrity issue spotted with threat level THREAT_LEVEL" + attack_one = "BOT strikes CRIMINAL with his wrench!" + attack_two = "BOT strikes you with his wrench!" + arrest_texts = list("Fixing", "Repairing") + arrest_emote = "ARREST_TYPE level THREAT_LEVEL structural issue in LOCATION" + stun_sounds = list('sound/weapons/genhit.ogg') + +/datum/beepsky_fashion/tophat + obj_icon_state = "tophat" + name = "Fancy Beepsky" + desc = "It's a secbot, wearing a top hat! How fancy." + +/datum/beepsky_fashion/fedora + obj_icon_state = "fedora" + name = "Fedorasky" + desc = "It's a secbot, wearing a fedora!" + +/datum/beepsky_fashion/sombrero + obj_icon_state = "sombrero" + name = "Sombrerosky" + desc = "A secbot wearing a sombrero. Truly, a hombre to all." + +/datum/beepsky_fashion/santa + obj_icon_state = "santa" + name = "Saint Beepsky" + desc = "Have you been a level 7 infraction this holiday season?" + capture_one = "BOT is tying CRIMINAL up with fairy lights!" + capture_two = "BOT is tying you up with fairy lights!" + infraction = "Level THREAT_LEVEL threat to holiday cheer spotted!" + attack_one = "BOT crushes CRIMINAL with their holiday spirit!" + attack_two = "BOT crushes you with their holiday spirit!" + arrest_emote = "ARREST_TYPE level THREAT_LEVEL threat to holiday cheer in LOCATION" + diff --git a/code/datums/brain_damage/magic.dm b/code/datums/brain_damage/magic.dm index 249907a1b8..a00b341b82 100644 --- a/code/datums/brain_damage/magic.dm +++ b/code/datums/brain_damage/magic.dm @@ -5,6 +5,61 @@ /datum/brain_trauma/magic resilience = TRAUMA_RESILIENCE_LOBOTOMY +/datum/brain_trauma/magic/lumiphobia + name = "Lumiphobia" + desc = "Patient has an inexplicable adverse reaction to light." + scan_desc = "light hypersensitivity" + gain_text = "You feel a craving for darkness." + lose_text = "Light no longer bothers you." + var/next_damage_warning = 0 + +/datum/brain_trauma/magic/lumiphobia/on_life() + ..() + var/turf/T = owner.loc + if(istype(T)) + var/light_amount = T.get_lumcount() + if(light_amount > SHADOW_SPECIES_LIGHT_THRESHOLD) //if there's enough light, start dying + if(world.time > next_damage_warning) + to_chat(owner, "The light burns you!") + next_damage_warning = world.time + 100 //Avoid spamming + owner.take_overall_damage(0,3) + +/datum/brain_trauma/magic/poltergeist + name = "Poltergeist" + desc = "Patient appears to be targeted by a violent invisible entity." + scan_desc = "paranormal activity" + gain_text = "You feel a hateful presence close to you." + lose_text = "You feel the hateful presence fade away." + +/datum/brain_trauma/magic/poltergeist/on_life() + ..() + if(prob(4)) + var/most_violent = -1 //So it can pick up items with 0 throwforce if there's nothing else + var/obj/item/throwing + for(var/obj/item/I in view(5, get_turf(owner))) + if(I.anchored) + continue + if(I.throwforce > most_violent) + most_violent = I.throwforce + throwing = I + if(throwing) + throwing.throw_at(owner, 8, 2) + +/datum/brain_trauma/magic/antimagic + name = "Athaumasia" + desc = "Patient is completely inert to magical forces." + scan_desc = "thaumic blank" + gain_text = "You realize that magic cannot be real." + lose_text = "You realize that magic might be real." + +/datum/brain_trauma/magic/antimagic/on_gain() + ADD_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT) + ..() + +/datum/brain_trauma/magic/antimagic/on_lose() + REMOVE_TRAIT(owner, TRAIT_ANTIMAGIC, TRAUMA_TRAIT) + ..() + /datum/brain_trauma/magic/stalker name = "Stalking Phantom" desc = "Patient is stalked by a phantom only they can see." @@ -39,7 +94,7 @@ if(get_dist(owner, stalker) <= 1) playsound(owner, 'sound/magic/demon_attack1.ogg', 50) owner.visible_message("[owner] is torn apart by invisible claws!", "Ghostly claws tear your body apart!") - owner.take_bodypart_damage(rand(20, 45)) + owner.take_bodypart_damage(rand(20, 45), wound_bonus=CANT_WOUND) else if(prob(50)) stalker.forceMove(get_step_towards(stalker, owner)) if(get_dist(owner, stalker) <= 8) diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm index cd8612fd19..3ba00d305b 100644 --- a/code/datums/brain_damage/severe.dm +++ b/code/datums/brain_damage/severe.dm @@ -119,8 +119,9 @@ /datum/brain_trauma/severe/paralysis/spinesnapped random_gain = FALSE + clonable = FALSE paralysis_type = "legs" - resilience = TRAUMA_RESILIENCE_LOBOTOMY + resilience = TRAUMA_RESILIENCE_LOBOTOMY // It shouldn't fix severed spinal cords really, but there is no specific surgery for that yet. /datum/brain_trauma/severe/narcolepsy name = "Narcolepsy" diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm index bc1f566f23..7cc5348a0a 100644 --- a/code/datums/brain_damage/special.dm +++ b/code/datums/brain_damage/special.dm @@ -103,8 +103,7 @@ . = ..() QDEL_IN(src, 300) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/hallucination/simple/bluespace_stream/attack_hand(mob/user) +/obj/effect/hallucination/simple/bluespace_stream/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user != seer || !linked_to) return var/slip_in_message = pick("slides sideways in an odd way, and disappears", "jumps into an unseen dimension",\ diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm index f5e00208c5..6b84e1362d 100644 --- a/code/datums/brain_damage/split_personality.dm +++ b/code/datums/brain_damage/split_personality.dm @@ -123,7 +123,9 @@ trauma = _trauma return ..() -/mob/living/split_personality/Life() +/mob/living/split_personality/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(QDELETED(body)) qdel(src) //in case trauma deletion doesn't already do it @@ -132,8 +134,6 @@ trauma.switch_personalities() qdel(trauma) - ..() - /mob/living/split_personality/Login() ..() to_chat(src, "As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.") diff --git a/code/datums/browser.dm b/code/datums/browser.dm index 5b1df6cb68..96b2a2a294 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -97,20 +97,20 @@ [get_footer()] "} -/datum/browser/proc/open(use_onclose = 1) +/datum/browser/proc/open(use_onclose = TRUE) if(isnull(window_id)) //null check because this can potentially nuke goonchat WARNING("Browser [title] tried to open with a null ID") to_chat(user, "The [title] browser you tried to open failed a sanity check! Please report this on github!") return var/window_size = "" - if (width && height) + if(width && height) window_size = "size=[width]x[height];" - if (stylesheets.len) - send_asset_list(user, stylesheets, verify=FALSE) - if (scripts.len) - send_asset_list(user, scripts, verify=FALSE) + if(stylesheets.len) + send_asset_list(user, stylesheets) + if(scripts.len) + send_asset_list(user, scripts) user << browse(get_content(), "window=[window_id];[window_size][window_options]") - if (use_onclose) + if(use_onclose) setup_onclose() /datum/browser/proc/setup_onclose() @@ -157,7 +157,7 @@ close() //designed as a drop in replacement for alert(); functions the same. (outside of needing User specified) -/proc/tgalert(var/mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) +/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1, Timeout = 6000) if (!User) User = usr switch(askuser(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)) diff --git a/code/datums/cinematic.dm b/code/datums/cinematic.dm index e229b25258..df2c15e9c8 100644 --- a/code/datums/cinematic.dm +++ b/code/datums/cinematic.dm @@ -30,7 +30,7 @@ GLOBAL_LIST_EMPTY(cinematics) /datum/cinematic var/id = CINEMATIC_DEFAULT var/list/watching = list() //List of clients watching this - var/list/locked = list() //Who had notransform set during the cinematic + var/list/locked = list() //Who had mob_transforming set during the cinematic var/is_global = FALSE //Global cinematics will override mob-specific ones var/obj/screen/cinematic/screen var/datum/callback/special_callback //For special effects synced with animation (explosions after the countdown etc) @@ -45,7 +45,7 @@ GLOBAL_LIST_EMPTY(cinematics) GLOB.cinematics -= src QDEL_NULL(screen) for(var/mob/M in locked) - M.notransform = FALSE + M.mob_transforming = FALSE return ..() /datum/cinematic/proc/play(watchers) @@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(cinematics) for(var/mob/M in GLOB.mob_list) if(M in watchers) - M.notransform = TRUE //Should this be done for non-global cinematics or even at all ? + M.mob_transforming = TRUE //Should this be done for non-global cinematics or even at all ? locked += M //Close watcher ui's SStgui.close_user_uis(M) @@ -79,7 +79,7 @@ GLOBAL_LIST_EMPTY(cinematics) M.client.screen += screen else if(is_global) - M.notransform = TRUE + M.mob_transforming = TRUE locked += M //Actually play it @@ -254,4 +254,4 @@ Nuke.Explosion() Narsie() -> Cinematic(CULT,world) -*/ \ No newline at end of file +*/ diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 441a161428..4f56f58d23 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -2,7 +2,7 @@ var/speed = 80 //time in deciseconds taken to butcher something var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops var/bonus_modifier = 0 //percentage increase to bonus item chance - var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering + var/butcher_sound = 'sound/effects/butcher.ogg' //sound played when butchering var/butchering_enabled = TRUE var/can_be_blunt = FALSE @@ -64,8 +64,11 @@ H.visible_message("[user] slits [H]'s throat!", \ "[user] slits your throat...") log_combat(user, H, "finishes slicing the throat of") - H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD) - H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30) + H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) // easy tiger, we'll get to that in a sec + var/obj/item/bodypart/slit_throat = H.get_bodypart(BODY_ZONE_HEAD) + if(slit_throat) + var/datum/wound/slash/critical/screaming_through_a_slit_throat = new + screaming_through_a_slit_throat.apply_wound(slit_throat) H.apply_status_effect(/datum/status_effect/neck_slice) /datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat) diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm index 863d55ccab..d138cf1971 100644 --- a/code/datums/components/caltrop.dm +++ b/code/datums/components/caltrop.dm @@ -48,7 +48,7 @@ var/damage = rand(min_damage, max_damage) if(HAS_TRAIT(H, TRAIT_LIGHT_STEP)) damage *= 0.75 - H.apply_damage(damage, BRUTE, picked_def_zone) + H.apply_damage(damage, BRUTE, picked_def_zone, wound_bonus = CANT_WOUND) if(cooldown < world.time - 10) //cooldown to avoid message spam. if(!H.incapacitated(ignore_restraints = TRUE)) diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm index c792cb4be9..0bb6c4a0af 100644 --- a/code/datums/components/chasm.dm +++ b/code/datums/components/chasm.dm @@ -109,7 +109,7 @@ AM.visible_message("[AM] falls into [parent]!", "[oblivion_message]") if (isliving(AM)) var/mob/living/L = AM - L.notransform = TRUE + L.mob_transforming = TRUE L.Paralyze(200) var/oldtransform = AM.transform diff --git a/code/datums/components/crafting/crafting.dm b/code/datums/components/crafting/crafting.dm new file mode 100644 index 0000000000..1a9f4c0512 --- /dev/null +++ b/code/datums/components/crafting/crafting.dm @@ -0,0 +1,461 @@ +/datum/component/personal_crafting/Initialize() + if(ismob(parent)) + RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button) + +/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL) + var/datum/hud/H = user.hud_used + var/obj/screen/craft/C = new() + C.icon = H.ui_style + H.static_inventory += C + CL.screen += C + RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact) + +/datum/component/personal_crafting + var/busy + var/viewing_category = 1 //typical powergamer starting on the Weapons tab + var/viewing_subcategory = 1 + var/list/categories = list( + CAT_WEAPONRY = list( + CAT_WEAPON, + CAT_AMMO, + ), + CAT_ROBOT = CAT_NONE, + CAT_MISC = list( + CAT_MISCELLANEOUS, + CAT_TOOL, + CAT_FURNITURE, + ), + CAT_PRIMAL = CAT_NONE, + CAT_FOOD = list( + CAT_BREAD, + CAT_BURGER, + CAT_CAKE, + CAT_DONUT, + CAT_EGG, + CAT_ICE, + CAT_MEAT, + CAT_MEXICAN, + CAT_MISCFOOD, + CAT_PASTRY, + CAT_PIE, + CAT_PIZZA, + CAT_SEAFOOD, + CAT_SALAD, + CAT_SANDWICH, + CAT_SOUP, + CAT_SPAGHETTI, + ), + CAT_DRINK = CAT_NONE, + CAT_CLOTHING = CAT_NONE, + ) + + var/cur_category = CAT_NONE + var/cur_subcategory = CAT_NONE + var/datum/action/innate/crafting/button + var/display_craftable_only = FALSE + var/display_compact = TRUE + +/* This is what procs do: + get_environment - gets a list of things accessable for crafting by user + get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list + check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff + check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep + construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs + del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list +*/ + +/** + * Check that the contents of the recipe meet the requirements. + * + * user: The /mob that initated the crafting. + * R: The /datum/crafting_recipe being attempted. + * contents: List of items to search for R's reqs. + */ +/datum/component/personal_crafting/proc/check_contents(atom/a, datum/crafting_recipe/R, list/contents) + var/list/item_instances = contents["instances"] + contents = contents["other"] + + var/list/requirements_list = list() + + // Process all requirements + for(var/requirement_path in R.reqs) + // Check we have the appropriate amount available in the contents list + var/needed_amount = R.reqs[requirement_path] + for(var/content_item_path in contents) + // Right path and not blacklisted + if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(content_item_path)) + continue + + needed_amount -= contents[content_item_path] + if(needed_amount <= 0) + break + + if(needed_amount > 0) + return FALSE + + // Store the instances of what we will use for R.check_requirements() for requirement_path + var/list/instances_list = list() + for(var/instance_path in item_instances) + if(ispath(instance_path, requirement_path)) + instances_list += item_instances[instance_path] + + requirements_list[requirement_path] = instances_list + + for(var/requirement_path in R.chem_catalysts) + if(contents[requirement_path] < R.chem_catalysts[requirement_path]) + return FALSE + + return R.check_requirements(a, requirements_list) + +/datum/component/personal_crafting/proc/get_environment(atom/a, list/blacklist = null, radius_range = 1) + . = list() + + if(!isturf(a.loc)) + return + + for(var/atom/movable/AM in range(radius_range, a)) + if(AM.flags_1 & HOLOGRAM_1) + continue + . += AM + +/datum/component/personal_crafting/proc/get_surroundings(atom/a) + . = list() + .["tool_behaviour"] = list() + .["other"] = list() + .["instances"] = list() + for(var/obj/item/I in get_environment(a)) + if(I.flags_1 & HOLOGRAM_1) + continue + if(.["instances"][I.type]) + .["instances"][I.type] += I + else + .["instances"][I.type] = list(I) + if(istype(I, /obj/item/stack)) + var/obj/item/stack/S = I + .["other"][I.type] += S.amount + else if(I.tool_behaviour) + .["tool_behaviour"] += I.tool_behaviour + .["other"][I.type] += 1 + else + if(istype(I, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/RC = I + if(RC.is_drainable()) + for(var/datum/reagent/A in RC.reagents.reagent_list) + .["other"][A.type] += A.volume + .["other"][I.type] += 1 + +/datum/component/personal_crafting/proc/check_tools(atom/a, datum/crafting_recipe/R, list/contents) + if(!R.tools.len) + return TRUE + var/list/possible_tools = list() + var/list/present_qualities = list() + present_qualities |= contents["tool_behaviour"] + for(var/obj/item/I in a.contents) + if(istype(I, /obj/item/storage)) + for(var/obj/item/SI in I.contents) + possible_tools += SI.type + if(SI.tool_behaviour) + present_qualities.Add(SI.tool_behaviour) + + possible_tools += I.type + + if(I.tool_behaviour) + present_qualities.Add(I.tool_behaviour) + + possible_tools |= contents["other"] + + main_loop: + for(var/A in R.tools) + if(A in present_qualities) + continue + else + for(var/I in possible_tools) + if(ispath(I, A)) + continue main_loop + return FALSE + return TRUE + +/datum/component/personal_crafting/proc/construct_item(atom/a, datum/crafting_recipe/R) + var/list/contents = get_surroundings(a) + var/send_feedback = 1 + if(check_contents(a, R, contents)) + if(check_tools(a, R, contents)) + //If we're a mob we'll try a do_after; non mobs will instead instantly construct the item + if(ismob(a) && !do_after(a, R.time, target = a)) + return "." + contents = get_surroundings(a) + if(!check_contents(a, R, contents)) + return ", missing component." + if(!check_tools(a, R, contents)) + return ", missing tool." + var/list/parts = del_reqs(R, a) + var/atom/movable/I = new R.result (get_turf(a.loc)) + I.CheckParts(parts, R) + if(send_feedback) + SSblackbox.record_feedback("tally", "object_crafted", 1, I.type) + return I //Send the item back to whatever called this proc so it can handle whatever it wants to do with the new item + return ", missing tool." + return ", missing component." + +/*Del reqs works like this: + + Loop over reqs var of the recipe + Set var amt to the value current cycle req is pointing to, its amount of type we need to delete + Get var/surroundings list of things accessable to crafting by get_environment() + Check the type of the current cycle req + If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isn't remove thing from surroundings + If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list + If there isn't enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching + While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one + If its stack check if it has enough amount + If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack + If no put all of the stack in the deletion list, substract its amount from amt and keep searching + While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one + If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop + + Then do a loop over parts var of the recipe + Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return + + After its done loop over deletion list and delete all the shit that wasn't taken by parts loop + + del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already +*/ + +/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, atom/a) + var/list/surroundings + var/list/Deletion = list() + . = list() + var/data + var/amt + main_loop: + for(var/A in R.reqs) + amt = R.reqs[A] + surroundings = get_environment(a, R.blacklist) + surroundings -= Deletion + if(ispath(A, /datum/reagent)) + var/datum/reagent/RG = new A + var/datum/reagent/RGNT + while(amt > 0) + var/obj/item/reagent_containers/RC = locate() in surroundings + RG = RC.reagents.get_reagent(A) + if(RG) + if(!locate(RG.type) in Deletion) + Deletion += new RG.type() + if(RG.volume > amt) + RG.volume -= amt + data = RG.data + RC.reagents.conditional_update(RC) + RG = locate(RG.type) in Deletion + RG.volume = amt + RG.data += data + continue main_loop + else + surroundings -= RC + amt -= RG.volume + RC.reagents.reagent_list -= RG + RC.reagents.conditional_update(RC) + RGNT = locate(RG.type) in Deletion + RGNT.volume += RG.volume + RGNT.data += RG.data + qdel(RG) + RC.on_reagent_change() + else + surroundings -= RC + else if(ispath(A, /obj/item/stack)) + var/obj/item/stack/S + var/obj/item/stack/SD + while(amt > 0) + S = locate(A) in surroundings + if(S.amount >= amt) + if(!locate(S.type) in Deletion) + SD = new S.type() + Deletion += SD + S.use(amt) + SD = locate(S.type) in Deletion + SD.amount += amt + continue main_loop + else + amt -= S.amount + if(!locate(S.type) in Deletion) + Deletion += S + else + data = S.amount + S = locate(S.type) in Deletion + S.add(data) + surroundings -= S + else + var/atom/movable/I + while(amt > 0) + I = locate(A) in surroundings + Deletion += I + surroundings -= I + amt-- + var/list/partlist = list(R.parts.len) + for(var/M in R.parts) + partlist[M] = R.parts[M] + for(var/A in R.parts) + if(istype(A, /datum/reagent)) + var/datum/reagent/RG = locate(A) in Deletion + if(RG.volume > partlist[A]) + RG.volume = partlist[A] + . += RG + Deletion -= RG + continue + else if(istype(A, /obj/item/stack)) + var/obj/item/stack/ST = locate(A) in Deletion + if(ST.amount > partlist[A]) + ST.amount = partlist[A] + . += ST + Deletion -= ST + continue + else + while(partlist[A] > 0) + var/atom/movable/AM = locate(A) in Deletion + . += AM + Deletion -= AM + partlist[A] -= 1 + while(Deletion.len) + var/DL = Deletion[Deletion.len] + Deletion.Cut(Deletion.len) + qdel(DL) + +/datum/component/personal_crafting/proc/component_ui_interact(obj/screen/craft/image, location, control, params, user) + if(user == parent) + ui_interact(user) + +/datum/component/personal_crafting/ui_state(mob/user) + return GLOB.not_incapacitated_turf_state + +//For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom +/datum/component/personal_crafting/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + cur_category = categories[1] + if(islist(categories[cur_category])) + var/list/subcats = categories[cur_category] + cur_subcategory = subcats[1] + else + cur_subcategory = CAT_NONE + ui = new(user, src, "PersonalCrafting") + ui.open() + +/datum/component/personal_crafting/ui_data(mob/user) + var/list/data = list() + data["busy"] = busy + data["category"] = cur_category + data["subcategory"] = cur_subcategory + data["display_craftable_only"] = display_craftable_only + data["display_compact"] = display_compact + + var/list/surroundings = get_surroundings(user) + var/list/craftability = list() + for(var/rec in GLOB.crafting_recipes) + var/datum/crafting_recipe/R = rec + + if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this. + continue + + if((R.category != cur_category) || (R.subcategory != cur_subcategory)) + continue + + craftability["[REF(R)]"] = check_contents(user, R, surroundings) + + data["craftability"] = craftability + return data + +/datum/component/personal_crafting/ui_static_data(mob/user) + var/list/data = list() + + var/list/crafting_recipes = list() + for(var/rec in GLOB.crafting_recipes) + var/datum/crafting_recipe/R = rec + + if(R.name == "") //This is one of the invalid parents that sneaks in + continue + + if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this. + continue + + if(isnull(crafting_recipes[R.category])) + crafting_recipes[R.category] = list() + + if(R.subcategory == CAT_NONE) + crafting_recipes[R.category] += list(build_recipe_data(R)) + else + if(isnull(crafting_recipes[R.category][R.subcategory])) + crafting_recipes[R.category][R.subcategory] = list() + crafting_recipes[R.category]["has_subcats"] = TRUE + crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R)) + + data["crafting_recipes"] = crafting_recipes + return data + +/datum/component/personal_crafting/ui_act(action, params) + if(..()) + return + switch(action) + if("make") + var/mob/user = usr + var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes + busy = TRUE + ui_interact(user) + var/atom/movable/result = construct_item(user, TR) + if(!istext(result)) //We made an item and didn't get a fail message + if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine + user.put_in_hands(result) + else + result.forceMove(user.drop_location()) + to_chat(user, "[TR.name] constructed.") + else + to_chat(user, "Construction failed[result]") + busy = FALSE + if("toggle_recipes") + display_craftable_only = !display_craftable_only + . = TRUE + if("toggle_compact") + display_compact = !display_compact + . = TRUE + if("set_category") + cur_category = params["category"] + cur_subcategory = params["subcategory"] || "" + . = TRUE + +/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R) + var/list/data = list() + data["name"] = R.name + data["ref"] = "[REF(R)]" + var/req_text = "" + var/tool_text = "" + var/catalyst_text = "" + + for(var/a in R.reqs) + //We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var) + //Also these are typepaths so sadly we can't just do "[a]" + var/atom/A = a + req_text += " [R.reqs[A]] [initial(A.name)]," + req_text = replacetext(req_text,",","",-1) + data["req_text"] = req_text + + for(var/a in R.chem_catalysts) + var/atom/A = a //cheat-typecast + catalyst_text += " [R.chem_catalysts[A]] [initial(A.name)]," + catalyst_text = replacetext(catalyst_text,",","",-1) + data["catalyst_text"] = catalyst_text + + for(var/a in R.tools) + if(ispath(a, /obj/item)) + var/obj/item/b = a + tool_text += " [initial(b.name)]," + else + tool_text += " [a]," + tool_text = replacetext(tool_text,",","",-1) + data["tool_text"] = tool_text + + return data + +//Mind helpers + +/datum/mind/proc/teach_crafting_recipe(R) + if(!learned_recipes) + learned_recipes = list() + learned_recipes |= R diff --git a/code/datums/components/crafting/glassware/lens_crafting.dm b/code/datums/components/crafting/glassware/lens_crafting.dm index 117df25a30..98fa242058 100644 --- a/code/datums/components/crafting/glassware/lens_crafting.dm +++ b/code/datums/components/crafting/glassware/lens_crafting.dm @@ -92,7 +92,7 @@ qdel(src) /obj/item/glasswork/glasses - name = "Hand Made Glasses" - desc = "Hande made glasses that have not been polished at all making them useless. Selling them could still be worth a bit of credits." + name = "Handmade Glasses" + desc = "Handmade glasses that have not been polished at all making them useless. Selling them could still be worth a few credits." icon = 'icons/obj/glass_ware.dmi' icon_state = "frames_2" \ No newline at end of file diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm index 4626ef69d1..deab5e9b69 100644 --- a/code/datums/components/crafting/guncrafting.dm +++ b/code/datums/components/crafting/guncrafting.dm @@ -1,4 +1,4 @@ -k// PARTS // +// PARTS // /obj/item/weaponcrafting icon = 'icons/obj/improvised.dmi' @@ -8,61 +8,33 @@ k// PARTS // custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 6) icon_state = "riflestock" -/obj/item/weaponcrafting/durathread_string - name = "durathread string" - desc = "A long piece of durathread with some resemblance to cable coil." +/obj/item/weaponcrafting/string + name = "wound thread" + desc = "A long piece of thread with some resemblance to cable coil." icon_state = "durastring" //////////////////////////////// -// KAT IMPROVISED WEAPON PARTS// +// IMPROVISED WEAPON PARTS// //////////////////////////////// /obj/item/weaponcrafting/improvised_parts - name = "Eerie bunch of coloured dots." - desc = "You feel the urge to report to Central that the parent type of guncrafting, which should never appear in this reality, has appeared. Whatever that means." + name = "Debug Improvised Gun Part" + desc = "A badly coded gun part. You should report coders if you see this." icon = 'icons/obj/guns/gun_parts.dmi' icon_state = "palette" -// BARRELS - -/obj/item/weaponcrafting/improvised_parts/barrel_rifle - name = "rifle barrel" - desc = "A pipe with a diameter just the right size to fire 7.62 rounds out of." - icon_state = "barrel_rifle" - -/obj/item/weaponcrafting/improvised_parts/barrel_shotgun - name = "shotgun barrel" - desc = "A twenty bore shotgun barrel." - icon_state = "barrel_shotgun" - -/obj/item/weaponcrafting/improvised_parts/barrel_pistol - name = "pistol barrel" - desc = "A pipe with a small diameter and some holes finely cut into it. It fits .32 ACP bullets. Probably." - icon_state = "barrel_pistol" - w_class = WEIGHT_CLASS_SMALL - // RECEIVERS /obj/item/weaponcrafting/improvised_parts/rifle_receiver - name = "bolt action receiver" - desc = "A crudely constructed receiver to create an improvised bolt-action breechloaded rifle. It's generic enough to modify to create other rifles, potentially." + name = "rifle receiver" + desc = "A crudely constructed receiver to create an improvised bolt-action breechloaded rifle." // removed some text implying that the item had more uses than it does icon_state = "receiver_rifle" w_class = WEIGHT_CLASS_SMALL -/obj/item/weaponcrafting/improvised_parts/pistol_receiver - name = "pistol receiver" - desc = "A receiver to connect house and connects all the parts to make an improvised pistol." - icon_state = "receiver_pistol" - w_class = WEIGHT_CLASS_SMALL - -/obj/item/weaponcrafting/improvised_parts/laser_receiver - name = "energy emitter assembly" - desc = "A mixture of components haphazardly wired together to form an energy emitter." - icon_state = "laser_assembly" /obj/item/weaponcrafting/improvised_parts/shotgun_receiver - name = "break-action assembly" - desc = "An improvised receiver to create a break-action breechloaded shotgun. Parts of this are still useful if you want to make another type of shotgun, however." + name = "shotgun reciever" + desc = "An improvised receiver to create a break-action breechloaded shotgun." // removed some text implying that the item had more uses than it does icon_state = "receiver_shotgun" w_class = WEIGHT_CLASS_SMALL @@ -78,15 +50,3 @@ k// PARTS // name = "wooden firearm body" desc = "A crudely fashioned wooden body to help keep higher calibre improvised weapons from blowing themselves apart." icon_state = "wooden_body" - -/obj/item/weaponcrafting/improvised_parts/wooden_grip - name = "wooden pistol grip" - desc = "A nice wooden grip hollowed out for pistol magazines." - icon_state = "wooden_pistolgrip" - w_class = WEIGHT_CLASS_SMALL - -/obj/item/weaponcrafting/improvised_parts/makeshift_lens - name = "makeshift focusing lens" - desc = "A properly made lens made with actual glassworking tools would perform much better, but this will have to do." - icon_state = "focusing_lens" - w_class = WEIGHT_CLASS_TINY diff --git a/code/datums/components/crafting/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm index 7a7379c834..717e99e8b2 100644 --- a/code/datums/components/crafting/recipes/recipes_clothing.dm +++ b/code/datums/components/crafting/recipes/recipes_clothing.dm @@ -40,13 +40,23 @@ reqs = list(/obj/item/paper = 20) category = CAT_CLOTHING +/datum/crafting_recipe/balaclavabreath + name = "Breathaclava" + result = /obj/item/clothing/mask/balaclava/breath + time = 10 + reqs = list(/obj/item/clothing/mask/balaclava = 1, + /obj/item/clothing/mask/breath = 1) + 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/durathread = 2, + /obj/item/stack/sticky_tape = 2, /obj/item/stack/sheet/leather = 2) category = CAT_CLOTHING @@ -263,6 +273,14 @@ time = 30 category = CAT_CLOTHING +/datum/crafting_recipe/durathread_reinforcement_kit + name = "Durathread Reinforcement Kit" + result = /obj/item/armorkit + reqs = list(/obj/item/stack/sheet/durathread = 4) + tools = list(/obj/item/stack/sheet/mineral/titanium, TOOL_WIRECUTTER) // tough needle for a tough fabric + time = 40 + category = CAT_CLOTHING + /datum/crafting_recipe/durathread_duffelbag name = "Durathread Dufflebag" result = /obj/item/storage/backpack/duffelbag/durathread diff --git a/code/datums/components/crafting/recipes/recipes_misc.dm b/code/datums/components/crafting/recipes/recipes_misc.dm index b076407efc..f113be728d 100644 --- a/code/datums/components/crafting/recipes/recipes_misc.dm +++ b/code/datums/components/crafting/recipes/recipes_misc.dm @@ -2,6 +2,15 @@ //Large Objects// ///////////////// +/datum/crafting_recipe/plunger + name = "Plunger" + result = /obj/item/plunger + time = 1 + reqs = list(/obj/item/stack/sheet/plastic = 1, + /obj/item/stack/sheet/mineral/wood = 1) + category = CAT_MISC + subcategory = CAT_TOOL + /datum/crafting_recipe/showercurtain name = "Shower Curtains" reqs = list(/obj/item/stack/sheet/cloth = 2, @@ -92,7 +101,7 @@ time = 150 subcategory = CAT_MISCELLANEOUS category = CAT_MISC - always_availible = FALSE // Disabled til learned + always_availible = FALSE // Disabled until learned /datum/crafting_recipe/bloodsucker/candelabrum @@ -126,7 +135,7 @@ /datum/crafting_recipe/brute_pack name = "Suture Pack" - result = /obj/item/stack/medical/suture/one + result = /obj/item/stack/medical/suture/five time = 1 reqs = list(/obj/item/stack/medical/gauze = 1, /datum/reagent/medicine/styptic_powder = 10) @@ -135,7 +144,7 @@ /datum/crafting_recipe/burn_pack name = "Regenerative Mesh" - result = /obj/item/stack/medical/mesh/one + result = /obj/item/stack/medical/mesh/five time = 1 reqs = list(/obj/item/stack/medical/gauze = 1, /datum/reagent/medicine/silver_sulfadiazine = 10) @@ -188,7 +197,7 @@ result = /obj/item/screwdriver/bronze reqs = list(/obj/item/screwdriver = 1, /obj/item/stack/cable_coil = 10, - /obj/item/stack/tile/bronze = 1, + /obj/item/stack/sheet/bronze = 1, /datum/reagent/water = 15) time = 40 subcategory = CAT_TOOL @@ -200,7 +209,7 @@ result = /obj/item/weldingtool/bronze reqs = list(/obj/item/weldingtool = 1, /obj/item/stack/cable_coil = 10, - /obj/item/stack/tile/bronze = 1, + /obj/item/stack/sheet/bronze = 1, /datum/reagent/water = 15) time = 40 subcategory = CAT_TOOL @@ -212,7 +221,7 @@ result = /obj/item/wirecutters/bronze reqs = list(/obj/item/wirecutters = 1, /obj/item/stack/cable_coil = 10, - /obj/item/stack/tile/bronze = 1, + /obj/item/stack/sheet/bronze = 1, /datum/reagent/water = 15) time = 40 subcategory = CAT_TOOL @@ -224,7 +233,7 @@ result = /obj/item/crowbar/bronze reqs = list(/obj/item/crowbar = 1, /obj/item/stack/cable_coil = 10, - /obj/item/stack/tile/bronze = 1, + /obj/item/stack/sheet/bronze = 1, /datum/reagent/water = 15) time = 40 subcategory = CAT_TOOL @@ -236,7 +245,7 @@ result = /obj/item/wrench/bronze reqs = list(/obj/item/wrench = 1, /obj/item/stack/cable_coil = 10, - /obj/item/stack/tile/bronze = 1, + /obj/item/stack/sheet/bronze = 1, /datum/reagent/water = 15) time = 40 subcategory = CAT_TOOL @@ -244,7 +253,7 @@ /datum/crafting_recipe/rcl name = "Makeshift Rapid Cable Layer" - result = /obj/item/twohanded/rcl/ghetto + result = /obj/item/rcl/ghetto time = 40 tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH) reqs = list(/obj/item/stack/sheet/metal = 15) @@ -269,6 +278,19 @@ subcategory = CAT_TOOL category = CAT_MISC +/datum/crafting_recipe/heretic/codex + name = "Codex Cicatrix" + result = /obj/item/forbidden_book + tools = list(/obj/item/pen) + reqs = list(/obj/item/paper = 5, + /obj/item/organ/eyes = 1, + /obj/item/organ/heart = 1, + /obj/item/stack/sheet/animalhide/human = 1) + time = 150 + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + always_availible = FALSE + //////////// //Vehicles// //////////// @@ -325,6 +347,13 @@ subcategory = CAT_MISCELLANEOUS category = CAT_MISC +/datum/crafting_recipe/catgirlplushie + name = "Catgirl Plushie" + reqs = list(/obj/item/toy/plush/hairball = 3) + result = /obj/item/toy/plush/catgirl + subcategory = CAT_MISCELLANEOUS + category = CAT_MISC + //////////// //Unsorted// //////////// diff --git a/code/datums/components/crafting/recipes/recipes_primal.dm b/code/datums/components/crafting/recipes/recipes_primal.dm index bb4f4ce6d5..aaae94df1d 100644 --- a/code/datums/components/crafting/recipes/recipes_primal.dm +++ b/code/datums/components/crafting/recipes/recipes_primal.dm @@ -50,7 +50,7 @@ /datum/crafting_recipe/bonespear name = "Bone Spear" - result = /obj/item/twohanded/bonespear + result = /obj/item/spear/bonespear time = 30 reqs = list(/obj/item/stack/sheet/bone = 4, /obj/item/stack/sheet/sinew = 1) @@ -58,7 +58,7 @@ /datum/crafting_recipe/boneaxe name = "Bone Axe" - result = /obj/item/twohanded/fireaxe/boneaxe + result = /obj/item/fireaxe/boneaxe time = 50 reqs = list(/obj/item/stack/sheet/bone = 6, /obj/item/stack/sheet/sinew = 3) @@ -74,20 +74,20 @@ /datum/crafting_recipe/headpike name = "Spike Head (Glass Spear)" time = 65 - reqs = list(/obj/item/twohanded/spear = 1, + reqs = list(/obj/item/spear = 1, /obj/item/bodypart/head = 1) parts = list(/obj/item/bodypart/head = 1, - /obj/item/twohanded/spear = 1) + /obj/item/spear = 1) result = /obj/structure/headpike category = CAT_PRIMAL /datum/crafting_recipe/headpikebone name = "Spike Head (Bone Spear)" time = 65 - reqs = list(/obj/item/twohanded/bonespear = 1, + reqs = list(/obj/item/spear/bonespear = 1, /obj/item/bodypart/head = 1) parts = list(/obj/item/bodypart/head = 1, - /obj/item/twohanded/bonespear = 1) + /obj/item/spear/bonespear = 1) result = /obj/structure/headpike/bone category = CAT_PRIMAL @@ -103,7 +103,7 @@ /datum/crafting_recipe/bone_bow name = "Bone Bow" result = /obj/item/gun/ballistic/bow/ashen - time = 200 + time = 120 // 80+120 = 200 always_availible = FALSE reqs = list(/obj/item/stack/sheet/bone = 8, /obj/item/stack/sheet/sinew = 4) @@ -112,7 +112,7 @@ /datum/crafting_recipe/bow_tablet name = "Sandstone Bow Making Manual" result = /obj/item/book/granter/crafting_recipe/bone_bow - time = 600 //Scribing + time = 200 //Scribing // don't care always_availible = FALSE reqs = list(/obj/item/stack/rods = 1, /obj/item/stack/sheet/mineral/sandstone = 4) 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 9d712ef059..ec8ea86d24 100644 --- a/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm +++ b/code/datums/components/crafting/recipes/recipes_weapon_and_ammo.dm @@ -42,7 +42,7 @@ /datum/crafting_recipe/spear name = "Spear" - result = /obj/item/twohanded/spear + result = /obj/item/spear reqs = list(/obj/item/restraints/handcuffs/cable = 1, /obj/item/shard = 1, /obj/item/stack/rods = 1) @@ -110,7 +110,7 @@ /datum/crafting_recipe/chainsaw name = "Chainsaw" - result = /obj/item/twohanded/required/chainsaw + result = /obj/item/chainsaw reqs = list(/obj/item/circular_saw = 1, /obj/item/stack/cable_coil = 3, /obj/item/stack/sheet/plasteel = 5) @@ -141,7 +141,7 @@ result = /obj/item/bombcore/chemical reqs = list( /obj/item/stock_parts/matter_bin = 1, - /obj/item/twohanded/required/gibtonite = 1, + /obj/item/gibtonite = 1, /obj/item/grenade/chem_grenade = 2 ) parts = list(/obj/item/stock_parts/matter_bin = 1, /obj/item/grenade/chem_grenade = 2) @@ -173,10 +173,10 @@ /datum/crafting_recipe/lance name = "Explosive Lance (Grenade)" - result = /obj/item/twohanded/spear - reqs = list(/obj/item/twohanded/spear = 1, + result = /obj/item/spear + reqs = list(/obj/item/spear = 1, /obj/item/grenade = 1) - parts = list(/obj/item/twohanded/spear = 1, + parts = list(/obj/item/spear = 1, /obj/item/grenade = 1) time = 15 category = CAT_WEAPONRY @@ -192,8 +192,8 @@ result = /obj/item/gun/ballistic/bow/pipe reqs = list(/obj/item/pipe = 5, /obj/item/stack/sheet/plastic = 15, - /obj/item/weaponcrafting/durathread_string = 5) - time = 450 + /obj/item/weaponcrafting/string = 5) + time = 150 category = CAT_WEAPONRY subcategory = CAT_WEAPON @@ -248,10 +248,10 @@ category = CAT_WEAPONRY subcategory = CAT_WEAPON -/datum/crafting_recipe/ishotgun +/datum/crafting_recipe/ishotgun // smaller and more versatile gun requires some better materials name = "Improvised Shotgun" result = /obj/item/gun/ballistic/revolver/doublebarrel/improvised - reqs = list(/obj/item/weaponcrafting/improvised_parts/barrel_shotgun = 1, + reqs = list(/obj/item/pipe = 2, // putting a large amount of meaningless timegates by forcing people to turn base resources into upgraded resources kinda sucks /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 1, /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1, /obj/item/weaponcrafting/improvised_parts/wooden_body = 1, @@ -262,10 +262,10 @@ category = CAT_WEAPONRY subcategory = CAT_WEAPON -/datum/crafting_recipe/irifle +/datum/crafting_recipe/irifle // larger and less versatile gun, but a bit easier to make name = "Improvised Rifle (7.62mm)" result = /obj/item/gun/ballistic/shotgun/boltaction/improvised - reqs = list(/obj/item/weaponcrafting/improvised_parts/barrel_rifle = 1, + reqs = list(/obj/item/pipe = 2, // above /obj/item/weaponcrafting/improvised_parts/rifle_receiver = 1, /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1, /obj/item/weaponcrafting/improvised_parts/wooden_body = 1, @@ -276,49 +276,6 @@ category = CAT_WEAPONRY subcategory = CAT_WEAPON -/datum/crafting_recipe/ipistol - name = "Improvised Pistol (.32)" - result = /obj/item/gun/ballistic/automatic/pistol/improvised/nomag - reqs = list(/obj/item/weaponcrafting/improvised_parts/barrel_pistol = 1, - /obj/item/weaponcrafting/improvised_parts/pistol_receiver = 1, - /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1, - /obj/item/weaponcrafting/improvised_parts/wooden_grip = 1, - /obj/item/stack/sheet/plastic = 15, - /obj/item/stack/sheet/plasteel = 1) - tools = list(TOOL_SCREWDRIVER, TOOL_WELDER, TOOL_WIRECUTTER) - time = 100 - category = CAT_WEAPONRY - subcategory = CAT_WEAPON - -/datum/crafting_recipe/ilaser - name = "Improvised Energy Gun" - result = /obj/item/gun/energy/e_gun/old/improvised - reqs = list(/obj/item/weaponcrafting/improvised_parts/laser_receiver = 1, - /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 1, - /obj/item/weaponcrafting/improvised_parts/makeshift_lens = 1, - /obj/item/stock_parts/cell = 1, - /obj/item/stack/sheet/metal = 10, - /obj/item/stack/sheet/plasteel = 5, - /obj/item/stack/cable_coil = 10) - tools = list(TOOL_SCREWDRIVER) - time = 100 - category = CAT_WEAPONRY - subcategory = CAT_WEAPON - -/datum/crafting_recipe/ilaser/upgraded - name = "Improvised Energy Gun Upgrade" - result = /obj/item/gun/energy/e_gun/old/improvised/upgraded - reqs = list(/obj/item/gun/energy/e_gun/old/improvised = 1, - /obj/item/glasswork/glass_base/lens = 1, - /obj/item/stock_parts/capacitor/quadratic = 2, - /obj/item/stock_parts/micro_laser/ultra = 1, - /obj/item/stock_parts/cell/bluespace = 1, - /obj/item/stack/cable_coil = 5) - tools = list(TOOL_SCREWDRIVER, TOOL_MULTITOOL) - time = 100 - category = CAT_WEAPONRY - subcategory = CAT_WEAPON - ////////////////// ///AMMO CRAFTING// ////////////////// @@ -326,9 +283,9 @@ /datum/crafting_recipe/arrow name = "Arrow" result = /obj/item/ammo_casing/caseless/arrow/wood - time = 30 + time = 5 // these only do 15 damage reqs = list(/obj/item/stack/sheet/mineral/wood = 1, - /obj/item/stack/sheet/durathread = 1, + /obj/item/stack/sheet/cloth = 1, /obj/item/stack/rods = 1) // 1 metal sheet = 2 rods = 2 arrows category = CAT_WEAPONRY subcategory = CAT_AMMO @@ -336,7 +293,7 @@ /datum/crafting_recipe/bone_arrow name = "Bone Arrow" result = /obj/item/ammo_casing/caseless/arrow/bone - time = 30 + time = 5 always_availible = FALSE reqs = list(/obj/item/stack/sheet/bone = 1, /obj/item/stack/sheet/sinew = 1, @@ -348,7 +305,7 @@ name = "Ashen Arrow" result = /obj/item/ammo_casing/caseless/arrow/ash tools = list(TOOL_WELDER) - time = 30 + time = 10 // 1.5 seconds minimum per actually worthwhile arrow excluding interface lag always_availible = FALSE reqs = list(/obj/item/ammo_casing/caseless/arrow/wood = 1) category = CAT_WEAPONRY @@ -442,92 +399,28 @@ category = CAT_WEAPONRY subcategory = CAT_AMMO -/datum/crafting_recipe/m32acp - name = ".32ACP Empty Magazine" - result = /obj/item/ammo_box/magazine/m32acp/empty - reqs = list(/obj/item/stack/sheet/metal = 3, - /obj/item/stack/sheet/plasteel = 1, - /obj/item/stack/packageWrap = 1) - tools = list(TOOL_WELDER,TOOL_SCREWDRIVER) - time = 5 - category = CAT_WEAPONRY - subcategory = CAT_AMMO - //////////////////// // PARTS CRAFTING // //////////////////// -// BARRELS - -/datum/crafting_recipe/rifle_barrel - name = "Improvised Rifle Barrel" - result = /obj/item/weaponcrafting/improvised_parts/barrel_rifle - reqs = list(/obj/item/pipe = 2) - tools = list(TOOL_WELDER,TOOL_SAW) - time = 150 - category = CAT_WEAPONRY - subcategory = CAT_PARTS - -/datum/crafting_recipe/shotgun_barrel - name = "Improvised Shotgun Barrel" - result = /obj/item/weaponcrafting/improvised_parts/barrel_shotgun - reqs = list(/obj/item/pipe = 2) - tools = list(TOOL_WELDER,TOOL_SAW) - time = 150 - category = CAT_WEAPONRY - subcategory = CAT_PARTS - -/datum/crafting_recipe/pistol_barrel - name = "Improvised Pistol Barrel" - result = /obj/item/weaponcrafting/improvised_parts/barrel_pistol - reqs = list(/obj/item/pipe = 1, - /obj/item/stack/sheet/plasteel = 1) - tools = list(TOOL_WELDER,TOOL_SAW) - time = 150 - category = CAT_WEAPONRY - subcategory = CAT_PARTS - // RECEIVERS /datum/crafting_recipe/rifle_receiver name = "Improvised Rifle Receiver" result = /obj/item/weaponcrafting/improvised_parts/rifle_receiver - reqs = list(/obj/item/stack/sheet/metal = 10, - /obj/item/stack/sheet/plasteel = 1) + reqs = list(/obj/item/stack/sheet/metal = 15) // you can carry multiple shotguns tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) - time = 50 + time = 25 category = CAT_WEAPONRY subcategory = CAT_PARTS /datum/crafting_recipe/shotgun_receiver name = "Improvised Shotgun Receiver" result = /obj/item/weaponcrafting/improvised_parts/shotgun_receiver - reqs = list(/obj/item/stack/sheet/metal = 10, - /obj/item/stack/sheet/plasteel = 1) - tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) // Dual wielding has been removed, plasteel is a soft timesink to obtain for most to make mass production harder. - time = 50 - category = CAT_WEAPONRY - subcategory = CAT_PARTS - -/datum/crafting_recipe/pistol_receiver - name = "Improvised Pistol Receiver" - result = /obj/item/weaponcrafting/improvised_parts/pistol_receiver - reqs = list(/obj/item/stack/sheet/metal = 5, - /obj/item/stack/sheet/plasteel = 1) - tools = list(TOOL_SCREWDRIVER, TOOL_WELDER, TOOL_SAW) - time = 50 - category = CAT_WEAPONRY - subcategory = CAT_PARTS - -/datum/crafting_recipe/laser_receiver - name = "Energy Weapon Assembly" - result = /obj/item/weaponcrafting/improvised_parts/laser_receiver - reqs = list(/obj/item/stack/sheet/metal = 10, - /obj/item/stock_parts/capacitor = 2, - /obj/item/stock_parts/micro_laser = 1, - /obj/item/assembly/prox_sensor = 1) - tools = list(TOOL_SCREWDRIVER, TOOL_MULTITOOL, TOOL_WELDER) // Prox sensor and multitool for the circuit board, welder for extremely ghetto soldering. - time = 150 + reqs = list(/obj/item/stack/sheet/metal = 15, + /obj/item/stack/sheet/plasteel = 1) // requires access or hacking since shotgun is better + tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) + time = 25 category = CAT_WEAPONRY subcategory = CAT_PARTS @@ -539,16 +432,6 @@ reqs = list(/obj/item/stack/sheet/metal = 3, /obj/item/assembly/igniter = 1) tools = list(TOOL_SCREWDRIVER, TOOL_WELDER) - time = 150 - category = CAT_WEAPONRY - subcategory = CAT_PARTS - -/datum/crafting_recipe/makeshift_lens - name = "Makeshift Lens" - result = /obj/item/weaponcrafting/improvised_parts/makeshift_lens - reqs = list(/obj/item/stack/sheet/metal = 1, - /obj/item/stack/sheet/glass = 2) - tools = list(TOOL_WELDER) // Glassmaking lets you make non-makeshift lenses. - time = 50 + time = 25 category = CAT_WEAPONRY subcategory = CAT_PARTS diff --git a/code/datums/components/edible.dm b/code/datums/components/edible.dm new file mode 100644 index 0000000000..dc2e490fe4 --- /dev/null +++ b/code/datums/components/edible.dm @@ -0,0 +1,245 @@ +/*! +This component makes it possible to make things edible. What this means is that you can take a bite or force someone to take a bite (in the case of items). +These items take a specific time to eat, and can do most of the things our original food items could. +Behavior that's still missing from this component that original food items had that should either be put into seperate components or somewhere else: + Components: + Drying component (jerky etc) + Customizable component (custom pizzas etc) + Processable component (Slicing and cooking behavior essentialy, making it go from item A to B when conditions are met.) + Dunkable component (Dunking things into reagent containers to absorb a specific amount of reagents) + Misc: + Something for cakes (You can store things inside) +*/ +/datum/component/edible + ///Amount of reagents taken per bite + var/bite_consumption = 2 + ///Amount of bites taken so far + var/bitecount = 0 + ///Flags for food + var/food_flags = NONE + ///Bitfield of the types of this food + var/foodtypes = NONE + ///Amount of seconds it takes to eat this food + var/eat_time = 30 + ///Defines how much it lowers someones satiety (Need to eat, essentialy) + var/junkiness = 0 + ///Message to send when eating + var/list/eatverbs + ///Callback to be ran for when you take a bite of something + var/datum/callback/after_eat + ///Last time we checked for food likes + var/last_check_time + +/datum/component/edible/Initialize(list/initial_reagents, food_flags = NONE, foodtypes = NONE, volume = 50, eat_time = 30, list/tastes, list/eatverbs = list("bite","chew","nibble","gnaw","gobble","chomp"), bite_consumption = 2, datum/callback/after_eat) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_ANIMAL, .proc/UseByAnimal) + if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/UseFromHand) + else if(isturf(parent)) + RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/TryToEatTurf) + + src.bite_consumption = bite_consumption + src.food_flags = food_flags + src.foodtypes = foodtypes + src.eat_time = eat_time + src.eatverbs = eatverbs + src.junkiness = junkiness + src.after_eat = after_eat + + var/atom/owner = parent + + if(!owner.reagents) //we don't want to override what's in the item if it possibly contains reagents already + owner.create_reagents(volume, INJECTABLE) + + if(initial_reagents) + for(var/rid in initial_reagents) + var/amount = initial_reagents[rid] + if(tastes && tastes.len && (rid == /datum/reagent/consumable/nutriment || rid == /datum/reagent/consumable/nutriment/vitamin)) + owner.reagents.add_reagent(rid, amount, tastes.Copy()) + else + owner.reagents.add_reagent(rid, amount) + +/datum/component/edible/proc/examine(datum/source, mob/user, list/examine_list) + if(!(food_flags & FOOD_IN_CONTAINER)) + switch (bitecount) + if (0) + return + if(1) + examine_list += "[parent] was bitten by someone!" + if(2,3) + examine_list += "[parent] was bitten [bitecount] times!" + else + examine_list += "[parent] was bitten multiple times!" + +/datum/component/edible/proc/UseFromHand(obj/item/source, mob/living/M, mob/living/user) + return TryToEat(M, user) + +/datum/component/edible/proc/TryToEatTurf(datum/source, mob/user) + return TryToEat(user, user) + +///All the checks for the act of eating itself and +/datum/component/edible/proc/TryToEat(mob/living/eater, mob/living/feeder) + + set waitfor = FALSE + + var/atom/owner = parent + + if(feeder.a_intent == INTENT_HARM) + return + if(!owner.reagents.total_volume)//Shouldn't be needed but it checks to see if it has anything left in it. + to_chat(feeder, "None of [owner] left, oh no!") + if(isturf(parent)) + var/turf/T = parent + T.ScrapeAway(1, CHANGETURF_INHERIT_AIR) + else + qdel(parent) + return + if(!CanConsume(eater, feeder)) + return + var/fullness = eater.nutrition + 10 //The theoretical fullness of the person eating if they were to eat this + for(var/datum/reagent/consumable/C in eater.reagents.reagent_list) //we add the nutrition value of what we're currently digesting + fullness += C.nutriment_factor * C.volume / C.metabolization_rate + + . = COMPONENT_ITEM_NO_ATTACK //Point of no return I suppose + + if(eater == feeder)//If you're eating it yourself. + if(!do_mob(feeder, eater, eat_time)) //Gotta pass the minimal eat time + return + var/eatverb = pick(eatverbs) + if(junkiness && eater.satiety < -150 && eater.nutrition > NUTRITION_LEVEL_STARVING + 50 && !HAS_TRAIT(eater, TRAIT_VORACIOUS)) + to_chat(eater, "You don't feel like eating any more junk food at the moment!") + return + else if(fullness <= 50) + eater.visible_message("[eater] hungrily [eatverb]s \the [parent], gobbling it down!", "You hungrily [eatverb] \the [parent], gobbling it down!") + else if(fullness > 50 && fullness < 150) + eater.visible_message("[eater] hungrily [eatverb]s \the [parent].", "You hungrily [eatverb] \the [parent].") + else if(fullness > 150 && fullness < 500) + eater.visible_message("[eater] [eatverb]s \the [parent].", "You [eatverb] \the [parent].") + else if(fullness > 500 && fullness < 600) + eater.visible_message("[eater] unwillingly [eatverb]s a bit of \the [parent].", "You unwillingly [eatverb] a bit of \the [parent].") + else if(fullness > (600 * (1 + eater.overeatduration / 2000))) // The more you eat - the more you can eat + eater.visible_message("[eater] cannot force any more of \the [parent] to go down [eater.p_their()] throat!", "You cannot force any more of \the [parent] to go down your throat!") + return + else //If you're feeding it to someone else. + if(isbrain(eater)) + to_chat(feeder, "[eater] doesn't seem to have a mouth!") + return + if(fullness <= (600 * (1 + eater.overeatduration / 1000))) + eater.visible_message("[feeder] attempts to feed [eater] [parent].", \ + "[feeder] attempts to feed you [parent].") + else + eater.visible_message("[feeder] cannot force any more of [parent] down [eater]'s throat!", \ + "[feeder] cannot force any more of [parent] down your throat!") + return + if(!do_mob(feeder, eater)) //Wait 3 seconds before you can feed + return + + log_combat(feeder, eater, "fed", owner.reagents.log_list()) + eater.visible_message("[feeder] forces [eater] to eat [parent]!", \ + "[feeder] forces you to eat [parent]!") + + TakeBite(eater, feeder) + +///This function lets the eater take a bite and transfers the reagents to the eater. +/datum/component/edible/proc/TakeBite(mob/living/eater, mob/living/feeder) + + var/atom/owner = parent + + if(!owner?.reagents) + return FALSE + if(eater.satiety > -200) + eater.satiety -= junkiness + playsound(eater.loc,'sound/items/eatfood.ogg', rand(10,50), TRUE) + if(owner.reagents.total_volume) + SEND_SIGNAL(parent, COMSIG_FOOD_EATEN, eater, feeder) + var/fraction = min(bite_consumption / owner.reagents.total_volume, 1) + owner.reagents.reaction(eater, INGEST, fraction) + owner.reagents.trans_to(eater, bite_consumption) + bitecount++ + On_Consume(eater) + checkLiked(fraction, eater) + + //Invoke our after eat callback if it is valid + if(after_eat) + after_eat.Invoke(eater, feeder) + + return TRUE + +///Checks whether or not the eater can actually consume the food +/datum/component/edible/proc/CanConsume(mob/living/eater, mob/living/feeder) + if(!iscarbon(eater)) + return FALSE + var/mob/living/carbon/C = eater + var/covered = "" + if(C.is_mouth_covered(head_only = 1)) + covered = "headgear" + else if(C.is_mouth_covered(mask_only = 1)) + covered = "mask" + if(covered) + var/who = (isnull(feeder) || eater == feeder) ? "your" : "[eater.p_their()]" + to_chat(feeder, "You have to remove [who] [covered] first!") + return FALSE + return TRUE + +///Check foodtypes to see if we should send a moodlet +/datum/component/edible/proc/checkLiked(var/fraction, mob/M) + if(last_check_time + 50 > world.time) + return FALSE + if(!ishuman(M)) + return FALSE + var/mob/living/carbon/human/H = M + if(HAS_TRAIT(H, TRAIT_AGEUSIA) && foodtypes & H.dna.species.toxic_food) + to_chat(H, "You don't feel so good...") + H.adjust_disgust(25 + 30 * fraction) + else + if(foodtypes & H.dna.species.toxic_food) + to_chat(H,"What the hell was that thing?!") + H.adjust_disgust(25 + 30 * fraction) + SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "toxic_food", /datum/mood_event/disgusting_food) + else if(foodtypes & H.dna.species.disliked_food) + to_chat(H,"That didn't taste very good...") + H.adjust_disgust(11 + 15 * fraction) + SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "gross_food", /datum/mood_event/gross_food) + else if(foodtypes & H.dna.species.liked_food) + to_chat(H,"I love this taste!") + H.adjust_disgust(-5 + -2.5 * fraction) + SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "fav_food", /datum/mood_event/favorite_food) + if((foodtypes & BREAKFAST) && world.time - SSticker.round_start_time < STOP_SERVING_BREAKFAST) + SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "breakfast", /datum/mood_event/breakfast) + last_check_time = world.time + +///Delete the item when it is fully eaten +/datum/component/edible/proc/On_Consume(mob/living/eater) + + var/atom/owner = parent + + if(!eater) + return + if(!owner.reagents.total_volume) + if(isturf(parent)) + var/turf/T = parent + T.ScrapeAway(1, CHANGETURF_INHERIT_AIR) + else + qdel(parent) + +///Ability to feed food to puppers +/datum/component/edible/proc/UseByAnimal(datum/source, mob/user) + + var/atom/owner = parent + + if(!isdog(user)) + return + var/mob/living/L = user + if(bitecount == 0 || prob(50)) + L.emote("me", 1, "nibbles away at \the [parent]") + bitecount++ + . = COMPONENT_ITEM_NO_ATTACK + L.taste(owner.reagents) // why should carbons get all the fun? + if(bitecount >= 5) + var/sattisfaction_text = pick("burps from enjoyment", "yaps for more", "woofs twice", "looks at the area where \the [parent] was") + if(sattisfaction_text) + L.emote("me", 1, "[sattisfaction_text]") + qdel(parent) diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index 137a1bb864..8c4e62979b 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -29,7 +29,6 @@ */ - /datum/component/embedded dupe_mode = COMPONENT_DUPE_ALLOWED var/obj/item/bodypart/limb @@ -120,7 +119,7 @@ UnregisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) if(overlay) var/atom/A = parent - A.cut_overlay(overlay, TRUE) + UnregisterSignal(A,COMSIG_ATOM_UPDATE_OVERLAYS) qdel(overlay) return ..() @@ -139,31 +138,37 @@ limb.embedded_objects |= weapon // on the inside... on the inside... weapon.forceMove(victim) RegisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING), .proc/byeItemCarbon) - + var/damage = 0 if(harmful) victim.visible_message("[weapon] embeds itself in [victim]'s [limb.name]!",ignored_mobs=victim) to_chat(victim, "[weapon] embeds itself in your [limb.name]!") victim.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) playsound(victim,'sound/weapons/bladeslice.ogg', 40) weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody! - var/damage = weapon.w_class * impact_pain_mult - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) + damage = weapon.w_class * impact_pain_mult SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) else victim.visible_message("[weapon] sticks itself to [victim]'s [limb.name]!",ignored_mobs=victim) to_chat(victim, "[weapon] sticks itself to your [limb.name]!") + if(damage > 0) + var/armor = victim.run_armor_check(limb.body_zone, "melee", "Your armor has protected your [limb.name].", "Your armor has softened a hit to your [limb.name].",weapon.armour_penetration) + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, blocked=armor, sharpness = weapon.get_sharpness()) + /// Called every time a carbon with a harmful embed moves, rolling a chance for the item to cause pain. The chance is halved if the carbon is crawling or walking. /datum/component/embedded/proc/jostleCheck() var/mob/living/carbon/victim = parent - var/chance = jostle_chance + var/damage = weapon.w_class * pain_mult + var/pain_chance_current = jostle_chance if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND)) - chance *= 0.5 + pain_chance_current *= 0.5 - if(harmful && prob(chance)) - var/damage = weapon.w_class * jostle_pain_mult - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) + if(pain_stam_pct && IS_STAMCRIT(victim)) //if it's a less-lethal embed, give them a break if they're already stamcritted + pain_chance_current *= 0.2 + damage *= 0.5 + if(harmful && prob(pain_chance_current)) + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) to_chat(victim, "[weapon] embedded in your [limb.name] jostles and stings!") @@ -173,7 +178,7 @@ if(harmful) var/damage = weapon.w_class * remove_pain_mult - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) victim.visible_message("[weapon] falls out of [victim.name]'s [limb.name]!", ignored_mobs=victim) to_chat(victim, "[weapon] falls out of your [limb.name]!") else @@ -199,7 +204,7 @@ if(harmful) var/damage = weapon.w_class * remove_pain_mult - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) //It hurts to rip it out, get surgery you dingus. + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) //It hurts to rip it out, get surgery you dingus. victim.emote("scream") victim.visible_message("[victim] successfully rips [weapon] out of [victim.p_their()] [limb.name]!", "You successfully remove [weapon] from your [limb.name].") else @@ -276,14 +281,16 @@ damage *= 0.7 if(harmful && prob(chance)) - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage) + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) to_chat(victim, "[weapon] embedded in your [limb.name] hurts!") - if(prob(fall_chance)) + var/fall_chance_current = fall_chance + if(victim.mobility_flags & ~MOBILITY_STAND) + fall_chance_current *= 0.2 + + if(prob(fall_chance_current)) fallOutCarbon() - - //////////////////////////////////////// //////////////TURF PROCS//////////////// //////////////////////////////////////// @@ -319,7 +326,8 @@ var/matrix/M = matrix() M.Translate(pixelX, pixelY) overlay.transform = M - hit.add_overlay(overlay, TRUE) + RegisterSignal(hit,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/apply_overlay) + hit.update_icon() if(harmful) hit.visible_message("[weapon] embeds itself in [hit]!") @@ -332,6 +340,8 @@ else hit.visible_message("[weapon] sticks itself to [hit]!") +/datum/component/embedded/proc/apply_overlay(atom/source, list/overlay_list) + overlay_list += overlay /datum/component/embedded/proc/examineTurf(datum/source, mob/user, list/examine_list) if(harmful) diff --git a/code/datums/components/fried.dm b/code/datums/components/fried.dm new file mode 100644 index 0000000000..4e21962778 --- /dev/null +++ b/code/datums/components/fried.dm @@ -0,0 +1,107 @@ +/*! + This component essentially encapsulates frying and utilizes the edible component + This means fried items can work like regular ones, and generally the code is far less messy +*/ +/datum/component/fried + var/fry_power //how powerfully was this item fried + var/atom/owner //the atom it is owned by + var/stored_name //name of the owner when the component was first added + var/frying_examine_text = "the coders messed frying code up, report this!" + +/datum/component/fried/Initialize(frying_power) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine) + RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/restore) //basically, unfry people who are being cleaned (badmemes fried someone) + + fry_power = frying_power + owner = parent + stored_name = owner.name + + setup_fried_item() + +//some stuff to do with the contents of fried junk +GLOBAL_VAR_INIT(frying_hardmode, TRUE) +GLOBAL_VAR_INIT(frying_bad_chem_add_volume, TRUE) +GLOBAL_LIST_INIT(frying_bad_chems, list( +/datum/reagent/toxin/bad_food = 1, +/datum/reagent/toxin = 1, +/datum/reagent/lithium = 1, +/datum/reagent/mercury = 1, +)) + +/datum/component/fried/proc/examine(datum/source, mob/user, list/examine_list) + examine_list += "[parent] has been [frying_examine_text]" + +/datum/component/fried/proc/setup_fried_item() //sets the name, colour and examine text and edibility up + //first we do some checks depending on the type of item being fried + var/list/fried_tastes = list("crispy") + var/fried_foodtypes = FRIED + var/fried_junk = FALSE + + if(!isfood(owner) && GLOB.frying_hardmode && GLOB.frying_bad_chems.len && !owner.reagents) //you fried some junk, it's not gonna taste great + fried_junk = TRUE + fried_foodtypes |= TOXIC // junk tastes toxic too + else + if(isfood(owner)) + var/obj/item/reagent_containers/food/snacks/food_item = owner + fried_tastes += food_item.tastes + fried_foodtypes |= food_item.foodtype + + var/fried_eat_time = 0 + if(isturf(owner)) + fried_eat_time = 30 //we want turfs to be eaten slowly + + var/colour_priority = FIXED_COLOUR_PRIORITY + if(ismob(owner)) + colour_priority = WASHABLE_COLOUR_PRIORITY //badmins fried someone and we want to let them wash the fry colour off + //lets heavily hint at how to undo their frying + to_chat(owner, "You've been coated in hot cooking oil! You should probably go wash it off at the showers.") + else + owner.AddComponent(/datum/component/edible, foodtypes = fried_tastes, tastes = fried_tastes, eat_time = fried_eat_time) //we don't want mobs to get the edible component + + switch(fry_power) + if(0 to 15) + owner.name = "lightly fried [owner.name]" + owner.add_atom_colour(rgb(166,103,54), colour_priority) + frying_examine_text = "lightly fried" + if(16 to 49) + owner.name = "fried [owner.name]" + owner.add_atom_colour(rgb(103,63,24), colour_priority) + frying_examine_text = "moderately fried" + if(50 to 59) + owner.name = "deep fried [owner.name]" + owner.add_atom_colour(rgb(63,23,4), colour_priority) + frying_examine_text = "deeply fried" + else + owner.name = "the physical manifestation of fried foods" + owner.add_atom_colour(rgb(33,19,9), colour_priority) + frying_examine_text = "incomprehensibly fried to a crisp" + + //adding the edible component gives it reagents meaning we can now add the bad frying reagents if it's junk + if(fried_junk && owner.reagents) //check again just incase + var/R = rand(1, GLOB.frying_bad_chems.len) + var/bad_chem = GLOB.frying_bad_chems[R] + var/bad_chem_amount = max(4,GLOB.frying_bad_chems[bad_chem] * (fry_power/12.5)) //4u of bad chem reached when deeply fried + owner.reagents.add_reagent(bad_chem, bad_chem_amount) + +/datum/component/fried/proc/restore_name() //restore somethings name + //we do string manipulation and not restoring their name to real_name because some things hide your real_name and we want to maintain that + if(copytext(owner.name,1,14) == "lightly fried ") + owner.name = copytext(owner.name,15) + else + if(copytext(owner.name,1,6) == "fried ") + owner.name = copytext(owner.name,7) + else + if(copytext(owner.name,1,11) == "deep fried ") + owner.name = copytext(owner.name, 12) + else + if(owner.name == "the physical manifestation of fried foods") //if the name is still this, their name hasn't changed, so we can safely restore their stored name + owner.name = stored_name + +/datum/component/fried/proc/restore() //restore a fried mob to being not-fried + if(ismob(owner)) + //restore the name, the colour should wash off itself, and then remove the component + restore_name() + RemoveComponent() diff --git a/code/datums/components/gps.dm b/code/datums/components/gps.dm new file mode 100644 index 0000000000..c2b3ad1f30 --- /dev/null +++ b/code/datums/components/gps.dm @@ -0,0 +1,149 @@ +///Global GPS_list. All GPS components get saved in here for easy reference. +GLOBAL_LIST_EMPTY(GPS_list) +///GPS component. Atoms that have this show up on gps. Pretty simple stuff. +/datum/component/gps + var/gpstag = "COM0" + var/tracking = TRUE + var/emped = FALSE + +/datum/component/gps/Initialize(_gpstag = "COM0") + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + gpstag = _gpstag + GLOB.GPS_list += src + +/datum/component/gps/Destroy() + GLOB.GPS_list -= src + return ..() + +///GPS component subtype. Only gps/item's can be used to open the UI. +/datum/component/gps/item + var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user. + var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown + +/datum/component/gps/item/Initialize(_gpstag = "COM0", emp_proof = FALSE) + . = ..() + if(. == COMPONENT_INCOMPATIBLE || !isitem(parent)) + return COMPONENT_INCOMPATIBLE + var/atom/A = parent + A.add_overlay("working") + A.name = "[initial(A.name)] ([gpstag])" + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact) + if(!emp_proof) + RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine) + RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_AltClick) + +///Called on COMSIG_ITEM_ATTACK_SELF +/datum/component/gps/item/proc/interact(datum/source, mob/user) + if(user) + ui_interact(user) + +///Called on COMSIG_PARENT_EXAMINE +/datum/component/gps/item/proc/on_examine(datum/source, mob/user, list/examine_list) + examine_list += "Alt-click to switch it [tracking ? "off":"on"]." + +///Called on COMSIG_ATOM_EMP_ACT +/datum/component/gps/item/proc/on_emp_act(datum/source, severity) + emped = TRUE + var/atom/A = parent + A.cut_overlay("working") + A.add_overlay("emp") + addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early + SStgui.close_uis(src) //Close the UI control if it is open. + +///Restarts the GPS after getting turned off by an EMP. +/datum/component/gps/item/proc/reboot() + emped = FALSE + var/atom/A = parent + A.cut_overlay("emp") + A.add_overlay("working") + +///Calls toggletracking +/datum/component/gps/item/proc/on_AltClick(datum/source, mob/user) + toggletracking(user) + +///Toggles the tracking for the gps +/datum/component/gps/item/proc/toggletracking(mob/user) + if(!user.canUseTopic(parent, BE_CLOSE)) + return //user not valid to use gps + if(emped) + to_chat(user, "It's busted!") + return + var/atom/A = parent + if(tracking) + A.cut_overlay("working") + to_chat(user, "[parent] is no longer tracking, or visible to other GPS devices.") + tracking = FALSE + else + A.add_overlay("working") + to_chat(user, "[parent] is now tracking, and visible to other GPS devices.") + tracking = TRUE + +/datum/component/gps/item/ui_interact(mob/user, datum/tgui/ui) + if(emped) + to_chat(user, "[parent] fizzles weakly.") + return + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Gps") + ui.open() + ui.set_autoupdate(updating) + +/datum/component/gps/item/ui_data(mob/user) + var/list/data = list() + data["power"] = tracking + data["tag"] = gpstag + data["updating"] = updating + data["globalmode"] = global_mode + if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed + return data + + var/turf/curr = get_turf(parent) + data["currentArea"] = "[get_area_name(curr, TRUE)]" + data["currentCoords"] = "[curr.x], [curr.y], [curr.z]" + + var/list/signals = list() + data["signals"] = list() + + for(var/gps in GLOB.GPS_list) + var/datum/component/gps/G = gps + if(G.emped || !G.tracking || G == src) + continue + var/turf/pos = get_turf(G.parent) + if(!pos || !global_mode && pos.z != curr.z) + continue + var/list/signal = list() + signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS + signal["coords"] = "[pos.x], [pos.y], [pos.z]" + if(pos.z == curr.z) //Distance/Direction calculations for same z-level only + signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs + signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision. + signals += list(signal) //Add this signal to the list of signals + data["signals"] = signals + return data + +/datum/component/gps/item/ui_act(action, params) + if(..()) + return + switch(action) + if("rename") + var/atom/parentasatom = parent + var/a = stripped_input(usr, "Please enter desired tag.", parentasatom.name, gpstag, 20) + + if (!a) + return + + gpstag = a + . = TRUE + parentasatom.name = "global positioning system ([gpstag])" + + if("power") + toggletracking(usr) + . = TRUE + if("updating") + updating = !updating + . = TRUE + if("globalmode") + global_mode = !global_mode + . = TRUE diff --git a/code/datums/components/killerqueen.dm b/code/datums/components/killerqueen.dm new file mode 100644 index 0000000000..1c660d0a87 --- /dev/null +++ b/code/datums/components/killerqueen.dm @@ -0,0 +1,91 @@ +/** + * KILLER QUEEN + * + * Simple contact bomb component + * Blows up the first person to touch it. + */ +/datum/component/killerqueen + can_transfer = TRUE + /// strength of explosion on the touch-er. 0 to disable. usually only used if the normal explosion is disabled (this is the default). + var/ex_strength = EXPLODE_HEAVY + /// callback to invoke with (parent, victim) before standard detonation - useful for losing a reference to this component or implementing custom behavior. return FALSE to prevent explosion. + var/datum/callback/pre_explode + /// callback to invoke with (parent) when deleting without an explosion + var/datum/callback/failure + /// did we explode + var/exploded = FALSE + /// examine message + var/examine_message + /// light explosion radius + var/light = 0 + /// heavy explosion radius + var/heavy = 0 + /// dev explosion radius + var/dev = 0 + /// flame explosion radius + var/flame = 0 + /// only triggered by living mobs + var/living_only = TRUE + + +/datum/component/killerqueen/Initialize(ex_strength = EXPLODE_HEAVY, datum/callback/pre_explode, datum/callback/failure, examine_message, light = 0, heavy = 0, dev = 0, flame = 0, living_only = TRUE) + . = ..() + if(. & COMPONENT_INCOMPATIBLE) + return + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + src.ex_strength = ex_strength + src.pre_explode = pre_explode + src.failure = failure + src.examine_message = examine_message + src.light = light + src.heavy = heavy + src.dev = dev + src.flame = flame + src.living_only = living_only + +/datum/component/killerqueen/Destroy() + if(!exploded) + failure?.Invoke(parent) + return ..() + +/datum/component/killerqueen/RegisterWithParent() + . = ..() + RegisterSignal(parent, list(COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_ATTACK_ANIMAL), .proc/touch_detonate) + RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/bump_detonate) + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/attackby_detonate) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_examine) + +/datum/component/killerqueen/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, list(COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW, + COMSIG_MOVABLE_BUMP, COMSIG_PARENT_ATTACKBY, COMSIG_PARENT_EXAMINE)) + +/datum/component/killerqueen/proc/attackby_detonate(datum/source, obj/item/I, mob/user) + detonate(user) + +/datum/component/killerqueen/proc/bump_detonate(datum/source, atom/A) + detonate(A) + +/datum/component/killerqueen/proc/touch_detonate(datum/source, mob/user) + detonate(user) + +/datum/component/killerqueen/proc/on_examine(datum/source, mob/examiner, list/examine_return) + if(examine_message) + examine_return += examine_message + +/datum/component/killerqueen/proc/detonate(atom/victim) + if(!isliving(victim) && living_only) + return + if(pre_explode && !pre_explode.Invoke(parent, victim)) + return + if(ex_strength) + victim.ex_act(ex_strength) + if(light || heavy || dev || flame) + explosion(parent, dev, heavy, light, flame_range = flame) + else + var/turf/T = get_turf(parent) + playsound(T, 'sound/effects/explosion2.ogg', 200, 1) + new /obj/effect/temp_visual/explosion(T) + exploded = TRUE + qdel(src) diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm index 51dc4ee8f7..7adc634621 100644 --- a/code/datums/components/material_container.dm +++ b/code/datums/components/material_container.dm @@ -105,7 +105,7 @@ /// Proc specifically for inserting items, returns the amount of materials entered. /datum/component/material_container/proc/insert_item(obj/item/I, var/multiplier = 1, stack_amt) - if(!I) + if(QDELETED(I)) return FALSE multiplier = CEILING(multiplier, 0.01) diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 90fea9ec8a..87bc681651 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -307,6 +307,10 @@ /datum/component/mood/proc/HandleNutrition(mob/living/L) + if(isethereal(L)) + HandleCharge(L) + if(HAS_TRAIT(L, TRAIT_NOHUNGER)) + return FALSE //no mood events for nutrition switch(L.nutrition) if(NUTRITION_LEVEL_FULL to INFINITY) add_event(null, "nutrition", /datum/mood_event/fat) @@ -321,6 +325,22 @@ if(0 to NUTRITION_LEVEL_STARVING) add_event(null, "nutrition", /datum/mood_event/starving) +/datum/component/mood/proc/HandleCharge(mob/living/carbon/human/H) + var/datum/species/ethereal/E = H.dna.species + switch(E.get_charge(H)) + if(ETHEREAL_CHARGE_NONE to ETHEREAL_CHARGE_LOWPOWER) + add_event(null, "charge", /datum/mood_event/decharged) + if(ETHEREAL_CHARGE_LOWPOWER to ETHEREAL_CHARGE_NORMAL) + add_event(null, "charge", /datum/mood_event/lowpower) + if(ETHEREAL_CHARGE_NORMAL to ETHEREAL_CHARGE_ALMOSTFULL) + clear_event(null, "charge") + if(ETHEREAL_CHARGE_ALMOSTFULL to ETHEREAL_CHARGE_FULL) + add_event(null, "charge", /datum/mood_event/charged) + if(ETHEREAL_CHARGE_FULL to ETHEREAL_CHARGE_OVERLOAD) + add_event(null, "charge", /datum/mood_event/overcharged) + if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS) + add_event(null, "charge", /datum/mood_event/supercharged) + /datum/component/mood/proc/update_beauty(area/A) if(A.outdoors) //if we're outside, we don't care. clear_event(null, "area_beauty") diff --git a/code/datums/components/omen.dm b/code/datums/components/omen.dm new file mode 100644 index 0000000000..3ea7677710 --- /dev/null +++ b/code/datums/components/omen.dm @@ -0,0 +1,74 @@ +/** + * omen.dm: For when you want someone to have a really bad day + * + * When you attach an omen component to someone, they start running the risk of all sorts of bad environmental injuries, like nearby vending machines randomly falling on you, + * or hitting your head really hard when you slip and fall, or... well, for now those two are all I have. More will come. + * + * Omens are removed once the victim is either maimed by one of the possible injuries, or if they receive a blessing (read: bashing with a bible) from the chaplain. + */ +/datum/component/omen + dupe_mode = COMPONENT_DUPE_UNIQUE + + /// Whatever's causing the omen, if there is one. Destroying the vessel won't stop the omen, but we destroy the vessel (if one exists) upon the omen ending + var/obj/vessel + +/datum/component/omen/Initialize(silent=FALSE, vessel) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + var/mob/person = parent + if(!silent) + to_chat(person, "You get a bad feeling...") + src.vessel = vessel + +/datum/component/omen/Destroy(force, silent) + if(vessel) + vessel.visible_message("[vessel] burns up in a sinister flash, taking an evil energy with it...") + vessel = null + return ..() + +/datum/component/omen/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/check_accident) + RegisterSignal(parent, COMSIG_LIVING_STATUS_KNOCKDOWN, .proc/check_slip) + RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/check_bless) + +/datum/component/omen/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_LIVING_STATUS_KNOCKDOWN, COMSIG_MOVABLE_MOVED, COMSIG_ADD_MOOD_EVENT)) + +/** + * check_accident() is called each step we take + * + * While we're walking around, roll to see if there's any environmental hazards (currently only vending machines) on one of the adjacent tiles we can trigger. + * We do the prob() at the beginning to A. add some tension for /when/ it will strike, and B. (more importantly) ameliorate the fact that we're checking up to 5 turfs's contents each time + */ +/datum/component/omen/proc/check_accident(atom/movable/our_guy) + if(!prob(15)) + return + for(var/t in get_adjacent_open_turfs(our_guy)) + var/turf/the_turf = t + for(var/obj/machinery/vending/darth_vendor in the_turf) + if(darth_vendor.tiltable) + darth_vendor.tilt(our_guy) + qdel(src) + return + +/// If we get knocked down, see if we have a really bad slip and bash our head hard +/datum/component/omen/proc/check_slip(mob/living/our_guy, amount) + if(amount <= 0 || prob(50)) // 50% chance to bonk our head + return + + var/obj/item/bodypart/the_head = our_guy.get_bodypart(BODY_ZONE_HEAD) + if(!the_head) + return + + playsound(get_turf(our_guy), "sound/effects/tableheadsmash.ogg", 90, TRUE) + our_guy.visible_message("[our_guy] hits [our_guy.p_their()] head really badly falling down!", "You hit your head really badly falling down!") + the_head.receive_damage(75) + our_guy.adjustOrganLoss(ORGAN_SLOT_BRAIN, 100) + qdel(src) + +/// Hijack the mood system to see if we get the blessing mood event to cancel the omen +/datum/component/omen/proc/check_bless(mob/living/our_guy, category) + if(category != "blessing") + return + to_chat(our_guy, "You feel a horrible omen lifted off your shoulders!") + qdel(src) diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index 938d9f5f56..6a1028cc65 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -1,3 +1,8 @@ +// the following defines are used for [/datum/component/pellet_cloud/var/list/wound_info_by_part] to store the damage, wound_bonus, and bw_bonus for each bodypart hit +#define CLOUD_POSITION_DAMAGE 1 +#define CLOUD_POSITION_W_BONUS 2 +#define CLOUD_POSITION_BW_BONUS 3 + /* * This component is used when you want to create a bunch of shrapnel or projectiles (say, shrapnel from a fragmentation grenade, or buckshot from a shotgun) from a central point, * without necessarily printing a separate message for every single impact. This component should be instantiated right when you need it (like the moment of firing), then activated @@ -29,7 +34,10 @@ var/list/pellets = list() /// An associated list with the atom hit as the key and how many pellets they've eaten for the value, for printing aggregate messages var/list/targets_hit = list() - /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs()] + + /// Another associated list for hit bodyparts on carbons so we can track how much wounding potential we have for each bodypart + var/list/wound_info_by_part = list() + /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs] var/list/bodies /// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs()] var/list/purple_hearts @@ -64,6 +72,7 @@ /datum/component/pellet_cloud/Destroy(force, silent) purple_hearts = null pellets = null + wound_info_by_part = null targets_hit = null bodies = null return ..() @@ -187,10 +196,26 @@ break ///One of our pellets hit something, record what it was and check if we're done (terminated == num_pellets) -/datum/component/pellet_cloud/proc/pellet_hit(obj/item/projectile/P, atom/movable/firer, atom/target, Angle) +/datum/component/pellet_cloud/proc/pellet_hit(obj/item/projectile/P, atom/movable/firer, atom/target, Angle, hit_zone) pellets -= P terminated++ hits++ + var/obj/item/bodypart/hit_part + if(iscarbon(target) && hit_zone) + var/mob/living/carbon/hit_carbon = target + hit_part = hit_carbon.get_bodypart(hit_zone) + if(hit_part) + target = hit_part + if(P.wound_bonus != CANT_WOUND) // handle wounding + // unfortunately, due to how pellet clouds handle finalizing only after every pellet is accounted for, that also means there might be a short delay in dealing wounds if one pellet goes wide + // while buckshot may reach a target or miss it all in one tick, we also have to account for possible ricochets that may take a bit longer to hit the target + if(isnull(wound_info_by_part[hit_part])) + wound_info_by_part[hit_part] = list(0, 0, 0) + wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE] += P.damage // these account for decay + wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS] += P.wound_bonus + wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS] += P.bare_wound_bonus + P.wound_bonus = CANT_WOUND // actual wounding will be handled aggregate + targets_hit[target]++ if(targets_hit[target] == 1) RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/on_target_qdel, override=TRUE) @@ -231,13 +256,23 @@ for(var/atom/target in targets_hit) var/num_hits = targets_hit[target] UnregisterSignal(target, COMSIG_PARENT_QDELETING) - if(num_hits > 1) - target.visible_message("[target] is hit by [num_hits] [proj_name]s!", null, null, COMBAT_MESSAGE_RANGE, target) - to_chat(target, "You're hit by [num_hits] [proj_name]s!") - else - target.visible_message("[target] is hit by a [proj_name]!", null, null, COMBAT_MESSAGE_RANGE, target) - to_chat(target, "You're hit by a [proj_name]!") + var/obj/item/bodypart/hit_part + if(isbodypart(target)) + hit_part = target + target = hit_part.owner + var/damage_dealt = wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE] + var/w_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS] + var/bw_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS] + var/wound_type = (initial(P.damage_type) == BRUTE) ? WOUND_BLUNT : WOUND_BURN // sharpness is handled in the wound rolling + wound_info_by_part[hit_part] = null + hit_part.painless_wound_roll(wound_type, damage_dealt, w_bonus, bw_bonus, initial(P.sharpness)) + if(num_hits > 1) + target.visible_message("[target] is hit by [num_hits] [proj_name]s[hit_part ? " in the [hit_part.name]" : ""]!", null, null, COMBAT_MESSAGE_RANGE, target) + to_chat(target, "You're hit by [num_hits] [proj_name]s[hit_part ? " in the [hit_part.name]" : ""]!") + else + target.visible_message("[target] is hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!", null, null, COMBAT_MESSAGE_RANGE, target) + to_chat(target, "You're hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!") UnregisterSignal(parent, COMSIG_PARENT_PREQDELETED) if(queued_delete) qdel(parent) @@ -281,3 +316,7 @@ targets_hit -= target bodies -= target purple_hearts -= target + +#undef CLOUD_POSITION_DAMAGE +#undef CLOUD_POSITION_W_BONUS +#undef CLOUD_POSITION_BW_BONUS diff --git a/code/datums/components/plumbing/_plumbing.dm b/code/datums/components/plumbing/_plumbing.dm new file mode 100644 index 0000000000..6592e41103 --- /dev/null +++ b/code/datums/components/plumbing/_plumbing.dm @@ -0,0 +1,215 @@ +/datum/component/plumbing + ///Index with "1" = /datum/ductnet/theductpointingnorth etc. "1" being the num2text from NORTH define + var/list/datum/ductnet/ducts = list() + ///shortcut to our parents' reagent holder + var/datum/reagents/reagents + ///TRUE if we wanna add proper pipe outless under our parent object. this is pretty good if i may so so myself + var/use_overlays = TRUE + ///We can't just cut all of the parents' overlays, so we'll track them here + var/list/image/ducterlays + ///directions in wich we act as a supplier + var/supply_connects + ///direction in wich we act as a demander + var/demand_connects + ///FALSE to pretty much just not exist in the plumbing world so we can be moved, TRUE to go plumbo mode + var/active = FALSE + ///if TRUE connects will spin with the parent object visually and codually, so you can have it work in any direction. FALSE if you want it to be static + var/turn_connects = TRUE + +/datum/component/plumbing/Initialize(start=TRUE, _turn_connects=TRUE) //turn_connects for wheter or not we spin with the object to change our pipes + if(parent && !istype(parent, /atom/movable)) + return COMPONENT_INCOMPATIBLE + var/atom/movable/AM = parent + if(!AM.reagents) + return COMPONENT_INCOMPATIBLE + reagents = AM.reagents + turn_connects = _turn_connects + + RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED,COMSIG_PARENT_PREQDELETED), .proc/disable) + RegisterSignal(parent, list(COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH), .proc/toggle_active) + + if(start) + enable() + + if(use_overlays) + create_overlays() + +/datum/component/plumbing/process() + if(!demand_connects || !reagents) + STOP_PROCESSING(SSfluids, src) + return + if(reagents.total_volume < reagents.maximum_volume) + for(var/D in GLOB.cardinals) + if(D & demand_connects) + send_request(D) +///Can we be added to the ductnet? +/datum/component/plumbing/proc/can_add(datum/ductnet/D, dir) + if(!active) + return + if(!dir || !D) + return FALSE + if(num2text(dir) in ducts) + return FALSE + + return TRUE +///called from in process(). only calls process_request(), but can be overwritten for children with special behaviour +/datum/component/plumbing/proc/send_request(dir) + process_request(amount = MACHINE_REAGENT_TRANSFER, reagent = null, dir = dir) +///check who can give us what we want, and how many each of them will give us +/datum/component/plumbing/proc/process_request(amount, reagent, dir) + var/list/valid_suppliers = list() + var/datum/ductnet/net + if(!ducts.Find(num2text(dir))) + return + net = ducts[num2text(dir)] + for(var/A in net.suppliers) + var/datum/component/plumbing/supplier = A + if(supplier.can_give(amount, reagent, net)) + valid_suppliers += supplier + for(var/A in valid_suppliers) + var/datum/component/plumbing/give = A + give.transfer_to(src, amount / valid_suppliers.len, reagent, net) +///returns TRUE when they can give the specified amount and reagent. called by process request +/datum/component/plumbing/proc/can_give(amount, reagent, datum/ductnet/net) + if(amount <= 0) + return + + if(reagent) //only asked for one type of reagent + for(var/A in reagents.reagent_list) + var/datum/reagent/R = A + if(R.type == reagent) + return TRUE + else if(reagents.total_volume > 0) //take whatever + return TRUE +///this is where the reagent is actually transferred and is thus the finish point of our process() +/datum/component/plumbing/proc/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) + if(!reagents || !target || !target.reagents) + return FALSE + if(reagent) + reagents.trans_id_to(target.parent, reagent, amount) + else + reagents.trans_to(target.parent, amount) +///We create our luxurious piping overlays/underlays, to indicate where we do what. only called once if use_overlays = TRUE in Initialize() +/datum/component/plumbing/proc/create_overlays() + var/atom/movable/AM = parent + for(var/image/I in ducterlays) + AM.overlays.Remove(I) + qdel(I) + ducterlays = list() + for(var/D in GLOB.cardinals) + var/color + var/direction + if(D & demand_connects) + color = "red" //red because red is mean and it takes + else if(D & supply_connects) + color = "blue" //blue is nice and gives + else + continue + var/image/I + if(turn_connects) + switch(D) + if(NORTH) + direction = "north" + if(SOUTH) + direction = "south" + if(EAST) + direction = "east" + if(WEST) + direction = "west" + I = image('icons/obj/plumbing/plumbers.dmi', "[direction]-[color]", layer = AM.layer - 1) + else + I = image('icons/obj/plumbing/plumbers.dmi', color, layer = AM.layer - 1) //color is not color as in the var, it's just the name + I.dir = D + AM.add_overlay(I) + ducterlays += I +///we stop acting like a plumbing thing and disconnect if we are, so we can safely be moved and stuff +/datum/component/plumbing/proc/disable() + if(!active) + return + STOP_PROCESSING(SSfluids, src) + for(var/A in ducts) + var/datum/ductnet/D = ducts[A] + D.remove_plumber(src) + active = FALSE + for(var/D in GLOB.cardinals) + if(D & (demand_connects | supply_connects)) + for(var/obj/machinery/duct/duct in get_step(parent, D)) + duct.attempt_connect() + +///settle wherever we are, and start behaving like a piece of plumbing +/datum/component/plumbing/proc/enable() + if(active) + return + update_dir() + active = TRUE + var/atom/movable/AM = parent + for(var/obj/machinery/duct/D in AM.loc) //Destroy any ducts under us. Ducts also self destruct if placed under a plumbing machine. machines disable when they get moved + if(D.anchored) //that should cover everything + D.disconnect_duct() + + if(demand_connects) + START_PROCESSING(SSfluids, src) + + for(var/D in GLOB.cardinals) + if(D & (demand_connects | supply_connects)) + for(var/atom/movable/A in get_step(parent, D)) + if(istype(A, /obj/machinery/duct)) + var/obj/machinery/duct/duct = A + duct.attempt_connect() + else + var/datum/component/plumbing/P = A.GetComponent(/datum/component/plumbing) + if(P) + direct_connect(P, D) + +/// Toggle our machinery on or off. This is called by a hook from default_unfasten_wrench with anchored as only param, so we dont have to copypaste this on every object that can move +/datum/component/plumbing/proc/toggle_active(obj/O, new_state) + if(new_state) + enable() + else + disable() +/** We update our connects only when we settle down by taking our current and original direction to find our new connects +* If someone wants it to fucking spin while connected to something go actually knock yourself out +*/ +/datum/component/plumbing/proc/update_dir() + if(!turn_connects) + return + var/atom/movable/AM = parent + var/new_demand_connects + var/new_supply_connects + var/new_dir = AM.dir + var/angle = 180 - dir2angle(new_dir) + if(new_dir == SOUTH) + demand_connects = initial(demand_connects) + supply_connects = initial(supply_connects) + else + for(var/D in GLOB.cardinals) + if(D & initial(demand_connects)) + new_demand_connects += turn(D, angle) + if(D & initial(supply_connects)) + new_supply_connects += turn(D, angle) + demand_connects = new_demand_connects + supply_connects = new_supply_connects +///Give the direction of a pipe, and it'll return wich direction it originally was when it's object pointed SOUTH +/datum/component/plumbing/proc/get_original_direction(dir) + var/atom/movable/AM = parent + return turn(dir, dir2angle(AM.dir) - 180) +//special case in-case we want to connect directly with another machine without a duct +/datum/component/plumbing/proc/direct_connect(datum/component/plumbing/P, dir) + if(!P.active) + return + var/opposite_dir = turn(dir, 180) + if(P.demand_connects & opposite_dir && supply_connects & dir || P.supply_connects & opposite_dir && demand_connects & dir) //make sure we arent connecting two supplies or demands + var/datum/ductnet/net = new() + net.add_plumber(src, dir) + net.add_plumber(P, opposite_dir) + +///has one pipe input that only takes, example is manual output pipe +/datum/component/plumbing/simple_demand + demand_connects = NORTH +///has one pipe output that only supplies. example is liquid pump and manual input pipe +/datum/component/plumbing/simple_supply + supply_connects = NORTH +///input and output, like a holding tank +/datum/component/plumbing/tank + demand_connects = WEST + supply_connects = EAST diff --git a/code/datums/components/plumbing/chemical_acclimator.dm b/code/datums/components/plumbing/chemical_acclimator.dm new file mode 100644 index 0000000000..1cbe6ff017 --- /dev/null +++ b/code/datums/components/plumbing/chemical_acclimator.dm @@ -0,0 +1,21 @@ +/datum/component/plumbing/acclimator + demand_connects = WEST + supply_connects = EAST + var/obj/machinery/plumbing/acclimator/AC + +/datum/component/plumbing/acclimator/Initialize(start=TRUE, _turn_connects=TRUE) + . = ..() + if(!istype(parent, /obj/machinery/plumbing/acclimator)) + return COMPONENT_INCOMPATIBLE + AC = parent + +/datum/component/plumbing/acclimator/can_give(amount, reagent) + . = ..() + if(. && AC.emptying) + return TRUE + return FALSE +///We're overriding process and not send_request, because all process does is do the requests, so we might aswell cut out the middle man and save some code from running +/datum/component/plumbing/acclimator/process() + if(AC.emptying) + return + . = ..() diff --git a/code/datums/components/plumbing/filter.dm b/code/datums/components/plumbing/filter.dm new file mode 100644 index 0000000000..76b76323c5 --- /dev/null +++ b/code/datums/components/plumbing/filter.dm @@ -0,0 +1,59 @@ +///The magical plumbing component used by the chemical filters. The different supply connects behave differently depending on the filters set on the chemical filter +/datum/component/plumbing/filter + demand_connects = NORTH + supply_connects = SOUTH | EAST | WEST //SOUTH is straight, EAST is left and WEST is right. We look from the perspective of the insert + +/datum/component/plumbing/filter/Initialize() + . = ..() + if(!istype(parent, /obj/machinery/plumbing/filter)) + return COMPONENT_INCOMPATIBLE + +/datum/component/plumbing/filter/can_give(amount, reagent, datum/ductnet/net) + . = ..() + if(.) + var/direction + for(var/A in ducts) + if(ducts[A] == net) + direction = get_original_direction(text2num(A)) //we need it relative to the direction, so filters don't change when we turn the filter + break + if(!direction) + return FALSE + if(reagent) + if(!can_give_in_direction(direction, reagent)) + return FALSE + +/datum/component/plumbing/filter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) + if(!reagents || !target || !target.reagents) + return FALSE + var/direction + for(var/A in ducts) + if(ducts[A] == net) + direction = get_original_direction(text2num(A)) + break + if(reagent) + reagents.trans_id_to(target.parent, reagent, amount) + else + for(var/A in reagents.reagent_list) + var/datum/reagent/R = A + if(!can_give_in_direction(direction, R.type)) + continue + var/new_amount + if(R.volume < amount) + new_amount = amount - R.volume + reagents.trans_id_to(target.parent, R.type, amount) + amount = new_amount + if(amount <= 0) + break +///We check if the direction and reagent are valid to give. Needed for filters since different outputs have different behaviours +/datum/component/plumbing/filter/proc/can_give_in_direction(dir, reagent) + var/obj/machinery/plumbing/filter/F = parent + switch(dir) + if(SOUTH) //straight + if(!F.left.Find(reagent) && !F.right.Find(reagent)) + return TRUE + if(WEST) //right + if(F.right.Find(reagent)) + return TRUE + if(EAST) //left + if(F.left.Find(reagent)) + return TRUE diff --git a/code/datums/components/plumbing/reaction_chamber.dm b/code/datums/components/plumbing/reaction_chamber.dm new file mode 100644 index 0000000000..90f4e621da --- /dev/null +++ b/code/datums/components/plumbing/reaction_chamber.dm @@ -0,0 +1,38 @@ +/datum/component/plumbing/reaction_chamber + demand_connects = WEST + supply_connects = EAST + +/datum/component/plumbing/reaction_chamber/Initialize(start=TRUE, _turn_connects=TRUE) + . = ..() + if(!istype(parent, /obj/machinery/plumbing/reaction_chamber)) + return COMPONENT_INCOMPATIBLE + +/datum/component/plumbing/reaction_chamber/can_give(amount, reagent, datum/ductnet/net) + . = ..() + var/obj/machinery/plumbing/reaction_chamber/RC = parent + if(!. || !RC.emptying) + return FALSE + +/datum/component/plumbing/reaction_chamber/send_request(dir) + var/obj/machinery/plumbing/reaction_chamber/RC = parent + if(RC.emptying || !LAZYLEN(RC.required_reagents)) + return + for(var/RT in RC.required_reagents) + var/has_reagent = FALSE + for(var/A in reagents.reagent_list) + var/datum/reagent/RD = A + if(RT == RD.type) + has_reagent = TRUE + if(RD.volume < RC.required_reagents[RT]) + process_request(min(RC.required_reagents[RT] - RD.volume, MACHINE_REAGENT_TRANSFER) , RT, dir) + return + if(!has_reagent) + process_request(min(RC.required_reagents[RT], MACHINE_REAGENT_TRANSFER), RT, dir) + return + + RC.reagent_flags &= ~NO_REACT + reagents.handle_reactions() + + RC.emptying = TRUE //If we move this up, it'll instantly get turned off since any reaction always sets the reagent_total to zero. Other option is make the reaction update + //everything for every chemical removed, wich isn't a good option either. + RC.on_reagent_change() //We need to check it now, because some reactions leave nothing left. diff --git a/code/datums/components/plumbing/splitter.dm b/code/datums/components/plumbing/splitter.dm new file mode 100644 index 0000000000..7194e8803b --- /dev/null +++ b/code/datums/components/plumbing/splitter.dm @@ -0,0 +1,45 @@ +/datum/component/plumbing/splitter + demand_connects = NORTH + supply_connects = SOUTH | EAST + +/datum/component/plumbing/splitter/Initialize() + . = ..() + if(. && !istype(parent, /obj/machinery/plumbing/splitter)) + return FALSE + +/datum/component/plumbing/splitter/can_give(amount, reagent, datum/ductnet/net) + . = ..() + if(!.) + return + . = FALSE + var/direction + for(var/A in ducts) + if(ducts[A] == net) + direction = get_original_direction(text2num(A)) + break + var/obj/machinery/plumbing/splitter/S = parent + switch(direction) + if(SOUTH) + if(S.turn_straight && S.transfer_straight <= amount) + S.turn_straight = FALSE + return TRUE + if(EAST) + if(!S.turn_straight && S.transfer_side <= amount) + S.turn_straight = TRUE + return TRUE + +/datum/component/plumbing/splitter/transfer_to(datum/component/plumbing/target, amount, reagent, datum/ductnet/net) + var/direction + for(var/A in ducts) + if(ducts[A] == net) + direction = get_original_direction(text2num(A)) + break + var/obj/machinery/plumbing/splitter/S = parent + switch(direction) + if(SOUTH) + if(amount >= S.transfer_straight) + amount = S.transfer_straight + if(EAST) + if(amount >= S.transfer_side) + amount = S.transfer_side + . = ..() diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm index decc2dd65c..8afa4353b2 100644 --- a/code/datums/components/radioactive.dm +++ b/code/datums/components/radioactive.dm @@ -29,10 +29,18 @@ if(strength > RAD_MINIMUM_CONTAMINATION) SSradiation.warn(src) + //Let's make er glow + //This relies on parent not being a turf or something. IF YOU CHANGE THAT, CHANGE THIS + var/atom/movable/master = parent + master.add_filter("rad_glow", 2, list("type" = "outline", "color" = "#39ff1430", "size" = 2)) + addtimer(CALLBACK(src, .proc/glow_loop, master), rand(1,19))//Things should look uneven + START_PROCESSING(SSradiation, src) /datum/component/radioactive/Destroy() STOP_PROCESSING(SSradiation, src) + var/atom/movable/master = parent + master.remove_filter("rad_glow") return ..() /datum/component/radioactive/process() @@ -46,6 +54,13 @@ if(strength <= RAD_BACKGROUND_RADIATION) return PROCESS_KILL + +/datum/component/radioactive/proc/glow_loop(atom/movable/master) + var/filter = master.get_filter("rad_glow") + if(filter) + animate(filter, alpha = 110, time = 15, loop = -1) + animate(alpha = 40, time = 25) + /datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, _strength, _source, _half_life, _can_contaminate) if(!i_am_original) return @@ -69,8 +84,9 @@ out += "[out ? " and it " : "[master] "]seems to be glowing a bit." if(RAD_AMOUNT_HIGH to INFINITY) //At this level the object can contaminate other objects out += "[out ? " and it " : "[master] "]hurts to look at." - else - out += "." + if(!LAZYLEN(out)) + return + out += "." examine_list += out.Join() /datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user) diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm index f5da669c3a..129faabdb7 100644 --- a/code/datums/components/rotation.dm +++ b/code/datums/components/rotation.dm @@ -98,16 +98,16 @@ /datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction) if(can_be_rotated) - if(!can_be_rotated.Invoke(user, default_rotation_direction)) + if(!can_be_rotated.Invoke(user, rotation)) return else - if(!default_can_be_rotated(user, default_rotation_direction)) + if(!default_can_be_rotated(user, rotation)) return if(can_user_rotate) - if(!can_user_rotate.Invoke(user, default_rotation_direction)) + if(!can_user_rotate.Invoke(user, rotation)) return else - if(!default_can_user_rotate(user, default_rotation_direction)) + if(!default_can_user_rotate(user, rotation)) return BaseRot(user, rotation) return TRUE diff --git a/code/datums/components/shielded.dm b/code/datums/components/shielded.dm index 2052e57f49..3cf70e80ef 100644 --- a/code/datums/components/shielded.dm +++ b/code/datums/components/shielded.dm @@ -14,6 +14,7 @@ var/mob/living/holder //who is currently benefiting from the shield. var/dissipating = FALSE //Is this shield meant to dissipate over time instead of recharging. var/del_on_overload = FALSE //will delete itself once it has no charges left. + var/cached_vis_overlay //text identifier of the visual overlay. /datum/component/shielded/Initialize(current, max = 3, delay = 20 SECONDS, rate = 1, slots, state = "shield-old", broken, \ sound = 'sound/magic/charge.ogg', end_sound = 'sound/machines/ding.ogg', diss = FALSE, del_overload = FALSE) @@ -47,9 +48,8 @@ holder = L var/to_add = charges >= 1 ? shield_state : broken_state if(to_add) - var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add) - M.layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01 - holder.add_overlay(M, TRUE) + var/layer = (L.layer > MOB_LAYER ? L.layer : MOB_LAYER) + 0.01 + SSvis_overlays.add_vis_overlay(L, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, L.dir) /datum/component/shielded/UnregisterFromParent() . = ..() @@ -57,9 +57,9 @@ UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK,COMSIG_ITEM_CHECK_BLOCK,COMSIG_ITEM_EQUIPPED,COMSIG_ITEM_DROPPED)) if(holder) UnregisterSignal(holder, list(COMSIG_LIVING_RUN_BLOCK, COMSIG_LIVING_GET_BLOCKING_ITEMS)) - var/to_remove = charges >= 1 ? shield_state : broken_state - if(to_remove) - holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE) + if(cached_vis_overlay) + SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay) + cached_vis_overlay = null holder = null /datum/component/shielded/process() @@ -80,7 +80,7 @@ holder.visible_message("[holder]'s shield overloads!") qdel(src) return - if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)) + if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))) update_shield_overlay(charges < 1) /datum/component/shielded/proc/adjust_charges(amount) @@ -93,20 +93,19 @@ holder.visible_message("[holder]'s shield overloads!") qdel(src) return - if(holder && (old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1)) + if(holder && ((old_charges < 1 && charges >= 1) || (!del_on_overload && old_charges >= 1 && charges < 1))) update_shield_overlay(charges < 1) /datum/component/shielded/proc/update_shield_overlay(broken) if(!holder) return - var/to_remove = broken ? shield_state : broken_state var/to_add = broken ? broken_state : shield_state - if(to_remove) - holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE) + if(cached_vis_overlay) + SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay) + cached_vis_overlay = null if(to_add) - var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add) - M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01 - holder.add_overlay(M, TRUE) + var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01 + SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir) /datum/component/shielded/proc/on_equip(obj/item/source, mob/living/equipper, slot) if(!(accepted_slots & slotdefine2slotbit(slot))) @@ -117,17 +116,16 @@ RegisterSignal(equipper, COMSIG_LIVING_GET_BLOCKING_ITEMS, .proc/include_shield) var/to_add = charges >= 1 ? shield_state : broken_state if(to_add) - var/mutable_appearance/M = mutable_appearance('icons/effects/effects.dmi', to_add) - M.layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01 - equipper.add_overlay(M, TRUE) + var/layer = (holder.layer > MOB_LAYER ? holder.layer : MOB_LAYER) + 0.01 + cached_vis_overlay = SSvis_overlays.add_vis_overlay(holder, 'icons/effects/effects.dmi', to_add, layer, GAME_PLANE, holder.dir) /datum/component/shielded/proc/on_drop(obj/item/source, mob/dropper) if(holder == dropper) UnregisterSignal(holder, COMSIG_LIVING_GET_BLOCKING_ITEMS) UnregisterSignal(parent, list(COMSIG_ITEM_RUN_BLOCK, COMSIG_ITEM_CHECK_BLOCK)) - var/to_remove = charges >= 1 ? shield_state : broken_state - if(to_remove) - holder.cut_overlay(mutable_appearance('icons/effects/effects.dmi', to_remove), TRUE) + if(cached_vis_overlay) + SSvis_overlays.remove_vis_overlay(holder, cached_vis_overlay) + cached_vis_overlay = null holder = null /datum/component/shielded/proc/include_shield(mob/source, list/items) diff --git a/code/datums/components/spawner.dm b/code/datums/components/spawner.dm index fe86b60375..27bf4a5986 100644 --- a/code/datums/components/spawner.dm +++ b/code/datums/components/spawner.dm @@ -8,6 +8,8 @@ var/list/faction = list("mining") /datum/component/spawner/Initialize(_mob_types, _spawn_time, _faction, _spawn_text, _max_mobs) + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE if(_spawn_time) spawn_time=_spawn_time if(_mob_types) @@ -19,20 +21,25 @@ if(_max_mobs) max_mobs=_max_mobs - RegisterSignal(parent, list(COMSIG_PARENT_QDELETING), .proc/stop_spawning) + RegisterSignal(parent, COMSIG_PARENT_QDELETING, .proc/stop_spawning) + RegisterSignal(parent, COMSIG_OBJ_ATTACK_GENERIC, .proc/on_attack_generic) START_PROCESSING(SSprocessing, src) /datum/component/spawner/process() try_spawn_mob() - -/datum/component/spawner/proc/stop_spawning(force, hint) +/datum/component/spawner/proc/stop_spawning(datum/source, force, hint) STOP_PROCESSING(SSprocessing, src) for(var/mob/living/simple_animal/L in spawned_mobs) if(L.nest == src) L.nest = null spawned_mobs = null +// Stopping clientless simple mobs' from indiscriminately bashing their own spawners due DestroySurroundings() et similars. +/datum/component/spawner/proc/on_attack_generic(datum/source, mob/user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration) + if(!user.client && ((user.faction & faction) || (user in spawned_mobs))) + return COMPONENT_STOP_GENERIC_ATTACK + /datum/component/spawner/proc/try_spawn_mob() var/atom/P = parent if(spawned_mobs.len >= max_mobs) diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index 792222b27b..df44aef4de 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -11,6 +11,13 @@ // This is to stop squeak spam from inhand usage var/last_use = 0 var/use_delay = 20 + + // squeak cooldowns + var/last_squeak = 0 + var/squeak_delay = 5 + + /// chance we'll be stopped from squeaking by cooldown when something crossing us squeaks + var/cross_squeak_delay_chance = 33 // about 3 things can squeak at a time /datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) if(!isatom(parent)) @@ -19,6 +26,7 @@ if(ismovable(parent)) RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak) RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ITEM_WEARERCROSSED), .proc/play_squeak_crossed) + RegisterSignal(parent, COMSIG_CROSS_SQUEAKED, .proc/delay_squeak) RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react) if(isitem(parent)) RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak) @@ -39,20 +47,28 @@ use_delay = use_delay_override /datum/component/squeak/proc/play_squeak() + do_play_squeak() + +/datum/component/squeak/proc/do_play_squeak(bypass_cooldown = FALSE) + if(!bypass_cooldown && ((last_squeak + squeak_delay) >= world.time)) + return FALSE if(prob(squeak_chance)) if(!override_squeak_sounds) playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) else playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1) + last_squeak = world.time + return TRUE + return FALSE /datum/component/squeak/proc/step_squeak() if(steps > step_delay) - play_squeak() + do_play_squeak(TRUE) steps = 0 else steps++ -/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM) +/datum/component/squeak/proc/play_squeak_crossed(datum/source, atom/movable/AM) if(isitem(AM)) var/obj/item/I = AM if(I.item_flags & ABSTRACT) @@ -63,13 +79,18 @@ return var/atom/current_parent = parent if(isturf(current_parent.loc)) - play_squeak() + if(do_play_squeak()) + SEND_SIGNAL(AM, COMSIG_CROSS_SQUEAKED) /datum/component/squeak/proc/use_squeak() if(last_use + use_delay < world.time) last_use = world.time play_squeak() +/datum/component/squeak/proc/delay_squeak() + if(prob(cross_squeak_delay_chance)) + last_squeak = world.time + /datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot) RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE) diff --git a/code/datums/components/storage/concrete/bag_of_holding.dm b/code/datums/components/storage/concrete/bag_of_holding.dm index 28b06b4867..e19edc89d8 100644 --- a/code/datums/components/storage/concrete/bag_of_holding.dm +++ b/code/datums/components/storage/concrete/bag_of_holding.dm @@ -34,3 +34,8 @@ qdel(A) return . = ..() + +/datum/component/storage/concrete/bluespace/bag_of_holding/can_be_inserted(obj/item/I, stop_messages = FALSE, mob/M) + if(I.GetComponent(/datum/component/storage/concrete/bluespace/bag_of_holding)) + return TRUE + return ..() diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm index bd12ecc092..a5f9271f4b 100644 --- a/code/datums/components/tackle.dm +++ b/code/datums/components/tackle.dm @@ -62,6 +62,7 @@ ///Store the thrownthing datum for later use /datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/TT) tackle = TT + tackle.thrower = user ///See if we can tackle or not. If we can, leap! /datum/component/tackler/proc/checkTackle(mob/living/carbon/user, atom/A, params) diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm new file mode 100644 index 0000000000..bcbf979101 --- /dev/null +++ b/code/datums/components/twohanded.dm @@ -0,0 +1,313 @@ +/** + * Two Handed Component + * + * When applied to an item it will make it two handed + * + */ +/datum/component/two_handed + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS // Only one of the component can exist on an item + var/wielded = FALSE /// Are we holding the two handed item properly + var/force_multiplier = 0 /// The multiplier applied to force when wielded, does not work with force_wielded, and force_unwielded + var/force_wielded = 0 /// The force of the item when weilded + var/force_unwielded = 0 /// The force of the item when unweilded + var/wieldsound = FALSE /// Play sound when wielded + var/unwieldsound = FALSE /// Play sound when unwielded + var/attacksound = FALSE /// Play sound on attack when wielded + var/require_twohands = FALSE /// Does it have to be held in both hands + var/icon_wielded = FALSE /// The icon that will be used when wielded + var/obj/item/offhand/offhand_item = null /// Reference to the offhand created for the item + var/sharpened_increase = 0 /// The amount of increase recived from sharpening the item + +/** + * Two Handed component + * + * vars: + * * require_twohands (optional) Does the item need both hands to be carried + * * wieldsound (optional) The sound to play when wielded + * * unwieldsound (optional) The sound to play when unwielded + * * attacksound (optional) The sound to play when wielded and attacking + * * force_multiplier (optional) The force multiplier when wielded, do not use with force_wielded, and force_unwielded + * * force_wielded (optional) The force setting when the item is wielded, do not use with force_multiplier + * * force_unwielded (optional) The force setting when the item is unwielded, do not use with force_multiplier + * * icon_wielded (optional) The icon to be used when wielded + */ +/datum/component/two_handed/Initialize(require_twohands=FALSE, wieldsound=FALSE, unwieldsound=FALSE, attacksound=FALSE, \ + force_multiplier=0, force_wielded=0, force_unwielded=0, icon_wielded=FALSE) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.require_twohands = require_twohands + src.wieldsound = wieldsound + src.unwieldsound = unwieldsound + src.attacksound = attacksound + src.force_multiplier = force_multiplier + src.force_wielded = force_wielded + src.force_unwielded = force_unwielded + src.icon_wielded = icon_wielded + +// Inherit the new values passed to the component +/datum/component/two_handed/InheritComponent(datum/component/two_handed/new_comp, original, require_twohands, wieldsound, unwieldsound, \ + force_multiplier, force_wielded, force_unwielded, icon_wielded) + if(!original) + return + if(require_twohands) + src.require_twohands = require_twohands + if(wieldsound) + src.wieldsound = wieldsound + if(unwieldsound) + src.unwieldsound = unwieldsound + if(attacksound) + src.attacksound = attacksound + if(force_multiplier) + src.force_multiplier = force_multiplier + if(force_wielded) + src.force_wielded = force_wielded + if(force_unwielded) + src.force_unwielded = force_unwielded + if(icon_wielded) + src.icon_wielded = icon_wielded + +// register signals withthe parent item +/datum/component/two_handed/RegisterWithParent() + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop) + RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/on_attack_self) + RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/on_attack) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON, .proc/on_update_icon) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_moved) + RegisterSignal(parent, COMSIG_ITEM_SHARPEN_ACT, .proc/on_sharpen) + +// Remove all siginals registered to the parent item +/datum/component/two_handed/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, + COMSIG_ITEM_DROPPED, + COMSIG_ITEM_ATTACK_SELF, + COMSIG_ITEM_ATTACK, + COMSIG_ATOM_UPDATE_ICON, + COMSIG_MOVABLE_MOVED, + COMSIG_ITEM_SHARPEN_ACT)) + +/// Triggered on equip of the item containing the component +/datum/component/two_handed/proc/on_equip(datum/source, mob/user, slot) + if(require_twohands && slot == SLOT_HANDS) // force equip the item + wield(user) + if(!user.is_holding(parent) && wielded && !require_twohands) + unwield(user) + +/// Triggered on drop of item containing the component +/datum/component/two_handed/proc/on_drop(datum/source, mob/user) + if(require_twohands) + unwield(user, show_message=TRUE) + if(wielded) + unwield(user) + if(source == offhand_item && !QDELETED(src)) + qdel(src) + +/// Triggered on attack self of the item containing the component +/datum/component/two_handed/proc/on_attack_self(datum/source, mob/user) + if(!user.is_holding(parent)) + return //give no quarter to telekinesis powergaemrs (telekinetic wielding will desync the offhand and result in all sorts of bugs so no until someone codes it properly) + if(wielded) + unwield(user) + else + wield(user) + +/** + * Wield the two handed item in both hands + * + * vars: + * * user The mob/living/carbon that is wielding the item + */ +/datum/component/two_handed/proc/wield(mob/living/carbon/user) + if(wielded) + return + if(ismonkey(user)) + to_chat(user, "It's too heavy for you to wield fully.") + return + if(user.get_inactive_held_item()) + if(require_twohands) + to_chat(user, "[parent] is too cumbersome to carry in one hand!") + user.dropItemToGround(parent, force=TRUE) + else + to_chat(user, "You need your other hand to be empty!") + return + if(user.get_num_arms() < 2) + if(require_twohands) + user.dropItemToGround(parent, force=TRUE) + to_chat(user, "You don't have enough intact hands.") + return + + // wield update status + if(SEND_SIGNAL(parent, COMSIG_TWOHANDED_WIELD, user) & COMPONENT_TWOHANDED_BLOCK_WIELD) + return // blocked wield from item + wielded = TRUE + RegisterSignal(user, COMSIG_MOB_SWAP_HANDS, .proc/on_swap_hands) + + // update item stats and name + var/obj/item/parent_item = parent + if(force_multiplier) + parent_item.force *= force_multiplier + else if(force_wielded) + parent_item.force = force_wielded + if(sharpened_increase) + parent_item.force += sharpened_increase + parent_item.name = "[parent_item.name] (Wielded)" + parent_item.update_icon() + + if(iscyborg(user)) + to_chat(user, "You dedicate your module to [parent].") + else + to_chat(user, "You grab [parent] with both hands.") + + // Play sound if one is set + if(wieldsound) + playsound(parent_item.loc, wieldsound, 50, TRUE) + + // Let's reserve the other hand + offhand_item = new(user) + offhand_item.name = "[parent_item.name] - offhand" + offhand_item.desc = "Your second grip on [parent_item]." + offhand_item.wielded = TRUE + RegisterSignal(offhand_item, COMSIG_ITEM_DROPPED, .proc/on_drop) + user.put_in_inactive_hand(offhand_item) + +/** + * Unwield the two handed item + * + * vars: + * * user The mob/living/carbon that is unwielding the item + * * show_message (option) show a message to chat on unwield + */ +/datum/component/two_handed/proc/unwield(mob/living/carbon/user, show_message=TRUE) + if(!wielded || !user) + return + + // wield update status + wielded = FALSE + UnregisterSignal(user, COMSIG_MOB_SWAP_HANDS) + SEND_SIGNAL(parent, COMSIG_TWOHANDED_UNWIELD, user) + + // update item stats + var/obj/item/parent_item = parent + if(sharpened_increase) + parent_item.force -= sharpened_increase + if(force_multiplier) + parent_item.force /= force_multiplier + else if(force_unwielded) + parent_item.force = force_unwielded + + // update the items name to remove the wielded status + var/sf = findtext(parent_item.name, " (Wielded)", -10) // 10 == length(" (Wielded)") + if(sf) + parent_item.name = copytext(parent_item.name, 1, sf) + else + parent_item.name = "[initial(parent_item.name)]" + + // Update icons + parent_item.update_icon() + if(user.get_item_by_slot(ITEM_SLOT_BACK) == parent) + user.update_inv_back() + else + user.update_inv_hands() + + // if the item requires two handed drop the item on unwield + if(require_twohands) + user.dropItemToGround(parent, force=TRUE) + + // Show message if requested + if(show_message) + if(iscyborg(user)) + to_chat(user, "You free up your module.") + else if(require_twohands) + to_chat(user, "You drop [parent].") + else + to_chat(user, "You are now carrying [parent] with one hand.") + + // Play sound if set + if(unwieldsound) + playsound(parent_item.loc, unwieldsound, 50, TRUE) + + // Remove the object in the offhand + if(offhand_item) + UnregisterSignal(offhand_item, COMSIG_ITEM_DROPPED) + qdel(offhand_item) + // Clear any old refrence to an item that should be gone now + offhand_item = null + +/** + * on_attack triggers on attack with the parent item + */ +/datum/component/two_handed/proc/on_attack(obj/item/source, mob/living/target, mob/living/user) + if(wielded && attacksound) + var/obj/item/parent_item = parent + playsound(parent_item.loc, attacksound, 50, TRUE) + +/** + * on_update_icon triggers on call to update parent items icon + * + * Updates the icon using icon_wielded if set + */ +/datum/component/two_handed/proc/on_update_icon(datum/source) + if(icon_wielded && wielded) + var/obj/item/parent_item = parent + if(parent_item) + parent_item.icon_state = icon_wielded + return COMSIG_ATOM_NO_UPDATE_ICON_STATE + +/** + * on_moved Triggers on item moved + */ +/datum/component/two_handed/proc/on_moved(datum/source, mob/user, dir) + unwield(user) + +/** + * on_swap_hands Triggers on swapping hands, blocks swap if the other hand is busy + */ +/datum/component/two_handed/proc/on_swap_hands(mob/user, obj/item/held_item) + if(!held_item) + return + if(held_item == parent) + return COMPONENT_BLOCK_SWAP + +/** + * on_sharpen Triggers on usage of a sharpening stone on the item + */ +/datum/component/two_handed/proc/on_sharpen(obj/item/item, amount, max_amount) + if(!item) + return COMPONENT_BLOCK_SHARPEN_BLOCKED + if(sharpened_increase) + return COMPONENT_BLOCK_SHARPEN_ALREADY + var/wielded_val = 0 + if(force_multiplier) + var/obj/item/parent_item = parent + if(wielded) + wielded_val = parent_item.force + else + wielded_val = parent_item.force * force_multiplier + else + wielded_val = force_wielded + if(wielded_val > max_amount) + return COMPONENT_BLOCK_SHARPEN_MAXED + sharpened_increase = min(amount, (max_amount - wielded_val)) + return COMPONENT_BLOCK_SHARPEN_APPLIED + +/** + * The offhand dummy item for two handed items + * + */ +/obj/item/offhand + name = "offhand" + icon_state = "offhand" + w_class = WEIGHT_CLASS_HUGE + item_flags = ABSTRACT + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + var/wielded = FALSE // Off Hand tracking of wielded status + +/obj/item/offhand/Destroy() + wielded = FALSE + return ..() + +/obj/item/offhand/equipped(mob/user, slot) + . = ..() + if(wielded && !user.is_holding(src) && !QDELETED(src)) + qdel(src) diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index dde8961482..4a9c558d39 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -24,16 +24,17 @@ GLOBAL_LIST_EMPTY(uplinks) var/unlock_note var/unlock_code var/failsafe_code - var/datum/ui_state/checkstate var/compact_mode = FALSE var/debug = FALSE var/saved_player_population = 0 var/list/filters = list() -/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/ui_state/_checkstate, datum/traitor_class/traitor_class) + +/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20, datum/traitor_class/traitor_class) if(!isitem(parent)) return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy) RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/interact) if(istype(parent, /obj/item/implant)) @@ -65,7 +66,6 @@ GLOBAL_LIST_EMPTY(uplinks) active = _enabled gamemode = _gamemode telecrystals = starting_tc - checkstate = _checkstate if(!lockable) active = TRUE locked = FALSE @@ -102,6 +102,15 @@ GLOBAL_LIST_EMPTY(uplinks) return //no hitting everyone/everything just to try to slot tcs in! if(istype(I, /obj/item/stack/telecrystal)) LoadTC(user, I) + if(active) + if(I.GetComponent(/datum/component/uplink)) + var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink) + var/amt = hidden_uplink.telecrystals + hidden_uplink.telecrystals -= amt + src.telecrystals += amt + to_chat(user, "You connect the [I] to your uplink, siphoning [amt] telecrystals before quickly undoing the connection.") + else + return for(var/category in uplink_items) for(var/item in uplink_items[category]) var/datum/uplink_item/UI = uplink_items[category][item] @@ -134,22 +143,20 @@ GLOBAL_LIST_EMPTY(uplinks) // an unlocked uplink blocks also opening the PDA or headset menu return COMPONENT_NO_INTERACT -/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) - state = checkstate ? checkstate : state - active = TRUE - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "uplink", name, 620, 580, master_ui, state) - ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input. - ui.set_style("syndicate") - ui.open() +/datum/component/uplink/ui_state(mob/user) + if(istype(parent, /obj/item/implant/uplink)) + return GLOB.not_incapacitated_state + return GLOB.inventory_state -/datum/component/uplink/ui_host(mob/user) - if(istype(parent, /obj/item/implant)) //implants are like organs, not really located inside mobs codewise. - var/obj/item/implant/I = parent - return I.imp_in - return ..() +/datum/component/uplink/ui_interact(mob/user, datum/tgui/ui) + active = TRUE + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Uplink", name) + // This UI is only ever opened by one person, + // and never is updated outside of user input. + ui.set_autoupdate(FALSE) + ui.open() /datum/component/uplink/ui_data(mob/user) if(!user.mind) @@ -157,8 +164,7 @@ GLOBAL_LIST_EMPTY(uplinks) var/list/data = list() data["telecrystals"] = telecrystals data["lockable"] = lockable - data["compact_mode"] = compact_mode - + data["compactMode"] = compact_mode return data /datum/component/uplink/ui_static_data(mob/user) @@ -179,8 +185,18 @@ GLOBAL_LIST_EMPTY(uplinks) is_inaccessible = FALSE if(is_inaccessible) continue + /* + if(I.restricted_species) //catpeople specfic gloves. + if(ishuman(user)) + var/is_inaccessible = TRUE + var/mob/living/carbon/human/H = user + for(var/F in I.restricted_species) + if(F == H.dna.species.id || debug) + is_inaccessible = FALSE + break if(is_inaccessible) continue + */ cat["items"] += list(list( "name" = I.name, "cost" = I.cost, @@ -192,21 +208,16 @@ GLOBAL_LIST_EMPTY(uplinks) /datum/component/uplink/ui_act(action, params) if(!active) return - switch(action) if("buy") - var/item = params["item"] - + var/item_name = params["name"] var/list/buyable_items = list() for(var/category in uplink_items) buyable_items += uplink_items[category] - - if(item in buyable_items) - var/datum/uplink_item/I = buyable_items[item] - //check to make sure people cannot buy items when the player pop is below the requirement - if(GLOB.joined_player_list.len >= I.player_minimum) - MakePurchase(usr, I) - . = TRUE + if(item_name in buyable_items) + var/datum/uplink_item/I = buyable_items[item_name] + MakePurchase(usr, I) + return TRUE if("lock") active = FALSE locked = TRUE @@ -215,9 +226,10 @@ GLOBAL_LIST_EMPTY(uplinks) SStgui.close_uis(src) if("select") selected_cat = params["category"] + return TRUE if("compact_toggle") compact_mode = !compact_mode - return TRUE + return TRUE /datum/component/uplink/proc/MakePurchase(mob/user, datum/uplink_item/U) if(!istype(U)) @@ -262,12 +274,12 @@ GLOBAL_LIST_EMPTY(uplinks) var/obj/item/pda/master = parent if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code))) if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code))) - failsafe() + failsafe(user) return COMPONENT_STOP_RINGTONE_CHANGE return locked = FALSE interact(null, user) - to_chat(user, "The PDA softly beeps.") + to_chat(user, "The PDA softly beeps.") user << browse(null, "window=pda") master.mode = 0 return COMPONENT_STOP_RINGTONE_CHANGE @@ -279,7 +291,7 @@ GLOBAL_LIST_EMPTY(uplinks) var/frequency = arguments[1] if(frequency != unlock_code) if(frequency == failsafe_code) - failsafe() + failsafe(master.loc) return locked = FALSE if(ismob(master.loc)) @@ -316,11 +328,13 @@ GLOBAL_LIST_EMPTY(uplinks) else if(istype(parent,/obj/item/pen)) return rand(1, 360) -/datum/component/uplink/proc/failsafe() +/datum/component/uplink/proc/failsafe(mob/living/carbon/user) if(!parent) return var/turf/T = get_turf(parent) if(!T) return + message_admins("[ADMIN_LOOKUPFLW(user)] has triggered an uplink failsafe explosion at [AREACOORD(T)] The owner of the uplink was [ADMIN_LOOKUPFLW(owner)].") + log_game("[key_name(user)] triggered an uplink failsafe explosion. The owner of the uplink was [key_name(owner)].") explosion(T,1,2,3) qdel(parent) //Alternatively could brick the uplink. diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm index 0fbbcd59b0..e2c3cbff86 100644 --- a/code/datums/components/wet_floor.dm +++ b/code/datums/components/wet_floor.dm @@ -121,7 +121,7 @@ if(-INFINITY to T0C) add_wet(TURF_WET_ICE, max_time_left()) //Water freezes into ice! if(T0C to T0C + 100) - decrease = ((T.air.temperature - T0C) / SSwet_floors.temperature_coeff) * (diff / SSwet_floors.time_ratio) + decrease = ((T.air.return_temperature() - T0C) / SSwet_floors.temperature_coeff) * (diff / SSwet_floors.time_ratio) if(T0C + 100 to INFINITY) decrease = INFINITY decrease = max(0, decrease) diff --git a/code/datums/datacore.dm b/code/datums/datacore.dm index 84ea6b6458..5aeb7626f6 100644 --- a/code/datums/datacore.dm +++ b/code/datums/datacore.dm @@ -1,13 +1,13 @@ - +//TODO: someone please get rid of this shit /datum/datacore - var/medical[] = list() + var/list/medical = list() var/medicalPrintCount = 0 - var/general[] = list() - var/security[] = list() + var/list/general = list() + var/list/security = list() var/securityPrintCount = 0 var/securityCrimeCounter = 0 - //This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). - var/locked[] = list() + ///This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). + var/list/locked = list() /datum/data var/name = "data" @@ -78,10 +78,12 @@ /datum/datacore/proc/manifest() for(var/mob/dead/new_player/N in GLOB.player_list) + if(!N?.client) + continue if(N.new_character) log_manifest(N.ckey,N.new_character.mind,N.new_character) if(ishuman(N.new_character)) - manifest_inject(N.new_character, N.client) + manifest_inject(N.new_character, N.client, N.client.prefs) CHECK_TICK /datum/datacore/proc/manifest_modify(name, assignment) @@ -89,6 +91,42 @@ if(foundrecord) foundrecord.fields["rank"] = assignment +/datum/datacore/proc/get_manifest_tg() //copypasted from tg, renamed to avoid namespace conflicts + var/list/manifest_out = list() + var/list/departments = list( + "Command" = GLOB.command_positions, + "Security" = GLOB.security_positions, + "Engineering" = GLOB.engineering_positions, + "Medical" = GLOB.medical_positions, + "Science" = GLOB.science_positions, + "Supply" = GLOB.supply_positions, + "Service" = GLOB.civilian_positions, + "Silicon" = GLOB.nonhuman_positions + ) + for(var/datum/data/record/t in GLOB.data_core.general) + var/name = t.fields["name"] + var/rank = t.fields["rank"] + var/has_department = FALSE + for(var/department in departments) + var/list/jobs = departments[department] + if(rank in jobs) + if(!manifest_out[department]) + manifest_out[department] = list() + manifest_out[department] += list(list( + "name" = name, + "rank" = rank + )) + has_department = TRUE + break + if(!has_department) + if(!manifest_out["Misc"]) + manifest_out["Misc"] = list() + manifest_out["Misc"] += list(list( + "name" = name, + "rank" = rank + )) + return manifest_out + /datum/datacore/proc/get_manifest(monochrome, OOC) var/list/heads = list() var/list/sec = list() @@ -197,7 +235,7 @@ return dat -/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C) +/datum/datacore/proc/manifest_inject(mob/living/carbon/human/H, client/C, datum/preferences/prefs) set waitfor = FALSE var/static/list/show_directions = list(SOUTH, WEST) if(H.mind && (H.mind.assigned_role != H.mind.special_role)) @@ -260,7 +298,7 @@ M.fields["alg_d"] = "No allergies have been detected in this patient." M.fields["cdi"] = "None" M.fields["cdi_d"] = "No diseases have been diagnosed at the moment." - M.fields["notes"] = H.get_trait_string(medical) + M.fields["notes"] = "Trait information as of shift start: [H.get_trait_string(medical)]
[prefs.medical_records]" medical += M //Security Record @@ -270,7 +308,7 @@ S.fields["criminal"] = "None" S.fields["mi_crim"] = list() S.fields["ma_crim"] = list() - S.fields["notes"] = "No notes." + S.fields["notes"] = prefs.security_records || "No notes." security += S //Locked Record diff --git a/code/datums/datum.dm b/code/datums/datum.dm index 6202ac444e..7756cfd906 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -39,6 +39,9 @@ /// A weak reference to another datum var/datum/weakref/weak_reference + ///Lazy associative list of currently active cooldowns. + var/list/cooldowns + #ifdef TESTING var/running_find_references var/last_find_references = 0 @@ -201,3 +204,34 @@ qdel(D) else return returned + +/** + * Callback called by a timer to end an associative-list-indexed cooldown. + * + * Arguments: + * * source - datum storing the cooldown + * * index - string index storing the cooldown on the cooldowns associative list + * + * This sends a signal reporting the cooldown end. + */ +/proc/end_cooldown(datum/source, index) + if(QDELETED(source)) + return + SEND_SIGNAL(source, COMSIG_CD_STOP(index)) + TIMER_COOLDOWN_END(source, index) + + +/** + * Proc used by stoppable timers to end a cooldown before the time has ran out. + * + * Arguments: + * * source - datum storing the cooldown + * * index - string index storing the cooldown on the cooldowns associative list + * + * This sends a signal reporting the cooldown end, passing the time left as an argument. + */ +/proc/reset_cooldown(datum/source, index) + if(QDELETED(source)) + return + SEND_SIGNAL(source, COMSIG_CD_RESET(index), S_TIMER_COOLDOWN_TIMELEFT(source, index)) + TIMER_COOLDOWN_END(source, index) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 348f9e6778..a91549ab4c 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -31,6 +31,9 @@ VV_DROPDOWN_OPTION(VV_HK_EXPOSE, "Show VV To Player") VV_DROPDOWN_OPTION(VV_HK_ADDCOMPONENT, "Add Component/Element") VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRAITS, "Modify Traits") + #ifdef REFERENCE_TRACKING + VV_DROPDOWN_OPTION(VV_HK_VIEW_REFERENCES, "View References") + #endif //This proc is only called if everything topic-wise is verified. The only verifications that should happen here is things like permission checks! //href_list is a reference, modifying it in these procs WILL change the rest of the proc in topic.dm of admin/view_variables! diff --git a/code/datums/diseases/advance/symptoms/flesh_eating.dm b/code/datums/diseases/advance/symptoms/flesh_eating.dm index 774d97202e..0fad819e8e 100644 --- a/code/datums/diseases/advance/symptoms/flesh_eating.dm +++ b/code/datums/diseases/advance/symptoms/flesh_eating.dm @@ -64,7 +64,8 @@ Bonus if(bleed) if(ishuman(M)) var/mob/living/carbon/human/H = M - H.bleed_rate += 5 * power + var/obj/item/bodypart/random_part = pick(H.bodyparts) + random_part.generic_bleedstacks += 5 * power return 1 /* diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 787704e848..2fc853500d 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -404,7 +404,7 @@ if(M.loc) environment = M.loc.return_air() if(environment) - plasmamount = environment.gases[/datum/gas/plasma] + plasmamount = environment.get_moles(/datum/gas/plasma) if(plasmamount && plasmamount > GLOB.meta_gas_visibility[/datum/gas/plasma]) //if there's enough plasma in the air to see . += power * 0.5 if(M.reagents.has_reagent(/datum/reagent/toxin/plasma)) diff --git a/code/datums/diseases/advance/symptoms/species.dm b/code/datums/diseases/advance/symptoms/species.dm index 49a3cf8d07..2d5255842b 100644 --- a/code/datums/diseases/advance/symptoms/species.dm +++ b/code/datums/diseases/advance/symptoms/species.dm @@ -31,4 +31,3 @@ /datum/symptom/inorganic_adaptation/OnRemove(datum/disease/advance/A) A.infectable_biotypes &= ~MOB_MINERAL - diff --git a/code/datums/diseases/transformation.dm b/code/datums/diseases/transformation.dm index 1bb927aa12..e90eededd9 100644 --- a/code/datums/diseases/transformation.dm +++ b/code/datums/diseases/transformation.dm @@ -20,11 +20,11 @@ /datum/disease/transformation/Copy() var/datum/disease/transformation/D = ..() - D.stage1 = stage1.Copy() - D.stage2 = stage2.Copy() - D.stage3 = stage3.Copy() - D.stage4 = stage4.Copy() - D.stage5 = stage5.Copy() + D.stage1 = stage1?.Copy() + D.stage2 = stage2?.Copy() + D.stage3 = stage3?.Copy() + D.stage4 = stage4?.Copy() + D.stage5 = stage5?.Copy() D.new_form = D.new_form return D @@ -52,9 +52,9 @@ to_chat(affected_mob, pick(stage5)) if(QDELETED(affected_mob)) return - if(affected_mob.notransform) + if(affected_mob.mob_transforming) return - affected_mob.notransform = 1 + affected_mob.mob_transforming = 1 for(var/obj/item/W in affected_mob.get_equipped_items(TRUE)) affected_mob.dropItemToGround(W) for(var/obj/item/I in affected_mob.held_items) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index ed5104e296..9486029fdd 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -15,6 +15,7 @@ var/mob/living/holder var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875 var/mutation_index[DNA_MUTATION_BLOCKS] //List of which mutations this carbon has and its assigned block + var/default_mutation_genes[DNA_MUTATION_BLOCKS] //List of the default genes from this mutation to allow DNA Scanner highlighting var/stability = 100 var/scrambled = FALSE //Did we take something like mutagen? In that case we cant get our genes scanned to instantly cheese all the powers. var/skin_tone_override //because custom skin tones are not found in the skin_tones global list. @@ -49,6 +50,7 @@ destination.dna.skin_tone_override = skin_tone_override destination.dna.features = features.Copy() destination.set_species(species.type, icon_update=0) + destination.dna.species.say_mod = species.say_mod destination.dna.real_name = real_name destination.dna.nameless = nameless destination.dna.custom_species = custom_species @@ -58,6 +60,7 @@ H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA if(transfer_SE) destination.dna.mutation_index = mutation_index + destination.dna.default_mutation_genes = default_mutation_genes destination.dna.update_body_size(old_size) @@ -66,11 +69,13 @@ /datum/dna/proc/copy_dna(datum/dna/new_dna) new_dna.unique_enzymes = unique_enzymes new_dna.mutation_index = mutation_index + new_dna.default_mutation_genes = default_mutation_genes new_dna.uni_identity = uni_identity new_dna.blood_type = blood_type new_dna.skin_tone_override = skin_tone_override new_dna.features = features.Copy() new_dna.species = new species.type + new_dna.species.say_mod = species.say_mod new_dna.real_name = real_name new_dna.nameless = nameless new_dna.custom_species = custom_species @@ -128,14 +133,14 @@ L[DNA_FACIAL_HAIR_COLOR_BLOCK] = sanitize_hexcolor(H.facial_hair_color) L[DNA_SKIN_TONE_BLOCK] = construct_block(GLOB.skin_tones.Find(H.skin_tone), GLOB.skin_tones.len) L[DNA_EYE_COLOR_BLOCK] = sanitize_hexcolor(H.eye_color) - L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"]) - L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"]) - L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"]) + L[DNA_COLOR_ONE_BLOCK] = sanitize_hexcolor(features["mcolor"], 6) + L[DNA_COLOR_TWO_BLOCK] = sanitize_hexcolor(features["mcolor2"], 6) + L[DNA_COLOR_THREE_BLOCK] = sanitize_hexcolor(features["mcolor3"], 6) if(!GLOB.mam_tails_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, GLOB.mam_tails_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/mam_tails, GLOB.mam_tails_list) L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len) if(!GLOB.mam_ears_list.len) - init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_ears, GLOB.mam_ears_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/ears/mam_ears, GLOB.mam_ears_list) L[DNA_MUTANTEAR_BLOCK] = construct_block(GLOB.mam_ears_list.Find(features["mam_ears"]), GLOB.mam_ears_list.len) if(!GLOB.mam_body_markings_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, GLOB.mam_body_markings_list) @@ -160,15 +165,18 @@ if(!LAZYLEN(mutations_temp)) return mutation_index.Cut() + default_mutation_genes.Cut() shuffle_inplace(mutations_temp) if(ismonkey(holder)) mutations |= new RACEMUT(MUT_NORMAL) mutation_index[RACEMUT] = GET_SEQUENCE(RACEMUT) else mutation_index[RACEMUT] = create_sequence(RACEMUT, FALSE) + default_mutation_genes[RACEMUT] = mutation_index[RACEMUT] for(var/i in 2 to DNA_MUTATION_BLOCKS) var/datum/mutation/human/M = mutations_temp[i] - mutation_index[M.type] = create_sequence(M.type, FALSE,M.difficulty) + mutation_index[M.type] = create_sequence(M.type, FALSE, M.difficulty) + default_mutation_genes[M.type] = mutation_index[M.type] shuffle_inplace(mutation_index) //Used to generate original gene sequences for every mutation @@ -233,11 +241,11 @@ if(DNA_HAIR_STYLE_BLOCK) setblock(uni_identity, blocknumber, construct_block(GLOB.hair_styles_list.Find(H.hair_style), GLOB.hair_styles_list.len)) if(DNA_COLOR_ONE_BLOCK) - sanitize_hexcolor(features["mcolor"]) + sanitize_hexcolor(features["mcolor"], 6) if(DNA_COLOR_TWO_BLOCK) - sanitize_hexcolor(features["mcolor2"]) + sanitize_hexcolor(features["mcolor2"], 6) if(DNA_COLOR_THREE_BLOCK) - sanitize_hexcolor(features["mcolor3"]) + sanitize_hexcolor(features["mcolor3"], 6) if(DNA_MUTANTTAIL_BLOCK) construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len) if(DNA_MUTANTEAR_BLOCK) @@ -389,7 +397,7 @@ return dna -/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures) +/mob/living/carbon/human/proc/hardset_dna(ui, list/mutation_index, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/default_mutation_genes) if(newreal_name) real_name = newreal_name @@ -414,6 +422,10 @@ if(LAZYLEN(mutation_index)) dna.mutation_index = mutation_index.Copy() + if(LAZYLEN(default_mutation_genes)) + dna.default_mutation_genes = default_mutation_genes.Copy() + else + dna.default_mutation_genes = mutation_index.Copy() domutcheck() SEND_SIGNAL(src, COMSIG_HUMAN_HARDSET_DNA, ui, mutation_index, newreal_name, newblood_type, mrace, newfeatures) @@ -505,8 +517,11 @@ . = TRUE if(on) mutation_index[HM.type] = GET_SEQUENCE(HM.type) + default_mutation_genes[HM.type] = mutation_index[HM.type] else if(GET_SEQUENCE(HM.type) == mutation_index[HM.type]) mutation_index[HM.type] = create_sequence(HM.type, FALSE, HM.difficulty) + default_mutation_genes[HM.type] = mutation_index[HM.type] + /datum/dna/proc/activate_mutation(mutation) //note that this returns a boolean and not a new mob if(!mutation) @@ -678,7 +693,7 @@ holder.update_transform() var/danger = CONFIG_GET(number/threshold_body_size_slowdown) if(features["body_size"] < danger) - var/slowdown = 1 + round(danger/features["body_size"], 0.1) * CONFIG_GET(number/body_size_slowdown_multiplier) + var/slowdown = (1 - round(features["body_size"] / danger, 0.1)) * CONFIG_GET(number/body_size_slowdown_multiplier) holder.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/small_stride, TRUE, slowdown) else if(old_size < danger) holder.remove_movespeed_modifier(/datum/movespeed_modifier/small_stride) diff --git a/code/datums/dog_fashion.dm b/code/datums/dog_fashion.dm index 744f57c391..2e80feac67 100644 --- a/code/datums/dog_fashion.dm +++ b/code/datums/dog_fashion.dm @@ -38,7 +38,6 @@ corgI.color = obj_color return corgI - /datum/dog_fashion/head icon_file = 'icons/mob/corgi_head.dmi' @@ -53,7 +52,6 @@ name = "Sous chef REAL_NAME" desc = "Your food will be taste-tested. All of it." - /datum/dog_fashion/head/captain name = "Captain REAL_NAME" desc = "Probably better than the last captain." diff --git a/code/datums/ductnet.dm b/code/datums/ductnet.dm new file mode 100644 index 0000000000..14a74a67c4 --- /dev/null +++ b/code/datums/ductnet.dm @@ -0,0 +1,65 @@ +///We handle the unity part of plumbing. We track who is connected to who. +/datum/ductnet + var/list/suppliers = list() + var/list/demanders = list() + var/list/obj/machinery/duct/ducts = list() + + var/capacity +///Add a duct to our network +/datum/ductnet/proc/add_duct(obj/machinery/duct/D) + if(!D || (D in ducts)) + return + ducts += D + D.duct = src +///Remove a duct from our network and commit suicide, because this is probably easier than to check who that duct was connected to and what part of us was lost +/datum/ductnet/proc/remove_duct(obj/machinery/duct/ducting) + destroy_network(FALSE) + for(var/obj/machinery/duct/D in ducting.neighbours) + addtimer(CALLBACK(D, /obj/machinery/duct/proc/reconnect), 0) //all needs to happen after the original duct that was destroyed finishes destroying itself + addtimer(CALLBACK(D, /obj/machinery/duct/proc/generate_connects), 0) + qdel(src) +///add a plumbing object to either demanders or suppliers +/datum/ductnet/proc/add_plumber(datum/component/plumbing/P, dir) + if(!P.can_add(src, dir)) + return FALSE + P.ducts[num2text(dir)] = src + if(dir & P.supply_connects) + suppliers += P + else if(dir & P.demand_connects) + demanders += P + return TRUE +///remove a plumber. we dont delete ourselves because ductnets dont persist through plumbing objects +/datum/ductnet/proc/remove_plumber(datum/component/plumbing/P) + suppliers.Remove(P) //we're probably only in one of these, but Remove() is inherently sane so this is fine + demanders.Remove(P) + + for(var/dir in P.ducts) + if(P.ducts[dir] == src) + P.ducts -= dir + if(!ducts.len) //there were no ducts, so it was a direct connection. we destroy ourselves since a ductnet with only one plumber and no ducts is worthless + destroy_network() +///we combine ductnets. this occurs when someone connects to seperate sets of fluid ducts +/datum/ductnet/proc/assimilate(datum/ductnet/D) + ducts.Add(D.ducts) + suppliers.Add(D.suppliers) + demanders.Add(D.demanders) + for(var/A in D.suppliers + D.demanders) + var/datum/component/plumbing/P = A + for(var/s in P.ducts) + if(P.ducts[s] != D) + continue + P.ducts[s] = src //all your ducts are belong to us + for(var/A in D.ducts) + var/obj/machinery/duct/M = A + M.duct = src //forget your old master + + destroy_network() +///destroy the network and tell all our ducts and plumbers we are gone +/datum/ductnet/proc/destroy_network(delete=TRUE) + for(var/A in suppliers + demanders) + remove_plumber(A) + for(var/A in ducts) + var/obj/machinery/duct/D = A + D.duct = null + if(delete) //I don't want code to run with qdeleted objects because that can never be good, so keep this in-case the ductnet has some business left to attend to before commiting suicide + qdel(src) diff --git a/code/datums/elements/beauty.dm b/code/datums/elements/beauty.dm index 8acfda73e1..8895026967 100644 --- a/code/datums/elements/beauty.dm +++ b/code/datums/elements/beauty.dm @@ -8,8 +8,11 @@ if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target)) return ELEMENT_INCOMPATIBLE beauty = beautyamount - RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area) - RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area) + + if(ismovable(target)) + RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area) + RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area) + var/area/A = get_area(target) if(A) enter_area(null, A) diff --git a/code/datums/elements/bsa_blocker.dm b/code/datums/elements/bsa_blocker.dm new file mode 100644 index 0000000000..61140ad0ed --- /dev/null +++ b/code/datums/elements/bsa_blocker.dm @@ -0,0 +1,10 @@ +//blocks bluespace artillery beams that try to fly through +//look not all elements need to be fancy +/datum/element/bsa_blocker/Attach(datum/target) + if(!isatom(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_ATOM_BSA_BEAM, .proc/block_bsa) + return ..() + +/datum/element/bsa_blocker/proc/block_bsa() + return COMSIG_ATOM_BLOCKS_BSA_BEAM diff --git a/code/datums/elements/decal.dm b/code/datums/elements/decal.dm index 4bd482915a..50519b08e7 100644 --- a/code/datums/elements/decal.dm +++ b/code/datums/elements/decal.dm @@ -33,39 +33,34 @@ if(description) RegisterSignal(A, COMSIG_PARENT_EXAMINE, .proc/examine) - apply(A, TRUE) - num_decals_per_atom[A]++ + apply(A) /datum/element/decal/Detach(datum/target) var/atom/A = target - remove(A, A.dir) - UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE)) - LAZYREMOVE(num_decals_per_atom, A) + num_decals_per_atom[A]-- + apply(A, TRUE) + if(!num_decals_per_atom[A]) + UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS)) + LAZYREMOVE(num_decals_per_atom, A) return ..() -/datum/element/decal/proc/remove(atom/target, old_dir) - pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(old_dir)) - for(var/i in 1 to num_decals_per_atom[target]) - target.cut_overlay(pic, TRUE) +/datum/element/decal/proc/apply(atom/target, removing = FALSE) + if(num_decals_per_atom[target] == 1 && !removing) + RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_overlay, TRUE) + target.update_icon() if(isitem(target)) addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE) -/datum/element/decal/proc/apply(atom/target, init = FALSE) - pic.dir = first_dir == NORTH ? target.dir : turn(first_dir, dir2angle(target.dir)) - if(init) - target.add_overlay(pic, TRUE) - else - for(var/i in 1 to num_decals_per_atom[target]) - target.add_overlay(pic, TRUE) - if(isitem(target)) - addtimer(CALLBACK(target, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE) +/datum/element/decal/proc/apply_overlay(atom/source, list/overlay_list) + pic.dir = first_dir == NORTH ? source.dir : turn(first_dir, dir2angle(source.dir)) + for(var/i in 1 to num_decals_per_atom[source]) + overlay_list += pic -/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir) +/datum/element/decal/proc/rotate_react(atom/source, old_dir, new_dir) if(old_dir == new_dir) return - remove(source, old_dir) - apply(source) + source.update_icon() /datum/element/decal/proc/clean_react(datum/source, strength) if(strength >= cleanable) diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm index 86189b67e1..876414330f 100644 --- a/code/datums/elements/embed.dm +++ b/code/datums/elements/embed.dm @@ -2,7 +2,7 @@ The presence of this element allows an item (or a projectile carrying an item) to embed itself in a human or turf when it is thrown into a target (whether by hand, gun, or explosive wave) with either at least 4 throwspeed (EMBED_THROWSPEED_THRESHOLD) or ignore_throwspeed_threshold set to TRUE. Items meant to be used as shrapnel for projectiles should have ignore_throwspeed_threshold set to true. - Whether we're dealing with a direct /obj/item (throwing a knife at someone) or an /obj/projectile with a shrapnel_type, how we handle things plays out the same, with one extra step separating them. + Whether we're dealing with a direct /obj/item (throwing a knife at someone) or an /obj/item/projectile with a shrapnel_type, how we handle things plays out the same, with one extra step separating them. Items simply make their COMSIG_MOVABLE_IMPACT or COMSIG_MOVABLE_IMPACT_ZONE check (against a closed turf or a carbon, respectively), while projectiles check on COMSIG_PROJECTILE_SELF_ON_HIT. Upon a projectile hitting a valid target, it spawns whatever type of payload it has defined, then has that try to embed itself in the target on its own. @@ -37,10 +37,10 @@ if(!isitem(target) && !isprojectile(target)) return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage) if(isitem(target)) RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, .proc/checkEmbedMob) RegisterSignal(target, COMSIG_MOVABLE_IMPACT, .proc/checkEmbedOther) - RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage) RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/examined) RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, .proc/tryForceEmbed) RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, .proc/detachFromWeapon) @@ -68,28 +68,28 @@ if(isitem(target)) UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT_ZONE, COMSIG_ELEMENT_ATTACH, COMSIG_MOVABLE_IMPACT, COMSIG_PARENT_EXAMINE, COMSIG_EMBED_TRY_FORCE, COMSIG_ITEM_DISABLE_EMBED)) else - UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT)) + UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT, COMSIG_ELEMENT_ATTACH)) /// Checking to see if we're gonna embed into a human -/datum/element/embed/proc/checkEmbedMob(obj/item/weapon, mob/living/carbon/victim, hit_zone, datum/thrownthing/throwingdatum, forced=FALSE) - if(!istype(victim) || HAS_TRAIT(victim, TRAIT_PIERCEIMMUNE)) +/datum/element/embed/proc/checkEmbedMob(obj/item/weapon, mob/living/carbon/victim, hit_zone, datum/thrownthing/throwingdatum, blocked = FALSE, forced = FALSE) + if(blocked || !istype(victim) || HAS_TRAIT(victim, TRAIT_PIERCEIMMUNE)) return var/actual_chance = embed_chance if(!weapon.isEmbedHarmless()) // all the armor in the world won't save you from a kick me sign - var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) // we'll be nice and take the better of bullet and bomb armor + var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) * 0.5 // we'll be nice and take the better of bullet and bomb armor, halved if(armor) // we only care about armor penetration if there's actually armor to penetrate var/pen_mod = -armor + weapon.armour_penetration // even a little bit of armor can make a big difference for shrapnel with large negative armor pen actual_chance += pen_mod // doing the armor pen as a separate calc just in case this ever gets expanded on if(actual_chance <= 0) - victim.visible_message("[weapon] bounces off [victim]'s armor!", "[weapon] bounces off your armor!", vision_distance = COMBAT_MESSAGE_RANGE) + victim.visible_message("[weapon] bounces off [victim]'s armor, unable to embed!", "[weapon] bounces off your armor, unable to embed!", vision_distance = COMBAT_MESSAGE_RANGE) return var/roll_embed = prob(actual_chance) - var/pass = forced || ((((throwingdatum ? throwingdatum.speed : weapon.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || ignore_throwspeed_threshold) && roll_embed) + var/pass = forced || ((((throwingdatum ? throwingdatum.speed : weapon.throw_speed) >= EMBED_THROWSPEED_THRESHOLD) || ignore_throwspeed_threshold) && roll_embed && (!HAS_TRAIT(victim, TRAIT_AUTO_CATCH_ITEM) || victim.incapacitated() || victim.get_active_held_item())) if(!pass) return @@ -147,7 +147,7 @@ return TRUE ///A different embed element has been attached, so we'll detach and let them handle things -/datum/element/embed/proc/severancePackage(obj/item/weapon, datum/element/E) +/datum/element/embed/proc/severancePackage(obj/weapon, datum/element/E) if(istype(E, /datum/element/embed)) Detach(weapon) @@ -169,46 +169,35 @@ * it to call tryForceEmbed() on its own embed element (it's out of our hands here, our projectile is done), where it will run through all the checks it needs to. */ /datum/element/embed/proc/checkEmbedProjectile(obj/item/projectile/P, atom/movable/firer, atom/hit, angle, hit_zone) - if(!iscarbon(hit) && !isclosedturf(hit)) + if(!iscarbon(hit)) Detach(P) return // we don't care var/obj/item/payload = new payload_type(get_turf(hit)) - var/did_embed - if(iscarbon(hit)) - var/mob/living/carbon/C = hit - var/obj/item/bodypart/limb - limb = C.get_bodypart(hit_zone) - if(!limb) - limb = C.get_bodypart() - did_embed = payload.tryEmbed(limb) - else - did_embed = payload.tryEmbed(hit) + if(istype(payload, /obj/item/shrapnel/bullet)) + payload.name = P.name + payload.embedding = P.embedding + payload.updateEmbedding() + var/mob/living/carbon/C = hit + var/obj/item/bodypart/limb = C.get_bodypart(hit_zone) + if(!limb) + limb = C.get_bodypart() - if(!did_embed) - payload.failedEmbed() + payload.tryEmbed(limb) Detach(P) /** - * tryForceEmbed() is called here when we fire COMSIG_EMBED_TRY_FORCE from [/obj/item/proc/tryEmbed]. Mostly, this means we're a piece of shrapnel from a projectile that just impacted something, and we're trying to embed in it. - * - * The reason for this extra mucking about is avoiding having to do an extra hitby(), and annoying the target by impacting them once with the projectile, then again with the shrapnel (which likely represents said bullet), and possibly - * AGAIN if we actually embed. This way, we save on at least one message. Runs the standard embed checks on the mob/turf. - * * Arguments: - * * I- what we're trying to embed, obviously - * * target- what we're trying to shish-kabob, either a bodypart, a carbon, or a closed turf + * * I- the item we're trying to insert into the target + * * target- what we're trying to shish-kabob, either a bodypart or a carbon * * hit_zone- if our target is a carbon, try to hit them in this zone, if we don't have one, pick a random one. If our target is a bodypart, we already know where we're hitting. * * forced- if we want this to succeed 100% */ /datum/element/embed/proc/tryForceEmbed(obj/item/I, atom/target, hit_zone, forced=FALSE) var/obj/item/bodypart/limb var/mob/living/carbon/C - var/turf/closed/T - if(!forced && !prob(embed_chance)) return - if(iscarbon(target)) C = target if(!hit_zone) @@ -218,10 +207,5 @@ limb = target hit_zone = limb.body_zone C = limb.owner - else if(isclosedturf(target)) - T = target - - if(C) - return checkEmbedMob(I, C, hit_zone, forced=TRUE) - else if(T) - return checkEmbedOther(I, T, forced=TRUE) + checkEmbedMob(I, C, hit_zone, forced=TRUE) + return TRUE diff --git a/code/datums/elements/flavor_text.dm b/code/datums/elements/flavor_text.dm index 92251861ed..3562345d26 100644 --- a/code/datums/elements/flavor_text.dm +++ b/code/datums/elements/flavor_text.dm @@ -82,9 +82,10 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code return if(href_list["show_flavor"]) var/atom/target = locate(href_list["show_flavor"]) + var/mob/living/L = target var/text = texts_by_atom[target] if(text) - usr << browse("[target.name][replacetext(texts_by_atom[target], "\n", "
")]
", "window=[target.name];size=500x200") + usr << browse("[isliving(target) ? L.get_visible_name() : target.name][replacetext(texts_by_atom[target], "\n", "
")]
", "window=[isliving(target) ? L.get_visible_name() : target.name];size=500x200") onclose(usr, "[target.name]") return TRUE diff --git a/code/datums/elements/photosynthesis.dm b/code/datums/elements/photosynthesis.dm index 93e4369b8b..4fe0615b1f 100644 --- a/code/datums/elements/photosynthesis.dm +++ b/code/datums/elements/photosynthesis.dm @@ -60,7 +60,7 @@ if(L.stat == DEAD) continue if(light_nutrition_gain) - L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_FULL) + L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_WELL_FED) if(light_amount > bonus_lum || light_amount < malus_lum) var/mult = ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM] if(light_bruteheal) diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm index dc32902e5e..246226ceba 100644 --- a/code/datums/explosion.dm +++ b/code/datums/explosion.dm @@ -103,13 +103,21 @@ GLOBAL_LIST_EMPTY(explosions) // 3/7/14 will calculate to 80 + 35 var/far_dist = 0 - far_dist += heavy_impact_range * 5 + far_dist += heavy_impact_range * 15 // Large explosions carry further far_dist += devastation_range * 20 if(!silent) var/frequency = get_rand_frequency() var/sound/explosion_sound = sound(get_sfx("explosion")) var/sound/far_explosion_sound = sound('sound/effects/explosionfar.ogg') + var/sound/creaking_explosion_sound = sound(get_sfx("explosion_creaking")) + var/sound/hull_creaking_sound = sound(get_sfx("hull_creaking")) + var/sound/explosion_echo_sound = sound('sound/effects/explosion_distant.ogg') + var/on_station = SSmapping.level_trait(epicenter.z, ZTRAIT_STATION) + var/creaking_explosion = FALSE + + if(prob(devastation_range*30+heavy_impact_range*5) && on_station) // Huge explosions are near guaranteed to make the station creak and whine, smaller ones might. + creaking_explosion = TRUE // prob over 100 always returns true for(var/mob/M in GLOB.player_list) // Double check for client @@ -126,11 +134,29 @@ GLOBAL_LIST_EMPTY(explosions) shake_camera(M, 25, clamp(baseshakeamount, 0, 10)) // You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station. else if(dist <= far_dist) - var/far_volume = clamp(far_dist, 30, 50) // Volume is based on explosion size and dist - far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion - M.playsound_local(epicenter, null, far_volume, 1, frequency, falloff = 5, S = far_explosion_sound) - if(baseshakeamount > 0) + var/far_volume = clamp(far_dist/2, 40, 60) // Volume is based on explosion size and dist + if(creaking_explosion) + M.playsound_local(epicenter, null, far_volume, 1, frequency, S = creaking_explosion_sound, distance_multiplier = 0) + else if(prob(75)) + M.playsound_local(epicenter, null, far_volume, 1, frequency, S = far_explosion_sound, distance_multiplier = 0) // Far sound + else + M.playsound_local(epicenter, null, far_volume, 1, frequency, S = explosion_echo_sound, distance_multiplier = 0) // Echo sound + + if(baseshakeamount > 0 || devastation_range) + if(!baseshakeamount) // Devastating explosions rock the station and ground + baseshakeamount = devastation_range*3 shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, 2.5)) + + else if(M.can_hear() && !isspaceturf(get_turf(M)) && heavy_impact_range) // Big enough explosions echo throughout the hull + var/echo_volume = 40 + if(devastation_range) + baseshakeamount = devastation_range + shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, 2.5)) + echo_volume = 60 + M.playsound_local(epicenter, null, echo_volume, 1, frequency, S = explosion_echo_sound, distance_multiplier = 0) + + if(creaking_explosion) // 5 seconds after the bang, the station begins to creak + addtimer(CALLBACK(M, /mob/proc/playsound_local, epicenter, null, rand(25, 40), 1, frequency, null, null, FALSE, hull_creaking_sound, null, null, null, null, 0), 5 SECONDS) EX_PREPROCESS_CHECK_TICK //postpone processing for a bit @@ -196,14 +222,12 @@ GLOBAL_LIST_EMPTY(explosions) //------- EX_ACT AND TURF FIRES ------- - if(T == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag - var/list/items = list() - for(var/I in T) - var/atom/A = I - if (!(A.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't. - items += A.GetAllContents() - for(var/O in items) - var/atom/A = O + if((T == epicenter) && !QDELETED(explosion_source) && ismovable(explosion_source) && (get_turf(explosion_source) == T)) // Ensures explosives detonating from bags trigger other explosives in that bag + var/list/atoms = list() + for(var/atom/A in explosion_source.loc) // the ismovableatom check 2 lines above makes sure we don't nuke an /area + atoms += A + for(var/i in atoms) + var/atom/A = i if(!QDELETED(A)) A.ex_act(dist) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index c46a03a986..5e9371f754 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -117,9 +117,8 @@ continue var/datum/gas_mixture/A = F.air - var/list/A_gases = A.gases var/trace_gases - for(var/id in A_gases) + for(var/id in A.get_gases()) if(id in GLOB.hardcoded_gases) continue trace_gases = TRUE @@ -128,15 +127,15 @@ // Can most things breathe? if(trace_gases) continue - if(A_gases[/datum/gas/oxygen] <= 16) + if(A.get_moles(/datum/gas/oxygen) < 16) continue - if(A_gases[/datum/gas/plasma]) + if(A.get_moles(/datum/gas/plasma)) continue - if(A_gases[/datum/gas/carbon_dioxide] >= 10) + if(A.get_moles(/datum/gas/carbon_dioxide) >= 10) continue // Aim for goldilocks temperatures and pressure - if((A.temperature <= 270) || (A.temperature >= 360)) + if((A.return_temperature() <= 270) || (A.return_temperature() >= 360)) continue var/pressure = A.return_pressure() if((pressure <= 20) || (pressure >= 550)) diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 0f4f02ae2a..4bf02e8587 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -32,20 +32,29 @@ var/datum/action/innate/end_holocall/hangup //hangup action var/call_start_time + var/head_call = FALSE //calls from a head of staff autoconnect, if the receiving pad is not secure. //creates a holocall made by `caller` from `calling_pad` to `callees` -/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees) +/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees, elevated_access = FALSE) call_start_time = world.time user = caller calling_pad.outgoing_call = src calling_holopad = calling_pad + head_call = elevated_access dialed_holopads = list() for(var/I in callees) var/obj/machinery/holopad/H = I if(!QDELETED(H) && H.is_operational()) dialed_holopads += H - H.say("Incoming call.") + if(head_call) + if(H.secure) + calling_pad.say("Auto-connection refused, falling back to call mode.") + H.say("Incoming call.") + else + H.say("Incoming connection.") + else + H.say("Incoming call.") LAZYADD(H.holo_calls, src) if(!dialed_holopads.len) @@ -79,6 +88,7 @@ dialed_holopads.Cut() if(calling_holopad) + calling_holopad.calling = FALSE calling_holopad.outgoing_call = null calling_holopad.SetLightsAndPower() calling_holopad = null @@ -145,6 +155,7 @@ if(!Check()) return + calling_holopad.calling = FALSE hologram = H.activate_holo(user) hologram.HC = src @@ -160,6 +171,8 @@ hangup = new(eye, src) hangup.Grant(user) + playsound(H, 'sound/machines/ping.ogg', 100) + H.say("Connection established.") //Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise /datum/holocall/proc/Check() @@ -178,7 +191,6 @@ . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME) if(!.) calling_holopad.say("No answer received.") - calling_holopad.temp = "" if(!.) testing("Holocall Check fail") @@ -241,10 +253,10 @@ record.caller_image = holodiskOriginal.record.caller_image record.entries = holodiskOriginal.record.entries.Copy() record.language = holodiskOriginal.record.language - to_chat(user, "You copy the record from [holodiskOriginal] to [src] by connecting the ports!") + to_chat(user, "You copy the record from [holodiskOriginal] to [src] by connecting the ports!") name = holodiskOriginal.name else - to_chat(user, "[holodiskOriginal] has no record on it!") + to_chat(user, "[holodiskOriginal] has no record on it!") ..() /obj/item/disk/holodisk/proc/build_record() @@ -331,6 +343,21 @@ DELAY 20"} /datum/preset_holoimage/engineer + outfit_type = /datum/outfit/job/engineer + +/datum/preset_holoimage/engineer/rig + outfit_type = /datum/outfit/job/engineer/gloved/rig + +/datum/preset_holoimage/engineer/ce + outfit_type = /datum/outfit/job/ce + +/datum/preset_holoimage/engineer/ce/rig + outfit_type = /datum/outfit/job/engineer/gloved/rig + +/datum/preset_holoimage/engineer/atmos + outfit_type = /datum/outfit/job/atmos + +/datum/preset_holoimage/engineer/atmos/rig outfit_type = /datum/outfit/job/engineer/gloved/rig /datum/preset_holoimage/researcher @@ -350,3 +377,90 @@ /datum/preset_holoimage/clown outfit_type = /datum/outfit/job/clown + +/obj/item/disk/holodisk/donutstation/whiteship + name = "Blackbox Print-out #DS024" + desc = "A holodisk containing the last viable recording of DS024's blackbox." + preset_image_type = /datum/preset_holoimage/engineer/ce + preset_record_text = {" + NAME Geysr Shorthalt + SAY Engine renovations complete and the ships been loaded. We all ready? + DELAY 25 + PRESET /datum/preset_holoimage/engineer + NAME Jacob Ullman + SAY Lets blow this popsicle stand of a station. + DELAY 20 + PRESET /datum/preset_holoimage/engineer/atmos + NAME Lindsey Cuffler + SAY Uh, sir? Shouldn't we call for a secondary shuttle? The bluespace drive on this thing made an awfully weird noise when we jumped here.. + DELAY 30 + PRESET /datum/preset_holoimage/engineer/ce + NAME Geysr Shorthalt + SAY Pah! Ship techie at the dock said to give it a good few kicks if it started acting up, let me just.. + DELAY 25 + SOUND punch + SOUND sparks + DELAY 10 + SOUND punch + SOUND sparks + DELAY 10 + SOUND punch + SOUND sparks + SOUND warpspeed + DELAY 15 + PRESET /datum/preset_holoimage/engineer/atmos + NAME Lindsey Cuffler + SAY Uhh.. is it supposed to be doing that?? + DELAY 15 + PRESET /datum/preset_holoimage/engineer/ce + NAME Geysr Shorthalt + SAY See? Working as intended. Now, are we all ready? + DELAY 10 + PRESET /datum/preset_holoimage/engineer + NAME Jacob Ullman + SAY Is it supposed to be glowing like that? + DELAY 20 + SOUND explosion + + "} + +/obj/item/disk/holodisk/ruin/snowengieruin + name = "Blackbox Print-out #EB412" + desc = "A holodisk containing the last moments of EB412. There's a bloody fingerprint on it." + preset_image_type = /datum/preset_holoimage/engineer + preset_record_text = {" + NAME Dave Tundrale + SAY Maria, how's Build? + DELAY 10 + NAME Maria Dell + PRESET /datum/preset_holoimage/engineer/atmos + SAY It's fine, don't worry. I've got Plastic on it. And frankly, i'm kinda busy with, the, uhhm, incinerator. + DELAY 30 + NAME Dave Tundrale + PRESET /datum/preset_holoimage/engineer + SAY Aight, wonderful. The science mans been kinda shit though. No RCDs- + DELAY 20 + NAME Maria Dell + PRESET /datum/preset_holoimage/engineer/atmos + SAY Enough about your RCDs. They're not even that important, just bui- + DELAY 15 + SOUND explosion + DELAY 10 + SAY Oh, shit! + DELAY 10 + PRESET /datum/preset_holoimage/engineer/atmos/rig + LANGUAGE /datum/language/narsie + NAME Unknown + SAY RISE, MY LORD!! + DELAY 10 + LANGUAGE /datum/language/common + NAME Plastic + PRESET /datum/preset_holoimage/engineer/rig + SAY Fuck, fuck, fuck! + DELAY 20 + SAY It's loose! CALL THE FUCKING SHUTT- + DELAY 10 + PRESET /datum/preset_holoimage/corgi + NAME Blackbox Automated Message + SAY Connection lost. Dumping audio logs to disk. + DELAY 50"} diff --git a/code/datums/http.dm b/code/datums/http.dm new file mode 100644 index 0000000000..2a9b53f131 --- /dev/null +++ b/code/datums/http.dm @@ -0,0 +1,74 @@ +/datum/http_request + var/id + var/in_progress = FALSE + + var/method + var/body + var/headers + var/url + + var/_raw_response + +/datum/http_request/proc/prepare(method, url, body = "", list/headers) + if (!length(headers)) + headers = "" + else + headers = json_encode(headers) + + src.method = method + src.url = url + src.body = body + src.headers = headers + +/datum/http_request/proc/execute_blocking() + _raw_response = rustg_http_request_blocking(method, url, body, headers) + +/datum/http_request/proc/begin_async() + if (in_progress) + CRASH("Attempted to re-use a request object.") + + id = rustg_http_request_async(method, url, body, headers) + + if (isnull(text2num(id))) + stack_trace("Proc error: [id]") + _raw_response = "Proc error: [id]" + else + in_progress = TRUE + +/datum/http_request/proc/is_complete() + if (isnull(id)) + return TRUE + + if (!in_progress) + return TRUE + + var/r = rustg_http_check_request(id) + + if (r == RUSTG_JOB_NO_RESULTS_YET) + return FALSE + else + _raw_response = r + in_progress = FALSE + return TRUE + +/datum/http_request/proc/into_response() + var/datum/http_response/R = new() + + try + var/list/L = json_decode(_raw_response) + R.status_code = L["status_code"] + R.headers = L["headers"] + R.body = L["body"] + catch + R.errored = TRUE + R.error = _raw_response + + return R + +/datum/http_response + var/status_code + var/body + var/list/headers + + var/errored = FALSE + var/error diff --git a/code/datums/hud.dm b/code/datums/hud.dm index c1811fb9b3..1c23d5f2a0 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -28,7 +28,8 @@ GLOBAL_LIST_INIT(huds, list( ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(), ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(), ANTAG_HUD_BLOODSUCKER = new/datum/atom_hud/antag/bloodsucker(), - ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag() + ANTAG_HUD_FUGITIVE = new/datum/atom_hud/antag(), + ANTAG_HUD_HERETIC = new/datum/atom_hud/antag/hidden() )) /datum/atom_hud diff --git a/code/datums/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm index bafb6fbf0e..8bee4f3d1c 100644 --- a/code/datums/looping_sounds/_looping_sound.dm +++ b/code/datums/looping_sounds/_looping_sound.dm @@ -23,10 +23,14 @@ var/end_sound var/chance var/volume = 100 + var/vary = FALSE var/max_loops var/direct + var/extra_range = 0 + var/falloff var/timerid + var/init_timerid /datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE) if(!mid_sounds) @@ -47,13 +51,16 @@ /datum/looping_sound/proc/start(atom/add_thing) if(add_thing) output_atoms |= add_thing - if(timerid) + if(timerid || init_timerid) return on_start() /datum/looping_sound/proc/stop(atom/remove_thing) if(remove_thing) output_atoms -= remove_thing + if(init_timerid) + deltimer(init_timerid) + init_timerid = null if(!timerid) return on_stop() @@ -80,7 +87,7 @@ if(direct) SEND_SOUND(thing, S) else - playsound(thing, S, volume) + playsound(thing, S, volume, vary, extra_range, falloff) /datum/looping_sound/proc/get_sound(starttime, _mid_sounds) . = _mid_sounds || mid_sounds @@ -92,7 +99,7 @@ if(start_sound) play(start_sound) start_wait = start_length - addtimer(CALLBACK(src, .proc/sound_loop), start_wait, TIMER_CLIENT_TIME) + init_timerid = addtimer(CALLBACK(src, .proc/sound_loop), start_wait, TIMER_CLIENT_TIME | TIMER_STOPPABLE) /datum/looping_sound/proc/on_stop() if(end_sound) diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm index 8241f685d7..1581323f89 100644 --- a/code/datums/martial/_martial.dm +++ b/code/datums/martial/_martial.dm @@ -44,11 +44,11 @@ //Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode. var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh) if(SEND_SIGNAL(D, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) - damage *= 1.5 + damage *= 1.2 if(!CHECK_MOBILITY(A, MOBILITY_STAND)) - damage *= 0.5 + damage *= 0.7 if(SEND_SIGNAL(A, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) - damage *= 0.25 + damage *= 0.8 return damage /datum/martial_art/proc/teach(mob/living/carbon/human/H, make_temporary = FALSE) diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm index e3c7726d61..4682595aec 100644 --- a/code/datums/martial/boxing.dm +++ b/code/datums/martial/boxing.dm @@ -58,12 +58,10 @@ var/datum/martial_art/boxing/style = new /obj/item/clothing/gloves/boxing/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == SLOT_GLOVES) + . = ..() + if(ishuman(user) && slot == SLOT_GLOVES) var/mob/living/carbon/human/H = user style.teach(H,TRUE) - return /obj/item/clothing/gloves/boxing/dropped(mob/user) . = ..() diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 50438d9d8d..3691b2fccc 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -196,9 +196,8 @@ var/datum/martial_art/krav_maga/style = new /obj/item/clothing/gloves/krav_maga/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == SLOT_GLOVES) + . = ..() + if(ishuman(user) && slot == SLOT_GLOVES) var/mob/living/carbon/human/H = user style.teach(H,1) @@ -224,8 +223,8 @@ /obj/item/clothing/gloves/krav_maga/combatglovesplus name = "combat gloves plus" desc = "These tactical gloves are fireproof and shock resistant, and using nanochip technology it teaches you the powers of krav maga." - icon_state = "combat" - item_state = "blackgloves" + icon_state = "fightglovesblack" + item_state = "fightglovesblack" siemens_coefficient = 0 permeability_coefficient = 0.05 strip_delay = 80 diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 82ddd90b42..7d884344f1 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -44,7 +44,7 @@ else playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1) log_combat(A, D, "strong punched (Sleeping Carp)")//so as to not double up on logging - D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting) + D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting, wound_bonus = CANT_WOUND) return TRUE ///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards @@ -56,7 +56,7 @@ playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1) var/atom/throw_target = get_edge_target_turf(D, A.dir) D.throw_at(throw_target, 7, 14, A) - D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST) + D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST, wound_bonus = CANT_WOUND, wound_bonus = CANT_WOUND) log_combat(A, D, "launchkicked (Sleeping Carp)") return TRUE @@ -66,14 +66,14 @@ A.do_attack_animation(D, ATTACK_EFFECT_KICK) playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1) if((D.mobility_flags & MOBILITY_STAND)) - D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD) + D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0) - D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) //A cit specific change form the tg port to really punish anyone who tries to stand up + D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) //A cit specific change form the tg port to really punish anyone who tries to stand up D.visible_message("[A] kicks [D] in the head, sending them face first into the floor!", \ "You are kicked in the head by [A], sending you crashing to the floor!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) else - D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD) - D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) + D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) + D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) D.drop_all_held_items() D.visible_message("[A] kicks [D] in the head!", \ "You are kicked in the head by [A]!", "You hear a sickening sound of flesh hitting flesh!", COMBAT_MESSAGE_RANGE, A) @@ -99,7 +99,7 @@ D.visible_message("[A] [atk_verb]s [D]!", \ "[A] [atk_verb]s you!", null, null, A) to_chat(A, "You [atk_verb] [D]!") - D.apply_damage(damage, BRUTE, affecting) + D.apply_damage(damage, BRUTE, affecting, wound_bonus = CANT_WOUND) playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1) if(CHECK_MOBILITY(D, MOBILITY_STAND) && damage >= stunthreshold) to_chat(D, "You stumble and fall!") @@ -180,14 +180,12 @@ to_chat(usr, "Keelhaul: Harm Grab. Kick opponents to the floor. Against prone targets, deal additional stamina damage and disarm them.") to_chat(usr, "In addition, your body has become incredibly resilient to most forms of attack. Weapons cannot readily pierce your hardened skin, and you are highly resistant to stuns and knockdowns, and can block all projectiles in Throw Mode. However, you are not invincible, and sustained damage will take it's toll. Avoid heat at all costs!") -/obj/item/twohanded/bostaff +/obj/item/staff/bostaff name = "bo staff" desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate." force = 10 w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK - force_unwielded = 10 - force_wielded = 24 throwforce = 20 throw_speed = 2 attack_verb = list("smashed", "slammed", "whacked", "thwacked") @@ -196,11 +194,29 @@ lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' block_chance = 50 + var/wielded = FALSE // track wielded status on item -/obj/item/twohanded/bostaff/update_icon_state() - icon_state = "bostaff[wielded]" +/obj/item/staff/bostaff/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) -/obj/item/twohanded/bostaff/attack(mob/target, mob/living/user) +/obj/item/staff/bostaff/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=10, force_wielded=24, icon_wielded="bostaff1") + +/// triggered on wield of two handed item +/obj/item/staff/bostaff/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/staff/bostaff/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/staff/bostaff/update_icon_state() + icon_state = "bostaff0" + +/obj/item/staff/bostaff/attack(mob/target, mob/living/user) add_fingerprint(user) if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50)) to_chat(user, "You club yourself over the head with [src].") @@ -249,7 +265,7 @@ else return ..() -/obj/item/twohanded/bostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +/obj/item/staff/bostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(!wielded) return BLOCK_NONE return ..() diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 87fcf78964..8dc1afba81 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -215,11 +215,17 @@ /datum/martial_art/wrestling/proc/FlipAnimation(mob/living/carbon/human/D) set waitfor = FALSE + var/transform_before + var/laying_before if (D) + transform_before = D.transform + laying_before = D.lying animate(D, transform = matrix(180, MATRIX_ROTATE), time = 1, loop = 0) sleep(15) if (D) - animate(D, transform = null, time = 1, loop = 0) + if(transform_before && laying_before == D.lying) //animate calls sleep so this should be fine and stop a bug with transforms + D.transform = transform_before + animate(D, transform = null, time = 1, loop = 0) /datum/martial_art/wrestling/proc/slam(mob/living/carbon/human/A, mob/living/carbon/human/D) if(!D) @@ -377,7 +383,7 @@ var/turf/ST = null var/falling = 0 var/damage = damage_roll(A,D) - + for (var/obj/O in oview(1, A)) if (O.density == 1) if (O == A) @@ -415,11 +421,17 @@ to_chat(A, "You can't drop onto [D] from here!") return FALSE + var/transform_before + var/laying_before if(A) + transform_before = A.transform + laying_before = A.lying animate(A, transform = matrix(90, MATRIX_ROTATE), time = 1, loop = 0) sleep(10) if(A) - animate(A, transform = null, time = 1, loop = 0) + if(transform_before && laying_before == A.lying) //if they suddenly dropped to the floor between this period, don't revert their animation + animate(A, transform = null, time = 1, loop = 0) + A.transform = transform_before A.forceMove(D.loc) @@ -472,12 +484,10 @@ var/datum/martial_art/wrestling/style = new /obj/item/storage/belt/champion/wrestling/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == SLOT_BELT) + . = ..() + if(ishuman(user) && slot == SLOT_BELT) var/mob/living/carbon/human/H = user style.teach(H,1) - return /obj/item/storage/belt/champion/wrestling/dropped(mob/user) . = ..() diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 1a8ce755e1..5148aab4ac 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -6,8 +6,6 @@ Simple datum which is instanced once per type and is used for every object of sa /datum/material var/name = "material" var/desc = "its..stuff." - ///Var that's mostly used by science machines to identify specific materials, should most likely be phased out at some point - var/id = "mat" ///Base color of the material, is used for greyscale. Item isn't changed in color if this is null. var/color ///Base alpha of the material, is used for greyscale icons. @@ -26,6 +24,20 @@ Simple datum which is instanced once per type and is used for every object of sa var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1) ///How beautiful is this material per unit? var/beauty_modifier = 0 + ///Can be used to override the sound items make, lets add some SLOSHing. + var/item_sound_override + ///Can be used to override the stepsound a turf makes. MORE SLOOOSH + var/turf_sound_override + ///what texture icon state to overlay + var/texture_layer_icon_state + ///a cached filter for the texture icon + var/cached_texture_filter + +/datum/material/New() + . = ..() + if(texture_layer_icon_state) + var/texture_icon = icon('icons/materials/composite.dmi', texture_layer_icon_state) + cached_texture_filter = filter(type="layer", icon=texture_icon, blend_mode = BLEND_INSET_OVERLAY) ///This proc is called when the material is added to an object. /datum/material/proc/on_applied(atom/source, amount, material_flags) @@ -34,16 +46,27 @@ Simple datum which is instanced once per type and is used for every object of sa source.add_atom_colour(color, FIXED_COLOUR_PRIORITY) if(alpha) source.alpha = alpha + if(texture_layer_icon_state) + ADD_KEEP_TOGETHER(source, MATERIAL_SOURCE(src)) + source.filters += cached_texture_filter if(material_flags & MATERIAL_ADD_PREFIX) source.name = "[name] [source.name]" - if(istype(source, /obj)) //objs - on_applied_obj(source, amount, material_flags) - if(beauty_modifier) addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0) + if(istype(source, /obj)) //objs + on_applied_obj(source, amount, material_flags) + + else if(isturf(source, /turf)) //turfs + on_applied_turf(source, amount, material_flags) + + source.mat_update_desc(src) + +///This proc is called when a material updates an object's description +/atom/proc/mat_update_desc(/datum/material/mat) + return ///This proc is called when the material is added to an object specifically. /datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags) if(material_flags & MATERIAL_AFFECT_STATISTICS) @@ -61,6 +84,24 @@ Simple datum which is instanced once per type and is used for every object of sa for(var/i in current_armor) temp_armor_list[i] = current_armor[i] * armor_modifiers[i] o.armor = getArmor(arglist(temp_armor_list)) + if(!isitem(o)) + return + var/obj/item/I = o + if(!item_sound_override) + return + I.hitsound = item_sound_override + I.usesound = item_sound_override + I.throwhitsound = item_sound_override + +/datum/material/proc/on_applied_turf(var/turf/T, amount, material_flags) + if(isopenturf(T)) + if(!turf_sound_override) + return + var/turf/open/O = T + O.footstep = turf_sound_override + O.barefootstep = turf_sound_override + O.clawfootstep = turf_sound_override + O.heavyfootstep = turf_sound_override ///This proc is called when the material is removed from an object. /datum/material/proc/on_removed(atom/source, material_flags) @@ -68,6 +109,9 @@ Simple datum which is instanced once per type and is used for every object of sa if(color) source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color) source.alpha = initial(source.alpha) + if(texture_layer_icon_state) + source.filters -= cached_texture_filter + REMOVE_KEEP_TOGETHER(source, MATERIAL_SOURCE(src)) if(material_flags & MATERIAL_ADD_PREFIX) source.name = initial(source.name) @@ -75,10 +119,16 @@ Simple datum which is instanced once per type and is used for every object of sa if(istype(source, /obj)) //objs on_removed_obj(source, material_flags) + else if(istype(source, /turf)) //turfs + on_removed_turf(source, material_flags) + ///This proc is called when the material is removed from an object specifically. -/datum/material/proc/on_removed_obj(var/obj/o, amount, material_flags) +/datum/material/proc/on_removed_obj(obj/o, material_flags) if(material_flags & MATERIAL_AFFECT_STATISTICS) var/new_max_integrity = initial(o.max_integrity) o.modify_max_integrity(new_max_integrity) o.force = initial(o.force) o.throwforce = initial(o.throwforce) + +/datum/material/proc/on_removed_turf(turf/T, material_flags) + return diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index d4921a04d2..1469965b57 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -1,21 +1,19 @@ ///Has no special properties. /datum/material/iron name = "iron" - id = "iron" desc = "Common iron ore often found in sedimentary and igneous layers of the crust." color = "#878687" - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/metal value_per_unit = 0.0025 ///Breaks extremely easily but is transparent. /datum/material/glass name = "glass" - id = "glass" desc = "Glass forged by melting sand." color = "#88cdf1" alpha = 150 - categories = list(MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) integrity_modifier = 0.1 sheet_type = /obj/item/stack/sheet/glass value_per_unit = 0.0025 @@ -30,10 +28,9 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Has no special properties. Could be good against vampires in the future perhaps. /datum/material/silver name = "silver" - id = "silver" desc = "Silver" color = list(255/255, 284/255, 302/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/silver value_per_unit = 0.025 beauty_modifier = 0.075 @@ -41,11 +38,10 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Slight force increase /datum/material/gold name = "gold" - id = "gold" desc = "Gold" color = list(340/255, 240/255, 50/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //gold is shiny, but not as bright as bananium strength_modifier = 1.2 - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/gold value_per_unit = 0.0625 beauty_modifier = 0.15 @@ -54,11 +50,10 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Has no special properties /datum/material/diamond name = "diamond" - id = "diamond" desc = "Highly pressurized carbon" color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) alpha = 132 - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond value_per_unit = 0.25 beauty_modifier = 0.3 @@ -67,10 +62,9 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Is slightly radioactive /datum/material/uranium name = "uranium" - id = "uranium" desc = "Uranium" color = rgb(48, 237, 26) - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/uranium value_per_unit = 0.05 beauty_modifier = 0.3 //It shines so beautiful @@ -88,10 +82,9 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Adds firestacks on hit (Still needs support to turn into gas on destruction) /datum/material/plasma name = "plasma" - id = "plasma" desc = "Isn't plasma a state of matter? Oh whatever." color = list(298/255, 46/255, 352/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/plasma value_per_unit = 0.1 beauty_modifier = 0.15 @@ -111,7 +104,6 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Can cause bluespace effects on use. (Teleportation) (Not yet implemented) /datum/material/bluespace name = "bluespace crystal" - id = "bluespace_crystal" desc = "Crystals with bluespace properties" color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) alpha = 200 @@ -123,10 +115,9 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Honks and slips /datum/material/bananium name = "bananium" - id = "bananium" desc = "Material with hilarious properties" color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/bananium value_per_unit = 0.5 beauty_modifier = 0.5 @@ -146,11 +137,10 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Mediocre force increase /datum/material/titanium name = "titanium" - id = "titanium" desc = "Titanium" color = "#b3c0c7" strength_modifier = 1.3 - categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/titanium value_per_unit = 0.0625 beauty_modifier = 0.05 @@ -158,11 +148,10 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/runite name = "runite" - id = "runite" desc = "Runite" color = "#3F9995" strength_modifier = 1.3 - categories = list(MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/runite beauty_modifier = 0.5 armor_modifiers = list("melee" = 1.35, "bullet" = 2, "laser" = 0.5, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 1.4, "acid" = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle. @@ -170,7 +159,6 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Force decrease /datum/material/plastic name = "plastic" - id = "plastic" desc = "Plastic" color = "#caccd9" strength_modifier = 0.85 @@ -182,7 +170,6 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Force decrease and mushy sound effect. (Not yet implemented) /datum/material/biomass name = "biomass" - id = "biomass" desc = "Organic matter" color = "#735b4d" strength_modifier = 0.8 @@ -190,12 +177,11 @@ Unless you know what you're doing, only use the first three numbers. They're in /datum/material/wood name = "wood" - id = "wood" desc = "Flexible, durable, but flamable. Hard to come across in space." color = "#bb8e53" strength_modifier = 0.5 sheet_type = /obj/item/stack/sheet/mineral/wood - categories = list(MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) value_per_unit = 0.06 beauty_modifier = 0.1 armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 0.4, "energy" = 0.4, "bomb" = 1, "bio" = 0.2, "rad" = 0, "fire" = 0, "acid" = 0.3) @@ -215,11 +201,10 @@ Unless you know what you're doing, only use the first three numbers. They're in ///Stronk force increase /datum/material/adamantine name = "adamantine" - id = "adamantine" desc = "A powerful material made out of magic, I mean science!" color = "#6d7e8e" strength_modifier = 1.5 - categories = list(MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/adamantine value_per_unit = 0.25 beauty_modifier = 0.4 @@ -228,10 +213,9 @@ Unless you know what you're doing, only use the first three numbers. They're in ///RPG Magic. (Admin only) /datum/material/mythril name = "mythril" - id = "mythril" desc = "How this even exists is byond me" color = "#f2d5d7" - categories = list(MAT_CATEGORY_RIGID = TRUE) + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) sheet_type = /obj/item/stack/sheet/mineral/mythril value_per_unit = 0.75 beauty_modifier = 0.5 @@ -246,3 +230,134 @@ Unless you know what you're doing, only use the first three numbers. They're in . = ..() if(istype(source, /obj/item)) qdel(source.GetComponent(/datum/component/fantasy)) + +//I don't like sand. It's coarse, and rough, and irritating, and it gets everywhere. +/datum/material/sand + name = "sand" + desc = "You know, it's amazing just how structurally sound sand can be." + color = "#EDC9AF" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/sandblock + value_per_unit = 0.001 + strength_modifier = 0.5 + integrity_modifier = 0.1 + armor_modifiers = list("melee" = 0.25, "bullet" = 0.25, "laser" = 1.25, "energy" = 0.25, "bomb" = 0.25, "bio" = 0.25, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) + beauty_modifier = 0.25 + turf_sound_override = FOOTSTEP_SAND + texture_layer_icon_state = "sand" + +//And now for our lavaland dwelling friends, sand, but in stone form! Truly revolutionary. +/datum/material/sandstone + name = "sandstone" + desc = "Bialtaakid 'ant taerif ma hdha." + color = "#B77D31" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/mineral/sandstone + value_per_unit = 0.0025 + armor_modifiers = list("melee" = 0.5, "bullet" = 0.5, "laser" = 1.25, "energy" = 0.5, "bomb" = 0.5, "bio" = 0.25, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) + beauty_modifier = 0.3 + turf_sound_override = FOOTSTEP_WOOD + texture_layer_icon_state = "brick" + +/datum/material/snow + name = "snow" + desc = "There's no business like snow business." + color = "#FFFFFF" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/mineral/snow + value_per_unit = 0.0025 + armor_modifiers = list("melee" = 0.25, "bullet" = 0.25, "laser" = 0.25, "energy" = 0.25, "bomb" = 0.25, "bio" = 0.25, "rad" = 1.5, "fire" = 0.25, "acid" = 1.5) + beauty_modifier = 0.3 + turf_sound_override = FOOTSTEP_SAND + texture_layer_icon_state = "sand" + +/datum/material/runedmetal + name = "runed metal" + desc = "Mir'ntrath barhah Nar'sie." + color = "#3C3434" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/runed_metal + value_per_unit = 0.75 + armor_modifiers = list("melee" = 1.2, "bullet" = 1.2, "laser" = 1, "energy" = 1, "bomb" = 1.2, "bio" = 1.2, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) + beauty_modifier = -0.15 + texture_layer_icon_state = "runed" + +/datum/material/bronze + name = "bronze" + desc = "Clock Cult? Never heard of it." + color = "#92661A" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/bronze + value_per_unit = 0.025 + armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) + beauty_modifier = 0.2 + +/datum/material/paper + name = "paper" + desc = "Ten thousand folds of pure starchy power." + color = "#E5DCD5" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/paperframes + value_per_unit = 0.0025 + armor_modifiers = list("melee" = 0.1, "bullet" = 0.1, "laser" = 0.1, "energy" = 0.1, "bomb" = 0.1, "bio" = 0.1, "rad" = 1.5, "fire" = 0, "acid" = 1.5) + beauty_modifier = 0.3 + turf_sound_override = FOOTSTEP_SAND + texture_layer_icon_state = "paper" + +/datum/material/paper/on_applied_obj(obj/source, amount, material_flags) + . = ..() + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/paper = source + paper.resistance_flags |= FLAMMABLE + paper.obj_flags |= UNIQUE_RENAME + +/datum/material/paper/on_removed_obj(obj/source, material_flags) + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/paper = source + paper.resistance_flags &= ~FLAMMABLE + return ..() + +/datum/material/cardboard + name = "cardboard" + desc = "They say cardboard is used by hobos to make incredible things." + color = "#5F625C" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/cardboard + value_per_unit = 0.003 + armor_modifiers = list("melee" = 0.25, "bullet" = 0.25, "laser" = 0.25, "energy" = 0.25, "bomb" = 0.25, "bio" = 0.25, "rad" = 1.5, "fire" = 0, "acid" = 1.5) + beauty_modifier = -0.1 + +/datum/material/cardboard/on_applied_obj(obj/source, amount, material_flags) + . = ..() + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/cardboard = source + cardboard.resistance_flags |= FLAMMABLE + cardboard.obj_flags |= UNIQUE_RENAME + +/datum/material/cardboard/on_removed_obj(obj/source, material_flags) + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/cardboard = source + cardboard.resistance_flags &= ~FLAMMABLE + return ..() + +/datum/material/bone + name = "bone" + desc = "Man, building with this will make you the coolest caveman on the block." + color = "#e3dac9" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/bone + value_per_unit = 0.05 + armor_modifiers = list("melee" = 1.2, "bullet" = 0.75, "laser" = 0.75, "energy" = 1.2, "bomb" = 1, "bio" = 1, "rad" = 1.5, "fire" = 1.5, "acid" = 1.5) + beauty_modifier = -0.2 + +/datum/material/bamboo + name = "bamboo" + desc = "If it's good enough for pandas, it's good enough for you." + color = "#339933" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/mineral/bamboo + value_per_unit = 0.0025 + armor_modifiers = list("melee" = 0.5, "bullet" = 0.5, "laser" = 0.5, "energy" = 0.5, "bomb" = 0.5, "bio" = 0.51, "rad" = 1.5, "fire" = 0.5, "acid" = 1.5) + beauty_modifier = 0.2 + turf_sound_override = FOOTSTEP_WOOD + texture_layer_icon_state = "bamboo" diff --git a/code/datums/materials/meat.dm b/code/datums/materials/meat.dm new file mode 100644 index 0000000000..14a373f2d2 --- /dev/null +++ b/code/datums/materials/meat.dm @@ -0,0 +1,32 @@ +///It's gross, gets the name of it's owner, and is all kinds of fucked up +/datum/material/meat + name = "meat" + desc = "Meat" + color = rgb(214, 67, 67) + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/meat + value_per_unit = 0.05 + beauty_modifier = -0.3 + strength_modifier = 0.7 + armor_modifiers = list("melee" = 0.3, "bullet" = 0.3, "laser" = 1.2, "energy" = 1.2, "bomb" = 0.3, "bio" = 0, "rad" = 0.7, "fire" = 1, "acid" = 1) + item_sound_override = 'sound/effects/meatslap.ogg' + turf_sound_override = FOOTSTEP_MEAT + texture_layer_icon_state = "meat" + +/datum/material/meat/on_removed(atom/source, material_flags) + . = ..() + qdel(source.GetComponent(/datum/component/edible)) + +/datum/material/meat/on_applied_obj(obj/O, amount, material_flags) + . = ..() + O.obj_flags |= UNIQUE_RENAME //So you can name it after the person its made from, a depressing comprimise. + make_edible(O, amount, material_flags) + +/datum/material/meat/on_applied_turf(turf/T, amount, material_flags) + . = ..() + make_edible(T, amount, material_flags) + +/datum/material/meat/proc/make_edible(atom/source, amount, material_flags) + var/nutriment_count = 3 * (amount / MINERAL_MATERIAL_AMOUNT) + var/oil_count = 2 * (amount / MINERAL_MATERIAL_AMOUNT) + source.AddComponent(/datum/component/edible, list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/cooking_oil = oil_count), null, RAW | MEAT | GROSS, null, 30, list("Fleshy")) diff --git a/code/datums/materials/pizza.dm b/code/datums/materials/pizza.dm new file mode 100644 index 0000000000..2a9542234f --- /dev/null +++ b/code/datums/materials/pizza.dm @@ -0,0 +1,30 @@ +/datum/material/pizza + name = "pizza" + desc = "~Jamme, jamme, n'coppa, jamme ja! Jamme, jamme, n'coppa jamme ja, funi-culi funi-cala funi-culi funi-cala!! Jamme jamme ja funiculi funicula!~" + color = "#FF9F23" + categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE) + sheet_type = /obj/item/stack/sheet/pizza + value_per_unit = 0.05 + beauty_modifier = 0.1 + strength_modifier = 0.7 + armor_modifiers = list("melee" = 0.3, "bullet" = 0.3, "laser" = 1.2, "energy" = 1.2, "bomb" = 0.3, "bio" = 0, "rad" = 0.7, "fire" = 1, "acid" = 1) + item_sound_override = 'sound/effects/meatslap.ogg' + turf_sound_override = FOOTSTEP_MEAT + texture_layer_icon_state = "pizza" + +/datum/material/pizza/on_removed(atom/source, material_flags) + . = ..() + qdel(source.GetComponent(/datum/component/edible)) + +/datum/material/pizza/on_applied_obj(obj/O, amount, material_flags) + . = ..() + make_edible(O, amount, material_flags) + +/datum/material/pizza/on_applied_turf(turf/T, amount, material_flags) + . = ..() + make_edible(T, amount, material_flags) + +/datum/material/pizza/proc/make_edible(atom/source, amount, material_flags) + var/nutriment_count = 3 * (amount / MINERAL_MATERIAL_AMOUNT) + var/oil_count = 2 * (amount / MINERAL_MATERIAL_AMOUNT) + source.AddComponent(/datum/component/edible, list(/datum/reagent/consumable/nutriment = nutriment_count, /datum/reagent/consumable/cooking_oil = oil_count), null, GRAIN | MEAT | DAIRY | VEGETABLES, null, 30, list("crust", "tomato", "cheese", "meat")) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 2a6835cc23..cb99fdc5a3 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -66,8 +66,11 @@ /// Our skill holder. var/datum/skill_holder/skill_holder + ///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not + var/mob/original_character + /datum/mind/New(var/key) - skill_holder = new() + skill_holder = new(src) src.key = key soulOwner = src martial_art = default_martial_art @@ -124,6 +127,8 @@ 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 + if(new_character.client) + LAZYCLEARLIST(new_character.client.recent_examines) current.update_atom_languages() //CIT CHANGE - makes arousal update when transfering bodies diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index f5692c297a..38b004a657 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -77,10 +77,14 @@ description = "Pull it out!\n" mood_change = -7 -/datum/mood_event/table - description = "Someone threw me on a table!\n" - mood_change = -2 - timeout = 2 MINUTES +/datum/mood_event/table_limbsmash + description = "That fucking table, man that hurts...\n" + mood_change = -3 + timeout = 3 MINUTES + +/datum/mood_event/table_limbsmash/add_effects(obj/item/bodypart/banged_limb) + if(banged_limb) + description = "My fucking [banged_limb.name], man that hurts...\n" /datum/mood_event/table/add_effects() if(ishuman(owner)) @@ -158,6 +162,11 @@ mood_change = -8 timeout = 3 MINUTES +/datum/mood_event/gates_of_mansus + description = "LIVING IN A PERFORMANCE IS WORSE THAN DEATH\n" + mood_change = -25 + timeout = 4 MINUTES + //These are unused so far but I want to remember them to use them later /datum/mood_event/cloned_corpse @@ -270,3 +279,13 @@ description = "I've produced better art than that from my ass.\n" mood_change = -2 timeout = 1200 + +/datum/mood_event/tripped + description = "I can't believe I fell for the oldest trick in the book!\n" + mood_change = -6 + timeout = 2 MINUTES + +/datum/mood_event/untied + description = "I hate when my shoes come untied!\n" + mood_change = -3 + timeout = 1 MINUTES diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index 95177f6869..b73756c2b1 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -70,6 +70,11 @@ mood_change = 40 //maybe being a cultist isnt that bad after all hidden = TRUE +/datum/mood_event/heretics + description = "THE HIGHER I RISE, THE MORE I SEE.\n" + mood_change = 12 //maybe being a cultist isnt that bad after all + hidden = TRUE + /datum/mood_event/family_heirloom description = "My family heirloom is safe with me.\n" mood_change = 1 @@ -196,3 +201,7 @@ 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 + +/datum/mood_event/cleared_stomach + description = "Feels nice to get that out of the way!\n" + mood_change = 3 diff --git a/code/datums/mood_events/needs_events.dm b/code/datums/mood_events/needs_events.dm index 962681eb94..b307bcb0aa 100644 --- a/code/datums/mood_events/needs_events.dm +++ b/code/datums/mood_events/needs_events.dm @@ -19,6 +19,27 @@ description = "I'm starving!\n" mood_change = -15 +//charge +/datum/mood_event/supercharged + description = "I can't possibly keep all this power inside, I need to release some quick!\n" + mood_change = -10 + +/datum/mood_event/overcharged + description = "I feel dangerously overcharged, perhaps I should release some power.\n" + mood_change = -4 + +/datum/mood_event/charged + description = "I feel the power in my veins!\n" + mood_change = 6 + +/datum/mood_event/lowpower + description = "My power is running low, I should go charge up somewhere.\n" + mood_change = -6 + +/datum/mood_event/decharged + description = "I'm in desperate need of some electricity!\n" + mood_change = -10 + //Disgust /datum/mood_event/gross description = "I saw something gross.\n" diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm index db739c5100..fb5f6ed5f6 100644 --- a/code/datums/mutations/_mutations.dm +++ b/code/datums/mutations/_mutations.dm @@ -42,6 +42,7 @@ var/synchronizer_coeff = -1 //makes the mutation hurt the user less var/power_coeff = -1 //boosts mutation strength var/energy_coeff = -1 //lowers mutation cooldown + var/list/valid_chrom_list = list() //List of strings of valid chromosomes this mutation can accept. /datum/mutation/human/New(class_ = MUT_OTHER, timer, datum/mutation/human/copymut) . = ..() @@ -90,7 +91,7 @@ /datum/mutation/human/proc/get_visual_indicator() return -/datum/mutation/human/proc/on_attack_hand(atom/target, proximity) +/datum/mutation/human/proc/on_attack_hand(atom/target, proximity, act_intent, unarmed_attack_flags) return /datum/mutation/human/proc/on_ranged_attack(atom/target, mouseparams) @@ -167,6 +168,7 @@ energy_coeff = HM.energy_coeff mutadone_proof = HM.mutadone_proof can_chromosome = HM.can_chromosome + valid_chrom_list = HM.valid_chrom_list /datum/mutation/human/proc/remove_chromosome() stabilizer_coeff = initial(stabilizer_coeff) @@ -192,3 +194,23 @@ power.panel = "Genetic" owner.AddSpell(power) return TRUE + +// Runs through all the coefficients and uses this to determine which chromosomes the +// mutation can take. Stores these as text strings in a list. +/datum/mutation/human/proc/update_valid_chromosome_list() + valid_chrom_list.Cut() + + if(can_chromosome == CHROMOSOME_NEVER) + valid_chrom_list += "none" + return + + valid_chrom_list += "Reinforcement" + + if(stabilizer_coeff != -1) + valid_chrom_list += "Stabilizer" + if(synchronizer_coeff != -1) + valid_chrom_list += "Synchronizer" + if(power_coeff != -1) + valid_chrom_list += "Power" + if(energy_coeff != -1) + valid_chrom_list += "Energetic" diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index 1475cfa356..bd9ecaeeaa 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -42,6 +42,7 @@ school = "evocation" charge_max = 600 clothes_req = NONE + antimagic_allowed = TRUE range = 20 base_icon_state = "fireball" action_icon_state = "fireball0" @@ -122,6 +123,7 @@ desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly." school = "evocation" clothes_req = NONE + antimagic_allowed = TRUE charge_max = 600 invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!" invocation_type = "shout" @@ -155,6 +157,7 @@ dropmessage = "You let the electricity from your hand dissipate." hand_path = /obj/item/melee/touch_attack/shock charge_max = 400 + antimagic_allowed = TRUE clothes_req = NONE action_icon_state = "zap" @@ -212,6 +215,7 @@ desc = "Get a scent off of the item you're currently holding to track it. With an empty hand, you'll track the scent you've remembered." charge_max = 100 clothes_req = NONE + antimagic_allowed = TRUE range = -1 include_user = TRUE action_icon_state = "nose" @@ -222,9 +226,8 @@ /obj/effect/proc_holder/spell/targeted/olfaction/cast(list/targets, mob/living/user = usr) //can we sniff? is there miasma in the air? var/datum/gas_mixture/air = user.loc.return_air() - var/list/cached_gases = air.gases - if(cached_gases[/datum/gas/miasma]) + if(air.get_moles(/datum/gas/miasma)) user.adjust_disgust(sensitivity * 45) to_chat(user, "With your overly sensitive nose, you get a whiff of stench and feel sick! Try moving to a cleaner area!") return @@ -290,6 +293,7 @@ name = "Drop a limb" desc = "Concentrate to make a random limb pop right off your body." clothes_req = NONE + antimagic_allowed = TRUE charge_max = 100 action_icon_state = "autotomy" @@ -327,6 +331,7 @@ name = "Lay Web" desc = "Drops a web. Only you will be able to traverse your web easily, making it pretty good for keeping you safe." clothes_req = NONE + antimagic_allowed = TRUE charge_max = 4 SECONDS //the same time to lay a web action_icon = 'icons/mob/actions/actions_genetic.dmi' action_icon_state = "lay_web" @@ -368,6 +373,7 @@ name = "Launch spike" desc = "Shoot your tongue out in the direction you're facing, embedding it and dealing damage until they remove it." clothes_req = NONE + antimagic_allowed = TRUE charge_max = 100 action_icon = 'icons/mob/actions/actions_genetic.dmi' action_icon_state = "spike" @@ -404,7 +410,7 @@ throw_speed = 4 embedding = list("embedded_pain_multiplier" = 4, "embed_chance" = 100, "embedded_fall_chance" = 0) w_class = WEIGHT_CLASS_SMALL - sharpness = IS_SHARP + sharpness = SHARP_POINTY var/mob/living/carbon/human/fired_by /// if we missed our target var/missed = TRUE diff --git a/code/datums/mutations/antenna.dm b/code/datums/mutations/antenna.dm index 978802fd80..ad08b8ebdc 100644 --- a/code/datums/mutations/antenna.dm +++ b/code/datums/mutations/antenna.dm @@ -90,6 +90,8 @@ to_chat(user, "You catch some drifting memories of their past conversations...") for(var/spoken_memory in recent_speech) to_chat(user, "[recent_speech[spoken_memory]]") + if(usr in GLOB.rockpaperscissors_players) + to_chat(user, "They're planning on playing [GLOB.rockpaperscissors_players[usr][1]]") if(iscarbon(M)) var/mob/living/carbon/human/H = M to_chat(user, "You find that their intent is to [H.a_intent]...") diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 4f8cd6b25e..5d363124d9 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -19,9 +19,31 @@ SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "hulk", /datum/mood_event/hulk) RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech) -/datum/mutation/human/hulk/on_attack_hand(atom/target, proximity) - if(proximity) //no telekinetic hulk attack - return target.attack_hulk(owner) +/datum/mutation/human/hulk/on_attack_hand(atom/target, proximity, act_intent, unarmed_attack_flags) + if(proximity && (act_intent == INTENT_HARM)) //no telekinetic hulk attack + if(!owner.CheckActionCooldown(CLICK_CD_MELEE)) + return INTERRUPT_UNARMED_ATTACK | NO_AUTO_CLICKDELAY_HANDLING + owner.DelayNextAction() + target.attack_hulk(owner) + return INTERRUPT_UNARMED_ATTACK | NO_AUTO_CLICKDELAY_HANDLING + +/** + *Checks damage of a hulk's arm and applies bone wounds as necessary. + * + *Called by specific atoms being attacked, such as walls. If an atom + *does not call this proc, than punching that atom will not cause + *arm breaking (even if the atom deals recoil damage to hulks). + *Arguments: + *arg1 is the arm to evaluate damage of and possibly break. + */ +/datum/mutation/human/hulk/proc/break_an_arm(obj/item/bodypart/arm) + switch(arm.brute_dam) + if(45 to 50) + arm.force_wound_upwards(/datum/wound/blunt/critical) + if(41 to 45) + arm.force_wound_upwards(/datum/wound/blunt/severe) + if(35 to 41) + arm.force_wound_upwards(/datum/wound/blunt/moderate) /datum/mutation/human/hulk/on_life() if(owner.health < 0) diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm index d4db7e34c2..531837e583 100644 --- a/code/datums/mutations/speech.dm +++ b/code/datums/mutations/speech.dm @@ -14,7 +14,7 @@ /datum/mutation/human/wacky name = "Wacky" - desc = "Unknown." + desc = "Unknown." quality = MINOR_NEGATIVE text_gain_indication = "You feel an off sensation in your voicebox." text_lose_indication = "The off sensation passes." diff --git a/code/datums/radiation_wave.dm b/code/datums/radiation_wave.dm index fe018a8761..8dc3b64e16 100644 --- a/code/datums/radiation_wave.dm +++ b/code/datums/radiation_wave.dm @@ -105,7 +105,6 @@ // modify the ignored_things list in __HELPERS/radiation.dm instead var/static/list/blacklisted = typecacheof(list( /turf, - /mob, /obj/structure/cable, /obj/machinery/atmospherics, /obj/item/ammo_casing, diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm index 5d86290f8f..64b8692ccd 100644 --- a/code/datums/ruins/space.dm +++ b/code/datums/ruins/space.dm @@ -325,6 +325,12 @@ name = "Abductor Replication Lab" description = "Some scientists tried and almost succeeded to recreate abductor tools. Somewhat slower and a bit less modern than their originals, these tools are the best you can get if you aren't an alien." +/datum/map_template/ruin/space/spacediner + id = "spacediner" + suffix = "spacediner.dmm" + name = "Space Diner" + description = "Come, traveler of the bluespace planes. Sit, enjoy a drink and take one of the fair maidens for a night. The exit is the way you came in, via that teleporter thingy, but do remember to stay safe." + //Space ruins for the station z /datum/map_template/ruin/spacenearstation prefix = "_maps/RandomRuins/SpaceRuinsStation/" diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm index 5282156042..d6b73f96ed 100644 --- a/code/datums/shuttles.dm +++ b/code/datums/shuttles.dm @@ -104,6 +104,9 @@ rack.AddComponent(/datum/component/magnetic_catch) //Whatever special stuff you want +/datum/map_template/shuttle/proc/post_load(obj/docking_port/mobile/M) + return + /datum/map_template/shuttle/proc/on_bought() return @@ -462,6 +465,10 @@ suffix = "whiteship_pod" name = "Salvage Pod" +/datum/map_template/shuttle/whiteship/cog + suffix = "cog" + name = "NT Prisoner Transport" + /datum/map_template/shuttle/cargo/box suffix = "box" name = "supply shuttle (Box)" @@ -628,4 +635,4 @@ /datum/map_template/shuttle/hunter/bounty suffix = "bounty" - name = "Bounty Hunter Ship" \ No newline at end of file + name = "Bounty Hunter Ship" diff --git a/code/datums/skills/_check_skills.dm b/code/datums/skills/_check_skills.dm index a94c7c95ba..91b36a123f 100644 --- a/code/datums/skills/_check_skills.dm +++ b/code/datums/skills/_check_skills.dm @@ -11,6 +11,69 @@ if(!mind.skill_holder) 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_html_readout()) - B.open() + + mind.skill_holder.ui_interact(src) + +/datum/skill_holder/ui_state(mob/user) + return GLOB.always_state + +/datum/skill_holder/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SkillPanel", "[owner.name]'s Skills") + ui.set_autoupdate(FALSE) + ui.open() + else if(need_static_data_update) + update_static_data(user) + need_static_data_update = FALSE + +/datum/skill_holder/ui_static_data(mob/user) + . = list() + .["skills"] = list() + for(var/path in GLOB.skill_datums) + var/datum/skill/S = GLOB.skill_datums[path] + var/list/dat = S.get_skill_data(src) + if(islist(dat["modifiers"])) + dat["modifiers"] = jointext(dat["modifiers"], ", ") + dat["percent_base"] = (dat["value_base"] / dat["max_value"]) + dat["percent_mod"] = (dat["value_mod"] / dat["max_value"]) + .["skills"] += list(dat) + +/datum/skill_holder/ui_data(mob/user) + . = list() + .["playername"] = owner.name + .["see_skill_mods"] = see_skill_mods + .["admin"] = check_rights(R_DEBUG, FALSE) + +/datum/skill_holder/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("toggle_mods") + see_skill_mods = !see_skill_mods + return TRUE + if ("adj_exp") + if(!check_rights(R_DEBUG)) + return + var/skill = text2path(params["skill"]) + var/number = input("Please insert the amount of experience/progress you'd like to add/subtract:") as num|null + if (number) + owner.set_skill_value(skill, owner.get_skill_value(skill, FALSE) + number) + return TRUE + if ("set_exp") + if(!check_rights(R_DEBUG)) + return + var/skill = text2path(params["skill"]) + var/number = input("Please insert the number you want to set the player's exp/progress to:") as num|null + if (!isnull(number)) + owner.set_skill_value(skill, number) + return TRUE + if ("set_lvl") + if(!check_rights(R_DEBUG)) + return + var/datum/skill/level/S = GLOB.skill_datums[text2path(params["skill"])] + var/number = input("Please insert a whole number between 0[S.associative ? " ([S.unskilled_tier])" : ""] and [S.max_levels][S.associative ? " ([S.levels[S.max_levels]])" : ""] corresponding to the level you'd like to set the player to.") as num|null + if (number >= 0 && number <= S.max_levels) + owner.set_skill_value(S.type, S.get_skill_level_value(number)) + return TRUE diff --git a/code/datums/skills/_skill.dm b/code/datums/skills/_skill.dm index 571a8274d8..eecf416b1b 100644 --- a/code/datums/skills/_skill.dm +++ b/code/datums/skills/_skill.dm @@ -8,6 +8,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) continue S = new path .[S.type] = S + . = sortTim(., /proc/cmp_skill_categories, TRUE) /** * Skill datums @@ -32,8 +33,14 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) var/base_multiplier = 1 /// Value added to the base multiplier depending on overall competency compared to maximum value/level. var/competency_multiplier = 1 + /// Experience gain multiplier gained from using items. + var/item_skill_gain_multi = 1 + /// Skill gain quantisation + var/skill_gain_quantisation = 0.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) + /// Index of this skill in the UI + var/ui_category = SKILL_UI_CAT_MISC /** * Ensures what someone's setting as a value for this skill is valid. @@ -57,10 +64,28 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) return new_value > existing /** - * Standard value "render" + * Get a list of data used in the skill panel menu. */ -/datum/skill/proc/standard_render_value(value, level) - return value +/datum/skill/proc/get_skill_data(datum/skill_holder/H) + var/skill_value = H.owner.get_skill_value(type, FALSE) + . = list( + "name" = name, + "desc" = desc, + "path" = type, + "value_base" = skill_value, + "value_mod" = skill_value, + "modifiers" = "None", + "max_value" = 1 //To avoid division by zero later on. + ) + var/list/mods = LAZYACCESS(H.skill_value_mods, type) + if(mods) + var/list/mod_names = list() + for(var/k in mods) + var/datum/skill_modifier/M = GLOB.skill_modifiers[k] + mod_names |= M.name + skill_value = M.apply_modifier(skill_value, type, H, MODIFIER_TARGET_VALUE) + .["value_mod"] = skill_value + .["modifiers"] = mod_names //Will be jointext()'d later. // 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. // Aka: So people don't forget to change checks if they change a skill's progression type. @@ -71,10 +96,12 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) competency_thresholds = list(THRESHOLD_COMPETENT = FALSE, THRESHOLD_EXPERT = TRUE, THRESHOLD_MASTER = TRUE) /datum/skill/binary/sanitize_value(new_value) - return new_value? TRUE : FALSE + return new_value >= 1 ? TRUE : FALSE -/datum/skill/binary/standard_render_value(value, level) - return value? "Yes" : "No" +/datum/skill/binary/get_skill_data(datum/skill_holder/H) + . = ..() + .["base_readout"] = .["value_base"] ? "Learned: Yes" : "Learned: No" + .["mod_readout"] = .["value_mod"] ? "Learned: Yes" : "Learned: No" /datum/skill/numerical abstract_type = /datum/skill/numerical @@ -84,14 +111,19 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) var/max_value = 100 /// Min value of this skill var/min_value = 0 - /// Display as a percent in standard_render_value? - var/display_as_percent = FALSE + +/datum/skill/numerical/New() + ..() + skill_gain_quantisation = item_skill_gain_multi = item_skill_gain_multi * (max_value - min_value) * STD_NUM_SKILL_ITEM_GAIN_MULTI /datum/skill/numerical/sanitize_value(new_value) return clamp(new_value, min_value, max_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/numerical/get_skill_data(datum/skill_holder/H) + . = ..() + .["base_readout"] = "Skill Progress: \[[.["value_base"]] / [max_value]\]" + .["mod_readout"] = "Skill Progress: \[[.["value_mod"]] / [max_value]\]" + .["max_value"] = max_value /datum/skill/enum abstract_type = /datum/skill/enum @@ -123,13 +155,7 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) 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) + var/value = round(get_skill_level_value(lvl), 1) if(!associative) levels += value continue @@ -167,8 +193,13 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) 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 +/datum/skill/level/get_skill_data(datum/skill_holder/H) + . = ..() + var/skill_value_base = .["value_base"] + var/skill_value_mod = .["value_mod"] + .["level_based"] = TRUE + + var/level = LAZYACCESS(H.skill_levels, type) || 0 var/current_lvl_xp_sum = 0 if(level) current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level] @@ -176,8 +207,50 @@ GLOBAL_LIST_INIT_TYPED(skill_datums, /datum/skill, init_skill_datums()) 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 + .["lvl_base_num"] = .["lvl_mod_num"] = level + .["lvl_base"] = .["lvl_mod"] = associative ? (!level ? unskilled_tier : levels[level]) : level + .["base_style"] = .["mod_style"] = "font-weight:bold; color:hsl([(level+1)*(350/max_levels+1)], 50%, 50%)" + .["xp_next_lvl_base"] = .["xp_next_lvl_mod"] = "\[[skill_value_base - current_lvl_xp_sum]/[next_lvl_xp]\]" - return "[associative ? current_lvl : "Lvl. [current_lvl]"] ([value - current_lvl_xp_sum]/[next_lvl_xp])[level == max_levels ? " \[MAX!\]" : ""]" + .["max_lvl"] = max_levels + var/max_value = associative ? levels[levels[max_levels]] : levels[max_levels] + .["max_value"] = max_value + + .["base_readout"] = "Overall Skill Progress: \[[skill_value_base]/[max_value]\]" + .["mod_readout"] = "Overall Skill Progress: \[[skill_value_mod]/[max_value]\]" + + var/list/mods = LAZYACCESS(H.skill_level_mods, type) + if(mods) //I'm not proud of doing the same-ish process twice a row but here we go. + var/list/mod_names = .["modifiers"] + if(!mod_names) + .["modifiers"] = mod_names = list() + for(var/k in mods) + var/datum/skill_modifier/M = GLOB.skill_modifiers[k] + mod_names |= M.name + level = M.apply_modifier(level, type, H, MODIFIER_TARGET_LEVEL) + + if(level) + current_lvl_xp_sum = associative ? levels[levels[level]] : levels[level] + else + current_lvl_xp_sum = 0 + next_index = min(max_levels, level+1) + 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 + .["lvl_mod_num"] = level + .["lvl_mod"] = associative ? (!level ? unskilled_tier : levels[level]) : level + .["mod_style"] = "font-weight:bold; color:hsl([(level+1)*(300/(max_levels+1))], 50%, 50%)" + .["xp_next_lvl_mod"] = "\[[skill_value_mod - current_lvl_xp_sum]/[next_lvl_xp]\]" + +/** + * Gets the base value required to reach a level specified by the 'num' arg. + */ +/datum/skill/level/proc/get_skill_level_value(num) + switch(level_up_method) + if(STANDARD_LEVEL_UP) + . = XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, num) + if(DWARFY_LEVEL_UP) + . = DORF_XP_LEVEL(standard_xp_lvl_up, xp_lvl_multiplier, num) /datum/skill/level/job abstract_type = /datum/skill/level/job diff --git a/code/datums/skills/_skill_holder.dm b/code/datums/skills/_skill_holder.dm index 0a5c4f8f58..73748417c3 100644 --- a/code/datums/skills/_skill_holder.dm +++ b/code/datums/skills/_skill_holder.dm @@ -20,6 +20,18 @@ var/list/original_values var/list/original_affinities var/list/original_levels + /// The mind datum this skill is associated with, only used for the check_skills UI + var/datum/mind/owner + /// For UI updates. + var/need_static_data_update = TRUE + /// Whether modifiers and final skill values or only base values are displayed. + var/see_skill_mods = TRUE + /// The current selected skill category. + var/selected_category + +/datum/skill_holder/New(owner) + ..() + src.owner = owner /** * Grabs the value of a skill. @@ -82,6 +94,7 @@ if(!isnull(value)) LAZYINITLIST(skill_holder.skills) S.set_skill_value(skill_holder, value, src, silent) + skill_holder.need_static_data_update = TRUE return TRUE return FALSE @@ -107,11 +120,9 @@ CRASH("You cannot auto increment a non numerical(experience skill!") var/current = get_skill_value(skill, FALSE) var/affinity = get_skill_affinity(skill) - 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 + var/target_value = round(current + (value * affinity), S.skill_gain_quantisation) + if(maximum && target_value >= maximum) //no more experience to gain, early return. + return boost_skill_value_to(skill, target_value, silent, current) /** @@ -183,18 +194,3 @@ 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/mind/proc/skill_html_readout() - var/list/out = list("

Skills


") - out += "" - for(var/path in GLOB.skill_datums) - var/datum/skill/S = GLOB.skill_datums[path] - 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(skill_value, skill_level)]
" - return out.Join("") diff --git a/code/datums/skills/_skill_modifier.dm b/code/datums/skills/_skill_modifier.dm index a28cf3aebd..c38cbf23c6 100644 --- a/code/datums/skills/_skill_modifier.dm +++ b/code/datums/skills/_skill_modifier.dm @@ -7,6 +7,8 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill) * and cause lots of edge cases. These are fairly simple overall... make a subtype though, don't use this one. */ /datum/skill_modifier + /// Name and description of the skill modifier, used in the UI + var/name = "???" /// flags for this skill modifier. var/modifier_flags = NONE /// target skills, can be a specific skill typepath or a list of skill traits. @@ -110,6 +112,7 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill) 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) + skill_holder.need_static_data_update = TRUE if(M.modifier_flags & MODIFIER_SKILL_BODYBOUND) M.RegisterSignal(src, COMSIG_MIND_TRANSFER, /datum/skill_modifier.proc/on_mind_transfer) @@ -141,6 +144,7 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill) 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) + skill_holder.need_static_data_update = TRUE if(!mind_transfer && M.modifier_flags & MODIFIER_SKILL_BODYBOUND) M.UnregisterSignal(src, COMSIG_MIND_TRANSFER) @@ -165,11 +169,7 @@ GLOBAL_LIST_EMPTY(potential_mods_per_skill) 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]) + mod = L.get_skill_level_value(L.competency_thresholds[mod]) else mod = S.competency_thresholds[mod] diff --git a/code/datums/skills/engineering.dm b/code/datums/skills/engineering.dm index db7b33450c..1226664953 100644 --- a/code/datums/skills/engineering.dm +++ b/code/datums/skills/engineering.dm @@ -1,5 +1,6 @@ /datum/skill/level/job/wiring name = "Wiring" - desc = "How proficient and knowledged you are at wiring beyond laying cables on the floor." + desc = "How proficient and knowledged you are at wiring beyond making post-futuristic wire art." name_color = COLOR_PALE_ORANGE skill_traits = list(SKILL_SANITY, SKILL_INTELLIGENCE, SKILL_USE_TOOL, SKILL_TRAINING_TOOL) + ui_category = SKILL_UI_CAT_ENG diff --git a/code/datums/skills/medical.dm b/code/datums/skills/medical.dm index 404c141157..4cf10c4c96 100644 --- a/code/datums/skills/medical.dm +++ b/code/datums/skills/medical.dm @@ -1,5 +1,6 @@ /datum/skill/numerical/surgery name = "Surgery" - desc = "How proficient you are at doing surgery." + desc = "How proficient you are at performing surgical procedures." name_color = COLOR_PALE_BLUE_GRAY competency_multiplier = 1.5 // 60% surgery speed up at max value of 100, considering the base multiplier. + ui_category = SKILL_UI_CAT_MED diff --git a/code/datums/skills/modifiers/job.dm b/code/datums/skills/modifiers/job.dm index 7d79ae89b3..e989ab11e3 100644 --- a/code/datums/skills/modifiers/job.dm +++ b/code/datums/skills/modifiers/job.dm @@ -1,6 +1,7 @@ /// Jobbie skill modifiers. /datum/skill_modifier/job + name = "Job Training" modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_VIRTUE|MODIFIER_SKILL_ORIGIN_DIFF priority = MODIFIER_SKILL_PRIORITY_MAX @@ -23,7 +24,7 @@ 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) +/datum/skill_modifier/job/level/New(id, register = FALSE) if(level_mod) value_mod = GET_STANDARD_LVL(level_mod) ..() diff --git a/code/datums/skills/modifiers/mood.dm b/code/datums/skills/modifiers/mood.dm index 30f24afcc4..a22b75d5b5 100644 --- a/code/datums/skills/modifiers/mood.dm +++ b/code/datums/skills/modifiers/mood.dm @@ -1,8 +1,10 @@ /datum/skill_modifier/bad_mood + name = "Mood (Dejected)" modifier_flags = MODIFIER_SKILL_VALUE|MODIFIER_SKILL_LEVEL|MODIFIER_SKILL_MULT|MODIFIER_SKILL_BODYBOUND target_skills = list(SKILL_SANITY) /datum/skill_modifier/great_mood + name = "Mood (Elated)" 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 index 13ebaf0658..313604f6b2 100644 --- a/code/datums/skills/modifiers/organs.dm +++ b/code/datums/skills/modifiers/organs.dm @@ -1,4 +1,5 @@ /datum/skill_modifier/brain_damage + name = "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 @@ -6,6 +7,7 @@ affinity_mod = 0.85 /datum/skill_modifier/heavy_brain_damage + name = "Brain Damage (Severe)" 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 diff --git a/code/datums/spawners_menu.dm b/code/datums/spawners_menu.dm index 1adcb6fde6..95a7d8e633 100644 --- a/code/datums/spawners_menu.dm +++ b/code/datums/spawners_menu.dm @@ -6,10 +6,13 @@ qdel(src) owner = new_owner -/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/spawners_menu/ui_state(mob/user) + return GLOB.observer_state + +/datum/spawners_menu/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "spawners_menu", "Spawners Menu", 700, 600, master_ui, state) + ui = new(user, src, "SpawnersMenu") ui.open() /datum/spawners_menu/ui_data(mob/user) @@ -42,11 +45,15 @@ if(..()) return - var/spawner_ref = pick(GLOB.mob_spawners[params["name"]]) - var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list - if(!MS) + var/group_name = params["name"] + if(!group_name || !(group_name in GLOB.mob_spawners)) + return + var/list/spawnerlist = GLOB.mob_spawners[group_name] + if(!spawnerlist.len) + return + var/obj/effect/mob_spawn/MS = pick(spawnerlist) + if(!istype(MS) || !(MS in GLOB.poi_list)) return - switch(action) if("jump") if(MS) @@ -55,4 +62,4 @@ if("spawn") if(MS) MS.attack_ghost(owner) - . = TRUE \ No newline at end of file + . = TRUE diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index e080e597a3..179ed765c5 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -441,6 +441,10 @@ owner.adjustBruteLoss(-10, FALSE) owner.adjustFireLoss(-5, FALSE) owner.adjustOxyLoss(-10) + if(!iscarbon(owner)) + return + var/mob/living/carbon/C = owner + QDEL_LIST(C.all_scars) /obj/screen/alert/status_effect/fleshmend name = "Fleshmend" diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 4e023daf33..5c8557429f 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -81,11 +81,11 @@ owner.adjustStaminaLoss(-0.5) //reduce stamina loss by 0.5 per tick, 10 per 2 seconds if(human_owner && human_owner.drunkenness) human_owner.drunkenness *= 0.997 //reduce drunkenness by 0.3% per tick, 6% per 2 seconds - if(prob(20)) - if(carbon_owner) - carbon_owner.handle_dreams() - if(prob(10) && owner.health > owner.crit_threshold) - owner.emote("snore") + if(carbon_owner && !carbon_owner.dreaming && prob(2)) + carbon_owner.dream() + // 2% per second, tick interval is in deciseconds + if(prob((tick_interval+1) * 0.2) && owner.health > owner.crit_threshold) + owner.emote("snore") /datum/status_effect/staggered id = "staggered" @@ -97,6 +97,21 @@ duration = set_duration return ..() +/datum/status_effect/off_balance + id = "offbalance" + alert_type = null + +/datum/status_effect/off_balance/on_creation(mob/living/new_owner, set_duration) + if(isnum(set_duration)) + duration = set_duration + return ..() + +/datum/status_effect/off_balance/on_remove() + var/active_item = owner.get_active_held_item() + if(is_type_in_typecache(active_item, GLOB.shove_disarming_types)) + owner.visible_message("[owner.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE) + return ..() + /obj/screen/alert/status_effect/asleep name = "Asleep" desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are." @@ -147,7 +162,6 @@ id = "tased" alert_type = null var/movespeed_mod = /datum/movespeed_modifier/status_effect/tased - var/nextmove_modifier = 1 var/stamdmg_per_ds = 0 //a 20 duration would do 20 stamdmg, disablers do 24 or something var/last_tick = 0 //fastprocess processing speed is a goddamn sham, don't trust it. @@ -176,13 +190,9 @@ C.adjustStaminaLoss(max(0, stamdmg_per_ds * diff)) //if you really want to try to stamcrit someone with a taser alone, you can, but it'll take time and good timing. last_tick = world.time -/datum/status_effect/electrode/nextmove_modifier() //why is this a proc. its no big deal since this doesnt get called often at all but literally w h y - return nextmove_modifier - /datum/status_effect/electrode/no_combat_mode id = "tased_strong" movespeed_mod = /datum/movespeed_modifier/status_effect/tased/no_combat_mode - nextmove_modifier = 2 blocks_combatmode = TRUE stamdmg_per_ds = 1 @@ -368,9 +378,9 @@ status_type = STATUS_EFFECT_REPLACE alert_type = null var/mutable_appearance/marked_underlay - var/obj/item/twohanded/kinetic_crusher/hammer_synced + var/obj/item/kinetic_crusher/hammer_synced -/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/twohanded/kinetic_crusher/new_hammer_synced) +/datum/status_effect/crusher_mark/on_creation(mob/living/new_owner, obj/item/kinetic_crusher/new_hammer_synced) . = ..() if(.) hammer_synced = new_hammer_synced @@ -396,6 +406,197 @@ owner.underlays -= marked_underlay //if this is being called, we should have an owner at this point. ..() +/datum/status_effect/eldritch + duration = 15 SECONDS + status_type = STATUS_EFFECT_REPLACE + alert_type = null + on_remove_on_mob_delete = TRUE + ///underlay used to indicate that someone is marked + var/mutable_appearance/marked_underlay + ///path for the underlay + var/effect_sprite = "" + +/datum/status_effect/eldritch/on_creation(mob/living/new_owner, ...) + marked_underlay = mutable_appearance('icons/effects/effects.dmi', effect_sprite,BELOW_MOB_LAYER) + return ..() + +/datum/status_effect/eldritch/on_apply() + . = ..() + if(owner.mob_size >= MOB_SIZE_HUMAN) + RegisterSignal(owner,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/update_owner_underlay) + owner.update_icon() + return TRUE + return FALSE + +/datum/status_effect/eldritch/on_remove() + UnregisterSignal(owner,COMSIG_ATOM_UPDATE_OVERLAYS) + owner.update_icon() + return ..() + +/datum/status_effect/eldritch/proc/update_owner_underlay(atom/source, list/overlays) + overlays += marked_underlay + +/datum/status_effect/eldritch/Destroy() + QDEL_NULL(marked_underlay) + return ..() + +/** + * What happens when this mark gets popped + * + * Adds actual functionality to each mark + */ +/datum/status_effect/eldritch/proc/on_effect() + playsound(owner, 'sound/magic/repulse.ogg', 75, TRUE) + qdel(src) //what happens when this is procced. + +//Each mark has diffrent effects when it is destroyed that combine with the mansus grasp effect. +/datum/status_effect/eldritch/flesh + id = "flesh_mark" + effect_sprite = "emark1" + +/datum/status_effect/eldritch/flesh/on_effect() + + if(ishuman(owner)) + var/mob/living/carbon/human/H = owner + var/obj/item/bodypart/bodypart = pick(H.bodyparts) + var/datum/wound/slash/severe/crit_wound = new + crit_wound.apply_wound(bodypart) + return ..() + +/datum/status_effect/eldritch/ash + id = "ash_mark" + effect_sprite = "emark2" + ///Dictates how much damage and stamina loss this mark will cause. + var/repetitions = 1 + +/datum/status_effect/eldritch/ash/on_creation(mob/living/new_owner, _repetition = 5) + . = ..() + repetitions = min(1,_repetition) + +/datum/status_effect/eldritch/ash/on_effect() + if(iscarbon(owner)) + var/mob/living/carbon/carbon_owner = owner + carbon_owner.adjustStaminaLoss(10 * repetitions) + carbon_owner.adjustFireLoss(5 * repetitions) + for(var/mob/living/carbon/victim in range(1,carbon_owner)) + if(IS_HERETIC(victim) || victim == carbon_owner) + continue + victim.apply_status_effect(type,repetitions-1) + break + return ..() + +/datum/status_effect/eldritch/rust + id = "rust_mark" + effect_sprite = "emark3" + +/datum/status_effect/eldritch/rust/on_effect() + if(!iscarbon(owner)) + return + var/mob/living/carbon/carbon_owner = owner + for(var/obj/item/I in carbon_owner.get_all_gear()) //Affects roughly 75% of items + if(!QDELETED(I) && prob(75)) //Just in case + I.take_damage(100) + return ..() + +/datum/status_effect/corrosion_curse + id = "corrosion_curse" + status_type = STATUS_EFFECT_REPLACE + alert_type = null + tick_interval = 1 SECONDS + +/datum/status_effect/corrosion_curse/on_creation(mob/living/new_owner, ...) + . = ..() + to_chat(owner, "Your feel your body starting to break apart...") + +/datum/status_effect/corrosion_curse/tick() + . = ..() + if(!ishuman(owner)) + return + var/mob/living/carbon/human/H = owner + var/chance = rand(0,100) + switch(chance) + if(0 to 19) + H.vomit() + if(20 to 29) + H.Dizzy(10) + if(30 to 39) + H.adjustOrganLoss(ORGAN_SLOT_LIVER,5) + if(40 to 49) + H.adjustOrganLoss(ORGAN_SLOT_HEART,5) + if(50 to 59) + H.adjustOrganLoss(ORGAN_SLOT_STOMACH,5) + if(60 to 69) + H.adjustOrganLoss(ORGAN_SLOT_EYES,10) + if(70 to 79) + H.adjustOrganLoss(ORGAN_SLOT_EARS,10) + if(80 to 89) + H.adjustOrganLoss(ORGAN_SLOT_LUNGS,10) + if(90 to 99) + H.adjustOrganLoss(ORGAN_SLOT_TONGUE,10) + if(100) + H.adjustOrganLoss(ORGAN_SLOT_BRAIN,20) + +/datum/status_effect/amok + id = "amok" + status_type = STATUS_EFFECT_REPLACE + alert_type = null + duration = 10 SECONDS + tick_interval = 1 SECONDS + +/datum/status_effect/amok/on_apply(mob/living/afflicted) + . = ..() + to_chat(owner, "Your feel filled with a rage that is not your own!") + +/datum/status_effect/amok/tick() + . = ..() + var/prev_intent = owner.a_intent + owner.a_intent = INTENT_HARM + + var/list/mob/living/targets = list() + for(var/mob/living/potential_target in oview(owner, 1)) + if(IS_HERETIC(potential_target) || potential_target.mind?.has_antag_datum(/datum/antagonist/heretic_monster)) + continue + targets += potential_target + if(LAZYLEN(targets)) + owner.log_message(" attacked someone due to the amok debuff.", LOG_ATTACK) //the following attack will log itself + owner.ClickOn(pick(targets)) + owner.a_intent = prev_intent + +/datum/status_effect/cloudstruck + id = "cloudstruck" + status_type = STATUS_EFFECT_REPLACE + duration = 3 SECONDS + on_remove_on_mob_delete = TRUE + ///This overlay is applied to the owner for the duration of the effect. + var/mutable_appearance/mob_overlay + +/datum/status_effect/cloudstruck/on_creation(mob/living/new_owner, set_duration) + if(isnum(set_duration)) + duration = set_duration + . = ..() + +/datum/status_effect/cloudstruck/on_apply() + . = ..() + mob_overlay = mutable_appearance('icons/effects/eldritch.dmi', "cloud_swirl", ABOVE_MOB_LAYER) + owner.overlays += mob_overlay + owner.update_icon() + ADD_TRAIT(owner, TRAIT_BLIND, "cloudstruck") + return TRUE + +/datum/status_effect/cloudstruck/on_remove() + . = ..() + if(QDELETED(owner)) + return + REMOVE_TRAIT(owner, TRAIT_BLIND, "cloudstruck") + if(owner) + owner.overlays -= mob_overlay + owner.update_icon() + +/datum/status_effect/cloudstruck/Destroy() + . = ..() + QDEL_NULL(mob_overlay) + + /datum/status_effect/stacking/saw_bleed id = "saw_bleed" tick_interval = 6 @@ -433,10 +634,19 @@ /datum/status_effect/neck_slice/tick() var/mob/living/carbon/human/H = owner - if(H.stat == DEAD || H.bleed_rate <= 8) + var/obj/item/bodypart/throat = H.get_bodypart(BODY_ZONE_HEAD) + if(H.stat == DEAD || !throat) H.remove_status_effect(/datum/status_effect/neck_slice) if(prob(10)) H.emote(pick("gasp", "gag", "choke")) + var/still_bleeding = FALSE + for(var/thing in throat.wounds) + var/datum/wound/W = thing + if(W.wound_type == WOUND_SLASH && W.severity > WOUND_SEVERITY_MODERATE) + still_bleeding = TRUE + break + if(!still_bleeding) + H.remove_status_effect(/datum/status_effect/neck_slice) /mob/living/proc/apply_necropolis_curse(set_curse, duration = 10 MINUTES) var/datum/status_effect/necropolis_curse/C = has_status_effect(STATUS_EFFECT_NECROPOLIS_CURSE) @@ -546,8 +756,8 @@ owner.DefaultCombatKnockdown(15, TRUE, FALSE, 15) if(iscarbon(owner)) var/mob/living/carbon/C = owner - C.silent = max(2, C.silent) - C.stuttering = max(5, C.stuttering) + C.silent = max(5, C.silent) //Increased, now lasts until five seconds after it ends, instead of 2 + C.stuttering = max(10, C.stuttering) //Increased, now lasts for five seconds after the mute ends, instead of 3 if(!old_health) old_health = owner.health if(!old_oxyloss) @@ -714,8 +924,9 @@ datum/status_effect/pacify if(hearing_args[HEARING_SPEAKER] == owner) return var/mob/living/carbon/C = owner + var/hypnomsg = uncostumize_say(hearing_args[HEARING_RAW_MESSAGE], hearing_args[HEARING_MESSAGE_MODE]) C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis - addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hearing_args[HEARING_RAW_MESSAGE]), 10) + addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hypnomsg), 10) addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it qdel(src) diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm index 33c8384d72..461ae9c65d 100644 --- a/code/datums/status_effects/status_effect.dm +++ b/code/datums/status_effects/status_effect.dm @@ -6,6 +6,7 @@ var/id = "effect" //Used for screen alerts. var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means. var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second. + var/next_tick //The scheduled time for the next tick. var/mob/living/owner //The mob affected by the status effect. var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves @@ -31,7 +32,7 @@ return if(duration != -1) duration = world.time + duration - tick_interval = world.time + tick_interval + next_tick = world.time + tick_interval if(alert_type) var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type) A.attached_effect = src //so the alert can reference us, if it needs to @@ -52,9 +53,9 @@ if(!owner) qdel(src) return - if(tick_interval < world.time) + if(next_tick < world.time) tick() - tick_interval = world.time + initial(tick_interval) + next_tick = world.time + tick_interval if(duration != -1 && duration < world.time) qdel(src) @@ -89,13 +90,12 @@ return duration = world.time + original_duration -//clickdelay/nextmove modifiers! -/datum/status_effect/proc/nextmove_modifier() +/** + * Multiplied to clickdelays + */ +/datum/status_effect/proc/action_cooldown_mod() return 1 -/datum/status_effect/proc/nextmove_adjust() - return 0 - //////////////// // ALERT HOOK // //////////////// @@ -221,7 +221,7 @@ threshold_crossed = FALSE //resets threshold effect if we fall below threshold so threshold effect can trigger again on_threshold_drop() if(stacks_added > 0) - tick_interval += delay_before_decay //refreshes time until decay + next_tick += delay_before_decay //refreshes time until decay stacks = min(stacks, max_stacks) status_overlay.icon_state = "[overlay_state][stacks]" status_underlay.icon_state = "[underlay_state][stacks]" @@ -278,3 +278,7 @@ /datum/status_effect/grouped/before_remove(source) sources -= source return !length(sources) + +//do_after modifier! +/datum/status_effect/proc/interact_speed_modifier() + return 1 diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm new file mode 100644 index 0000000000..045b1b257d --- /dev/null +++ b/code/datums/status_effects/wound_effects.dm @@ -0,0 +1,197 @@ + +// The shattered remnants of your broken limbs fill you with determination! +/obj/screen/alert/status_effect/determined + name = "Determined" + desc = "The serious wounds you've sustained have put your body into fight-or-flight mode! Now's the time to look for an exit!" + icon_state = "regenerative_core" + +/datum/status_effect/determined + id = "determined" + alert_type = /obj/screen/alert/status_effect/determined + +/datum/status_effect/determined/on_apply() + . = ..() + owner.visible_message("[owner] grits [owner.p_their()] teeth in pain!", "Your senses sharpen as your body tenses up from the wounds you've sustained!", vision_distance=COMBAT_MESSAGE_RANGE) + +/datum/status_effect/determined/on_remove() + owner.visible_message("[owner]'s body slackens noticeably!", "Your adrenaline rush dies off, and the pain from your wounds come aching back in...", vision_distance=COMBAT_MESSAGE_RANGE) + return ..() + +/datum/status_effect/limp + id = "limp" + status_type = STATUS_EFFECT_REPLACE + tick_interval = 10 + alert_type = /obj/screen/alert/status_effect/limp + var/msg_stage = 0//so you dont get the most intense messages immediately + /// The left leg of the limping person + var/obj/item/bodypart/l_leg/left + /// The right leg of the limping person + var/obj/item/bodypart/r_leg/right + /// Which leg we're limping with next + var/obj/item/bodypart/next_leg + /// How many deciseconds we limp for on the left leg + var/slowdown_left = 0 + /// How many deciseconds we limp for on the right leg + var/slowdown_right = 0 + +/datum/status_effect/limp/on_apply() + if(!iscarbon(owner)) + return FALSE + var/mob/living/carbon/C = owner + left = C.get_bodypart(BODY_ZONE_L_LEG) + right = C.get_bodypart(BODY_ZONE_R_LEG) + update_limp() + RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/check_step) + RegisterSignal(C, list(COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), .proc/update_limp) + return ..() + +/datum/status_effect/limp/on_remove() + UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB)) + return ..() + +/obj/screen/alert/status_effect/limp + name = "Limping" + desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least splinted!" + +/datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced) + if(!owner.client || !(owner.mobility_flags & MOBILITY_STAND) || !owner.has_gravity() || (owner.movement_type & FLYING) || forced) + return + var/determined_mod = 1 + if(owner.has_status_effect(STATUS_EFFECT_DETERMINED)) + determined_mod = 0.25 + if(next_leg == left) + owner.client.move_delay += slowdown_left * determined_mod + next_leg = right + else + owner.client.move_delay += slowdown_right * determined_mod + next_leg = left + +/datum/status_effect/limp/proc/update_limp() + var/mob/living/carbon/C = owner + left = C.get_bodypart(BODY_ZONE_L_LEG) + right = C.get_bodypart(BODY_ZONE_R_LEG) + + if(!left && !right) + C.remove_status_effect(src) + return + + slowdown_left = 0 + slowdown_right = 0 + + if(left) + for(var/thing in left.wounds) + var/datum/wound/W = thing + slowdown_left += W.limp_slowdown + + if(right) + for(var/thing in right.wounds) + var/datum/wound/W = thing + slowdown_right += W.limp_slowdown + + // this handles losing your leg with the limp and the other one being in good shape as well + if(!slowdown_left && !slowdown_right) + C.remove_status_effect(src) + return + + +///////////////////////// +//////// WOUNDS ///////// +///////////////////////// + +// wound alert +/obj/screen/alert/status_effect/wound + name = "Wounded" + desc = "Your body has sustained serious damage, click here to inspect yourself." + +/obj/screen/alert/status_effect/wound/Click() + var/mob/living/carbon/C = usr + C.check_self_for_injuries() + +// wound status effect base +/datum/status_effect/wound + id = "wound" + status_type = STATUS_EFFECT_MULTIPLE + var/obj/item/bodypart/linked_limb + var/datum/wound/linked_wound + alert_type = NONE + +/datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound) + . = ..() + linked_wound = incoming_wound + linked_limb = linked_wound.limb + +/datum/status_effect/wound/on_remove() + linked_wound = null + linked_limb = null + UnregisterSignal(owner, COMSIG_CARBON_LOSE_WOUND) + return ..() + +/datum/status_effect/wound/on_apply() + if(!iscarbon(owner)) + return FALSE + RegisterSignal(owner, COMSIG_CARBON_LOSE_WOUND, .proc/check_remove) + return ..() + +/// check if the wound getting removed is the wound we're tied to +/datum/status_effect/wound/proc/check_remove(mob/living/L, datum/wound/W) + if(W == linked_wound) + qdel(src) + + +// bones +/datum/status_effect/wound/blunt + +/datum/status_effect/wound/blunt/interact_speed_modifier() + var/mob/living/carbon/C = owner + + if(C.get_active_hand() == linked_limb) + to_chat(C, "The [lowertext(linked_wound)] in your [linked_limb.name] slows your progress!") + return linked_wound.interaction_efficiency_penalty + + return 1 + +/datum/status_effect/wound/blunt/action_cooldown_mod() + var/mob/living/carbon/C = owner + + if(C.get_active_hand() == linked_limb) + return linked_wound.interaction_efficiency_penalty + + return 1 + +/datum/status_effect/wound/blunt/moderate + id = "disjoint" +/datum/status_effect/wound/blunt/severe + id = "hairline" + +/datum/status_effect/wound/blunt/critical + id = "compound" + +// cuts +/datum/status_effect/wound/slash/moderate + id = "abrasion" + +/datum/status_effect/wound/slash/severe + id = "laceration" + +/datum/status_effect/wound/slash/critical + id = "avulsion" + +// pierce +/datum/status_effect/wound/pierce/moderate + id = "breakage" + +/datum/status_effect/wound/pierce/severe + id = "puncture" + +/datum/status_effect/wound/pierce/critical + id = "rupture" + +// burns +/datum/status_effect/wound/burn/moderate + id = "seconddeg" + +/datum/status_effect/wound/burn/severe + id = "thirddeg" + +/datum/status_effect/wound/burn/critical + id = "fourthdeg" diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 9c2128163f..68b5d6f987 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -14,7 +14,7 @@ if(NOBLOOD in H.dna.species.species_traits) //can't lose blood if your species doesn't have any return else - quirk_holder.blood_volume -= 0.275 + quirk_holder.blood_volume -= 0.2 /datum/quirk/depression name = "Depression" @@ -54,9 +54,9 @@ GLOBAL_LIST_EMPTY(family_heirlooms) if("Botanist") heirloom_type = pick(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/storage/bag/plants, /obj/item/toy/plush/beeplushie) if("Medical Doctor") - heirloom_type = /obj/item/healthanalyzer/advanced + heirloom_type = /obj/item/healthanalyzer if("Paramedic") - heirloom_type = pick(/obj/item/clothing/neck/stethoscope, /obj/item/bodybag) + heirloom_type = /obj/item/lighter if("Station Engineer") heirloom_type = /obj/item/wirecutters/brass if("Atmospheric Technician") @@ -314,6 +314,13 @@ GLOBAL_LIST_EMPTY(family_heirlooms) medical_record_text = "Patient is usually anxious in social encounters and prefers to avoid them." var/dumb_thing = TRUE +/datum/quirk/social_anxiety/add() + RegisterSignal(quirk_holder, COMSIG_MOB_EYECONTACT, .proc/eye_contact) + RegisterSignal(quirk_holder, COMSIG_MOB_EXAMINATE, .proc/looks_at_floor) + +/datum/quirk/social_anxiety/remove() + UnregisterSignal(quirk_holder, list(COMSIG_MOB_EYECONTACT, COMSIG_MOB_EXAMINATE)) + /datum/quirk/social_anxiety/on_process() var/nearby_people = 0 for(var/mob/living/carbon/human/H in oview(3, quirk_holder)) @@ -331,6 +338,43 @@ GLOBAL_LIST_EMPTY(family_heirlooms) if(prob(1)) new/obj/item/reagent_containers/food/snacks/pastatomato(get_turf(H)) //now that's what I call spaghetti code +// small chance to make eye contact with inanimate objects/mindless mobs because of nerves +/datum/quirk/social_anxiety/proc/looks_at_floor(datum/source, atom/A) + var/mob/living/mind_check = A + if(prob(85) || (istype(mind_check) && mind_check.mind)) + return + + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, quirk_holder, "You make eye contact with [A]."), 3) + +/datum/quirk/social_anxiety/proc/eye_contact(datum/source, mob/living/other_mob, triggering_examiner) + if(prob(75)) + return + var/msg + if(triggering_examiner) + msg = "You make eye contact with [other_mob], " + else + msg = "[other_mob] makes eye contact with you, " + + switch(rand(1,3)) + if(1) + quirk_holder.Jitter(10) + msg += "causing you to start fidgeting!" + if(2) + quirk_holder.stuttering = max(3, quirk_holder.stuttering) + msg += "causing you to start stuttering!" + if(3) + quirk_holder.Stun(2 SECONDS) + msg += "causing you to freeze up!" + + SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "anxiety_eyecontact", /datum/mood_event/anxiety_eyecontact) + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, quirk_holder, "[msg]"), 3) // so the examine signal has time to fire and this will print after + return COMSIG_BLOCK_EYECONTACT + +/datum/mood_event/anxiety_eyecontact + description = "Sometimes eye contact makes me so nervous...\n" + mood_change = -5 + timeout = 3 MINUTES + /datum/quirk/phobia name = "Phobia" desc = "You've had a traumatic past, one that has scarred you for life, and cripples you when dealing with your greatest fears." @@ -406,3 +450,21 @@ GLOBAL_LIST_EMPTY(family_heirlooms) mob_trait = TRAIT_COLDBLOODED gain_text = "You feel cold-blooded." lose_text = "You feel more warm-blooded." + +/datum/quirk/monophobia + name = "Monophobia" + desc = "You will become increasingly stressed when not in company of others, triggering panic reactions ranging from sickness to heart attacks." + value = -3 // Might change it to 4. + gain_text = "You feel really lonely..." + lose_text = "You feel like you could be safe on your own." + medical_record_text = "Patient feels sick and distressed when not around other people, leading to potentially lethal levels of stress." + +/datum/quirk/monophobia/post_add() + . = ..() + var/mob/living/carbon/human/H = quirk_holder + H.gain_trauma(/datum/brain_trauma/severe/monophobia, TRAUMA_RESILIENCE_ABSOLUTE) + +/datum/quirk/monophobia/remove() + . = ..() + var/mob/living/carbon/human/H = quirk_holder + H?.cure_trauma_type(/datum/brain_trauma/severe/monophobia, TRAUMA_RESILIENCE_ABSOLUTE) diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index 4b039aa1b5..e92564a3b4 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -122,3 +122,19 @@ if(H) var/datum/species/species = H.dna.species species.disliked_food &= ~ALCOHOL + +/datum/quirk/longtimer + name = "Longtimer" + desc = "You've been around for a long time and seen more than your fair share of action, suffering some pretty nasty scars along the way. For whatever reason, you've declined to get them removed or augmented." + value = 0 + gain_text = "Your body has seen better days." + lose_text = "Your sins may wash away, but those scars are here to stay..." + medical_record_text = "Patient has withstood significant physical trauma and declined plastic surgery procedures to heal scarring." + /// the minimum amount of scars we can generate + var/min_scars = 3 + /// the maximum amount of scars we can generate + var/max_scars = 7 + +/datum/quirk/longtimer/on_spawn() + var/mob/living/carbon/C = quirk_holder + C.generate_fake_scars(rand(min_scars, max_scars)) diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index 11e7e12bd8..04fbc4a590 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -97,6 +97,12 @@ /datum/wires/proc/get_wire(color) return colors[color] +/datum/wires/proc/get_color_of_wire(wire_type) + for(var/color in colors) + var/other_type = colors[color] + if(wire_type == other_type) + return color + /datum/wires/proc/get_attached(color) if(assemblies[color]) return assemblies[color] @@ -117,7 +123,7 @@ return TRUE /datum/wires/proc/is_dud(wire) - return findtext(wire, WIRE_DUD_PREFIX) + return findtext(wire, WIRE_DUD_PREFIX, 1, length(WIRE_DUD_PREFIX) + 1) /datum/wires/proc/is_dud_color(color) return is_dud(get_wire(color)) @@ -197,6 +203,7 @@ S.forceMove(holder.drop_location()) return S +/// Called from [/atom/proc/emp_act] /datum/wires/proc/emp_pulse() var/list/possible_wires = shuffle(wires) var/remaining_pulses = MAXIMUM_EMP_WIRES @@ -239,11 +246,13 @@ return ..() return UI_CLOSE -/datum/wires/ui_interact(mob/user, ui_key = "wires", 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) - if(!ui) - ui = new(user, src, ui_key, "wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state) +/datum/wires/ui_state(mob/user) + return GLOB.physical_state + +/datum/wires/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if (!ui) + ui = new(user, src, "Wires", "[holder.name] Wires") ui.open() /datum/wires/ui_data(mob/user) diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index 2b13344cc6..179adf46bd 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -53,11 +53,8 @@ /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 - return TRUE + if(A.panel_open) + return TRUE /datum/wires/airlock/get_status() var/obj/machinery/door/airlock/A = holder @@ -74,6 +71,8 @@ /datum/wires/airlock/on_pulse(wire) set waitfor = FALSE var/obj/machinery/door/airlock/A = holder + if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100)) + return FALSE switch(wire) if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power. A.loseMainPower() @@ -115,10 +114,7 @@ A.aiControlDisabled = -1 if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. if(!A.secondsElectrified) - A.set_electrified(30) - if(usr) - LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")) - log_combat(usr, A, "electrified") + A.set_electrified(30, usr) if(WIRE_SAFETY) A.safe = !A.safe if(!A.density) @@ -131,25 +127,23 @@ /datum/wires/airlock/on_cut(wire, mend) var/obj/machinery/door/airlock/A = holder + if(!A.hasSiliconAccessInArea(usr) && A.isElectrified() && A.shock(usr, 100)) + return FALSE switch(wire) if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power. if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2)) A.regainMainPower() - if(usr) - A.shock(usr, 50) else A.loseMainPower() - if(usr) - A.shock(usr, 50) + if(isliving(usr)) + A.shock(usr, 50) if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power. if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) A.regainBackupPower() - if(usr) - A.shock(usr, 50) else A.loseBackupPower() - if(usr) - A.shock(usr, 50) + if(isliving(usr)) + A.shock(usr, 50) if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing. if(!mend) A.bolt() @@ -170,10 +164,7 @@ A.set_electrified(0) else if(A.secondsElectrified != -1) - A.set_electrified(-1) - if(usr) - LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]")) - log_combat(usr, A, "electrified") + A.set_electrified(-1, usr) if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. A.safe = mend if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable. @@ -184,5 +175,5 @@ A.lights = mend A.update_icon() if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. - if(usr) + if(isliving(usr)) A.shock(usr, 50) diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm index dc4db9e85d..25493f2e30 100644 --- a/code/datums/wires/explosive.dm +++ b/code/datums/wires/explosive.dm @@ -75,8 +75,8 @@ /datum/wires/explosive/gibtonite - holder_type = /obj/item/twohanded/required/gibtonite + holder_type = /obj/item/gibtonite /datum/wires/explosive/gibtonite/explode() - var/obj/item/twohanded/required/gibtonite/P = holder + var/obj/item/gibtonite/P = holder P.GibtoniteReaction(null, 2) \ No newline at end of file diff --git a/code/datums/world_topic.dm b/code/datums/world_topic.dm index 30699d36f4..261e423640 100644 --- a/code/datums/world_topic.dm +++ b/code/datums/world_topic.dm @@ -74,6 +74,25 @@ for(var/client/C in GLOB.clients) C.AnnouncePR(final_composed) +/datum/world_topic/auto_bunker_passthrough + keyword = "auto_bunker_override" + require_comms_key = TRUE + +/datum/world_topic/auto_bunker_passthrough/Run(list/input) + if(!CONFIG_GET(flag/allow_cross_server_bunker_override)) + return "Function Disabled" + var/ckeytobypass = input["ckey"] + var/is_new_ckey = !(ckey(ckeytobypass) in GLOB.bunker_passthrough) + var/sender = input["source"] || "UNKNOWN" + GLOB.bunker_passthrough |= ckey(ckeytobypass) + GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime + SSpersistence.SavePanicBunker() //we can do this every time, it's okay + if(!is_new_ckey) + log_admin("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).") + message_admins("AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).") + send2irc("Panic Bunker", "AUTO BUNKER: [ckeytobypass] given access (incoming comms from [sender]).") + return "Success" + /datum/world_topic/ahelp_relay keyword = "Ahelp" require_comms_key = TRUE diff --git a/code/datums/wounds/_scars.dm b/code/datums/wounds/_scars.dm new file mode 100644 index 0000000000..8cd0d8a047 --- /dev/null +++ b/code/datums/wounds/_scars.dm @@ -0,0 +1,152 @@ +/** + * scars are cosmetic datums that are assigned to bodyparts once they recover from wounds. Each wound type and severity have their own descriptions for what the scars + * look like, and then each body part has a list of "specific locations" like your elbow or wrist or wherever the scar can appear, to make it more interesting than "right arm" + * + * + * Arguments: + * * + */ +/datum/scar + var/obj/item/bodypart/limb + var/mob/living/carbon/victim + var/severity + var/description + var/precise_location + + /// Scars from the longtimer quirk are "fake" and won't be saved with persistent scarring, since it makes you spawn with a lot by default + var/fake=FALSE + + /// How many tiles away someone can see this scar, goes up with severity. Clothes covering this limb will decrease visibility by 1 each, except for the head/face which is a binary "is mask obscuring face" check + var/visibility = 2 + /// Whether this scar can actually be covered up by clothing + var/coverable = TRUE + /// What zones this scar can be applied to + var/list/applicable_zones = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG) + +/datum/scar/Destroy(force, ...) + if(limb) + LAZYREMOVE(limb.scars, src) + if(victim) + LAZYREMOVE(victim.all_scars, src) + . = ..() + +/** + * generate() is used to actually fill out the info for a scar, according to the limb and wound it is provided. + * + * After creating a scar, call this on it while targeting the scarred bodypart with a given wound to apply the scar. + * + * Arguments: + * * BP- The bodypart being targeted + * * W- The wound being used to generate the severity and description info + * * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate) + */ +/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE) + if(!(BP.body_zone in applicable_zones)) + qdel(src) + return + limb = BP + severity = W.severity + if(limb.owner) + victim = limb.owner + if(add_to_scars) + LAZYADD(limb.scars, src) + if(victim) + LAZYADD(victim.all_scars, src) + + if(victim && victim.get_biological_state() == BIO_JUST_BONE) + description = pick(strings(BONE_SCAR_FILE, W.scar_keyword)) || "general disfigurement" + else + description = pick(strings(FLESH_SCAR_FILE, W.scar_keyword)) || "general disfigurement" + + precise_location = pick(strings(SCAR_LOC_FILE, limb.body_zone)) + switch(W.severity) + if(WOUND_SEVERITY_MODERATE) + visibility = 2 + if(WOUND_SEVERITY_SEVERE) + visibility = 3 + if(WOUND_SEVERITY_CRITICAL) + visibility = 5 + if(WOUND_SEVERITY_LOSS) + visibility = 7 + precise_location = "amputation" + +/// Used when we finalize a scar from a healing cut +/datum/scar/proc/lazy_attach(obj/item/bodypart/BP, datum/wound/W) + LAZYADD(BP.scars, src) + if(BP.owner) + victim = BP.owner + LAZYADD(victim.all_scars, src) + +/// Used to "load" a persistent scar +/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE) + if(!(BP.body_zone in applicable_zones) || !BP.is_organic_limb()) + qdel(src) + return + + limb = BP + src.severity = severity + LAZYADD(limb.scars, src) + if(BP.owner) + victim = BP.owner + LAZYADD(victim.all_scars, src) + src.description = description + precise_location = specific_location + switch(severity) + if(WOUND_SEVERITY_MODERATE) + visibility = 2 + if(WOUND_SEVERITY_SEVERE) + visibility = 3 + if(WOUND_SEVERITY_CRITICAL) + visibility = 5 + if(WOUND_SEVERITY_LOSS) + visibility = 7 + return TRUE + +/// What will show up in examine_more() if this scar is visible +/datum/scar/proc/get_examine_description(mob/viewer) + if(!victim || !is_visible(viewer)) + return + + var/msg = "[victim.p_they(TRUE)] [victim.p_have()] [description] on [victim.p_their()] [precise_location]." + switch(severity) + if(WOUND_SEVERITY_MODERATE) + msg = "[msg]" + if(WOUND_SEVERITY_SEVERE) + msg = "[msg]" + if(WOUND_SEVERITY_CRITICAL) + msg = "[msg]" + if(WOUND_SEVERITY_LOSS) + msg = "[victim.p_their(TRUE)] [limb.name] [description]." // different format + msg = "[msg]" + return "\t[msg]" + +/// Whether a scar can currently be seen by the viewer +/datum/scar/proc/is_visible(mob/viewer) + if(!victim || !viewer) + return + if(get_dist(viewer, victim) > visibility) + return + + if(!ishuman(victim) || isobserver(viewer) || victim == viewer) + return TRUE + + var/mob/living/carbon/human/human_victim = victim + if(istype(limb, /obj/item/bodypart/head)) + if((human_victim.wear_mask && (human_victim.wear_mask.flags_inv & HIDEFACE)) || (human_victim.head && (human_victim.head.flags_inv & HIDEFACE))) + return FALSE + else if(limb.scars_covered_by_clothes) + var/num_covers = LAZYLEN(human_victim.clothingonpart(limb)) + if(num_covers + get_dist(viewer, victim) >= visibility) + return FALSE + + return TRUE + +/// Used to format a scar to safe in preferences for persistent scars +/datum/scar/proc/format() + if(!fake) + return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]" + +/// Used to format a scar to safe in preferences for persistent scars +/datum/scar/proc/format_amputated(body_zone) + description = pick(list("is several skintone shades paler than the rest of the body", "is a gruesome patchwork of artificial flesh", "has a large series of attachment scars at the articulation points")) + return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]" \ No newline at end of file diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm new file mode 100644 index 0000000000..29c87b32d4 --- /dev/null +++ b/code/datums/wounds/_wounds.dm @@ -0,0 +1,327 @@ +/* + Wounds are specific medical complications that can arise and be applied to (currently) carbons, with a focus on humans. All of the code for and related to this is heavily WIP, + and the documentation will be slanted towards explaining what each part/piece is leading up to, until such a time as I finish the core implementations. The original design doc + can be found at https://hackmd.io/@Ryll/r1lb4SOwU + + Wounds are datums that operate like a mix of diseases, brain traumas, and components, and are applied to a /obj/item/bodypart (preferably attached to a carbon) when they take large spikes of damage + or under other certain conditions (thrown hard against a wall, sustained exposure to plasma fire, etc). Wounds are categorized by the three following criteria: + 1. Severity: Either MODERATE, SEVERE, or CRITICAL. See the hackmd for more details + 2. Viable zones: What body parts the wound is applicable to. Generic wounds like broken bones and severe burns can apply to every zone, but you may want to add special wounds for certain limbs + like a twisted ankle for legs only, or open air exposure of the organs for particularly gruesome chest wounds. Wounds should be able to function for every zone they are marked viable for. + 3. Damage type: Currently either BRUTE or BURN. Again, see the hackmd for a breakdown of my plans for each type. + + When a body part suffers enough damage to get a wound, the severity (determined by a roll or something, worse damage leading to worse wounds), affected limb, and damage type sustained are factored into + deciding what specific wound will be applied. I'd like to have a few different types of wounds for at least some of the choices, but I'm just doing rough generals for now. Expect polishing +*/ + +/datum/wound + /// What it's named + var/name = "ouchie" + /// The description shown on the scanners + var/desc = "" + /// The basic treatment suggested by health analyzers + var/treat_text = "" + /// What the limb looks like on a cursory examine + var/examine_desc = "is badly hurt" + + /// needed for "your arm has a compound fracture" vs "your arm has some third degree burns" + var/a_or_from = "a" + /// The visible message when this happens + var/occur_text = "" + /// This sound will be played upon the wound being applied + var/sound_effect + + /// Either WOUND_SEVERITY_TRIVIAL (meme wounds like stubbed toe), WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, or WOUND_SEVERITY_CRITICAL (or maybe WOUND_SEVERITY_LOSS) + var/severity = WOUND_SEVERITY_MODERATE + /// The list of wounds it belongs in, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN + var/wound_type + + /// What body zones can we affect + var/list/viable_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + /// Who owns the body part that we're wounding + var/mob/living/carbon/victim = null + /// The bodypart we're parented to + var/obj/item/bodypart/limb = null + + /// Specific items such as bandages or sutures that can try directly treating this wound + var/list/treatable_by + /// Specific items such as bandages or sutures that can try directly treating this wound only if the user has the victim in an aggressive grab or higher + var/list/treatable_by_grabbed + /// Tools with the specified tool flag will also be able to try directly treating this wound + var/treatable_tool + /// How long it will take to treat this wound with a standard effective tool, assuming it doesn't need surgery + var/base_treat_time = 5 SECONDS + + /// Using this limb in a do_after interaction will multiply the length by this duration (arms) + var/interaction_efficiency_penalty = 1 + /// Incoming damage on this limb will be multiplied by this, to simulate tenderness and vulnerability (mostly burns). + var/damage_mulitplier_penalty = 1 + /// If set and this wound is applied to a leg, we take this many deciseconds extra per step on this leg + var/limp_slowdown + /// How much we're contributing to this limb's bleed_rate + var/blood_flow + + /// The minimum we need to roll on [/obj/item/bodypart/proc/check_wounding] to begin suffering this wound, see check_wounding_mods() for more + var/threshold_minimum + /// How much having this wound will add to all future check_wounding() rolls on this limb, to allow progression to worse injuries with repeated damage + var/threshold_penalty + /// If we need to process each life tick + var/processes = FALSE + + /// If having this wound makes currently makes the parent bodypart unusable + var/disabling + + /// What status effect we assign on application + var/status_effect_type + /// The status effect we're linked to + var/datum/status_effect/linked_status_effect + /// If we're operating on this wound and it gets healed, we'll nix the surgery too + var/datum/surgery/attached_surgery + /// if you're a lazy git and just throw them in cryo, the wound will go away after accumulating severity * 25 power + var/cryo_progress + + /// What kind of scars this wound will create description wise once healed + var/scar_keyword = "generic" + /// If we've already tried scarring while removing (since remove_wound calls qdel, and qdel calls remove wound, .....) TODO: make this cleaner + var/already_scarred = FALSE + /// If we forced this wound through badmin smite, we won't count it towards the round totals + var/from_smite + + /// What flags apply to this wound + var/wound_flags = (FLESH_WOUND | BONE_WOUND | ACCEPTS_GAUZE) + +/datum/wound/Destroy() + if(attached_surgery) + QDEL_NULL(attached_surgery) + if(limb?.wounds && (src in limb.wounds)) // destroy can call remove_wound() and remove_wound() calls qdel, so we check to make sure there's anything to remove first + remove_wound() + limb = null + victim = null + return ..() + +/** + * apply_wound() is used once a wound type is instantiated to assign it to a bodypart, and actually come into play. + * + * + * Arguments: + * * L: The bodypart we're wounding, we don't care about the person, we can get them through the limb + * * silent: Not actually necessary I don't think, was originally used for demoting wounds so they wouldn't make new messages, but I believe old_wound took over that, I may remove this shortly + * * old_wound: If our new wound is a replacement for one of the same time (promotion or demotion), we can reference the old one just before it's removed to copy over necessary vars + * * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented) + */ +/datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE) + if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || isalien(L.owner) || !L.is_organic_limb()) + qdel(src) + return + + if(ishuman(L.owner)) + var/mob/living/carbon/human/H = L.owner + if(((wound_flags & BONE_WOUND) && !(HAS_BONE in H.dna.species.species_traits)) || ((wound_flags & FLESH_WOUND) && !(HAS_FLESH in H.dna.species.species_traits))) + qdel(src) + return + + // we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check + // in case we ever directly add wounds + for(var/i in L.wounds) + var/datum/wound/preexisting_wound = i + if((preexisting_wound.type == type) && (preexisting_wound != old_wound)) + qdel(src) + return + + victim = L.owner + limb = L + LAZYADD(victim.all_wounds, src) + LAZYADD(limb.wounds, src) + limb.update_wounds() + if(status_effect_type) + linked_status_effect = victim.apply_status_effect(status_effect_type, src) + SEND_SIGNAL(victim, COMSIG_CARBON_GAIN_WOUND, src, limb) + if(!victim.alerts["wound"]) // only one alert is shared between all of the wounds + victim.throw_alert("wound", /obj/screen/alert/status_effect/wound) + + var/demoted + if(old_wound) + demoted = (severity <= old_wound.severity) + + if(severity == WOUND_SEVERITY_TRIVIAL) + return + + if(!(silent || demoted)) + var/msg = "[victim]'s [limb.name] [occur_text]!" + var/vis_dist = COMBAT_MESSAGE_RANGE + + if(severity != WOUND_SEVERITY_MODERATE) + msg = "[msg]" + vis_dist = DEFAULT_MESSAGE_RANGE + + victim.visible_message(msg, "Your [limb.name] [occur_text]!", vision_distance = vis_dist) + if(sound_effect) + playsound(L.owner, sound_effect, 70 + 20 * severity, TRUE) + + if(!demoted) + wound_injury(old_wound) + second_wind() + +/// Remove the wound from whatever it's afflicting, and cleans up whateverstatus effects it had or modifiers it had on interaction times. ignore_limb is used for detachments where we only want to forget the victim +/datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE) + //TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff + if(limb && !already_scarred && !replaced) + already_scarred = TRUE + var/datum/scar/new_scar = new + new_scar.generate(limb, src) + if(victim) + LAZYREMOVE(victim.all_wounds, src) + if(!victim.all_wounds) + victim.clear_alert("wound") + SEND_SIGNAL(victim, COMSIG_CARBON_LOSE_WOUND, src, limb) + if(limb && !ignore_limb) + LAZYREMOVE(limb.wounds, src) + limb.update_wounds(replaced) + +/** + * replace_wound() is used when you want to replace the current wound with a new wound, presumably of the same category, just of a different severity (either up or down counts) + * + * This proc actually instantiates the new wound based off the specific type path passed, then returns the new instantiated wound datum. + * + * Arguments: + * * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/slash/severe + * * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented) + */ +/datum/wound/proc/replace_wound(new_type, smited = FALSE) + var/datum/wound/new_wound = new new_type + already_scarred = TRUE + remove_wound(replaced=TRUE) + new_wound.apply_wound(limb, old_wound = src, smited = smited) + qdel(src) + return new_wound + +/// The immediate negative effects faced as a result of the wound +/datum/wound/proc/wound_injury(datum/wound/old_wound = null) + return + +/// Additional beneficial effects when the wound is gained, in case you want to give a temporary boost to allow the victim to try an escape or last stand +/datum/wound/proc/second_wind() + switch(severity) + if(WOUND_SEVERITY_MODERATE) + victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_MODERATE) + if(WOUND_SEVERITY_SEVERE) + victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_SEVERE) + if(WOUND_SEVERITY_CRITICAL) + victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_CRITICAL) + if(WOUND_SEVERITY_LOSS) + victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_LOSS) + +/** + * try_treating() is an intercept run from [/mob/living/carbon/proc/attackby] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction. + * + * This proc leads into [/datum/wound/proc/treat] and probably shouldn't be added onto in children types. You can specify what items or tools you want to be intercepted + * with var/list/treatable_by and var/treatable_tool, then if an item fulfills one of those requirements and our wound claims it first, it goes over to treat() and treat_self(). + * + * Arguments: + * * I: The item we're trying to use + * * user: The mob trying to use it on us + */ +/datum/wound/proc/try_treating(obj/item/I, mob/user) + // first we weed out if we're not dealing with our wound's bodypart, or if it might be an attack + if(!I || limb.body_zone != user.zone_selected || (I.force && user.a_intent != INTENT_HELP)) + return FALSE + + var/allowed = FALSE + + // check if we have a valid treatable tool (or, if cauteries are allowed, if we have something hot) + if((I.tool_behaviour == treatable_tool) || (treatable_tool == TOOL_CAUTERY && I.get_temperature())) + allowed = TRUE + // failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only + else if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(I, user)) + allowed = TRUE + // failing THAT, we check if we have a generally allowed item + else + for(var/allowed_type in treatable_by) + if(istype(I, allowed_type)) + allowed = TRUE + break + + // if none of those apply, we return false to avoid interrupting + if(!allowed) + return FALSE + + // now that we've determined we have a valid attempt at treating, we can stomp on their dreams if we're already interacting with the patient + if(INTERACTING_WITH(user, victim)) + to_chat(user, "You're already interacting with [victim]!") + return TRUE + + // lastly, treat them + treat(I, user) + return TRUE + +/// Return TRUE if we have an item that can only be used while aggro grabbed (unhanded aggro grab treatments go in [/datum/wound/proc/try_handling]). Treatment is still is handled in [/datum/wound/proc/treat] +/datum/wound/proc/check_grab_treatments(obj/item/I, mob/user) + return FALSE + +/// Like try_treating() but for unhanded interactions from humans, used by joint dislocations for manual bodypart chiropractice for example. +/datum/wound/proc/try_handling(mob/living/carbon/human/user) + return FALSE + +/// Someone is using something that might be used for treating the wound on this limb +/datum/wound/proc/treat(obj/item/I, mob/user) + return + +/// If var/processing is TRUE, this is run on each life tick +/datum/wound/proc/handle_process() + return + +/// For use in do_after callback checks +/datum/wound/proc/still_exists() + return (!QDELETED(src) && limb) + +/// When our parent bodypart is hurt +/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus) + return + +/// Called from cryoxadone and pyroxadone when they're proc'ing. Wounds will slowly be fixed separately from other methods when these are in effect. crappy name but eh +/datum/wound/proc/on_xadone(power) + cryo_progress += power + if(cryo_progress > 33 * severity) + qdel(src) + +/// When synthflesh is applied to the victim, we call this. No sense in setting up an entire chem reaction system for wounds when we only care for a few chems. Probably will change in the future +/datum/wound/proc/on_synthflesh(power) + return + +/// Called when the patient is undergoing stasis, so that having fully treated a wound doesn't make you sit there helplessly until you think to unbuckle them +/datum/wound/proc/on_stasis() + return + +/// Called when we're crushed in an airlock or firedoor, for one of the improvised joint dislocation fixes +/datum/wound/proc/crush() + return + +/// Used when we're being dragged while bleeding, the value we return is how much bloodloss this wound causes from being dragged. Since it's a proc, you can let bandages soak some of the blood +/datum/wound/proc/drag_bleed_amount() + return + +/** + * get_examine_description() is used in carbon/examine and human/examine to show the status of this wound. Useful if you need to show some status like the wound being splinted or bandaged. + * + * Return the full string line you want to show, note that we're already dealing with the 'warning' span at this point, and that \n is already appended for you in the place this is called from + * + * Arguments: + * * mob/user: The user examining the wound's owner, if that matters + */ +/datum/wound/proc/get_examine_description(mob/user) + . = "[victim.p_their(TRUE)] [limb.name] [examine_desc]" + . = severity <= WOUND_SEVERITY_MODERATE ? "[.]." : "[.]!" + +/datum/wound/proc/get_scanner_description(mob/user) + return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]" + +/datum/wound/proc/severity_text() + switch(severity) + if(WOUND_SEVERITY_TRIVIAL) + return "Trivial" + if(WOUND_SEVERITY_MODERATE) + return "Moderate" + if(WOUND_SEVERITY_SEVERE) + return "Severe" + if(WOUND_SEVERITY_CRITICAL) + return "Critical" diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm new file mode 100644 index 0000000000..128c860a6d --- /dev/null +++ b/code/datums/wounds/bones.dm @@ -0,0 +1,420 @@ +/* + Bones +*/ +// TODO: well, a lot really, but i'd kill to get overlays and a bonebreaking effect like Blitz: The League, similar to electric shock skeletons + +/* + Base definition +*/ +/datum/wound/blunt + sound_effect = 'sound/effects/wounds/crack1.ogg' + wound_type = WOUND_BLUNT + wound_flags = (BONE_WOUND | ACCEPTS_GAUZE) + + /// Have we been taped? + var/taped + /// Have we been bone gel'd? + var/gelled + /// If we did the gel + surgical tape healing method for fractures, how many regen points we need + var/regen_points_needed + /// Our current counter for gel + surgical tape regeneration + var/regen_points_current + /// If we suffer severe head booboos, we can get brain traumas tied to them + var/datum/brain_trauma/active_trauma + /// What brain trauma group, if any, we can draw from for head wounds + var/brain_trauma_group + /// If we deal brain traumas, when is the next one due? + var/next_trauma_cycle + /// How long do we wait +/- 20% for the next trauma? + var/trauma_cycle_cooldown + /// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest + var/internal_bleeding_chance = 0 + +/* + Overwriting of base procs +*/ +/datum/wound/blunt/wound_injury(datum/wound/old_wound = null) + if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group) + processes = TRUE + active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) + next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) + + RegisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, .proc/attack_with_hurt_hand) + if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity))) + var/obj/item/I = victim.get_item_for_held_index(limb.held_index) + if(istype(I, /obj/item/offhand)) + I = victim.get_inactive_held_item() + + if(I && victim.dropItemToGround(I)) + victim.visible_message("[victim] drops [I] in shock!", "The force on your [limb.name] causes you to drop [I]!", vision_distance=COMBAT_MESSAGE_RANGE) + + update_inefficiencies() + +/datum/wound/blunt/remove_wound(ignore_limb, replaced) + limp_slowdown = 0 + QDEL_NULL(active_trauma) + if(victim) + UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + return ..() + +/datum/wound/blunt/handle_process() + . = ..() + if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle) + if(active_trauma) + QDEL_NULL(active_trauma) + else + active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) + next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) + + if(!regen_points_needed) + return + + regen_points_current++ + if(prob(severity * 2)) + victim.take_bodypart_damage(rand(2, severity * 2), stamina=rand(2, severity * 2.5), wound_bonus=CANT_WOUND) + if(prob(33)) + to_chat(victim, "You feel a sharp pain in your body as your bones are reforming!") + + if(regen_points_current > regen_points_needed) + if(!victim || !limb) + qdel(src) + return + to_chat(victim, "Your [limb.name] has recovered from your fracture!") + remove_wound() + +/// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so +/datum/wound/blunt/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) + if(victim.get_active_hand() != limb || victim.a_intent == INTENT_HELP || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) + return + + // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit + if(prob((severity - 1) * 15)) + // And you have a 70% or 50% chance to actually land the blow, respectively + if(prob(70 - 20 * (severity - 1))) + to_chat(victim, "The fracture in your [limb.name] shoots with pain as you strike [target]!") + limb.receive_damage(brute=rand(1,5)) + else + victim.visible_message("[victim] weakly strikes [target] with [victim.p_their()] broken [limb.name], recoiling from pain!", \ + "You fail to strike [target] as the fracture in your [limb.name] lights up in unbearable pain!", vision_distance=COMBAT_MESSAGE_RANGE) + victim.emote("scream") + victim.Stun(0.5 SECONDS) + limb.receive_damage(brute=rand(3,7)) + return COMPONENT_NO_ATTACK_HAND + +/datum/wound/blunt/receive_damage(wounding_type, wounding_dmg, wound_bonus) + if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) + return + if(ishuman(victim)) + var/mob/living/carbon/human/human_victim = victim + if(NOBLOOD in human_victim.dna?.species.species_traits) + return + + if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg)) + var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound + switch(blood_bled) + if(1 to 6) + victim.bleed(blood_bled, TRUE) + if(7 to 13) + victim.visible_message("[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.", "You cough up a bit of blood from the blow to your chest.", vision_distance=COMBAT_MESSAGE_RANGE) + victim.bleed(blood_bled, TRUE) + if(14 to 19) + victim.visible_message("[victim] spits out a string of blood from the blow to [victim.p_their()] chest!", "You spit out a string of blood from the blow to your chest!", vision_distance=COMBAT_MESSAGE_RANGE) + new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) + victim.bleed(blood_bled) + if(20 to INFINITY) + victim.visible_message("[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!", "You choke up on a spray of blood from the blow to your chest!", vision_distance=COMBAT_MESSAGE_RANGE) + victim.bleed(blood_bled) + new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) + victim.add_splatter_floor(get_step(victim.loc, victim.dir)) + + +/datum/wound/blunt/get_examine_description(mob/user) + if(!limb.current_gauze && !gelled && !taped) + return ..() + + var/list/msg = list() + if(!limb.current_gauze) + msg += "[victim.p_their(TRUE)] [limb.name] [examine_desc]" + else + var/sling_condition = "" + // how much life we have left in these bandages + switch(limb.current_gauze.obj_integrity / limb.current_gauze.max_integrity * 100) + if(0 to 25) + sling_condition = "just barely " + if(25 to 50) + sling_condition = "loosely " + if(50 to 75) + sling_condition = "mostly " + if(75 to INFINITY) + sling_condition = "tightly " + + msg += "[victim.p_their(TRUE)] [limb.name] is [sling_condition] fastened in a sling of [limb.current_gauze.name]" + + if(taped) + msg += ", and appears to be reforming itself under some surgical tape!" + else if(gelled) + msg += ", with fizzing flecks of blue bone gel sparking off the bone!" + else + msg += "!" + return "[msg.Join()]" + +/* + New common procs for /datum/wound/blunt/ +*/ + +/datum/wound/blunt/proc/update_inefficiencies() + if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) + if(limb.current_gauze) + limp_slowdown = initial(limp_slowdown) * limb.current_gauze.splint_factor + else + limp_slowdown = initial(limp_slowdown) + victim.apply_status_effect(STATUS_EFFECT_LIMP) + else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + if(limb.current_gauze) + interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_gauze.splint_factor) + else + interaction_efficiency_penalty = interaction_efficiency_penalty + + if(initial(disabling)) + disabling = !limb.current_gauze + + limb.update_wounds() + +/* + Moderate (Joint Dislocation) +*/ + +/datum/wound/blunt/moderate + name = "Joint Dislocation" + desc = "Patient's bone has been unset from socket, causing pain and reduced motor function." + treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice." + examine_desc = "is awkwardly jammed out of place" + occur_text = "jerks violently and becomes unseated" + severity = WOUND_SEVERITY_MODERATE + viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + interaction_efficiency_penalty = 1.5 + limp_slowdown = 1.5 + threshold_minimum = 45 + threshold_penalty = 15 + treatable_tool = TOOL_BONESET + wound_flags = (BONE_WOUND) + status_effect_type = /datum/status_effect/wound/blunt/moderate + scar_keyword = "bluntmoderate" + +/datum/wound/blunt/moderate/crush() + if(prob(33)) + victim.visible_message("[victim]'s dislocated [limb.name] pops back into place!", "Your dislocated [limb.name] pops back into place! Ow!") + remove_wound() + +/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user) + if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB) + return FALSE + + if(user.grab_state == GRAB_PASSIVE) + to_chat(user, "You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!") + return TRUE + + if(user.grab_state >= GRAB_AGGRESSIVE) + user.visible_message("[user] begins twisting and straining [victim]'s dislocated [limb.name]!", "You begin twisting and straining [victim]'s dislocated [limb.name]...", ignored_mobs=victim) + to_chat(victim, "[user] begins twisting and straining your dislocated [limb.name]!") + if(user.a_intent == INTENT_HELP) + chiropractice(user) + else + malpractice(user) + return TRUE + +/// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent +/datum/wound/blunt/moderate/proc/chiropractice(mob/living/carbon/human/user) + var/time = base_treat_time + + if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + + if(prob(65)) + user.visible_message("[user] snaps [victim]'s dislocated [limb.name] back into place!", "You snap [victim]'s dislocated [limb.name] back into place!", ignored_mobs=victim) + to_chat(victim, "[user] snaps your dislocated [limb.name] back into place!") + victim.emote("scream") + limb.receive_damage(brute=20, wound_bonus=CANT_WOUND) + qdel(src) + else + user.visible_message("[user] wrenches [victim]'s dislocated [limb.name] around painfully!", "You wrench [victim]'s dislocated [limb.name] around painfully!", ignored_mobs=victim) + to_chat(victim, "[user] wrenches your dislocated [limb.name] around painfully!") + limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) + chiropractice(user) + +/// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent +/datum/wound/blunt/moderate/proc/malpractice(mob/living/carbon/human/user) + var/time = base_treat_time + + if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + + if(prob(65)) + user.visible_message("[user] snaps [victim]'s dislocated [limb.name] with a sickening crack!", "You snap [victim]'s dislocated [limb.name] with a sickening crack!", ignored_mobs=victim) + to_chat(victim, "[user] snaps your dislocated [limb.name] with a sickening crack!") + victim.emote("scream") + limb.receive_damage(brute=25, wound_bonus=30) + else + user.visible_message("[user] wrenches [victim]'s dislocated [limb.name] around painfully!", "You wrench [victim]'s dislocated [limb.name] around painfully!", ignored_mobs=victim) + to_chat(victim, "[user] wrenches your dislocated [limb.name] around painfully!") + limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) + malpractice(user) + + +/datum/wound/blunt/moderate/treat(obj/item/I, mob/user) + if(victim == user) + victim.visible_message("[user] begins resetting [victim.p_their()] [limb.name] with [I].", "You begin resetting your [limb.name] with [I]...") + else + user.visible_message("[user] begins resetting [victim]'s [limb.name] with [I].", "You begin resetting [victim]'s [limb.name] with [I]...") + + if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists))) + return + + if(victim == user) + limb.receive_damage(brute=15, wound_bonus=CANT_WOUND) + victim.visible_message("[user] finishes resetting [victim.p_their()] [limb.name]!", "You reset your [limb.name]!") + else + limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) + user.visible_message("[user] finishes resetting [victim]'s [limb.name]!", "You finish resetting [victim]'s [limb.name]!", victim) + to_chat(victim, "[user] resets your [limb.name]!") + + victim.emote("scream") + qdel(src) + +/* + Severe (Hairline Fracture) +*/ + +/datum/wound/blunt/severe + name = "Hairline Fracture" + desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality." + treat_text = "Recommended light surgical application of bone gel, though a sling of medical gauze will prevent worsening situation." + examine_desc = "appears grotesquely swollen, its attachment weakened" + occur_text = "sprays chips of bone and develops a nasty looking bruise" + + severity = WOUND_SEVERITY_SEVERE + interaction_efficiency_penalty = 2 + limp_slowdown = 4 + threshold_minimum = 70 + threshold_penalty = 30 + treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) + status_effect_type = /datum/status_effect/wound/blunt/severe + scar_keyword = "bluntsevere" + brain_trauma_group = BRAIN_TRAUMA_MILD + trauma_cycle_cooldown = 1.5 MINUTES + internal_bleeding_chance = 40 + wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE) + +/datum/wound/blunt/critical + name = "Compound Fracture" + desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb." + treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP." + examine_desc = "is mangled and pulped, seemingly held together by tissue alone" + occur_text = "cracks apart, exposing broken bones to open air" + + severity = WOUND_SEVERITY_CRITICAL + interaction_efficiency_penalty = 4 + limp_slowdown = 6 + sound_effect = 'sound/effects/wounds/crack2.ogg' + threshold_minimum = 125 + threshold_penalty = 50 + disabling = TRUE + treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) + status_effect_type = /datum/status_effect/wound/blunt/critical + scar_keyword = "bluntcritical" + brain_trauma_group = BRAIN_TRAUMA_SEVERE + trauma_cycle_cooldown = 2.5 MINUTES + internal_bleeding_chance = 60 + wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE) + +// doesn't make much sense for "a" bone to stick out of your head +/datum/wound/blunt/critical/apply_wound(obj/item/bodypart/L, silent, datum/wound/old_wound, smited) + if(L.body_zone == BODY_ZONE_HEAD) + occur_text = "splits open, exposing a bare, cracked skull through the flesh and blood" + examine_desc = "has an unsettling indent, with bits of skull poking out" + . = ..() + +/// if someone is using bone gel on our wound +/datum/wound/blunt/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user) + if(gelled) + to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!") + return + + user.visible_message("[user] begins hastily applying [I] to [victim]'s' [limb.name]...", "You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name], disregarding the warning label...") + + if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists))) + return + + I.use(1) + victim.emote("scream") + if(user != victim) + user.visible_message("[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!", "You finish applying [I] to [victim]'s [limb.name]!", ignored_mobs=victim) + to_chat(victim, "[user] finishes applying [I] to your [limb.name], and you can feel the bones exploding with pain as they begin melting and reforming!") + else + var/painkiller_bonus = 0 + if(victim.drunkenness) + painkiller_bonus += 5 + if(victim.reagents?.has_reagent(/datum/reagent/medicine/morphine)) + painkiller_bonus += 10 + if(victim.reagents?.has_reagent(/datum/reagent/determination)) + painkiller_bonus += 5 + + if(prob(25 + (20 * severity - 2) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers + victim.visible_message("[victim] fails to finish applying [I] to [victim.p_their()] [limb.name], passing out from the pain!", "You black out from the pain of applying [I] to your [limb.name] before you can finish!") + victim.AdjustUnconscious(5 SECONDS) + return + victim.visible_message("[victim] finishes applying [I] to [victim.p_their()] [limb.name], grimacing from the pain!", "You finish applying [I] to your [limb.name], and your bones explode in pain!") + + limb.receive_damage(30, stamina=100, wound_bonus=CANT_WOUND) + if(!gelled) + gelled = TRUE + +/// if someone is using surgical tape on our wound +/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user) + if(!gelled) + to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] must be coated with bone gel to perform this emergency operation!") + return + if(taped) + to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] is already wrapped in [I.name] and reforming!") + return + + user.visible_message("[user] begins applying [I] to [victim]'s' [limb.name]...", "You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...") + + if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists))) + return + + regen_points_current = 0 + regen_points_needed = 30 SECONDS * (user == victim ? 1.5 : 1) * (severity - 1) + I.use(1) + if(user != victim) + user.visible_message("[user] finishes applying [I] to [victim]'s [limb.name], emitting a fizzing noise!", "You finish applying [I] to [victim]'s [limb.name]!", ignored_mobs=victim) + to_chat(victim, "[user] finishes applying [I] to your [limb.name], you immediately begin to feel your bones start to reform!") + else + victim.visible_message("[victim] finishes applying [I] to [victim.p_their()] [limb.name], !", "You finish applying [I] to your [limb.name], and you immediately begin to feel your bones start to reform!") + + taped = TRUE + processes = TRUE + +/datum/wound/blunt/treat(obj/item/I, mob/user) + if(istype(I, /obj/item/stack/medical/bone_gel)) + gel(I, user) + else if(istype(I, /obj/item/stack/sticky_tape/surgical)) + tape(I, user) + +/datum/wound/blunt/get_scanner_description(mob/user) + . = ..() + + . += "
" + + if(!gelled) + . += "Alternative Treatment: Apply bone gel directly to injured limb, then apply surgical tape to begin bone regeneration. This is both excruciatingly painful and slow, and only recommended in dire circumstances.\n" + else if(!taped) + . += "Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow.\n" + else + . += "Note: Bone regeneration in effect. Bone is [round(regen_points_current*100/regen_points_needed)]% regenerated.\n" + + if(limb.body_zone == BODY_ZONE_HEAD) + . += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired." + else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume) + . += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired." + . += "
" diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm new file mode 100644 index 0000000000..f3e22807cf --- /dev/null +++ b/code/datums/wounds/burns.dm @@ -0,0 +1,296 @@ + + +// TODO: well, a lot really, but specifically I want to add potential fusing of clothing/equipment on the affected area, and limb infections, though those may go in body part code +/datum/wound/burn + a_or_from = "from" + wound_type = WOUND_BURN + processes = TRUE + sound_effect = 'sound/effects/wounds/sizzle1.ogg' + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) + + treatable_by = list(/obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon + + // Flesh damage vars + /// How much damage to our flesh we currently have. Once both this and infestation reach 0, the wound is considered healed + var/flesh_damage = 5 + /// Our current counter for how much flesh regeneration we have stacked from regenerative mesh/synthflesh/whatever, decrements each tick and lowers flesh_damage + var/flesh_healing = 0 + + // Infestation vars (only for severe and critical) + /// How quickly infection breeds on this burn if we don't have disinfectant + var/infestation_rate = 0 + /// Our current level of infection + var/infestation = 0 + /// Our current level of sanitization/anti-infection, from disinfectants/alcohol/UV lights. While positive, totally pauses and slowly reverses infestation effects each tick + var/sanitization = 0 + + /// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen) + var/strikes_to_lose_limb = 3 + + +/datum/wound/burn/handle_process() + . = ..() + if(strikes_to_lose_limb == 0) + victim.adjustToxLoss(0.5) + if(prob(1)) + victim.visible_message("The infection on the remnants of [victim]'s [limb.name] shift and bubble nauseatingly!", "You can feel the infection on the remnants of your [limb.name] coursing through your veins!") + return + + if(victim.reagents) + if(victim.reagents.has_reagent(/datum/reagent/medicine/spaceacillin)) + sanitization += 0.9 + if(victim.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine/)) + sanitization += 0.9 + if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve)) + sanitization += 0.3 + flesh_healing += 0.5 + + if(limb.current_gauze) + limb.seep_gauze(WOUND_BURN_SANITIZATION_RATE) + + if(flesh_healing > 0) + var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) + flesh_damage = max(0, flesh_damage - 1) + flesh_healing = max(0, flesh_healing - bandage_factor) // good bandages multiply the length of flesh healing + + // here's the check to see if we're cleared up + if((flesh_damage <= 0) && (infestation <= 1)) + to_chat(victim, "The burns on your [limb.name] have cleared up!") + qdel(src) + return + + // sanitization is checked after the clearing check but before the rest, because we freeze the effects of infection while we have sanitization + if(sanitization > 0) + var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) + infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE) + sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor)) + return + + infestation += infestation_rate + + switch(infestation) + if(0 to WOUND_INFECTION_MODERATE) + if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) + if(prob(30)) + victim.adjustToxLoss(0.2) + if(prob(6)) + to_chat(victim, "The blisters on your [limb.name] ooze a strange pus...") + if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) + if(!disabling && prob(2)) + to_chat(victim, "Your [limb.name] completely locks up, as you struggle for control against the infection!") + disabling = TRUE + else if(disabling && prob(8)) + to_chat(victim, "You regain sensation in your [limb.name], but it's still in terrible shape!") + disabling = FALSE + else if(prob(20)) + victim.adjustToxLoss(0.5) + if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) + if(!disabling && prob(3)) + to_chat(victim, "You suddenly lose all sensation of the festering infection in your [limb.name]!") + disabling = TRUE + else if(disabling && prob(3)) + to_chat(victim, "You can barely feel your [limb.name] again, and you have to strain to retain motor control!") + disabling = FALSE + else if(prob(1)) + to_chat(victim, "You contemplate life without your [limb.name]...") + victim.adjustToxLoss(0.75) + else if(prob(4)) + victim.adjustToxLoss(1) + if(WOUND_INFECTION_SEPTIC to INFINITY) + if(prob(infestation)) + switch(strikes_to_lose_limb) + if(3 to INFINITY) + to_chat(victim, "The skin on your [limb.name] is literally dripping off, you feel awful!") + if(2) + to_chat(victim, "The infection in your [limb.name] is literally dripping off, you feel horrible!") + if(1) + to_chat(victim, "Infection has just about completely claimed your [limb.name]!") + if(0) + to_chat(victim, "The last of the nerve endings in your [limb.name] wither away, as the infection completely paralyzes your joint connector.") + threshold_penalty = 120 // piss easy to destroy + var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone) + victim.gain_trauma(sepsis) + strikes_to_lose_limb-- + +/datum/wound/burn/get_examine_description(mob/user) + if(strikes_to_lose_limb <= 0) + return "[victim.p_their(TRUE)] [limb.name] is completely dead and unrecognizable as organic." + + var/list/condition = list("[victim.p_their(TRUE)] [limb.name] [examine_desc]") + if(limb.current_gauze) + var/bandage_condition + switch(limb.current_gauze.absorption_capacity) + if(0 to 1.25) + bandage_condition = "nearly ruined " + if(1.25 to 2.75) + bandage_condition = "badly worn " + if(2.75 to 4) + bandage_condition = "slightly pus-stained " + if(4 to INFINITY) + bandage_condition = "clean " + + condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]" + else + switch(infestation) + if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) + condition += ", with small spots of discoloration along the nearby veins!" + if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) + condition += ", with dark clouds spreading outwards under the skin!" + if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) + condition += ", with streaks of rotten infection pulsating outward!" + if(WOUND_INFECTION_SEPTIC to INFINITY) + return "[victim.p_their(TRUE)] [limb.name] is a mess of char and rot, skin literally dripping off the bone with infection!" + else + condition += "!" + + return "[condition.Join()]" + +/datum/wound/burn/get_scanner_description(mob/user) + if(strikes_to_lose_limb == 0) + var/oopsie = "Type: [name]\nSeverity: [severity_text()]" + oopsie += "
Infection Level: The infection is total. The bodypart is lost. Amputate or augment limb immediately.
" + return oopsie + + . = ..() + . += "
" + + if(infestation <= sanitization && flesh_damage <= flesh_healing) + . += "No further treatment required: Burns will heal shortly." + else + switch(infestation) + if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) + . += "Infection Level: Moderate\n" + if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) + . += "Infection Level: Severe\n" + if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) + . += "Infection Level: CRITICAL\n" + if(WOUND_INFECTION_SEPTIC to INFINITY) + . += "Infection Level: LOSS IMMINENT\n" + if(infestation > sanitization) + . += "\tSurgical debridement, antiobiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n" + + if(flesh_damage > 0) + . += "Flesh damage detected: Please apply ointment or regenerative mesh to allow recovery.\n" + . += "
" + +/* + new burn common procs +*/ + +/// if someone is using ointment on our burns +/datum/wound/burn/proc/ointment(obj/item/stack/medical/ointment/I, mob/user) + user.visible_message("[user] begins applying [I] to [victim]'s [limb.name]...", "You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...") + if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), extra_checks = CALLBACK(src, .proc/still_exists))) + return + + limb.heal_damage(I.heal_brute, I.heal_burn) + user.visible_message("[user] applies [I] to [victim].", "You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].") + I.use(1) + sanitization += I.sanitization + flesh_healing += I.flesh_regeneration + + if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage)) + to_chat(user, "You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.") + else + try_treating(I, user) + +/// if someone is using mesh on our burns +/datum/wound/burn/proc/mesh(obj/item/stack/medical/mesh/I, mob/user) + user.visible_message("[user] begins wrapping [victim]'s [limb.name] with [I]...", "You begin wrapping [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + + limb.heal_damage(I.heal_brute, I.heal_burn) + user.visible_message("[user] applies [I] to [victim].", "You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].") + I.use(1) + sanitization += I.sanitization + flesh_healing += I.flesh_regeneration + + if(sanitization >= infestation && flesh_healing > flesh_damage) + to_chat(user, "You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.name] to recover.") + else + try_treating(I, user) + +/// Paramedic UV penlights +/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user) + if(!COOLDOWN_FINISHED(I, uv_cooldown)) + to_chat(user, "[I] is still recharging!") + return + if(infestation <= 0 || infestation < sanitization) + to_chat(user, "There's no infection to treat on [victim]'s [limb.name]!") + return + + user.visible_message("[user] flashes the burns on [victim]'s [limb] with [I].", "You flash the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I].", vision_distance=COMBAT_MESSAGE_RANGE) + sanitization += I.uv_power + COOLDOWN_START(I, uv_cooldown, I.uv_cooldown_length) + +/datum/wound/burn/treat(obj/item/I, mob/user) + if(istype(I, /obj/item/stack/medical/ointment)) + ointment(I, user) + else if(istype(I, /obj/item/stack/medical/mesh)) + mesh(I, user) + else if(istype(I, /obj/item/flashlight/pen/paramedic)) + uv(I, user) + +// people complained about burns not healing on stasis beds, so in addition to checking if it's cured, they also get the special ability to very slowly heal on stasis beds if they have the healing effects stored +/datum/wound/burn/on_stasis() + . = ..() + if(flesh_healing > 0) + flesh_damage = max(0, flesh_damage - 0.2) + if((flesh_damage <= 0) && (infestation <= 1)) + to_chat(victim, "The burns on your [limb.name] have cleared up!") + qdel(src) + return + if(sanitization > 0) + infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE * 0.2) + +/datum/wound/burn/on_synthflesh(amount) + flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard + +// we don't even care about first degree burns, straight to second +/datum/wound/burn/moderate + name = "Second Degree Burns" + desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations." + treat_text = "Recommended application of topical ointment or regenerative mesh to affected region." + examine_desc = "is badly burned and breaking out in blisters" + occur_text = "breaks out with violent red burns" + severity = WOUND_SEVERITY_MODERATE + damage_mulitplier_penalty = 1.05 + threshold_minimum = 50 + threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds + status_effect_type = /datum/status_effect/wound/burn/moderate + flesh_damage = 5 + scar_keyword = "burnmoderate" + +/datum/wound/burn/severe + name = "Third Degree Burns" + desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity." + treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment." + examine_desc = "appears seriously charred, with aggressive red splotches" + occur_text = "chars rapidly, exposing ruined tissue and spreading angry red burns" + severity = WOUND_SEVERITY_SEVERE + damage_mulitplier_penalty = 1.1 + threshold_minimum = 90 + threshold_penalty = 40 + status_effect_type = /datum/status_effect/wound/burn/severe + treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) + infestation_rate = 0.05 // appx 13 minutes to reach sepsis without any treatment + flesh_damage = 12.5 + scar_keyword = "burnsevere" + +/datum/wound/burn/critical + name = "Catastrophic Burns" + desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity." + treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging." + examine_desc = "is a ruined mess of blanched bone, melted fat, and charred tissue" + occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess" + severity = WOUND_SEVERITY_CRITICAL + damage_mulitplier_penalty = 1.15 + sound_effect = 'sound/effects/wounds/sizzle2.ogg' + threshold_minimum = 150 + threshold_penalty = 80 + status_effect_type = /datum/status_effect/wound/burn/critical + treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) + infestation_rate = 0.15 // appx 4.33 minutes to reach sepsis without any treatment + flesh_damage = 20 + scar_keyword = "burncritical" diff --git a/code/datums/wounds/loss.dm b/code/datums/wounds/loss.dm new file mode 100644 index 0000000000..6c5e536fb2 --- /dev/null +++ b/code/datums/wounds/loss.dm @@ -0,0 +1,41 @@ +/datum/wound/loss + name = "Dismembered" + desc = "oof ouch!!" + + sound_effect = 'sound/effects/dismember.ogg' + severity = WOUND_SEVERITY_LOSS + threshold_minimum = 180 + status_effect_type = null + scar_keyword = "dismember" + wound_flags = null + +/// Our special proc for our special dismembering, the wounding type only matters for what text we have +/datum/wound/loss/proc/apply_dismember(obj/item/bodypart/dismembered_part, wounding_type=WOUND_SLASH) + if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in viable_zones) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember()) + qdel(src) + return + + already_scarred = TRUE // so we don't scar a limb we don't have. If I add different levels of amputation desc, do it here + + switch(wounding_type) + if(WOUND_BLUNT) + occur_text = "is shattered through the last bone holding it together, severing it completely!" + if(WOUND_SLASH) + occur_text = "is slashed through the last tissue holding it together, severing it completely!" + if(WOUND_PIERCE) + occur_text = "is pierced through the last tissue holding it together, severing it completely!" + if(WOUND_BURN) + occur_text = "is completely incinerated, falling to dust!" + + victim = dismembered_part.owner + + var/msg = "[victim]'s [dismembered_part.name] [occur_text]!" + + victim.visible_message(msg, "Your [dismembered_part.name] [occur_text]!") + + limb = dismembered_part + severity = WOUND_SEVERITY_LOSS + second_wind() + log_wound(victim, src) + dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE) + qdel(src) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm new file mode 100644 index 0000000000..56c60b31d7 --- /dev/null +++ b/code/datums/wounds/pierce.dm @@ -0,0 +1,170 @@ +/* + Pierce +*/ + +/datum/wound/pierce + sound_effect = 'sound/weapons/slice.ogg' + processes = TRUE + wound_type = WOUND_PIERCE + treatable_by = list(/obj/item/stack/medical/suture) + treatable_tool = TOOL_CAUTERY + base_treat_time = 3 SECONDS + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) + + /// How much blood we start losing when this wound is first applied + var/initial_flow + /// If gauzed, what percent of the internal bleeding actually clots of the total absorption rate + var/gauzed_clot_rate + + /// When hit on this bodypart, we have this chance of losing some blood + the incoming damage + var/internal_bleeding_chance + /// If we let off blood when hit, the max blood lost is this * the incoming damage + var/internal_bleeding_coefficient + +/datum/wound/pierce/wound_injury(datum/wound/old_wound) + blood_flow = initial_flow + +/datum/wound/pierce/receive_damage(wounding_type, wounding_dmg, wound_bonus) + if(victim.stat == DEAD || wounding_dmg < 5) + return + if(victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg)) + if(limb.current_gauze && limb.current_gauze.splint_factor) + wounding_dmg *= (1 - limb.current_gauze.splint_factor) + var/blood_bled = rand(1, wounding_dmg * internal_bleeding_coefficient) // 12 brute toolbox can cause up to 15/18/21 bloodloss on mod/sev/crit + switch(blood_bled) + if(1 to 6) + victim.bleed(blood_bled, TRUE) + if(7 to 13) + victim.visible_message("Blood droplets fly from the hole in [victim]'s [limb.name].", "You cough up a bit of blood from the blow to your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE) + victim.bleed(blood_bled, TRUE) + if(14 to 19) + victim.visible_message("A small stream of blood spurts from the hole in [victim]'s [limb.name]!", "You spit out a string of blood from the blow to your [limb.name]!", vision_distance=COMBAT_MESSAGE_RANGE) + new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) + victim.bleed(blood_bled) + if(20 to INFINITY) + victim.visible_message("A spray of blood streams from the gash in [victim]'s [limb.name]!", "You choke up on a spray of blood from the blow to your [limb.name]!", vision_distance=COMBAT_MESSAGE_RANGE) + victim.bleed(blood_bled) + new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) + victim.add_splatter_floor(get_step(victim.loc, victim.dir)) + +/datum/wound/pierce/handle_process() + blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW) + + if(victim.bodytemperature < (BODYTEMP_NORMAL - 10)) + blood_flow -= 0.2 + if(prob(5)) + to_chat(victim, "You feel the [lowertext(name)] in your [limb.name] firming up from the cold!") + + if(victim.reagents?.has_reagent(/datum/reagent/toxin/heparin)) + blood_flow += 0.5 // old herapin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first + + if(limb.current_gauze) + blood_flow -= limb.current_gauze.absorption_rate * gauzed_clot_rate + limb.current_gauze.absorption_capacity -= limb.current_gauze.absorption_rate + + if(blood_flow <= 0) + qdel(src) + +/datum/wound/pierce/on_stasis() + . = ..() + if(blood_flow <= 0) + qdel(src) + +/datum/wound/pierce/treat(obj/item/I, mob/user) + if(istype(I, /obj/item/stack/medical/suture)) + suture(I, user) + else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300) + tool_cauterize(I, user) + +/datum/wound/pierce/on_xadone(power) + . = ..() + blood_flow -= 0.03 * power // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort + +/datum/wound/pierce/on_synthflesh(power) + . = ..() + blood_flow -= 0.05 * power // 20u * 0.05 = -1 blood flow, less than with slashes but still good considering smaller bleed rates + +/// If someone is using a suture to close this cut +/datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/I, mob/user) + var/self_penalty_mult = (user == victim ? 1.4 : 1) + user.visible_message("[user] begins stitching [victim]'s [limb.name] with [I]...", "You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + user.visible_message("[user] stitches up some of the bleeding on [victim].", "You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].") + var/blood_sutured = I.stop_bleeding / self_penalty_mult * 0.5 + blood_flow -= blood_sutured + limb.heal_damage(I.heal_brute, I.heal_burn) + + if(blood_flow > 0) + try_treating(I, user) + else + to_chat(user, "You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [limb.name].") + +/// If someone is using either a cautery tool or something with heat to cauterize this pierce +/datum/wound/pierce/proc/tool_cauterize(obj/item/I, mob/user) + var/self_penalty_mult = (user == victim ? 1.5 : 1) + user.visible_message("[user] begins cauterizing [victim]'s [limb.name] with [I]...", "You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + + user.visible_message("[user] cauterizes some of the bleeding on [victim].", "You cauterize some of the bleeding on [victim].") + limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND) + if(prob(30)) + victim.emote("scream") + var/blood_cauterized = (0.6 / self_penalty_mult) * 0.5 + blood_flow -= blood_cauterized + + if(blood_flow > 0) + try_treating(I, user) + +/datum/wound/pierce/moderate + name = "Minor Breakage" + desc = "Patient's skin has been broken open, causing severe bruising and minor internal bleeding in affected area." + treat_text = "Treat affected site with bandaging or exposure to extreme cold. In dire cases, brief exposure to vacuum may suffice." // space is cold in ss13, so it's like an ice pack! + examine_desc = "has a small, circular hole, gently bleeding" + occur_text = "spurts out a thin stream of blood" + sound_effect = 'sound/effects/wounds/pierce1.ogg' + severity = WOUND_SEVERITY_MODERATE + initial_flow = 1.5 + gauzed_clot_rate = 0.8 + internal_bleeding_chance = 30 + internal_bleeding_coefficient = 1.25 + threshold_minimum = 40 + threshold_penalty = 15 + status_effect_type = /datum/status_effect/wound/pierce/moderate + scar_keyword = "piercemoderate" + +/datum/wound/pierce/severe + name = "Open Puncture" + desc = "Patient's internal tissue is penetrated, causing sizeable internal bleeding and reduced limb stability." + treat_text = "Repair punctures in skin by suture or cautery, extreme cold may also work." + examine_desc = "is pierced clear through, with bits of tissue obscuring the open hole" + occur_text = "looses a violent spray of blood, revealing a pierced wound" + sound_effect = 'sound/effects/wounds/pierce2.ogg' + severity = WOUND_SEVERITY_SEVERE + initial_flow = 2.25 + gauzed_clot_rate = 0.6 + internal_bleeding_chance = 60 + internal_bleeding_coefficient = 1.5 + threshold_minimum = 60 + threshold_penalty = 25 + status_effect_type = /datum/status_effect/wound/pierce/severe + scar_keyword = "piercesevere" + +/datum/wound/pierce/critical + name = "Ruptured Cavity" + desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs." + treat_text = "Surgical repair of puncture wound, followed by supervised resanguination." + examine_desc = "is ripped clear through, barely held together by exposed bone" + occur_text = "blasts apart, sending chunks of viscera flying in all directions" + sound_effect = 'sound/effects/wounds/pierce3.ogg' + severity = WOUND_SEVERITY_CRITICAL + initial_flow = 3 + gauzed_clot_rate = 0.4 + internal_bleeding_chance = 80 + internal_bleeding_coefficient = 1.75 + threshold_minimum = 110 + threshold_penalty = 40 + status_effect_type = /datum/status_effect/wound/pierce/critical + scar_keyword = "piercecritical" + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm new file mode 100644 index 0000000000..9044835272 --- /dev/null +++ b/code/datums/wounds/slash.dm @@ -0,0 +1,300 @@ +/* + Cuts +*/ + +/datum/wound/slash + sound_effect = 'sound/weapons/slice.ogg' + processes = TRUE + wound_type = WOUND_SLASH + treatable_by = list(/obj/item/stack/medical/suture) + treatable_by_grabbed = list(/obj/item/gun/energy/laser) + treatable_tool = TOOL_CAUTERY + base_treat_time = 3 SECONDS + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) + + /// How much blood we start losing when this wound is first applied + var/initial_flow + /// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound + var/minimum_flow + /// How fast our blood flow will naturally decrease per tick, not only do larger cuts bleed more faster, they clot slower + var/clot_rate + + /// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better + var/demotes_to + + /// How much staunching per type (cautery, suturing, bandaging) you can have before that type is no longer effective for this cut NOT IMPLEMENTED + var/max_per_type + /// The maximum flow we've had so far + var/highest_flow + + /// A bad system I'm using to track the worst scar we earned (since we can demote, we want the biggest our wound has been, not what it was when it was cured (probably moderate)) + var/datum/scar/highest_scar + +/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null) + blood_flow = initial_flow + if(old_wound) + blood_flow = max(old_wound.blood_flow, initial_flow) + if(old_wound.severity > severity && old_wound.highest_scar) + highest_scar = old_wound.highest_scar + old_wound.highest_scar = null + + if(!highest_scar) + highest_scar = new + highest_scar.generate(limb, src, add_to_scars=FALSE) + +/datum/wound/slash/remove_wound(ignore_limb, replaced) + if(!replaced && highest_scar) + already_scarred = TRUE + highest_scar.lazy_attach(limb) + return ..() + +/datum/wound/slash/get_examine_description(mob/user) + if(!limb.current_gauze) + return ..() + + var/list/msg = list("The cuts on [victim.p_their()] [limb.name] are wrapped with") + // how much life we have left in these bandages + switch(limb.current_gauze.absorption_capacity) + if(0 to 1.25) + msg += "nearly ruined " + if(1.25 to 2.75) + msg += "badly worn " + if(2.75 to 4) + msg += "slightly bloodied " + if(4 to INFINITY) + msg += "clean " + msg += "[limb.current_gauze.name]!" + + return "[msg.Join()]" + +/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus) + if(victim.stat != DEAD && wounding_type == WOUND_SLASH) // can't stab dead bodies to make it bleed faster this way + blood_flow += 0.05 * wounding_dmg + +/datum/wound/slash/drag_bleed_amount() + // say we have 3 severe cuts with 3 blood flow each, pretty reasonable + // compare with being at 100 brute damage before, where you bled (brute/100 * 2), = 2 blood per tile + var/bleed_amt = min(blood_flow * 0.1, 1) // 3 * 3 * 0.1 = 0.9 blood total, less than before! the share here is .3 blood of course. + + if(limb.current_gauze) // gauze stops all bleeding from dragging on this limb, but wears the gauze out quicker + limb.seep_gauze(bleed_amt * 0.33) + return + + return bleed_amt + +/datum/wound/slash/handle_process() + if(victim.stat == DEAD) + blood_flow -= max(clot_rate, WOUND_SLASH_DEAD_CLOT_MIN) + if(blood_flow < minimum_flow) + if(demotes_to) + replace_wound(demotes_to) + return + qdel(src) + return + + blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW) + + if(victim.reagents?.has_reagent(/datum/reagent/toxin/heparin)) + blood_flow += 0.5 // old herapin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first + + if(limb.current_gauze) + if(clot_rate > 0) + blood_flow -= clot_rate + blood_flow -= limb.current_gauze.absorption_rate + limb.seep_gauze(limb.current_gauze.absorption_rate) + else + blood_flow -= clot_rate + + if(blood_flow > highest_flow) + highest_flow = blood_flow + + if(blood_flow < minimum_flow) + if(demotes_to) + replace_wound(demotes_to) + else + to_chat(victim, "The cut on your [limb.name] has stopped bleeding!") + qdel(src) + + +/datum/wound/slash/on_stasis() + if(blood_flow >= minimum_flow) + return + if(demotes_to) + replace_wound(demotes_to) + return + qdel(src) + +/* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */ + +/datum/wound/slash/check_grab_treatments(obj/item/I, mob/user) + if(istype(I, /obj/item/gun/energy/laser)) + return TRUE + +/datum/wound/slash/treat(obj/item/I, mob/user) + if(istype(I, /obj/item/gun/energy/laser)) + las_cauterize(I, user) + else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300) + tool_cauterize(I, user) + else if(istype(I, /obj/item/stack/medical/suture)) + suture(I, user) + +/datum/wound/slash/try_handling(mob/living/carbon/human/user) + if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB) + return FALSE + + if(!iscatperson(user)) + return FALSE + + lick_wounds(user) + return TRUE + +/// if a felinid is licking this cut to reduce bleeding +/datum/wound/slash/proc/lick_wounds(mob/living/carbon/human/user) + if(INTERACTING_WITH(user, victim)) + to_chat(user, "You're already interacting with [victim]!") + return + + if(user.is_mouth_covered()) + to_chat(user, "Your mouth is covered, you can't lick [victim]'s wounds!") + return + + if(!user.getorganslot(ORGAN_SLOT_TONGUE)) + to_chat(user, "You can't lick wounds without a tongue!") // f in chat + return + + // transmission is one way patient -> felinid since google said cat saliva is antiseptic or whatever, and also because felinids are already risking getting beaten for this even without people suspecting they're spreading a deathvirus + for(var/datum/disease/D in victim.diseases) + user.ForceContractDisease(D) + + user.visible_message("[user] begins licking the wounds on [victim]'s [limb.name].", "You begin licking the wounds on [victim]'s [limb.name]...", ignored_mobs=victim) + to_chat(victim, "[user] begins to lick the wounds on your [limb.name].[user] licks the wounds on [victim]'s [limb.name].", "You lick some of the wounds on [victim]'s [limb.name]", ignored_mobs=victim) + to_chat(victim, "[user] licks the wounds on your [limb.name]! minimum_flow) + try_handling(user) + else if(demotes_to) + to_chat(user, "You successfully lower the severity of [victim]'s cuts.") + +/datum/wound/slash/on_xadone(power) + . = ..() + blood_flow -= 0.03 * power // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort + +/datum/wound/slash/on_synthflesh(power) + . = ..() + blood_flow -= 0.075 * power // 20u * 0.075 = -1.5 blood flow, pretty good for how little effort it is + +/// If someone's putting a laser gun up to our cut to cauterize it +/datum/wound/slash/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user) + var/self_penalty_mult = (user == victim ? 1.25 : 1) + user.visible_message("[user] begins aiming [lasgun] directly at [victim]'s [limb.name]...", "You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.name]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + var/damage = lasgun.chambered.BB.damage + lasgun.chambered.BB.wound_bonus -= 30 + lasgun.chambered.BB.damage *= self_penalty_mult + if(!lasgun.process_fire(victim, victim, TRUE, null, limb.body_zone)) + return + victim.emote("scream") + blood_flow -= damage / (5 * self_penalty_mult) // 20 / 5 = 4 bloodflow removed, p good + victim.visible_message("The cuts on [victim]'s [limb.name] scar over!") + +/// If someone is using either a cautery tool or something with heat to cauterize this cut +/datum/wound/slash/proc/tool_cauterize(obj/item/I, mob/user) + var/self_penalty_mult = (user == victim ? 1.5 : 1) + user.visible_message("[user] begins cauterizing [victim]'s [limb.name] with [I]...", "You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + + user.visible_message("[user] cauterizes some of the bleeding on [victim].", "You cauterize some of the bleeding on [victim].") + limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND) + if(prob(30)) + victim.emote("scream") + var/blood_cauterized = (0.6 / self_penalty_mult) + blood_flow -= blood_cauterized + + if(blood_flow > minimum_flow) + try_treating(I, user) + else if(demotes_to) + to_chat(user, "You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.") + +/// If someone is using a suture to close this cut +/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/I, mob/user) + var/self_penalty_mult = (user == victim ? 1.4 : 1) + user.visible_message("[user] begins stitching [victim]'s [limb.name] with [I]...", "You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + user.visible_message("[user] stitches up some of the bleeding on [victim].", "You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].") + var/blood_sutured = I.stop_bleeding / self_penalty_mult + blood_flow -= blood_sutured + limb.heal_damage(I.heal_brute, I.heal_burn) + + if(blood_flow > minimum_flow) + try_treating(I, user) + else if(demotes_to) + to_chat(user, "You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.") + + +/datum/wound/slash/moderate + name = "Rough Abrasion" + desc = "Patient's skin has been badly scraped, generating moderate blood loss." + treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest." + examine_desc = "has an open cut" + occur_text = "is cut open, slowly leaking blood" + sound_effect = 'sound/effects/wounds/blood1.ogg' + severity = WOUND_SEVERITY_MODERATE + initial_flow = 1.5 + minimum_flow = 0.375 + max_per_type = 3 + clot_rate = 0.12 + threshold_minimum = 30 + threshold_penalty = 10 + status_effect_type = /datum/status_effect/wound/slash/moderate + scar_keyword = "slashmoderate" + +/datum/wound/slash/severe + name = "Open Laceration" + desc = "Patient's skin is ripped clean open, allowing significant blood loss." + treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery." + examine_desc = "has a severe cut" + occur_text = "is ripped open, veins spurting blood" + sound_effect = 'sound/effects/wounds/blood2.ogg' + severity = WOUND_SEVERITY_SEVERE + initial_flow = 2.4375 + minimum_flow = 2.0625 + clot_rate = 0.07 + max_per_type = 4 + threshold_minimum = 60 + threshold_penalty = 25 + demotes_to = /datum/wound/slash/moderate + status_effect_type = /datum/status_effect/wound/slash/severe + scar_keyword = "slashsevere" + +/datum/wound/slash/critical + name = "Weeping Avulsion" + desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention." + treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination." + examine_desc = "is carved down to the bone, spraying blood wildly" + occur_text = "is torn open, spraying blood wildly" + sound_effect = 'sound/effects/wounds/blood3.ogg' + severity = WOUND_SEVERITY_CRITICAL + initial_flow = 3.1875 + minimum_flow = 3 + clot_rate = -0.05 // critical cuts actively get worse instead of better + max_per_type = 5 + threshold_minimum = 90 + threshold_penalty = 40 + demotes_to = /datum/wound/slash/severe + status_effect_type = /datum/status_effect/wound/slash/critical + scar_keyword = "slashcritical" + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index dabbe93bec..672d5c096f 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -16,6 +16,8 @@ /// If it's valid territory for gangs/cults to summon var/valid_territory = TRUE + /// malf ais can hack this + var/valid_malf_hack = TRUE /// if blobs can spawn there and if it counts towards their score. var/blob_allowed = TRUE /// whether servants can warp into this area from Reebe @@ -516,7 +518,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) used_environ += amount -/area/Entered(atom/movable/M) +/area/Entered(atom/movable/M, atom/OldLoc) set waitfor = FALSE SEND_SIGNAL(src, COMSIG_AREA_ENTERED, M) SEND_SIGNAL(M, COMSIG_ENTER_AREA, src) //The atom that enters the area @@ -524,6 +526,11 @@ GLOBAL_LIST_EMPTY(teleportlocs) return var/mob/living/L = M + var/turf/oldTurf = get_turf(OldLoc) + var/area/A = oldTurf?.loc + if(A && (A.has_gravity != has_gravity)) + L.update_gravity(L.mob_has_gravity()) + if(!L.ckey) return @@ -567,6 +574,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) power_environ = FALSE always_unpowered = FALSE valid_territory = FALSE + valid_malf_hack = FALSE blob_allowed = FALSE addSorted() diff --git a/code/game/atoms.dm b/code/game/atoms.dm index e3f4829d3d..8a66394ecc 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -26,7 +26,6 @@ var/list/atom_colours //used to store the different colors on an atom //its inherent color, the colored paint applied on it, special color effect etc... - var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. var/list/remove_overlays // a very temporary list of overlays to remove var/list/add_overlays // a very temporary list of overlays to add @@ -48,6 +47,7 @@ var/rad_insulation = RAD_NO_INSULATION ///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.) + ///The list referenced by this var can be shared by multiple objects and should not be directly modified. Instead, use [set_custom_materials][/atom/proc/set_custom_materials]. var/list/custom_materials ///Bitfield for how the atom handles materials. var/material_flags = NONE @@ -69,6 +69,9 @@ /// A luminescence-shifted value of the last color calculated for chatmessage overlays var/chat_color_darkened + ///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy() + var/list/targeted_by + /atom/New(loc, ...) //atom creation method that preloads variables at creation if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() @@ -100,6 +103,8 @@ stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 + if(loc) + SEND_SIGNAL(loc, COMSIG_ATOM_CREATED, src) /// Sends a signal that the new atom `src`, has been created at `loc` //atom color stuff if(color) add_atom_colour(color, FIXED_COLOUR_PRIORITY) @@ -114,11 +119,8 @@ if (canSmoothWith) canSmoothWith = typelist("canSmoothWith", canSmoothWith) - var/temp_list = list() - for(var/i in custom_materials) - temp_list[SSmaterials.GetMaterialRef(i)] = custom_materials[i] //Get the proper instanced version - custom_materials = null //Null the list to prepare for applying the materials properly - set_custom_materials(temp_list) + // apply materials properly from the default custom_materials value + set_custom_materials(custom_materials) ComponentInitialize() @@ -142,7 +144,11 @@ qdel(reagents) LAZYCLEARLIST(overlays) - LAZYCLEARLIST(priority_overlays) + + for(var/i in targeted_by) + var/mob/M = i + LAZYREMOVE(M.do_afters, src) + targeted_by = null QDEL_NULL(light) @@ -219,7 +225,7 @@ /atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) if(does_attack_animation) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) log_combat(user, src, "punched", "hulk powers") user.do_attack_animation(src, ATTACK_EFFECT_SMASH) @@ -368,6 +374,20 @@ SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) +/** + * Called when a mob examines (shift click or verb) this atom twice (or more) within EXAMINE_MORE_TIME (default 1.5 seconds) + * + * This is where you can put extra information on something that may be superfluous or not important in critical gameplay + * moments, while allowing people to manually double-examine to take a closer look + * + * Produces a signal [COMSIG_PARENT_EXAMINE_MORE] + */ +/atom/proc/examine_more(mob/user) + . = list() + SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE_MORE, user, .) + if(!LAZYLEN(.)) // lol ..length + return list("You examine [src] closer, but find nothing of interest...") + /// Updates the icon of the atom /atom/proc/update_icon() // I expect we're going to need more return flags and options in this proc @@ -438,7 +458,7 @@ var/blood_id = get_blood_id() if(!(blood_id in GLOB.blood_reagent_types)) return - return list("ANIMAL DNA" = "Y-") + return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-") /mob/living/carbon/get_blood_dna_list() var/blood_id = get_blood_id() @@ -446,13 +466,15 @@ return var/list/blood_dna = list() if(dna) + blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors blood_dna[dna.unique_enzymes] = dna.blood_type else + blood_dna["color"] = BLOOD_COLOR_HUMAN blood_dna["UNKNOWN DNA"] = "X*" return blood_dna /mob/living/carbon/alien/get_blood_dna_list() - return list("UNKNOWN DNA" = "X*") + return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*") //to add a mob's dna info into an object's blood_DNA list. /atom/proc/transfer_mob_blood_dna(mob/living/L) @@ -463,18 +485,33 @@ LAZYINITLIST(blood_DNA) //if our list of DNA doesn't exist yet, initialise it. var/old_length = blood_DNA.len blood_DNA |= new_blood_dna + var/changed = FALSE + if(!blood_DNA["color"]) + blood_DNA["color"] = new_blood_dna["color"] + changed = TRUE + else + var/old = blood_DNA["color"] + blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"]) + changed = old != blood_DNA["color"] if(blood_DNA.len == old_length) return FALSE - return TRUE + return changed //to add blood dna info to the object's blood_DNA list /atom/proc/transfer_blood_dna(list/blood_dna, list/datum/disease/diseases) LAZYINITLIST(blood_DNA) + var/old_length = blood_DNA.len blood_DNA |= blood_dna if(blood_DNA.len > old_length) - return TRUE + . = TRUE //some new blood DNA was added + if(!blood_dna["color"]) + return + if(!blood_DNA["color"]) + blood_DNA["color"] = blood_dna["color"] + else + blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"]) //to add blood from a mob onto something, and transfer their dna info /atom/proc/add_mob_blood(mob/living/M) @@ -543,28 +580,7 @@ return TRUE /atom/proc/blood_DNA_to_color() - var/list/colors = list()//first we make a list of all bloodtypes present - for(var/bloop in blood_DNA) - if(colors[blood_DNA[bloop]]) - colors[blood_DNA[bloop]]++ - else - colors[blood_DNA[bloop]] = 1 - - var/final_rgb = BLOOD_COLOR_HUMAN //a default so we don't have white blood graphics if something messed up - - if(colors.len) - var/sum = 0 //this is all shitcode, but it works; trust me - final_rgb = bloodtype_to_color(colors[1]) - sum = colors[colors[1]] - if(colors.len > 1) - var/i = 2 - while(i <= colors.len) - var/tmp = colors[colors[i]] - final_rgb = BlendRGB(final_rgb, bloodtype_to_color(colors[i]), tmp/(tmp+sum)) - sum += tmp - i++ - - return final_rgb + return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN /atom/proc/clean_blood() . = blood_DNA? TRUE : FALSE @@ -733,7 +749,7 @@ flags_1 |= ADMIN_SPAWNED_1 . = ..() switch(var_name) - if("color") + if(NAMEOF(src, color)) add_atom_colour(color, ADMIN_COLOUR_PRIORITY) /atom/vv_get_dropdown() @@ -922,6 +938,8 @@ log_game(log_text) if(LOG_GAME) log_game(log_text) + if(LOG_SHUTTLE) + log_shuttle(log_text) else stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).") log_game(log_text) @@ -942,15 +960,16 @@ if(source != target) target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE) -/* -Proc for attack log creation, because really why not -1 argument is the actor performing the action -2 argument is the target of the action -3 is a verb describing the action (e.g. punched, throwed, kicked, etc.) -4 is a tool with which the action was made (usually an item) -5 is any additional text, which will be appended to the rest of the log line -*/ - +/** + * Log a combat message in the attack log + * + * Arguments: + * * atom/user - argument is the actor performing the action + * * atom/target - argument is the target of the action + * * what_done - is a verb describing the action (e.g. punched, throwed, kicked, etc.) + * * atom/object - is a tool with which the action was made (usually an item) + * * addition - is any additional text, which will be appended to the rest of the log line + */ /proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null) var/ssource = key_name(user) var/starget = key_name(target) @@ -974,6 +993,39 @@ Proc for attack log creation, because really why not var/reverse_message = "has been [what_done] by [ssource][postfix]" target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE) +/** + * log_wound() is for when someone is *attacked* and suffers a wound. Note that this only captures wounds from damage, so smites/forced wounds aren't logged, as well as demotions like cuts scabbing over + * + * Note that this has no info on the attack that dealt the wound: information about where damage came from isn't passed to the bodypart's damaged proc. When in doubt, check the attack log for attacks at that same time + * TODO later: Add logging for healed wounds, though that will require some rewriting of healing code to prevent admin heals from spamming the logs. Not high priority + * + * Arguments: + * * victim- The guy who got wounded + * * suffered_wound- The wound, already applied, that we're logging. It has to already be attached so we can get the limb from it + * * dealt_damage- How much damage is associated with the attack that dealt with this wound. + * * dealt_wound_bonus- The wound_bonus, if one was specified, of the wounding attack + * * dealt_bare_wound_bonus- The bare_wound_bonus, if one was specified *and applied*, of the wounding attack. Not shown if armor was present + * * base_roll- Base wounding ability of an attack is a random number from 1 to (dealt_damage ** WOUND_DAMAGE_EXPONENT). This is the number that was rolled in there, before mods + */ +/proc/log_wound(atom/victim, datum/wound/suffered_wound, dealt_damage, dealt_wound_bonus, dealt_bare_wound_bonus, base_roll) + if(QDELETED(victim) || !suffered_wound) + return + var/message = "has suffered: [suffered_wound][suffered_wound.limb ? " to [suffered_wound.limb.name]" : null]"// maybe indicate if it's a promote/demote? + + if(dealt_damage) + message += " | Damage: [dealt_damage]" + // The base roll is useful since it can show how lucky someone got with the given attack. For example, dealing a cut + if(base_roll) + message += " (rolled [base_roll]/[dealt_damage ** WOUND_DAMAGE_EXPONENT])" + + if(dealt_wound_bonus) + message += " | WB: [dealt_wound_bonus]" + + if(dealt_bare_wound_bonus) + message += " | BWB: [dealt_bare_wound_bonus]" + + victim.log_message(message, LOG_ATTACK, color="blue") + // Filter stuff /atom/proc/add_filter(name,priority,list/params) LAZYINITLIST(filter_data) @@ -1006,26 +1058,21 @@ Proc for attack log creation, because really why not ///Sets the custom materials for an item. /atom/proc/set_custom_materials(var/list/materials, multiplier = 1) - - if(!materials) - materials = custom_materials - if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways for(var/i in custom_materials) var/datum/material/custom_material = SSmaterials.GetMaterialRef(i) custom_material.on_removed(src, material_flags) //Remove the current materials if(!length(materials)) + custom_materials = null return - custom_materials = list() //Reset the list + if(material_flags) + for(var/x in materials) + var/datum/material/custom_material = SSmaterials.GetMaterialRef(x) + custom_material.on_applied(src, materials[x] * multiplier * material_modifier, material_flags) - for(var/x in materials) - var/datum/material/custom_material = SSmaterials.GetMaterialRef(x) - - if(material_flags & MATERIAL_EFFECTS) - custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags) - custom_materials[custom_material] += materials[x] * multiplier + custom_materials = SSmaterials.FindOrCreateMaterialCombo(materials, multiplier) /** * Returns true if this atom has gravity for the passed in turf @@ -1072,3 +1119,11 @@ Proc for attack log creation, because really why not max_grav = max(G.setting,max_grav) return max_grav return SSmapping.level_trait(T.z, ZTRAIT_GRAVITY) + +/** + * Causes effects when the atom gets hit by a rust effect from heretics + * + * Override this if you want custom behaviour in whatever gets hit by the rust + */ +/atom/proc/rust_heretic_act() + return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 9736f473e8..0a6c2b9eca 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -120,25 +120,25 @@ if((var_name in careful_edits) && (var_value % world.icon_size) != 0) return FALSE switch(var_name) - if("x") + if(NAMEOF(src, x)) var/turf/T = locate(var_value, y, z) if(T) forceMove(T) return TRUE return FALSE - if("y") + if(NAMEOF(src, y)) var/turf/T = locate(x, var_value, z) if(T) forceMove(T) return TRUE return FALSE - if("z") + if(NAMEOF(src, z)) var/turf/T = locate(x, y, var_value) if(T) forceMove(T) return TRUE return FALSE - if("loc") + if(NAMEOF(src, loc)) if(istype(var_value, /atom)) forceMove(var_value) return TRUE @@ -646,3 +646,10 @@ animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING) sleep(1) animate(I, alpha = 0, transform = matrix(), time = 1) + +/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran + SHOULD_CALL_PARENT(TRUE) + if(anchored == anchorvalue) + return + . = anchored + anchored = anchorvalue diff --git a/code/game/atoms_movement.dm b/code/game/atoms_movement.dm index 68db17f076..db9424d983 100644 --- a/code/game/atoms_movement.dm +++ b/code/game/atoms_movement.dm @@ -6,6 +6,7 @@ // To be removed on step_ conversion // All this work to prevent a second bump /atom/movable/Move(atom/newloc, direct=0) + set waitfor = FALSE //n o . = FALSE if(!newloc || newloc == loc) return @@ -52,6 +53,7 @@ //////////////////////////////////////// /atom/movable/Move(atom/newloc, direct) + set waitfor = FALSE //n o var/atom/movable/pullee = pulling var/turf/T = loc if(!moving_from_pull) diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm index 7b798f19e4..be8dee5bf8 100644 --- a/code/game/gamemodes/clock_cult/clock_cult.dm +++ b/code/game/gamemodes/clock_cult/clock_cult.dm @@ -38,7 +38,8 @@ Credit where due: 5. Xhuis from /tg/ for coding the first iteration of the mode, and the new, reworked version 6. ChangelingRain from /tg/ for maintaining the gamemode for months after its release prior to its rework 7. Clockwork cult code as of now, at least the one being pulled from Citadel Station's master branch, is being, or already is, fixed by Coolgat3 and Avunia. - +8. Modern clockwork cult code mixed with original clockwork code, with various changes to make it less of a fustercluck, done by KeRSe. \ + Fixes and assistance done by TimothyTeakettle, Kevinz000, and Deltafire15. -Very glad for the help they gave. */ /////////// @@ -133,7 +134,7 @@ Credit where due: config_tag = "clockwork_cult" antag_flag = ROLE_SERVANT_OF_RATVAR false_report_weight = 10 - required_players = 35 + required_players = 24 //Fixing this directly for now since apparently config machine for forcing modes broke. required_enemies = 3 recommended_enemies = 5 enemy_minimum_age = 7 @@ -143,13 +144,12 @@ Credit where due: announce_text = "Servants of Ratvar are trying to summon the Justiciar!\n\ Servants: Construct defenses to protect the Ark. Sabotage the station!\n\ Crew: Stop the servants before they can summon the Clockwork Justiciar." - var/servants_to_serve = list() + var/list/servants_to_serve = list() //Yes this list is made out of list var/roundstart_player_count - var/ark_time //In minutes, how long the Ark waits before activation; this is equal to 30 + (number of players / 5) (max 40 mins.) var/datum/team/clockcult/main_clockcult -/datum/game_mode/clockwork_cult/pre_setup() +/datum/game_mode/clockwork_cult/pre_setup() //Gamemode and job code is pain. Have fun codediving all of that stuff, whoever works on this next - Delta var/list/errorList = list() var/list/reebes = SSmapping.LoadGroup(errorList, "Reebe", "map_files/generic", "City_of_Cogs.dmm", default_traits = ZTRAITS_REEBE, silent = TRUE) if(errorList.len) // reebe failed to load @@ -162,38 +162,36 @@ Credit where due: restricted_jobs += protected_jobs if(CONFIG_GET(flag/protect_assistant_from_antagonist)) restricted_jobs += "Assistant" - var/starter_servants = 4 //Guaranteed four servants + var/starter_servants = 4 //Try to go for at least four var/number_players = num_players() roundstart_player_count = number_players if(number_players > 30) //plus one servant for every additional 10 players above 30 number_players -= 30 starter_servants += round(number_players / 10) - starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players) - GLOB.clockwork_vitality += 50 * starter_servants //some starter Vitality to help recover from initial fuck ups + starter_servants = min(starter_servants, 8) //max 8 servants (that sould only happen with a ton of players) while(starter_servants) + if(!antag_candidates.len) + break //Skip setup, DO NOT RUNTIME var/datum/mind/servant = antag_pick(antag_candidates) servants_to_serve += servant antag_candidates -= servant - servant.assigned_role = ROLE_SERVANT_OF_RATVAR servant.special_role = ROLE_SERVANT_OF_RATVAR + servant.restricted_roles = restricted_jobs starter_servants-- - ark_time = 30 + round((roundstart_player_count / 5)) //In minutes, how long the Ark will wait before activation - ark_time = min(ark_time, 35) //35 minute maximum for the activation timer - return 1 + if(!servants_to_serve.len) //Uh oh, something went wrong + setup_error = "There are no clockcult candidates! (Or something went very wrong)" + return FALSE + GLOB.clockwork_vitality += 50 * servants_to_serve.len //some starter Vitality to help recover from initial fuck ups + return TRUE //Haha yes it works time to not touch it any more than that. /datum/game_mode/clockwork_cult/post_setup() for(var/S in servants_to_serve) var/datum/mind/servant = S log_game("[key_name(servant)] was made an initial servant of Ratvar") var/mob/living/L = servant.current - var/turf/T = pick(GLOB.servant_spawns) - L.forceMove(T) - GLOB.servant_spawns -= T greet_servant(L) equip_servant(L) add_servant_of_ratvar(L, TRUE) - var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar //that's a mouthful - G.final_countdown(ark_time) ..() return 1 @@ -201,22 +199,23 @@ Credit where due: if(!M) return 0 to_chat(M, "You are a servant of Ratvar, the Clockwork Justiciar!") - to_chat(M, "You have approximately [ark_time] minutes until the Ark activates.") - to_chat(M, "Unlock Script scripture by converting a new servant.") - to_chat(M, "Application scripture will be unlocked halfway until the Ark's activation.") + to_chat(M, "Unlock Script scripture by converting a new servant or when 35kw of power is reached.") + to_chat(M, "Application scripture will be unlocked when 50kw of power is reached.") M.playsound_local(get_turf(M), 'sound/ambience/antag/clockcultalr.ogg', 100, FALSE, pressure_affected = FALSE) return 1 -/datum/game_mode/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob, with one of each component +/datum/game_mode/proc/equip_servant(mob/living/M) //Grants a clockwork slab to the mob if(!M || !ishuman(M)) return FALSE var/mob/living/carbon/human/L = M - L.equipOutfit(/datum/outfit/servant_of_ratvar) var/obj/item/clockwork/slab/S = new var/slot = "At your feet" - var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK, "On your belt" = SLOT_BELT) + var/list/slots = list("In your left pocket" = SLOT_L_STORE, "In your right pocket" = SLOT_R_STORE, "In your backpack" = SLOT_IN_BACKPACK) if(ishuman(L)) var/mob/living/carbon/human/H = L + var/obj/item/clockwork/replica_fabricator/F = new + if(H.equip_to_slot_or_del(F, SLOT_IN_BACKPACK)) + to_chat(H, "You have been equipped with a replica fabricator, an advanced tool that can convert objects like doors, tables or even coats into clockwork equivalents.") slot = H.equip_in_one_of_slots(S, slots) if(slot == "In your backpack") slot = "In your [H.back.name]" @@ -224,10 +223,8 @@ Credit where due: if(!S.forceMove(get_turf(L))) qdel(S) if(S && !QDELETED(S)) - to_chat(L, "There is a paper in your backpack! It'll tell you if anything's changed, as well as what to expect.") to_chat(L, "[slot] is a clockwork slab, a multipurpose tool used to construct machines and invoke ancient words of power. If this is your first time \ - as a servant, you can find a concise tutorial in the Recollection category of its interface.") - to_chat(L, "If you want more information, you can read the wiki page to learn more.") + as a servant, you can read the wiki page to learn more.") return TRUE return FALSE @@ -278,7 +275,7 @@ Credit where due: gloves = /obj/item/clothing/gloves/color/yellow belt = /obj/item/storage/belt/utility/servant backpack_contents = list(/obj/item/storage/box/engineer = 1, \ - /obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1, /obj/item/reagent_containers/food/drinks/bottle/holyoil = 1) + /obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/reagent_containers/food/drinks/bottle/holyoil = 1) id = /obj/item/pda var/plasmaman //We use this to determine if we should activate internals in post_equip() @@ -305,53 +302,3 @@ Credit where due: PDA.update_label() PDA.id_check(H, W) H.sec_hud_set_ID() - - -//This paper serves as a quick run-down to the cult as well as a changelog to refer to. -//Check strings/clockwork_cult_changelog.txt for the changelog, and update it when you can! -/obj/item/paper/servant_primer - name = "The Ark And You: A Primer On Servitude" - color = "#DAAA18" - info = "DON'T PANIC.

\ - Here's a quick primer on what you should know here.\ -
    \ -
  1. You're in a place called Reebe right now. The crew can't get here normally.
  2. \ -
  3. In the north is your base camp, with supplies, consoles, and the Ark. In the south is an inaccessible area that the crew can walk between \ - once they arrive (more on that later.) Everything between that space is an open area.
  4. \ -
  5. Your job as a servant is to build fortifications and defenses to protect the Ark and your base once the Ark activates. You can do this \ - however you like, but work with your allies and coordinate your efforts.
  6. \ -
  7. Once the Ark activates, the station will be alerted. Portals to Reebe will open up in nearly every room. When they take these portals, \ - the crewmembers will arrive in the area that you can't access, but can get through it freely - whereas you can't. Treat this as the \"spawn\" of the \ - crew and defend it accordingly.
  8. \ -
\ -
\ - Here is the layout of Reebe, from left to right:\ -
    \ -
  • Dressing Room: Contains clothing, a dresser, and a mirror. There are spare slabs and absconders here.
  • \ -
  • Listening Station: Contains intercoms, a telecomms relay, and a list of frequencies.
  • \ -
  • Ark Chamber: Houses the Ark.
  • \ -
  • Observation Room: Contains five camera observers. These can be used to watch the station through its cameras, as well as to teleport down \ - to most areas. To do this, use the Warp action while hovering over the tile you want to warp to.
  • \ -
  • Infirmary: Contains sleepers and basic medical supplies for superficial wounds. The sleepers can consume Vitality to heal any occupants. \ - This room is generally more useful during the preparation phase; when defending the Ark, scripture is more useful.
  • \ -
\ -
\ -

Things that have changed:

\ -
    \ - CLOCKCULTCHANGELOG\ -
\ -
\ - Good luck!" - -/obj/item/paper/servant_primer/Initialize() - . = ..() - var/changelog = world.file2list("strings/clockwork_cult_changelog.txt") - var/changelog_contents = "" - for(var/entry in changelog) - changelog_contents += "
  • [entry]
  • " - info = replacetext(info, "CLOCKCULTCHANGELOG", changelog_contents) - -/obj/item/paper/servant_primer/oui_getcontent(mob/target) - if(!is_servant_of_ratvar(target) && !isobserver(target)) - return "[name][stars(info)]
    [stamps]" - return ..() diff --git a/code/game/gamemodes/clown_ops/bananium_bomb.dm b/code/game/gamemodes/clown_ops/bananium_bomb.dm index ce864007f0..695fc79169 100644 --- a/code/game/gamemodes/clown_ops/bananium_bomb.dm +++ b/code/game/gamemodes/clown_ops/bananium_bomb.dm @@ -51,4 +51,4 @@ H.dna.add_mutation(CLOWNMUT) H.dna.add_mutation(SMILE) - H.gain_trauma(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_LOBOTOMY, "clowns") //MWA HA HA + H.gain_trauma(/datum/brain_trauma/mild/phobia/clowns, TRAUMA_RESILIENCE_LOBOTOMY) //MWA HA HA diff --git a/code/game/gamemodes/clown_ops/clown_ops.dm b/code/game/gamemodes/clown_ops/clown_ops.dm index 11898701fa..108c67ad27 100644 --- a/code/game/gamemodes/clown_ops/clown_ops.dm +++ b/code/game/gamemodes/clown_ops/clown_ops.dm @@ -58,6 +58,7 @@ if(visualsOnly) return H.dna.add_mutation(SMILE) + H.faction |= "clown" /datum/outfit/syndicate/clownop/leader name = "Clown Operative Leader - Basic" diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index afa3dbfeaa..a27cb02ea8 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -62,7 +62,7 @@ hitsound = null attack_verb_on = list("slipped") clumsy_check = FALSE - sharpness = IS_BLUNT + sharpness = SHARP_NONE sword_color = "yellow" heat = 0 light_color = "#ffff00" diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index da33da5f43..63574c6475 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -191,6 +191,24 @@ SSticker.mode_result = "loss - rev heads killed" SSticker.news_report = REVS_LOSE +////////////////////////////////////////////// +// // +// HERETIC SMUGGLER // +// // +////////////////////////////////////////////// + +/datum/dynamic_ruleset/latejoin/heretic_smuggler + name = "Heretic Smuggler" + antag_datum = /datum/antagonist/heretic + antag_flag = ROLE_HERETIC + protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") + restricted_roles = list("AI","Cyborg") + required_candidates = 1 + weight = 4 + cost = 10 + requirements = list(40,30,20,10,10,10,10,10,10,10) + repeatable = TRUE + ////////////////////////////////////////////// // // // BLOODSUCKERS // diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index edaadeae1c..766ddcefc7 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -143,6 +143,46 @@ changeling.add_antag_datum(new_antag) return TRUE +////////////////////////////////////////////// +// // +// ELDRITCH CULT // +// // +////////////////////////////////////////////// + +/datum/dynamic_ruleset/roundstart/heretics + name = "Heretics" + antag_flag = ROLE_HERETIC + antag_datum = /datum/antagonist/heretic + protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain") + restricted_roles = list("AI", "Cyborg") + required_candidates = 1 + weight = 3 + cost = 20 + scaling_cost = 15 + requirements = list(50,45,45,40,35,20,20,15,10,10) + antag_cap = list(1,1,1,1,2,2,2,2,3,3) + + +/datum/dynamic_ruleset/roundstart/heretics/pre_execute() + . = ..() + var/num_ecult = antag_cap[indice_pop] * (scaled_times + 1) + + for (var/i = 1 to num_ecult) + var/mob/picked_candidate = pick_n_take(candidates) + assigned += picked_candidate.mind + picked_candidate.mind.restricted_roles = restricted_roles + picked_candidate.mind.special_role = ROLE_HERETIC + return TRUE + +/datum/dynamic_ruleset/roundstart/heretics/execute() + + for(var/c in assigned) + var/datum/mind/cultie = c + var/datum/antagonist/heretic/new_antag = new antag_datum() + cultie.add_antag_datum(new_antag) + + return TRUE + ////////////////////////////////////////////// // // // WIZARDS // diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index 561b38fde1..148de9568a 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -50,10 +50,6 @@ Property weights are: for(var/r in SSevents.running) var/datum/round_event/R = r threat += R.threat() - for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list) - var/turf/T = get_turf(H) - if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction)) - threat += H.threat() for(var/obj/item/phylactery/P in GLOB.poi_list) threat += 25 // can't be giving them too much of a break for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS]) @@ -91,6 +87,8 @@ Property weights are: mean += 2.5 if(CHAOS_MAX) mean += 5 + else + voters += 0.5 if(voters) GLOB.dynamic_curve_centre += (mean/voters) if(flags & USE_PREV_ROUND_WEIGHTS) @@ -128,7 +126,8 @@ Property weights are: for(var/property in property_weights) if(property in rule.property_weights) // just treat it as 0 if it's not in there property_weight += rule.property_weights[property] * property_weights[property] - drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult + if(property_weight > 0) + drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult return drafted_rules /datum/dynamic_storyteller/proc/midround_draft() @@ -140,25 +139,26 @@ Property weights are: if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) continue rule.trim_candidates() - var/threat_weight = 1 - if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway - var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) - /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to - pick this particular ruleset. - Let's use a toy example: there's 60 threat level and 10 threat spent. - We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets. - Ruleset 1 has 30 cost, ruleset 2 has 5 cost. - When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1 - is 2.26 times as likely to be picked, all other things considered. - Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight. - */ - threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) if (rule.ready()) var/property_weight = 0 for(var/property in property_weights) - if(property in rule.property_weights) + if(property in rule.property_weights) // just treat it as 0 if it's not in there property_weight += rule.property_weights[property] * property_weights[property] - drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1) + if(property_weight > 0) + var/threat_weight = 1 + if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway + var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) + /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to + pick this particular ruleset. + Let's use a toy example: there's 60 threat level and 10 threat spent. + We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets. + Ruleset 1 has 30 cost, ruleset 2 has 5 cost. + When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1 + is 2.26 times as likely to be picked, all other things considered. + Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight. + */ + threat_weight = abs(1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) + drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight return drafted_rules /datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer) @@ -175,28 +175,29 @@ Property weights are: rule.candidates = list(newPlayer) rule.trim_candidates() - var/threat_weight = 1 - if(!(rule.flags & MINOR_RULESET)) - var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) - threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) if (rule.ready()) var/property_weight = 0 for(var/property in property_weights) if(property in rule.property_weights) property_weight += rule.property_weights[property] * property_weights[property] - drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1) + if(property_weight > 0) + var/threat_weight = 1 + if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) + var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) + threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) + drafted_rules[rule] = rule.get_weight() * property_weight * rule.weight_mult * threat_weight return drafted_rules /datum/dynamic_storyteller/proc/event_draft() var/list/drafted_rules = list() for(var/datum/dynamic_ruleset/event/rule in mode.events) - if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost) - if(rule.ready()) - var/property_weight = 0 - for(var/property in property_weights) - if(property in rule.property_weights) - property_weight += rule.property_weights[property] * property_weights[property] - drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult + if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level + 20 - mode.threat) >= rule.cost && rule.ready()) + var/property_weight = 0 + for(var/property in property_weights) + if(property in rule.property_weights) + property_weight += rule.property_weights[property] * property_weights[property] + if(property_weight > 0) + drafted_rules[rule] = rule.get_weight() + property_weight * rule.weight_mult return drafted_rules @@ -313,9 +314,8 @@ Property weights are: /datum/dynamic_storyteller/random/event_draft() var/list/drafted_rules = list() for(var/datum/dynamic_ruleset/event/rule in mode.events) - if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level)) - if(rule.ready()) - drafted_rules[rule] = 1 + if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && rule.ready()) + drafted_rules[rule] = 1 return drafted_rules /datum/dynamic_storyteller/story @@ -330,7 +330,7 @@ Property weights are: /datum/dynamic_storyteller/story/calculate_threat() var/current_time = (world.time / SSautotransfer.targettime)*180 - mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1) + mode.threat_level = round((mode.initial_threat_level*(sin(current_time)/2)+0.75),0.1) return ..() /datum/dynamic_storyteller/classic diff --git a/code/game/gamemodes/eldritch_cult/eldritch_cult.dm b/code/game/gamemodes/eldritch_cult/eldritch_cult.dm new file mode 100644 index 0000000000..20a129a5a3 --- /dev/null +++ b/code/game/gamemodes/eldritch_cult/eldritch_cult.dm @@ -0,0 +1,67 @@ +/datum/game_mode/heretics + name = "heresy" + config_tag = "heresy" + antag_flag = ROLE_HERETIC + false_report_weight = 5 + restricted_jobs = list("AI", "Cyborg") + protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster") //citadel change - adds HoP, CE, CMO, and RD to heretic role blacklist + required_players = 15 + required_enemies = 1 + recommended_enemies = 4 + reroll_friendly = 1 + enemy_minimum_age = 0 + round_ends_with_antag_death = 0 + + announce_span = "danger" + announce_text = "Heretics have been spotted on the station!\n\ + Heretics: Accomplish your objectives.\n\ + Crew: Do not let the madman succeed!" + + var/ecult_possible = 4 //hard limit on culties if scaling is turned off + var/num_ecult = 1 + var/list/culties = list() + +/datum/game_mode/heretics/pre_setup() + + if(CONFIG_GET(flag/protect_roles_from_antagonist)) + restricted_jobs += protected_jobs + + if(CONFIG_GET(flag/protect_assistant_from_antagonist)) + restricted_jobs += "Assistant" + + + var/esc = CONFIG_GET(number/ecult_scaling_coeff) + if(esc) + num_ecult = min(max(1, min(round(num_players() / (esc * 2)) + 2, round(num_players() / esc))),4) + else + num_ecult = max(1, min(num_players(), ecult_possible)) + + for(var/i in 1 to num_ecult) + if(!antag_candidates.len) + break + var/datum/mind/cultie = antag_pick(antag_candidates) + antag_candidates -= cultie + cultie.special_role = ROLE_HERETIC + cultie.restricted_roles = restricted_jobs + culties += cultie + + var/enough_heretics = culties.len > 0 + + if(!enough_heretics) + setup_error = "Not enough heretic candidates" + return FALSE + else + for(var/antag in culties) + return TRUE + +/datum/game_mode/heretics/post_setup() + for(var/c in culties) + var/datum/mind/cultie = c + log_game("[key_name(cultie)] has been selected as a heretic!") + var/datum/antagonist/heretic/new_antag = new() + cultie.add_antag_datum(new_antag) + return ..() + +/datum/game_mode/heretics/generate_report() + return "Cybersun Industries has announced that they have successfully raided a high-security library. The library contained a very dangerous book that was \ + shown to posses anomalous properties. We suspect that the book has been copied over, Stay vigilant!" diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index a7ccada9f2..3d7eeb7a8a 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -543,6 +543,8 @@ /datum/game_mode/proc/get_remaining_days(client/C) if(!C) return 0 + if(C.prefs?.db_flags & DB_FLAG_EXEMPT) + return 0 if(!CONFIG_GET(flag/use_age_restriction_for_jobs)) return 0 if(!isnum(C.player_age)) diff --git a/code/game/gamemodes/gangs/dominator.dm b/code/game/gamemodes/gangs/dominator.dm index db145ffacc..a7e44ef325 100644 --- a/code/game/gamemodes/gangs/dominator.dm +++ b/code/game/gamemodes/gangs/dominator.dm @@ -149,7 +149,7 @@ add_fingerprint(user) return ..() -/obj/machinery/dominator/attack_hand(mob/user) +/obj/machinery/dominator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(operating || (stat & BROKEN)) examine(user) return diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 3b95b1281f..10b92d9655 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -201,10 +201,13 @@ GLOBAL_LIST_EMPTY(objectives) return won || ..() /datum/objective/assassinate/once/process() - won = check_completion() + won = check_midround_completion() if(won) STOP_PROCESSING(SSprocessing,src) +/datum/objective/assassinate/once/proc/check_midround_completion() + return won || !considered_alive(target) //The target afking / logging off for a bit during the round doesn't complete it, but them being afk at roundend does. + /datum/objective/assassinate/internal var/stolen = 0 //Have we already eliminated this target? @@ -842,6 +845,37 @@ GLOBAL_LIST_EMPTY(possible_items_special) /datum/objective/destroy/internal var/stolen = FALSE //Have we already eliminated this target? +/datum/objective/steal_five_of_type + name = "steal five of" + explanation_text = "Steal at least five items!" + var/list/wanted_items = list(/obj/item) + +/datum/objective/steal_five_of_type/New() + ..() + wanted_items = typecacheof(wanted_items) + +/datum/objective/steal_five_of_type/summon_guns + name = "steal guns" + explanation_text = "Steal at least five guns!" + wanted_items = list(/obj/item/gun) + +/datum/objective/steal_five_of_type/summon_magic + name = "steal magic" + explanation_text = "Steal at least five magical artefacts!" + wanted_items = list(/obj/item/spellbook, /obj/item/gun/magic, /obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/scrying, /obj/item/antag_spawner/contract, /obj/item/necromantic_stone) + +/datum/objective/steal_five_of_type/check_completion() + var/list/datum/mind/owners = get_owners() + var/stolen_count = 0 + for(var/datum/mind/M in owners) + if(!isliving(M.current)) + continue + var/list/all_items = M.current.GetAllContents() //this should get things in cheesewheels, books, etc. + for(var/obj/I in all_items) //Check for wanted items + if(is_type_in_typecache(I, wanted_items)) + stolen_count++ + return stolen_count >= 5 + //Created by admin tools /datum/objective/custom name = "custom" diff --git a/code/game/gamemodes/objective_items.dm b/code/game/gamemodes/objective_items.dm index 131e61c674..7b7fdbeaf9 100644 --- a/code/game/gamemodes/objective_items.dm +++ b/code/game/gamemodes/objective_items.dm @@ -36,7 +36,7 @@ targetitem = /obj/item/gun/energy/e_gun/hos difficulty = 10 excludefromjob = list("Head Of Security") - altitems = list(/obj/item/gun/ballistic/revolver/mws, /obj/item/choice_beacon/hosgun) //We now look for eather the alt verson of the hos gun or the beacon picker. + altitems = list(/obj/item/gun/ballistic/revolver/mws, /obj/item/choice_beacon/hosgun) //We now look for either the alt verson of the hos gun or the beacon picker. /datum/objective_item/steal/handtele name = "a hand teleporter." @@ -94,6 +94,11 @@ targetitem = /obj/item/documents //Any set of secret documents. Doesn't have to be NT's difficulty = 5 +/datum/objective_item/steal/blackbox + name = "the black box from the onboard blackbox recording device. Take care to wear the proper safety equipment when extracting the black box as the telecommunications array is likely to be under inhospitable conditions." + targetitem = /obj/item/blackbox //steal the forbidden ssblackbox + difficulty = 10 + /datum/objective_item/steal/nuke_core name = "the heavily radioactive plutonium core from the onboard self-destruct. Take care to wear the proper safety equipment when extracting the core!" targetitem = /obj/item/nuke_core @@ -125,7 +130,7 @@ /datum/objective_item/steal/plasma/check_special_completion(obj/item/tank/T) var/target_amount = text2num(name) var/found_amount = 0 - found_amount += T.air_contents.gases[/datum/gas/plasma] + found_amount += T.air_contents.get_moles(/datum/gas/plasma) return found_amount>=target_amount diff --git a/code/game/gamemodes/sandbox/airlock_maker.dm b/code/game/gamemodes/sandbox/airlock_maker.dm index ddb622ab08..3d8eb7f7fc 100644 --- a/code/game/gamemodes/sandbox/airlock_maker.dm +++ b/code/game/gamemodes/sandbox/airlock_maker.dm @@ -7,7 +7,7 @@ /obj/structure/door_assembly var/datum/airlock_maker/maker = null -/obj/structure/door_assembly/attack_hand() +/obj/structure/door_assembly/on_attack_hand() . = ..() if(.) return diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm index 2f3645a248..23f065318e 100644 --- a/code/game/gamemodes/wizard/wizard.dm +++ b/code/game/gamemodes/wizard/wizard.dm @@ -44,7 +44,7 @@ /datum/game_mode/wizard/are_special_antags_dead() - for(var/datum/mind/wizard in wizards) + for(var/datum/mind/wizard in wizards | apprentices) if(isliving(wizard.current) && wizard.current.stat!=DEAD) return FALSE @@ -58,6 +58,14 @@ return TRUE +/datum/game_mode/wizard/check_finished() + . = ..() + if(.) + finished = TRUE + else if(gamemode_ready && are_special_antags_dead() && !CONFIG_GET(keyed_list/continuous)[config_tag]) + finished = TRUE + . = TRUE + /datum/game_mode/wizard/set_round_result() ..() if(finished) diff --git a/code/game/machinery/PDApainter.dm b/code/game/machinery/PDApainter.dm index 88dc0ebb56..6bac63dff0 100644 --- a/code/game/machinery/PDApainter.dm +++ b/code/game/machinery/PDApainter.dm @@ -107,10 +107,7 @@ stat |= BROKEN update_icon() -/obj/machinery/pdapainter/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/pdapainter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!storedpda) to_chat(user, "[src] is empty.") diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 5402c8f41e..047e6c955f 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -12,9 +12,9 @@ density = FALSE state_open = TRUE circuit = /obj/item/circuitboard/machine/sleeper - req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines + var/efficiency = 1 - var/min_health = 30 + var/min_health = -25 var/list/available_chems var/controls_inside = FALSE var/list/possible_chems = list( @@ -31,32 +31,13 @@ /obj/machinery/sleeper/Initialize() . = ..() - create_reagents(500, NO_REACT) + // if(mapload) + // component_parts -= circuit + // QDEL_NULL(circuit) occupant_typecache = GLOB.typecache_living update_icon() 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) - buffer.volume = reagents.maximum_volume - buffer.reagents.maximum_volume = reagents.maximum_volume - reagents.trans_to(buffer.reagents, reagents.total_volume) - -/obj/machinery/sleeper/proc/add_inital_chems() - for(var/i in available_chems) - var/datum/reagent/R = reagents.has_reagent(i) - if(!R) - reagents.add_reagent(i, (20)) - continue - if(R.volume < 20) - reagents.add_reagent(i, (20 - R.volume)) /obj/machinery/sleeper/RefreshParts() var/E @@ -73,15 +54,11 @@ available_chems |= possible_chems[i] reset_chem_buttons() - //Total container size 500 - 2000u - if(reagents) - reagents.maximum_volume = (500*E) - - /obj/machinery/sleeper/update_icon_state() - icon_state = initial(icon_state) if(state_open) - icon_state += "-open" + icon_state = "[initial(icon_state)]-open" + else + icon_state = initial(icon_state) /obj/machinery/sleeper/container_resist(mob/living/user) visible_message("[occupant] emerges from [src]!", @@ -98,10 +75,12 @@ /obj/machinery/sleeper/open_machine() if(!state_open && !panel_open) + // flick("[initial(icon_state)]-anim", src) ..() /obj/machinery/sleeper/close_machine(mob/user) if((isnull(user) || istype(user)) && state_open && !panel_open) + // flick("[initial(icon_state)]-anim", src) ..(user) var/mob/living/mob_occupant = occupant if(mob_occupant && mob_occupant.stat != DEAD) @@ -112,46 +91,23 @@ if (. & EMP_PROTECT_SELF) return if(is_operational() && occupant) - var/datum/reagent/R = pick(reagents.reagent_list) + var/datum/reagent/R = pick(reagents.reagent_list) //cit specific inject_chem(R.type, occupant) open_machine() - //Is this too much? + //Is this too much? Cit specific if(severity == EMP_HEAVY) var/chem = pick(available_chems) available_chems -= chem available_chems += get_random_reagent_id() reset_chem_buttons() -/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/reagent_containers/sleeper_buffer)) - var/obj/item/reagent_containers/sleeper_buffer/SB = I - if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume) - SB.reagents.trans_to(reagents, SB.reagents.total_volume) - visible_message("[user] places the [SB] into the [src].") - qdel(SB) - return - else - SB.reagents.trans_to(reagents, SB.reagents.total_volume) - visible_message("[user] adds as much as they can to the [src] from the [SB].") - return - if(istype(I, /obj/item/reagent_containers)) - var/obj/item/reagent_containers/RC = I - if(RC.reagents.total_volume == 0) - to_chat(user, "The [I] is empty!") - for(var/datum/reagent/R in RC.reagents.reagent_list) - if((obj_flags & EMAGGED) || (allowed(usr))) - break - if(!istype(R, /datum/reagent/medicine)) - visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"") - return - RC.reagents.trans_to(reagents, 1000) - visible_message("[user] adds as much as they can to the [src] from the [I].") - return - - /obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) + if(user.stat || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) return + if(isliving(user)) + var/mob/living/L = user + if(!(L.mobility_flags & MOBILITY_STAND)) + return close_machine(target) /obj/machinery/sleeper/screwdriver_act(mob/living/user, obj/item/I) @@ -187,31 +143,29 @@ visible_message("[usr] pries open [src].", "You pry open [src].") open_machine() +/obj/machinery/sleeper/ui_state(mob/user) + if(controls_inside) + return GLOB.contained_state + return GLOB.default_state + +/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Sleeper", name) + ui.open() + /obj/machinery/sleeper/AltClick(mob/user) - . = ..() - if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) + if(!user.canUseTopic(src, !issilicon(user))) return if(state_open) close_machine() else open_machine() - return TRUE /obj/machinery/sleeper/examine(mob/user) . = ..() . += "Alt-click [src] to [state_open ? "close" : "open"] it." -/obj/machinery/sleeper/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) - - if(controls_inside && state == GLOB.notcontained_state) - state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it. - - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state) - ui.open() - /obj/machinery/sleeper/process() ..() check_nap_violations() @@ -221,22 +175,13 @@ /obj/machinery/sleeper/ui_data() var/list/data = list() - var/chemical_list = list() - var/blood_percent = 0 - data["occupied"] = occupant ? 1 : 0 data["open"] = state_open - data["blood_levels"] = blood_percent - data["blood_status"] = "Patient either has no blood, or does not require it to function." - data["chemical_list"] = chemical_list data["chems"] = list() for(var/chem in available_chems) - var/datum/reagent/R = reagents.has_reagent(chem) - R = GLOB.chemical_reagents_list[chem] - data["synthchems"] += list(list("name" = R.name, "id" = R.type, "synth_allowed" = synth_allowed(chem))) - for(var/datum/reagent/R in reagents.reagent_list) - data["chems"] += list(list("name" = R.name, "id" = R.type, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.type))) + var/datum/reagent/R = GLOB.chemical_reagents_list[chem] + data["chems"] += list(list("name" = R.name, "id" = R.type, "allowed" = chem_allowed(chem))) data["occupant"] = list() var/mob/living/mob_occupant = occupant @@ -264,40 +209,10 @@ 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) + data["occupant"]["reagents"] = list() + if(mob_occupant.reagents && 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)) - else - chemical_list = "Patient has no reagents." - - data["occupant"]["failing_organs"] = list() - var/mob/living/carbon/C = mob_occupant - if(C) - for(var/obj/item/organ/Or in C.getFailingOrgans()) - if(istype(Or, /obj/item/organ/brain)) - continue - data["occupant"]["failing_organs"] += list(list("name" = Or.name)) - - if(istype(C)) //Non-carbons shouldn't be able to enter sleepers, but this is to prevent runtimes if something ever breaks - if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner. - blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100) - var/blood_id = C.get_blood_id() - var/blood_warning = "" - if(blood_percent < 80) - blood_warning = "Patient has low blood levels." - if(blood_percent < 60) - blood_warning = "Patient has DANGEROUSLY low blood levels." - if(blood_id) - var/blood_type = C.dna.blood_type - if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance - var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id] - if(R) - blood_type = R.name - else - blood_type = blood_id - data["blood_status"] = "Patient has [blood_type] type blood. [blood_warning]" - data["blood_levels"] = blood_percent + data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume)) return data /obj/machinery/sleeper/ui_act(action, params) @@ -314,37 +229,14 @@ . = TRUE if("inject") var/chem = text2path(params["chem"]) - var/amount = text2num(params["volume"]) if(!is_operational() || !mob_occupant || isnull(chem)) return if(mob_occupant.health < min_health && chem != /datum/reagent/medicine/epinephrine) return - if(inject_chem(chem, usr, amount)) + if(inject_chem(chem, usr)) . = TRUE if(scrambled_chems && prob(5)) to_chat(usr, "Chemical system re-route detected, results may not be as expected!") - if("synth") - var/chem = text2path(params["chem"]) - if(!is_operational()) - return - reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in - if("purge") - var/chem = text2path(params["chem"]) - if(allowed(usr)) - if(!is_operational()) - return - reagents.remove_reagent(chem, 1000) - return - if(chem in available_chems) - if(!is_operational()) - return - /*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in - if(R.purity < 0.8)*/ - reagents.remove_reagent(chem, 1000) - else - visible_message("Access Denied.") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - /obj/machinery/sleeper/emag_act(mob/user) . = ..() @@ -353,10 +245,9 @@ to_chat(user, "You scramble the sleeper's user interface!") return TRUE -//trans to -/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10) - if(chem_allowed(chem)) - reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU +/obj/machinery/sleeper/proc/inject_chem(chem, mob/user) + if((chem in available_chems) && chem_allowed(chem)) + occupant.reagents.add_reagent(chem_buttons[chem], 10) //emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU if(user) log_combat(user, occupant, "injected [chem] into", addition = "via [src]") return TRUE @@ -369,14 +260,6 @@ var/occ_health = mob_occupant.health > min_health || chem == /datum/reagent/medicine/epinephrine return amount && occ_health -/obj/machinery/sleeper/proc/synth_allowed(chem) - var/datum/reagent/R = reagents.has_reagent(chem) - if(!R) - return TRUE - if(R.volume < 50) - return TRUE - return FALSE - /obj/machinery/sleeper/proc/reset_chem_buttons() scrambled_chems = FALSE LAZYINITLIST(chem_buttons) @@ -416,22 +299,6 @@ component_parts += new /obj/item/stack/cable_coil(null) RefreshParts() -/obj/machinery/sleeper/clockwork - name = "soothing sleeper" - desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch." - icon_state = "sleeper_clockwork" - enter_message = "You hear the gentle hum and click of machinery, and are lulled into a sense of peace." - possible_chems = list(list("epinephrine", "salbutamol", "bicaridine", "kelotane", "oculine", "inacusiate", "mannitol")) - -/obj/machinery/sleeper/clockwork/process() - if(occupant && isliving(occupant)) - var/mob/living/L = occupant - if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing - GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1) - L.adjustBruteLoss(-1) - L.adjustFireLoss(-1) - L.adjustOxyLoss(-5) - /obj/machinery/sleeper/old icon_state = "oldpod" @@ -442,8 +309,6 @@ 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( @@ -476,3 +341,23 @@ /obj/machinery/sleeper/party/emag_act(mob/user) ..() leddit = TRUE + +/obj/machinery/sleeper/clockwork + name = "soothing sleeper" + desc = "A large cryogenics unit built from brass. Its surface is pleasantly cool the touch." + icon_state = "sleeper_clockwork" + enter_message = "You hear the gentle hum and click of machinery, and are lulled into a sense of peace." + possible_chems = list( + list(/datum/reagent/medicine/epinephrine, /datum/reagent/medicine/salbutamol, /datum/reagent/medicine/bicaridine, /datum/reagent/medicine/kelotane, /datum/reagent/medicine/oculine, /datum/reagent/medicine/inacusiate, /datum/reagent/medicine/mannitol) + ) //everything is available at start + fair_market_price = 0 //it's free + +/obj/machinery/sleeper/clockwork/process() + ..() + if(occupant && isliving(occupant)) + var/mob/living/L = occupant + if(GLOB.clockwork_vitality) //If there's Vitality, the sleeper has passive healing + GLOB.clockwork_vitality = max(0, GLOB.clockwork_vitality - 1) + L.adjustBruteLoss(-1) + L.adjustFireLoss(-1) + L.adjustOxyLoss(-5) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 096b40ddb7..2b7411d03f 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -92,6 +92,7 @@ Class Procs: pressure_resistance = 15 max_integrity = 200 layer = BELOW_OBJ_LAYER //keeps shit coming out of the machine from ending up underneath it. + flags_1 = DEFAULT_RICOCHET_1 flags_ricochet = RICOCHET_HARD ricochet_chance_mod = 0.3 @@ -116,12 +117,13 @@ Class Procs: 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 + var/wire_compatible = FALSE // For storing and overriding ui id and dimensions var/tgui_id // ID of TGUI interface var/ui_style // ID of custom TGUI style (optional) var/ui_x var/ui_y - + var/init_process = TRUE //Stop processing from starting on init 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 @@ -138,7 +140,7 @@ Class Procs: circuit = new circuit circuit.apply_default_parts(src) - if(!speed_process) + if(!speed_process && init_process) START_PROCESSING(SSmachines, src) else START_PROCESSING(SSfastprocess, src) @@ -313,7 +315,7 @@ Class Procs: if(user.a_intent != INTENT_HARM) return attack_hand(user) else - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) user.visible_message("[user.name] smashes against \the [src.name] with its paws.", null, null, COMBAT_MESSAGE_RANGE) take_damage(4, BRUTE, "melee", 1) @@ -432,6 +434,7 @@ Class Procs: to_chat(user, "You [anchored ? "un" : ""]secure [src].") setAnchored(!anchored) playsound(src, 'sound/items/deconstruct.ogg', 50, 1) + SEND_SIGNAL(src, COMSIG_OBJ_DEFAULT_UNFASTEN_WRENCH, anchored) return SUCCESSFUL_UNFASTEN return FAILED_UNFASTEN return CANT_UNFASTEN @@ -546,3 +549,6 @@ Class Procs: . = . % 9 AM.pixel_x = -8 + ((.%3)*8) AM.pixel_y = -8 + (round( . / 3)*8) + +/obj/machinery/rust_heretic_act() + take_damage(500, BRUTE, "melee", 1) diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm index 557adf488b..4b5e4088d7 100644 --- a/code/game/machinery/airlock_control.dm +++ b/code/game/machinery/airlock_control.dm @@ -122,10 +122,7 @@ else icon_state = "airlock_sensor_off" -/obj/machinery/airlock_sensor/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/airlock_sensor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/datum/signal/signal = new(list( "tag" = master_tag, "command" = "cycle" @@ -161,4 +158,4 @@ /obj/machinery/airlock_sensor/Destroy() SSradio.remove_object(src,frequency) - return ..() \ No newline at end of file + return ..() diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm index 7eef48ebdd..b004746051 100644 --- a/code/game/machinery/announcement_system.dm +++ b/code/game/machinery/announcement_system.dm @@ -39,7 +39,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) icon_state = (panel_open ? "AAS_Off_Open" : "AAS_Off") /obj/machinery/announcement_system/update_overlays() - . =..() + . = ..() if(arrivalToggle) . += greenlight @@ -54,19 +54,15 @@ GLOBAL_LIST_EMPTY(announcement_systems) GLOB.announcement_systems -= src //"OH GOD WHY ARE THERE 100,000 LISTED ANNOUNCEMENT SYSTEMS?!!" return ..() -/obj/machinery/announcement_system/power_change() - ..() - update_icon() - /obj/machinery/announcement_system/attackby(obj/item/P, mob/user, params) - if(istype(P, /obj/item/screwdriver)) + if(P.tool_behaviour == TOOL_SCREWDRIVER) P.play_tool_sound(src) panel_open = !panel_open to_chat(user, "You [panel_open ? "open" : "close"] the maintenance hatch of [src].") update_icon() else if(default_deconstruction_crowbar(P)) return - else if(istype(P, /obj/item/multitool) && panel_open && (stat & BROKEN)) + else if(P.tool_behaviour == TOOL_MULTITOOL && panel_open && (stat & BROKEN)) to_chat(user, "You reset [src]'s firmware.") stat &= ~BROKEN update_icon() @@ -88,10 +84,6 @@ GLOBAL_LIST_EMPTY(announcement_systems) message = CompileText(arrival, user, rank) else if(message_type == "NEWHEAD" && newheadToggle) message = CompileText(newhead, user, rank) - //CITADEL EDIT for cryopods - else if(message_type == "CRYOSTORAGE") - message = CompileText("%PERSON, %RANK has been moved to cryo storage.", user, rank) - //END EDIT else if(message_type == "ARRIVALS_BROKEN") message = "The arrivals shuttle has been damaged. Docking for repairs..." @@ -101,63 +93,58 @@ GLOBAL_LIST_EMPTY(announcement_systems) for(var/channel in channels) radio.talk_into(src, message, channel) -//config stuff +/obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AutomatedAnnouncement") + ui.open() -/obj/machinery/announcement_system/ui_interact(mob/user) +/obj/machinery/announcement_system/ui_data() + var/list/data = list() + data["arrival"] = arrival + data["arrivalToggle"] = arrivalToggle + data["newhead"] = newhead + data["newheadToggle"] = newheadToggle + return data + +/obj/machinery/announcement_system/ui_act(action, param) . = ..() - if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) + if(.) + return + if(!usr.canUseTopic(src, !issilicon(usr))) return if(stat & BROKEN) - visible_message("[src] buzzes.", "You hear a faint buzz.") - playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1) + visible_message("[src] buzzes.", "You hear a faint buzz.") + playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, TRUE) return - - - var/contents = "Arrival Announcement: ([(arrivalToggle ? "On" : "Off")])
    \n[arrival]

    \n" - contents += "Departmental Head Announcement: ([(newheadToggle ? "On" : "Off")])
    \n[newhead]

    \n" - - var/datum/browser/popup = new(user, "announcement_config", "Automated Announcement Configuration", 370, 220) - popup.set_content(contents) - popup.open() - -/obj/machinery/announcement_system/Topic(href, href_list) - if(..()) - return - if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) - return - if(stat & BROKEN) - visible_message("[src] buzzes.", "You hear a faint buzz.") - playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 1) - return - - if(href_list["ArrivalTopic"]) - var/NewMessage = stripped_input(usr, "Enter in the arrivals announcement configuration.", "Arrivals Announcement Config", arrival) - if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) - return - if(NewMessage) - arrival = NewMessage - else if(href_list["NewheadTopic"]) - var/NewMessage = stripped_input(usr, "Enter in the departmental head announcement configuration.", "Head Departmental Announcement Config", newhead) - if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr))) - return - if(NewMessage) - newhead = NewMessage - - else if(href_list["NewheadT-Topic"]) - newheadToggle = !newheadToggle - update_icon() - else if(href_list["ArrivalT-Topic"]) - arrivalToggle = !arrivalToggle - update_icon() - + switch(action) + if("ArrivalText") + var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) + if(!usr.canUseTopic(src, !issilicon(usr))) + return + if(NewMessage) + arrival = NewMessage + log_game("The arrivals announcement was updated: [NewMessage] by:[key_name(usr)]") + if("NewheadText") + var/NewMessage = trim(html_encode(param["newText"]), MAX_MESSAGE_LEN) + if(!usr.canUseTopic(src, !issilicon(usr))) + return + if(NewMessage) + newhead = NewMessage + log_game("The head announcement was updated: [NewMessage] by:[key_name(usr)]") + if("NewheadToggle") + newheadToggle = !newheadToggle + update_icon() + if("ArrivalToggle") + arrivalToggle = !arrivalToggle + update_icon() add_fingerprint(usr) - interact(usr) /obj/machinery/announcement_system/attack_robot(mob/living/silicon/user) . = attack_ai(user) /obj/machinery/announcement_system/attack_ai(mob/user) - if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) + if(!user.canUseTopic(src, !issilicon(user))) return if(stat & BROKEN) to_chat(user, "[src]'s firmware appears to be malfunctioning!") @@ -165,8 +152,8 @@ GLOBAL_LIST_EMPTY(announcement_systems) interact(user) /obj/machinery/announcement_system/proc/act_up() //does funny breakage stuff - stat |= BROKEN - update_icon() + if(!obj_break()) // if badmins flag this unbreakable or its already broken + return arrival = pick("#!@%ERR-34%2 CANNOT LOCAT@# JO# F*LE!", "CRITICAL ERROR 99.", "ERR)#: DA#AB@#E NOT F(*ND!") newhead = pick("OV#RL()D: \[UNKNOWN??\] DET*#CT)D!", "ER)#R - B*@ TEXT F*O(ND!", "AAS.exe is not responding. NanoOS is searching for a solution to the problem.") @@ -177,9 +164,7 @@ GLOBAL_LIST_EMPTY(announcement_systems) act_up() /obj/machinery/announcement_system/emag_act() - . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED act_up() - return TRUE diff --git a/code/game/machinery/aug_manipulator.dm b/code/game/machinery/aug_manipulator.dm index b95e3149ea..28733a6b6c 100644 --- a/code/game/machinery/aug_manipulator.dm +++ b/code/game/machinery/aug_manipulator.dm @@ -100,10 +100,7 @@ stat |= BROKEN update_icon() -/obj/machinery/aug_manipulator/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/aug_manipulator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) if(storedpart) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 4eeb6b8b0f..1f0687151d 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -46,29 +46,16 @@ "Dinnerware", "Imported" ) - var/list/allowed_materials = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/gold, - /datum/material/silver, - /datum/material/diamond, - /datum/material/uranium, - /datum/material/plasma, - /datum/material/bluespace, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/runite, - /datum/material/plastic, - /datum/material/adamantine, - /datum/material/mythril, - /datum/material/wood - ) + var/list/allowed_materials /// Base print speed var/base_print_speed = 10 /obj/machinery/autolathe/Initialize() - AddComponent(/datum/component/material_container, allowed_materials, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert)) + var/list/mats = allowed_materials + if(!mats) + mats = SSmaterials.materialtypes_by_category[MAT_CATEGORY_RIGID] + AddComponent(/datum/component/material_container, mats, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert)) . = ..() wires = new /datum/wires/autolathe(src) stored_research = new stored_research diff --git a/code/game/machinery/bank_machine.dm b/code/game/machinery/bank_machine.dm index 2b683f16a3..882d0b989c 100644 --- a/code/game/machinery/bank_machine.dm +++ b/code/game/machinery/bank_machine.dm @@ -3,6 +3,7 @@ desc = "A machine used to deposit and withdraw station funds." icon = 'goon/icons/obj/goon_terminals.dmi' idle_power_usage = 100 + var/siphoning = FALSE var/next_warning = 0 var/obj/item/radio/radio @@ -38,7 +39,6 @@ return return ..() - /obj/machinery/computer/bank_machine/process() ..() if(siphoning) @@ -51,7 +51,7 @@ end_syphon() return - playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1) + playsound(src, 'sound/items/poster_being_created.ogg', 100, TRUE) syphoning_credits += 200 D.adjust_money(-200) if(next_warning < world.time && prob(15)) @@ -60,17 +60,20 @@ radio.talk_into(src, message, radio_channel) next_warning = world.time + minimum_time_between_warnings -/obj/machinery/computer/bank_machine/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/bank_machine/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "bank_machine", name, 320, 165, master_ui, state) + ui = new(user, src, "BankMachine", name) ui.open() /obj/machinery/computer/bank_machine/ui_data(mob/user) var/list/data = list() var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) - data["current_balance"] = D.account_balance + + if(D) + data["current_balance"] = D.account_balance + else + data["current_balance"] = 0 data["siphoning"] = siphoning data["station_name"] = station_name() diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm index 71de04ee99..b5031b68a1 100644 --- a/code/game/machinery/buttons.dm +++ b/code/game/machinery/buttons.dm @@ -43,7 +43,11 @@ board.one_access = 1 board.accesses = req_one_access -/obj/machinery/button/update_icon_state() + setup_device() + + +/obj/machinery/button/update_icon() + cut_overlays() if(panel_open) icon_state = "button-open" else if(stat & (NOPOWER|BROKEN)) @@ -129,7 +133,12 @@ A.id = id initialized_button = 1 -/obj/machinery/button/attack_hand(mob/user) +/obj/machinery/button/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + if(id && istype(device, /obj/item/assembly/control)) + var/obj/item/assembly/control/A = device + A.id = "[idnum][id]" + +/obj/machinery/button/on_attack_hand(mob/user) . = ..() if(.) return diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index e386674b9e..2795ba45a9 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -72,6 +72,11 @@ if(mapload && is_station_level(z) && prob(3) && !start_active) toggle_cam() +/obj/machinery/camera/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + for(var/i in network) + network -= i + network += "[idnum][i]" + /obj/machinery/camera/Destroy() if(can_use()) toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks @@ -230,7 +235,7 @@ itemname = P.name info = P.notehtml to_chat(U, "You hold \the [itemname] up to the camera...") - U.changeNext_move(CLICK_CD_MELEE) + U.DelayNextAction(CLICK_CD_MELEE) for(var/mob/O in GLOB.player_list) if(isAI(O)) var/mob/living/silicon/ai/AI = O diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 83b0c0ee2d..effd70e9ab 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -79,10 +79,7 @@ charging = null update_icon() -/obj/machinery/cell_charger/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/cell_charger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!charging) return @@ -103,8 +100,18 @@ removecell() /obj/machinery/cell_charger/attack_ai(mob/user) + if(!charging) + return + + charging.forceMove(loc) + to_chat(user, "You remotely disconnect the battery port and eject [charging] from [src].") + + removecell() return +/obj/machinery/cell_charger/attack_robot(mob/user) + attack_ai(user) + /obj/machinery/cell_charger/emp_act(severity) . = ..() diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index cfe9d14663..5bbd3f8a65 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -26,6 +26,7 @@ var/efficiency var/datum/mind/clonemind + var/get_clone_mind = CLONEPOD_GET_MIND var/grab_ghost_when = CLONER_MATURE_CLONE var/internal_radio = TRUE @@ -74,31 +75,6 @@ speed_coeff = max(1, speed_coeff) heal_level = clamp((efficiency * 10) + 10, MINIMUM_HEAL_LEVEL, 100) -//The return of data disks?? Just for transferring between genetics machine/cloning machine. -//TO-DO: Make the genetics machine accept them. -/obj/item/disk/data - name = "cloning data disk" - icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk. - var/list/fields = list() - var/list/mutations = list() - var/max_mutations = 6 - var/read_only = 0 //Well,it's still a floppy disk - -//Disk stuff. -/obj/item/disk/data/Initialize() - . = ..() - icon_state = "datadisk[rand(0,6)]" - add_overlay("datadisk_gene") - -/obj/item/disk/data/attack_self(mob/user) - read_only = !read_only - to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].") - -/obj/item/disk/data/examine(mob/user) - . = ..() - . += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]." - - //Clonepod /obj/machinery/clonepod/examine(mob/user) @@ -134,43 +110,44 @@ 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, datum/bank_account/insurance) +/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, blood_type, datum/species/mrace, list/features, factions, list/quirks, datum/bank_account/insurance, list/traumas) if(panel_open) return FALSE if(mess || attempting) return FALSE - clonemind = locate(mindref) in SSticker.minds - if(!istype(clonemind)) //not a mind - return FALSE - if(!QDELETED(clonemind.current)) - if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body + if(get_clone_mind == CLONEPOD_GET_MIND) + clonemind = locate(mindref) in SSticker.minds + if(!istype(clonemind)) //not a mind return FALSE - if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding. + if(!QDELETED(clonemind.current)) + if(clonemind.current.stat != DEAD) //mind is associated with a non-dead body + return FALSE + if(clonemind.current.suiciding) // Mind is associated with a body that is suiciding. + return FALSE + if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker + return FALSE + if(clonemind.active) //somebody is using that mind + if( ckey(clonemind.key)!=ckey ) + return FALSE + else + // get_ghost() will fail if they're unable to reenter their body + var/mob/dead/observer/G = clonemind.get_ghost() + if(!G) + return FALSE + if(G.suiciding) // The ghost came from a body that is suiciding. + return FALSE + if(clonemind.damnation_type) //Can't clone the damned. + INVOKE_ASYNC(src, .proc/horrifyingsound) + mess = TRUE + update_icon() return FALSE - if(AmBloodsucker(clonemind.current)) //If the mind is a bloodsucker - return FALSE - if(clonemind.active) //somebody is using that mind - if( ckey(clonemind.key)!=ckey ) - return FALSE - else - // get_ghost() will fail if they're unable to reenter their body - var/mob/dead/observer/G = clonemind.get_ghost() - if(!G) - return FALSE - if(G.suiciding) // The ghost came from a body that is suiciding. - return FALSE - if(clonemind.damnation_type) //Can't clone the damned. - INVOKE_ASYNC(src, .proc/horrifyingsound) - mess = TRUE - update_icon() - return FALSE current_insurance = insurance attempting = TRUE //One at a time!! countdown.start() var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) - H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features) + H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features) H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone. @@ -192,7 +169,14 @@ ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT) H.Unconscious(80) - clonemind.transfer_to(H) + if(clonemind) + clonemind.transfer_to(H) + + else if(get_clone_mind == CLONEPOD_POLL_MIND) + var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone? (Don't ERP without permission from the original)", null, null, null, 100, H, POLL_IGNORE_CLONE) + if(LAZYLEN(candidates)) + var/mob/C = pick(candidates) + H.key = C.key if(grab_ghost_when == CLONER_FRESH_CLONE) H.grab_ghost() @@ -209,6 +193,12 @@ var/datum/quirk/Q = new V(H) Q.on_clone(quirks[V]) + for(var/t in traumas) + var/datum/brain_trauma/BT = t + var/datum/brain_trauma/cloned_trauma = BT.on_clone() + if(cloned_trauma) + H.gain_trauma(cloned_trauma, BT.resilience) + H.set_cloned_appearance() H.give_genitals(TRUE) @@ -271,9 +261,6 @@ var/obj/item/bodypart/BP = I BP.attach_limb(mob_occupant) - //Premature clones may have brain damage. - mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, -((speed_coeff / 2) * dmg_mult)) - use_power(7500) //This might need tweaking. else if((mob_occupant && mob_occupant.cloneloss <= (100 - heal_level))) @@ -399,6 +386,13 @@ to_chat(occupant, "There is a bright flash!
    You feel like a new being.
    ") mob_occupant.flash_act() + var/list/policies = CONFIG_GET(keyed_list/policyconfig) + var/policy = policies[POLICYCONFIG_ON_CLONE] + if(policy) + to_chat(occupant, policy) + occupant.log_message("revived using cloning.", LOG_GAME) + mob_occupant.adjustOrganLoss(ORGAN_SLOT_BRAIN, mob_occupant.getCloneLoss()) + occupant.forceMove(T) update_icon() mob_occupant.domutcheck(1) //Waiting until they're out before possible monkeyizing. The 1 argument forces powers to manifest. @@ -474,10 +468,9 @@ unattached_flesh.Cut() H.setCloneLoss(CLONE_INITIAL_DAMAGE) //Yeah, clones start with very low health, not with random, because why would they start with random health - //H.setOrganLoss(ORGAN_SLOT_BRAIN, CLONE_INITIAL_DAMAGE) - // In addition to being cellularly damaged and having barely any - - // brain function, they also have no limbs or internal organs. + // In addition to being cellularly damaged, they also have no limbs or internal organs. + // Applying brainloss is done when the clone leaves the pod, so application of traumas can happen. + // based on the level of damage sustained. if(!HAS_TRAIT(H, TRAIT_NODISMEMBER)) var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) @@ -545,6 +538,17 @@ . += "cover-on" . += "panel" +//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead +/obj/machinery/clonepod/experimental + name = "experimental cloning pod" + desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations." + icon = 'icons/obj/machines/cloning.dmi' + icon_state = "pod_0" + req_access = null + circuit = /obj/item/circuitboard/machine/clonepod/experimental + internal_radio = FALSE + get_clone_mind = CLONEPOD_POLL_MIND + /* * Manual -- A big ol' manual. */ diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 7439fd1b8b..a2fdc2336f 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -43,10 +43,13 @@ table.computer = src break -/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/operating/ui_state(mob/user) + return GLOB.not_incapacitated_state + +/obj/machinery/computer/operating/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "operating_computer", name, 350, 470, master_ui, state) + ui = new(user, src, "OperatingComputer", name) ui.open() /obj/machinery/computer/operating/ui_data(mob/user) @@ -108,8 +111,53 @@ )) else data["patient"] = null + return data + switch(patient.stat) + if(CONSCIOUS) + data["patient"]["stat"] = "Conscious" + data["patient"]["statstate"] = "good" + if(SOFT_CRIT) + data["patient"]["stat"] = "Conscious" + data["patient"]["statstate"] = "average" + if(UNCONSCIOUS) + data["patient"]["stat"] = "Unconscious" + data["patient"]["statstate"] = "average" + if(DEAD) + data["patient"]["stat"] = "Dead" + data["patient"]["statstate"] = "bad" + data["patient"]["health"] = patient.health + data["patient"]["blood_type"] = patient.dna.blood_type + data["patient"]["maxHealth"] = patient.maxHealth + data["patient"]["minHealth"] = HEALTH_THRESHOLD_DEAD + data["patient"]["bruteLoss"] = patient.getBruteLoss() + data["patient"]["fireLoss"] = patient.getFireLoss() + data["patient"]["toxLoss"] = patient.getToxLoss() + data["patient"]["oxyLoss"] = patient.getOxyLoss() + data["procedures"] = list() + if(patient.surgeries.len) + for(var/datum/surgery/procedure in patient.surgeries) + var/datum/surgery_step/surgery_step = procedure.get_surgery_step() + var/chems_needed = surgery_step.get_chem_list() + var/alternative_step + var/alt_chems_needed = "" + if(surgery_step.repeatable) + var/datum/surgery_step/next_step = procedure.get_surgery_next_step() + if(next_step) + alternative_step = capitalize(next_step.name) + alt_chems_needed = next_step.get_chem_list() + else + alternative_step = "Finish operation" + data["procedures"] += list(list( + "name" = capitalize("[parse_zone(procedure.location)] [procedure.name]"), + "next_step" = capitalize(surgery_step.name), + "chems_needed" = chems_needed, + "alternative_step" = alternative_step, + "alt_chems_needed" = alt_chems_needed + )) return data + + /obj/machinery/computer/operating/ui_act(action, params) if(..()) return diff --git a/code/game/machinery/computer/aifixer.dm b/code/game/machinery/computer/aifixer.dm index 9ff46c021b..8ebb64097d 100644 --- a/code/game/machinery/computer/aifixer.dm +++ b/code/game/machinery/computer/aifixer.dm @@ -2,12 +2,13 @@ name = "\improper AI system integrity restorer" desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order." req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS) - var/mob/living/silicon/ai/occupier = null - var/active = 0 - circuit = /obj/item/circuitboard/computer/aifixer icon_keyboard = "tech_key" icon_screen = "ai-fixer" light_color = LIGHT_COLOR_PINK + circuit = /obj/item/circuitboard/computer/aifixer + + var/mob/living/silicon/ai/occupier = null + var/active = FALSE /obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params) if(occupier && istype(I, /obj/item/screwdriver)) @@ -18,60 +19,45 @@ else return ..() -/obj/machinery/computer/aifixer/ui_interact(mob/user) - . = ..() - var/dat = "" +/obj/machinery/computer/aifixer/ui_interact(mob/user, datum/tgui/ui) //artur didn't port this correctly + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AiRestorer", name) + ui.open() - if (src.occupier) - var/laws - dat += "

    Stored AI: [src.occupier.name]

    " - dat += "System integrity: [(src.occupier.health+100)/2]%
    " +/obj/machinery/computer/aifixer/ui_data(mob/user) + var/list/data = list() - if (src.occupier.laws.zeroth) - laws += "0: [src.occupier.laws.zeroth]
    " + data["ejectable"] = FALSE + data["AI_present"] = FALSE + data["error"] = null + if(!occupier) + data["error"] = "Please transfer an AI unit." + else + data["AI_present"] = TRUE + data["name"] = occupier.name + data["restoring"] = active + data["health"] = (occupier.health + 100) / 2 + data["isDead"] = occupier.stat == DEAD + data["laws"] = occupier.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE) - for (var/index = 1, index <= src.occupier.laws.hacked.len, index++) - var/law = src.occupier.laws.hacked[index] - if (length(law) > 0) - var/num = ionnum() - laws += "[num]: [law]
    " + return data - for (var/index = 1, index <= src.occupier.laws.ion.len, index++) - var/law = src.occupier.laws.ion[index] - if (length(law) > 0) - var/num = ionnum() - laws += "[num]: [law]
    " +/obj/machinery/computer/aifixer/ui_act(action, params) + if(..()) + return + if(!occupier) + active = FALSE - var/number = 1 - for (var/index = 1, index <= src.occupier.laws.inherent.len, index++) - var/law = src.occupier.laws.inherent[index] - if (length(law) > 0) - laws += "[number]: [law]
    " - number++ - - for (var/index = 1, index <= src.occupier.laws.supplied.len, index++) - var/law = src.occupier.laws.supplied[index] - if (length(law) > 0) - laws += "[number]: [law]
    " - number++ - - dat += "Laws:
    [laws]
    " - - if (src.occupier.stat == DEAD) - dat += "AI non-functional" - else - dat += "AI functional" - if (!src.active) - dat += {"

    Begin Reconstruction"} - else - dat += "

    Reconstruction in process, please wait.
    " - dat += {"
    Close"} - var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return + switch(action) + if("PRG_beginReconstruction") + if(occupier?.health < 100) + to_chat(usr, "Reconstruction in progress. This will take several minutes.") + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE) + active = TRUE + occupier.notify_ghost_cloning("Your core files are being restored!", source = src) + . = TRUE /obj/machinery/computer/aifixer/proc/Fix() use_power(1000) @@ -91,17 +77,6 @@ active = Fix() if(oldstat != occupier.stat) update_icon() - updateDialog() - -/obj/machinery/computer/aifixer/Topic(href, href_list) - if(..()) - return - if(href_list["fix"]) - to_chat(usr, "Reconstruction in progress. This will take several minutes.") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) - active = TRUE - add_fingerprint(usr) - updateUsrDialog() /obj/machinery/computer/aifixer/update_overlays() . = ..() diff --git a/code/game/machinery/computer/apc_control.dm b/code/game/machinery/computer/apc_control.dm index eae2d5fa5b..c14837b8e3 100644 --- a/code/game/machinery/computer/apc_control.dm +++ b/code/game/machinery/computer/apc_control.dm @@ -3,19 +3,19 @@ desc = "Used to remotely control the flow of power to different parts of the station." icon_screen = "solar" icon_keyboard = "power_key" - req_access = list(ACCESS_ENGINE) + req_access = list(ACCESS_CE) circuit = /obj/item/circuitboard/computer/apc_control light_color = LIGHT_COLOR_YELLOW var/mob/living/operator //Who's operating the computer right now var/obj/machinery/power/apc/active_apc //The APC we're using right now - var/list/result_filters //For sorting the results - var/checking_logs = 0 + var/should_log = TRUE + var/restoring = FALSE var/list/logs - var/auth_id = "\[NULL\]" + var/auth_id = "\[NULL\]:" -/obj/machinery/computer/apc_control/Initialize() +/obj/machinery/computer/apc_control/Initialize(mapload, obj/item/circuitboard/C) . = ..() - result_filters = list("Name" = null, "Charge Above" = null, "Charge Below" = null, "Responsive" = null) + logs = list() /obj/machinery/computer/apc_control/process() if(operator && (!operator.Adjacent(src) || stat)) @@ -23,8 +23,8 @@ if(active_apc) if(!active_apc.locked) active_apc.say("Remote access canceled. Interface locked.") - playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0) - playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0) + playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE) + playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE) active_apc.locked = TRUE active_apc.update_icon() active_apc.remote_control = null @@ -34,171 +34,163 @@ if(!IsAdminGhost(user)) to_chat(user,"[src] does not support AI control.") //You already have APC access, cheater! return - ..(user) + ..() /obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/APC) return APC.z == z && !APC.malfhack && !APC.aidisabled && !(APC.obj_flags & EMAGGED) && !APC.stat && !istype(APC.area, /area/ai_monitored) && !APC.area.outdoors -/obj/machinery/computer/apc_control/ui_interact(mob/living/user) - . = ..() - var/dat - if(authenticated) - if(!checking_logs) - dat += "Logged in as [auth_id].

    " - dat += "Filters
    " - dat += "Name: [result_filters["Name"] ? result_filters["Name"] : "None set"]
    " - dat += "Charge: \>[result_filters["Charge Above"] ? result_filters["Charge Above"] : "NaN"]% and \<[result_filters["Charge Below"] ? result_filters["Charge Below"] : "NaN"]%
    " - dat += "Accessible: [result_filters["Responsive"] ? "Non-Responsive Only" : "All"]

    " - for(var/A in GLOB.apcs_list) - if(check_apc(A)) - var/obj/machinery/power/apc/APC = A - if(result_filters["Name"] && !findtext(APC.name, result_filters["Name"]) && !findtext(APC.area.name, result_filters["Name"])) - continue - if(result_filters["Charge Above"] && (!APC.cell || (APC.cell && (APC.cell.charge / APC.cell.maxcharge) < result_filters["Charge Above"] / 100))) - continue - if(result_filters["Charge Below"] && APC.cell && (APC.cell.charge / APC.cell.maxcharge) > result_filters["Charge Below"] / 100) - continue - if(result_filters["Responsive"] && !APC.aidisabled) - continue - dat += "[A]
    \ - Charge: [APC.cell ? "[DisplayEnergy(APC.cell.charge)] / [DisplayEnergy(APC.cell.maxcharge)] ([round((APC.cell.charge / APC.cell.maxcharge) * 100)]%)" : "No Powercell Installed"]
    \ - Area: [APC.area]
    \ - [APC.aidisabled || APC.panel_open ? "APC does not respond to interface query." : "APC responds to interface query."]

    " - dat += "Check Logs
    " - dat += "Log Out
    " - if(obj_flags & EMAGGED) - dat += "WARNING: Logging functionality partially disabled from outside source.
    " - dat += "Restore logging functionality?
    " - else - if(logs.len) - for(var/entry in logs) - dat += "[entry]
    " - else - dat += "No activity has been recorded at this time.
    " - if(obj_flags & EMAGGED) - dat += "@#%! CLEAR LOGS" - dat += "Return" - operator = user - else - dat = "Please swipe a valid ID to log in..." - var/datum/browser/popup = new(user, "apc_control", name, 600, 400) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() +/obj/machinery/computer/apc_control/ui_interact(mob/user, datum/tgui/ui) + operator = user + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ApcControl") + ui.open() -/obj/machinery/computer/apc_control/Topic(href, href_list) +/obj/machinery/computer/apc_control/ui_data(mob/user) + var/list/data = list() + data["auth_id"] = auth_id + data["authenticated"] = authenticated + data["emagged"] = obj_flags & EMAGGED + data["logging"] = should_log + data["restoring"] = restoring + data["logs"] = list() + data["apcs"] = list() + + for(var/entry in logs) + data["logs"] += list(list("entry" = entry)) + + for(var/apc in GLOB.apcs_list) + if(check_apc(apc)) + var/obj/machinery/power/apc/A = apc + var/has_cell = (A.cell) ? TRUE : FALSE + data["apcs"] += list(list( + "name" = A.area.name, + "operating" = A.operating, + "charge" = (has_cell) ? A.cell.percent() : "NOCELL", + "load" = DisplayPower(A.lastused_total), + "charging" = A.charging, + "chargeMode" = A.chargemode, + "eqp" = A.equipment, + "lgt" = A.lighting, + "env" = A.environ, + "responds" = A.aidisabled || A.panel_open, + "ref" = REF(A) + ) + ) + return data + +/obj/machinery/computer/apc_control/ui_act(action, params) if(..()) return - if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src)) - return - if(href_list["authenticate"]) - var/obj/item/card/id/ID = usr.get_idcard(TRUE) - if(ID && istype(ID)) - if(check_access(ID)) + switch(action) + if("log-in") + if(obj_flags & EMAGGED) authenticated = TRUE - auth_id = "[ID.registered_name] ([ID.assignment])" - log_activity("logged in") - if(href_list["log_out"]) - log_activity("logged out") - authenticated = FALSE - auth_id = "\[NULL\]" - if(href_list["restore_logging"]) - to_chat(usr, "[icon2html(src, usr)] Logging functionality restored from backup data.") - obj_flags &= ~EMAGGED - LAZYADD(logs, "-=- Logging restored to full functionality at this point -=-") - if(href_list["access_apc"]) - playsound(src, "terminal_type", 50, 0) - var/obj/machinery/power/apc/APC = locate(href_list["access_apc"]) in GLOB.apcs_list - if(!APC || APC.aidisabled || APC.panel_open || QDELETED(APC)) - to_chat(usr, "[icon2html(src, usr)] APC does not return interface request. Remote access may be disabled.") - return - if(active_apc) - to_chat(usr, "[icon2html(src, usr)] Disconnected from [active_apc].") - active_apc.say("Remote access canceled. Interface locked.") - playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0) - playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0) - active_apc.locked = TRUE - active_apc.update_icon() - active_apc.remote_control = null - active_apc = null - to_chat(usr, "[icon2html(src, usr)] Connected to APC in [get_area_name(APC.area, TRUE)]. Interface request sent.") - log_activity("remotely accessed APC in [get_area_name(APC.area, TRUE)]") - APC.remote_control = src - APC.ui_interact(usr) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - message_admins("[ADMIN_LOOKUPFLW(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].") - log_game("[key_name(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].") - if(APC.locked) - APC.say("Remote access detected. Interface unlocked.") - playsound(APC, 'sound/machines/boltsup.ogg', 25, 0) - playsound(APC, 'sound/machines/terminal_alert.ogg', 50, 0) - APC.locked = FALSE - APC.update_icon() - active_apc = APC - if(href_list["name_filter"]) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - var/new_filter = stripped_input(usr, "What name are you looking for?", name) - if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) - return - log_activity("changed name filter to \"[new_filter]\"") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - result_filters["Name"] = new_filter - if(href_list["above_filter"]) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (greater than).", name) as null|num - if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) - return - log_activity("changed greater than charge filter to \"[new_filter]\"") - if(new_filter) - new_filter = clamp(new_filter, 0, 100) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - result_filters["Charge Above"] = new_filter - if(href_list["below_filter"]) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (lesser than).", name) as null|num - if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) - return - log_activity("changed lesser than charge filter to \"[new_filter]\"") - if(new_filter) - new_filter = clamp(new_filter, 0, 100) - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - result_filters["Charge Below"] = new_filter - if(href_list["access_filter"]) - if(isnull(result_filters["Responsive"])) - result_filters["Responsive"] = 1 - log_activity("sorted by non-responsive APCs only") - else - result_filters["Responsive"] = !result_filters["Responsive"] - log_activity("sorted by all APCs") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - if(href_list["check_logs"]) - checking_logs = TRUE - log_activity("checked logs") - if(href_list["check_apcs"]) - checking_logs = FALSE - log_activity("checked APCs") - if(href_list["clear_logs"]) - logs = list() - ui_interact(usr) //Refresh the UI after a filter changes + auth_id = "Unknown (Unknown):" + log_activity("[auth_id] logged in to the terminal") + return + var/obj/item/card/id/ID = operator.get_idcard(TRUE) + if(ID && istype(ID)) + if(check_access(ID)) + authenticated = TRUE + auth_id = "[ID.registered_name] ([ID.assignment]):" + log_activity("[auth_id] logged in to the terminal") + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) + else + auth_id = "[ID.registered_name] ([ID.assignment]):" + log_activity("[auth_id] attempted to log into the terminal") + return + auth_id = "Unknown (Unknown):" + log_activity("[auth_id] attempted to log into the terminal") + if("log-out") + log_activity("[auth_id] logged out of the terminal") + playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) + authenticated = FALSE + auth_id = "\[NULL\]" + if("toggle-logs") + should_log = !should_log + log_game("[key_name(operator)] set the logs of [src] in [AREACOORD(src)] [should_log ? "On" : "Off"]") + if("restore-console") + restoring = TRUE + addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9) + if("access-apc") + var/ref = params["ref"] + playsound(src, "terminal_type", 50, FALSE) + var/obj/machinery/power/apc/APC = locate(ref) in GLOB.apcs_list + if(!APC) + return + if(active_apc) + to_chat(operator, "[icon2html(src, auth_id)] Disconnected from [active_apc].") + active_apc.say("Remote access canceled. Interface locked.") + playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE) + playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE) + active_apc.locked = TRUE + active_apc.update_icon() + active_apc.remote_control = null + active_apc = null + APC.remote_control = src + APC.ui_interact(operator) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + log_game("[key_name(operator)] remotely accessed [APC] from [src] at [AREACOORD(src)].") + log_activity("[auth_id] remotely accessed APC in [get_area_name(APC.area, TRUE)]") + if(APC.locked) + APC.say("Remote access detected. Interface unlocked.") + playsound(APC, 'sound/machines/boltsup.ogg', 25, FALSE) + playsound(APC, 'sound/machines/terminal_alert.ogg', 50, FALSE) + APC.locked = FALSE + APC.update_icon() + active_apc = APC + if("check-logs") + log_activity("Checked Logs") + if("check-apcs") + log_activity("Checked APCs") + if("toggle-minor") + var/ref = params["ref"] + var/type = params["type"] + var/value = params["value"] + var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list + if(!target) + return + target.vars[type] = target.setsubsystem(text2num(value)) + target.update_icon() + target.update() + var/setTo = "" + switch(target.vars[type]) + if(0) + setTo = "Off" + if(1) + setTo = "Auto Off" + if(2) + setTo = "On" + if(3) + setTo = "Auto On" + log_activity("Set APC [target.area.name] [type] to [setTo]") + log_game("[key_name(operator)] Set APC [target.area.name] [type] to [setTo]]") + if("breaker") + var/ref = params["ref"] + var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list + target.toggle_breaker() + var/setTo = target.operating ? "On" : "Off" + log_activity("Turned APC [target.area.name]'s breaker [setTo]") /obj/machinery/computer/apc_control/emag_act(mob/user) - . = ..() - if(!authenticated) - to_chat(user, "You bypass [src]'s access requirements using your emag.") - authenticated = TRUE - log_activity("logged in") - else - if(obj_flags & EMAGGED) - return - user.visible_message("You emag [src], disabling precise logging and allowing you to clear logs.") - log_game("[key_name(user)] emagged [src] at [AREACOORD(src)], disabling operator tracking.") - obj_flags |= EMAGGED - playsound(src, "sparks", 50, 1) - return TRUE + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + log_game("[key_name(user)] emagged [src] at [AREACOORD(src)]") + playsound(src, "sparks", 50, TRUE) /obj/machinery/computer/apc_control/proc/log_activity(log_text) - var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]" - LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]) [op_string] [log_text]") + if(!should_log) + return + LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]): [auth_id] [log_text]") + +/obj/machinery/computer/apc_control/proc/restore_comp() + obj_flags &= ~EMAGGED + should_log = TRUE + log_game("[key_name(operator)] restored the logs of [src] in [AREACOORD(src)]") + log_activity("-=- Logging restored to full functionality at this point -=-") + restoring = FALSE /mob/proc/using_power_flow_console() for(var/obj/machinery/computer/apc_control/A in range(1, src)) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 2d9880578c..4fb39c04e1 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -42,9 +42,9 @@ /obj/item/clothing/mask/facehugger/toy = ARCADE_WEIGHT_RARE, /obj/item/gun/ballistic/automatic/toy/pistol/unrestricted = ARCADE_WEIGHT_TRICK, /obj/item/hot_potato/harmless/toy = ARCADE_WEIGHT_RARE, - /obj/item/twohanded/dualsaber/toy = ARCADE_WEIGHT_RARE, - /obj/item/twohanded/dualsaber/hypereutactic/toy = ARCADE_WEIGHT_RARE, - /obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow = ARCADE_WEIGHT_RARE, + /obj/item/dualsaber/toy = ARCADE_WEIGHT_RARE, + /obj/item/dualsaber/hypereutactic/toy = ARCADE_WEIGHT_RARE, + /obj/item/dualsaber/hypereutactic/toy/rainbow = ARCADE_WEIGHT_RARE, /obj/item/storage/box/snappops = ARCADE_WEIGHT_TRICK, /obj/item/clothing/under/syndicate/tacticool = ARCADE_WEIGHT_TRICK, @@ -136,3 +136,17 @@ empprize = pickweight(prizes) new empprize(loc) explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes) + +/obj/machinery/computer/arcade/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/stack/arcadeticket)) + var/obj/item/stack/arcadeticket/T = O + var/amount = T.get_amount() + if(amount <2) + to_chat(user, "You need 2 tickets to claim a prize!") + return + prizevend(user) + T.pay_tickets() + T.update_icon() + O = T + to_chat(user, "You turn in 2 tickets to the [src] and claim a prize!") + return diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm index b906b1afb5..fc99edd3eb 100644 --- a/code/game/machinery/computer/arcade/battle.dm +++ b/code/game/machinery/computer/arcade/battle.dm @@ -184,6 +184,15 @@ blocked = FALSE return +/obj/machinery/computer/arcade/battle/examine_more(mob/user) + to_chat(user, "Scribbled on the side of the Arcade Machine you notice some writing...\ + \nmagical -> >=50 power\ + \nsmart -> defend, defend, light attack\ + \nshotgun -> defend, defend, power attack\ + \nshort temper -> counter, counter, counter\ + \npoisonous -> light attack, light attack, light attack\ + \nchonker -> power attack, power attack, power attack") + return ..() /obj/machinery/computer/arcade/battle/emag_act(mob/user) . = ..() diff --git a/code/game/machinery/computer/arcade/misc_arcade.dm b/code/game/machinery/computer/arcade/misc_arcade.dm index 78b4a6863c..24516740f9 100644 --- a/code/game/machinery/computer/arcade/misc_arcade.dm +++ b/code/game/machinery/computer/arcade/misc_arcade.dm @@ -8,7 +8,7 @@ icon_state = "arcade" circuit = /obj/item/circuitboard/computer/arcade/amputation -/obj/machinery/computer/arcade/amputation/attack_hand(mob/user) +/obj/machinery/computer/arcade/amputation/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!iscarbon(user)) return var/mob/living/carbon/c_user = user @@ -28,4 +28,4 @@ for(var/i=1; i<=rand(3,5); i++) prizevend(user) else - to_chat(c_user, "You (wisely) decide against putting your hand in the machine.") \ No newline at end of file + to_chat(c_user, "You (wisely) decide against putting your hand in the machine.") diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index 6df7120dcc..50a6d10302 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -19,11 +19,10 @@ SSradio.remove_object(src, receive_frequency) return ..() -/obj/machinery/computer/atmos_alert/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/atmos_alert/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_alert", name, 350, 300, master_ui, state) + ui = new(user, src, "AtmosAlertConsole", name) ui.open() /obj/machinery/computer/atmos_alert/ui_data(mob/user) @@ -45,11 +44,11 @@ if("clear") var/zone = params["zone"] if(zone in priority_alarms) - to_chat(usr, "Priority alarm for [zone] cleared.") + to_chat(usr, "Priority alarm for [zone] cleared.") priority_alarms -= zone . = TRUE if(zone in minor_alarms) - to_chat(usr, "Minor alarm for [zone] cleared.") + to_chat(usr, "Minor alarm for [zone] cleared.") minor_alarms -= zone . = TRUE update_icon() diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index 79ea51eca4..4ba8d9f3d3 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -53,14 +53,14 @@ "id_tag" = id_tag, "timestamp" = world.time, "pressure" = air_sample.return_pressure(), - "temperature" = air_sample.temperature, + "temperature" = air_sample.return_temperature(), "gases" = list() )) var/total_moles = air_sample.total_moles() if(total_moles) - for(var/gas_id in air_sample.gases) + for(var/gas_id in air_sample.get_gases()) var/gas_name = GLOB.meta_gas_names[gas_id] - signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100 + signal.data["gases"][gas_name] = air_sample.get_moles(gas_id) / total_moles * 100 radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) @@ -91,8 +91,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) icon_screen = "tank" icon_keyboard = "atmos_key" circuit = /obj/item/circuitboard/computer/atmos_control - ui_x = 400 - ui_y = 925 var/frequency = FREQ_ATMOS_STORAGE var/list/sensors = list( @@ -123,11 +121,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) SSradio.remove_object(src, frequency) return ..() -/obj/machinery/computer/atmos_control/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_control", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "AtmosControlConsole", name) ui.open() /obj/machinery/computer/atmos_control/ui_data(mob/user) @@ -265,13 +262,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers) for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) U.broadcast_status() -/obj/machinery/computer/atmos_control/tank/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "atmos_control", name, ui_x, ui_y, master_ui, state) - ui.open() - /obj/machinery/computer/atmos_control/tank/ui_data(mob/user) var/list/data = ..() data["tank"] = TRUE diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 70a59230b2..d42291cd3c 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -4,109 +4,163 @@ icon_screen = "cameras" icon_keyboard = "security_key" circuit = /obj/item/circuitboard/computer/security - var/last_pic = 1 - var/list/network = list("ss13") - var/list/watchers = list() //who's using the console, associated with the camera they're on. - light_color = LIGHT_COLOR_RED + var/list/network = list("ss13") + var/obj/machinery/camera/active_camera + var/list/concurrent_users = list() + + // Stuff needed to render the map + var/map_name + var/const/default_map_size = 15 + var/obj/screen/cam_screen + var/obj/screen/plane_master/lighting/cam_plane_master + var/obj/screen/background/cam_background + /obj/machinery/computer/security/Initialize() . = ..() + // Map name has to start and end with an A-Z character, + // and definitely NOT with a square bracket or even a number. + // I wasted 6 hours on this. :agony: + map_name = "camera_console_[REF(src)]_map" + // Convert networks to lowercase for(var/i in network) network -= i network += lowertext(i) - -/obj/machinery/computer/security/check_eye(mob/user) - if(!can_interact(user) || !(user in watchers) || !watchers[user]) - user.unset_machine() - return - var/obj/machinery/camera/C = watchers[user] - if(!C.can_use()) - user.unset_machine() - return - -/obj/machinery/computer/security/on_unset_machine(mob/user) - watchers.Remove(user) - user.reset_perspective(null) + // Initialize map objects + cam_screen = new + cam_screen.name = "screen" + cam_screen.assigned_map = map_name + cam_screen.del_on_map_removal = FALSE + cam_screen.screen_loc = "[map_name]:1,1" + cam_plane_master = new + cam_plane_master.name = "plane_master" + cam_plane_master.assigned_map = map_name + cam_plane_master.del_on_map_removal = FALSE + cam_plane_master.screen_loc = "[map_name]:CENTER" + cam_background = new + cam_background.assigned_map = map_name + cam_background.del_on_map_removal = FALSE /obj/machinery/computer/security/Destroy() - if(watchers.len) - for(var/mob/M in watchers) - M.unset_machine() //to properly reset the view of the users if the console is deleted. + qdel(cam_screen) + qdel(cam_plane_master) + qdel(cam_background) return ..() -/obj/machinery/computer/security/can_interact(mob/user) - if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src)) - return FALSE - return ..() +/obj/machinery/computer/security/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + for(var/i in network) + network -= i + network += "[idnum][i]" -/obj/machinery/computer/security/interact(mob/user, special_state) +/obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui) + // Update UI + ui = SStgui.try_update_ui(user, src, ui) + // Show static if can't use the camera + if(!active_camera?.can_use()) + show_camera_static() + if(!ui) + var/user_ref = REF(user) + var/is_living = isliving(user) + // Ghosts shouldn't count towards concurrent users, which produces + // an audible terminal_on click. + if(is_living) + concurrent_users += user_ref + // Turn on the console + if(length(concurrent_users) == 1 && is_living) + playsound(src, 'sound/machines/terminal_on.ogg', 25, FALSE) + use_power(active_power_usage) + // Register map objects + user.client.register_map_obj(cam_screen) + for(var/plane in cam_plane_master) + user.client.register_map_obj(plane) + user.client.register_map_obj(cam_background) + // Open UI + ui = new(user, src, "CameraConsole", name) + ui.open() + +/obj/machinery/computer/security/ui_data() + var/list/data = list() + data["network"] = network + data["activeCamera"] = null + if(active_camera) + data["activeCamera"] = list( + name = active_camera.c_tag, + status = active_camera.status, + ) + return data + +/obj/machinery/computer/security/ui_static_data() + var/list/data = list() + data["mapRef"] = map_name + var/list/cameras = get_available_cameras() + data["cameras"] = list() + for(var/i in cameras) + var/obj/machinery/camera/C = cameras[i] + data["cameras"] += list(list( + name = C.c_tag, + )) + return data + +/obj/machinery/computer/security/ui_act(action, params) . = ..() - if (ismob(user) && !isliving(user)) // ghosts don't need cameras - return - if (!network) - stack_trace("No camera network") - user.unset_machine() - return FALSE - if (!(islist(network))) - stack_trace("Camera network is not a list") - user.unset_machine() - return FALSE - - var/list/camera_list = get_available_cameras() - if(!(user in watchers)) - for(var/Num in camera_list) - var/obj/machinery/camera/CAM = camera_list[Num] - if(istype(CAM) && CAM.can_use()) - watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants. - break - if(!(user in watchers)) - user.unset_machine() // no usable camera on the network, we disconnect the user from the computer. - return FALSE - playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0) - use_camera_console(user) - -/obj/machinery/computer/security/proc/use_camera_console(mob/user) - var/list/camera_list = get_available_cameras() - var/t = input(user, "Which camera should you change to?") as null|anything in camera_list - if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine. - return - if(!t || t == "Cancel") - user.unset_machine() - playsound(src, 'sound/machines/terminal_off.ogg', 25, 0) + if(.) return - var/obj/machinery/camera/C = camera_list[t] + if(action == "switch_camera") + var/c_tag = params["name"] + var/list/cameras = get_available_cameras() + var/obj/machinery/camera/C = cameras[c_tag] + active_camera = C + playsound(src, get_sfx("terminal_type"), 25, FALSE) - if(!C || !C.can_use() || !can_interact(user)) - user.unset_machine() - return FALSE + // Show static if can't use the camera + if(!active_camera?.can_use()) + show_camera_static() + return TRUE - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0) - if(isAI(user)) - var/mob/living/silicon/ai/A = user - A.eyeobj.setLoc(get_turf(C)) - A.client.eye = A.eyeobj - else - user.reset_perspective(C) - user.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static) - user.clear_fullscreen("flash", 5) - watchers[user] = C - use_power(50) - addtimer(CALLBACK(src, .proc/use_camera_console, user), 5) + var/list/visible_turfs = list() + for(var/turf/T in (C.isXRay() \ + ? range(C.view_range, C) \ + : view(C.view_range, C))) + visible_turfs += T -//returns the list of cameras accessible from this computer + var/list/bbox = get_bbox_of_atoms(visible_turfs) + var/size_x = bbox[3] - bbox[1] + 1 + var/size_y = bbox[4] - bbox[2] + 1 + + cam_screen.vis_contents = visible_turfs + cam_background.icon_state = "clear" + cam_background.fill_rect(1, 1, size_x, size_y) + + return TRUE + +/obj/machinery/computer/security/ui_close(mob/user) + var/user_ref = REF(user) + var/is_living = isliving(user) + // Living creature or not, we remove you anyway. + concurrent_users -= user_ref + // Unregister map objects + user.client.clear_map(map_name) + // Turn off the console + if(length(concurrent_users) == 0 && is_living) + active_camera = null + playsound(src, 'sound/machines/terminal_off.ogg', 25, FALSE) + use_power(0) + +/obj/machinery/computer/security/proc/show_camera_static() + cam_screen.vis_contents.Cut() + cam_background.icon_state = "scanline2" + cam_background.fill_rect(1, 1, default_map_size, default_map_size) + +// Returns the list of cameras accessible from this computer /obj/machinery/computer/security/proc/get_available_cameras() var/list/L = list() for (var/obj/machinery/camera/C in GLOB.cameranet.cameras) if((is_away_level(z) || is_away_level(C.z)) && (C.z != z))//if on away mission, can only receive feed from same z_level cameras continue L.Add(C) - - camera_sort(L) - var/list/D = list() - D["Cancel"] = "Cancel" for(var/obj/machinery/camera/C in L) if(!C.network) stack_trace("Camera in a cameranet has no camera network") @@ -114,9 +168,9 @@ if(!(islist(C.network))) stack_trace("Camera in a cameranet has a non-list camera network") continue - var/list/tempnetwork = C.network&network + var/list/tempnetwork = C.network & network if(tempnetwork.len) - D["[C.c_tag][(C.status ? null : " (Deactivated)")]"] = C + D["[C.c_tag]"] = C return D // SECURITY MONITORS @@ -127,7 +181,6 @@ icon_state = "television" icon_keyboard = null icon_screen = "detective_tv" - clockwork = TRUE //it'd look weird pass_flags = PASSTABLE /obj/machinery/computer/security/mining @@ -145,7 +198,7 @@ circuit = /obj/item/circuitboard/computer/research /obj/machinery/computer/security/hos - name = "Head of Security's camera console" + name = "\improper Head of Security's camera console" desc = "A custom security console with added access to the labor camp network." network = list("ss13", "labor") circuit = null @@ -157,7 +210,7 @@ circuit = null /obj/machinery/computer/security/qm - name = "Quartermaster's camera console" + name = "\improper Quartermaster's camera console" desc = "A console with access to the mining, auxillary base and vault camera networks." network = list("mine", "auxbase", "vault") circuit = null @@ -172,7 +225,6 @@ network = list("thunder") density = FALSE circuit = null - clockwork = TRUE //it'd look very weird light_power = 0 /obj/machinery/computer/security/telescreen/Initialize() @@ -190,11 +242,35 @@ name = "entertainment monitor" desc = "Damn, they better have the /tg/ channel on these things." icon = 'icons/obj/status_display.dmi' - icon_state = "entertainment" + icon_state = "entertainment_blank" network = list("thunder") + density = FALSE + circuit = null + interaction_flags_atom = NONE // interact() is called by BigClick() + var/icon_state_off = "entertainment_blank" + var/icon_state_on = "entertainment" + +/obj/machinery/computer/security/telescreen/entertainment/Initialize() + . = ..() + RegisterSignal(src, COMSIG_CLICK, .proc/BigClick) + +// Bypass clickchain to allow humans to use the telescreen from a distance +/obj/machinery/computer/security/telescreen/entertainment/proc/BigClick() + interact(usr) + +/obj/machinery/computer/security/telescreen/entertainment/proc/notify(on) + if(on && icon_state == icon_state_off) + say(pick( + "Feats of bravery live now at the thunderdome!", + "Two enter, one leaves! Tune in now!", + "Violence like you've never seen it before!", + "Spears! Camera! Action! LIVE NOW!")) + icon_state = icon_state_on + else + icon_state = icon_state_off /obj/machinery/computer/security/telescreen/rd - name = "Research Director's telescreen" + name = "\improper Research Director's telescreen" desc = "Used for watching the AI and the RD's goons from the safety of his office." network = list("rd", "aicore", "aiupload", "minisat", "xeno", "test") @@ -202,26 +278,26 @@ name = "circuitry telescreen" desc = "Used for watching the other eggheads from the safety of the circuitry lab." network = list("rd") - + /obj/machinery/computer/security/telescreen/ce - name = "Chief Engineer's telescreen" + name = "\improper Chief Engineer's telescreen" desc = "Used for watching the engine, telecommunications and the minisat." network = list("engine", "singularity", "tcomms", "minisat") /obj/machinery/computer/security/telescreen/cmo - name = "Chief Medical Officer's telescreen" + name = "\improper Chief Medical Officer's telescreen" desc = "A telescreen with access to the medbay's camera network." network = list("medbay") /obj/machinery/computer/security/telescreen/vault - name = "Vault monitor" + name = "vault monitor" desc = "A telescreen that connects to the vault's camera network." network = list("vault") /obj/machinery/computer/security/telescreen/toxins - name = "Bomb test site monitor" + name = "bomb test site monitor" desc = "A telescreen that connects to the bomb test site's camera." - network = list("toxin") + network = list("toxins") /obj/machinery/computer/security/telescreen/engine name = "engine monitor" @@ -254,7 +330,7 @@ network = list("minisat") /obj/machinery/computer/security/telescreen/aiupload - name = "AI upload monitor" + name = "\improper AI upload monitor" desc = "A telescreen that connects to the AI upload's camera network." network = list("aiupload") diff --git a/code/game/machinery/computer/camera_advanced.dm b/code/game/machinery/computer/camera_advanced.dm index 5fe62ebb76..4b5806b8fd 100644 --- a/code/game/machinery/computer/camera_advanced.dm +++ b/code/game/machinery/computer/camera_advanced.dm @@ -29,9 +29,17 @@ if(lock_override & CAMERA_LOCK_REEBE) z_lock |= SSmapping.levels_by_trait(ZTRAIT_REEBE) +/obj/machinery/computer/camera_advanced/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + for(var/i in networks) + networks -= i + networks += "[idnum][i]" + /obj/machinery/computer/camera_advanced/syndie icon_keyboard = "syndie_key" +/obj/machinery/computer/camera_advanced/syndie/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + return //For syndie nuke shuttle, to spy for station. + /obj/machinery/computer/camera_advanced/proc/CreateEye() eyeobj = new() eyeobj.origin = src @@ -95,10 +103,7 @@ return FALSE return ..() -/obj/machinery/computer/camera_advanced/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/computer/camera_advanced/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(current_user) to_chat(user, "The console is already in use!") return @@ -268,112 +273,4 @@ C.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static) C.clear_fullscreen("flash", 3) //Shorter flash than normal since it's an ~~advanced~~ console! else - playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0) - - -//Used by servants of Ratvar! They let you beam to the station. -/obj/machinery/computer/camera_advanced/ratvar - name = "ratvarian camera observer" - desc = "A console used to snoop on the station's goings-on. A jet of steam occasionally whooshes out from slats on its sides." - use_power = FALSE - networks = list("ss13", "minisat") //:eye: - var/datum/action/innate/servant_warp/warp_action = new - -/obj/machinery/computer/camera_advanced/ratvar/Initialize() - . = ..() - ratvar_act() - -/obj/machinery/computer/camera_advanced/ratvar/process() - if(prob(1)) - playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 25, TRUE) - new/obj/effect/temp_visual/steam_release(get_turf(src)) - -/obj/machinery/computer/camera_advanced/ratvar/CreateEye() - ..() - eyeobj.visible_icon = TRUE - eyeobj.icon = 'icons/mob/cameramob.dmi' //in case you still had any doubts - eyeobj.icon_state = "generic_camera" - -/obj/machinery/computer/camera_advanced/ratvar/GrantActions(mob/living/carbon/user) - ..() - if(warp_action) - warp_action.Grant(user) - warp_action.target = src - actions += warp_action - -/obj/machinery/computer/camera_advanced/ratvar/can_use(mob/living/user) - if(!is_servant_of_ratvar(user)) - to_chat(user, "[src]'s keys are in a language foreign to you, and you don't understand anything on its screen.") - return - if(clockwork_ark_active()) - to_chat(user, "The Ark is active, and [src] has shut down.") - return - . = ..() - -/datum/action/innate/servant_warp - name = "Warp" - desc = "Warps to the tile you're viewing. You can use the Abscond scripture to return. Clicking this button again cancels the warp." - icon_icon = 'icons/mob/actions/actions_clockcult.dmi' - button_icon_state = "warp_down" - background_icon_state = "bg_clock" - buttontooltipstyle = "clockcult" - var/cancel = FALSE //if TRUE, an active warp will be canceled - var/obj/effect/temp_visual/ratvar/warp_marker/warping - -/datum/action/innate/servant_warp/Activate() - if(QDELETED(target) || !(ishuman(owner) || iscyborg(owner)) || !owner.canUseTopic(target)) - return - if(!GLOB.servants_active) //No leaving unless there's servants from the get-go - return - if(warping) - cancel = TRUE - return - var/mob/living/carbon/human/user = owner - var/mob/camera/aiEye/remote/remote_eye = user.remote_control - var/obj/machinery/computer/camera_advanced/ratvar/R = target - var/turf/T = get_turf(remote_eye) - if(!is_reebe(user.z) || !is_station_level(T.z)) - return - if(isclosedturf(T)) - to_chat(user, "You can't teleport into a wall.") - return - else if(isspaceturf(T)) - to_chat(user, "[prob(1) ? "Servant cannot into space." : "You can't teleport into space."]") - return - else if(T.flags_1 & NOJAUNT_1) - to_chat(user, "This tile is blessed by holy water and deflects the warp.") - return - var/area/AR = get_area(T) - if(!AR.clockwork_warp_allowed) - to_chat(user, "[AR.clockwork_warp_fail]") - return - if(alert(user, "Are you sure you want to warp to [AR]?", target.name, "Warp", "Cancel") == "Cancel" || QDELETED(R) || !user.canUseTopic(R)) - return - do_sparks(5, TRUE, user) - do_sparks(5, TRUE, T) - warping = new(T) - user.visible_message("[user]'s [target.name] flares!", "You begin warping to [AR]...") - button_icon_state = "warp_cancel" - owner.update_action_buttons() - if(!do_after(user, 50, target = warping, extra_checks = CALLBACK(src, .proc/is_canceled))) - to_chat(user, "Warp interrupted.") - QDEL_NULL(warping) - button_icon_state = "warp_down" - owner.update_action_buttons() - cancel = FALSE - return - button_icon_state = "warp_down" - owner.update_action_buttons() - QDEL_NULL(warping) - if(!do_teleport(user, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) - to_chat(user, "Warp Failed. Something deflected our attempt to warp to [AR].") - return - T.visible_message("[user] warps in!") - playsound(user, 'sound/magic/magic_missile.ogg', 50, TRUE) - playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE) - user.setDir(SOUTH) - flash_color(user, flash_color = "#AF0AAF", flash_time = 5) - R.remove_eye_control(user) - -/datum/action/innate/servant_warp/proc/is_canceled() - return !cancel + playsound(origin, 'sound/machines/terminal_prompt_deny.ogg', 25, 0) \ No newline at end of file diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 981a5643a8..400ce041c7 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -8,6 +8,7 @@ circuit = /obj/item/circuitboard/computer/cloning req_access = list(ACCESS_HEADS) //ONLY USED FOR RECORD DELETION RIGHT NOW. var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning. + var/clonepod_type = /obj/machinery/clonepod var/list/pods //Linked cloning pods var/temp = "Inactive" var/scantemp_ckey @@ -17,6 +18,7 @@ var/obj/item/disk/data/diskette = null //Mostly so the geneticist can steal everything. var/loading = 0 // Nice loading text var/autoprocess = 0 + var/use_records = TRUE // Old experimental cloner. var/list/records = list() light_color = LIGHT_COLOR_BLUE @@ -36,29 +38,32 @@ return ..() /obj/machinery/computer/cloning/proc/GetAvailablePod(mind = null) - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/pod = P - if(pod.occupant && pod.clonemind == mind) - return null - if(pod.is_operational() && !(pod.occupant || pod.mess)) - return pod + if(!pods) + return + for(var/P in pods) + var/obj/machinery/clonepod/pod = P + if(pod.occupant && pod.get_clone_mind == CLONEPOD_GET_MIND && pod.clonemind == mind) + return null + if(pod.is_operational() && !(pod.occupant || pod.mess)) + return pod /obj/machinery/computer/cloning/proc/HasEfficientPod() - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/pod = P - if(pod.is_operational() && pod.efficiency > 5) - return TRUE + if(!pods) + return + for(var/P in pods) + var/obj/machinery/clonepod/pod = P + if(pod.is_operational() && pod.efficiency > 5) + return TRUE /obj/machinery/computer/cloning/proc/GetAvailableEfficientPod(mind = null) - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/pod = P - if(pod.occupant && pod.clonemind == mind) - return pod - else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5) - . = pod + if(!pods) + return + for(var/P in pods) + var/obj/machinery/clonepod/pod = P + if(pod.occupant && pod.clonemind == mind) + return pod + else if(!. && pod.is_operational() && !(pod.occupant || pod.mess) && pod.efficiency > 5) + . = pod /obj/machinery/computer/cloning/process() if(!(scanner && LAZYLEN(pods) && autoprocess)) @@ -73,7 +78,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"], R.fields["bank_account"])) + if(pod.growclone(R.fields["ckey"], R.fields["name"], R.fields["UI"], R.fields["SE"], R.fields["mind"], R.fields["blood_type"], R.fields["mrace"], R.fields["features"], R.fields["factions"], R.fields["quirks"], R.fields["bank_account"], R.fields["traumas"])) temp = "[R.fields["name"]] => Cloning cycle in progress..." records -= R @@ -103,12 +108,10 @@ return null /obj/machinery/computer/cloning/proc/findcloner() - var/obj/machinery/clonepod/podf = null - + var/obj/machinery/clonepod/podf for(var/direction in GLOB.cardinals) - - podf = locate(/obj/machinery/clonepod, get_step(src, direction)) - if (!isnull(podf) && podf.is_operational()) + podf = locate(clonepod_type, get_step(src, direction)) + if(podf?.is_operational()) AttachCloner(podf) /obj/machinery/computer/cloning/proc/AttachCloner(obj/machinery/clonepod/pod) @@ -132,7 +135,7 @@ else if(istype(W, /obj/item/multitool)) var/obj/item/multitool/P = W - if(istype(P.buffer, /obj/machinery/clonepod)) + if(istype(P.buffer, clonepod_type)) if(get_area(P.buffer) != get_area(src)) to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-") P.buffer = null @@ -157,13 +160,14 @@ var/dat = "" dat += "Refresh" - if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL) - if(!autoprocess) - dat += "Autoclone" + if(use_records) + if(scanner && HasEfficientPod() && scanner.scan_level >= AUTOCLONING_MINIMAL_LEVEL) + if(!autoprocess) + dat += "Autoclone" + else + dat += "Stop autoclone" else - dat += "Stop autoclone" - else - dat += "Autoclone" + dat += "Autoclone" dat += "

    Cloning Pod Status

    " dat += "
    [temp] 
    " @@ -190,26 +194,29 @@ else if(loading) dat += "[scanner_occupant] => Scanning..." else - if(scanner_occupant.ckey != scantemp_ckey) - scantemp = "Ready to Scan" - scantemp_ckey = scanner_occupant.ckey + if(use_records) + if(scanner_occupant.ckey != scantemp_ckey) + scantemp = "Ready to Scan" + scantemp_ckey = scanner_occupant.ckey + else + scantemp = "Ready to Clone" dat += "[scanner_occupant] => [scantemp]" dat += "" if(scanner_occupant) - dat += "Start Scan" - dat += "
    [src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]" + dat += "[use_records ? "Start Scan" : "Clone"]" + dat += "
    [scanner.locked ? "Unlock Scanner" : "Lock Scanner"]" else - dat += "Start Scan" - - // Database - dat += "

    Database Functions

    " - if (src.records.len && src.records.len > 0) - dat += "View Records ([src.records.len])
    " - else - dat += "View Records (0)
    " - if (src.diskette) - dat += "Eject Disk
    " + dat += "[use_records ? "Start Scan" : "Clone"]" + if(use_records) + // Database + dat += "

    Database Functions

    " + if (src.records.len && src.records.len > 0) + dat += "View Records ([src.records.len])
    " + else + dat += "View Records (0)
    " + if (src.diskette) + dat += "Eject Disk
    " @@ -290,24 +297,19 @@ autoprocess = FALSE STOP_PROCESSING(SSmachines, src) playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + . = TRUE else if ((href_list["scan"]) && !isnull(scanner) && scanner.is_operational()) scantemp = "" - loading = 1 + loading = TRUE src.updateUsrDialog() playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) say("Initiating scan...") var/prev_locked = scanner.locked scanner.locked = TRUE - spawn(20) - src.scan_occupant(scanner.occupant) - - loading = 0 - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - scanner.locked = prev_locked - + addtimer(CALLBACK(src, .proc/finish_scan, scanner.occupant, prev_locked), 2 SECONDS) + . = TRUE //No locking an open scanner. else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational()) @@ -317,8 +319,17 @@ else scanner.locked = FALSE playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + . = TRUE - else if(href_list["view_rec"]) + + else if (href_list["refresh"]) + src.updateUsrDialog() + playsound(src, "terminal_type", 25, 0) + . = TRUE + + if(. || !use_records) + return + if(href_list["view_rec"]) playsound(src, "terminal_type", 25, 0) src.active_record = find_record("id", href_list["view_rec"], records) if(active_record) @@ -330,6 +341,7 @@ src.menu = 3 else src.temp = "Record missing." + . = TRUE else if (href_list["del_rec"]) if ((!src.active_record) || (src.menu < 3)) @@ -353,8 +365,9 @@ else src.temp = "Access Denied." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + . = TRUE - else if (href_list["disk"]) //Load or eject. + else if (href_list["disk"] && use_records) //Load or eject. switch(href_list["disk"]) if("load") if (!diskette || !istype(diskette.fields) || !diskette.fields["name"] || !diskette.fields) @@ -392,10 +405,7 @@ diskette.name = "data disk - '[src.diskette.fields["name"]]'" src.temp = "Save successful." playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - - else if (href_list["refresh"]) - src.updateUsrDialog() - playsound(src, "terminal_type", 25, 0) + . = TRUE else if (href_list["clone"]) var/datum/data/record/C = find_record("id", href_list["clone"], records) @@ -415,7 +425,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"], C.fields["bank_account"])) + else if(pod.growclone(C.fields["ckey"], C.fields["name"], C.fields["UI"], C.fields["SE"], C.fields["mind"], C.fields["blood_type"], C.fields["mrace"], C.fields["features"], C.fields["factions"], C.fields["quirks"], C.fields["bank_account"], C.fields["traumas"])) temp = "[C.fields["name"]] => Cloning cycle in progress..." playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) records.Remove(C) @@ -429,53 +439,49 @@ else temp = "Data corruption." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + . = TRUE - else if (href_list["menu"]) - src.menu = text2num(href_list["menu"]) + else if (href_list["menu"] && use_records) + menu = text2num(href_list["menu"]) playsound(src, "terminal_type", 25, 0) + . = TRUE +/obj/machinery/computer/cloning/proc/finish_scan(mob/living/L, prev_locked) + if(!scanner || !L) + return src.add_fingerprint(usr) src.updateUsrDialog() - return + + if(use_records) + scan_occupant(L) + else + clone_occupant(L) + + loading = FALSE + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + scanner.locked = prev_locked /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 + + // Do not use unless you know what they are. + var/mob/living/carbon/C = mob_occupant + var/mob/living/brain/B = mob_occupant + 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 - if(!istype(dna)) - scantemp = "Unable to locate valid genetic data." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if(mob_occupant.suiciding || mob_occupant.hellbound) - scantemp = "Subject's brain is not responding to scanning stimuli." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) - scantemp = "Subject no longer contains the fundamental materials required to create a living clone." - playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) - return - if ((!mob_occupant.ckey) || (!mob_occupant.client)) - scantemp = "Mental interface failure." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if (find_record("ckey", mob_occupant.ckey, records)) - 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) + if(!can_scan(dna, mob_occupant, FALSE, has_bank_account)) return + var/datum/data/record/R = new() if(dna.species) // We store the instance rather than the path, because some @@ -497,11 +503,17 @@ 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() + R.fields["traumas"] = list() + if(ishuman(mob_occupant)) + R.fields["traumas"] = C.get_traumas() + if(isbrain(mob_occupant)) + R.fields["traumas"] = B.get_traumas() + + R.fields["bank_account"] = has_bank_account if (!isnull(mob_occupant.mind)) //Save that mind so traitors can continue traitoring after cloning. R.fields["mind"] = "[REF(mob_occupant.mind)]" @@ -520,3 +532,78 @@ board.records = records scantemp = "Subject successfully scanned." playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + +//Used by the experimental cloning computer. +/obj/machinery/computer/cloning/proc/clone_occupant(occupant) + var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) + var/datum/dna/dna + if(ishuman(mob_occupant)) + var/mob/living/carbon/C = mob_occupant + dna = C.has_dna() + if(isbrain(mob_occupant)) + var/mob/living/brain/B = mob_occupant + dna = B.stored_dna + + if(!can_scan(dna, mob_occupant, TRUE)) + return + + var/clone_species + if(dna.species) + clone_species = dna.species + else + var/datum/species/rando_race = pick(GLOB.roundstart_races) + clone_species = rando_race.type + + var/obj/machinery/clonepod/pod = GetAvailablePod() + //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. + if(!LAZYLEN(pods)) + temp = "No Clonepods detected." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else if(!pod) + temp = "No Clonepods available." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else if(pod.occupant) + temp = "Cloning cycle already in progress." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + else + pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction) + temp = "[mob_occupant.real_name] => Cloning data sent to pod." + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + +/obj/machinery/computer/cloning/proc/can_scan(datum/dna/dna, mob/living/mob_occupant, experimental = FALSE, datum/bank_account/account) + if(!istype(dna)) + scantemp = "Unable to locate valid genetic data." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if(!experimental) + if(mob_occupant.suiciding || mob_occupant.hellbound) + scantemp = "Subject's brain is not responding to scanning stimuli." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) + scantemp = "Subject no longer contains the fundamental materials required to create a living clone." + playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) + return + if (!experimental) + if(!mob_occupant.ckey || !mob_occupant.client) + scantemp = "Mental interface failure." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if (find_record("ckey", mob_occupant.ckey, records)) + scantemp = "Subject already in database." + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + return + if(SSeconomy.full_ancap && !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 + return TRUE + +//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks. +/obj/machinery/computer/cloning/prototype + name = "prototype cloning console" + desc = "Used to operate an experimental cloner." + icon_screen = "dna" + icon_keyboard = "med_key" + circuit = /obj/item/circuitboard/computer/cloning/prototype + clonepod_type = /obj/machinery/clonepod/experimental diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 22bea14381..6a99b248e3 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -61,7 +61,7 @@ // main interface if("main") state = STATE_DEFAULT - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) if("login") var/mob/M = usr @@ -73,19 +73,19 @@ auth_id = "[I.registered_name] ([I.assignment])" if((ACCESS_CAPTAIN in I.access)) authenticated = 2 - playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) if(obj_flags & EMAGGED) authenticated = 2 auth_id = "Unknown" to_chat(M, "[src] lets out a quiet alarm as its login is overridden.") - playsound(src, 'sound/machines/terminal_on.ogg', 50, 0) - playsound(src, 'sound/machines/terminal_alert.ogg', 25, 0) + playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE) + playsound(src, 'sound/machines/terminal_alert.ogg', 25, FALSE) if(prob(25)) for(var/mob/living/silicon/ai/AI in active_ais()) SEND_SOUND(AI, sound('sound/machines/terminal_alert.ogg', volume = 10)) //Very quiet for balance reasons if("logout") authenticated = 0 - playsound(src, 'sound/machines/terminal_off.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE) if("swipeidseclevel") var/mob/M = usr @@ -109,7 +109,7 @@ security_level_cd = world.time + 15 SECONDS if(GLOB.security_level != old_level) to_chat(usr, "Authorization confirmed. Modifying security level.") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) //Only notify people if an actual change happened var/security_level = NUM2SECLEVEL(GLOB.security_level) log_game("[key_name(usr)] has changed the security level to [security_level] with [src] at [AREACOORD(usr)].") @@ -118,28 +118,28 @@ tmp_alertlevel = 0 else to_chat(usr, "You are not authorized to do this!") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) tmp_alertlevel = 0 state = STATE_DEFAULT else to_chat(usr, "You need to swipe your ID!") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) if("announce") if(authenticated==2) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE) make_announcement(usr) if("crossserver") if(authenticated==2) if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + to_chat(usr, "Arrays recycling. Please stand by.") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return var/input = stripped_multiline_input(usr, "Please choose a message to transmit to allied stations. Please be aware that this process is very expensive, and abuse will lead to... termination.", "Send a message to an allied station.", "") if(!input || !(usr in view(1,src)) || !checkCCcooldown()) return - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) send2otherserver("[station_name()]", input,"Comms_Console") minor_announce(input, title = "Outgoing message to allied station") usr.log_talk(input, LOG_SAY, tag="message to the other server") @@ -168,22 +168,18 @@ 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 - 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]") - M.unload_preview() - M.load_template(S) - M.existing_shuttle = SSshuttle.emergency - M.action_load(S) - message_admins("[S.name] loaded, purchased by [usr]") - else - to_chat(usr, "Something went wrong! The shuttle exchange system seems to be down.") + SSshuttle.shuttle_purchased = TRUE + SSshuttle.unload_preview() + SSshuttle.load_template(S) + SSshuttle.existing_shuttle = SSshuttle.emergency + SSshuttle.action_load(S) + 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].") + log_shuttle("[key_name(usr)] has purchased [S.name].") + SSblackbox.record_feedback("text", "shuttle_purchase", 1, "[S.name]") else - to_chat(usr, "Not enough credits.") + to_chat(usr, "Insufficient credits.") if("callshuttle") state = STATE_DEFAULT @@ -268,7 +264,7 @@ // Status display stuff if("setstat") - playsound(src, "terminal_type", 50, 0) + playsound(src, "terminal_type", 50, FALSE) switch(href_list["statdisp"]) if("message") post_status("message", stat_msg1, stat_msg2) @@ -308,13 +304,13 @@ if("MessageSyndicate") if((authenticated==2) && (obj_flags & EMAGGED)) if(!checkCCcooldown()) - to_chat(usr, "Arrays recycling. Please stand by.") - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) + to_chat(usr, "Arrays recycling. Please stand by.") + playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) return var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING COORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "Send a message to /??????/.", "") if(!input || !(usr in view(1,src)) || !checkCCcooldown()) return - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) Syndicate_announce(input, usr) to_chat(usr, "SYSERR @l(19833)of(transmit.dm): !@$ MESSAGE TRANSMITTED TO SYNDICATE COMMAND.") for(var/client/X in GLOB.admins) @@ -327,7 +323,7 @@ if("RestoreBackup") to_chat(usr, "Backup routing data restored!") - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) obj_flags &= ~EMAGGED updateDialog() @@ -341,7 +337,7 @@ return Nuke_request(input, usr) to_chat(usr, "Request sent.") - usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY) + usr.log_message("has requested the nuclear codes from CentCom with reason \"[input]\"", LOG_SAY) priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport") CM.lastTimeUsed = world.time @@ -448,7 +444,7 @@ if(authenticated == 1) authenticated = 2 to_chat(user, "You scramble the communication routing circuits!") - playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_alert.ogg', 50, FALSE) return TRUE /obj/machinery/computer/communications/ui_interact(mob/user) @@ -514,16 +510,16 @@ dat += "
    \[ Log In \]" if(STATE_CALLSHUTTLE) dat += get_call_shuttle_form() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE) if(STATE_CANCELSHUTTLE) dat += get_cancel_shuttle_form() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE) if(STATE_MESSAGELIST) dat += "Messages:" for(var/i in 1 to messages.len) var/datum/comm_message/M = messages[i] dat += "
    [M.title]" - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if(STATE_VIEWMESSAGE) if (currmsg) dat += "[currmsg.title]

    [currmsg.content]" @@ -557,7 +553,7 @@ dat += " Red Alert |" dat += " Lockdown |" dat += " Biohazard \]

    " - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) if(STATE_ALERT_LEVEL) dat += "Current alert level: [NUM2SECLEVEL(GLOB.security_level)]
    " if(GLOB.security_level == SEC_LEVEL_DELTA) @@ -571,7 +567,7 @@ dat += "Confirm the change to: [NUM2SECLEVEL(tmp_alertlevel)]
    " dat += "Swipe ID to confirm change.
    " if(STATE_TOGGLE_EMERGENCY) - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, FALSE) if(GLOB.emergency_access == 1) dat += "Emergency Maintenance Access is currently ENABLED" dat += "
    Restore maintenance access restrictions?
    \[ OK | Cancel \]" @@ -722,7 +718,7 @@ /obj/machinery/computer/communications/proc/make_announcement(mob/living/user, is_silicon) if(!SScommunications.can_announce(user, is_silicon)) - to_chat(user, "Intercomms recharging. Please stand by.") + to_chat(user, "Intercomms recharging. Please stand by.") return var/input = stripped_input(user, "Please choose a message to announce to the station crew.", "What?") if(!input || !user.canUseTopic(src)) diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 01a1d043a2..19da4f75d8 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -76,11 +76,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) /datum/crewmonitor/Destroy() return ..() -/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/crewmonitor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if (!ui) - ui = new(user, src, ui_key, "crew", "crew monitor", 800, 600 , master_ui, state) + ui = new(user, src, "CrewConsole") ui.open() /datum/crewmonitor/proc/show(mob/M, source) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index d465ff2022..286c106788 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -1,25 +1,41 @@ +/// Base timeout for creating mutation activators and other injectors #define INJECTOR_TIMEOUT 100 +/// Maximum number of genetic makeup storage slots in DNA Console #define NUMBER_OF_BUFFERS 3 +/// Timeout for DNA Scramble in DNA Consoles #define SCRAMBLE_TIMEOUT 600 -#define JOKER_TIMEOUT 12000 //20 minutes -#define JOKER_UPGRADE 1800 +/// Timeout for using the Joker feature to solve a gene in DNA Console +#define JOKER_TIMEOUT 12000 +/// How much time DNA Scanner upgrade tiers remove from JOKER_TIMEOUT +#define JOKER_UPGRADE 3000 +/// Maximum value for radiaton strength when pulsing enzymes #define RADIATION_STRENGTH_MAX 15 -#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has more range +/// Larger multipliers will affect the range of values when pulsing enzymes +#define RADIATION_STRENGTH_MULTIPLIER 1 +/// Maximum value for the radiation pulse duration when pulsing enzymes #define RADIATION_DURATION_MAX 30 -#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate +/// Large values reduce pulse accuracy and may pulse other enzymes than selected +#define RADIATION_ACCURACY_MULTIPLIER 3 +/// Special status indicating a scanner occupant is transforming eg. from monkey to human +#define STATUS_TRANSFORMING 4 -#define RADIATION_IRRADIATION_MULTIPLIER 1 //multiplier for how much radiation a test subject receives +/// Multiplier for how much radiation received from DNA Console functionality +#define RADIATION_IRRADIATION_MULTIPLIER 1 -#define SCANNER_ACTION_SE 1 -#define SCANNER_ACTION_UI 2 -#define SCANNER_ACTION_UE 3 -#define SCANNER_ACTION_MIXED 4 +/// Flag for the mutation ref search system. Search will include scanner occupant +#define SEARCH_OCCUPANT 1 +/// Flag for the mutation ref search system. Search will include console storage +#define SEARCH_STORED 2 +/// Flag for the mutation ref search system. Search will include diskette storage +#define SEARCH_DISKETTE 4 +/// Flag for the mutation ref search system. Search will include advanced injector mutations +#define SEARCH_ADV_INJ 8 /obj/machinery/computer/scan_consolenew - name = "\improper DNA scanner access console" + name = "DNA Console" desc = "Scan DNA." icon_screen = "dna" icon_keyboard = "med_key" @@ -31,47 +47,103 @@ active_power_usage = 400 light_color = LIGHT_COLOR_BLUE + /// Link to the techweb's stored research. Used to retrieve stored mutations var/datum/techweb/stored_research + /// Maximum number of mutations that DNA Consoles are able to store var/max_storage = 6 - var/combine + /// Duration for enzyme radiation pulses var/radduration = 2 + /// Strength for enzyme radiation pulses var/radstrength = 1 + /// Maximum number of chromosomes that DNA Consoles are able to store. var/max_chromosomes = 6 - - ///Amount of mutations we can store - var/list/buffer[NUMBER_OF_BUFFERS] - ///mutations we have stored + /// Maximum number of enzymes we can store + var/list/genetic_makeup_buffer[NUMBER_OF_BUFFERS] + /// List of all mutations stored on the DNA Console var/list/stored_mutations = list() - ///chromosomes we have stored + /// List of all chromosomes stored in the DNA Console var/list/stored_chromosomes = list() - ///combinations of injectors for the 'injector selection'. format is list("Elsa" = list(Cryokinesis, Geladikinesis), "The Hulk" = list(Hulk, Gigantism), etc) Glowy and the gang being an initialized datum - var/list/injector_selection = list() - ///max amount of selections you can make + /// Assoc list of all advanced injectors. Keys are injector names. Values are lists of mutations. + var/list/list/injector_selection = list() + /// Maximum number of advanced injectors that DNA Consoles store var/max_injector_selections = 2 - ///hard-cap on the advanced dna injector + /// Maximum number of mutation that an advanced injector can store var/max_injector_mutations = 10 - ///the max instability of the advanced injector. + /// Maximum total instability of all combined mutations allowed on an advanced injector var/max_injector_instability = 50 - var/injectorready = 0 //world timer cooldown var + /// World time when injectors are ready to be printed + var/injectorready = 0 + /// World time when JOKER algorithm can be used in DNA Consoles var/jokerready = 0 + /// World time when Scramble can be used in DNA Consoles var/scrambleready = 0 - var/current_screen = "mainmenu" - var/current_mutation //what block are we inspecting? only used when screen = "info" - var/current_storage //what storage block are we looking at? - var/obj/machinery/dna_scannernew/connected = null + + /// Currently stored genetic data diskette var/obj/item/disk/data/diskette = null + + /// Current delayed action, used for delayed enzyme transfer on scanner door close var/list/delayed_action = null + /// Index of the enzyme being modified during delayed enzyme pulse operations + var/rad_pulse_index = 0 + /// World time when the enzyme pulse should complete + var/rad_pulse_timer = 0 + + /// Used for setting tgui data - Whether the connected DNA Scanner is usable + var/can_use_scanner = FALSE + /// Used for setting tgui data - Whether the current DNA Scanner occupant is viable for genetic modification + var/is_viable_occupant = FALSE + /// Used for setting tgui data - Whether Scramble DNA is ready + var/is_scramble_ready = FALSE + /// Used for setting tgui data - Whether JOKER algorithm is ready + var/is_joker_ready = FALSE + /// Used for setting tgui data - Whether injectors are ready to be printed + var/is_injector_ready = FALSE + /// Used for setting tgui data - Wheher an enzyme pulse operation is ongoing + var/is_pulsing_rads = FALSE + /// Used for setting tgui data - Time until scramble is ready + var/time_to_scramble = 0 + /// Used for setting tgui data - Time until joker is ready + var/time_to_joker = 0 + /// Used for setting tgui data - Time until injectors are ready + var/time_to_injector = 0 + /// Used for setting tgui data - Time until the enzyme pulse is complete + var/time_to_pulse = 0 + + /// Currently connected DNA Scanner + var/obj/machinery/dna_scannernew/connected_scanner = null + /// Current DNA Scanner occupant + var/mob/living/carbon/scanner_occupant = null + + /// Used for setting tgui data - List of occupant mutations + var/list/tgui_occupant_mutations = list() + /// Used for setting tgui data - List of DNA Console stored mutations + var/list/tgui_console_mutations = list() + /// Used for setting tgui data - List of diskette stored mutations + var/list/tgui_diskette_mutations = list() + /// Used for setting tgui data - List of DNA Console chromosomes + var/list/tgui_console_chromosomes = list() + /// Used for setting tgui data - List of occupant mutations + var/list/tgui_genetic_makeup = list() + /// Used for setting tgui data - List of occupant mutations + var/list/tgui_advinjector_mutations = list() + + + /// State of tgui view, i.e. which tab is currently active, or which genome we're currently looking at. + var/list/list/tgui_view_state = list() + +/obj/machinery/computer/scan_consolenew/process() + . = ..() + + // This is for pulsing the UI element with radiation as part of genetic makeup + // If rad_pulse_index > 0 then it means we're attempting a rad pulse + if((rad_pulse_index > 0) && (rad_pulse_timer <= world.time)) + rad_pulse() + return + /obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params) - if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES - if (!src.diskette) - if (!user.transferItemToLoc(I,src)) - return - src.diskette = I - to_chat(user, "You insert [I].") - src.updateUsrDialog() - return + // Store chromosomes in the console if there's room if (istype(I, /obj/item/chromosome)) if(LAZYLEN(stored_chromosomes) < max_chromosomes) I.forceMove(src) @@ -80,856 +152,1794 @@ else to_chat(user, "You cannot store any more chromosomes!") return + + // Insert data disk if console disk slot is empty + // Swap data disk if there is one already a disk in the console + if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES + // Insert disk into DNA Console + if (!user.transferItemToLoc(I,src)) + return + // If insertion was successful and there's already a diskette in the console, eject the old one. + if(diskette) + eject_disk(user) + // Set the new diskette. + diskette = I + to_chat(user, "You insert [I].") + return + + // Recycle non-activator used injectors + // Turn activator used injectors (aka research injectors) to chromosomes if(istype(I, /obj/item/dnainjector/activator)) var/obj/item/dnainjector/activator/A = I if(A.used) to_chat(user,"Recycled [I].") if(A.research) - var/c_typepath = generate_chromosome() - var/obj/item/chromosome/CM = new c_typepath (drop_location()) - to_chat(user,"Recycled [I].") - if((LAZYLEN(stored_chromosomes) < max_chromosomes) && prob(60)) - CM.forceMove(src) - stored_chromosomes += CM - to_chat(user,"[capitalize(CM.name)] added to storage.") + if(prob(60)) + var/c_typepath = generate_chromosome() + var/obj/item/chromosome/CM = new c_typepath (drop_location()) + if(LAZYLEN(stored_chromosomes) < max_chromosomes) + CM.forceMove(src) + stored_chromosomes += CM + to_chat(user,"[capitalize(CM.name)] added to storage.") + else + to_chat(user, "You cannot store any more chromosomes!") + to_chat(user, "[capitalize(CM.name)] added on top of the console.") + else + to_chat(user, "There was not enough genetic data to extract a viable chromosome.") qdel(I) return - else - return ..() + + return ..() + + +/obj/machinery/computer/scan_consolenew/AltClick(mob/user) + // Make sure the user can interact with the machine. + if(!user.canUseTopic(src, !issilicon(user))) + return + + eject_disk(user) /obj/machinery/computer/scan_consolenew/Initialize() . = ..() - for(var/direction in GLOB.cardinals) - connected = locate(/obj/machinery/dna_scannernew, get_step(src, direction)) - if(!isnull(connected)) - break + + // Connect with a nearby DNA Scanner on init + connect_to_scanner() + + // Set appropriate ready timers and limits for machines functions injectorready = world.time + INJECTOR_TIMEOUT scrambleready = world.time + SCRAMBLE_TIMEOUT jokerready = world.time + JOKER_TIMEOUT + // Set the default tgui state + set_default_state() + + // Link machine with research techweb. Used for discovering and accessing + // already discovered mutations stored_research = SSresearch.science_tech /obj/machinery/computer/scan_consolenew/examine(mob/user) . = ..() - if(jokerready < world.time) - . += "JOKER algorithm available." + +/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui) + // Most of ui_interact is spent setting variables for passing to the tgui + // interface. + // We can also do some general state processing here too as it's a good + // indication that a player is using the console. + + var/scanner_op = scanner_operational() + var/can_modify_occ = can_modify_occupant() + + // Check for connected AND operational scanner. + if(scanner_op) + can_use_scanner = TRUE else - . += "JOKER algorithm available in about [round(0.00166666667 * (jokerready - world.time))] minutes." + can_use_scanner = FALSE + connected_scanner = null + is_viable_occupant = FALSE -/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, last_change) - . = ..() - if(!user) - return - var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window - if(user.client) - var/datum/asset/simple/assets = get_asset_datum(/datum/asset/simple/genetics) - assets.send(user.client) - if(!(in_range(src, user) || hasSiliconAccessInArea(user))) - popup.close() - return - popup.add_stylesheet("scannernew", 'html/browser/scannernew.css') + // Check for a viable occupant in the scanner. + if(can_modify_occ) + is_viable_occupant = TRUE + else + is_viable_occupant = FALSE - var/mob/living/carbon/viable_occupant - var/list/occupant_status = list("
    Subject Status:
    ") - var/scanner_status - var/list/temp_html = list() - if(connected && connected.is_operational()) - if(connected.occupant) //set occupant_status message - viable_occupant = connected.occupant - if(viable_occupant.has_dna() && !HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification - occupant_status += "[viable_occupant.name] => " - switch(viable_occupant.stat) - if(CONSCIOUS) - occupant_status += "Conscious" - if(UNCONSCIOUS) - occupant_status += "Unconscious" - else - occupant_status += "DEAD" - occupant_status += "
    " - occupant_status += "
    Health:
    [viable_occupant.health] %
    " - occupant_status += "
    Radiation Level:
    [viable_occupant.radiation/(RAD_MOB_SAFE/100)] %
    " - occupant_status += "
    Unique Enzymes :
    [viable_occupant.dna.unique_enzymes]
    " - occupant_status += "
    Last Operation:
    [last_change ? last_change : "----"]
    " + + // Populates various buffers for passing to tgui + build_mutation_list(can_modify_occ) + build_genetic_makeup_list() + + // Populate variables for passing to tgui interface + is_scramble_ready = (scrambleready < world.time) + time_to_scramble = round((scrambleready - world.time)/10) + + is_joker_ready = (jokerready < world.time) + time_to_joker = round((jokerready - world.time)/10) + + is_injector_ready = (injectorready < world.time) + time_to_injector = round((injectorready - world.time)/10) + + is_pulsing_rads = ((rad_pulse_index > 0) && (rad_pulse_timer > world.time)) + time_to_pulse = round((rad_pulse_timer - world.time)/10) + + // Attempt to update tgui ui, open and update if needed. + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "DnaConsole") + ui.open() + +/obj/machinery/computer/scan_consolenew/ui_data(mob/user) + var/list/data = list() + + data["view"] = tgui_view_state + data["storage"] = list() + + // This block of code generates the huge data structure passed to the tgui + // interface for displaying all the various bits of console/scanner data + // Should all be very self-explanatory + data["isScannerConnected"] = can_use_scanner + if(can_use_scanner) + data["scannerOpen"] = connected_scanner.state_open + data["scannerLocked"] = connected_scanner.locked + data["radStrength"] = radstrength + data["radDuration"] = radduration + data["stdDevStr"] = radstrength * RADIATION_STRENGTH_MULTIPLIER + switch(RADIATION_ACCURACY_MULTIPLIER / (radduration + (connected_scanner.precision_coeff ** 2))) //hardcoded values from a z-table for a normal distribution + if(0 to 0.25) + data["stdDevAcc"] = ">95 %" + if(0.25 to 0.5) + data["stdDevAcc"] = "68-95 %" + if(0.5 to 0.75) + data["stdDevAcc"] = "55-68 %" else - viable_occupant = null - occupant_status += "Invalid DNA structure" + data["stdDevAcc"] = "<38 %" + + data["isViableSubject"] = is_viable_occupant + if(is_viable_occupant) + data["subjectName"] = scanner_occupant.name + if(scanner_occupant.transformation_timer) + data["subjectStatus"] = STATUS_TRANSFORMING else - occupant_status += "No subject detected" - - if(connected.state_open) - scanner_status = "Open" - else - scanner_status = "Closed" - if(connected.locked) - scanner_status += "(Locked)" - else - scanner_status += "(Unlocked)" - - + data["subjectStatus"] = scanner_occupant.stat + data["subjectHealth"] = scanner_occupant.health + data["subjectRads"] = scanner_occupant.radiation/(RAD_MOB_SAFE/100) + data["subjectEnzymes"] = scanner_occupant.dna.unique_enzymes + data["isMonkey"] = ismonkey(scanner_occupant) + data["subjectUNI"] = scanner_occupant.dna.uni_identity + data["storage"]["occupant"] = tgui_occupant_mutations + //data["subjectMutations"] = tgui_occupant_mutations else - occupant_status += "----" - scanner_status += "Error: No scanner detected" + data["subjectName"] = null + data["subjectStatus"] = null + data["subjectHealth"] = null + data["subjectRads"] = null + data["subjectEnzymes"] = null + //data["subjectMutations"] = null + data["storage"]["occupant"] = null - var/list/status = list("
    ") - status += "
    Scanner:
    [scanner_status]
    " - status += occupant_status + data["hasDelayedAction"] = (delayed_action != null) + data["isScrambleReady"] = is_scramble_ready + data["isJokerReady"] = is_joker_ready + data["isInjectorReady"] = is_injector_ready + data["scrambleSeconds"] = time_to_scramble + data["jokerSeconds"] = time_to_joker + data["injectorSeconds"] = time_to_injector + data["isPulsingRads"] = is_pulsing_rads + data["radPulseSeconds"] = time_to_pulse + if(diskette != null) + data["hasDisk"] = TRUE + data["diskCapacity"] = diskette.max_mutations - LAZYLEN(diskette.mutations) + data["diskReadOnly"] = diskette.read_only + //data["diskMutations"] = tgui_diskette_mutations + data["storage"]["disk"] = tgui_diskette_mutations + data["diskHasMakeup"] = (LAZYLEN(diskette.genetic_makeup_buffer) > 0) + data["diskMakeupBuffer"] = diskette.genetic_makeup_buffer.Copy() + else + data["hasDisk"] = FALSE + data["diskCapacity"] = 0 + data["diskReadOnly"] = TRUE + //data["diskMutations"] = null + data["storage"]["disk"] = null + data["diskHasMakeup"] = FALSE + data["diskMakeupBuffer"] = null - status += "

    Radiation Emitter Status

    " - var/stddev = radstrength*RADIATION_STRENGTH_MULTIPLIER - status += "
    Output Level:
    [radstrength]
    " - status += "
      \> Mutation:
    (-[stddev] to +[stddev] = 68 %) (-[2*stddev] to +[2*stddev] = 95 %)
    " - if(connected) - stddev = RADIATION_ACCURACY_MULTIPLIER/(radduration + (connected.precision_coeff ** 2)) - else - stddev = RADIATION_ACCURACY_MULTIPLIER/radduration - var/chance_to_hit - switch(stddev) //hardcoded values from a z-table for a normal distribution - if(0 to 0.25) - chance_to_hit = ">95 %" - if(0.25 to 0.5) - chance_to_hit = "68-95 %" - if(0.5 to 0.75) - chance_to_hit = "55-68 %" - else - chance_to_hit = "<38 %" - status += "
    Pulse Duration:
    [radduration]
    " - status += "
      \> Accuracy:
    [chance_to_hit]
    " - status += "
    " // Close statusDisplay div - var/list/buttons = list("Scan") - if(connected) - buttons += "[connected.state_open ? "Close" : "Open"] Scanner" - if (connected.state_open) - buttons += "[connected.locked ? "Unlock" : "Lock"] Scanner" - else - buttons += "[connected.locked ? "Unlock" : "Lock"] Scanner" - else - buttons += "Open Scanner Lock Scanner" - if(viable_occupant && (scrambleready < world.time)) - buttons += "Scramble DNA" - else - buttons += "Scramble DNA" - if(diskette) - buttons += "Disk" - else - buttons += "Disk" - if(current_screen == "mutations") - buttons += "Mutations" - else - buttons += "Mutations" - if((current_screen == "mainmenu") || !current_screen) - buttons += "Genetic Sequencer" - else - buttons += "Genetic Sequencer" - if(current_screen == "ui") - buttons += "Unique Identifiers" - else - buttons += "Unique Identifiers" - if(current_screen == "advinjector") - buttons += "Adv. Injectors" - else - buttons += "Adv. Injectors" - switch(current_screen) - if("working") - temp_html += status - temp_html += "

    System Busy

    " - temp_html += "Working ... Please wait ([DisplayTimeText(radduration*10)])" - if("ui") - temp_html += status - temp_html += buttons - temp_html += "

    Unique Identifiers

    " - temp_html += "-- Output Level ++" - temp_html += "
    -- Pulse Duration ++" - temp_html += "

    Irradiate Subject

    " - temp_html += "
    Unique Identifier:
    " - var/max_line_len = 7*DNA_BLOCK_SIZE - if(viable_occupant) - temp_html += "
    1
    " - var/char = "" - var/ui_text = viable_occupant.dna.uni_identity - var/len_byte = length(ui_text) - var/char_it = 0 - for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char)) - char_it++ - char = ui_text[byte_it] - temp_html += "[char]" - if((char_it % max_line_len) == 0) - temp_html += "
    " - if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte) - temp_html += "
    [(char_it / DNA_BLOCK_SIZE) + 1]
    " - else - temp_html += "---------" - temp_html += "

    Buffer Menu

    " + data["mutationCapacity"] = max_storage - LAZYLEN(stored_mutations) + //data["mutationStorage"] = tgui_console_mutations + data["storage"]["console"] = tgui_console_mutations + data["chromoCapacity"] = max_chromosomes - LAZYLEN(stored_chromosomes) + data["chromoStorage"] = tgui_console_chromosomes + data["makeupCapacity"] = NUMBER_OF_BUFFERS + data["makeupStorage"] = tgui_genetic_makeup - if(istype(buffer)) - for(var/i=1, i<=buffer.len, i++) - temp_html += "
    Slot [i]: " - var/list/buffer_slot = buffer[i] - if( !buffer_slot || !buffer_slot.len || !buffer_slot["name"] || !((buffer_slot["UI"] && buffer_slot["UE"]) || buffer_slot["SE"]) ) - temp_html += "
    \tNo Data" - if(viable_occupant) - temp_html += "
    Save to Buffer" - else - temp_html += "
    Save to Buffer" - temp_html += "Clear Buffer" - if(diskette) - temp_html += "Load from Disk" - else - temp_html += "Load from Disk" - temp_html += "Save to Disk" - else - var/ui = buffer_slot["UI"] - var/ue = buffer_slot["UE"] - var/name = buffer_slot["name"] - var/label = buffer_slot["label"] - var/blood_type = buffer_slot["blood_type"] - temp_html += "
    \tLabel: [label ? label : name]" - temp_html += "
    \tSubject: [name]" - if(ue && name && blood_type) - temp_html += "
    \tBlood Type: [blood_type]" - temp_html += "
    \tUE: [ue] " - if(viable_occupant) - temp_html += "Occupant" - else - temp_html += "Occupant" - temp_html += "Occupant:Delayed" - if(injectorready < world.time) - temp_html += "Injector" - else - temp_html += "Injector" - else - temp_html += "
    \tBlood Type: No Data" - temp_html += "
    \tUE: No Data" - if(ui) - temp_html += "
    \tUI: [ui] " - if(viable_occupant) - temp_html += "Occupant" - else - temp_html += "Occupant" - temp_html += "Occupant:Delayed" - if(injectorready < world.time) - temp_html += "Injector" - else - temp_html += "Injector" - else - temp_html += "
    \tUI: No Data" - if(ue && name && blood_type && ui) - temp_html += "
    \tUI+UE: [ui]/[ue] " - if(viable_occupant) - temp_html += "Occupant" - else - temp_html += "Occupant" - temp_html += "Occupant:Delayed" - if(injectorready < world.time) - temp_html += "UI+UE Injector" - else - temp_html += "UI+UE Injector" - if(viable_occupant) - temp_html += "
    Save to Buffer" - else - temp_html += "
    Save to Buffer" - temp_html += "Clear Buffer" - if(diskette) - temp_html += "Load from Disk" - else - temp_html += "Load from Disk" - if(diskette && !diskette.read_only) - temp_html += "Save to Disk" - else - temp_html += "Save to Disk" - if("disk") - temp_html += status - temp_html += buttons - if(diskette) - temp_html += "

    [diskette.name]


    " - temp_html += "Eject Disk
    " - if(LAZYLEN(diskette.mutations)) - temp_html += "" - for(var/datum/mutation/human/A in diskette.mutations) - temp_html += "" - temp_html += "" - if(LAZYLEN(stored_mutations) < max_storage) - temp_html += "" - else - temp_html += "" - temp_html += "" - temp_html += "
    [A.name]DeleteImportImport
    " - else - temp_html += "
    Load diskette to start ----------" - if("info") - if(LAZYLEN(stored_mutations)) - if(LAZYLEN(stored_mutations) >= current_storage) - var/datum/mutation/human/HM = stored_mutations[current_storage] - if(HM) - temp_html += display_sequence(HM.type, current_storage) - else - current_screen = "mainmenu" - if("mutations") - temp_html += status - temp_html += buttons - temp_html += "

    Mutation Storage:

    " - temp_html += "" - for(var/datum/mutation/human/HM in stored_mutations) - var/i = stored_mutations.Find(HM) - temp_html += "" - temp_html += "" - temp_html += "" - if(combine == HM.type) - temp_html += "" - else - temp_html += "" - temp_html += "
    [HM.name]ExportDeleteCombine
    Combine

    " - temp_html += "

    Chromosome Storage:

    " - temp_html += "" - for(var/i in 1 to stored_chromosomes.len) - var/obj/item/chromosome/CM = stored_chromosomes[i] - temp_html += "
    " - temp_html += "
    [CM.name]
    " - if("advinjector") - temp_html += status - temp_html += buttons - temp_html += "
    Advanced Injectors:

    " - temp_html += "" - for(var/A in injector_selection) - temp_html += "
    [A]" - var/list/true_selection = injector_selection[A] - temp_html += "
    " - for(var/B in true_selection) - var/datum/mutation/human/HM = B - var/mutcolor - switch(HM.quality) - if(POSITIVE) - mutcolor = "good" - if(MINOR_NEGATIVE) - mutcolor = "average" - if(NEGATIVE) - mutcolor = "bad" - temp_html += "
    [HM.name] " - temp_html += "Remove
    " - if (injectorready < world.time) - temp_html += "
    Print Advanced Injector" - else - temp_html += "
    Print Advanced Injector" - temp_html += "Remove Injector
    " - temp_html += "
    " - else - temp_html += status - temp_html += buttons - temp_html += "
    Genetic Sequence:

    " - if(viable_occupant) - if(viable_occupant) - for(var/A in get_mutation_list()) - temp_html += display_inactive_sequence(A) - temp_html += "
    " - else - temp_html += "----" - if(viable_occupant && (current_mutation in get_mutation_list(viable_occupant))) - temp_html += display_sequence(current_mutation) - temp_html += "

    " - else - temp_html += "----------" + //data["advInjectors"] = tgui_advinjector_mutations + data["storage"]["injector"] = tgui_advinjector_mutations + data["maxAdvInjectors"] = max_injector_selections - popup.set_content(temp_html.Join()) - popup.open() + return data -/obj/machinery/computer/scan_consolenew/proc/display_inactive_sequence(mutation) - var/temp_html = "" - var/class = "unselected" - var/mob/living/carbon/viable_occupant = get_viable_occupant() - if(!viable_occupant) - return - - var/location = viable_occupant.dna.mutation_index.Find(mutation) //We do this because we dont want people using sysexp or similair tools to just read the mutations. - - if(!location) //Do this only when needed, dont make a list with mutations for every iteration if you dont need to - var/list/mutations = get_mutation_list(TRUE) - if(mutation in mutations) - location = mutations.Find(mutation) - if(mutation == current_mutation) - class = "selected" - if(location > DNA_MUTATION_BLOCKS) - temp_html += "Extra Mutation" - else if(mutation in stored_research.discovered_mutations) - temp_html += "Discovered Mutation" - else - temp_html += "Undiscovered" - return temp_html - -/obj/machinery/computer/scan_consolenew/proc/display_sequence(mutation, storage_slot) //Storage slot is for when viewing from the stored mutations - var/temp_html = "" - if(!mutation) - temp_html += "ERR-" - return - var/mut_name = "Unknown gene" - var/mut_desc = "No information available." - var/alias - var/discovered = FALSE - var/active = FALSE - var/scrambled = FALSE - var/instability - var/mob/living/carbon/viable_occupant = get_viable_occupant() - var/datum/mutation/human/HM = get_valid_mutation(mutation) - - if(viable_occupant) - var/datum/mutation/human/M = viable_occupant.dna.get_mutation(mutation) - if(M) - scrambled = M.scrambled - active = TRUE - var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(mutation) - alias = A.alias - if(active && !scrambled) - discover(mutation) - if(stored_research && (mutation in stored_research.discovered_mutations)) - mut_name = A.name - mut_desc = A.desc - discovered = TRUE - instability = A.instability - var/extra - if(viable_occupant && !(storage_slot || viable_occupant.dna.mutation_in_sequence(mutation))) - extra = TRUE - - if(discovered && !scrambled) - var/mutcolor - switch(A.quality) - if(POSITIVE) - mutcolor = "good" - if(MINOR_NEGATIVE) - mutcolor = "average" - if(NEGATIVE) - mutcolor = "bad" - if(HM) - instability *= GET_MUTATION_STABILIZER(HM) - temp_html += "
    [mut_name] ([alias])
    " - temp_html += "
    Instability : [round(instability)]
    " - else - temp_html += "
    [alias]
    " - temp_html += "
    [mut_desc]
    " - if(active && !storage_slot) - if(HM?.can_chromosome && (HM in viable_occupant.dna.mutations)) - var/i = viable_occupant.dna.mutations.Find(HM) - var/chromosome_name = "----" - if(HM.chromosome_name) - chromosome_name = HM.chromosome_name - temp_html += "
    Chromosome status: [chromosome_name]
    " - temp_html += "
    Sequence:

    " - if(!scrambled) - for(var/block in 1 to A.blocks) - var/whole_sequence = get_valid_gene_string(mutation) - var/sequence = copytext(whole_sequence, 1+(block-1)*(DNA_SEQUENCE_LENGTH*2),(DNA_SEQUENCE_LENGTH*2*block+1)) - temp_html += "
    " - for(var/i in 1 to DNA_SEQUENCE_LENGTH) - var/num = 1+(i-1)*2 - var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1)) - temp_html += "" - temp_html += "" - for(var/i in 1 to DNA_SEQUENCE_LENGTH) - temp_html += "" - temp_html += "" - for(var/i in 1 to DNA_SEQUENCE_LENGTH) - var/num = i*2 - var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1)) - temp_html += "" - temp_html += "
    |
    " - temp_html += "




    " - else - temp_html = "
    Sequence unreadable due to unpredictable mutation.
    " - if((active || storage_slot) && (injectorready < world.time) && !scrambled) - temp_html += "Print Activator" - temp_html += "Print Mutator" - else - temp_html += "Print Activator" - temp_html += "Print Mutator" - temp_html += "
    " - if(storage_slot) - temp_html += "Delete" - if((LAZYLEN(stored_mutations) < max_storage) && diskette && !diskette.read_only) - temp_html += "Export" - else - temp_html += "Export" - temp_html += "Back" - else if(active && !scrambled) - temp_html += "Store" - temp_html += "Adv. Injector" - if(extra || scrambled) - temp_html += "Nullify" - else - temp_html += "Nullify" - temp_html += "
    " - return temp_html - -/obj/machinery/computer/scan_consolenew/Topic(href, href_list) +/obj/machinery/computer/scan_consolenew/ui_act(action, var/list/params) if(..()) - return - if(!isturf(usr.loc)) - return - if(!((isturf(loc) && in_range(src, usr)) || hasSiliconAccessInArea(usr))) - return - if(current_screen == "working") - return + return TRUE + + . = TRUE add_fingerprint(usr) usr.set_machine(src) - var/mob/living/carbon/viable_occupant = get_viable_occupant() + switch(action) + // Connect this DNA Console to a nearby DNA Scanner + // Usually only activate as an option if there is no connected scanner + if("connect_scanner") + connect_to_scanner() + return - //Basic Tasks/////////////////////////////////////////// - var/num = round(text2num(href_list["num"])) - var/last_change - switch(href_list["task"]) - if("togglelock") - if(connected) - connected.locked = !connected.locked - if("toggleopen") - if(connected) - connected.toggle_open(usr) - if("setduration") - if(!num) - num = round(input(usr, "Choose pulse duration:", "Input an Integer", null) as num|null) - if(num) - radduration = WRAP(num, 1, RADIATION_DURATION_MAX+1) - if("setstrength") - if(!num) - num = round(input(usr, "Choose pulse strength:", "Input an Integer", null) as num|null) - if(num) - radstrength = WRAP(num, 1, RADIATION_STRENGTH_MAX+1) - if("screen") - current_screen = href_list["text"] - if("scramble") - if(viable_occupant && (scrambleready < world.time)) - viable_occupant.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA)) - viable_occupant.dna.generate_dna_blocks() - scrambleready = world.time + SCRAMBLE_TIMEOUT - to_chat(usr,"DNA scrambled.") - viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER*50/(connected.damage_coeff ** 2) - if("setbufferlabel") - var/text = sanitize(input(usr, "Input a new label:", "Input a Text", null) as text|null) - if(num && text) - num = clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - buffer_slot["label"] = text - if("setbuffer") - if(num && viable_occupant) - num = clamp(num, 1, NUMBER_OF_BUFFERS) - buffer[num] = list( - "label"="Buffer[num]:[viable_occupant.real_name]", - "UI"=viable_occupant.dna.uni_identity, - "UE"=viable_occupant.dna.unique_enzymes, - "name"=viable_occupant.real_name, - "blood_type"=viable_occupant.dna.blood_type - ) - if("clearbuffer") - if(num) - num = clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - buffer_slot.Cut() - if("transferbuffer") - if(num && viable_occupant) - switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove - if("ui") - apply_buffer(SCANNER_ACTION_UI,num) - if("ue") - apply_buffer(SCANNER_ACTION_UE,num) - if("mixed") - apply_buffer(SCANNER_ACTION_MIXED,num) - if("injector") - if(num && injectorready < world.time) - num = clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - var/obj/item/dnainjector/timed/I - switch(href_list["text"]) - if("ui") - if(buffer_slot["UI"]) - I = new /obj/item/dnainjector/timed(loc) - I.fields = list("UI"=buffer_slot["UI"]) - if(connected) - I.damage_coeff = connected.damage_coeff - if("ue") - if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) - I = new /obj/item/dnainjector/timed(loc) - I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) - if(connected) - I.damage_coeff = connected.damage_coeff - if("mixed") - if(buffer_slot["UI"] && buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) - I = new /obj/item/dnainjector/timed(loc) - I.fields = list("UI"=buffer_slot["UI"],"name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) - if(connected) - I.damage_coeff = connected.damage_coeff - if(I) - injectorready = world.time + INJECTOR_TIMEOUT - if("loaddisk") - if(num && diskette && diskette.fields) - num = clamp(num, 1, NUMBER_OF_BUFFERS) - buffer[num] = diskette.fields.Copy() - if("savedisk") - if(num && diskette && !diskette.read_only) - num = clamp(num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[num] - if(istype(buffer_slot)) - diskette.name = "data disk \[[buffer_slot["label"]]\]" - diskette.fields = buffer_slot.Copy() - if("ejectdisk") - if(diskette) - diskette.forceMove(drop_location()) - diskette = null - if("setdelayed") - if(num) - delayed_action = list("action"=text2num(href_list["delayaction"]),"buffer"=num) - if("pulseui") - if(num && viable_occupant && connected) - radduration = WRAP(radduration, 1, RADIATION_DURATION_MAX+1) - radstrength = WRAP(radstrength, 1, RADIATION_STRENGTH_MAX+1) + // Toggle the door open/closed status on attached DNA Scanner + if("toggle_door") + // GUARD CHECK - Scanner still connected and operational? + if(!scanner_operational()) + return - var/locked_state = connected.locked - connected.locked = TRUE + connected_scanner.toggle_open(usr) + return - current_screen = "working" - ui_interact(usr) + // Toggle the door bolts on the attached DNA Scanner + if("toggle_lock") + // GUARD CHECK - Scanner still connected and operational? + if(!scanner_operational()) + return - sleep(radduration*10) - current_screen = "ui" + connected_scanner.locked = !connected_scanner.locked + return - if(viable_occupant && connected && connected.occupant==viable_occupant) - viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation - switch(href_list["task"]) //Same thing as there but values are even lower, on best part they are about 0.0*, effectively no damage - if("pulseui") - var/len = length_char(viable_occupant.dna.uni_identity) - num = WRAP(num, 1, len+1) - num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2 - //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low - var/block = round((num-1)/DNA_BLOCK_SIZE)+1 - var/subblock = num - block*DNA_BLOCK_SIZE - last_change = "UI #[block]-[subblock]; " + // Scramble scanner occupant's DNA + if("scramble_dna") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + // GUARD CHECK - Is scramble DNA actually ready? + if(!can_modify_occupant() || !(scrambleready < world.time)) + return - var/hex = copytext_char(viable_occupant.dna.uni_identity, num, num+1) - last_change += "[hex]" - hex = scramble(hex, radstrength, radduration) - last_change += "->[hex]" + scanner_occupant.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA)) + scanner_occupant.dna.generate_dna_blocks() + scrambleready = world.time + SCRAMBLE_TIMEOUT + to_chat(usr,"DNA scrambled.") + scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER*50/(connected_scanner.damage_coeff ** 2) + return - viable_occupant.dna.uni_identity = copytext_char(viable_occupant.dna.uni_identity, 1, num) + hex + copytext_char(viable_occupant.dna.uni_identity, num + 1) - viable_occupant.updateappearance(mutations_overlay_update=1) + // Check whether a specific mutation is eligible for discovery within the + // scanner occupant + // This is additionally done when a mutation's tab is selected in the tgui + // interface. This is because some mutations, such as Monkified on monkeys, + // are infact completed by default but not yet discovered. Likewise, all + // mutations can have their sequence completed while Monkified is still an + // active mutation and thus won't immediately be discovered but could be + // discovered when Monkified is removed + // ---------------------------------------------------------------------- // + // params["alias"] - Alias of a mutation. The alias is the "hidden" name of + // the mutation, for example "Mutation 5" or "Mutation 33" + if("check_discovery") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // GUARD CHECK - Have we somehow cheekily swapped occupants? This is + // unexpected. + if(!(scanner_occupant == connected_scanner.occupant)) + return + + check_discovery(params["alias"]) + return + + // Check all mutations of the occupant and check if any are discovered. + // This is called when the Genetic Sequencer is selected. It'll do things + // like immediately discover Monkified without needing to click through + // the mutation tabs and handle cases where mutations are solved but not + // discovered due to the Monkified mutation being active then removed. + if("all_check_discovery") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // GUARD CHECK - Have we somehow cheekily swapped occupants? This is + // unexpected. + if(!(scanner_occupant == connected_scanner.occupant)) + return + + // Go over all standard mutations and check if they've been discovered. + for(var/mutation_type in scanner_occupant.dna.mutation_index) + var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(mutation_type) + check_discovery(HM.alias) + + return + + // Set a gene in a mutation's genetic sequence. Will also check for mutations + // discovery as part of the process. + // ---------------------------------------------------------------------- // + // params["alias"] - Alias of a mutation. The alias is the "hidden" name of + // the mutation, for example "Mutation 5" or "Mutation 33" + // params["gene"] - The letter of the new gene + // params["pos"] - The BYOND index of the letter in the gene sequence to be + // changed. Expects a text string from TGUI and will convert to a number + if("pulse_gene") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // GUARD CHECK - Have we somehow cheekily swapped occupants? This is + // unexpected. + if(!(scanner_occupant == connected_scanner.occupant)) + return + + // GUARD CHECK - Is the occupant currently undergoing some form of + // transformation? If so, we don't want to be pulsing genes. + if(scanner_occupant.transformation_timer) + to_chat(usr,"Gene pulse failed: The scanner occupant undergoing a transformation.") + return + + // Resolve mutation's BYOND path from the alias + var/alias = params["alias"] + var/path = GET_MUTATION_TYPE_FROM_ALIAS(alias) + // Make sure the occupant still has this mutation + if(!(path in scanner_occupant.dna.mutation_index)) + return + + // Resolve BYOND path to genome sequence of scanner occupant + var/sequence = GET_GENE_STRING(path, scanner_occupant.dna) + + var/newgene = params["gene"] + var/genepos = text2num(params["pos"]) + + // If the new gene is J, this means we're dealing with a JOKER + // GUARD CHECK - Is JOKER actually ready? + if((newgene == "J") && (jokerready < world.time)) + var/truegenes = GET_SEQUENCE(path) + newgene = truegenes[genepos] + jokerready = world.time + JOKER_TIMEOUT - (JOKER_UPGRADE * (connected_scanner.precision_coeff-1)) + + // If the gene is an X, we want to update the default genes with the new + // X to allow highlighting logic to work on the tgui interface. + if(newgene == "X") + var/defaultseq = scanner_occupant.dna.default_mutation_genes[path] + defaultseq = copytext_char(defaultseq, 1, genepos) + newgene + copytext_char(defaultseq, genepos + 1) + scanner_occupant.dna.default_mutation_genes[path] = defaultseq + + // Copy genome to scanner occupant and do some basic mutation checks as + // we've increased the occupant rads + sequence = copytext_char(sequence, 1, genepos) + newgene + copytext_char(sequence, genepos + 1) + scanner_occupant.dna.mutation_index[path] = sequence + scanner_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected_scanner.damage_coeff + scanner_occupant.domutcheck() + + // GUARD CHECK - Modifying genetics can lead to edge cases where the + // scanner occupant is qdel'd and replaced with a different entity. + // Examples of this include adding/removing the Monkified mutation which + // qdels the previous entity and creates a brand new one in its place. + // We should redo all of our occupant modification checks again, although + // it is less than ideal. + if(!can_modify_occupant()) + return + + // Check if we cracked a mutation + check_discovery(alias) + + return + + // Apply a chromosome to a specific mutation. + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to apply the chromo to + // params["chromo"] - Name of the chromosome to apply to the mutation + if("apply_chromo") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // GUARD CHECK - Have we somehow cheekily swapped occupants? This is + // unexpected. + if(!(scanner_occupant == connected_scanner.occupant)) + return + + var/bref = params["mutref"] + + // GUARD CHECK - Only search occupant for this specific ref, since your + // can only apply chromosomes to mutations occupants. + var/datum/mutation/human/HM = get_mut_by_ref(bref, SEARCH_OCCUPANT) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + // Look through our stored chromos and compare names to find a + // stored chromo we can apply. + for(var/obj/item/chromosome/CM in stored_chromosomes) + if(CM.can_apply(HM) && (CM.name == params["chromo"])) + stored_chromosomes -= CM + CM.apply(HM) + + return + + // Print any type of standard injector, limited right now to activators that + // activate a dormant mutation and mutators that forcibly create a new + // MUT_EXTRA mutation + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to create an injector of + // params["is_activator"] - Is this an "Activator" style injector, also + // referred to as a "Research" type. Expects a string with 0 or 1, which + // then gets converted to a number. + // params["source"] - The source the request came from. + // Expected results: + // "occupant" - From genetic sequencer + // "console" - From DNA Console storage + // "disk" - From inserted diskette + if("print_injector") + // Because printing mutators and activators share a bunch of code, + // it makes sense to keep them both together and set unique vars + // later in the code + + // As a side note, because mutations can contain unique metadata, + // this system uses BYOND Atom Refs to safely and accurately + // identify mutations from big ol' lists + + // GUARD CHECK - Is the injector actually ready? + if(world.time < injectorready) + return + + var/search_flags = 0 + + switch(params["source"]) + if("occupant") + // GUARD CHECK - Make sure we can modify the occupant before we + // attempt to search them for any given mutation refs. This could + // lead to no search flags being passed to get_mut_by_ref and this + // is intended functionality to prevent any cheese or abuse + if(can_modify_occupant()) + search_flags |= SEARCH_OCCUPANT + if("console") + search_flags |= SEARCH_STORED + if("disk") + search_flags |= SEARCH_DISKETTE + + var/bref = params["mutref"] + var/datum/mutation/human/HM = get_mut_by_ref(bref, search_flags) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + // Create a new DNA Injector and add the appropriate mutations to it + var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc) + I.add_mutations += new HM.type(copymut = HM) + + var/is_activator = text2num(params["is_activator"]) + + // Activators are also called "research" injectors and are used to create + // chromosomes by recycling at the DNA Console + if(is_activator) + I.name = "[HM.name] activator" + I.research = TRUE + // If there's an operational connected scanner, we can use its upgrades + // to improve our injector's radiation generation + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff*4 + injectorready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected_scanner.precision_coeff) else - current_screen = "mainmenu" - - if(connected) - connected.locked = locked_state - if("inspect") - if(viable_occupant) - var/list/mutations = get_mutation_list(TRUE) - if(current_mutation == mutations[num]) - current_mutation = null + injectorready = world.time + INJECTOR_TIMEOUT + else + I.name = "[HM.name] mutator" + I.doitanyway = TRUE + // If there's an operational connected scanner, we can use its upgrades + // to improve our injector's radiation generation + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff + injectorready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected_scanner.precision_coeff) else - current_mutation = mutations[num] + injectorready = world.time + INJECTOR_TIMEOUT * 5 + + return + + // Save a mutation to the console's storage buffer. + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to store + // params["source"] - The source the request came from. + // Expected results: + // "occupant" - From genetic sequencer + // "disk" - From inserted diskette + if("save_console") + var/search_flags = 0 + + switch(params["source"]) + if("occupant") + // GUARD CHECK - Make sure we can modify the occupant before we + // attempt to search them for any given mutation refs. This could + // lead to no search flags being passed to get_mut_by_ref and this + // is intended functionality to prevent any cheese or abuse + if(can_modify_occupant()) + search_flags |= SEARCH_OCCUPANT + if("disk") + search_flags |= SEARCH_DISKETTE + + // GUARD CHECK - Is mutation storage full? + if(LAZYLEN(stored_mutations) >= max_storage) + to_chat(usr,"Mutation storage is full.") + return + + var/bref = params["mutref"] + var/datum/mutation/human/HM = get_mut_by_ref(bref, search_flags) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + var/datum/mutation/human/A = new HM.type() + A.copy_mutation(HM) + stored_mutations += A + to_chat(usr,"Mutation successfully stored.") + return + + // Save a mutation to the diskette's storage buffer. + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to store + // params["source"] - The source the request came from + // Expected results: + // "occupant" - From genetic sequencer + // "console" - From DNA Console storage + if("save_disk") + // GUARD CHECK - This code shouldn't even be callable without a diskette + // inserted. Unexpected result + if(!diskette) + return + + // GUARD CHECK - Make sure the disk is not full + if(LAZYLEN(diskette.mutations) >= diskette.max_mutations) + to_chat(usr,"Disk storage is full.") + return + + // GUARD CHECK - Make sure the disk isn't set to read only, as we're + // attempting to write to it + if(diskette.read_only) + to_chat(usr,"Disk is set to read only mode.") + return + + var/search_flags = 0 + + switch(params["source"]) + if("occupant") + // GUARD CHECK - Make sure we can modify the occupant before we + // attempt to search them for any given mutation refs. This could + // lead to no search flags being passed to get_mut_by_ref and this + // is intended functionality to prevent any cheese or abuse + if(can_modify_occupant()) + search_flags |= SEARCH_OCCUPANT + if("console") + search_flags |= SEARCH_STORED + + var/bref = params["mutref"] + var/datum/mutation/human/HM = get_mut_by_ref(bref, search_flags) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + var/datum/mutation/human/A = new HM.type() + A.copy_mutation(HM) + diskette.mutations += A + to_chat(usr,"Mutation successfully stored to disk.") + return + + // Completely removes a MUT_EXTRA mutation or mutation with corrupt gene + // sequence from the scanner occupant + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to nullify + if("nullify") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + var/bref = params["mutref"] + var/datum/mutation/human/HM = get_mut_by_ref(bref, SEARCH_OCCUPANT) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + // GUARD CHECK - Nullify should only be used on scrambled or "extra" + // mutations. + if(!HM.scrambled && !(HM.class == MUT_EXTRA)) + return + + scanner_occupant.dna.remove_mutation(HM.type) + return + + // Deletes saved mutation from console buffer. + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to delete + if("delete_console_mut") + var/bref = params["mutref"] + var/datum/mutation/human/HM = get_mut_by_ref(bref, SEARCH_STORED) - if("inspectstorage") - current_storage = num - current_screen = "info" - if("savemut") - if(viable_occupant) - var/succes - if(LAZYLEN(stored_mutations) < max_storage) - var/mutation = text2path(href_list["path"]) - if(ispath(mutation, /datum/mutation/human)) //sanity checks - var/datum/mutation/human/HM = viable_occupant.dna.get_mutation(mutation) - if(HM) - var/datum/mutation/human/A = new HM.type() - A.copy_mutation(HM) - succes = TRUE - stored_mutations += A - to_chat(usr,"Mutation succesfully stored.") - if(!succes) //we can exactly return here - to_chat(usr,"Mutation storage is full.") - if("deletemut") - var/datum/mutation/human/HM = stored_mutations[num] if(HM) stored_mutations.Remove(HM) qdel(HM) - current_screen = "mutations" - if("activator") - if(injectorready < world.time) - var/mutation = text2path(href_list["path"]) - if(ispath(mutation, /datum/mutation/human)) - var/datum/mutation/human/HM = get_valid_mutation(mutation) - if(HM) - var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc) - I.add_mutations += new HM.type (copymut = HM) - I.name = "[HM.name] activator" - I.research = TRUE - if(connected) - I.damage_coeff = connected.damage_coeff*4 - injectorready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected.precision_coeff) //precision_coeff being the matter bin rating - else - injectorready = world.time + INJECTOR_TIMEOUT - if("mutator") - if(injectorready < world.time) - var/mutation = text2path(href_list["path"]) - if(ispath(mutation, /datum/mutation/human)) - var/datum/mutation/human/HM = get_valid_mutation(mutation) - if(HM) - var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc) - I.add_mutations += new HM.type (copymut = HM) - I.doitanyway = TRUE - I.name = "[HM.name] injector" - if(connected) - I.damage_coeff = connected.damage_coeff - injectorready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected.precision_coeff) - else - injectorready = world.time + INJECTOR_TIMEOUT * 5 - if("advinjector") - var/selection = href_list["injector"] - if(injectorready < world.time) - if(injector_selection.Find(selection)) - var/list/true_selection = injector_selection[selection] - if(LAZYLEN(injector_selection)) - var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc) - for(var/A in true_selection) - var/datum/mutation/human/HM = A - I.add_mutations += new HM.type (copymut = HM) - I.doitanyway = TRUE - I.name = "Advanced [selection] injector" - if(connected) - I.damage_coeff = connected.damage_coeff - injectorready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected.precision_coeff) - else - injectorready = world.time + INJECTOR_TIMEOUT * 8 - if("nullify") - if(viable_occupant) - var/datum/mutation/human/A = viable_occupant.dna.get_mutation(current_mutation) - if(A && (!viable_occupant.dna.mutation_in_sequence(current_mutation) || A.scrambled)) - viable_occupant.dna.remove_mutation(current_mutation) - current_screen = "mainmenu" - current_mutation = null - if("pulsegene") - if(current_screen != "info") - var/path = text2path(href_list["path"]) - if(viable_occupant && num && (path in viable_occupant.dna.mutation_index)) - var/list/genes = list("A","T","G","C","X") - if(jokerready < world.time) - genes += "JOKER" - var/sequence = GET_GENE_STRING(path, viable_occupant.dna) - var/original = sequence[num] - var/new_gene = input("From [original] to-", "New block", original) as null|anything in genes - if(!new_gene) - new_gene = original - if(viable_occupant == get_viable_occupant()) //No cheesing - if((new_gene == "JOKER") && (jokerready < world.time)) - var/true_genes = GET_SEQUENCE(current_mutation) - new_gene = true_genes[num] - jokerready = world.time + JOKER_TIMEOUT - (JOKER_UPGRADE * (connected.precision_coeff-1)) - sequence = copytext(sequence, 1, num) + new_gene + copytext(sequence, num+1, length(sequence)+1) - viable_occupant.dna.mutation_index[path] = sequence - viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected.damage_coeff - viable_occupant.domutcheck() - if("exportdiskmut") - if(diskette && !diskette.read_only) - var/path = text2path(href_list["path"]) - if(ispath(path, /datum/mutation/human)) - var/datum/mutation/human/A = get_valid_mutation(path) - if(A && diskette && (LAZYLEN(diskette.mutations) < diskette.max_mutations)) - var/datum/mutation/human/HM = new A.type() - diskette.mutations += HM - HM.copy_mutation(A) - to_chat(usr, "Succesfully written [A.name] to [diskette.name].") - if("deletediskmut") - if(diskette && !diskette.read_only) - if(num && (LAZYLEN(diskette.mutations) >= num)) - var/datum/mutation/human/A = diskette.mutations[num] - diskette.mutations.Remove(A) - qdel(A) - if("importdiskmut") - if(diskette && (LAZYLEN(diskette.mutations) >= num)) - if(LAZYLEN(stored_mutations) < max_storage) - var/datum/mutation/human/A = diskette.mutations[num] - var/datum/mutation/human/HM = new A.type() - HM.copy_mutation(A) - stored_mutations += HM - to_chat(usr,"Succesfully written [A.name] to storage.") - if("combine") - if(num && (LAZYLEN(stored_mutations) >= num)) - if(LAZYLEN(stored_mutations) < max_storage) - var/datum/mutation/human/A = stored_mutations[num] - var/path = A.type - if(combine) - var/result_path = get_mixed_mutation(combine, path) - if(result_path) - stored_mutations += new result_path() - to_chat(usr, "Succes! New mutation has been added to storage") - discover(result_path) - combine = null - else - to_chat(usr, "Failed. No mutation could be created.") - combine = null - else - combine = path - to_chat(usr,"Selected [A.name] for combining") - else - to_chat(usr, "Not enough space to store potential mutation.") - if("ejectchromosome") - if(LAZYLEN(stored_chromosomes) <= num) - var/obj/item/chromosome/CM = stored_chromosomes[num] - CM.forceMove(drop_location()) - adjust_item_drop_location(CM) - stored_chromosomes -= CM - if("applychromosome") - if(viable_occupant && (LAZYLEN(viable_occupant.dna.mutations) <= num)) - var/datum/mutation/human/HM = viable_occupant.dna.mutations[num] - var/list/chromosomes = list() - for(var/obj/item/chromosome/CM in stored_chromosomes) - if(CM.can_apply(HM)) - chromosomes += CM - if(chromosomes.len) - var/obj/item/chromosome/CM = input("Select a chromosome to apply", "Apply Chromosome") as null|anything in sortNames(chromosomes) - if(CM) - to_chat(usr, "You apply [CM] to [HM.name].") - stored_chromosomes -= CM - CM.apply(HM) - if("expand_advinjector") - var/mutation = text2path(href_list["path"]) - var/datum/mutation/human/HM = get_valid_mutation(mutation) - if(HM && LAZYLEN(injector_selection)) - var/which_injector = input(usr, "Select Adv. Injector", "Advanced Injectors") as null|anything in injector_selection - if(injector_selection.Find(which_injector)) - var/list/true_selection = injector_selection[which_injector] - var/total_instability - for(var/B in true_selection) - var/datum/mutation/human/mootacion = B - total_instability += mootacion.instability - total_instability += HM.instability - if((total_instability > max_injector_instability) || (true_selection.len + 1) > max_injector_mutations) - to_chat(usr, "Adding more mutations would make the advanced injector too unstable!") - else - true_selection += HM //reminder that this works. because I keep forgetting this works - if("remove_from_advinjector") - var/mutation = text2path(href_list["path"]) - var/selection = href_list["injector"] - if(injector_selection.Find(selection)) - var/list/true_selection = injector_selection[selection] - for(var/B in true_selection) - var/datum/mutation/human/HM = B - if(HM.type == mutation) - true_selection -= HM - break + return - if("remove_advinjector") - var/selection = href_list["injector"] - for(selection in injector_selection) - if(selection == selection) - injector_selection.Remove(selection) + // Deletes saved mutation from disk buffer. + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to delete + if("delete_disk_mut") + // GUARD CHECK - This code shouldn't even be callable without a diskette + // inserted. Unexpected result + if(!diskette) + return - if("add_advinjector") - if(LAZYLEN(injector_selection) < max_injector_selections) - var/new_selection = input(usr, "Enter Adv. Injector name", "Advanced Injectors") as text|null - if(new_selection && !(new_selection in injector_selection)) - injector_selection[new_selection] = list() + // GUARD CHECK - Make sure the disk isn't set to read only, as we're + // attempting to write to it (via deletion) + if(diskette.read_only) + to_chat(usr,"Disk is set to read only mode.") + return + var/bref = params["mutref"] + var/datum/mutation/human/HM = get_mut_by_ref(bref, SEARCH_DISKETTE) - ui_interact(usr,last_change) + if(HM) + diskette.mutations.Remove(HM) + qdel(HM) -/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd) //hexadecimal genetics. dont confuse with scramble button + return + + // Ejects a stored chromosome from the DNA Console + // ---------------------------------------------------------------------- // + // params["chromo"] - Text string of the chromosome name + if("eject_chromo") + var/chromname = params["chromo"] + + for(var/obj/item/chromosome/CM in stored_chromosomes) + if(chromname == CM.name) + CM.forceMove(drop_location()) + adjust_item_drop_location(CM) + stored_chromosomes -= CM + return + + return + + // Combines two mutations from the console to try and create a new mutation + // ---------------------------------------------------------------------- // + // params["firstref"] - ATOM Ref of first mutation for combination + // params["secondref"] - ATOM Ref of second mutation for combination + // mutation + if("combine_console") + // GUaRD CHECK - Make sure mutation storage isn't full. If it is, we won't + // be able to store the new combo mutation + if(LAZYLEN(stored_mutations) >= max_storage) + to_chat(usr,"Mutation storage is full.") + return + + // GUARD CHECK - We're running a research-type operation. If, for some + // reason, somehow the DNA Console has been disconnected from the research + // network - Or was never in it to begin with - don't proceed + if(!stored_research) + return + + var/first_bref = params["firstref"] + var/second_bref = params["secondref"] + + // GUARD CHECK - Find the source and destination mutations on the console + // and make sure they actually exist. + var/datum/mutation/human/source_mut = get_mut_by_ref(first_bref, SEARCH_STORED | SEARCH_DISKETTE) + if(!source_mut) + return + + var/datum/mutation/human/dest_mut = get_mut_by_ref(second_bref, SEARCH_STORED | SEARCH_DISKETTE) + if(!dest_mut) + return + + // Attempt to mix the two mutations to get a new type + var/result_path = get_mixed_mutation(source_mut.type, dest_mut.type) + + if(!result_path) + return + + // If we got a new type, add it to our storage + stored_mutations += new result_path() + to_chat(usr, "Success! New mutation has been added to console storage.") + + // If it's already discovered, end here. Otherwise, add it to the list of + // discovered mutations. + // We've already checked for stored_research earlier + if(result_path in stored_research.discovered_mutations) + return + + var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(result_path) + stored_research.discovered_mutations += result_path + say("Successfully mutated [HM.name].") + return + + // Combines two mutations from the disk to try and create a new mutation + // ---------------------------------------------------------------------- // + // params["firstref"] - ATOM Ref of first mutation for combination + // params["secondref"] - ATOM Ref of second mutation for combination + // mutation + if("combine_disk") + // GUARD CHECK - This code shouldn't even be callable without a diskette + // inserted. Unexpected result + if(!diskette) + return + + // GUARD CHECK - Make sure the disk is not full. + if(LAZYLEN(diskette.mutations) >= diskette.max_mutations) + to_chat(usr,"Disk storage is full.") + return + + // GUARD CHECK - Make sure the disk isn't set to read only, as we're + // attempting to write to it + if(diskette.read_only) + to_chat(usr,"Disk is set to read only mode.") + return + + // GUARD CHECK - We're running a research-type operation. If, for some + // reason, somehow the DNA Console has been disconnected from the research + // network - Or was never in it to begin with - don't proceed + if(!stored_research) + return + + var/first_bref = params["firstref"] + var/second_bref = params["secondref"] + + // GUARD CHECK - Find the source and destination mutations on the console + // and make sure they actually exist. + var/datum/mutation/human/source_mut = get_mut_by_ref(first_bref, SEARCH_STORED | SEARCH_DISKETTE) + if(!source_mut) + return + + var/datum/mutation/human/dest_mut = get_mut_by_ref(second_bref, SEARCH_STORED | SEARCH_DISKETTE) + if(!dest_mut) + return + + // Attempt to mix the two mutations to get a new type + var/result_path = get_mixed_mutation(source_mut.type, dest_mut.type) + + if(!result_path) + return + + // If we got a new type, add it to our storage + diskette.mutations += new result_path() + to_chat(usr, "Success! New mutation has been added to the disk.") + + // If it's already discovered, end here. Otherwise, add it to the list of + // discovered mutations + // We've already checked for stored_research earlier + if(result_path in stored_research.discovered_mutations) + return + + var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(result_path) + stored_research.discovered_mutations += result_path + say("Successfully mutated [HM.name].") + return + + // Sets the Genetic Makeup pulse strength. + // ---------------------------------------------------------------------- // + // params["val"] - New strength value as text string, converted to number + // later on in code + if("set_pulse_strength") + var/value = round(text2num(params["val"])) + radstrength = WRAP(value, 1, RADIATION_STRENGTH_MAX+1) + return + + // Sets the Genetic Makeup pulse duration + // ---------------------------------------------------------------------- // + // params["val"] - New strength value as text string, converted to number + // later on in code + if("set_pulse_duration") + var/value = round(text2num(params["val"])) + radduration = WRAP(value, 1, RADIATION_DURATION_MAX+1) + return + + // Saves Genetic Makeup information to disk + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // copy to disk + if("save_makeup_disk") + // GUARD CHECK - This code shouldn't even be callable without a diskette + // inserted. Unexpected result + if(!diskette) + return + + // GUARD CHECK - Make sure the disk isn't set to read only, as we're + // attempting to write to it + if(diskette.read_only) + to_chat(usr,"Disk is set to read only mode.") + return + + // Convert the index to a number and clamp within the array range + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + + var/list/buffer_slot = genetic_makeup_buffer[buffer_index] + + // GUARD CHECK - This should not be possible to activate on a buffer slot + // that doesn't have any genetic data. Unexpected result + if(!istype(buffer_slot)) + return + + diskette.genetic_makeup_buffer = buffer_slot.Copy() + return + + // Loads Genetic Makeup from disk to a console buffer + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // copy to. Expected as text string, converted to number later + if("load_makeup_disk") + // GUARD CHECK - This code shouldn't even be callable without a diskette + // inserted. Unexpected result + if(!diskette) + return + + // GUARD CHECK - This should not be possible to activate on a diskette + // that doesn't have any genetic data. Unexpected result + if(LAZYLEN(diskette.genetic_makeup_buffer) == 0) + return + + // Convert the index to a number and clamp within the array range, then + // copy the data from the disk to that buffer + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + genetic_makeup_buffer[buffer_index] = diskette.genetic_makeup_buffer.Copy() + return + + // Deletes genetic makeup buffer from the inserted diskette + if("del_makeup_disk") + // GUARD CHECK - This code shouldn't even be callable without a diskette + // inserted. Unexpected result + if(!diskette) + return + + // GUARD CHECK - Make sure the disk isn't set to read only, as we're + // attempting to write (via deletion) to it + if(diskette.read_only) + to_chat(usr,"Disk is set to read only mode.") + return + + diskette.genetic_makeup_buffer.Cut() + return + + // Saves the scanner occupant's genetic makeup to a given console buffer + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // save the new genetic data to. Expected as text string, converted to + // number later + if("save_makeup_console") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // Convert the index to a number and clamp within the array range, then + // copy the data from the disk to that buffer + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + + // Set the new information + genetic_makeup_buffer[buffer_index] = list( + "label"="Slot [buffer_index]:[scanner_occupant.real_name]", + "UI"=scanner_occupant.dna.uni_identity, + "UE"=scanner_occupant.dna.unique_enzymes, + "name"=scanner_occupant.real_name, + "blood_type"=scanner_occupant.dna.blood_type) + + return + + // Deleted genetic makeup data from a console buffer slot + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // delete the genetic data from. Expected as text string, converted to + // number later + if("del_makeup_console") + // Convert the index to a number and clamp within the array range, then + // copy the data from the disk to that buffer + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = genetic_makeup_buffer[buffer_index] + + // GUARD CHECK - This shouldn't be possible to execute this on a null + // buffer. Unexpected resut + if(!istype(buffer_slot)) + return + + genetic_makeup_buffer[buffer_index] = null + return + + // Eject stored diskette from console + if("eject_disk") + eject_disk(usr) + return + + // Create a Genetic Makeup injector. These injectors are timed and thus are + // only temporary + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // create the makeup injector from. Expected as text string, converted to + // number later + // params["type"] - Type of injector to create + // Expected results: + // "ue" - Unique Enzyme, changes name and blood type + // "ui" - Unique Identity, changes looks + // "mixed" - Combination of both ue and ui + if("makeup_injector") + // Convert the index to a number and clamp within the array range, then + // copy the data from the disk to that buffer + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = genetic_makeup_buffer[buffer_index] + + // GUARD CHECK - This shouldn't be possible to execute this on a null + // buffer. Unexpected resut + if(!istype(buffer_slot)) + return + + var/type = params["type"] + var/obj/item/dnainjector/timed/I + + switch(type) + if("ui") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["UI"]) + to_chat(usr,"Genetic data corrupted, unable to create injector.") + return + + I = new /obj/item/dnainjector/timed(loc) + I.fields = list("UI"=buffer_slot["UI"]) + + // If there is a connected scanner, we can use its upgrades to reduce + // the radiation generated by this injector + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff + if("ue") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) + to_chat(usr,"Genetic data corrupted, unable to create injector.") + return + + I = new /obj/item/dnainjector/timed(loc) + I.fields = list("name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) + + // If there is a connected scanner, we can use its upgrades to reduce + // the radiation generated by this injector + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff + if("mixed") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) + to_chat(usr,"Genetic data corrupted, unable to create injector.") + return + + I = new /obj/item/dnainjector/timed(loc) + I.fields = list("UI"=buffer_slot["UI"],"name"=buffer_slot["name"], "UE"=buffer_slot["UE"], "blood_type"=buffer_slot["blood_type"]) + + // If there is a connected scanner, we can use its upgrades to reduce + // the radiation generated by this injector + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff + + // If we successfully created an injector, don't forget to set the new + // ready timer. + if(I) + injectorready = world.time + INJECTOR_TIMEOUT + + return + + // Applies a genetic makeup buffer to the scanner occupant + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // apply to the scanner occupant. Expected as text string, converted to + // number later + // params["type"] - Type of genetic makeup copy to implement + // Expected results: + // "ue" - Unique Enzyme, changes name and blood type + // "ui" - Unique Identity, changes looks + // "mixed" - Combination of both ue and ui + if("makeup_apply") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // Convert the index to a number and clamp within the array range, then + // copy the data from the disk to that buffer + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = genetic_makeup_buffer[buffer_index] + + // GUARD CHECK - This shouldn't be possible to execute this on a null + // buffer. Unexpected resut + if(!istype(buffer_slot)) + return + + var/type = params["type"] + + apply_genetic_makeup(type, buffer_slot) + return + + // Applies a genetic makeup buffer to the next scanner occupant. This sets + // some code that will run when the connected DNA Scanner door is next + // closed + // This allows people to self-modify their genetic makeup, as tgui + // interfaces can not be accessed while inside the DNA Scanner and genetic + // makeup injectors are only temporary + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the console genetic makeup buffer to + // apply to the scanner occupant. Expected as text string, converted to + // number later + // params["type"] - Type of genetic makeup copy to implement + // Expected results: + // "ue" - Unique Enzyme, changes name and blood type + // "ui" - Unique Identity, changes looks + // "mixed" - Combination of both ue and ui + if("makeup_delay") + // Convert the index to a number and clamp within the array range, then + // copy the data from the disk to that buffer + var/buffer_index = text2num(params["index"]) + buffer_index = clamp(buffer_index, 1, NUMBER_OF_BUFFERS) + var/list/buffer_slot = genetic_makeup_buffer[buffer_index] + + // GUARD CHECK - This shouldn't be possible to execute this on a null + // buffer. Unexpected resut + if(!istype(buffer_slot)) + return + + var/type = params["type"] + + // Set the delayed action. The next time the scanner door is closed, + // unless this is cancelled in the UI, the action will happen + delayed_action = list("type" = type, "buffer_slot" = buffer_slot) + return + + // Attempts to modify the indexed element of the Unique Identity string + // This is a time delayed action that is handled in process() + // ---------------------------------------------------------------------- // + // params["index"] - The BYOND index of the Unique Identity string to + // attempt to modify + if("makeup_pulse") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + if(!can_modify_occupant()) + return + + // Set the appropriate timer and index to pulse. This is then managed + // later on in process() + var/len = length_char(scanner_occupant.dna.uni_identity) + rad_pulse_timer = world.time + (radduration*10) + rad_pulse_index = WRAP(text2num(params["index"]), 1, len+1) + START_PROCESSING(SSobj, src) + return + + // Cancels the delayed action - In this context it is not the radiation + // pulse from "makeup_pulse", which can not be cancelled. It is instead + // the delayed genetic transfer from "makeup_delay" + if("cancel_delay") + delayed_action = null + return + + // Creates a new advanced injector storage buffer in the console + // ---------------------------------------------------------------------- // + // params["name"] - The name to apply to the new injector + if("new_adv_inj") + // GUARD CHECK - Make sure we can make a new injector. This code should + // not be called if we're already maxed out and this is an Unexpected + // result + if(!(LAZYLEN(injector_selection) < max_injector_selections)) + return + + // GUARD CHECK - Sanitise and trim the proposed name. This prevents HTML + // injection and equivalent as tgui input is not stripped + var/inj_name = params["name"] + inj_name = trim(sanitize(inj_name)) + + // GUARD CHECK - If the name is null or blank, or the name is already in + // the list of advanced injectors, we want to reject it as we can't have + // duplicate named advanced injectors + if(!inj_name || (inj_name in injector_selection)) + return + + injector_selection[inj_name] = list() + return + + // Deleted an advanced injector storage buffer from the console + // ---------------------------------------------------------------------- // + // params["name"] - The name of the injector to delete + if("del_adv_inj") + var/inj_name = params["name"] + + // GUARD CHECK - If the name is null or blank, reject. + // GUARD CHECK - If the name isn't in the list of advanced injectors, we + // want to reject this as it shouldn't be possible ever do this. + // Unexpected result + if(!inj_name || !(inj_name in injector_selection)) + return + + injector_selection.Remove(inj_name) + return + + // Creates an injector from an advanced injector buffer + // ---------------------------------------------------------------------- // + // params["name"] - The name of the injector to print + if("print_adv_inj") + // As a side note, because mutations can contain unique metadata, + // this system uses BYOND Atom Refs to safely and accurately + // identify mutations from big ol' lists. + + // GUARD CHECK - Is the injector actually ready? + if(world.time < injectorready) + return + + var/inj_name = params["name"] + + // GUARD CHECK - If the name is null or blank, reject. + // GUARD CHECK - If the name isn't in the list of advanced injectors, we + // want to reject this as it shouldn't be possible ever do this. + // Unexpected result + if(!inj_name || !(inj_name in injector_selection)) + return + + var/list/injector = injector_selection[inj_name] + var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc) + + // Run through each mutation in our Advanced Injector and add them to a + // new injector + for(var/A in injector) + var/datum/mutation/human/HM = A + I.add_mutations += new HM.type(copymut=HM) + + // Force apply any mutations, this is functionality similar to mutators + I.doitanyway = TRUE + I.name = "Advanced [inj_name] injector" + + // If there's an operational connected scanner, we can use its upgrades + // to improve our injector's radiation generation + if(scanner_operational()) + I.damage_coeff = connected_scanner.damage_coeff + injectorready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected_scanner.precision_coeff) + else + injectorready = world.time + INJECTOR_TIMEOUT * 8 + + return + + // Adds a mutation to an advanced injector + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to add to the injector + // params["advinj"] - Name of the advanced injector to add the mutation to + if("add_advinj_mut") + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + // This is needed because this operation can only be completed from the + // genetic sequencer. + if(!can_modify_occupant()) + return + + var/adv_inj = params["advinj"] + + // GUARD CHECK - Make sure our advanced injector actually exists. This + // should not be possible. Unexpected result + if(!(adv_inj in injector_selection)) + return + + // GUARD CHECK - Make sure we limit the number of mutations appropriately + if(LAZYLEN(injector_selection[adv_inj]) >= max_injector_mutations) + to_chat(usr,"Advanced injector mutation storage is full.") + return + + var/mut_source = params["source"] + var/search_flag = 0 + + switch(mut_source) + if("disk") + search_flag = SEARCH_DISKETTE + if("occupant") + search_flag = SEARCH_OCCUPANT + if("console") + search_flag = SEARCH_STORED + + if(!search_flag) + return + + var/bref = params["mutref"] + // We've already made sure we can modify the occupant, so this is safe to + // call + var/datum/mutation/human/HM = get_mut_by_ref(bref, search_flag) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + // We want to make sure we stick within the instability limit. + // We start with the instability of the mutation we're intending to add. + var/instability_total = HM.instability + + // We then add the instabilities of all other mutations in the injector, + // remembering to apply the Stabilizer chromosome modifiers + for(var/datum/mutation/human/I in injector_selection[adv_inj]) + instability_total += I.instability * GET_MUTATION_STABILIZER(I) + + // If this would take us over the max instability, we inform the user. + if(instability_total > max_injector_instability) + to_chat(usr,"Extra mutation would make the advanced injector too instable.") + return + + // If we've got here, all our checks are passed and we can successfully + // add the mutation to the advanced injector. + var/datum/mutation/human/A = new HM.type() + A.copy_mutation(HM) + injector_selection[adv_inj] += A + to_chat(usr,"Mutation successfully added to advanced injector.") + return + + // Deletes a mutation from an advanced injector + // ---------------------------------------------------------------------- // + // params["mutref"] - ATOM Ref of specific mutation to del from the injector + if("delete_injector_mut") + var/bref = params["mutref"] + + var/datum/mutation/human/HM = get_mut_by_ref(bref, SEARCH_ADV_INJ) + + // GUARD CHECK - This should not be possible. Unexpected result + if(!HM) + return + + // Check Advanced Injectors to find and remove the mutation + for(var/I in injector_selection) + if(injector_selection["[I]"].Remove(HM)) + qdel(HM) + return + + return + + // Sets a new tgui view state + // ---------------------------------------------------------------------- // + // params["id"] - Key for the state to set + // params[...] - Every other element is used to set state variables + if("set_view") + for (var/key in params) + if(key == "src") + continue + tgui_view_state[key] = params[key] + return TRUE + return FALSE + +/** + * Applies the enzyme buffer to the current scanner occupant + * + * Applies the type of a specific genetic makeup buffer to the current scanner + * occupant + * + * Arguments: + * * type - "ui"/"ue"/"mixed" - Which part of the enzyme buffer to apply + * * buffer_slot - Index of the enzyme buffer to apply + */ +/obj/machinery/computer/scan_consolenew/proc/apply_genetic_makeup(type, buffer_slot) + // Note - This proc is only called from code that has already performed the + // necessary occupant guard checks. If you call this code yourself, please + // apply can_modify_occupant() or equivalent checks first. + + // Pre-calc the rad increase since we'll be using it in all the possible + // operations + var/rad_increase = rand(100/(connected_scanner.damage_coeff ** 2),250/(connected_scanner.damage_coeff ** 2)) + + switch(type) + if("ui") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["UI"]) + to_chat(usr,"Genetic data corrupted, unable to apply genetic data.") + return FALSE + scanner_occupant.dna.uni_identity = buffer_slot["UI"] + scanner_occupant.updateappearance(mutations_overlay_update=1) + scanner_occupant.radiation += rad_increase + scanner_occupant.domutcheck() + return TRUE + if("ue") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) + to_chat(usr,"Genetic data corrupted, unable to apply genetic data.") + return FALSE + scanner_occupant.real_name = buffer_slot["name"] + scanner_occupant.name = buffer_slot["name"] + scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] + scanner_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.radiation += rad_increase + scanner_occupant.domutcheck() + return TRUE + if("mixed") + // GUARD CHECK - There's currently no way to save partial genetic data. + // However, if this is the case, we can't make a complete injector and + // this catches that edge case + if(!buffer_slot["UI"] || !buffer_slot["name"] || !buffer_slot["UE"] || !buffer_slot["blood_type"]) + to_chat(usr,"Genetic data corrupted, unable to apply genetic data.") + return FALSE + scanner_occupant.dna.uni_identity = buffer_slot["UI"] + scanner_occupant.updateappearance(mutations_overlay_update=1) + scanner_occupant.real_name = buffer_slot["name"] + scanner_occupant.name = buffer_slot["name"] + scanner_occupant.dna.unique_enzymes = buffer_slot["UE"] + scanner_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.radiation += rad_increase + scanner_occupant.domutcheck() + return TRUE + + return FALSE +/** + * Checks if there is a connected DNA Scanner that is operational + */ +/obj/machinery/computer/scan_consolenew/proc/scanner_operational() + if(!connected_scanner) + return FALSE + + return (connected_scanner && connected_scanner.is_operational()) + +/** + * Checks if there is a valid DNA Scanner occupant for genetic modification + * + * Checks if there is a valid subject in the DNA Scanner that can be genetically + * modified. Will set the scanner occupant var as part of this check. + * Requires that the scanner can be operated and will return early if it can't + */ +/obj/machinery/computer/scan_consolenew/proc/can_modify_occupant() + // GUARD CHECK - We always want to perform the scanner operational check as + // part of checking if we can modify the occupant. + // We can never modify the occupant of a broken scanner. + if(!scanner_operational()) + return FALSE + + if(!connected_scanner.occupant) + return FALSE + + scanner_occupant = connected_scanner.occupant + + // Check validity of occupent for DNA Modification + // DNA Modification: + // requires DNA + // this DNA can not be bad + // is done via radiation bursts, so radiation immune carbons are not viable + // And the DNA Scanner itself must have a valid scan level + if(scanner_occupant.has_dna() && !HAS_TRAIT(scanner_occupant, TRAIT_RADIMMUNE) && !HAS_TRAIT(scanner_occupant, TRAIT_NOCLONE) || (connected_scanner.scan_level == 3)) + return TRUE + + return FALSE + +/** + * Checks for adjacent DNA scanners and connects when it finds a viable one + * + * Seearches cardinal directions in order. Stops when it finds a viable DNA Scanner. + * Will connect to a broken scanner if no functional scanner is available. + * Links itself to the DNA Scanner to receive door open and close events. + */ +/obj/machinery/computer/scan_consolenew/proc/connect_to_scanner() + var/obj/machinery/dna_scannernew/test_scanner = null + var/obj/machinery/dna_scannernew/broken_scanner = null + + // Look in each cardinal direction and try and find a DNA Scanner + // If you find a DNA Scanner, check to see if it broken or working + // If it's working, set the current scanner and return early + // If it's not working, remember it anyway as a broken scanner + for(var/direction in GLOB.cardinals) + test_scanner = locate(/obj/machinery/dna_scannernew, get_step(src, direction)) + if(!isnull(test_scanner)) + if(test_scanner.is_operational()) + connected_scanner = test_scanner + connected_scanner.linked_console = src + return + else + broken_scanner = test_scanner + + // Ultimately, if we have a broken scanner, we'll attempt to connect to it as + // a fallback case, but the code above will prefer a working scanner + if(!isnull(broken_scanner)) + connected_scanner = broken_scanner + connected_scanner.linked_console = src + +/** + * Called by connected DNA Scanners when their doors close. + * + * Sets the new scanner occupant and completes delayed enzyme transfer if one + * is queued. + */ +/obj/machinery/computer/scan_consolenew/proc/on_scanner_close() + // Set the appropriate occupant now the scanner is closed + if(connected_scanner.occupant) + scanner_occupant = connected_scanner.occupant + else + scanner_occupant = null + + // If we have a delayed action - In this case the only delayed action is + // applying a genetic makeup buffer the next time the DNA Scanner is closed - + // we want to perform it. + // GUARD CHECK - Make sure we can modify the occupant, apply_genetic_makeup() + // assumes we've already done this. + if(delayed_action && can_modify_occupant()) + var/type = delayed_action["type"] + var/buffer_slot = delayed_action["buffer_slot"] + if(apply_genetic_makeup(type, buffer_slot)) + to_chat(connected_scanner.occupant, "[src] activates!") + delayed_action = null + +/** + * Called by connected DNA Scanners when their doors open. + * + * Clears enzyme pulse operations, stops processing and nulls the current + * scanner occupant var. + */ +/obj/machinery/computer/scan_consolenew/proc/on_scanner_open() + // If we had a radiation pulse action ongoing, we want to stop this. + // Imagine it being like a microwave stopping when you open the door. + rad_pulse_index = 0 + rad_pulse_timer = 0 + STOP_PROCESSING(SSobj, src) + scanner_occupant = null + +/** + * Builds the genetic makeup list which will be sent to tgui interface. + */ +/obj/machinery/computer/scan_consolenew/proc/build_genetic_makeup_list() + // No code will ever null this list, we can safely Cut it. + tgui_genetic_makeup.Cut() + + for(var/i=1, i <= NUMBER_OF_BUFFERS, i++) + if(genetic_makeup_buffer[i]) + tgui_genetic_makeup["[i]"] = genetic_makeup_buffer[i].Copy() + else + tgui_genetic_makeup["[i]"] = null + +/** + * Builds the genetic makeup list which will be sent to tgui interface. + * + * Will iterate over the connected scanner occupant, DNA Console, inserted + * diskette and chromosomes and any advanced injectors, building the main data + * structures which get passed to the tgui interface. + */ +/obj/machinery/computer/scan_consolenew/proc/build_mutation_list(can_modify_occ) + // No code will ever null these lists. We can safely Cut them. + tgui_occupant_mutations.Cut() + tgui_diskette_mutations.Cut() + tgui_console_mutations.Cut() + tgui_console_chromosomes.Cut() + tgui_advinjector_mutations.Cut() + + // ------------------------------------------------------------------------ // + // GUARD CHECK - Can we genetically modify the occupant? This check will have + // previously included checks to make sure the DNA Scanner is still + // operational + if(can_modify_occ) + // ---------------------------------------------------------------------- // + // Start cataloguing all mutations that the occupant has by default + for(var/mutation_type in scanner_occupant.dna.mutation_index) + var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(mutation_type) + + var/list/mutation_data = list() + var/text_sequence = scanner_occupant.dna.mutation_index[mutation_type] + var/default_sequence = scanner_occupant.dna.default_mutation_genes[mutation_type] + var/discovered = (stored_research && (mutation_type in stored_research.discovered_mutations)) + + mutation_data["Alias"] = HM.alias + mutation_data["Sequence"] = text_sequence + mutation_data["DefaultSeq"] = default_sequence + mutation_data["Discovered"] = discovered + mutation_data["Source"] = "occupant" + + // We only want to pass this information along to the tgui interface if + // the mutation has been discovered. Prevents people being able to cheese + // or "hack" their way to figuring out what undiscovered mutations are + if(discovered) + mutation_data["Name"] = HM.name + mutation_data["Description"] = HM.desc + mutation_data["Instability"] = HM.instability * GET_MUTATION_STABILIZER(HM) + mutation_data["Quality"] = HM.quality + + // Assume the mutation is normal unless assigned otherwise. + var/mut_class = MUT_NORMAL + + // Check if the mutation is currently activated. If it is, we can add even + // MORE information to send to tgui. + var/datum/mutation/human/A = scanner_occupant.dna.get_mutation(mutation_type) + if(A) + mutation_data["Active"] = TRUE + mutation_data["Scrambled"] = A.scrambled + mutation_data["Class"] = A.class + mut_class = A.class + mutation_data["CanChromo"] = A.can_chromosome + mutation_data["ByondRef"] = REF(A) + mutation_data["Type"] = A.type + if(A.can_chromosome) + mutation_data["ValidChromos"] = jointext(A.valid_chrom_list, ", ") + mutation_data["AppliedChromo"] = A.chromosome_name + mutation_data["ValidStoredChromos"] = build_chrom_list(A) + else + mutation_data["Active"] = FALSE + mutation_data["Scrambled"] = FALSE + mutation_data["Class"] = MUT_NORMAL + + // Technically NONE of these mutations should be MUT_EXTRA but this will + // catch any weird edge cases + // Assign icons by priority - MUT_EXTRA will ALSO be discovered, so it + // has a higher priority for icon/image assignment + if (mut_class == MUT_EXTRA) + mutation_data["Image"] = "dna_extra.gif" + else if(discovered) + mutation_data["Image"] = "dna_discovered.gif" + else + mutation_data["Image"] = "dna_undiscovered.gif" + + tgui_occupant_mutations += list(mutation_data) + + // ---------------------------------------------------------------------- // + // Now get additional/"extra" mutations that they shouldn't have by default + for(var/datum/mutation/human/HM in scanner_occupant.dna.mutations) + // If it's in the mutation index array, we've already catalogued this + // mutation and can safely skip over it. It really shouldn't be, but this + // will catch any weird edge cases + if(HM.type in scanner_occupant.dna.mutation_index) + continue + + var/list/mutation_data = list() + var/text_sequence = GET_SEQUENCE(HM.type) + + // These will all be active mutations. They're added by injector and their + // sequencing code can't be changed. They can only be nullified, which + // completely removes them. + var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(HM.type) + + mutation_data["Alias"] = A.alias + mutation_data["Sequence"] = text_sequence + mutation_data["Discovered"] = TRUE + mutation_data["Quality"] = HM.quality + mutation_data["Source"] = "occupant" + + mutation_data["Name"] = HM.name + mutation_data["Description"] = HM.desc + mutation_data["Instability"] = HM.instability * GET_MUTATION_STABILIZER(HM) + + mutation_data["Active"] = TRUE + mutation_data["Scrambled"] = HM.scrambled + mutation_data["Class"] = HM.class + mutation_data["CanChromo"] = HM.can_chromosome + mutation_data["ByondRef"] = REF(HM) + mutation_data["Type"] = HM.type + + if(HM.can_chromosome) + mutation_data["ValidChromos"] = jointext(HM.valid_chrom_list, ", ") + mutation_data["AppliedChromo"] = HM.chromosome_name + mutation_data["ValidStoredChromos"] = build_chrom_list(HM) + + // Nothing in this list should be undiscovered. Technically nothing + // should be anything but EXTRA. But we're just handling some edge cases. + if (HM.class == MUT_EXTRA) + mutation_data["Image"] = "dna_extra.gif" + else + mutation_data["Image"] = "dna_discovered.gif" + + tgui_occupant_mutations += list(mutation_data) + + // ------------------------------------------------------------------------ // + // Build the list of mutations stored within the DNA Console + for(var/datum/mutation/human/HM in stored_mutations) + var/list/mutation_data = list() + + var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(HM.type) + + mutation_data["Alias"] = A.alias + mutation_data["Name"] = HM.name + mutation_data["Source"] = "console" + mutation_data["Active"] = TRUE + mutation_data["Description"] = HM.desc + mutation_data["Instability"] = HM.instability * GET_MUTATION_STABILIZER(HM) + mutation_data["ByondRef"] = REF(HM) + mutation_data["Type"] = HM.type + + mutation_data["CanChromo"] = HM.can_chromosome + if(HM.can_chromosome) + mutation_data["ValidChromos"] = jointext(HM.valid_chrom_list, ", ") + mutation_data["AppliedChromo"] = HM.chromosome_name + mutation_data["ValidStoredChromos"] = build_chrom_list(HM) + + tgui_console_mutations += list(mutation_data) + + // ------------------------------------------------------------------------ // + // Build the list of chromosomes stored within the DNA Console + var/chrom_index = 1 + for(var/obj/item/chromosome/CM in stored_chromosomes) + var/list/chromo_data = list() + + chromo_data["Name"] = CM.name + chromo_data["Description"] = CM.desc + chromo_data["Index"] = chrom_index + + tgui_console_chromosomes += list(chromo_data) + ++chrom_index + + // ------------------------------------------------------------------------ // + // Build the list of mutations stored on any inserted diskettes + if(diskette) + for(var/datum/mutation/human/HM in diskette.mutations) + var/list/mutation_data = list() + + var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(HM.type) + + mutation_data["Alias"] = A.alias + mutation_data["Name"] = HM.name + mutation_data["Active"] = TRUE + //mutation_data["Sequence"] = GET_SEQUENCE(HM.type) + mutation_data["Source"] = "disk" + mutation_data["Description"] = HM.desc + mutation_data["Instability"] = HM.instability * GET_MUTATION_STABILIZER(HM) + mutation_data["ByondRef"] = REF(HM) + mutation_data["Type"] = HM.type + + mutation_data["CanChromo"] = HM.can_chromosome + if(HM.can_chromosome) + mutation_data["ValidChromos"] = jointext(HM.valid_chrom_list, ", ") + mutation_data["AppliedChromo"] = HM.chromosome_name + mutation_data["ValidStoredChromos"] = build_chrom_list(HM) + + tgui_diskette_mutations += list(mutation_data) + + // ------------------------------------------------------------------------ // + // Build the list of mutations stored within any Advanced Injectors + if(LAZYLEN(injector_selection)) + for(var/I in injector_selection) + var/list/mutations = list() + for(var/datum/mutation/human/HM in injector_selection[I]) + var/list/mutation_data = list() + + var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(HM.type) + + mutation_data["Alias"] = A.alias + mutation_data["Name"] = HM.name + mutation_data["Active"] = TRUE + //mutation_data["Sequence"] = GET_SEQUENCE(HM.type) + mutation_data["Source"] = "injector" + mutation_data["Description"] = HM.desc + mutation_data["Instability"] = HM.instability * GET_MUTATION_STABILIZER(HM) + mutation_data["ByondRef"] = REF(HM) + mutation_data["Type"] = HM.type + + if(HM.can_chromosome) + mutation_data["AppliedChromo"] = HM.chromosome_name + + mutations += list(mutation_data) + tgui_advinjector_mutations += list(list( + "name" = "[I]", + "mutations" = mutations, + )) + +/** + * Takes any given chromosome and calculates chromosome compatibility + * + * Will iterate over the stored chromosomes in the DNA Console and will check + * whether it can be applied to the supplied mutation. Then returns a list of + * names of chromosomes that were compatible. + * + * Arguments: + * * mutation - The mutation to check chromosome compatibility with + */ +/obj/machinery/computer/scan_consolenew/proc/build_chrom_list(mutation) + var/list/chromosomes = list() + + for(var/obj/item/chromosome/CM in stored_chromosomes) + if(CM.can_apply(mutation)) + chromosomes += CM.name + + return chromosomes + +/** + * Checks whether a mutation alias has been discovered + * + * Checks whether a given mutation's genetic sequence has been completed and + * discovers it if appropriate + * + * Arguments: + * * alias - Alias of the mutation to check (ie "Mutation 51" or "Mutation 12") + */ +/obj/machinery/computer/scan_consolenew/proc/check_discovery(alias) + // Note - All code paths that call this have already done checks on the + // current occupant to prevent cheese and other abuses. If you call this + // proc please also do the following checks first: + // if(!can_modify_occupant()) + // return + // if(!(scanner_occupant == connected_scanner.occupant)) + // return + + // Turn the alias ("Mutation 1", "Mutation 35") into a mutation path + var/path = GET_MUTATION_TYPE_FROM_ALIAS(alias) + + // Check to see if this mutation is in the active mutation list. If it isn't, + // then the mutation isn't eligible for discovery. If it is but is scrambled, + // then the mutation isn't eligible for discovery. Finally, check if the + // mutation is in discovered mutations - If it isn't, add it to discover. + var/datum/mutation/human/M = scanner_occupant.dna.get_mutation(path) + if(!M) + return FALSE + if(M.scrambled) + return FALSE + if(stored_research && !(path in stored_research.discovered_mutations)) + var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(path) + stored_research.discovered_mutations += path + say("Successfully discovered [HM.name].") + return TRUE + + return FALSE + +/** + * Find a mutation from various storage locations via ATOM ref + * + * Takes an ATOM Ref and searches the appropriate mutation buffers and storage + * vars to try and find the associated mutation. + * + * Arguments: + * * ref - ATOM ref of the mutation to locate + * * target_flags - Flags for storage mediums to search, see #defines + */ +/obj/machinery/computer/scan_consolenew/proc/get_mut_by_ref(ref, target_flags) + var/mutation + + // Assume the occupant is valid and the check has been carried out before + // calling this proc with the relevant flags. + if(target_flags & SEARCH_OCCUPANT) + mutation = (locate(ref) in scanner_occupant.dna.mutations) + if(mutation) + return mutation + + if(target_flags & SEARCH_STORED) + mutation = (locate(ref) in stored_mutations) + if(mutation) + return mutation + + if(diskette && (target_flags & SEARCH_DISKETTE)) + mutation = (locate(ref) in diskette.mutations) + if(mutation) + return mutation + + if(injector_selection && (target_flags & SEARCH_ADV_INJ)) + for(var/I in injector_selection) + mutation = (locate(ref) in injector_selection["[I]"]) + if(mutation) + return mutation + + return null + +/** + * Creates a randomised accuracy value for the enzyme pulse functionality. + * + * Donor code from previous DNA Console iteration. + * + * Arguments: + * * position - Index of the intended enzyme element to pulse + * * radduration - Duration of intended radiation pulse + * * number_of_blocks - Number of individual data blocks in the pulsed enzyme + */ +/obj/machinery/computer/scan_consolenew/proc/randomize_radiation_accuracy(position, radduration, number_of_blocks) + var/val = round(gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration) + position, 1) + return WRAP(val, 1, number_of_blocks+1) + +/** + * Scrambles an enzyme element value for the enzyme pulse functionality. + * + * Donor code from previous DNA Console iteration. + * + * Arguments: + * * input - Enzyme identity element to scramble, expected hex value + * * rs - Strength of radiation pulse, increases the range of possible outcomes + */ +/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs) var/length = length(input) var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER) if(ran == 0) @@ -940,98 +1950,71 @@ ran = -round(-ran) //positive, so ceiling it return num2hex(WRAP(hex2num(input)+ran, 0, 16**length), length) -/obj/machinery/computer/scan_consolenew/proc/randomize_radiation_accuracy(position, radduration, number_of_blocks) - var/val = round(gaussian(0, RADIATION_ACCURACY_MULTIPLIER/radduration) + position, 1) - return WRAP(val, 1, number_of_blocks+1) + /** + * Performs the enzyme radiation pulse. + * + * Donor code from previous DNA Console iteration. Called from process() when + * there is a radiation pulse in progress. Ends processing. + */ +/obj/machinery/computer/scan_consolenew/proc/rad_pulse() + // GUARD CHECK - Can we genetically modify the occupant? Includes scanner + // operational guard checks. + // If we can't, abort the procedure. + if(!can_modify_occupant()) + rad_pulse_index = 0 + STOP_PROCESSING(SSobj, src) + return -/obj/machinery/computer/scan_consolenew/proc/get_viable_occupant() - var/mob/living/carbon/viable_occupant = null - if(connected) - viable_occupant = connected.occupant - if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE)) - viable_occupant = null - return viable_occupant + var/len = length_char(scanner_occupant.dna.uni_identity) + var/num = randomize_radiation_accuracy(rad_pulse_index, radduration + (connected_scanner.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2 //Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low + var/hex = copytext_char(scanner_occupant.dna.uni_identity, num, num+1) + hex = scramble(hex, radstrength, radduration) -/obj/machinery/computer/scan_consolenew/proc/apply_buffer(action,buffer_num) - buffer_num = clamp(buffer_num, 1, NUMBER_OF_BUFFERS) - var/list/buffer_slot = buffer[buffer_num] - var/mob/living/carbon/viable_occupant = get_viable_occupant() - if(istype(buffer_slot)) - viable_occupant.radiation += rand(100/(connected.damage_coeff ** 2),250/(connected.damage_coeff ** 2)) - //15 and 40 are just magic numbers that were here before so i didnt touch them, they are initial boundaries of damage - //Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3 - //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove - switch(action) - if(SCANNER_ACTION_UI) - if(buffer_slot["UI"]) - viable_occupant.dna.uni_identity = buffer_slot["UI"] - viable_occupant.updateappearance(mutations_overlay_update=1) - if(SCANNER_ACTION_UE) - if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) - viable_occupant.real_name = buffer_slot["name"] - viable_occupant.name = buffer_slot["name"] - viable_occupant.dna.unique_enzymes = buffer_slot["UE"] - viable_occupant.dna.blood_type = buffer_slot["blood_type"] - if(SCANNER_ACTION_MIXED) - if(buffer_slot["UI"]) - viable_occupant.dna.uni_identity = buffer_slot["UI"] - viable_occupant.updateappearance(mutations_overlay_update=1) - if(buffer_slot["name"] && buffer_slot["UE"] && buffer_slot["blood_type"]) - viable_occupant.real_name = buffer_slot["name"] - viable_occupant.name = buffer_slot["name"] - viable_occupant.dna.unique_enzymes = buffer_slot["UE"] - viable_occupant.dna.blood_type = buffer_slot["blood_type"] + scanner_occupant.dna.uni_identity = copytext_char(scanner_occupant.dna.uni_identity, 1, num) + hex + copytext_char(scanner_occupant.dna.uni_identity, num + 1) + scanner_occupant.updateappearance(mutations_overlay_update=1) -/obj/machinery/computer/scan_consolenew/proc/on_scanner_close() - if(delayed_action && get_viable_occupant()) - to_chat(connected.occupant, "[src] activates!") - apply_buffer(delayed_action["action"],delayed_action["buffer"]) - delayed_action = null //or make it stick + reset button ? + rad_pulse_index = 0 + STOP_PROCESSING(SSobj, src) + return -/obj/machinery/computer/scan_consolenew/proc/get_valid_mutation(mutation) - var/mob/living/carbon/C = get_viable_occupant() - if(C) - var/datum/mutation/human/HM = C.dna.get_mutation(mutation) - if(HM) - return HM - for(var/datum/mutation/human/A in stored_mutations) - if(A.type == mutation) - return A +/** + * Sets the default state for the tgui interface. + */ +/obj/machinery/computer/scan_consolenew/proc/set_default_state() + tgui_view_state["consoleMode"] = "storage" + tgui_view_state["storageMode"] = "console" + tgui_view_state["storageConsSubMode"] = "mutations" + tgui_view_state["storageDiskSubMode"] = "mutations" +/** + * Ejects the DNA Disk from the console. + * + * Will insert into the user's hand if possible, otherwise will drop it at the + * console's location. + * + * Arguments: + * * user - The mob that is attempting to eject the diskette. + */ +/obj/machinery/computer/scan_consolenew/proc/eject_disk(mob/user) + // Check for diskette. + if(!diskette) + return -/obj/machinery/computer/scan_consolenew/proc/get_mutation_list(include_storage) //Returns a list of the mutation index types and any extra mutations - var/mob/living/carbon/viable_occupant = get_viable_occupant() - var/list/paths = list() - if(viable_occupant) - for(var/A in viable_occupant.dna.mutation_index) - paths += A - for(var/datum/mutation/human/A in viable_occupant.dna.mutations) - if(A.class == MUT_EXTRA) - paths += A.type - if(include_storage) - for(var/datum/mutation/human/A in stored_mutations) - paths += A.type - return paths + to_chat(user, "You eject [diskette] from [src].") -/obj/machinery/computer/scan_consolenew/proc/get_valid_gene_string(mutation) - var/mob/living/carbon/C = get_viable_occupant() - if(C && (mutation in C.dna.mutation_index)) - return GET_GENE_STRING(mutation, C.dna) - else if(C && (LAZYLEN(C.dna.mutations))) - for(var/datum/mutation/human/A in C.dna.mutations) - if(A.type == mutation) - return GET_SEQUENCE(mutation) - for(var/datum/mutation/human/A in stored_mutations) - if(A.type == mutation) - return GET_SEQUENCE(mutation) + // Reset the state to console storage. + tgui_view_state["storageMode"] = "console" + + // If the disk shouldn't pop into the user's hand for any reason, drop it on the console instead. + if(!istype(user) || !Adjacent(user) || !user.put_in_active_hand(diskette)) + diskette.forceMove(drop_location()) + diskette = null -/obj/machinery/computer/scan_consolenew/proc/discover(mutation) - if(stored_research && !(mutation in stored_research.discovered_mutations)) - stored_research.discovered_mutations += mutation - return TRUE -/////////////////////////// DNA MACHINES #undef INJECTOR_TIMEOUT #undef NUMBER_OF_BUFFERS +#undef SCRAMBLE_TIMEOUT +#undef JOKER_TIMEOUT +#undef JOKER_UPGRADE #undef RADIATION_STRENGTH_MAX #undef RADIATION_STRENGTH_MULTIPLIER @@ -1041,11 +2024,9 @@ #undef RADIATION_IRRADIATION_MULTIPLIER -#undef SCANNER_ACTION_SE -#undef SCANNER_ACTION_UI -#undef SCANNER_ACTION_UE -#undef SCANNER_ACTION_MIXED +#undef STATUS_TRANSFORMING -//#undef BAD_MUTATION_DIFFICULTY -//#undef GOOD_MUTATION_DIFFICULTY -//#undef OP_MUTATION_DIFFICULTY +#undef SEARCH_OCCUPANT +#undef SEARCH_STORED +#undef SEARCH_DISKETTE +#undef SEARCH_ADV_INJ diff --git a/code/game/machinery/computer/launchpad_control.dm b/code/game/machinery/computer/launchpad_control.dm index 1924cd9f23..b2f7ae73a1 100644 --- a/code/game/machinery/computer/launchpad_control.dm +++ b/code/game/machinery/computer/launchpad_control.dm @@ -53,10 +53,10 @@ var/obj/machinery/launchpad/pad = launchpads[number] return pad -/obj/machinery/computer/launchpad/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) +/obj/machinery/computer/launchpad/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "launchpad_console", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "LaunchpadConsole", name) ui.open() /obj/machinery/computer/launchpad/ui_data(mob/user) @@ -128,4 +128,4 @@ if("pull") teleport(usr, current_pad, FALSE) . = TRUE - . = TRUE \ No newline at end of file + . = TRUE diff --git a/code/game/machinery/computer/prisoner/gulag_teleporter.dm b/code/game/machinery/computer/prisoner/gulag_teleporter.dm index ca75ff1dd0..13727b585b 100644 --- a/code/game/machinery/computer/prisoner/gulag_teleporter.dm +++ b/code/game/machinery/computer/prisoner/gulag_teleporter.dm @@ -6,8 +6,6 @@ icon_keyboard = "security_key" req_access = list(ACCESS_ARMORY) circuit = /obj/item/circuitboard/computer/gulag_teleporter_console - ui_x = 350 - ui_y = 295 var/default_goal = 200 var/obj/machinery/gulag_teleporter/teleporter = null @@ -21,11 +19,10 @@ . = ..() scan_machinery() -/obj/machinery/computer/prisoner/gulag_teleporter_computer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "gulag_console", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "GulagTeleporterConsole", name) ui.open() /obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user) diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm index 2621616759..401d05da12 100644 --- a/code/game/machinery/computer/robot.dm +++ b/code/game/machinery/computer/robot.dm @@ -5,163 +5,122 @@ icon_keyboard = "rd_key" req_access = list(ACCESS_ROBOTICS) circuit = /obj/item/circuitboard/computer/robotics - var/temp = null - light_color = LIGHT_COLOR_PINK + ui_x = 500 + ui_y = 460 /obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R) + . = FALSE if(!istype(R)) - return FALSE + return if(isAI(user)) - if (R.connected_ai != user) - return FALSE + if(R.connected_ai != user) + return if(iscyborg(user)) - if (R != user) - return FALSE + if(R != user) + return if(R.scrambledcodes) - return FALSE - if (hasSiliconAccessInArea(user) && !issilicon(user)) - if (!Adjacent(user)) - return FALSE + return return TRUE -/obj/machinery/computer/robotics/ui_interact(mob/user) - . = ..() - if (src.z > 6) - to_chat(user, "Unable to establish a connection: \black You're too far away from the station!") - return - user.set_machine(src) - var/dat - var/robots = 0 +/obj/machinery/computer/robotics/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "RoboticsControlConsole", name) + ui.open() + +/obj/machinery/computer/robotics/ui_data(mob/user) + var/list/data = list() + + data["can_hack"] = FALSE + if(issilicon(user)) + var/mob/living/silicon/S = user + if(S.hack_software) + data["can_hack"] = TRUE + else if(IsAdminGhost(user)) + data["can_hack"] = TRUE + + data["cyborgs"] = list() for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs) if(!can_control(user, R)) continue - robots++ - dat += "[R.name] |" - if(R.stat) - dat += " Not Responding |" - else if(R.locked_down) - dat += " Locked Down |" - else - dat += " Operating Normally |" - if(R.cell) - dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |" - else - dat += " No Cell Installed |" - if(R.module) - dat += " Module Installed ([R.module.name]) |" - else - dat += " No Module Installed |" - if(R.connected_ai) - dat += " Slaved to [R.connected_ai.name] |" - else - dat += " Independent from AI |" - if(issilicon(user) && user != R) - var/mob/living/silicon/S = user - if(is_servant_of_ratvar(S)) - dat += "(Convert) " - else if(S.hack_software && !R.emagged) - dat += "(Hack) " - else if(IsAdminGhost(user) && !R.emagged) - dat += "(Hack) " - dat += "([R.locked_down? "Lockdown" : "Release"]) " - dat += "(Destroy)" - dat += "
    " + if(z != (get_turf(R)).z) + continue + var/list/cyborg_data = list( + name = R.name, + locked_down = R.locked_down, + status = R.stat, + charge = R.cell ? round(R.cell.percent()) : null, + module = R.module ? "[R.module.name] Module" : "No Module Detected", + synchronization = R.connected_ai, + emagged = R.emagged, + ref = REF(R) + ) + data["cyborgs"] += list(cyborg_data) - if(!robots) - dat += "No Cyborg Units detected within access parameters." - dat += "
    " - - var/drones = 0 + data["drones"] = list() for(var/mob/living/simple_animal/drone/D in GLOB.drones_list) if(D.hacked) continue - drones++ - dat += "[D.name] |" - if(D.stat) - dat += " Not Responding |" - dat += "(Destroy)" - dat += "
    " + if(z != (get_turf(D)).z) + continue + var/list/drone_data = list( + name = D.name, + status = D.stat, + ref = REF(D) + ) + data["drones"] += list(drone_data) - if(!drones) - dat += "No Drone Units detected within access parameters." + return data - var/datum/browser/popup = new(user, "computer", "Cyborg Control Console", 400, 500) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - return - -/obj/machinery/computer/robotics/Topic(href, href_list) +/obj/machinery/computer/robotics/ui_act(action, params) if(..()) return - if (href_list["temp"]) - src.temp = null - - else if (href_list["killbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["killbot"]) in GLOB.silicon_mobs - if(can_control(usr, R)) - var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm" && can_control(usr, R) && !..()) + switch(action) + if("killbot") + if(allowed(usr)) + var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs + if(can_control(usr, R) && !..()) var/turf/T = get_turf(R) message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(R, R.client)] at [ADMIN_VERBOSEJMP(T)]!") log_game("\[key_name(usr)] detonated [key_name(R)]!") if(R.connected_ai) to_chat(R.connected_ai, "

    ALERT - Cyborg detonation detected: [R.name]
    ") R.self_destruct() - else - to_chat(usr, "Access Denied.") - - else if (href_list["stopbot"]) - if(src.allowed(usr)) - var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs - if(can_control(usr, R)) - var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort") - if(choice == "Confirm" && can_control(usr, R) && !..()) - message_admins("[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!") + else + to_chat(usr, "Access Denied.") + if("stopbot") + if(allowed(usr)) + var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs + if(can_control(usr, R) && !..()) + message_admins("[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!") log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!") R.SetLockdown(!R.locked_down) to_chat(R, "[!R.locked_down ? "Your lockdown has been lifted!" : "You have been locked down!"]") if(R.connected_ai) to_chat(R.connected_ai, "[!R.locked_down ? "NOTICE - Cyborg lockdown lifted" : "ALERT - Cyborg lockdown detected"]: [R.name]
    ") - - else - to_chat(usr, "Access Denied.") - - else if (href_list["magbot"]) - var/mob/living/silicon/S = usr - if((istype(S) && S.hack_software) || IsAdminGhost(usr)) - var/mob/living/silicon/robot/R = locate(href_list["magbot"]) in GLOB.silicon_mobs - if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R)) - log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!") - message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!") - R.SetEmagged(1) - - else if(href_list["convert"]) - if(isAI(usr) && is_servant_of_ratvar(usr)) - var/mob/living/silicon/robot/R = locate(href_list["convert"]) in GLOB.silicon_mobs - if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr) - log_game("[key_name(usr)] converted [key_name(R)] using robotic console!") - message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!") - add_servant_of_ratvar(R) - - else if (href_list["killdrone"]) - if(src.allowed(usr)) - var/mob/living/simple_animal/drone/D = locate(href_list["killdrone"]) in GLOB.mob_list - if(D.hacked) - to_chat(usr, "ERROR: [D] is not responding to external commands.") else - var/turf/T = get_turf(D) - message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!") - log_game("[key_name(usr)] detonated [key_name(D)]!") - var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread - s.set_up(3, 1, D) - s.start() - D.visible_message("\the [D] self destructs!") - D.gib() - - - src.updateUsrDialog() - return + to_chat(usr, "Access Denied.") + if("magbot") + var/mob/living/silicon/S = usr + if((istype(S) && S.hack_software) || IsAdminGhost(usr)) + var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs + if(istype(R) && !R.emagged && (R.connected_ai == usr || IsAdminGhost(usr)) && !R.scrambledcodes && can_control(usr, R)) + log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!") + message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!") + R.SetEmagged(TRUE) + if("killdrone") + if(allowed(usr)) + var/mob/living/simple_animal/drone/D = locate(params["ref"]) in GLOB.mob_list + if(D.hacked) + to_chat(usr, "ERROR: [D] is not responding to external commands.") + else + var/turf/T = get_turf(D) + message_admins("[ADMIN_LOOKUPFLW(usr)] detonated [key_name_admin(D)] at [ADMIN_VERBOSEJMP(T)]!") + log_game("[key_name(usr)] detonated [key_name(D)]!") + var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread + s.set_up(3, TRUE, D) + s.start() + D.visible_message("\the [D] self-destructs!") + D.gib() diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 25f4237439..5c280eeace 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -662,7 +662,7 @@ What a mess.*/ GLOB.data_core.removeMajorCrime(active1.fields["id"], href_list["cdataid"]) if("notes") if(istype(active2, /datum/data/record)) - var/t1 = stripped_input(usr, "Please summarize notes:", "Secure. records", active2.fields["notes"], null) + var/t1 = stripped_multiline_input(usr, "Please summarize notes:", "Secure records", active2.fields["notes"], 8192) if(!canUseSecurityRecordsConsole(usr, t1, null, a2)) return active2.fields["notes"] = t1 diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index fcb18b4dff..7b2e6ab455 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -16,11 +16,10 @@ GLOB.alert_consoles -= src return ..() -/obj/machinery/computer/station_alert/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/station_alert/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "station_alert", name, 325, 500, master_ui, state) + ui = new(user, src, "StationAlertConsole", name) ui.open() /obj/machinery/computer/station_alert/ui_data(mob/user) @@ -31,6 +30,7 @@ data["alarms"][class] = list() for(var/area in alarms[class]) data["alarms"][class] += area + return data /obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source) diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index 6710258626..3a8ff7bf19 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -34,11 +34,10 @@ break return power_station -obj/machinery/computer/teleporter/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/teleporter/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "teleporter", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "Teleporter", name) ui.open() /obj/machinery/computer/teleporter/ui_data(mob/user) @@ -56,7 +55,6 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t return data - /obj/machinery/computer/teleporter/ui_act(action, params) if(..()) return @@ -92,16 +90,18 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t say("Processing hub calibration to target...") calibrating = TRUE power_station.update_icon() - spawn(50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration - calibrating = FALSE - if(check_hub_connection()) - power_station.teleporter_hub.calibrated = TRUE - say("Calibration complete.") - else - say("Error: Unable to detect hub.") - power_station.update_icon() + addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration . = TRUE +/obj/machinery/computer/teleporter/proc/finish_calibration() + calibrating = FALSE + if(check_hub_connection()) + power_station.teleporter_hub.calibrated = TRUE + say("Calibration complete.") + else + say("Error: Unable to detect hub.") + power_station.update_icon() + /obj/machinery/computer/teleporter/proc/check_hub_connection() if(!power_station) return FALSE diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 9ecc19e40f..756f924cfa 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -9,6 +9,7 @@ var/active = FALSE var/list/rangers = list() var/stop = 0 + var/volume = 70 var/datum/track/selection = null /obj/machinery/jukebox/disco @@ -51,74 +52,91 @@ else icon_state = "[initial(icon_state)]" -/obj/machinery/jukebox/ui_interact(mob/user) - . = ..() - if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) - return - if (!anchored) +/obj/machinery/jukebox/ui_status(mob/user) + if(!anchored) to_chat(user,"This device must be anchored by a wrench!") - return - if(!allowed(user)) + return UI_CLOSE + if(!allowed(user) && !isobserver(user)) to_chat(user,"Error: Access Denied.") - user.playsound_local(src,'sound/misc/compiler-failure.ogg', 25, 1) - return - if(!SSjukeboxes.songs.len) + user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE) + return UI_CLOSE + if(!SSjukeboxes.songs.len && !isobserver(user)) to_chat(user,"Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.") - playsound(src,'sound/misc/compiler-failure.ogg', 25, 1) - return - var/list/dat = list() - dat +="
    " - dat += " Select Track
    " - if(istype(selection)) - dat += "Track Selected: [selection.song_name]
    " - dat += "Track Length: [DisplayTimeText(selection.song_length)]

    " - else - dat += "Track Selected: None!

    " - var/datum/browser/popup = new(user, "vending", "[name]", 400, 350) - popup.set_content(dat.Join()) - popup.open() + playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE) + return UI_CLOSE + return ..() +/obj/machinery/jukebox/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Jukebox", name) + ui.open() -/obj/machinery/jukebox/Topic(href, href_list) - if(..()) +/obj/machinery/jukebox/ui_data(mob/user) + var/list/data = list() + data["active"] = active + data["songs"] = list() + for(var/datum/track/S in SSjukeboxes.songs) + var/list/track_data = list( + name = S.song_name + ) + data["songs"] += list(track_data) + data["track_selected"] = null + data["track_length"] = null + data["track_beat"] = null + if(selection) + data["track_selected"] = selection.song_name + data["track_length"] = DisplayTimeText(selection.song_length) + data["track_beat"] = selection.song_beat + data["volume"] = volume + return data + +/obj/machinery/jukebox/ui_act(action, list/params) + . = ..() + if(.) return - add_fingerprint(usr) - switch(href_list["action"]) + + switch(action) if("toggle") - if (QDELETED(src)) + if(QDELETED(src)) return if(!active) if(stop > world.time) to_chat(usr, "Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].") - playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) + playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE) return - if(!istype(selection)) - to_chat(usr, "Error: Severe user incompetence detected.") - playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) - return - if(!activate_music()) - to_chat(usr, "Error: Generic hardware failure.") - playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) - return - updateUsrDialog() - else if(active) + activate_music() + START_PROCESSING(SSobj, src) + return TRUE + else stop = 0 - updateUsrDialog() - if("select") + return TRUE + if("select_track") if(active) to_chat(usr, "Error: You cannot change the song until the current one is over.") return - var/list/available = list() for(var/datum/track/S in SSjukeboxes.songs) available[S.song_name] = S - var/selected = input(usr, "Choose your song", "Track:") as null|anything in available + var/selected = params["track"] if(QDELETED(src) || !selected || !istype(available[selected], /datum/track)) return selection = available[selected] - updateUsrDialog() + return TRUE + if("set_volume") + var/new_volume = params["volume"] + if(new_volume == "reset") + volume = initial(volume) + return TRUE + else if(new_volume == "min") + volume = 0 + return TRUE + else if(new_volume == "max") + volume = 100 + return TRUE + else if(text2num(new_volume) != null) + volume = text2num(new_volume) + return TRUE /obj/machinery/jukebox/proc/activate_music() var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2) diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm index 5c13bfdf5d..677cbe1208 100644 --- a/code/game/machinery/defibrillator_mount.dm +++ b/code/game/machinery/defibrillator_mount.dm @@ -59,7 +59,7 @@ return defib.get_cell() //defib interaction -/obj/machinery/defibrillator_mount/attack_hand(mob/living/user) +/obj/machinery/defibrillator_mount/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(!defib) to_chat(user, "There's no defibrillator unit loaded!") return diff --git a/code/game/machinery/dish_drive.dm b/code/game/machinery/dish_drive.dm index 31e6a3cfeb..3cfd8fdfc4 100644 --- a/code/game/machinery/dish_drive.dm +++ b/code/game/machinery/dish_drive.dm @@ -31,7 +31,7 @@ if(user.Adjacent(src)) . += "Alt-click it to beam its contents to any nearby disposal bins." -/obj/machinery/dish_drive/attack_hand(mob/living/user) +/obj/machinery/dish_drive/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(!contents.len) to_chat(user, "There's nothing in [src]!") return diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index 4b2ba85d11..e721e986d2 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -15,6 +15,7 @@ var/precision_coeff var/message_cooldown var/breakout_time = 1200 + var/obj/machinery/computer/scan_consolenew/linked_console = null /obj/machinery/dna_scannernew/RefreshParts() scan_level = 0 @@ -22,8 +23,8 @@ precision_coeff = 0 for(var/obj/item/stock_parts/scanning_module/P in component_parts) scan_level += P.rating - for(var/obj/item/stock_parts/matter_bin/P in component_parts) - precision_coeff = P.rating + for(var/obj/item/stock_parts/matter_bin/M in component_parts) + precision_coeff = M.rating for(var/obj/item/stock_parts/micro_laser/P in component_parts) damage_coeff = P.rating @@ -31,11 +32,8 @@ . = ..() if(in_range(user, src) || isobserver(user)) . += "The status display reads: Radiation pulse accuracy increased by factor [precision_coeff**2].
    Radiation pulse damage decreased by factor [damage_coeff**2].
    " - if(scan_level >= 3) - . += "Scanner has been upgraded to support autoprocessing." /obj/machinery/dna_scannernew/update_icon_state() - //no power or maintenance if(stat & (NOPOWER|BROKEN)) icon_state = initial(icon_state)+ (state_open ? "_open" : "") + "_unpowered" @@ -53,10 +51,6 @@ //running icon_state = initial(icon_state)+ (state_open ? "_open" : "") -/obj/machinery/dna_scannernew/power_change() - ..() - update_icon() - /obj/machinery/dna_scannernew/proc/toggle_open(mob/user) if(panel_open) to_chat(user, "Close the maintenance panel first.") @@ -76,11 +70,9 @@ if(!locked) open_machine() return - 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(breakout_time)].)", \ - "You hear a metallic creaking from [src].") + "You hear a metallic creaking from [src].") if(do_after(user,(breakout_time), target = src)) if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked) return @@ -96,33 +88,28 @@ return C return null -/obj/machinery/dna_scannernew/close_machine(atom/movable/target) +/obj/machinery/dna_scannernew/close_machine(mob/living/carbon/user) if(!state_open) return FALSE - ..(target) - - // search for ghosts, if the corpse is empty and the scanner is connected to a cloner - var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) - if(istype(mob_occupant)) - if(locate_computer(/obj/machinery/computer/cloning)) - if(!mob_occupant.suiciding && !(HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && !mob_occupant.hellbound) - mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src) + ..(user) // DNA manipulators cannot operate on severed heads or brains - if(isliving(occupant)) - var/obj/machinery/computer/scan_consolenew/console = locate_computer(/obj/machinery/computer/scan_consolenew) - if(console) - console.on_scanner_close() + if(iscarbon(occupant)) + if(linked_console) + linked_console.on_scanner_close() return TRUE /obj/machinery/dna_scannernew/open_machine() - if(state_open || panel_open) + if(state_open) return FALSE ..() + if(linked_console) + linked_console.on_scanner_open() + return TRUE /obj/machinery/dna_scannernew/relaymove(mob/user as mob) @@ -133,51 +120,49 @@ return open_machine() -/obj/machinery/dna_scannernew/screwdriver_act(mob/living/user, obj/item/I) - . = TRUE - if(..()) - return - if(occupant) - to_chat(user, "[src] is currently occupied!") - return - if(state_open) - to_chat(user, "[src] must be closed to [panel_open ? "close" : "open"] its maintenance hatch!") - return - if(default_deconstruction_screwdriver(user, icon_state, icon_state, I)) //sent icon_state is irrelevant... - update_icon() //..since we're updating the icon here, since the scanner can be unpowered when opened/closed - return - return FALSE +/obj/machinery/dna_scannernew/attackby(obj/item/I, mob/user, params) -/obj/machinery/dna_scannernew/wrench_act(mob/living/user, obj/item/I) - . = ..() - if(default_change_direction_wrench(user, I)) - return TRUE + if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))//sent icon_state is irrelevant... + update_icon()//..since we're updating the icon here, since the scanner can be unpowered when opened/closed + return -/obj/machinery/dna_scannernew/crowbar_act(mob/living/user, obj/item/I) - . = ..() if(default_pry_open(I)) - return TRUE - if(default_deconstruction_crowbar(I)) - return TRUE + return -/obj/machinery/dna_scannernew/default_pry_open(obj/item/I) //wew - . = !(state_open || panel_open || (flags_1 & NODECONSTRUCT_1)) && I.tool_behaviour == TOOL_CROWBAR - if(.) - I.play_tool_sound(src, 50) - visible_message("[usr] pries open [src].", "You pry open [src].") - open_machine() + if(default_deconstruction_crowbar(I)) + return + + return ..() /obj/machinery/dna_scannernew/interact(mob/user) toggle_open(user) -/obj/machinery/dna_scannernew/AltClick(mob/user) - . = ..() - if(!user.canUseTopic(src, !hasSiliconAccessInArea(user))) - return - interact(user) - return TRUE - /obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) + var/mob/living/L = user + if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser()) return close_machine(target) + + +//Just for transferring between genetics machines. +/obj/item/disk/data + name = "DNA data disk" + icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk. + var/list/genetic_makeup_buffer = list() + var/list/fields = list() + var/list/mutations = list() + var/max_mutations = 6 + var/read_only = FALSE //Well,it's still a floppy disk + +/obj/item/disk/data/Initialize() + . = ..() + icon_state = "datadisk[rand(0,6)]" + add_overlay("datadisk_gene") + +/obj/item/disk/data/attack_self(mob/user) + read_only = !read_only + to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].") + +/obj/item/disk/data/examine(mob/user) + . = ..() + . += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]." diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 2a45267c65..515a4672a5 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -50,7 +50,7 @@ integrity_failure = 0.25 damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N autoclose = TRUE - secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. + secondsElectrified = NOT_ELECTRIFIED //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. assemblytype = /obj/structure/door_assembly normalspeed = 1 explosion_block = 1 @@ -93,7 +93,7 @@ var/shuttledocked = 0 var/delayed_close_requested = FALSE // TRUE means the door will automatically close the next time it's opened. - var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close + air_tight = FALSE var/prying_so_hard = FALSE rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE @@ -157,6 +157,10 @@ . = ..() AddComponent(/datum/component/ntnet_interface) +/obj/machinery/door/airlock/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + if(id_tag) + id_tag = "[idnum][id_tag]" + /obj/machinery/door/airlock/proc/update_other_id() for(var/obj/machinery/door/airlock/A in GLOB.airlocks) if(A.closeOtherId == closeOtherId && A != src) @@ -188,7 +192,7 @@ /obj/machinery/door/airlock/vv_edit_var(var_name) . = ..() switch (var_name) - if ("cyclelinkeddir") + if (NAMEOF(src, cyclelinkeddir)) cyclelinkairlock() /obj/machinery/door/airlock/check_access_ntnet(datum/netdata/data) @@ -294,10 +298,10 @@ /obj/machinery/door/airlock/Destroy() QDEL_NULL(wires) + QDEL_NULL(electronics) if(charge) qdel(charge) charge = null - QDEL_NULL(electronics) if (cyclelinkedairlock) if (cyclelinkedairlock.cyclelinkedairlock == src) cyclelinkedairlock.cyclelinkedairlock = null @@ -305,7 +309,7 @@ if(id_tag) for(var/obj/machinery/doorButtons/D in GLOB.machines) D.removeMe(src) - qdel(note) + QDEL_NULL(note) for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) diag_hud.remove_from_hud(src) return ..() @@ -413,8 +417,8 @@ // shock user with probability prb (if all connections & power are working) // returns TRUE if shocked, FALSE otherwise // The preceding comment was borrowed from the grille's shock script -/obj/machinery/door/airlock/proc/shock(mob/user, prb) - if(!hasPower()) // unpowered, no shock +/obj/machinery/door/airlock/proc/shock(mob/living/user, prb) + if(!istype(user) || !hasPower()) // unpowered, no shock return FALSE if(shockCooldown > world.time) return FALSE //Already shocked someone recently? @@ -759,13 +763,10 @@ /obj/machinery/door/airlock/attack_paw(mob/user) return attack_hand(user) -/obj/machinery/door/airlock/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/door/airlock/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!(issilicon(user) || IsAdminGhost(user))) - if(src.isElectrified()) - if(src.shock(user, 100)) + if(isElectrified()) + if(shock(user, 100)) return if(ishuman(user) && prob(40) && src.density) @@ -779,6 +780,8 @@ H.apply_damage(10, BRUTE, BODY_ZONE_HEAD) else visible_message("[user] headbutts the airlock. Good thing [user.p_theyre()] wearing a helmet.") + else + return ..() /obj/machinery/door/airlock/attempt_wire_interaction(mob/user) if(security_level) @@ -787,15 +790,15 @@ return ..() /obj/machinery/door/airlock/proc/electrified_loop() - while (secondsElectrified > 0) + while (secondsElectrified > NOT_ELECTRIFIED) sleep(10) if(QDELETED(src)) return - secondsElectrified -= 1 + secondsElectrified-- updateDialog() // This is to protect against changing to permanent, mid loop. - if(secondsElectrified==0) + if(secondsElectrified == NOT_ELECTRIFIED) set_electrified(NOT_ELECTRIFIED) else set_electrified(ELECTRIFIED_PERMANENT) @@ -822,8 +825,8 @@ /obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params) if(!issilicon(user) && !IsAdminGhost(user)) - if(src.isElectrified()) - if(src.shock(user, 75)) + if(isElectrified()) + if(shock(user, 75)) return add_fingerprint(user) @@ -836,7 +839,7 @@ to_chat(user, "You need at least 2 metal sheets to reinforce [src].") return to_chat(user, "You start reinforcing [src].") - if(do_after(user, 20, 1, target = src)) + if(do_after(user, 20, TRUE, target = src)) if(!panel_open || !S.use(2)) return user.visible_message("[user] reinforces \the [src] with metal.", @@ -1058,16 +1061,16 @@ to_chat(user, "The airlock's bolts prevent it from being forced!") else if( !welded && !operating) if(!beingcrowbarred) //being fireaxe'd - var/obj/item/twohanded/fireaxe/F = I - if(F.wielded) - INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2) - else - to_chat(user, "You need to be wielding the fire axe to do that!") + var/obj/item/fireaxe/axe = I + if(!axe.wielded) + to_chat(user, "You need to be wielding \the [axe] to do that!") + return + INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2) else INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2) if(istype(I, /obj/item/crowbar/power)) - if(isElectrified()) + if(hasPower() && isElectrified()) shock(user,100)//it's like sticking a forck in a power socket return @@ -1087,12 +1090,11 @@ time_to_open = 50 playsound(src, 'sound/machines/airlock_alien_prying.ogg',100,1) //is it aliens or just the CE being a dick? prying_so_hard = TRUE - var/result = do_after(user, time_to_open,target = src) - prying_so_hard = FALSE - if(result) + if(do_after(user, time_to_open,target = src)) open(2) if(density && !open(2)) to_chat(user, "Despite your attempts, [src] refuses to open.") + prying_so_hard = FALSE /obj/machinery/door/airlock/open(forced=0) if( operating || welded || locked ) @@ -1109,7 +1111,6 @@ detonated = 1 charge = null for(var/mob/living/carbon/human/H in orange(2,src)) - H.Unconscious(160) H.adjust_fire_stacks(20) H.IgniteMob() //Guaranteed knockout and ignition for nearby people H.apply_damage(40, BRUTE, BODY_ZONE_CHEST) @@ -1357,12 +1358,25 @@ wires.cut_all() update_icon() -/obj/machinery/door/airlock/proc/set_electrified(seconds) +/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user) secondsElectrified = seconds diag_hud_set_electrified() - if(secondsElectrified > 0) + if(secondsElectrified > NOT_ELECTRIFIED) INVOKE_ASYNC(src, .proc/electrified_loop) + if(user) + var/message + switch(secondsElectrified) + if(ELECTRIFIED_PERMANENT) + message = "permanently shocked" + if(NOT_ELECTRIFIED) + message = "unshocked" + else + message = "temp shocked for [secondsElectrified] seconds" + LAZYADD(shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(user)] - ([uppertext(message)])")) + log_combat(user, src, message) + //add_hiddenprint(user) + /obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() if(obj_integrity < (0.75 * max_integrity)) @@ -1436,11 +1450,10 @@ else if(istype(note, /obj/item/photo)) return "photo" -/obj/machinery/door/airlock/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) - SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/door/airlock/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "ai_airlock", name, 500, 390, master_ui, state) + ui = new(user, src, "AiAirlock", name) ui.open() return TRUE @@ -1448,13 +1461,13 @@ var/list/data = list() var/list/power = list() - power["main"] = src.secondsMainPowerLost ? 0 : 2 // boolean - power["main_timeleft"] = src.secondsMainPowerLost - power["backup"] = src.secondsBackupPowerLost ? 0 : 2 // boolean - power["backup_timeleft"] = src.secondsBackupPowerLost + power["main"] = secondsMainPowerLost ? 0 : 2 // boolean + power["main_timeleft"] = secondsMainPowerLost + power["backup"] = secondsBackupPowerLost ? 0 : 2 // boolean + power["backup_timeleft"] = secondsBackupPowerLost data["power"] = power - data["shock"] = secondsElectrified == 0 ? 2 : 0 + data["shock"] = secondsElectrified == NOT_ELECTRIFIED ? 2 : 0 data["shock_timeleft"] = secondsElectrified data["id_scanner"] = !aiDisabledIdScanner data["emergency"] = emergency // access @@ -1491,14 +1504,14 @@ loseMainPower() update_icon() else - to_chat(usr, "Main power is already offline.") + to_chat(usr, "Main power is already offline.") . = TRUE if("disrupt-backup") if(!secondsBackupPowerLost) loseBackupPower() update_icon() else - to_chat(usr, "Backup power is already offline.") + to_chat(usr, "Backup power is already offline.") . = TRUE if("shock-restore") shock_restore(usr) @@ -1527,7 +1540,6 @@ . = TRUE if("speed-toggle") normalspeed = !normalspeed - . = TRUE if("open-close") user_toggle_open(usr) diff --git a/code/game/machinery/doors/airlock_electronics.dm b/code/game/machinery/doors/airlock_electronics.dm index ae6930f5fb..ef2be8d744 100644 --- a/code/game/machinery/doors/airlock_electronics.dm +++ b/code/game/machinery/doors/airlock_electronics.dm @@ -2,42 +2,54 @@ name = "airlock electronics" req_access = list(ACCESS_MAINT_TUNNELS) custom_price = PRICE_CHEAP - + /// A list of all granted accesses var/list/accesses = list() + /// If the airlock should require ALL or only ONE of the listed accesses var/one_access = 0 - var/unres_sides = 0 //unrestricted sides, or sides of the airlock that will open regardless of access + /// Unrestricted sides, or sides of the airlock that will open regardless of access + var/unres_sides = 0 + /// A holder of the electronics, in case of them working as an integrated part + var/holder /obj/item/electronics/airlock/examine(mob/user) . = ..() . += "Has a neat selection menu for modifying airlock access levels." -/obj/item/electronics/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) - SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/electronics/airlock/ui_state(mob/user) + return GLOB.hands_state + +/obj/item/electronics/airlock/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "airlock_electronics", name, 420, 485, master_ui, state) + ui = new(user, src, "AirlockElectronics", name) ui.open() +/obj/item/electronics/airlock/ui_static_data(mob/user) + var/list/data = list() + var/list/regions = list() + for(var/i in 1 to 7) + var/list/accesses = list() + for(var/access in get_region_accesses(i)) + if (get_access_desc(access)) + accesses += list(list( + "desc" = replacetext(get_access_desc(access), " ", " "), + "ref" = access, + )) + + regions += list(list( + "name" = get_region_accesses_name(i), + "regid" = i, + "accesses" = accesses + )) + + data["regions"] = regions + return data + /obj/item/electronics/airlock/ui_data() var/list/data = list() - var/list/regions = list() - - for(var/i in 1 to 7) - var/list/region = list() - var/list/accesses = list() - for(var/j in get_region_accesses(i)) - var/list/access = list() - access["name"] = get_access_desc(j) - access["id"] = j - access["req"] = (j in src.accesses) - accesses[++accesses.len] = access - region["name"] = get_region_accesses_name(i) - region["accesses"] = accesses - regions[++regions.len] = region - data["regions"] = regions + data["accesses"] = accesses data["oneAccess"] = one_access data["unres_direction"] = unres_sides - return data /obj/item/electronics/airlock/ui_act(action, params) @@ -48,12 +60,12 @@ accesses = list() one_access = 0 . = TRUE - if("one_access") - one_access = !one_access - . = TRUE if("grant_all") accesses = get_all_accesses() . = TRUE + if("one_access") + one_access = !one_access + . = TRUE if("set") var/access = text2num(params["access"]) if (!(access in accesses)) @@ -65,3 +77,20 @@ var/unres_direction = text2num(params["unres_direction"]) unres_sides ^= unres_direction //XOR, toggles only the bit that was clicked . = TRUE + if("grant_region") + var/region = text2num(params["region"]) + if(isnull(region)) + return + accesses |= get_region_accesses(region) + . = TRUE + if("deny_region") + var/region = text2num(params["region"]) + if(isnull(region)) + return + accesses -= get_region_accesses(region) + . = TRUE + +/obj/item/electronics/airlock/ui_host() + if(holder) + return holder + return src diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm index 530a287134..b34e97d374 100644 --- a/code/game/machinery/doors/airlock_types.dm +++ b/code/game/machinery/doors/airlock_types.dm @@ -310,6 +310,17 @@ opacity = 0 glass = TRUE +/obj/machinery/door/airlock/bronze + name = "bronze airlock" + icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi' + overlays_file = 'icons/obj/doors/airlocks/clockwork/overlays.dmi' + assemblytype = /obj/structure/door_assembly/door_assembly_bronze + +/obj/machinery/door/airlock/bronze/seethru + assemblytype = /obj/structure/door_assembly/door_assembly_bronze/seethru + opacity = 0 + glass = TRUE + ////////////////////////////////// /* Station2 Airlocks diff --git a/code/game/machinery/doors/brigdoors.dm b/code/game/machinery/doors/brigdoors.dm index 1d39372dec..b2e0050819 100644 --- a/code/game/machinery/doors/brigdoors.dm +++ b/code/game/machinery/doors/brigdoors.dm @@ -140,11 +140,10 @@ . = new_time == timer_duration //return 1 on no change timer_duration = new_time -/obj/machinery/door_timer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/door_timer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "brig_timer", name, 300, 138, master_ui, state) + ui = new(user, src, "BrigTimer", name) ui.open() //icon update function @@ -235,7 +234,7 @@ preset_time = PRESET_LONG . = set_timer(preset_time) if(timing) - activation_time = REALTIMEOFDAY + activation_time = world.time else . = FALSE diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 1fb50e13c6..d4ba70bb6c 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -11,14 +11,15 @@ max_integrity = 350 armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 70) CanAtmosPass = ATMOS_PASS_DENSITY - flags_1 = PREVENT_CLICK_UNDER_1 + flags_1 = PREVENT_CLICK_UNDER_1|DEFAULT_RICOCHET_1 ricochet_chance_mod = 0.8 interaction_flags_atom = INTERACT_ATOM_UI_INTERACT var/secondsElectrified = 0 + var/air_tight = FALSE //TRUE means density will be set as soon as the door begins to close var/shockedby - var/visible = TRUE + var/visible = TRUE // To explain: Whether the door can block line of sight when closed or not. var/operating = FALSE var/glass = FALSE var/welded = FALSE @@ -139,10 +140,7 @@ do_animate("deny") return -/obj/machinery/door/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/door/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) return try_to_activate_door(user) /obj/machinery/door/attack_tk(mob/user) @@ -161,7 +159,7 @@ open() else close() - return + return TRUE if(density) do_animate("deny") @@ -181,11 +179,36 @@ /obj/machinery/door/proc/try_to_crowbar(obj/item/I, mob/user) return +/obj/machinery/door/proc/is_holding_pressure() + var/turf/open/T = loc + if(!T) + return FALSE + if(!density) + return FALSE + // alrighty now we check for how much pressure we're holding back + var/min_moles = T.air.total_moles() + var/max_moles = min_moles + // okay this is a bit hacky. First, we set density to 0 and recalculate our adjacent turfs + density = FALSE + T.ImmediateCalculateAdjacentTurfs() + // then we use those adjacent turfs to figure out what the difference between the lowest and highest pressures we'd be holding is + for(var/turf/open/T2 in T.atmos_adjacent_turfs) + if((flags_1 & ON_BORDER_1) && get_dir(src, T2) != dir) + continue + var/moles = T2.air.total_moles() + if(moles < min_moles) + min_moles = moles + if(moles > max_moles) + max_moles = moles + density = TRUE + T.ImmediateCalculateAdjacentTurfs() // alright lets put it back + return max_moles - min_moles > 20 + /obj/machinery/door/attackby(obj/item/I, mob/user, params) - if(user.a_intent != INTENT_HARM && (istype(I, /obj/item/crowbar) || istype(I, /obj/item/twohanded/fireaxe))) + if(user.a_intent != INTENT_HARM && (I.tool_behaviour == TOOL_CROWBAR || istype(I, /obj/item/fireaxe))) try_to_crowbar(I, user) return 1 - else if(istype(I, /obj/item/weldingtool)) + else if(I.tool_behaviour == TOOL_WELDER) try_to_weld(I, user) return 1 else if(!(I.item_flags & NOBLUDGEON) && user.a_intent != INTENT_HARM) @@ -223,13 +246,13 @@ if(prob(20/severity) && (istype(src, /obj/machinery/door/airlock) || istype(src, /obj/machinery/door/window)) ) INVOKE_ASYNC(src, .proc/open) if(prob(severity*10 - 20)) - if(secondsElectrified == 0) - secondsElectrified = -1 + if(secondsElectrified == MACHINE_NOT_ELECTRIFIED) + secondsElectrified = MACHINE_ELECTRIFIED_PERMANENT LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\]EM Pulse") addtimer(CALLBACK(src, .proc/unelectrify), 300) /obj/machinery/door/proc/unelectrify() - secondsElectrified = 0 + secondsElectrified = MACHINE_NOT_ELECTRIFIED /obj/machinery/door/update_icon_state() if(density) @@ -289,8 +312,11 @@ return operating = TRUE + do_animate("closing") layer = closingLayer + if(air_tight) + density = TRUE sleep(5) density = TRUE sleep(5) @@ -302,7 +328,7 @@ update_freelook_sight() if(safe) CheckForMobs() - else + else if(!(flags_1 & ON_BORDER_1)) crush() return 1 @@ -314,6 +340,11 @@ /obj/machinery/door/proc/crush() for(var/mob/living/L in get_turf(src)) L.visible_message("[src] closes on [L], crushing [L.p_them()]!", "[src] closes on you and crushes you!") + if(iscarbon(L)) + var/mob/living/carbon/C = L + for(var/i in C.all_wounds) // should probably replace with signal + var/datum/wound/W = i + W.crush(DOOR_CRUSH_DAMAGE) if(isalien(L)) //For xenos L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans. L.emote("roar") diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index b52cf1a891..228c2e1f52 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -23,6 +23,10 @@ assemblytype = /obj/structure/firelock_frame armor = list("melee" = 30, "bullet" = 30, "laser" = 20, "energy" = 20, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 70) interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN + air_tight = TRUE + attack_hand_is_action = TRUE + attack_hand_speed = CLICK_CD_MELEE + var/emergency_close_timer = 0 var/nextstate = null var/boltslocked = TRUE var/list/affecting_areas @@ -68,13 +72,16 @@ return ..() /obj/machinery/door/firedoor/Bumped(atom/movable/AM) - if(panel_open || operating) + if(panel_open || operating || welded) return - if(!density) - return ..() + if(ismob(AM)) + var/mob/user = AM + if(density && !welded && !operating && !(stat & NOPOWER) && (!density || allow_hand_open(user))) + add_fingerprint(user) + open() + return TRUE return FALSE - /obj/machinery/door/firedoor/power_change() if(powered(power_channel)) stat &= ~NOPOWER @@ -82,13 +89,17 @@ else stat |= NOPOWER -/obj/machinery/door/firedoor/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/door/firedoor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) + if(!welded && !operating && !(stat & NOPOWER) && (!density || allow_hand_open(user))) + add_fingerprint(user) + if(density) + emergency_close_timer = world.time + 30 // prevent it from instaclosing again if in space + open() + else + close() + return TRUE if(operating || !density) return - user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] bangs on \the [src].", "You bang on \the [src].") @@ -100,7 +111,7 @@ return if(welded) - if(istype(C, /obj/item/wrench)) + if(C.tool_behaviour == TOOL_WRENCH) if(boltslocked) to_chat(user, "There are screws locking the bolts in place!") return @@ -114,7 +125,7 @@ "You undo [src]'s floor bolts.") deconstruct(TRUE) return - if(istype(C, /obj/item/screwdriver)) + if(C.tool_behaviour == TOOL_SCREWDRIVER) user.visible_message("[user] [boltslocked ? "unlocks" : "locks"] [src]'s bolts.", \ "You [boltslocked ? "unlock" : "lock"] [src]'s floor bolts.") C.play_tool_sound(src) @@ -140,10 +151,27 @@ return if(density) + if(is_holding_pressure()) + // tell the user that this is a bad idea, and have a do_after as well + to_chat(user, "As you begin crowbarring \the [src] a gush of air blows in your face... maybe you should reconsider?") + if(!do_after(user, 15, TRUE, src)) // give them a few seconds to reconsider their decision. + return + log_game("[key_name_admin(user)] has opened a firelock with a pressure difference at [AREACOORD(loc)]") // there bibby I made it logged just for you. Enjoy. + // since we have high-pressure-ness, close all other firedoors on the tile + whack_a_mole() + if(welded || operating || !density) + return // in case things changed during our do_after + emergency_close_timer = world.time + 60 // prevent it from instaclosing again if in space open() else close() +/obj/machinery/door/firedoor/proc/allow_hand_open(mob/user) + var/area/A = get_area(src) + if(A && A.fire) + return FALSE + return !is_holding_pressure() + /obj/machinery/door/firedoor/attack_ai(mob/user) add_fingerprint(user) if(welded || operating || stat & NOPOWER) @@ -171,20 +199,16 @@ if("closing") flick("door_closing", src) -/obj/machinery/door/firedoor/update_icon_state() +/obj/machinery/door/firedoor/update_icon() + cut_overlays() if(density) icon_state = "door_closed" + if(welded) + add_overlay("welded") else icon_state = "door_open" - -/obj/machinery/door/firedoor/update_overlays() - . = ..() - if(!welded) - return - if(density) - . += "welded" - else - . += "welded_open" + if(welded) + add_overlay("welded_open") /obj/machinery/door/firedoor/open() . = ..() @@ -194,6 +218,61 @@ . = ..() latetoggle() +/obj/machinery/door/firedoor/proc/whack_a_mole(reconsider_immediately = FALSE) + set waitfor = 0 + for(var/cdir in GLOB.cardinals) + if((flags_1 & ON_BORDER_1) && cdir != dir) + continue + whack_a_mole_part(get_step(src, cdir), reconsider_immediately) + if(flags_1 & ON_BORDER_1) + whack_a_mole_part(get_turf(src), reconsider_immediately) + +/obj/machinery/door/firedoor/proc/whack_a_mole_part(turf/start_point, reconsider_immediately) + set waitfor = 0 + var/list/doors_to_close = list() + var/list/turfs = list() + turfs[start_point] = 1 + for(var/i = 1; (i <= turfs.len && i <= 11); i++) // check up to 11 turfs. + var/turf/open/T = turfs[i] + if(istype(T, /turf/open/space)) + return -1 + for(var/T2 in T.atmos_adjacent_turfs) + if(turfs[T2]) + continue + var/is_cut_by_unopen_door = FALSE + for(var/obj/machinery/door/firedoor/FD in T2) + if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, T) != FD.dir) + continue + if(FD.operating || FD == src || FD.welded || FD.density) + continue + doors_to_close += FD + is_cut_by_unopen_door = TRUE + + for(var/obj/machinery/door/firedoor/FD in T) + if((FD.flags_1 & ON_BORDER_1) && get_dir(T, T2) != FD.dir) + continue + if(FD.operating || FD == src || FD.welded || FD.density) + continue + doors_to_close += FD + is_cut_by_unopen_door= TRUE + if(!is_cut_by_unopen_door) + turfs[T2] = 1 + if(turfs.len > 10) + return // too big, don't bother + for(var/obj/machinery/door/firedoor/FD in doors_to_close) + FD.emergency_pressure_stop(FALSE) + if(reconsider_immediately) + var/turf/open/T = FD.loc + if(istype(T)) + T.ImmediateCalculateAdjacentTurfs() + +/obj/machinery/door/firedoor/proc/emergency_pressure_stop(consider_timer = TRUE) + set waitfor = 0 + if(density || operating || welded) + return + if(world.time >= emergency_close_timer || !consider_timer) + close() + /obj/machinery/door/firedoor/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) var/obj/structure/firelock_frame/F = new assemblytype(get_turf(src)) @@ -219,7 +298,7 @@ /obj/machinery/door/firedoor/border_only icon = 'icons/obj/doors/edge_Doorfire.dmi' - flags_1 = ON_BORDER_1 + flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1 CanAtmosPass = ATMOS_PASS_PROC /obj/machinery/door/firedoor/border_only/closed @@ -227,6 +306,59 @@ opacity = TRUE density = TRUE +/obj/machinery/door/firedoor/border_only/close() + if(density) + return TRUE + if(operating || welded) + return + var/turf/T1 = get_turf(src) + var/turf/T2 = get_step(T1, dir) + for(var/mob/living/M in T1) + if(M.stat == CONSCIOUS && M.pulling && M.pulling.loc == T2 && !M.pulling.anchored && M.pulling.move_resist <= M.move_force) + var/mob/living/M2 = M.pulling + if(!istype(M2) || !M2.buckled || !M2.buckled.buckle_prevents_pull) + to_chat(M, "You pull [M.pulling] through [src] right as it closes") + M.pulling.forceMove(T1) + M.start_pulling(M2) + + for(var/mob/living/M in T2) + if(M.stat == CONSCIOUS && M.pulling && M.pulling.loc == T1 && !M.pulling.anchored && M.pulling.move_resist <= M.move_force) + var/mob/living/M2 = M.pulling + if(!istype(M2) || !M2.buckled || !M2.buckled.buckle_prevents_pull) + to_chat(M, "You pull [M.pulling] through [src] right as it closes") + M.pulling.forceMove(T2) + M.start_pulling(M2) + . = ..() + +/obj/machinery/door/firedoor/border_only/allow_hand_open(mob/user) + var/area/A = get_area(src) + if((!A || !A.fire) && !is_holding_pressure()) + return TRUE + whack_a_mole(TRUE) // WOOP WOOP SIDE EFFECTS + var/turf/T = loc + var/turf/T2 = get_step(T, dir) + if(!T || !T2) + return + var/status1 = check_door_side(T) + var/status2 = check_door_side(T2) + if((status1 == 1 && status2 == -1) || (status1 == -1 && status2 == 1)) + to_chat(user, "Access denied. Try closing another firedoor to minimize decompression, or using a crowbar.") + return FALSE + return TRUE + +/obj/machinery/door/firedoor/border_only/proc/check_door_side(turf/open/start_point) + var/list/turfs = list() + turfs[start_point] = 1 + for(var/i = 1; (i <= turfs.len && i <= 11); i++) // check up to 11 turfs. + var/turf/open/T = turfs[i] + if(istype(T, /turf/open/space)) + return -1 + for(var/T2 in T.atmos_adjacent_turfs) + turfs[T2] = 1 + if(turfs.len <= 10) + return 0 // not big enough to matter + return start_point.air.return_pressure() < 20 ? -1 : 1 + /obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target) if(istype(mover) && (mover.pass_flags & PASSGLASS)) return TRUE @@ -257,6 +389,18 @@ assemblytype = /obj/structure/firelock_frame/heavy max_integrity = 550 +/obj/machinery/door/firedoor/window + name = "window shutter" + icon = 'icons/obj/doors/doorfirewindow.dmi' + desc = "A second window that slides in when the original window is broken, designed to protect against hull breaches. Truly a work of genius by NT engineers." + glass = TRUE + explosion_block = 0 + max_integrity = 50 + resistance_flags = 0 // not fireproof + heat_proof = FALSE + +/obj/machinery/door/firedoor/window/allow_hand_open() + return TRUE /obj/item/electronics/firelock name = "firelock circuitry" @@ -294,7 +438,7 @@ /obj/structure/firelock_frame/attackby(obj/item/C, mob/user) switch(constructionStep) if(CONSTRUCTION_PANEL_OPEN) - if(istype(C, /obj/item/crowbar)) + if(C.tool_behaviour == TOOL_CROWBAR) C.play_tool_sound(src) user.visible_message("[user] starts prying something out from [src]...", \ "You begin prying out the wire cover...") @@ -308,7 +452,7 @@ constructionStep = CONSTRUCTION_WIRES_EXPOSED update_icon() return - if(istype(C, /obj/item/wrench)) + if(C.tool_behaviour == TOOL_WRENCH) if(locate(/obj/machinery/door/firedoor) in get_turf(src)) to_chat(user, "There's already a firelock there.") return @@ -350,7 +494,7 @@ return if(CONSTRUCTION_WIRES_EXPOSED) - if(istype(C, /obj/item/wirecutters)) + if(C.tool_behaviour == TOOL_WIRECUTTER) C.play_tool_sound(src) user.visible_message("[user] starts cutting the wires from [src]...", \ "You begin removing [src]'s wires...") @@ -364,7 +508,7 @@ constructionStep = CONSTRUCTION_GUTTED update_icon() return - if(istype(C, /obj/item/crowbar)) + if(C.tool_behaviour == TOOL_CROWBAR) C.play_tool_sound(src) user.visible_message("[user] starts prying a metal plate into [src]...", \ "You begin prying the cover plate back onto [src]...") @@ -379,7 +523,7 @@ update_icon() return if(CONSTRUCTION_GUTTED) - if(istype(C, /obj/item/crowbar)) + if(C.tool_behaviour == TOOL_CROWBAR) user.visible_message("[user] begins removing the circuit board from [src]...", \ "You begin prying out the circuit board from [src]...") if(!C.use_tool(src, user, 50, volume=50)) @@ -401,7 +545,7 @@ "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.use_tool(src, user, 0, 5)) + if(constructionStep != CONSTRUCTION_GUTTED || B.get_amount() < 5 || !B) return user.visible_message("[user] adds wires to [src].", \ "You wire [src].") @@ -410,7 +554,7 @@ update_icon() return if(CONSTRUCTION_NOCIRCUIT) - if(istype(C, /obj/item/weldingtool)) + if(C.tool_behaviour == TOOL_WELDER) if(!C.tool_start_check(user, amount=1)) return user.visible_message("[user] begins cutting apart [src]'s frame...", \ diff --git a/code/game/machinery/doors/poddoor.dm b/code/game/machinery/doors/poddoor.dm index c032ded6b0..4226d8a439 100644 --- a/code/game/machinery/doors/poddoor.dm +++ b/code/game/machinery/doors/poddoor.dm @@ -16,6 +16,9 @@ damage_deflection = 70 poddoor = TRUE +/obj/machinery/door/poddoor/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + id = "[idnum][id]" + /obj/machinery/door/poddoor/preopen icon_state = "open" density = FALSE diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 492e90720c..22bacf6aa1 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -11,7 +11,7 @@ integrity_failure = 0 armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 70, "acid" = 100) visible = FALSE - flags_1 = ON_BORDER_1 + flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1 opacity = 0 CanAtmosPass = ATMOS_PASS_PROC interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN @@ -54,6 +54,15 @@ else icon_state = "[src.base_state]open" +/obj/machinery/door/window/update_atom_colour() + if((color && (color_hex2num(color) < 255))) + visible = TRUE + if(density) + set_opacity(TRUE) + else + visible = FALSE + set_opacity(density && visible) + /obj/machinery/door/window/proc/open_and_close() open() if(src.check_access(null)) @@ -143,16 +152,18 @@ do_animate("opening") playsound(src.loc, 'sound/machines/windowdoor.ogg', 100, 1) src.icon_state ="[src.base_state]open" - sleep(10) + addtimer(CALLBACK(src, .proc/finish_opening), 10) + return TRUE +/obj/machinery/door/window/proc/finish_opening() + operating = FALSE density = FALSE -// src.sd_set_opacity(0) //TODO: why is this here? Opaque windoors? ~Carn + if(visible) + set_opacity(FALSE) air_update_turf(1) update_freelook_sight() - if(operating == 1) //emag again operating = FALSE - return 1 /obj/machinery/door/window/close(forced=0) if (src.operating) @@ -171,10 +182,13 @@ density = TRUE air_update_turf(1) update_freelook_sight() - sleep(10) + addtimer(CALLBACK(src, .proc/finish_closing), 10) + return TRUE +/obj/machinery/door/window/proc/finish_closing() + if(visible) + set_opacity(TRUE) operating = FALSE - return 1 /obj/machinery/door/window/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) switch(damage_type) diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm deleted file mode 100644 index 2c669aac80..0000000000 --- a/code/game/machinery/exp_cloner.dm +++ /dev/null @@ -1,298 +0,0 @@ -//Experimental cloner; clones a body regardless of the owner's status, letting a ghost control it instead -/obj/machinery/clonepod/experimental - name = "experimental cloning pod" - desc = "An ancient cloning pod. It seems to be an early prototype of the experimental cloners used in Nanotrasen Stations." - icon = 'icons/obj/machines/cloning.dmi' - icon_state = "pod_0" - req_access = null - circuit = /obj/item/circuitboard/machine/clonepod/experimental - internal_radio = FALSE - -//Start growing a human clone in the pod! -/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks) - if(panel_open) - return FALSE - if(mess || attempting) - return FALSE - - attempting = TRUE //One at a time!! - countdown.start() - - var/mob/living/carbon/human/H = new /mob/living/carbon/human(src) - - H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features) - - if(efficiency > 2) - var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations) - H.dna.remove_mutation_group(unclean_mutations) - if(efficiency > 5 && prob(20)) - H.easy_randmut(POSITIVE) - if(efficiency < 3 && prob(50)) - var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) - if(ismob(M)) - H = M - - H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment. - occupant = H - - if(!clonename) //to prevent null names - clonename = "clone ([rand(1,999)])" - H.real_name = clonename - - icon_state = "pod_1" - //Get the clone body ready - maim_clone(H) - ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning") - ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning") - ADD_TRAIT(H, TRAIT_MUTE, "cloning") - ADD_TRAIT(H, TRAIT_NOBREATH, "cloning") - ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning") - H.Unconscious(80) - - var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H) - if(LAZYLEN(candidates)) - var/mob/C = pick(candidates) - H.key = C.key - - if(grab_ghost_when == CLONER_FRESH_CLONE) - H.grab_ghost() - to_chat(H, "Consciousness slowly creeps over you as your body regenerates.
    So this is what cloning feels like?
    ") - - if(grab_ghost_when == CLONER_MATURE_CLONE) - H.ghostize(TRUE) //Only does anything if they were still in their old body and not already a ghost - to_chat(H.get_ghost(TRUE), "Your body is beginning to regenerate in a cloning pod. You will become conscious when it is complete.") - - if(H) - H.faction |= factions - - H.set_cloned_appearance() - - H.suiciding = FALSE - attempting = FALSE - return TRUE - - -//Prototype cloning console, much more rudimental and lacks modern functions such as saving records, autocloning, or safety checks. -/obj/machinery/computer/prototype_cloning - name = "prototype cloning console" - desc = "Used to operate an experimental cloner." - icon_screen = "dna" - icon_keyboard = "med_key" - circuit = /obj/item/circuitboard/computer/prototype_cloning - var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning. - var/list/pods //Linked experimental cloning pods - var/temp = "Inactive" - var/scantemp = "Ready to Scan" - var/loading = FALSE // Nice loading text - - light_color = LIGHT_COLOR_BLUE - -/obj/machinery/computer/prototype_cloning/Initialize() - . = ..() - updatemodules(TRUE) - -/obj/machinery/computer/prototype_cloning/Destroy() - if(pods) - for(var/P in pods) - DetachCloner(P) - pods = null - return ..() - -/obj/machinery/computer/prototype_cloning/proc/GetAvailablePod(mind = null) - if(pods) - for(var/P in pods) - var/obj/machinery/clonepod/experimental/pod = P - if(pod.is_operational() && !(pod.occupant || pod.mess)) - return pod - -/obj/machinery/computer/prototype_cloning/proc/updatemodules(findfirstcloner) - scanner = findscanner() - if(findfirstcloner && !LAZYLEN(pods)) - findcloner() - -/obj/machinery/computer/prototype_cloning/proc/findscanner() - var/obj/machinery/dna_scannernew/scannerf = null - - // Loop through every direction - for(var/direction in GLOB.cardinals) - // Try to find a scanner in that direction - scannerf = locate(/obj/machinery/dna_scannernew, get_step(src, direction)) - // If found and operational, return the scanner - if (!isnull(scannerf) && scannerf.is_operational()) - return scannerf - - // If no scanner was found, it will return null - return null - -/obj/machinery/computer/prototype_cloning/proc/findcloner() - var/obj/machinery/clonepod/experimental/podf = null - for(var/direction in GLOB.cardinals) - podf = locate(/obj/machinery/clonepod/experimental, get_step(src, direction)) - if (!isnull(podf) && podf.is_operational()) - AttachCloner(podf) - -/obj/machinery/computer/prototype_cloning/proc/AttachCloner(obj/machinery/clonepod/experimental/pod) - if(!pod.connected) - pod.connected = src - LAZYADD(pods, pod) - -/obj/machinery/computer/prototype_cloning/proc/DetachCloner(obj/machinery/clonepod/experimental/pod) - pod.connected = null - LAZYREMOVE(pods, pod) - -/obj/machinery/computer/prototype_cloning/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/multitool)) - var/obj/item/multitool/P = W - - if(istype(P.buffer, /obj/machinery/clonepod/experimental)) - if(get_area(P.buffer) != get_area(src)) - to_chat(user, "-% Cannot link machines across power zones. Buffer cleared %-") - P.buffer = null - return - to_chat(user, "-% Successfully linked [P.buffer] with [src] %-") - var/obj/machinery/clonepod/experimental/pod = P.buffer - if(pod.connected) - pod.connected.DetachCloner(pod) - AttachCloner(pod) - else - P.buffer = src - to_chat(user, "-% Successfully stored [REF(P.buffer)] [P.buffer.name] in buffer %-") - return - else - return ..() - -/obj/machinery/computer/prototype_cloning/attack_hand(mob/user) - if(..()) - return - interact(user) - -/obj/machinery/computer/prototype_cloning/interact(mob/user) - user.set_machine(src) - add_fingerprint(user) - - if(..()) - return - - updatemodules(TRUE) - - var/dat = "" - dat += "Refresh" - - dat += "

    Cloning Pod Status

    " - dat += "
    [temp] 
    " - - if (isnull(src.scanner) || !LAZYLEN(pods)) - dat += "

    Modules

    " - //dat += "Reload Modules" - if (isnull(src.scanner)) - dat += "ERROR: No Scanner detected!
    " - if (!LAZYLEN(pods)) - dat += "ERROR: No Pod detected
    " - - // Scan-n-Clone - if (!isnull(src.scanner)) - var/mob/living/scanner_occupant = get_mob_or_brainmob(scanner.occupant) - - dat += "

    Cloning

    " - - dat += "
    " - if(!scanner_occupant) - dat += "Scanner Unoccupied" - else if(loading) - dat += "[scanner_occupant] => Scanning..." - else - scantemp = "Ready to Clone" - dat += "[scanner_occupant] => [scantemp]" - dat += "
    " - - if(scanner_occupant) - dat += "Clone" - dat += "
    [src.scanner.locked ? "Unlock Scanner" : "Lock Scanner"]" - else - dat += "Clone" - - var/datum/browser/popup = new(user, "cloning", "Prototype Cloning System Control") - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/computer/prototype_cloning/Topic(href, href_list) - if(..()) - return - - if(loading) - return - - else if ((href_list["clone"]) && !isnull(scanner) && scanner.is_operational()) - scantemp = "" - - loading = TRUE - updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) - say("Initiating scan...") - - spawn(20) - clone_occupant(scanner.occupant) - loading = FALSE - updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - - //No locking an open scanner. - else if ((href_list["lock"]) && !isnull(scanner) && scanner.is_operational()) - if ((!scanner.locked) && (scanner.occupant)) - scanner.locked = TRUE - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else - scanner.locked = FALSE - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - - else if (href_list["refresh"]) - updateUsrDialog() - playsound(src, "terminal_type", 25, 0) - - add_fingerprint(usr) - updateUsrDialog() - return - -/obj/machinery/computer/prototype_cloning/proc/clone_occupant(occupant) - var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) - var/datum/dna/dna - if(ishuman(mob_occupant)) - var/mob/living/carbon/C = mob_occupant - dna = C.has_dna() - if(isbrain(mob_occupant)) - var/mob/living/brain/B = mob_occupant - dna = B.stored_dna - - if(!istype(dna)) - scantemp = "Unable to locate valid genetic data." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - return - if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) - scantemp = "Subject no longer contains the fundamental materials required to create a living clone." - playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) - return - - var/clone_species - if(dna.species) - clone_species = dna.species - else - var/datum/species/rando_race = pick(GLOB.roundstart_races) - clone_species = rando_race.type - - var/obj/machinery/clonepod/pod = GetAvailablePod() - //Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs. - if(!LAZYLEN(pods)) - temp = "No Clonepods detected." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(!pod) - temp = "No Clonepods available." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else if(pod.occupant) - temp = "Cloning cycle already in progress." - playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) - else - pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction) - temp = "[mob_occupant.real_name] => Cloning data sent to pod." - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index 0b23e650d7..000b3dc7b5 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -141,7 +141,7 @@ if(user) log_game("[user] reset a fire alarm at [COORD(src)]") -/obj/machinery/firealarm/attack_hand(mob/user) +/obj/machinery/firealarm/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(buildstage != 2) return ..() add_fingerprint(user) diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index f4f1aa0637..c0e1122140 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -36,6 +36,9 @@ else bulb = new(src) +/obj/machinery/flasher/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + id = "[idnum][id]" + /obj/machinery/flasher/Destroy() QDEL_NULL(bulb) return ..() diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm index 55b1e34022..93c6e66867 100644 --- a/code/game/machinery/gulag_item_reclaimer.dm +++ b/code/game/machinery/gulag_item_reclaimer.dm @@ -20,18 +20,15 @@ return ..() /obj/machinery/gulag_item_reclaimer/emag_act(mob/user) - . = ..() if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items return req_access = list() obj_flags |= EMAGGED - return TRUE -/obj/machinery/gulag_item_reclaimer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "gulag_item_reclaimer", name, 300, 400, master_ui, state) + ui = new(user, src, "GulagItemReclaimer", name) ui.open() /obj/machinery/gulag_item_reclaimer/ui_data(mob/user) @@ -60,20 +57,22 @@ mobs += list(mob_info) data["mobs"] = mobs - - data["can_reclaim"] = can_reclaim return data -/obj/machinery/gulag_item_reclaimer/ui_act(action, list/params) +/obj/machinery/gulag_item_reclaimer/ui_act(action, params) + if(..()) + return + switch(action) if("release_items") - var/mob/M = locate(params["mobref"]) - if(M == usr || allowed(usr)) - drop_items(M) - else - to_chat(usr, "Access denied.") + var/mob/living/carbon/human/H = locate(params["mobref"]) in stored_items + if(H != usr && !allowed(usr)) + to_chat(usr, "Access denied.") + return + drop_items(H) + . = TRUE /obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user) if(!stored_items[user]) diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm index fb41ac986d..da64699dd4 100644 --- a/code/game/machinery/gulag_teleporter.dm +++ b/code/game/machinery/gulag_teleporter.dm @@ -101,8 +101,6 @@ The console is located at computer/gulag_teleporter.dm if(!locked) open_machine() return - 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(breakout_time)].)", \ "You hear a metallic creaking from [src].") diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 141f261688..191967ac1a 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -50,7 +50,7 @@ harvesting = FALSE warming_up = FALSE -/obj/machinery/harvester/attack_hand(mob/user) +/obj/machinery/harvester/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(state_open) close_machine() else if(!harvesting) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 621e486e90..4a576c5a6e 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -25,7 +25,6 @@ Possible to do for anyone motivated enough: */ GLOBAL_LIST_EMPTY(network_holopads) - #define HOLOPAD_PASSIVE_POWER_USAGE 1 #define HOLOGRAM_POWER_USAGE 2 @@ -34,34 +33,64 @@ GLOBAL_LIST_EMPTY(network_holopads) desc = "It's a floor-mounted device for projecting holographic images." icon_state = "holopad0" layer = LOW_OBJ_LAYER - plane = ABOVE_WALL_PLANE + plane = FLOOR_PLANE flags_1 = HEAR_1 + req_access = list(ACCESS_KEYCARD_AUTH) //Used to allow for forced connecting to other (not secure) holopads. Anyone can make a call, though. use_power = IDLE_POWER_USE idle_power_usage = 5 active_power_usage = 100 max_integrity = 300 armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) circuit = /obj/item/circuitboard/machine/holopad - var/list/masters //List of living mobs that use the holopad - var/list/holorays //Holoray-mob link. - var/last_request = 0 //to prevent request spam. ~Carn - var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating. - var/temp = "" - var/list/holo_calls //array of /datum/holocalls - var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs - var/obj/item/disk/holodisk/disk //Record disk - var/replay_mode = FALSE //currently replaying a recording - var/loop_mode = FALSE //currently looping a recording - var/record_mode = FALSE //currently recording - var/record_start = 0 //recording start time - var/record_user //user that inititiated the recording - var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram - var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging + /// List of living mobs that use the holopad + var/list/masters + /// Holoray-mob link + var/list/holorays + /// To prevent request spam. ~Carn + var/last_request = 0 + /// Change to change how far the AI can move away from the holopad before deactivating + var/holo_range = 5 + /// Array of /datum/holocalls + var/list/holo_calls + /// Currently outgoing holocall, do not modify the datums only check and call the public procs + var/datum/holocall/outgoing_call + /// Record disk + var/obj/item/disk/holodisk/disk + /// Currently replaying a recording + var/replay_mode = FALSE + /// Currently looping a recording + var/loop_mode = FALSE + /// Currently recording + var/record_mode = FALSE + /// Recording start time + var/record_start = 0 + /// User that inititiated the recording + var/record_user + /// Replay hologram + var/obj/effect/overlay/holo_pad_hologram/replay_holo + /// Calls will be automatically answered after a couple rings, here for debugging + var/static/force_answer_call = FALSE + // var/static/list/holopads = list() var/obj/effect/overlay/holoray/ray var/ringing = FALSE var/offset = FALSE var/on_network = TRUE + /// For pads in secure areas; do not allow forced connecting + var/secure = FALSE + /// If we are currently calling another holopad + var/calling = FALSE +/* +/obj/machinery/holopad/secure + name = "secure holopad" + desc = "It's a floor-mounted device for projecting holographic images. This one will refuse to auto-connect incoming calls." + secure = TRUE +/obj/machinery/holopad/secure/Initialize() + . = ..() + var/obj/item/circuitboard/machine/holopad/board = circuit + board.secure = TRUE + board.build_path = /obj/machinery/holopad/secure +*/ /obj/machinery/holopad/tutorial resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF flags_1 = NODECONSTRUCT_1 @@ -78,7 +107,7 @@ GLOBAL_LIST_EMPTY(network_holopads) new_disk.forceMove(src) disk = new_disk -/obj/machinery/holopad/tutorial/attack_hand(mob/user) +/obj/machinery/holopad/tutorial/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!istype(user)) return if(user.incapacitated() || !is_operational()) @@ -121,10 +150,8 @@ GLOBAL_LIST_EMPTY(network_holopads) return ..() /obj/machinery/holopad/power_change() - if (powered()) - stat &= ~NOPOWER - else - stat |= NOPOWER + . = ..() + if (!powered()) if(replay_mode) replay_stop() if(record_mode) @@ -163,171 +190,150 @@ GLOBAL_LIST_EMPTY(network_holopads) if(istype(P,/obj/item/disk/holodisk)) if(disk) - to_chat(user,"There's already a disk inside [src]") + to_chat(user,"There's already a disk inside [src]!") return if (!user.transferItemToLoc(P,src)) return - to_chat(user,"You insert [P] into [src]") + to_chat(user,"You insert [P] into [src].") disk = P - updateDialog() return return ..() +/obj/machinery/holopad/ui_status(mob/user) + if(!is_operational()) + return UI_CLOSE + if(outgoing_call && !calling) + return UI_CLOSE + return ..() -/obj/machinery/holopad/ui_interact(mob/living/carbon/human/user) //Carn: Hologram requests. +/obj/machinery/holopad/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Holopad", name) + ui.open() + +/obj/machinery/holopad/ui_data(mob/user) + var/list/data = list() + data["calling"] = calling + data["on_network"] = on_network + data["on_cooldown"] = last_request + 200 < world.time ? FALSE : TRUE + data["allowed"] = allowed(user) + data["disk"] = disk ? TRUE : FALSE + data["disk_record"] = disk?.record ? TRUE : FALSE + data["replay_mode"] = replay_mode + data["loop_mode"] = loop_mode + data["record_mode"] = record_mode + data["holo_calls"] = list() + for(var/I in holo_calls) + var/datum/holocall/HC = I + var/list/call_data = list( + caller = HC.user, + connected = HC.connected_holopad == src ? TRUE : FALSE, + ref = REF(HC) + ) + data["holo_calls"] += list(call_data) + return data + +/obj/machinery/holopad/ui_act(action, list/params) . = ..() - if(!istype(user)) + if(.) return - if(outgoing_call || user.incapacitated() || !is_operational()) - return - - user.set_machine(src) - var/dat - if(temp) - dat = temp - else - if(on_network) - dat += "Request an AI's presence
    " - dat += "Call another holopad
    " - if(disk) - if(disk.record) - //Replay - dat += "Replay disk recording
    " - dat += "Loop disk recording
    " - //Clear - dat += "Clear disk recording
    " + switch(action) + if("AIrequest") + if(last_request + 200 < world.time) + last_request = world.time + to_chat(usr, "You requested an AI's presence.") + var/area/area = get_area(src) + for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs) + if(!AI.client) + continue + to_chat(AI, "Your presence is requested at \the [area].") + return TRUE else - //Record - dat += "Start new recording
    " - //Eject - dat += "Eject disk
    " + to_chat(usr, "A request for AI presence was already sent recently.") + return + if("holocall") + if(outgoing_call) + return + if(usr.loc == loc) + var/list/callnames = list() + for(var/I in GLOB.network_holopads) + var/area/A = get_area(I) + if(A) + LAZYADD(callnames[A], I) + callnames -= get_area(src) + var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in sortNames(callnames) + if(QDELETED(usr) || !result || outgoing_call) + return + if(usr.loc == loc) + var/input = text2num(params["headcall"]) + var/headcall = input == 1 ? TRUE : FALSE + new /datum/holocall(usr, src, callnames[result], headcall) + calling = TRUE + return TRUE + else + to_chat(usr, "You must stand on the holopad to make a call!") + if("connectcall") + var/datum/holocall/call_to_connect = locate(params["holopad"]) in holo_calls + if(!QDELETED(call_to_connect)) + call_to_connect.Answer(src) + return TRUE + if("disconnectcall") + var/datum/holocall/call_to_disconnect = locate(params["holopad"]) in holo_calls + if(!QDELETED(call_to_disconnect)) + call_to_disconnect.Disconnect(src) + return TRUE + if("disk_eject") + if(disk && !replay_mode) + disk.forceMove(drop_location()) + disk = null + return TRUE + if("replay_mode") + if(replay_mode) + replay_stop() + return TRUE + else + replay_start() + return TRUE + if("loop_mode") + loop_mode = !loop_mode + return TRUE + if("record_mode") + if(record_mode) + record_stop() + return TRUE + else + record_start(usr) + return TRUE + if("record_clear") + record_clear() + return TRUE + if("offset") + offset++ + if(offset > 4) + offset = FALSE + var/turf/new_turf + if(!offset) + new_turf = get_turf(src) + else + new_turf = get_step(src, GLOB.cardinals[offset]) + replay_holo.forceMove(new_turf) + return TRUE + if("hang_up") + if(outgoing_call) + outgoing_call.Disconnect(src) + return TRUE - if(LAZYLEN(holo_calls)) - dat += "=====================================================
    " - - if(on_network) - var/one_answered_call = FALSE - var/one_unanswered_call = FALSE - for(var/I in holo_calls) - var/datum/holocall/HC = I - if(HC.connected_holopad != src) - dat += "Answer call from [get_area(HC.calling_holopad)]
    " - one_unanswered_call = TRUE - else - one_answered_call = TRUE - - if(one_answered_call && one_unanswered_call) - dat += "=====================================================
    " - //we loop twice for formatting - for(var/I in holo_calls) - var/datum/holocall/HC = I - if(HC.connected_holopad == src) - dat += "Disconnect call from [HC.user]
    " - - - var/datum/browser/popup = new(user, "holopad", name, 300, 175) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -//Stop ringing the AI!! +/** + * hangup_all_calls: Disconnects all current holocalls from the holopad + */ /obj/machinery/holopad/proc/hangup_all_calls() for(var/I in holo_calls) var/datum/holocall/HC = I HC.Disconnect(src) -/obj/machinery/holopad/Topic(href, href_list) - if(..() || isAI(usr)) - return - add_fingerprint(usr) - if(!is_operational()) - return - if (href_list["AIrequest"]) - if(last_request + 200 < world.time) - last_request = world.time - temp = "You requested an AI's presence.
    " - temp += "Main Menu" - var/area/area = get_area(src) - for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs) - if(!AI.client) - continue - to_chat(AI, "Your presence is requested at \the [area].") - else - temp = "A request for AI presence was already sent recently.
    " - temp += "Main Menu" - - else if(href_list["Holocall"]) - if(outgoing_call) - return - - temp = "You must stand on the holopad to make a call!
    " - temp += "Main Menu" - if(usr.loc == loc) - var/list/callnames = list() - for(var/I in GLOB.network_holopads) - var/area/A = get_area(I) - if(A) - LAZYADD(callnames[A], I) - callnames -= get_area(src) - - var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames - if(QDELETED(usr) || !result || outgoing_call) - return - - if(usr.loc == loc) - temp = "Dialing...
    " - temp += "Main Menu" - new /datum/holocall(usr, src, callnames[result]) - - else if(href_list["connectcall"]) - var/datum/holocall/call_to_connect = locate(href_list["connectcall"]) - if(!QDELETED(call_to_connect)) - call_to_connect.Answer(src) - temp = "" - - else if(href_list["disconnectcall"]) - var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"]) - if(!QDELETED(call_to_disconnect)) - call_to_disconnect.Disconnect(src) - temp = "" - - else if(href_list["mainmenu"]) - temp = "" - if(outgoing_call) - outgoing_call.Disconnect() - - else if(href_list["disk_eject"]) - if(disk && !replay_mode) - disk.forceMove(drop_location()) - disk = null - - else if(href_list["replay_stop"]) - replay_stop() - else if(href_list["replay_start"]) - replay_start() - else if(href_list["loop_start"]) - loop_mode = TRUE - replay_start() - else if(href_list["record_start"]) - record_start(usr) - else if(href_list["record_stop"]) - record_stop() - else if(href_list["record_clear"]) - record_clear() - else if(href_list["offset"]) - offset++ - if (offset > 4) - offset = FALSE - var/turf/new_turf - if (!offset) - new_turf = get_turf(src) - else - new_turf = get_step(src, GLOB.cardinals[offset]) - replay_holo.forceMove(new_turf) - updateDialog() - //do not allow AIs to answer calls or people will use it to meta the AI sattelite /obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user) if (!istype(user)) @@ -366,6 +372,9 @@ GLOBAL_LIST_EMPTY(network_holopads) if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2))) HC.Answer(src) break + if(!secure) //HC.head_call && + HC.Answer(src) + break if(outgoing_call) HC.Disconnect(src)//can't answer calls while calling else @@ -412,17 +421,17 @@ GLOBAL_LIST_EMPTY(network_holopads) /*This is the proc for special two-way communication between AI and holopad/people talking near holopad. For the other part of the code, check silicon say.dm. Particularly robot talk.*/ -/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) +/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. for(var/mob/living/silicon/ai/master in masters) if(masters[master] && speaker != master) - master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) + master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) for(var/I in holo_calls) var/datum/holocall/HC = I if(HC.connected_holopad == src && speaker != HC.hologram) - HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source) + HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods) if(outgoing_call && speaker == outgoing_call.user) outgoing_call.hologram.say(raw_message) @@ -449,7 +458,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ else icon_state = "holopad0" -/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h) +/obj/machinery/holopad/proc/set_holo(mob/living/user, obj/effect/overlay/holo_pad_hologram/h) LAZYSET(masters, user, h) LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc)) var/mob/living/silicon/ai/AI = user @@ -504,7 +513,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ else return FALSE -/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction) +/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf) if(LAZYLEN(masters) && masters[user]) var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] var/transfered = FALSE @@ -516,8 +525,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ transfered = TRUE //All is good. holo.forceMove(new_turf) - if(direction) - holo.setDir(direction) if(!transfered) update_holoray(user,new_turf) return TRUE @@ -568,22 +575,15 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ if(!replay_mode) replay_mode = TRUE replay_holo = setup_replay_holo(disk.record) - temp = "Replaying...
    " - temp += "Change offset
    " - temp += "End replay" SetLightsAndPower() replay_entry(1) - return /obj/machinery/holopad/proc/replay_stop() if(replay_mode) replay_mode = FALSE - loop_mode = FALSE offset = FALSE - temp = null QDEL_NULL(replay_holo) SetLightsAndPower() - updateDialog() /obj/machinery/holopad/proc/record_start(mob/living/user) if(!user || !disk || disk.record) @@ -593,8 +593,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ record_start = world.time record_user = user disk.record.set_caller_image(user) - temp = "Recording...
    " - temp += "End recording." /obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language) if(!record_mode) @@ -641,7 +639,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ if(replay_holo) replay_holo.say(message) if(HOLORECORD_SOUND) - playsound(src,entry[2],50,1) + playsound(src,entry[2],50,TRUE) if(HOLORECORD_DELAY) addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2]) return @@ -660,14 +658,11 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ /obj/machinery/holopad/proc/record_stop() if(record_mode) record_mode = FALSE - temp = null record_user = null - updateDialog() /obj/machinery/holopad/proc/record_clear() if(disk && disk.record) QDEL_NULL(disk.record) - updateDialog() /obj/effect/overlay/holo_pad_hologram initial_language_holder = /datum/language_holder/universal diff --git a/code/game/machinery/hypnochair.dm b/code/game/machinery/hypnochair.dm index 1b57f61b79..41f420204e 100644 --- a/code/game/machinery/hypnochair.dm +++ b/code/game/machinery/hypnochair.dm @@ -6,14 +6,12 @@ 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() @@ -25,24 +23,24 @@ 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) +/obj/machinery/hypnochair/ui_state(mob/user) + return GLOB.notcontained_state + +/obj/machinery/hypnochair/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "hypnochair", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "HypnoChair", name) ui.open() /obj/machinery/hypnochair/ui_data() var/list/data = list() - data["occupied"] = occupant ? TRUE : FALSE + data["occupied"] = occupant ? 1 : 0 data["open"] = state_open data["interrogating"] = interrogating @@ -178,8 +176,6 @@ 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].") @@ -203,3 +199,4 @@ if(!(L.mobility_flags & MOBILITY_STAND)) return close_machine(target) + diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 099b51db82..ba4d01cfe5 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -26,10 +26,7 @@ on = TRUE icon_state = "igniter1" -/obj/machinery/igniter/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/igniter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) use_power(50) @@ -53,6 +50,9 @@ else icon_state = "igniter0" +/obj/machinery/igniter/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + id = "[idnum][id]" + // Wall mounted remote-control igniter. /obj/machinery/sparker diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index ad5df7cea0..ff6f96a29f 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -3,17 +3,19 @@ /obj/machinery/iv_drip name = "\improper IV drip" - desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate." + desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. Alt-Click to change the transfer rate." icon = 'icons/obj/iv_drip.dmi' icon_state = "iv_drip" anchored = FALSE mouse_drag_pointer = MOUSE_ACTIVE_POINTER var/mob/living/carbon/attached var/mode = IV_INJECTING + var/dripfeed = FALSE var/obj/item/reagent_containers/beaker var/static/list/drip_containers = typecacheof(list(/obj/item/reagent_containers/blood, /obj/item/reagent_containers/food, - /obj/item/reagent_containers/glass)) + /obj/item/reagent_containers/glass, + /obj/item/reagent_containers/chem_pack)) /obj/machinery/iv_drip/Initialize(mapload) . = ..() @@ -131,9 +133,11 @@ if(mode) if(beaker.reagents.total_volume) var/transfer_amount = 5 + if (dripfeed) + transfer_amount = 1 if(istype(beaker, /obj/item/reagent_containers/blood)) // speed up transfer on blood packs - transfer_amount = 10 + transfer_amount *= 2 var/fraction = min(transfer_amount/beaker.reagents.total_volume, 1) //the fraction that is transfered of the total volume beaker.reagents.reaction(attached, INJECT, fraction, FALSE) //make reagents reacts, but don't spam messages beaker.reagents.trans_to(attached, transfer_amount) @@ -157,12 +161,7 @@ attached.transfer_blood_to(beaker, amount) update_icon() -/obj/machinery/iv_drip/attack_hand(mob/user) - . = ..() - if(.) - return - if(!ishuman(user)) - return +/obj/machinery/iv_drip/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(attached) visible_message("[attached] is detached from [src]") attached = null @@ -173,7 +172,21 @@ else toggle_mode() -/obj/machinery/iv_drip/verb/eject_beaker() +/obj/machinery/iv_drip/AltClick(mob/living/user) + if(!user.canUseTopic(src, be_close=TRUE)) + return + if(dripfeed) + dripfeed = FALSE + to_chat(usr, "You loosen the valve to speed up the [src].") + else + dripfeed = TRUE + to_chat(usr, "You tighten the valve to slowly drip-feed the contents of [src].") + +/obj/machinery/iv_drip/attack_robot(mob/user) + if(Adjacent(user)) + attack_hand(user) + +/obj/machinery/iv_drip/verb/eject_beaker(mob/user) set category = "Object" set name = "Remove IV Container" set src in view(1) @@ -188,6 +201,8 @@ if(usr && Adjacent(usr) && usr.can_hold_items()) if(!usr.put_in_hands(beaker)) beaker.forceMove(drop_location()) + if(iscyborg(user)) + beaker.forceMove(drop_location()) beaker = null update_icon() @@ -225,7 +240,7 @@ /obj/machinery/iv_drip/telescopic name = "telescopic IV drip" - desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down." + desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down.Alt-Click with a beaker attached to change the transfer rate." icon_state = "iv_drip" /obj/machinery/iv_drip/telescopic/update_icon_state() diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index c8219e9ebf..e3df79e291 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -282,13 +282,14 @@ ui_interact(user) to_chat(user, "[src] projects a display onto your retina.") -/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, 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, "launchpad_remote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height - ui.set_style("syndicate") - ui.open() +/obj/item/launchpad_remote/ui_state(mob/user) + return GLOB.inventory_state +/obj/item/launchpad_remote/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "LaunchpadRemote") + ui.open() ui.set_autoupdate(TRUE) /obj/item/launchpad_remote/ui_data(mob/user) diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm index ab0a0534ab..a8fa31d5fb 100644 --- a/code/game/machinery/mass_driver.dm +++ b/code/game/machinery/mass_driver.dm @@ -11,6 +11,8 @@ var/id = 1 var/drive_range = 50 //this is mostly irrelevant since current mass drivers throw into space, but you could make a lower-range mass driver for interstation transport or something I guess. +/obj/machinery/mass_driver/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + id = "[idnum][id]" /obj/machinery/mass_driver/proc/drive(amount) if(stat & (BROKEN|NOPOWER)) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 1887ee46c0..54d320e93b 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -4,6 +4,15 @@ #define POPUP_ANIM_TIME 5 #define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad +#define TURRET_FLAG_SHOOT_ALL_REACT (1<<0) // The turret gets pissed off and shoots at people nearby (unless they have sec access!) +#define TURRET_FLAG_AUTH_WEAPONS (1<<1) // Checks if it can shoot people that have a weapon they aren't authorized to have +#define TURRET_FLAG_SHOOT_CRIMINALS (1<<2) // Checks if it can shoot people that are wanted +#define TURRET_FLAG_SHOOT_ALL (1<<3) // The turret gets pissed off and shoots at people nearby (unless they have sec access!) +#define TURRET_FLAG_SHOOT_ANOMALOUS (1<<4) // Checks if it can shoot at unidentified lifeforms (ie xenos) +#define TURRET_FLAG_SHOOT_UNSHIELDED (1<<5) // Checks if it can shoot people that aren't mindshielded and who arent heads +#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs +#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff + /obj/machinery/porta_turret name = "turret" icon = 'icons/obj/turrets.dmi' @@ -15,69 +24,79 @@ use_power = IDLE_POWER_USE //this turret uses and requires power idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power - req_access = list(ACCESS_SEC_DOORS) + req_access = list(ACCESS_SECURITY) /// Only people with Security access power_channel = EQUIP //drains power from the EQUIPMENT channel - - var/base_icon_state = "standard" - var/scan_range = 7 - var/atom/base = null //for turrets inside other objects - - var/raised = 0 //if the turret cover is "open" and the turret is raised - var/raising= 0 //if the turret is currently opening or closing its cover - max_integrity = 160 //the turret's health integrity_failure = 0.5 armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) - - var/locked = TRUE //if the turret's behaviour control access is locked - var/controllock = FALSE //if the turret responds to control panels - - var/installation = /obj/item/gun/energy/e_gun/turret //the type of weapon installed by default + /// Base turret icon state + var/base_icon_state = "standard" + /// Scan range of the turret for locating targets + var/scan_range = 7 + /// For turrets inside other objects + var/atom/base = null + /// If the turret cover is "open" and the turret is raised + var/raised = FALSE + /// If the turret is currently opening or closing its cover + var/raising = FALSE + /// If the turret's behaviour control access is locked + var/locked = TRUE + /// If the turret responds to control panels + var/controllock = FALSE + /// The type of weapon installed by default + var/installation = /obj/item/gun/energy/e_gun/turret + /// What stored gun is in the turret var/obj/item/gun/stored_gun = null - var/gun_charge = 0 //the charge of the gun when retrieved from wreckage - + /// The charge of the gun when retrieved from wreckage + var/gun_charge = 0 + /// In which mode is turret in, stun or lethal var/mode = TURRET_STUN - - var/stun_projectile = null //stun mode projectile type + /// Stun mode projectile type + var/stun_projectile = null + /// Sound of stun projectile var/stun_projectile_sound - var/nonlethal_projectile //projectile to use in stun mode when the target is resting, if any + /// Projectile to use in stun mode when the target is resting, if any + var/nonlethal_projectile + /// Sound of stun projectile wen the target is resting, optional var/nonlethal_projectile_sound - var/lethal_projectile = null //lethal mode projectile type + /// Lethal mode projectile type + var/lethal_projectile = null + /// Sound of lethal projectile var/lethal_projectile_sound - - var/reqpower = 500 //power needed per shot - var/always_up = 0 //Will stay active - var/has_cover = 1 //Hides the cover - - var/obj/machinery/porta_turret_cover/cover = null //the cover that is covering this turret - - var/last_fired = 0 //world.time the turret last fired - var/shot_delay = 15 //ticks until next shot (1.5 ?) - - - var/check_records = 1 //checks if it can use the security records - var/criminals = 1 //checks if it can shoot people on arrest - var/auth_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have - var/stun_all = 0 //if this is active, the turret shoots everything that isn't security or head of staff - var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos) - var/shoot_unloyal = 0 //checks if it can shoot people that aren't loyalty implantd - - var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) - - var/on = TRUE //determines if the turret is on - - var/list/faction = list("turret") // Same faction mobs will never be shot at, no matter the other settings - - var/datum/effect_system/spark_spread/spark_system //the spark system, used for generating... sparks? - + /// Power needed per shot + var/reqpower = 500 + /// Will stay active + var/always_up = FALSE + /// Hides the cover + var/has_cover = TRUE + /// The cover that is covering this turret + var/obj/machinery/porta_turret_cover/cover = null + /// World.time the turret last fired + var/last_fired = 0 + /// Ticks until next shot (1.5 ?) + var/shot_delay = 15 + /// Turret flags about who is turret allowed to shoot + var/turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS + /// Determines if the turret is on + var/on = TRUE + /// Same faction mobs will never be shot at, no matter the other settings + var/list/faction = list("turret") + /// The spark system, used for generating... sparks? + var/datum/effect_system/spark_spread/spark_system + /// Linked turret control panel of the turret var/obj/machinery/turretid/cp = null - - var/wall_turret_direction //The turret will try to shoot from a turf in that direction when in a wall - - var/manual_control = FALSE // + /// The turret will try to shoot from a turf in that direction when in a wall + var/wall_turret_direction + /// If the turret is manually controlled + var/manual_control = FALSE + /// Action button holder for quitting manual control var/datum/action/turret_quit/quit_action + /// Action button holder for switching between turret modes when manually controlling var/datum/action/turret_toggle/toggle_action + /// Mob that is remotely controlling the turret var/mob/remote_controller + /// MISSING: + var/shot_stagger = 0 /obj/machinery/porta_turret/Initialize() . = ..() @@ -99,6 +118,27 @@ if(!has_cover) INVOKE_ASYNC(src, .proc/popUp) +/obj/machinery/porta_turret/proc/toggle_on(var/set_to) + var/current = on + if (!isnull(set_to)) + on = set_to + else + on = !on + if (current != on) + check_should_process() + if (!on) + popDown() + +/obj/machinery/porta_turret/proc/check_should_process() + if (datum_flags & DF_ISPROCESSING) + if (!on || !anchored || (stat & BROKEN) || !powered()) + //end_processing() + STOP_PROCESSING(SSmachines, src) + else + if (on && anchored && !(stat & BROKEN) && powered()) + START_PROCESSING(SSmachines, src) + //begin_processing() + /obj/machinery/porta_turret/update_icon_state() if(!anchored) icon_state = "turretCover" @@ -118,7 +158,6 @@ else icon_state = "[base_icon_state]_unpowered" - /obj/machinery/porta_turret/proc/setup(obj/item/gun/turret_gun) if(stored_gun) qdel(stored_gun) @@ -159,83 +198,88 @@ remove_control() return ..() -/obj/machinery/porta_turret/ui_interact(mob/user) - . = ..() - var/dat - dat += "Status: [on ? "On" : "Off"]
    " - dat += "Behaviour controls are [locked ? "locked" : "unlocked"]
    " +/obj/machinery/porta_turret/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableTurret", name) + ui.open() - if(!locked) - dat += "Check for Weapon Authorization: [auth_weapons ? "Yes" : "No"]
    " - dat += "Check Security Records: [check_records ? "Yes" : "No"]
    " - dat += "Neutralize Identified Criminals: [criminals ? "Yes" : "No"]
    " - dat += "Neutralize All Non-Security and Non-Command Personnel: [stun_all ? "Yes" : "No"]
    " - dat += "Neutralize All Unidentified Life Signs: [check_anomalies ? "Yes" : "No"]
    " - dat += "Neutralize All Non-Loyalty Implanted Personnel: [shoot_unloyal ? "Yes" : "No"]
    " +/obj/machinery/porta_turret/ui_data(mob/user) + var/list/data = list( + "locked" = locked, + "on" = on, + "check_weapons" = turret_flags & TURRET_FLAG_AUTH_WEAPONS, + "neutralize_criminals" = turret_flags & TURRET_FLAG_SHOOT_CRIMINALS, + "neutralize_all" = turret_flags & TURRET_FLAG_SHOOT_ALL, + "neutralize_unidentified" = turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS, + "neutralize_nonmindshielded" = turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED, + "neutralize_cyborgs" = turret_flags & TURRET_FLAG_SHOOT_BORGS, + "ignore_heads" = turret_flags & TURRET_FLAG_SHOOT_HEADS, + "manual_control" = manual_control, + "silicon_user" = FALSE, + "allow_manual_control" = FALSE, + "lasertag_turret" = istype(src, /obj/machinery/porta_turret/lasertag), + ) if(issilicon(user)) + data["silicon_user"] = TRUE if(!manual_control) var/mob/living/silicon/S = user if(S.hack_software) - dat += "Assume direct control : Manual Control
    " - else - dat += "Warning! Remote control protocol enabled.
    " + data["allow_manual_control"] = TRUE + return data - - var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300) - popup.set_content(dat) - popup.open() - -/obj/machinery/porta_turret/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - add_fingerprint(usr) - - if(href_list["power"] && !locked) - if(anchored) //you can't turn a turret on/off if it's not anchored/secured - on = !on //toggle on/off - else - to_chat(usr, "It has to be secured first!") - interact(usr) +/obj/machinery/porta_turret/ui_act(action, list/params) + . = ..() + if(.) return - if(href_list["operation"]) - switch(href_list["operation"]) //toggles customizable behavioural protocols - if("authweapon") - auth_weapons = !auth_weapons - if("checkrecords") - check_records = !check_records - if("shootcrooks") - criminals = !criminals - if("shootall") - stun_all = !stun_all - if("checkxenos") - check_anomalies = !check_anomalies - if("checkloyal") - shoot_unloyal = !shoot_unloyal - if("manual") - if(issilicon(usr) && !manual_control) - give_control(usr) - interact(usr) + switch(action) + if("power") + if(anchored) + toggle_on() + return TRUE + else + to_chat(usr, "It has to be secured first!") + if("authweapon") + turret_flags ^= TURRET_FLAG_AUTH_WEAPONS + return TRUE + if("shootcriminals") + turret_flags ^= TURRET_FLAG_SHOOT_CRIMINALS + return TRUE + if("shootall") + turret_flags ^= TURRET_FLAG_SHOOT_ALL + return TRUE + if("checkxenos") + turret_flags ^= TURRET_FLAG_SHOOT_ANOMALOUS + return TRUE + if("checkloyal") + turret_flags ^= TURRET_FLAG_SHOOT_UNSHIELDED + return TRUE + if("shootborgs") + turret_flags ^= TURRET_FLAG_SHOOT_BORGS + return TRUE + if("shootheads") + turret_flags ^= TURRET_FLAG_SHOOT_HEADS + return TRUE + if("manual") + if(!issilicon(usr)) + return + give_control(usr) + return TRUE + +/obj/machinery/porta_turret/ui_host(mob/user) + if(has_cover && cover) + return cover + if(base) + return base + return src /obj/machinery/porta_turret/power_change() - if(!anchored) + . = ..() + if(!anchored || (stat & BROKEN) || !powered()) update_icon() remove_control() - return - if(stat & BROKEN) - update_icon() - remove_control() - else - if( powered() ) - stat &= ~NOPOWER - update_icon() - else - spawn(rand(0, 15)) - stat |= NOPOWER - remove_control() - update_icon() - + check_should_process() /obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params) if(stat & BROKEN) @@ -283,8 +327,10 @@ locked = !locked to_chat(user, "Controls are now [locked ? "locked" : "unlocked"].") else - to_chat(user, "Access denied.") + to_chat(user, "Access denied.") else if(istype(I, /obj/item/multitool) && !locked) + if(!multitool_check_buffer(user, I)) + return var/obj/item/multitool/M = I M.buffer = src to_chat(user, "You add [src] to multitool buffer.") @@ -292,19 +338,17 @@ return ..() /obj/machinery/porta_turret/emag_act(mob/user) - . = ..() if(obj_flags & EMAGGED) return to_chat(user, "You short out [src]'s threat assessment circuits.") - visible_message("[src] hums oddly...") + audible_message("[src] hums oddly...") obj_flags |= EMAGGED controllock = TRUE - on = FALSE //turns off the turret temporarily + toggle_on(FALSE) //turns off the turret temporarily update_icon() - sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit - on = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here - return TRUE - + //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit + addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 6 SECONDS) + //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here /obj/machinery/porta_turret/emp_act(severity) . = ..() @@ -313,63 +357,41 @@ if(on) //if the turret is on, the EMP no matter how severe disables the turret for a while //and scrambles its settings, with a slight chance of having an emag effect - check_records = pick(0, 1) - criminals = pick(0, 1) - auth_weapons = pick(0, 1) - stun_all = pick(0, 0, 0, 0, 1) //stun_all is a pretty big deal, so it's least likely to get turned on + if(prob(50)) + turret_flags |= TURRET_FLAG_SHOOT_CRIMINALS + if(prob(50)) + turret_flags |= TURRET_FLAG_AUTH_WEAPONS + if(prob(20)) + turret_flags |= TURRET_FLAG_SHOOT_ALL // Shooting everyone is a pretty big deal, so it's least likely to get turned on - on = FALSE + toggle_on(FALSE) remove_control() - spawn(rand(60,600)) - if(!on) - on = TRUE + addtimer(CALLBACK(src, .proc/toggle_on, TRUE), rand(60,600)) /obj/machinery/porta_turret/take_damage(damage, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) . = ..() - if(.) //damage received + if(. && obj_integrity > 0) //damage received if(prob(30)) spark_system.start() - if(on && !attacked && !(obj_flags & EMAGGED)) - attacked = TRUE + if(on && !(turret_flags & TURRET_FLAG_SHOOT_ALL_REACT) && !(obj_flags & EMAGGED)) + turret_flags |= TURRET_FLAG_SHOOT_ALL_REACT addtimer(CALLBACK(src, .proc/reset_attacked), 60) /obj/machinery/porta_turret/proc/reset_attacked() - attacked = FALSE + turret_flags &= ~TURRET_FLAG_SHOOT_ALL_REACT /obj/machinery/porta_turret/deconstruct(disassembled = TRUE) qdel(src) /obj/machinery/porta_turret/obj_break(damage_flag) - if(!(flags_1 & NODECONSTRUCT_1) && !(stat & BROKEN)) - stat |= BROKEN //enables the BROKEN bit + . = ..() + if(.) power_change() invisibility = 0 spark_system.start() //creates some sparks because they look cool qdel(cover) //deletes the cover - no need on keeping it there! -//turret healing -/obj/machinery/porta_turret/examine(mob/user) - . = ..() - if(obj_integrity < max_integrity) - . += "Use a welder to fix it." - -/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I) - . = TRUE - if(obj_integrity < max_integrity) - if(!I.tool_start_check(user, amount=0)) - return - user.visible_message("[user] is welding the turret.", \ - "You begin repairing the turret...", \ - "You hear welding.") - if(I.use_tool(src, user, 40, volume=50)) - obj_integrity = max_integrity - user.visible_message("[user.name] has repaired [src].", \ - "You finish repairing the turret.") - else - to_chat(user, "The turret doesn't need repairing.") - - /obj/machinery/porta_turret/process() //the main machinery process if(cover == null && anchored) //if it has no cover and is anchored @@ -381,35 +403,43 @@ cover.parent_turret = src //assign the cover its parent_turret, which would be this (src) if(!on || (stat & (NOPOWER|BROKEN)) || manual_control) - return + return PROCESS_KILL var/list/targets = list() for(var/mob/A in view(scan_range, base)) if(A.invisibility > SEE_INVISIBLE_LIVING) continue - if(check_anomalies)//if it's set to check for simple animals + if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS)//if it's set to check for simple animals if(isanimal(A)) var/mob/living/simple_animal/SA = A if(SA.stat || in_faction(SA)) //don't target if dead or in faction continue targets += SA - if(issilicon(A)) - var/mob/living/silicon/sillycone = A - if(sillycone.stat || in_faction(sillycone)) + continue + + if(issilicon(A)) + var/mob/living/silicon/sillycone = A + + if(ispAI(A)) + continue + + if((turret_flags & TURRET_FLAG_SHOOT_BORGS) && sillycone.stat != DEAD && iscyborg(sillycone)) + targets += sillycone + continue + + if(sillycone.stat || in_faction(sillycone)) + continue + + if(iscyborg(sillycone)) + var/mob/living/silicon/robot/sillyconerobot = A + if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE) continue - if(iscyborg(sillycone)) - var/mob/living/silicon/robot/sillyconerobot = A - if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE) - continue - - targets += sillycone - - if(iscarbon(A)) + else if(iscarbon(A)) var/mob/living/carbon/C = A - //If not emagged, only target non downed carbons - if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || (C.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)))//CIT CHANGE - replaces check for lying with check for recoveringstam + //If not emagged, only target carbons that can use items + if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE))) continue //If emagged, target all but dead carbons @@ -418,12 +448,13 @@ //if the target is a human and not in our faction, analyze threat level if(ishuman(C) && !in_faction(C)) + if(assess_perp(C) >= 4) targets += C - - else if(check_anomalies) //non humans who are not simple animals (xenos etc) + else if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) //non humans who are not simple animals (xenos etc) if(!in_faction(C)) targets += C + for(var/A in GLOB.mechas_list) if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range)) var/obj/mecha/Mech = A @@ -431,11 +462,18 @@ if(assess_perp(Mech.occupant) >= 4) targets += Mech + if((turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) && GLOB.blobs.len && (mode == TURRET_LETHAL)) + for(var/obj/structure/blob/B in view(scan_range, base)) + targets += B + if(targets.len) tryToShootAt(targets) else if(!always_up) popDown() // no valid targets, close the cover +/obj/machinery/porta_turret/proc/randomize_shot_stagger() + shot_stagger = rand(0, min(2 SECONDS, round(shot_delay/3, world.tick_lag))) + /obj/machinery/porta_turret/proc/tryToShootAt(list/atom/movable/targets) while(targets.len > 0) var/atom/movable/M = pick(targets) @@ -443,7 +481,6 @@ if(target(M)) return 1 - /obj/machinery/porta_turret/proc/popUp() //pops the turret up if(!anchored) return @@ -485,36 +522,37 @@ if(obj_flags & EMAGGED) return 10 //if emagged, always return 10. - if((stun_all || attacked) && !allowed(perp)) + if((turret_flags & (TURRET_FLAG_SHOOT_ALL | TURRET_FLAG_SHOOT_ALL_REACT)) && !allowed(perp)) //if the turret has been attacked or is angry, target all non-sec people if(!allowed(perp)) return 10 - if(auth_weapons) //check for weapon authorization + if(turret_flags & TURRET_FLAG_AUTH_WEAPONS) //check for weapon authorization if(isnull(perp.wear_id) || istype(perp.wear_id.GetID(), /obj/item/card/id/syndicate)) if(allowed(perp)) //if the perp has security access, return 0 return 0 - if(perp.is_holding_item_of_type(/obj/item/gun) || perp.is_holding_item_of_type(/obj/item/melee/baton)) threatcount += 4 if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee/baton)) threatcount += 2 - if(check_records) //if the turret can check the records, check if they are set to *Arrest* on records + if(turret_flags & TURRET_FLAG_SHOOT_CRIMINALS) //if the turret can check the records, check if they are set to *Arrest* on records var/perpname = perp.get_face_name(perp.get_id_name()) var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security) if(!R || (R.fields["criminal"] == "*Arrest*")) threatcount += 4 - if(shoot_unloyal) - if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)) - threatcount += 4 + if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD))) + threatcount += 4 + + // If we aren't shooting heads then return a threatcount of 0 + if (!(turret_flags & TURRET_FLAG_SHOOT_HEADS) && (perp.get_assignment() in GLOB.command_positions)) + return 0 return threatcount - /obj/machinery/porta_turret/proc/in_faction(mob/target) for(var/faction1 in faction) if(faction1 in target.faction) @@ -525,18 +563,21 @@ if(target) popUp() //pop the turret up if it's not already up. setDir(get_dir(base, target))//even if you can't shoot, follow the target - shootAt(target) + INVOKE_ASYNC(src, .proc/shootAt, target) return 1 return -/obj/machinery/porta_turret/proc/shootAt(atom/movable/target) +/obj/machinery/porta_turret/proc/shootAt(atom/movable/target, stagger_enabled = FALSE) if(!raised) //the turret has to be raised in order to fire - makes sense, right? return - if(!(obj_flags & EMAGGED)) //if it hasn't been emagged, cooldown before shooting again - if(last_fired + shot_delay > world.time) - return - last_fired = world.time + if(last_fired + shot_delay > world.time) + return + last_fired = world.time + + if(stagger_enabled) + randomize_shot_stagger() + sleep(shot_stagger) var/turf/T = get_turf(src) var/turf/U = get_turf(target) @@ -557,15 +598,14 @@ T = closer break - var/mob/living/carbon/C - if(iscarbon(target)) - C = target - update_icon() var/obj/item/projectile/A //any emagged turrets drains 2x power and uses a different projectile? if(mode == TURRET_STUN) - if(nonlethal_projectile && C && C.resting) + var/mob/living/carbon/C = null + if(iscarbon(target)) + C = target + if(nonlethal_projectile && C?.resting) use_power(reqpower*0.5) A = new nonlethal_projectile(T) playsound(loc, nonlethal_projectile_sound, 75, 1) @@ -576,7 +616,7 @@ else use_power(reqpower * 2) A = new lethal_projectile(T) - playsound(loc, lethal_projectile_sound, 75, 1) + playsound(loc, lethal_projectile_sound, 75, TRUE) //Shooting Code: @@ -586,16 +626,15 @@ A.fire() return A -/obj/machinery/porta_turret/proc/setState(on, mode) +/obj/machinery/porta_turret/proc/setState(on, mode, shoot_cyborgs) if(controllock) return - src.on = on - if(!on) - popDown() + + shoot_cyborgs ? (turret_flags |= TURRET_FLAG_SHOOT_BORGS) : (turret_flags &= ~TURRET_FLAG_SHOOT_BORGS) + toggle_on(on) src.mode = mode power_change() - /datum/action/turret_toggle name = "Toggle Mode" icon_icon = 'icons/mob/actions/actions_mecha.dmi' @@ -679,7 +718,15 @@ /obj/machinery/porta_turret/syndicate/ComponentInitialize() . = ..() - AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + // AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) + AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) //this one or ^ one? + + +/obj/machinery/porta_turret/syndicate/setup() + return + +/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp) + return 10 //Syndicate turrets shoot everything not in their faction /obj/machinery/porta_turret/syndicate/energy icon_state = "standard_stun" @@ -692,7 +739,6 @@ lethal_projectile_sound = 'sound/weapons/laser.ogg' desc = "An energy blaster auto-turret." - /obj/machinery/porta_turret/syndicate/energy/heavy icon_state = "standard_stun" base_icon_state = "standard" @@ -709,14 +755,13 @@ integrity_failure = 0.08 armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) - -/obj/machinery/porta_turret/syndicate/setup() - return - -/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp) - return 10 //Syndicate turrets shoot everything not in their faction +/obj/machinery/porta_turret/syndicate/energy/raven + stun_projectile = /obj/item/projectile/beam/laser + stun_projectile_sound = 'sound/weapons/laser.ogg' + faction = list("neutral","silicon","turret") /obj/machinery/porta_turret/syndicate/pod + integrity_failure = 0.5 max_integrity = 40 stun_projectile = /obj/item/projectile/bullet/syndicate_turret lethal_projectile = /obj/item/projectile/bullet/syndicate_turret @@ -743,6 +788,7 @@ faction = list("silicon") nonlethal_projectile = /obj/item/projectile/beam/disabler nonlethal_projectile_sound = 'sound/weapons/taser2.ogg' + turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS | TURRET_FLAG_SHOOT_HEADS /obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp) return 10 //AI turrets shoot at everything not in their faction @@ -798,6 +844,7 @@ /obj/machinery/porta_turret/centcom_shuttle/weak max_integrity = 120 + integrity_failure = 0.5 name = "Old Laser Turret" desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else." stun_projectile = /obj/item/projectile/beam/weak/penetrator @@ -811,7 +858,6 @@ stun_projectile_sound = 'sound/weapons/gunshot.ogg' desc = "A ballistic machine gun auto-turret." - //////////////////////// //Turret Control Panel// //////////////////////// @@ -822,14 +868,22 @@ icon = 'icons/obj/machines/turret_control.dmi' icon_state = "control_standby" density = FALSE - var/enabled = 1 - var/lethal = 0 - var/locked = TRUE - var/control_area = null //can be area name, path or nothing. - var/ailock = 0 // AI cannot use this req_access = list(ACCESS_AI_UPLOAD) - var/list/obj/machinery/porta_turret/turrets = list() resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + /// Variable dictating if linked turrets are active and will shoot targets + var/enabled = TRUE + /// Variable dictating if linked turrets will shoot lethal projectiles + var/lethal = FALSE + /// Variable dictating if the panel is locked, preventing changes to turret settings + var/locked = TRUE + /// An area in which linked turrets are located, it can be an area name, path or nothing + var/control_area = null + /// AI is unable to use this machine if set to TRUE + var/ailock = FALSE + /// Variable dictating if linked turrets will shoot cyborgs + var/shoot_cyborgs = FALSE + /// List of all linked turrets + var/list/turrets = list() /obj/machinery/turretid/Initialize(mapload, ndir = 0, built = 0) . = ..() @@ -862,112 +916,111 @@ T.cp = src /obj/machinery/turretid/examine(mob/user) - . = ..() - if(hasSiliconAccessInArea(user) && (!stat & BROKEN)) - . += "Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets." - . += "Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"]." + . += ..() + if(issilicon(user) && !(stat & BROKEN)) + . += {"Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets. + Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"]."} /obj/machinery/turretid/attackby(obj/item/I, mob/user, params) if(stat & BROKEN) return if (istype(I, /obj/item/multitool)) + if(!multitool_check_buffer(user, I)) + return var/obj/item/multitool/M = I if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret)) turrets |= M.buffer - to_chat(user, "You link \the [M.buffer] with \the [src]") + to_chat(user, "You link \the [M.buffer] with \the [src].") return - if (hasSiliconAccessInArea(user)) + if (issilicon(user)) return attack_hand(user) if ( get_dist(src, user) == 0 ) // trying to unlock the interface if (allowed(usr)) if(obj_flags & EMAGGED) - to_chat(user, "The turret control is unresponsive.") + to_chat(user, "The turret control is unresponsive!") return locked = !locked to_chat(user, "You [ locked ? "lock" : "unlock"] the panel.") - if (locked) - if (user.machine==src) - user.unset_machine() - user << browse(null, "window=turretid") - else - if (user.machine==src) - attack_hand(user) else - to_chat(user, "Access denied.") + to_chat(user, "Access denied.") /obj/machinery/turretid/emag_act(mob/user) - . = ..() if(obj_flags & EMAGGED) return - to_chat(user, "You short out the turret controls' access analysis module.") + to_chat(user, "You short out the turret controls' access analysis module.") obj_flags |= EMAGGED locked = FALSE - if(user && user.machine == src) - attack_hand(user) - return TRUE /obj/machinery/turretid/attack_ai(mob/user) if(!ailock || IsAdminGhost(user)) return attack_hand(user) else - to_chat(user, "There seems to be a firewall preventing you from accessing this device.") + to_chat(user, "There seems to be a firewall preventing you from accessing this device!") -/obj/machinery/turretid/ui_interact(mob/user) +/obj/machinery/turretid/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TurretControl", name) + ui.open() + +/obj/machinery/turretid/ui_data(mob/user) + var/list/data = list() + data["locked"] = locked + data["siliconUser"] = hasSiliconAccessInArea(user) || IsAdminGhost(user) + data["enabled"] = enabled + data["lethal"] = lethal + data["shootCyborgs"] = shoot_cyborgs + return data + +/obj/machinery/turretid/ui_act(action, list/params) . = ..() - if ( get_dist(src, user) > 0 ) - if ( !(hasSiliconAccessInArea(user) || IsAdminGhost(user)) ) - to_chat(user, "You are too far away.") - user.unset_machine() - user << browse(null, "window=turretid") - return - - var/t = "" - - if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user))) - t += "
    Swipe ID card to unlock interface
    " - else - if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user)) - t += "
    Swipe ID card to lock interface
    " - t += "Turrets [enabled?"activated":"deactivated"] - [enabled?"Disable":"Enable"]?
    " - t += "Currently set for [lethal?"lethal":"stun repeatedly"] - Change to [lethal?"Stun repeatedly":"Lethal"]?
    " - - var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([get_area_name(src, TRUE)])") - popup.set_content(t) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() - -/obj/machinery/turretid/Topic(href, href_list) - if(..()) + if(.) return - if (locked) - if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr))) - to_chat(usr, "Control panel is locked!") - return - if (href_list["toggleOn"]) - toggle_on() - else if (href_list["toggleLethal"]) - toggle_lethal() - attack_hand(usr) -/obj/machinery/turretid/proc/toggle_lethal() + switch(action) + if("lock") + if(!hasSiliconAccessInArea(usr) || IsAdminGhost(usr)) + return + if((obj_flags & EMAGGED) || (stat & BROKEN)) + to_chat(usr, "The turret control is unresponsive!") + return + locked = !locked + return TRUE + if("power") + toggle_on(usr) + return TRUE + if("mode") + toggle_lethal(usr) + return TRUE + if("shoot_silicons") + shoot_silicons(usr) + return TRUE + +/obj/machinery/turretid/proc/toggle_lethal(mob/user) lethal = !lethal + add_hiddenprint(user) + log_combat(user, src, "[lethal ? "enabled" : "disabled"] lethals on") updateTurrets() -/obj/machinery/turretid/proc/toggle_on() +/obj/machinery/turretid/proc/toggle_on(mob/user) enabled = !enabled + add_hiddenprint(user) + log_combat(user, src, "[enabled ? "enabled" : "disabled"]") + updateTurrets() + +/obj/machinery/turretid/proc/shoot_silicons(mob/user) + shoot_cyborgs = !shoot_cyborgs + add_hiddenprint(user) + log_combat(user, src, "[shoot_cyborgs ? "Shooting Borgs" : "Not Shooting Borgs"]") updateTurrets() /obj/machinery/turretid/proc/updateTurrets() for (var/obj/machinery/porta_turret/aTurret in turrets) - aTurret.setState(enabled, lethal) - update_icon() - -/obj/machinery/turretid/power_change() - ..() + aTurret.setState(enabled, lethal, shoot_cyborgs) update_icon() /obj/machinery/turretid/update_icon_state() @@ -1045,11 +1098,7 @@ /obj/machinery/porta_turret/lasertag req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE) - check_records = 0 - criminals = 0 - auth_weapons = 1 - stun_all = 0 - check_anomalies = 0 + turret_flags = TURRET_FLAG_AUTH_WEAPONS var/team_color /obj/machinery/porta_turret/lasertag/assess_perp(mob/living/carbon/human/perp) @@ -1077,20 +1126,14 @@ if(properties["team_color"]) team_color = properties["team_color"] -/obj/machinery/porta_turret/lasertag/ui_interact(mob/user) - . = ..() +/obj/machinery/porta_turret/lasertag/ui_status(mob/user) if(ishuman(user)) var/mob/living/carbon/human/H = user if(team_color == "blue" && istype(H.wear_suit, /obj/item/clothing/suit/redtag)) - return + return UI_CLOSE if(team_color == "red" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag)) - return - - var/dat = "Status: [on ? "On" : "Off"]" - - var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300) - popup.set_content(dat) - popup.open() + return UI_CLOSE + return ..() //lasertag presets /obj/machinery/porta_turret/lasertag/red @@ -1106,11 +1149,9 @@ if(on) if(team_color == "blue") if(istype(P, /obj/item/projectile/beam/lasertag/redtag)) - on = FALSE - spawn(100) - on = TRUE + toggle_on(FALSE) + addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS) else if(team_color == "red") if(istype(P, /obj/item/projectile/beam/lasertag/bluetag)) - on = FALSE - spawn(100) - on = TRUE + toggle_on(FALSE) + addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS) diff --git a/code/game/machinery/porta_turret/portable_turret_construct.dm b/code/game/machinery/porta_turret/portable_turret_construct.dm index 9d86e3792d..7c2000175e 100644 --- a/code/game/machinery/porta_turret/portable_turret_construct.dm +++ b/code/game/machinery/porta_turret/portable_turret_construct.dm @@ -79,6 +79,9 @@ if(PTURRET_INTERNAL_ARMOUR_ON) if(istype(I, /obj/item/gun/energy)) //the gun installation part var/obj/item/gun/energy/E = I + if(!E.can_turret) + to_chat(user, "[src] can't be fit into turrets.") + return if(!user.transferItemToLoc(E, src)) return installed_gun = E @@ -168,10 +171,7 @@ return ..() -/obj/machinery/porta_turret_construct/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/porta_turret_construct/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) switch(build_step) if(PTURRET_GUN_EQUIPPED) build_step = PTURRET_INTERNAL_ARMOUR_ON diff --git a/code/game/machinery/porta_turret/portable_turret_cover.dm b/code/game/machinery/porta_turret/portable_turret_cover.dm index 7fdb9b38be..e0746bda78 100644 --- a/code/game/machinery/porta_turret/portable_turret_cover.dm +++ b/code/game/machinery/porta_turret/portable_turret_cover.dm @@ -31,10 +31,7 @@ return parent_turret.attack_ai(user) -/obj/machinery/porta_turret_cover/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/porta_turret_cover/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) return parent_turret.attack_hand(user) diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm old mode 100644 new mode 100755 index 2fff2011c1..1d118023c9 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -19,7 +19,7 @@ /obj/item/modular_computer, /obj/item/ammo_casing/mws_batt, /obj/item/ammo_box/magazine/mws_mag, - /obj/item/twohanded/electrostaff, + /obj/item/electrostaff, /obj/item/gun/ballistic/automatic/magrifle)) /obj/machinery/recharger/RefreshParts() @@ -108,10 +108,7 @@ return ..() -/obj/machinery/recharger/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/recharger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) if(charging) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index bbafe99006..0accd0994c 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -126,17 +126,6 @@ update_icon() /obj/machinery/recharge_station/proc/process_occupant() - if(occupant && iscyborg(occupant)) - var/mob/living/silicon/robot/R = occupant - restock_modules() - if(repairs) - R.heal_bodypart_damage(repairs, repairs - 1) - if(R.cell) - R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge) - -/obj/machinery/recharge_station/proc/restock_modules() - if(occupant) - var/mob/living/silicon/robot/R = occupant - if(R && R.module) - var/coeff = recharge_speed * 0.005 - R.module.respawn_consumable(R, coeff) + if(!occupant) + return + SEND_SIGNAL(occupant, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, recharge_speed, repairs) diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index 8680aa69e6..706d2bb9bf 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -225,6 +225,6 @@ /obj/item/paper/guides/recycler name = "paper - 'garbage duty instructions'" - info = "

    New Assignment

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

    There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!" + info = "_New Assignment_\n\n You have been assigned to collect garbage from trash bins, located around the station. The crewmembers will put their trash into it and you will collect the said trash.

    There is a recycling machine near your closet, inside maintenance; use it to recycle the trash for a small chance to get useful minerals. Then deliver these minerals to cargo or engineering. You are our last hope for a clean station, do not screw this up!" #undef SAFETY_COOLDOWN diff --git a/code/game/machinery/sheetifier.dm b/code/game/machinery/sheetifier.dm new file mode 100644 index 0000000000..7b83401194 --- /dev/null +++ b/code/game/machinery/sheetifier.dm @@ -0,0 +1,44 @@ +/obj/machinery/sheetifier + name = "Sheet-meister 2000" + desc = "A very sheety machine" + icon = 'icons/obj/machines/sheetifier.dmi' + icon_state = "base_machine" + density = TRUE + use_power = IDLE_POWER_USE + idle_power_usage = 10 + active_power_usage = 100 + circuit = /obj/item/circuitboard/machine/sheetifier + layer = BELOW_OBJ_LAYER + var/busy_processing = FALSE + +/obj/machinery/sheetifier/Initialize() + . = ..() + AddComponent(/datum/component/material_container, list(/datum/material/meat), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE, /obj/item/reagent_containers/food/snacks/meat/slab, CALLBACK(src, .proc/CanInsertMaterials), CALLBACK(src, .proc/AfterInsertMaterials)) + +/obj/machinery/sheetifier/update_overlays() + . = ..() + if(stat & (BROKEN|NOPOWER)) + return + var/mutable_appearance/on_overlay = mutable_appearance(icon, "buttons_on") + . += on_overlay + +/obj/machinery/sheetifier/update_icon_state() + icon_state = "base_machine[busy_processing ? "_processing" : ""]" + +/obj/machinery/sheetifier/proc/CanInsertMaterials() + return !busy_processing + +/obj/machinery/sheetifier/proc/AfterInsertMaterials(item_inserted, id_inserted, amount_inserted) + busy_processing = TRUE + update_icon() + var/datum/material/last_inserted_material = id_inserted + var/mutable_appearance/processing_overlay = mutable_appearance(icon, "processing") + processing_overlay.color = last_inserted_material.color + flick_overlay_static(processing_overlay, src, 64) + addtimer(CALLBACK(src, .proc/finish_processing), 64) + +/obj/machinery/sheetifier/proc/finish_processing() + busy_processing = FALSE + update_icon() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + materials.retrieve_all() //Returns all as sheets diff --git a/code/game/machinery/shuttle/shuttle_engine.dm b/code/game/machinery/shuttle/shuttle_engine.dm index 1b2ce686d2..c3de384c58 100644 --- a/code/game/machinery/shuttle/shuttle_engine.dm +++ b/code/game/machinery/shuttle/shuttle_engine.dm @@ -130,7 +130,7 @@ var/deltaTemperature = req_power / heat_cap if(deltaTemperature < 0) return - env.temperature += deltaTemperature + env.set_temperature(env.return_temperature(),deltaTemperature) air_update_turf() /obj/machinery/shuttle/engine/default_change_direction_wrench(mob/user, obj/item/I) diff --git a/code/game/machinery/shuttle/shuttle_heater.dm b/code/game/machinery/shuttle/shuttle_heater.dm index 3c36e53b5a..56854d2d71 100644 --- a/code/game/machinery/shuttle/shuttle_heater.dm +++ b/code/game/machinery/shuttle/shuttle_heater.dm @@ -89,8 +89,8 @@ var/datum/gas_mixture/air_contents = airs[1] if(!air_contents) return - air_contents.volume = gas_capacity - air_contents.temperature = T20C + air_contents.set_volume(gas_capacity) + air_contents.set_temperature(T20C) /obj/machinery/atmospherics/components/unary/shuttle/heater/proc/hasFuel(var/required) var/datum/gas_mixture/air_contents = airs[1] diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 1730569e10..c6484b051c 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -83,9 +83,9 @@ var/datum/gas_mixture/env = L.return_air() var/newMode = HEATER_MODE_STANDBY - if(setMode != HEATER_MODE_COOL && env.temperature < targetTemperature - temperatureTolerance) + if(setMode != HEATER_MODE_COOL && env.return_temperature() < targetTemperature - temperatureTolerance) newMode = HEATER_MODE_HEAT - else if(setMode != HEATER_MODE_HEAT && env.temperature > targetTemperature + temperatureTolerance) + else if(setMode != HEATER_MODE_HEAT && env.return_temperature() > targetTemperature + temperatureTolerance) newMode = HEATER_MODE_COOL if(mode != newMode) @@ -96,7 +96,7 @@ return var/heat_capacity = env.heat_capacity() - var/requiredPower = abs(env.temperature - targetTemperature) * heat_capacity + var/requiredPower = abs(env.return_temperature() - targetTemperature) * heat_capacity requiredPower = min(requiredPower, heatingPower) if(requiredPower < 1) @@ -106,7 +106,7 @@ if(mode == HEATER_MODE_COOL) deltaTemperature *= -1 if(deltaTemperature) - env.temperature += deltaTemperature + env.set_temperature(env.return_temperature() + deltaTemperature) air_update_turf() cell.use(requiredPower / efficiency) else @@ -170,12 +170,10 @@ ..() 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) +/obj/machinery/space_heater/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "space_heater", name, 400, 305, master_ui, state) + ui = new(user, src, "SpaceHeater", name) ui.open() /obj/machinery/space_heater/ui_data() @@ -194,9 +192,9 @@ var/curTemp if(istype(L)) var/datum/gas_mixture/env = L.return_air() - curTemp = env.temperature + curTemp = env.return_temperature() else if(isturf(L)) - curTemp = L.temperature + curTemp = L.return_temperature() if(isnull(curTemp)) data["currentTemp"] = "N/A" else @@ -210,7 +208,7 @@ if("power") on = !on mode = HEATER_MODE_STANDBY - usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "You switch [on ? "on" : "off"] \the [src].") + usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "You switch [on ? "on" : "off"] \the [src].") update_icon() if (on) START_PROCESSING(SSmachines, src) @@ -222,16 +220,7 @@ if(!panel_open) return var/target = params["target"] - var/adjust = text2num(params["adjust"]) - if(target == "input") - target = input("New target temperature:", name, round(targetTemperature - T0C, 1)) as num|null - if(!isnull(target) && !..()) - target += T0C - . = TRUE - else if(adjust) - target = targetTemperature + adjust - . = TRUE - else if(text2num(target) != null) + if(text2num(target) != null) target= text2num(target) + T0C . = TRUE if(.) diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 3bb67e2a1c..8937106601 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -287,7 +287,7 @@ if(!.) return switch(var_name) - if("shuttle_id") + if(NAMEOF(src, shuttle_id)) update() /obj/machinery/status_display/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index cf6b2b4bf4..cecf351ea9 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -301,8 +301,6 @@ open_machine() dump_contents() return - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT user.visible_message("You see [user] kicking against the doors of [src]!", \ "You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)", \ "You hear a thump from [src].") @@ -379,11 +377,13 @@ return ..() -/obj/machinery/suit_storage_unit/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) +/obj/machinery/suit_storage_unit/ui_state(mob/user) + return GLOB.notcontained_state + +/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "suit_storage_unit", name, 400, 305, master_ui, state) + ui = new(user, src, "SuitStorageUnit", name) ui.open() /obj/machinery/suit_storage_unit/ui_data() diff --git a/code/game/machinery/syndicatebeacon.dm b/code/game/machinery/syndicatebeacon.dm index e300afe6b9..1b3f942c51 100644 --- a/code/game/machinery/syndicatebeacon.dm +++ b/code/game/machinery/syndicatebeacon.dm @@ -68,10 +68,7 @@ GLOBAL_VAR_INIT(singularity_counter, 0) /obj/machinery/power/singularity_beacon/attack_ai(mob/user) return -/obj/machinery/power/singularity_beacon/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/power/singularity_beacon/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(anchored) return active ? Deactivate(user) : Activate(user) else diff --git a/code/game/machinery/telecomms/computers/logbrowser.dm b/code/game/machinery/telecomms/computers/logbrowser.dm index fdf6ba121c..ca04009e3b 100644 --- a/code/game/machinery/telecomms/computers/logbrowser.dm +++ b/code/game/machinery/telecomms/computers/logbrowser.dm @@ -17,11 +17,10 @@ var/notice = "" var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech -/obj/machinery/computer/telecomms/server/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/telecomms/server/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "tcommsserver", "Telecomms Server Monitor", 575, 400, master_ui, state) + ui = new(user, src, "TelecommsLogBrowser", "Telecomms Server Monitor") ui.open() /obj/machinery/computer/telecomms/server/ui_data(mob/user) diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm index 41d417967b..539025e4d5 100644 --- a/code/game/machinery/telecomms/computers/message.dm +++ b/code/game/machinery/telecomms/computers/message.dm @@ -36,12 +36,11 @@ light_color = LIGHT_COLOR_GREEN -/obj/machinery/computer/message_monitor/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/message_monitor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "telepdalog", name, 727, 510, master_ui, state) + ui = new(user, src, "TelecommsPDALog", name) ui.open() /obj/machinery/computer/message_monitor/ui_static_data(mob/user) @@ -389,7 +388,6 @@ /obj/item/paper/monitorkey/proc/print(obj/machinery/telecomms/message_server/server) info = "

    Daily Key Reset


    The new message monitor key is '[server.decryptkey]'.
    Please keep this a secret and away from the clown.
    If necessary, change the password to a more secure one." - info_links = info add_overlay("paper_words") /obj/item/paper/monitorkey/LateInitialize() diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm index bca16a0de4..b711b9fa40 100644 --- a/code/game/machinery/telecomms/computers/telemonitor.dm +++ b/code/game/machinery/telecomms/computers/telemonitor.dm @@ -17,12 +17,11 @@ circuit = /obj/item/circuitboard/computer/comm_monitor -/obj/machinery/computer/telecomms/monitor/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "telemonitor", name, 575, 400, master_ui, state) + ui = new(user, src, "TelecommsMonitor", name) ui.open() /obj/machinery/computer/telecomms/monitor/ui_data(mob/user) diff --git a/code/game/machinery/telecomms/machine_interactions.dm b/code/game/machinery/telecomms/machine_interactions.dm index 6d299f4413..cc8784c5b8 100644 --- a/code/game/machinery/telecomms/machine_interactions.dm +++ b/code/game/machinery/telecomms/machine_interactions.dm @@ -27,16 +27,15 @@ else return ..() -/obj/machinery/telecomms/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) +/obj/machinery/telecomms/ui_interact(mob/user, datum/tgui/ui) if(!canInteract(user)) if(ui) ui.close() //haha no. return - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "teleinteract", "[name] Access", 520, 500, master_ui, state) + ui = new(user, src, "TelecommsInteraction", "[name] Access") ui.open() /obj/machinery/telecomms/ui_data(mob/user) diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm index 7f8872ca74..04fd5f6af5 100644 --- a/code/game/machinery/telecomms/machines/message_server.dm +++ b/code/game/machinery/telecomms/machines/message_server.dm @@ -5,16 +5,73 @@ require the message server. */ -// A decorational representation of SSblackbox, usually placed alongside the message server. +// A decorational representation of SSblackbox, usually placed alongside the message server. Also contains a traitor theft item. /obj/machinery/blackbox_recorder icon = 'icons/obj/stationobjs.dmi' icon_state = "blackbox" - name = "Blackbox Recorder" + name = "blackbox recorder" density = TRUE use_power = IDLE_POWER_USE idle_power_usage = 10 active_power_usage = 100 armor = list("melee" = 25, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 70) + var/obj/item/stored + +/obj/machinery/blackbox_recorder/Initialize() + . = ..() + stored = new /obj/item/blackbox(src) + +/obj/machinery/blackbox_recorder/on_attack_hand(mob/living/user, act_intent, unarmed_attack_flags) + . = ..() + if(stored) + to_chat(user, "You start struggling to pry the [stored] from the [src]...") + if(!do_after(user, 30 SECONDS, TRUE, src)) + to_chat(user, "Your fingers slip as you fail to pry the [stored] from the [src], clicking it right back into the slot!") + return + if(user.put_in_hands(stored)) + stored.forceMove(user.drop_location()) + stored = null + to_chat(user, "You successfully pry the [stored] from the [src], and send its overwhelming weight tumbling onto the ground! The tapes on the [src] stop spinning...") + update_icon() + return + else + to_chat(user, "It seems that the blackbox is missing...") + return + +/obj/machinery/blackbox_recorder/attackby(obj/item/I, mob/living/user, params) + . = ..() + if(istype(I, /obj/item/blackbox)) + if(HAS_TRAIT(I, TRAIT_NODROP) || !user.transferItemToLoc(I, src)) + to_chat(user, "[I] is stuck to your hand!") + return + user.visible_message("[user] clicks the [I] into the [src]!", \ + "You press [I] into [src], and it clicks into place. The tapes on the [src] begin spinning again...") + playsound(src, 'sound/machines/click.ogg', 50, TRUE) + stored = I + update_icon() + return ..() + return ..() + +/obj/machinery/blackbox_recorder/Destroy() + if(stored) + stored.forceMove(loc) + new /obj/effect/decal/cleanable/oil(loc) + return ..() + +/obj/machinery/blackbox_recorder/update_icon() + . = ..() + if(!stored) + icon_state = "blackbox_b" + else + icon_state = "blackbox" + +/obj/item/blackbox + name = "the blackbox" + desc = "A strange relic, capable of recording data on extradimensional vertices. It lives inside the blackbox recorder for safe keeping." + icon = 'icons/obj/stationobjs.dmi' + icon_state = "blackcube" + w_class = WEIGHT_CLASS_BULKY + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF // The message server itself. @@ -140,9 +197,9 @@ ..() if(href_list["photo"]) var/mob/M = usr - - M << browse_rsc(picture.picture_image, "pda_photo.png") - + + M << browse_rsc(picture.picture_image, "pda_photo.png") + var/dat = "
    " dat += "" dat += "
    " diff --git a/code/game/machinery/turnstile.dm b/code/game/machinery/turnstile.dm index 9bc5193bbb..f30ef22dd7 100644 --- a/code/game/machinery/turnstile.dm +++ b/code/game/machinery/turnstile.dm @@ -18,9 +18,6 @@ /obj/machinery/turnstile/CanAtmosPass(turf/T) return TRUE -/obj/machinery/turnstile/bullet_act(obj/item/projectile/P, def_zone) - return BULLET_ACT_FORCE_PIERCE //Pass through! - /obj/machinery/turnstile/proc/allowed_access(var/mob/B) if(B.pulledby && ismob(B.pulledby)) return allowed(B.pulledby) | allowed(B) @@ -28,6 +25,8 @@ return allowed(B) /obj/machinery/turnstile/CanPass(atom/movable/AM, turf/T) + if(istype(AM, /obj/item/projectile)) + return TRUE if(ismob(AM)) var/mob/B = AM if(isliving(AM)) @@ -60,6 +59,8 @@ return FALSE /obj/machinery/turnstile/CheckExit(atom/movable/AM as mob|obj, target) + if(istype(AM, /obj/item/projectile)) + return TRUE if(isliving(AM)) var/mob/living/M = AM var/outdir = dir @@ -81,4 +82,4 @@ M.last_bumped = world.time return canexit else - return TRUE \ No newline at end of file + return TRUE diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index 26220d4d89..3441ac7eaa 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -297,10 +297,7 @@ GLOBAL_LIST_INIT(dye_registry, list( else return ..() -/obj/machinery/washing_machine/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/washing_machine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(busy) to_chat(user, "[src] is busy.") return diff --git a/code/game/machinery/wishgranter.dm b/code/game/machinery/wishgranter.dm index ee28f118fa..12fdc2193b 100644 --- a/code/game/machinery/wishgranter.dm +++ b/code/game/machinery/wishgranter.dm @@ -10,7 +10,7 @@ var/charges = 1 var/insisting = 0 -/obj/machinery/wish_granter/attack_hand(mob/living/carbon/user) +/obj/machinery/wish_granter/on_attack_hand(mob/living/carbon/user) if(charges <= 0) to_chat(user, "The Wish Granter lies silent.") return @@ -31,7 +31,7 @@ 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! + user.action_cooldown_mod *= 0.5 to_chat(user, "Things around you feel slower!") charges-- insisting = FALSE @@ -101,14 +101,14 @@ 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! + user.action_cooldown_mod *= 0.8 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) + killwish.loot = list(/obj/item/dualsaber/hypereutactic) charges-- insisting = FALSE if(!charges) diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 717884e9a4..89b641ccc6 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -21,7 +21,7 @@ var/cell_charge = get_charge() var/datum/gas_mixture/int_tank_air = internal_tank.return_air() var/tank_pressure = internal_tank ? round(int_tank_air.return_pressure(),0.01) : "None" - var/tank_temperature = internal_tank ? int_tank_air.temperature : "Unknown" + var/tank_temperature = internal_tank ? int_tank_air.return_temperature() : "Unknown" var/cabin_pressure = round(return_pressure(),0.01) var/output = {"[report_internal_damage()] [integrity<30?"DAMAGE LEVEL CRITICAL
    ":null] @@ -155,4 +155,4 @@ var/color="" for (var/i=0;i<6;i++) color = color+pick(colors) - return color \ No newline at end of file + return color diff --git a/code/game/mecha/combat/neovgre.dm b/code/game/mecha/combat/neovgre.dm index fdcc4df151..1bd68546c8 100644 --- a/code/game/mecha/combat/neovgre.dm +++ b/code/game/mecha/combat/neovgre.dm @@ -15,6 +15,8 @@ internals_req_access = list() add_req_access = 0 wreckage = /obj/structure/mecha_wreckage/durand/neovgre + stepsound = 'sound/mecha/neostep2.ogg' + turnsound = 'sound/mecha/powerloader_step.ogg' /obj/mecha/combat/neovgre/GrantActions(mob/living/user, human_occupant = 0) //No Eject action for you sonny jim, your life for Ratvar! internals_action.Grant(user, src) @@ -32,7 +34,7 @@ /obj/mecha/combat/neovgre/MouseDrop_T(mob/M, mob/user) if(!is_servant_of_ratvar(user)) - to_chat(user, "BEGONE HERETIC!") + to_chat(user, "BEGONE HEATHEN!") return else ..() @@ -91,7 +93,7 @@ /obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre equip_cooldown = 8 //Rapid fire heavy laser cannon, simple yet elegant energy_drain = 30 - name = "Aribter Laser Cannon" + name = "Arbiter 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' diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 86cdd87505..ef1565502e 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -11,10 +11,15 @@ var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff) var/energy_drain = 0 var/obj/mecha/chassis = null - var/range = MELEE //bitFflags + /// Bitflag. Determines the range of the equipment. + var/range = MELEE + /// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this. + var/mech_flags = NONE var/salvageable = 1 + //var/detachable = TRUE // Set to FALSE for built-in equipment that cannot be removed var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist. + //var/destroy_sound = 'sound/mecha/critdestr.ogg' /obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() if(chassis) @@ -35,9 +40,14 @@ if(chassis.selected == src) chassis.selected = null src.update_chassis_page() - chassis.occupant_message("[src] is destroyed!") + //log_message("[src] is destroyed.", LOG_MECHA) chassis.log_append_to_last("[src] is destroyed.",1) - SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50)) + if(chassis.occupant) + chassis.occupant_message("[src] is destroyed!") + SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50)) + //chassis.occupant.playsound_local(chassis, destroy_sound, 50) + //if(!detachable) //If we're a built-in nondetachable equipment, let's lock up the slot that we were in. + // chassis.max_equip-- chassis = null return ..() @@ -59,7 +69,7 @@ return txt /obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not? - return range&RANGED + return range&RANGED //rename to MECHA_RANGE and MECHA_MELEE /obj/item/mecha_parts/mecha_equipment/proc/is_melee() return range&MELEE @@ -72,10 +82,10 @@ return 0 if(!equip_ready) return 0 - if(crit_fail) - return 0 if(energy_drain && !chassis.has_charge(energy_drain)) return 0 + if(crit_fail) + return 0 if(chassis.equipment_disabled) to_chat(chassis.occupant, "Error -- Equipment control unit is unresponsive.
    ") return 0 @@ -117,8 +127,6 @@ chassis = M forceMove(M) M.mecha_log_message("[src] initialized.") - if(!M.selected && selectable) - M.selected = src src.update_chassis_page() return @@ -150,7 +158,7 @@ chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]") return -/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color) +/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color) //on tg this just overrides log_message log_message(message, LOG_GAME, color) //pass to default admin logging too if(chassis) chassis.mecha_log_message(message, color) //and pass to our chassis diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 4a4d58ea73..1435f78718 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -1,6 +1,7 @@ // Sleeper, Medical Beam, and Syringe gun /obj/item/mecha_parts/mecha_equipment/medical + mech_flags = EXOSUIT_MODULE_MEDICAL /obj/item/mecha_parts/mecha_equipment/medical/Initialize() . = ..() diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index d4a29f639d..7c7c6be2bc 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -17,6 +17,7 @@ toolspeed = 0.9 var/drill_delay = 7 var/drill_level = DRILL_BASIC + mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT /obj/item/mecha_parts/mecha_equipment/drill/Initialize() . = ..() @@ -153,6 +154,7 @@ selectable = 0 equip_cooldown = 15 var/scanning_time = 0 + mech_flags = EXOSUIT_MODULE_WORKING /obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize() . = ..() diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index 4ddb5281ea..8039aabd1f 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -388,7 +388,7 @@ /obj/item/mecha_parts/mecha_equipment/generator/get_equip_info() var/output = ..() if(output) - return "[output] \[[fuel]: [round(fuel.amount*fuel.mats_per_stack,0.1)] cm3\] - [equip_ready?"A":"Dea"]ctivate" + return "[output] \[[fuel]: [round(fuel.amount*MINERAL_MATERIAL_AMOUNT,0.1)] cm3\] - [equip_ready?"A":"Dea"]ctivate" /obj/item/mecha_parts/mecha_equipment/generator/action(target) if(chassis) @@ -398,9 +398,9 @@ /obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P) if(P.type == fuel.type && P.amount > 0) - var/to_load = max(max_fuel - fuel.amount*fuel.mats_per_stack,0) + var/to_load = max(max_fuel - fuel.amount*MINERAL_MATERIAL_AMOUNT,0) if(to_load) - var/units = min(max(round(to_load / P.mats_per_stack),1),P.amount) + var/units = min(max(round(to_load / MINERAL_MATERIAL_AMOUNT),1),P.amount) fuel.amount += units P.use(units) occupant_message("[units] unit\s of [fuel] successfully loaded.") @@ -422,13 +422,13 @@ return var/datum/gas_mixture/GM = new if(prob(10)) - GM.gases[/datum/gas/plasma] += 100 - GM.temperature = 1500+T0C //should be enough to start a fire + GM.adjust_moles(/datum/gas/plasma,100) + GM.set_temperature(1500+T0C) //should be enough to start a fire T.visible_message("[src] suddenly disgorges a cloud of heated plasma.") qdel(src) else - GM.gases[/datum/gas/plasma] += 5 - GM.temperature = istype(T) ? T.air.return_temperature() : T20C + GM.adjust_moles(/datum/gas/plasma,5) + GM.set_temperature(istype(T) ? T.air.return_temperature() : T20C) T.visible_message("[src] suddenly disgorges a cloud of plasma.") T.assume_air(GM) return @@ -454,7 +454,7 @@ if(cur_charge < chassis.cell.maxcharge) use_fuel = fuel_per_cycle_active chassis.give_power(power_per_cycle) - fuel.amount -= min(use_fuel/fuel.mats_per_stack,fuel.amount) + fuel.amount -= min(use_fuel/MINERAL_MATERIAL_AMOUNT,fuel.amount) update_equip_info() return 1 diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm index 759fcd996d..1c4586205a 100644 --- a/code/game/mecha/equipment/tools/work_tools.dm +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -8,11 +8,12 @@ icon_state = "mecha_clamp" equip_cooldown = 15 energy_drain = 10 + tool_behaviour = TOOL_RETRACTOR + toolspeed = 0.8 var/dam_force = 20 var/obj/mecha/working/ripley/cargo_holder harmful = TRUE - tool_behaviour = TOOL_RETRACTOR - toolspeed = 0.8 + mech_flags = EXOSUIT_MODULE_RIPLEY /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) if(..()) @@ -180,6 +181,7 @@ equip_cooldown = 5 energy_drain = 0 range = MELEE|RANGED + mech_flags = EXOSUIT_MODULE_WORKING /obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize() . = ..() diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 65aa001fe1..f2bced4aa8 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -9,6 +9,7 @@ var/projectile_delay = 0 var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired. var/kickback = TRUE //Will using this weapon in no grav push mecha back. + mech_flags = EXOSUIT_MODULE_COMBAT /obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M) if(..()) diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index bcf1b948e2..e9f682e929 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -81,10 +81,10 @@ var/obj/machinery/mech_bay_recharge_port/recharge_port light_color = LIGHT_COLOR_PINK -/obj/machinery/computer/mech_bay_power_console/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "mech_bay_power_console", "Mech Bay Power Control Console", 400, 200, master_ui, state) + ui = new(user, src, "MechBayPowerConsole", name) ui.open() /obj/machinery/computer/mech_bay_power_console/ui_act(action, params) @@ -104,7 +104,6 @@ data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null, "name" = recharge_port.recharging_mech.name,) if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell)) data["recharge_port"]["mech"]["cell"] = list( - "critfail" = recharge_port.recharging_mech.cell.crit_fail, "charge" = recharge_port.recharging_mech.cell.charge, "maxcharge" = recharge_port.recharging_mech.cell.maxcharge ) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 93228c7fee..002753c5d4 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -9,48 +9,65 @@ active_power_usage = 5000 req_access = list(ACCESS_ROBOTICS) circuit = /obj/item/circuitboard/machine/mechfab - var/time_coeff = 1 - var/component_coeff = 1 - var/datum/techweb/specialized/autounlocking/exofab/stored_research - var/sync = 0 - var/part_set - var/datum/design/being_built + // processing_flags = START_PROCESSING_MANUALLY + + // subsystem_type = /datum/controller/subsystem/processing/fastprocess + + /// Current items in the build queue. var/list/queue = list() - var/processing_queue = 0 - var/screen = "main" - var/temp - var/offstation_security_levels = TRUE + /// Whether or not the machine is building the entire queue automagically. + var/process_queue = FALSE + + /// The current design datum that the machine is building. + var/datum/design/being_built + /// World time when the build will finish. + var/build_finish = 0 + /// World time when the build started. + var/build_start = 0 + /// Reference to all materials used in the creation of the item being_built. + var/list/build_materials + /// Part currently stored in the Exofab. + var/obj/item/stored_part + + /// Coefficient for the speed of item building. Based on the installed parts. + var/time_coeff = 1 + /// Coefficient for the efficiency of material usage in item building. Based on the installed parts. + var/component_coeff = 1 + + /// Copy of the currently synced techweb. + var/datum/techweb/specialized/autounlocking/exofab/stored_research + + /// Whether the Exofab links to the ore silo on init. Special derelict or maintanance variants should set this to FALSE. + var/link_on_init = TRUE + + /// Reference to a remote material inventory, such as an ore silo. + var/datum/component/remote_materials/rmat + + /// A list of categories that valid MECHFAB design datums will broadly categorise themselves under. var/list/part_sets = list( "Cyborg", "Ripley", "Firefighter", "Odysseus", "Gygax", + "Medical-Spec Gygax", "Durand", "H.O.N.K", "Phazon", "Exosuit Equipment", "Exosuit Ammunition", "Cyborg Upgrade Modules", + "Cybernetics", + "Implants", + "Control Interfaces", "Misc" ) -/obj/machinery/mecha_part_fabricator/Initialize() - var/static/list/allowed_types = list( - /datum/material/iron, - /datum/material/glass, - /datum/material/silver, - /datum/material/gold, - /datum/material/diamond, - /datum/material/plasma, - /datum/material/uranium, - /datum/material/bananium, - /datum/material/titanium, - /datum/material/bluespace - ) - var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert)) - materials.precise_insertion = TRUE +/obj/machinery/mecha_part_fabricator/Initialize(mapload) stored_research = new + rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init) + + RefreshParts() //Recalculating local material sizes if the fab isn't linked return ..() /obj/machinery/mecha_part_fabricator/RefreshParts() @@ -59,8 +76,7 @@ //maximum stocking amount (default 300000, 600000 at T4) for(var/obj/item/stock_parts/matter_bin/M in component_parts) T += M.rating - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.max_amount = (200000 + (T*50000)) + rmat.set_local_size((200000 + (T*50000))) //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) T = 1.15 @@ -73,89 +89,157 @@ for(var/obj/item/stock_parts/manipulator/Ml in component_parts) T += Ml.rating time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) - var/obj/item/circuitboard/machine/mechfab/C = circuit - offstation_security_levels = C.offstation_security_levels + + // Adjust the build time of any item currently being built. + if(being_built) + var/last_const_time = build_finish - build_start + var/new_const_time = get_construction_time_w_coeff(initial(being_built.construction_time)) + var/const_time_left = build_finish - world.time + var/new_build_time = (new_const_time / last_const_time) * const_time_left + build_finish = world.time + new_build_time + + update_static_data(usr) /obj/machinery/mecha_part_fabricator/examine(mob/user) . = ..() - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) if(in_range(user, src) || isobserver(user)) - . += "The status display reads: Storing up to [materials.max_amount] material units.
    Material consumption at [component_coeff*100]%.
    Build time reduced by [100-time_coeff*100]%.
    " + . += "The status display reads: Storing up to [rmat.local_size] material units.
    Material consumption at [component_coeff*100]%.
    Build time reduced by [100-time_coeff*100]%.
    " -/obj/machinery/mecha_part_fabricator/emag_act() - . = ..() - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - req_access = list() - INVOKE_ASYNC(src, .proc/error_action_sucessful) - return TRUE - -/obj/machinery/mecha_part_fabricator/proc/error_action_sucessful() - say("DB error \[Code 0x00F1\]") - sleep(10) - say("Attempting auto-repair...") - sleep(15) - say("User DB corrupted \[Code 0x00FA\]. Truncating data structure...") - sleep(30) - say("User DB truncated. Please contact your Nanotrasen system operator for future assistance.") - - -/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name) - var/output = "" - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(!(set_name in D.category)) - continue - output += "
    [output_part_info(D)]
    \[" - if(check_clearance(D) && check_resources(D)) - output += "Build | " - output += "Add to queue\]\[?\]
    " - return output - -/obj/machinery/mecha_part_fabricator/proc/check_clearance(datum/design/D) - if(!(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) && !ISINRANGE(GLOB.security_level, D.min_security_level, D.max_security_level)) - return FALSE - return TRUE - -/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D) - var/clearance = !(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) - var/sec_text = "" - if(clearance && (D.min_security_level > SEC_LEVEL_GREEN || D.max_security_level < SEC_LEVEL_DELTA)) - sec_text = " (Allowed security levels: " - for(var/n in D.min_security_level to D.max_security_level) - sec_text += NUM2SECLEVEL(n) - if(n + 1 <= D.max_security_level) - sec_text += ", " - sec_text += ") " - var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [sec_text][get_construction_time_w_coeff(D)/10]sec" - return output - -/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D) - var/i = 0 - var/output +/** + * Generates an info list for a given part. + * + * Returns a list of part information. + * * D - Design datum to get information on. + * * categories - Boolean, whether or not to parse snowflake categories into the part information list. + */ +/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, categories = FALSE) + var/cost = list() for(var/c in D.materials) var/datum/material/M = c - output += "[i?" | ":null][get_resource_cost_w_coeff(D, M)] [M.name]" - i++ - return output + cost[M.name] = get_resource_cost_w_coeff(D, M) + var/obj/built_item = D.build_path + + var/list/category_override = null + var/list/sub_category = null + + if(categories) + // Handle some special cases to build up sub-categories for the fab interface. + // Start with checking if this design builds a cyborg module. + if(built_item in typesof(/obj/item/borg/upgrade)) + var/obj/item/borg/upgrade/U = built_item + var/module_types = initial(U.module_flags) + sub_category = list() + if(module_types) + if(module_types & BORG_MODULE_SECURITY) + sub_category += "Security" + if(module_types & BORG_MODULE_MINER) + sub_category += "Mining" + if(module_types & BORG_MODULE_JANITOR) + sub_category += "Janitor" + if(module_types & BORG_MODULE_MEDICAL) + sub_category += "Medical" + if(module_types & BORG_MODULE_ENGINEERING) + sub_category += "Engineering" + else + sub_category += "All Cyborgs" + // Else check if this design builds a piece of exosuit equipment. + else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment)) + var/obj/item/mecha_parts/mecha_equipment/E = built_item + var/mech_types = initial(E.mech_flags) + sub_category = "Equipment" + if(mech_types) + category_override = list() + if(mech_types & EXOSUIT_MODULE_RIPLEY) + category_override += "Ripley" + if(mech_types & EXOSUIT_MODULE_FIREFIGHTER) + category_override += "Firefighter" + if(mech_types & EXOSUIT_MODULE_ODYSSEUS) + category_override += "Odysseus" + // if(mech_types & EXOSUIT_MODULE_CLARKE) + // category_override += "Clarke" + if(mech_types & EXOSUIT_MODULE_GYGAX_MED) + category_override += "Medical-Spec Gygax" + if(mech_types & EXOSUIT_MODULE_GYGAX) + category_override += "Gygax" + if(mech_types & EXOSUIT_MODULE_DURAND) + category_override += "Durand" + if(mech_types & EXOSUIT_MODULE_HONK) + category_override += "H.O.N.K" + if(mech_types & EXOSUIT_MODULE_PHAZON) + category_override += "Phazon" + + + var/list/part = list( + "name" = D.name, + "desc" = initial(built_item.desc), + "printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10, + "cost" = cost, + "id" = D.id, + "subCategory" = sub_category, + "categoryOverride" = category_override, + "searchMeta" = "UNKNOWN"//D.search_metadata + ) + + return part + +/** + * Generates a list of resources / materials available to this Exosuit Fab + * + * Returns null if there is no material container available. + * List format is list(material_name = list(amount = ..., ref = ..., etc.)) + */ /obj/machinery/mecha_part_fabricator/proc/output_available_resources() - var/output - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - for(var/mat_id in materials.materials) - var/datum/material/M = mat_id - var/amount = materials.materials[mat_id] - output += "[M.name]: [amount] cm³" - if(amount >= MINERAL_MATERIAL_AMOUNT) - output += "- Remove \[1\]" - if(amount >= (MINERAL_MATERIAL_AMOUNT * 10)) - output += " | \[10\]" - output += " | \[All\]" - output += "
    " - return output + var/datum/component/material_container/materials = rmat.mat_container + var/list/material_data = list() + + if(materials) + for(var/mat_id in materials.materials) + var/datum/material/M = mat_id + var/list/material_info = list() + var/amount = materials.materials[mat_id] + + material_info = list( + "name" = M.name, + "ref" = REF(M), + "amount" = amount, + "sheets" = round(amount / MINERAL_MATERIAL_AMOUNT), + "removable" = amount >= MINERAL_MATERIAL_AMOUNT + ) + + material_data += list(material_info) + + return material_data + + return null + +/** + * Intended to be called when an item starts printing. + * + * Adds the overlay to show the fab working and sets active power usage settings. + */ +/obj/machinery/mecha_part_fabricator/proc/on_start_printing() + add_overlay("fab-active") + use_power = ACTIVE_POWER_USE + +/** + * Intended to be called when the exofab has stopped working and is no longer printing items. + * + * Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing. + */ +/obj/machinery/mecha_part_fabricator/proc/on_finish_printing() + cut_overlay("fab-active") + use_power = IDLE_POWER_USE + desc = initial(desc) + process_queue = FALSE + +/** + * Calculates resource/material costs for printing an item based on the machine's resource coefficient. + * + * Returns a list of k,v resources with their amounts. + * * D - Design datum to calculate the modified resource cost of. + */ /obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D) var/list/resources = list() for(var/R in D.materials) @@ -163,294 +247,419 @@ resources[M] = get_resource_cost_w_coeff(D, M) return resources +/** + * Checks if the Exofab has enough resources to print a given item. + * + * Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources. + * Returns TRUE if there are sufficient resources to print the item. + * * D - Design datum to calculate the modified resource cost of. + */ /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) - if(D.reagents_list.len) // No reagents storage - no reagent designs. + if(length(D.reagents_list)) // No reagents storage - no reagent designs. return FALSE - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/datum/component/material_container/materials = rmat.mat_container if(materials.has_materials(get_resources_w_coeff(D))) return TRUE return FALSE -/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D) +/** + * Attempts to build the next item in the build queue. + * + * Returns FALSE if either there are no more parts to build or the next part is not buildable. + * Returns TRUE if the next part has started building. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE) + if(!length(queue)) + return FALSE + + var/datum/design/D = queue[1] + if(build_part(D, verbose)) + remove_from_queue(1) + return TRUE + + return FALSE + +/** + * Starts the build process for a given design datum. + * + * Returns FALSE if the procedure fails. Returns TRUE when being_built is set. + * Uses materials. + * * D - Design datum to attempt to print. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE) + if(!D) + return FALSE + + var/datum/component/material_container/materials = rmat.mat_container + if (!materials) + if(verbose) + say("No access to material storage, please contact the quartermaster.") + return FALSE + if (rmat.on_hold()) + if(verbose) + say("Mineral access is on hold, please contact the quartermaster.") + return FALSE + if(!check_resources(D)) + if(verbose) + say("Not enough resources. Processing stopped.") + return FALSE + + build_materials = get_resources_w_coeff(D) + + materials.use_materials(build_materials) being_built = D - desc = "It's building \a [initial(D.name)]." - var/list/res_coef = get_resources_w_coeff(D) + build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time)) + build_start = world.time + desc = "It's building \a [D.name]." - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.use_materials(res_coef) - add_overlay("fab-active") - use_power = ACTIVE_POWER_USE - updateUsrDialog() - sleep(get_construction_time_w_coeff(D)) - use_power = IDLE_POWER_USE - cut_overlay("fab-active") - desc = initial(desc) + rmat.silo_log(src, "built", -1, "[D.name]", build_materials) - var/location = get_step(src,(dir)) - var/obj/item/I = new D.build_path(location) - I.set_custom_materials(res_coef) - say("\The [I] is complete.") - being_built = null - - updateUsrDialog() return TRUE -/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page() - send_byjax(usr,"mecha_fabricator.browser","queue",list_queue()) - return +/obj/machinery/mecha_part_fabricator/process() + // If there's a stored part to dispense due to an obstruction, try to dispense it. + if(stored_part) + var/turf/exit = get_step(src,(dir)) + if(exit.density) + return TRUE -/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name) - if(set_name in part_sets) - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(set_name in D.category) - add_to_queue(D) + say("Obstruction cleared. \The [stored_part] is complete.") + stored_part.forceMove(exit) + stored_part = null -/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D) + // If there's nothing being built, try to build something + if(!being_built) + // If we're not processing the queue anymore or there's nothing to build, end processing. + if(!process_queue || !build_next_in_queue()) + on_finish_printing() + STOP_PROCESSING(SSfastprocess, src) + //end_processing() + return TRUE + on_start_printing() + + // If there's an item being built, check if it is complete. + if(being_built && (build_finish < world.time)) + // Then attempt to dispense it and if appropriate build the next item. + dispense_built_part(being_built) + if(process_queue) + build_next_in_queue(FALSE) + return TRUE + +/** + * Dispenses a part to the tile infront of the Exosuit Fab. + * + * Returns FALSE is the machine cannot dispense the part on the appropriate turf. + * Return TRUE if the part was successfully dispensed. + * * D - Design datum to attempt to dispense. + */ +/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D) + var/obj/item/I = new D.build_path(src) + // I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this. + I.set_custom_materials(build_materials) + + being_built = null + + var/turf/exit = get_step(src,(dir)) + if(exit.density) + say("Error! Part outlet is obstructed.") + desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed." + stored_part = I + return FALSE + + say("\The [I] is complete.") + I.forceMove(exit) + return TRUE + +/** + * Adds a list of datum designs to the build queue. + * + * Will only add designs that are in this machine's stored techweb. + * Does final checks for datum IDs and makes sure this machine can build the designs. + * * part_list - List of datum design ids for designs to add to the queue. + */ +/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list) + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if((D.build_type & MECHFAB) && (D.id in part_list)) + add_to_queue(D) + +/** + * Adds a datum design to the build queue. + * + * Returns TRUE if successful and FALSE if the design was not added to the queue. + * * D - Datum design to add to the queue. + */ +/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D) if(!istype(queue)) queue = list() if(D) queue[++queue.len] = D - return queue.len + return TRUE + return FALSE +/** + * Removes datum design from the build queue based on index. + * + * Returns TRUE if successful and FALSE if a design was not removed from the queue. + * * index - Index in the build queue of the element to remove. + */ /obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) - if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>queue.len)) + if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue))) return FALSE queue.Cut(index,++index) return TRUE -/obj/machinery/mecha_part_fabricator/proc/process_queue() - var/datum/design/D = queue[1] - if(!D) - remove_from_queue(1) - if(queue.len) - return process_queue() - else - return - temp = null - while(D) - if(stat&(NOPOWER|BROKEN)) - return FALSE - if(!check_clearance(D)) - say("Security level not met. Queue processing stopped.") - temp = {"Security level not met to build next part.
    - Try again | Return"} - return FALSE - if(!check_resources(D)) - say("Not enough resources. Queue processing stopped.") - temp = {"Not enough resources to build next part.
    -
    Try again | Return"} - return FALSE - remove_from_queue(1) - build_part(D) - D = listgetindex(queue, 1) - say("Queue processing finished successfully.") - +/** + * Generates a list of parts formatted for tgui based on the current build queue. + * + * Returns a formatted list of lists containing formatted part information for every part in the build queue. + */ /obj/machinery/mecha_part_fabricator/proc/list_queue() - var/output = "Queue contains:" - if(!istype(queue) || !queue.len) - output += "
    Nothing" - else - output += "
      " - var/i = 0 - for(var/datum/design/D in queue) - i++ - var/obj/part = D.build_path - output += "" - output += initial(part.name) + " - " - output += "[i>1?"":null] " - output += "[i↓":null] " - output += "Remove" + if(!istype(queue) || !length(queue)) + return null - output += "
    " - output += "\[Process queue | Clear queue\]" - return output + var/list/queued_parts = list() + for(var/datum/design/D in queue) + var/list/part = output_part_info(D) + queued_parts += list(part) + return queued_parts +/** + * Syncs machine with R&D servers. + * + * Requires an R&D Console visible within 7 tiles. Copies techweb research. Updates tgui's state data. + */ /obj/machinery/mecha_part_fabricator/proc/sync() - temp = "Updating local R&D database..." - updateUsrDialog() - sleep(30) //only sleep if called by user - - for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src)) + for(var/obj/machinery/computer/rdconsole/RDC in orange(7,src)) RDC.stored_research.copy_research_to(stored_research) - temp = "Processed equipment designs.
    " - //check if the tech coefficients have changed - temp += "Return" - - updateUsrDialog() + update_static_data(usr) say("Successfully synchronized with R&D server.") return - temp = "Unable to connect to local R&D Database.
    Please check your connections and try again.
    Return" - updateUsrDialog() + say("Unable to connect to local R&D server.") return +/** + * Calculates the coefficient-modified resource cost of a single material component of a design's recipe. + * + * Returns coefficient-modified resource cost for the given material component. + * * D - Design datum to pull the resource cost from. + * * resource - Material datum reference to the resource to calculate the cost of. + * * roundto - Rounding value for round() proc + */ /obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1) return round(D.materials[resource]*component_coeff, roundto) -/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran - return round(initial(D.construction_time)*time_coeff, roundto) +/** + * Calculates the coefficient-modified build time of a design. + * + * Returns coefficient-modified build time of a given design. + * * D - Design datum to calculate the modified build time of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran + return round(construction_time*time_coeff, roundto) -/obj/machinery/mecha_part_fabricator/ui_interact(mob/user as mob) - . = ..() - var/dat, left_part - user.set_machine(src) - var/turf/exit = get_step(src,(dir)) - if(exit.density) - say("Error! Part outlet is obstructed.") - return - if(temp) - left_part = temp - else if(being_built) - var/obj/I = being_built.build_path - left_part = {"Building [initial(I.name)].
    - Please wait until completion...
    "} +/obj/machinery/mecha_part_fabricator/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/sheetmaterials) + ) + +/obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ExosuitFabricator") + ui.open() + +/obj/machinery/mecha_part_fabricator/ui_static_data(mob/user) + var/list/data = list() + + var/list/final_sets = list() + var/list/buildable_parts = list() + + for(var/part_set in part_sets) + final_sets += part_set + + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if(D.build_type & MECHFAB) + // This is for us. + var/list/part = output_part_info(D, TRUE) + + if(part["category_override"]) + for(var/cat in part["category_override"]) + buildable_parts[cat] += list(part) + if(!(cat in part_sets)) + final_sets += cat + continue + + for(var/cat in part_sets) + // Find all matching categories. + if(!(cat in D.category)) + continue + + buildable_parts[cat] += list(part) + + data["partSets"] = final_sets + data["buildableParts"] = buildable_parts + + return data + +/obj/machinery/mecha_part_fabricator/ui_data(mob/user) + var/list/data = list() + + data["materials"] = output_available_resources() + + if(being_built) + var/list/part = list( + "name" = being_built.name, + "duration" = build_finish - world.time, + "printTime" = get_construction_time_w_coeff(initial(being_built.construction_time)) + ) + data["buildingPart"] = part else - switch(screen) - if("main") - left_part = output_available_resources()+"
    " - left_part += "Sync with R&D servers
    " - for(var/part_set in part_sets) - left_part += "[part_set] - \[Add all parts to queue\]
    " - if("parts") - left_part += output_parts_list(part_set) - left_part += "
    Return" - dat = {" - - - [name] data - - - - - - - - - -
    - [left_part] - - [list_queue()] -
    - - "} - user << browse(dat, "window=mecha_fabricator;size=1000x430") - onclose(user, "mecha_fabricator") - return + data["buildingPart"] = null -/obj/machinery/mecha_part_fabricator/Topic(href, href_list) + data["queue"] = list_queue() + + if(stored_part) + data["storedPart"] = stored_part.name + else + data["storedPart"] = null + + data["isProcessingQueue"] = process_queue + + return data + +/obj/machinery/mecha_part_fabricator/ui_act(action, var/list/params) if(..()) - return - if(href_list["part_set"]) - var/tpart_set = href_list["part_set"] - if(tpart_set) - if(tpart_set=="clear") - part_set = null - else - part_set = tpart_set - screen = "parts" - if(href_list["part"]) - var/T = href_list["part"] - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(D.id == T) - if(!processing_queue) - build_part(D) - else - add_to_queue(D) - break - if(href_list["add_to_queue"]) - var/T = href_list["add_to_queue"] - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(D.id == T) + return TRUE + + . = TRUE + + add_fingerprint(usr) + usr.set_machine(src) + + switch(action) + if("sync_rnd") + // Sync with R&D Servers + sync() + return + if("add_queue_set") + // Add all parts of a set to queue + var/part_list = params["part_list"] + add_part_set_to_queue(part_list) + return + if("add_queue_part") + // Add a specific part to queue + var/T = params["id"] + for(var/v in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(v) + if((D.build_type & MECHFAB) && (D.id == T)) add_to_queue(D) break - return update_queue_on_page() - if(href_list["remove_from_queue"]) - remove_from_queue(text2num(href_list["remove_from_queue"])) - return update_queue_on_page() - if(href_list["partset_to_queue"]) - add_part_set_to_queue(href_list["partset_to_queue"]) - return update_queue_on_page() - if(href_list["process_queue"]) - spawn(0) - if(processing_queue || being_built) - return FALSE - processing_queue = 1 - process_queue() - processing_queue = 0 - if(href_list["clear_temp"]) - temp = null - if(href_list["screen"]) - screen = href_list["screen"] - if(href_list["queue_move"] && href_list["index"]) - var/index = text2num(href_list["index"]) - var/new_index = index + text2num(href_list["queue_move"]) - if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) - if(ISINRANGE(new_index,1,queue.len)) - queue.Swap(index,new_index) - return update_queue_on_page() - if(href_list["clear_queue"]) - queue = list() - return update_queue_on_page() - if(href_list["sync"]) - sync() - if(href_list["part_desc"]) - var/T = href_list["part_desc"] - for(var/v in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(v) - if(D.build_type & MECHFAB) - if(D.id == T) - var/obj/part = D.build_path - temp = {"

    [initial(part.name)] description:

    - [initial(part.desc)]
    - Return - "} - break + return + if("del_queue_part") + // Delete a specific from from the queue + var/index = text2num(params["index"]) + remove_from_queue(index) + return + if("clear_queue") + // Delete everything from queue + queue.Cut() + return + if("build_queue") + // Build everything in queue + if(process_queue) + return + process_queue = TRUE - if(href_list["remove_mat"] && href_list["material"]) - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - var/datum/material/Mat = locate(href_list["material"]) - materials.retrieve_sheets(text2num(href_list["remove_mat"]), Mat) + if(!being_built) + START_PROCESSING(SSfastprocess, src) + //begin_processing() + return + if("stop_queue") + // Pause queue building. Also known as stop. + process_queue = FALSE + return + if("build_part") + // Build a single part + if(being_built || process_queue) + return - updateUsrDialog() - return + var/id = params["id"] + var/datum/design/D = SSresearch.techweb_design_by_id(id) -/obj/machinery/mecha_part_fabricator/on_deconstruction() - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - materials.retrieve_all() - ..() + if(!(D.build_type & MECHFAB) || !(D.id == id)) + return + + if(build_part(D)) + on_start_printing() + START_PROCESSING(SSfastprocess, src) + //begin_processing() teege has this as a helper proc. please port it! + + return + if("move_queue_part") + // Moves a part up or down in the queue. + var/index = text2num(params["index"]) + var/new_index = index + text2num(params["newindex"]) + if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) + if(ISINRANGE(new_index,1,length(queue))) + queue.Swap(index,new_index) + return + if("remove_mat") + // Remove a material from the fab + var/mat_ref = params["ref"] + var/amount = text2num(params["amount"]) + var/datum/material/mat = locate(mat_ref) + eject_sheets(mat, amount) + return + + return FALSE + +/** + * Eject material sheets. + * + * Returns the number of sheets successfully ejected. + * eject_sheet - Byond REF of the material to eject. + * eject_amt - Number of sheets to attempt to eject. + */ +/obj/machinery/mecha_part_fabricator/proc/eject_sheets(eject_sheet, eject_amt) + var/datum/component/material_container/mat_container = rmat.mat_container + if (!mat_container) + say("No access to material storage, please contact the quartermaster.") + return 0 + if (rmat.on_hold()) + say("Mineral access is on hold, please contact the quartermaster.") + return 0 + var/count = mat_container.retrieve_sheets(text2num(eject_amt), eject_sheet, drop_location()) + var/list/matlist = list() + matlist[eject_sheet] = text2num(eject_amt) + rmat.silo_log(src, "ejected", -count, "sheets", matlist) + return count /obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted) var/datum/material/M = id_inserted add_overlay("fab-load-[M.name]") addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10) - updateUsrDialog() -/obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params) - if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) +/obj/machinery/mecha_part_fabricator/screwdriver_act(mob/living/user, obj/item/I) + if(..()) return TRUE + if(being_built) + to_chat(user, "\The [src] is currently processing! Please wait until completion.") + return FALSE + return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", I) - if(default_deconstruction_crowbar(W)) +/obj/machinery/mecha_part_fabricator/crowbar_act(mob/living/user, obj/item/I) + if(..()) return TRUE - - return ..() + if(being_built) + to_chat(user, "\The [src] is currently processing! Please wait until completion.") + return FALSE + return default_deconstruction_crowbar(I) /obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user) if(panel_open) @@ -462,6 +671,9 @@ return TRUE +/obj/machinery/mecha_part_fabricator/maint + link_on_init = FALSE + /obj/machinery/mecha_part_fabricator/offstation - offstation_security_levels = FALSE + link_on_init = FALSE circuit = /obj/item/circuitboard/machine/mechfab/offstation diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 32be825489..f16a5f9292 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -24,6 +24,8 @@ infra_luminosity = 15 //byond implementation is bugged. force = 5 flags_1 = HEAR_1|BLOCK_FACE_ATOM_1 + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE var/can_move = 0 //time of next allowed movement var/mob/living/occupant = null var/step_in = 10 //make a step in step_in/10 sec. @@ -151,6 +153,9 @@ /obj/mecha/get_cell() return cell +/obj/mecha/rust_heretic_act() + take_damage(500, BRUTE) + /obj/mecha/Destroy() go_out() var/mob/living/silicon/ai/AI @@ -247,10 +252,10 @@ /obj/mecha/proc/add_cabin() cabin_air = new - cabin_air.temperature = T20C - cabin_air.volume = 200 - cabin_air.gases[/datum/gas/oxygen] = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) - cabin_air.gases[/datum/gas/nitrogen] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) + cabin_air.set_temperature(T20C) + cabin_air.set_volume(200) + cabin_air.set_moles(/datum/gas/oxygen,O2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) + cabin_air.set_moles(/datum/gas/nitrogen,N2STANDARD*cabin_air.return_volume()/(R_IDEAL_GAS_EQUATION*cabin_air.return_temperature())) return cabin_air /obj/mecha/proc/add_radio() @@ -302,9 +307,9 @@ if(int_tank_air.return_pressure() > internal_tank.maximum_pressure && !(internal_damage & MECHA_INT_TANK_BREACH)) setInternalDamage(MECHA_INT_TANK_BREACH) if(int_tank_air && int_tank_air.return_volume() > 0) //heat the air_contents - int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) + int_tank_air.set_temperature(min(6000+T0C, int_tank_air.return_temperature()+rand(10,15))) if(cabin_air && cabin_air.return_volume()>0) - cabin_air.temperature = min(6000+T0C, cabin_air.return_temperature()+rand(10,15)) + cabin_air.set_temperature(min(6000+T0C, cabin_air.return_temperature()+rand(10,15))) if(cabin_air.return_temperature() > max_temperature/2) take_damage(4/round(max_temperature/cabin_air.return_temperature(),0.1), BURN, 0, 0) @@ -329,8 +334,8 @@ if(internal_temp_regulation) if(cabin_air && cabin_air.return_volume() > 0) - var/delta = cabin_air.temperature - T20C - cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) + var/delta = cabin_air.return_temperature() - T20C + cabin_air.set_temperature(cabin_air.return_temperature() - max(-10, min(10, round(delta/4,0.1)))) if(internal_tank) var/datum/gas_mixture/tank_air = internal_tank.return_air() diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index 5160282180..34cb57f661 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -642,6 +642,304 @@ user.visible_message("[user] unfastens Gygax Armor Plates.", "You unfasten Gygax Armor Plates.") return TRUE +//Begin Medigax +/datum/component/construction/unordered/mecha_chassis/medigax + result = /datum/component/construction/mecha/medigax + steps = list( + /obj/item/mecha_parts/part/medigax_torso, + /obj/item/mecha_parts/part/medigax_left_arm, + /obj/item/mecha_parts/part/medigax_right_arm, + /obj/item/mecha_parts/part/medigax_left_leg, + /obj/item/mecha_parts/part/medigax_right_leg, + /obj/item/mecha_parts/part/medigax_head + ) + +/datum/component/construction/mecha/medigax + result = /obj/mecha/medical/medigax + base_icon = "medigax" + steps = list( + //1 + list( + "key" = TOOL_WRENCH, + "desc" = "The hydraulic systems are disconnected." + ), + + //2 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_WRENCH, + "desc" = "The hydraulic systems are connected." + ), + + //3 + list( + "key" = /obj/item/stack/cable_coil, + "amount" = 5, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "The hydraulic systems are active." + ), + + //4 + list( + "key" = TOOL_WIRECUTTER, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "The wiring is added." + ), + + //5 + list( + "key" = /obj/item/circuitboard/mecha/gygax/main, + "action" = ITEM_DELETE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "The wiring is adjusted." + ), + + //6 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Central control module is installed." + ), + + //7 + list( + "key" = /obj/item/circuitboard/mecha/gygax/peripherals, + "action" = ITEM_DELETE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Central control module is secured." + ), + + //8 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Peripherals control module is installed." + ), + + //9 + list( + "key" = /obj/item/circuitboard/mecha/gygax/targeting, + "action" = ITEM_DELETE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Peripherals control module is secured." + ), + + //10 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Weapon control module is installed." + ), + + //11 + list( + "key" = /obj/item/stock_parts/scanning_module, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Weapon control module is secured." + ), + + //12 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Scanner module is installed." + ), + + //13 + list( + "key" = /obj/item/stock_parts/capacitor, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Scanner module is secured." + ), + + //14 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "Capacitor is installed." + ), + + //15 + list( + "key" = /obj/item/stock_parts/cell, + "action" = ITEM_MOVE_INSIDE, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "Capacitor is secured." + ), + + //16 + list( + "key" = TOOL_SCREWDRIVER, + "back_key" = TOOL_CROWBAR, + "desc" = "The power cell is installed." + ), + + //17 + list( + "key" = /obj/item/stack/sheet/metal, + "amount" = 5, + "back_key" = TOOL_SCREWDRIVER, + "desc" = "The power cell is secured." + ), + + //18 + list( + "key" = TOOL_WRENCH, + "back_key" = TOOL_CROWBAR, + "desc" = "Internal armor is installed." + ), + + //19 + list( + "key" = TOOL_WELDER, + "back_key" = TOOL_WRENCH, + "desc" = "Internal armor is wrenched." + ), + + //20 + list( + "key" = /obj/item/mecha_parts/part/medigax_armor, + "action" = ITEM_DELETE, + "back_key" = TOOL_WELDER, + "desc" = "Internal armor is welded." + ), + + //21 + list( + "key" = TOOL_WRENCH, + "back_key" = TOOL_CROWBAR, + "desc" = "External armor is installed." + ), + + //22 + list( + "key" = TOOL_WELDER, + "back_key" = TOOL_WRENCH, + "desc" = "External armor is wrenched." + ), + + ) + +/datum/component/construction/mecha/medigax/action(datum/source, atom/used_atom, mob/user) + return check_step(used_atom,user) + +/datum/component/construction/mecha/medigax/custom_action(obj/item/I, mob/living/user, diff) + if(!..()) + return FALSE + + switch(index) + if(1) + user.visible_message("[user] connects [parent] hydraulic systems", "You connect [parent] hydraulic systems.") + if(2) + if(diff==FORWARD) + user.visible_message("[user] activates [parent] hydraulic systems.", "You activate [parent] hydraulic systems.") + else + user.visible_message("[user] disconnects [parent] hydraulic systems", "You disconnect [parent] hydraulic systems.") + if(3) + if(diff==FORWARD) + user.visible_message("[user] adds the wiring to [parent].", "You add the wiring to [parent].") + else + user.visible_message("[user] deactivates [parent] hydraulic systems.", "You deactivate [parent] hydraulic systems.") + if(4) + if(diff==FORWARD) + user.visible_message("[user] adjusts the wiring of [parent].", "You adjust the wiring of [parent].") + else + user.visible_message("[user] removes the wiring from [parent].", "You remove the wiring from [parent].") + if(5) + if(diff==FORWARD) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + else + user.visible_message("[user] disconnects the wiring of [parent].", "You disconnect the wiring of [parent].") + if(6) + if(diff==FORWARD) + user.visible_message("[user] secures the mainboard.", "You secure the mainboard.") + else + user.visible_message("[user] removes the central control module from [parent].", "You remove the central computer mainboard from [parent].") + if(7) + if(diff==FORWARD) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + else + user.visible_message("[user] unfastens the mainboard.", "You unfasten the mainboard.") + if(8) + if(diff==FORWARD) + user.visible_message("[user] secures the peripherals control module.", "You secure the peripherals control module.") + else + user.visible_message("[user] removes the peripherals control module from [parent].", "You remove the peripherals control module from [parent].") + if(9) + if(diff==FORWARD) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + else + user.visible_message("[user] unfastens the peripherals control module.", "You unfasten the peripherals control module.") + if(10) + if(diff==FORWARD) + user.visible_message("[user] secures the weapon control module.", "You secure the weapon control module.") + else + user.visible_message("[user] removes the weapon control module from [parent].", "You remove the weapon control module from [parent].") + if(11) + if(diff==FORWARD) + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") + else + user.visible_message("[user] unfastens the weapon control module.", "You unfasten the weapon control module.") + if(12) + if(diff==FORWARD) + user.visible_message("[user] secures the scanner module.", "You secure the scanner module.") + else + user.visible_message("[user] removes the scanner module from [parent].", "You remove the scanner module from [parent].") + if(13) + if(diff==FORWARD) + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") + else + user.visible_message("[user] unfastens the scanner module.", "You unfasten the scanner module.") + if(14) + if(diff==FORWARD) + user.visible_message("[user] secures the capacitor.", "You secure the capacitor.") + else + user.visible_message("[user] removes the capacitor from [parent].", "You remove the capacitor from [parent].") + if(15) + if(diff==FORWARD) + user.visible_message("[user] installs [I] into [parent].", "You install [I] into [parent].") + else + user.visible_message("[user] unfastens the capacitor.", "You unfasten the capacitor.") + if(16) + if(diff==FORWARD) + user.visible_message("[user] secures the power cell.", "You secure the power cell.") + else + user.visible_message("[user] pries the power cell from [parent].", "You pry the power cell from [parent].") + if(17) + if(diff==FORWARD) + user.visible_message("[user] installs the internal armor layer to [parent].", "You install the internal armor layer to [parent].") + else + user.visible_message("[user] unfastens the power cell.", "You unfasten the power cell.") + if(18) + if(diff==FORWARD) + user.visible_message("[user] secures the internal armor layer.", "You secure the internal armor layer.") + else + user.visible_message("[user] pries internal armor layer from [parent].", "You pry internal armor layer from [parent].") + if(19) + if(diff==FORWARD) + user.visible_message("[user] welds the internal armor layer to [parent].", "You weld the internal armor layer to [parent].") + else + user.visible_message("[user] unfastens the internal armor layer.", "You unfasten the internal armor layer.") + if(20) + if(diff==FORWARD) + user.visible_message("[user] installs [I] to [parent].", "You install [I] to [parent].") + else + user.visible_message("[user] cuts the internal armor layer from [parent].", "You cut the internal armor layer from [parent].") + if(21) + if(diff==FORWARD) + user.visible_message("[user] secures Gygax Armor Plates.", "You secure Medical Gygax Armor Plates.") + else + user.visible_message("[user] pries Gygax Armor Plates from [parent].", "You pry Medical Gygax Armor Plates from [parent].") + if(22) + if(diff==FORWARD) + user.visible_message("[user] welds Gygax Armor Plates to [parent].", "You weld Medical Gygax Armor Plates to [parent].") + else + user.visible_message("[user] unfastens Gygax Armor Plates.", "You unfasten Medical Gygax Armor Plates.") + return TRUE +// End Medigax + /datum/component/construction/unordered/mecha_chassis/firefighter result = /datum/component/construction/mecha/firefighter steps = list( diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 91c97ff14a..50d18c6fda 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -5,62 +5,71 @@ icon_keyboard = "tech_key" req_access = list(ACCESS_ROBOTICS) circuit = /obj/item/circuitboard/computer/mecha_control - var/list/located = list() - var/screen = 0 - var/stored_data -/obj/machinery/computer/mecha/ui_interact(mob/user) - . = ..() - var/dat = "[src.name]" - if(screen == 0) - dat += "

    Tracking beacons data

    " - var/list/trackerlist = list() - for(var/obj/mecha/MC in GLOB.mechas_list) - trackerlist += MC.trackers - for(var/obj/item/mecha_parts/mecha_tracking/TR in trackerlist) - var/answer = TR.get_mecha_info() - if(answer) - dat += {"
    [answer]
    - Send message
    - Show exosuit log
    - [TR.recharging?"Recharging EMP Pulse...
    ":"(EMP Pulse)
    "]"} +/obj/machinery/computer/mecha/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ExosuitControlConsole", name) + ui.open() - if(screen==1) - dat += "

    Log contents

    " - dat += "Return
    " - dat += "[stored_data]" +/obj/machinery/computer/mecha/ui_data(mob/user) + var/list/data = list() - dat += "(Refresh)
    " - dat += "" + var/list/trackerlist = list() + for(var/obj/mecha/MC in GLOB.mechas_list) + trackerlist += MC.trackers - user << browse(dat, "window=computer;size=400x500") - onclose(user, "computer") + data["mechs"] = list() + for(var/obj/item/mecha_parts/mecha_tracking/MT in trackerlist) + if(!MT.chassis) + continue + var/obj/mecha/M = MT.chassis + var/list/mech_data = list( + name = M.name, + integrity = round((M.obj_integrity / M.max_integrity) * 100), + charge = M.cell ? round(M.cell.percent()) : null, + airtank = M.internal_tank ? M.return_pressure() : null, + pilot = M.occupant, + location = get_area_name(M, TRUE), + active_equipment = M.selected, + emp_recharging = MT.recharging, + tracker_ref = REF(MT) + ) + if(istype(M, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/RM = M + mech_data += list( + cargo_space = round((RM.cargo.len / RM.cargo_capacity) * 100) + ) -/obj/machinery/computer/mecha/Topic(href, href_list) + data["mechs"] += list(mech_data) + + return data + +/obj/machinery/computer/mecha/ui_act(action, params) if(..()) return - if(href_list["send_message"]) - var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["send_message"]) - if (!istype(MT)) - return - var/message = stripped_input(usr,"Input message","Transmit message") - var/obj/mecha/M = MT.in_mecha() - if(trim(message) && M) - M.occupant_message(message) - return - if(href_list["shock"]) - var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["shock"]) - if (istype(MT)) - MT.shock() - if(href_list["get_log"]) - var/obj/item/mecha_parts/mecha_tracking/MT = locate(href_list["get_log"]) - if(istype(MT)) - stored_data = MT.get_mecha_log() - screen = 1 - if(href_list["return"]) - screen = 0 - updateUsrDialog() - return + + switch(action) + if("send_message") + var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"]) + if(!istype(MT)) + return + var/message = stripped_input(usr, "Input message", "Transmit message") + var/obj/mecha/M = MT.chassis + if(trim(message) && M) + M.occupant_message(message) + to_chat(usr, "Message sent.") + . = TRUE + if("shock") + var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["tracker_ref"]) + if(!istype(MT)) + return + var/obj/mecha/M = MT.chassis + if(M) + MT.shock() + log_game("[key_name(usr)] has activated remote EMP on exosuit [M], located at [loc_name(M)], which is currently [M.occupant? "being piloted by [key_name(M.occupant)]." : "without a pilot."] ") + message_admins("[key_name_admin(usr)][ADMIN_FLW(usr)] has activated remote EMP on exosuit [M][ADMIN_JMP(M)], which is currently [M.occupant ? "being piloted by [key_name_admin(M.occupant)][ADMIN_FLW(M.occupant)]." : "without a pilot."] ") + . = TRUE /obj/item/mecha_parts/mecha_tracking name = "exosuit tracking beacon" @@ -68,24 +77,31 @@ icon = 'icons/obj/device.dmi' icon_state = "motion2" w_class = WEIGHT_CLASS_SMALL - var/ai_beacon = FALSE //If this beacon allows for AI control. Exists to avoid using istype() on checking. - var/recharging = 0 + /// If this beacon allows for AI control. Exists to avoid using istype() on checking + var/ai_beacon = FALSE + /// Cooldown variable for EMP pulsing + var/recharging = FALSE + /// The Mecha that this tracking beacon is attached to + var/obj/mecha/chassis +/** + * Returns a html formatted string describing attached mech status + */ /obj/item/mecha_parts/mecha_tracking/proc/get_mecha_info() - if(!in_mecha()) - return 0 - var/obj/mecha/M = src.loc - var/cell_charge = M.get_charge() - var/answer = {"Name: [M.name] -Integrity: [M.obj_integrity/M.max_integrity*100]% -Cell charge: [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"] -Airtank: [M.return_pressure()]kPa -Pilot: [M.occupant||"None"] -Location: [get_area(M)||"Unknown"] -Active equipment: [M.selected||"None"] "} - if(istype(M, /obj/mecha/working/ripley)) - var/obj/mecha/working/ripley/RM = M - answer += "Used cargo space: [RM.cargo.len/RM.cargo_capacity*100]%
    " + if(!chassis) + return FALSE + + var/cell_charge = chassis.get_charge() + var/answer = {"Name: [chassis.name]
    + Integrity: [round((chassis.obj_integrity/chassis.max_integrity * 100), 0.01)]%
    + Cell Charge: [isnull(cell_charge) ? "Not Found":"[chassis.cell.percent()]%"]
    + Airtank: [chassis.internal_tank ? "[round(chassis.return_pressure(), 0.01)]" : "Not Equipped"] kPa
    + Pilot: [chassis.occupant || "None"]
    + Location: [get_area_name(chassis, TRUE) || "Unknown"]
    + Active Equipment: [chassis.selected || "None"]"} + if(istype(chassis, /obj/mecha/working/ripley)) + var/obj/mecha/working/ripley/RM = chassis + answer += "
    Used Cargo Space: [round((RM.cargo.len / RM.cargo_capacity * 100), 0.01)]%" return answer @@ -95,42 +111,41 @@ qdel(src) /obj/item/mecha_parts/mecha_tracking/Destroy() - if(ismecha(loc)) - var/obj/mecha/M = loc - if(src in M.trackers) - M.trackers -= src + if(chassis) + if(src in chassis.trackers) + chassis.trackers -= src + chassis = null return ..() -/obj/item/mecha_parts/mecha_tracking/proc/in_mecha() - if(ismecha(loc)) - return loc - return 0 +/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/mecha/M) + if(!..()) + return + M.trackers += src + M.diag_hud_set_mechtracking() + chassis = M +/** + * Attempts to EMP mech that the tracker is attached to, if there is one and tracker is not on cooldown + */ /obj/item/mecha_parts/mecha_tracking/proc/shock() if(recharging) return - var/obj/mecha/M = in_mecha() - if(M) - M.emp_act(EMP_HEAVY) - addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 15 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) - recharging = 1 + if(chassis) + chassis.emp_act(EMP_HEAVY) + addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) + recharging = TRUE +/** + * Resets recharge variable, allowing tracker to be EMP pulsed again + */ /obj/item/mecha_parts/mecha_tracking/proc/recharge() - recharging = 0 - -/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log() - if(!ismecha(loc)) - return 0 - var/obj/mecha/M = src.loc - return M.get_log_html() - + recharging = FALSE /obj/item/mecha_parts/mecha_tracking/ai_control name = "exosuit AI control beacon" desc = "A device used to transmit exosuit data. Also allows active AI units to take control of said exosuit." ai_beacon = TRUE - /obj/item/storage/box/mechabeacons name = "exosuit tracking beacons" diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 395ac810f4..40336fb01e 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -54,11 +54,7 @@ . *= booster_damage_modifier -/obj/mecha/attack_hand(mob/living/user) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) // Ugh. Ideally we shouldn't be setting cooldowns outside of click code. +/obj/mecha/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) playsound(loc, 'sound/weapons/tap.ogg', 40, 1, -1) user.visible_message("[user] hits [name]. Nothing happens", null, null, COMBAT_MESSAGE_RANGE) @@ -255,7 +251,7 @@ return else if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) if(obj_integrity < max_integrity) if(W.use_tool(src, user, 0, volume=50, amount=1)) if (internal_damage & MECHA_INT_TANK_BREACH) diff --git a/code/game/mecha/mecha_parts.dm b/code/game/mecha/mecha_parts.dm index 811ffdef35..8a9e4e641f 100644 --- a/code/game/mecha/mecha_parts.dm +++ b/code/game/mecha/mecha_parts.dm @@ -9,6 +9,13 @@ w_class = WEIGHT_CLASS_GIGANTIC flags_1 = CONDUCT_1 +/obj/item/mecha_parts/proc/try_attach_part(mob/user, obj/mecha/M) //For attaching parts to a finished mech + if(!user.transferItemToLoc(src, M)) + to_chat(user, "\The [src] is stuck to your hand, you cannot put it in \the [M]!") + return FALSE + user.visible_message("[user] attaches [src] to [M].", "You attach [src] to [M].") + return TRUE + /obj/item/mecha_parts/chassis name = "Mecha Chassis" icon_state = "backbone" @@ -129,6 +136,47 @@ desc = "A set of armor plates designed for the Gygax. Designed to effectively deflect damage with a lightweight construction." icon_state = "gygax_armor" +///////// Medical Gygax + +/obj/item/mecha_parts/chassis/medigax + name = "\improper Medical Gygax chassis" + construct_type = /datum/component/construction/unordered/mecha_chassis/medigax + +/obj/item/mecha_parts/part/medigax_torso + name = "\improper Medical Gygax torso" + desc = "A torso part of Gygax. Contains power unit, processing core and life support systems." + icon_state = "medigax_harness" + +/obj/item/mecha_parts/part/medigax_head + name = "\improper Medical Gygax head" + desc = "A Gygax head. Houses advanced surveillance and targeting sensors." + icon_state = "medigax_head" + +/obj/item/mecha_parts/part/medigax_left_arm + name = "\improper Medical Gygax left arm" + desc = "A Gygax left arm. Data and power sockets are compatible with most exosuit tools and weapons." + icon_state = "medigax_l_arm" + +/obj/item/mecha_parts/part/medigax_right_arm + name = "\improper Medical Gygax right arm" + desc = "A Gygax right arm. Data and power sockets are compatible with most exosuit tools and weapons." + icon_state = "medigax_r_arm" + +/obj/item/mecha_parts/part/medigax_left_leg + name = "\improper Medical Gygax left leg" + desc = "A Gygax left leg. Constructed with advanced servomechanisms and actuators to enable faster speed." + icon_state = "medigax_l_leg" + +/obj/item/mecha_parts/part/medigax_right_leg + name = "\improper Medical Gygax right leg" + desc = "A Gygax right leg. Constructed with advanced servomechanisms and actuators to enable faster speed." + icon_state = "medigax_r_leg" + +/obj/item/mecha_parts/part/medigax_armor + gender = PLURAL + name = "\improper Medical Gygax armor plates" + desc = "A set of armor plates designed for the Gygax. Designed to effectively deflect damage with a lightweight construction." + icon_state = "medigax_armor" //////////// Durand diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index b1ab944b49..067cffd319 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -75,7 +75,7 @@ var/cell_charge = get_charge() var/datum/gas_mixture/int_tank_air = internal_tank.return_air() var/tank_pressure = internal_tank ? round(int_tank_air.return_pressure(),0.01) : "None" - var/tank_temperature = internal_tank ? int_tank_air.temperature : "Unknown" + var/tank_temperature = internal_tank ? int_tank_air.return_temperature() : "Unknown" var/cabin_pressure = round(return_pressure(),0.01) . = {"[report_internal_damage()] [integrity<30?"DAMAGE LEVEL CRITICAL
    ":null] @@ -256,7 +256,7 @@ output_access_dialog(id_card, usr) if(href_list["del_req_access"] && add_req_access) - operation_req_access -= text2num(href_list["add_req_access"]) + operation_req_access -= text2num(href_list["del_req_access"]) output_access_dialog(id_card, usr) if(href_list["finish_req_access"]) diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index ecf39bcb0b..9175489c89 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -125,6 +125,24 @@ name = "\improper Dark Gygax wreckage" icon_state = "darkgygax-broken" +/obj/structure/mecha_wreckage/medigax + name = "\improper Medical Gygax wreckage" + icon_state = "medigax-broken" + +/obj/structure/mecha_wreckage/medigax/Initialize() + . = ..() + var/list/parts = list(/obj/item/mecha_parts/part/medigax_torso, + /obj/item/mecha_parts/part/medigax_head, + /obj/item/mecha_parts/part/medigax_left_arm, + /obj/item/mecha_parts/part/medigax_right_arm, + /obj/item/mecha_parts/part/medigax_left_leg, + /obj/item/mecha_parts/part/medigax_right_leg) + for(var/i = 0; i < 2; i++) + if(parts.len && prob(40)) + var/part = pick(parts) + welder_salvage += part + parts -= part + /obj/structure/mecha_wreckage/marauder name = "\improper Marauder wreckage" icon_state = "marauder-broken" diff --git a/code/game/mecha/medical/medigax.dm b/code/game/mecha/medical/medigax.dm new file mode 100644 index 0000000000..98b7c9455b --- /dev/null +++ b/code/game/mecha/medical/medigax.dm @@ -0,0 +1,34 @@ +/obj/mecha/medical/medigax + desc = "A Gygax with it's actuator overload stripped and a slick white paint scheme, for medical use, These exosuits are developed and produced by Vey-Med. (© All rights reserved)." + name = "\improper Medical Gygax" + icon_state = "medigax" + step_in = 1.75 // a little faster than an odysseus + max_temperature = 25000 + max_integrity = 250 + wreckage = /obj/structure/mecha_wreckage/odysseus + armor = list("melee" = 25, "bullet" = 20, "laser" = 30, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + internal_damage_threshold = 35 + deflect_chance = 15 + step_energy_drain = 6 + infra_luminosity = 6 + + +/obj/mecha/medical/medigax/moved_inside(mob/living/carbon/human/H) + . = ..() + if(.) + var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + hud.add_hud_to(H) + +/obj/mecha/medical/medigax/go_out() + if(isliving(occupant)) + var/mob/living/carbon/human/L = occupant + var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + hud.remove_hud_from(L) + ..() + +/obj/mecha/medical/medigax/mmi_moved_inside(obj/item/mmi/mmi_as_oc, mob/user) + . = ..() + if(.) + var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED] + var/mob/living/brain/B = mmi_as_oc.brainmob + hud.add_hud_to(B) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index bacb8c6669..bdb748925c 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -9,7 +9,7 @@ var/buckle_prevents_pull = FALSE //Interaction -/atom/movable/attack_hand(mob/living/user) +/atom/movable/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -145,3 +145,13 @@ var/mob/living/L = M.pulledby L.set_pull_offsets(M, L.grab_state) return M + +/atom/movable/proc/precise_user_unbuckle_mob(mob/user) + if(!buckled_mobs) + return + else if(length(buckled_mobs) == 1) + return user_unbuckle_mob(buckled_mobs[1], user) + else + var/unbuckled = input(user, "Who do you wish to unbuckle?","Unbuckle Who?") as null|mob in buckled_mobs + return user_unbuckle_mob(unbuckled, user) + diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index e75a18dca8..41270bb09e 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -8,7 +8,7 @@ anchored = TRUE light_range = 3 var/movechance = 70 - var/obj/item/assembly/signaler/anomaly/aSignal + var/obj/item/assembly/signaler/anomaly/aSignal = /obj/item/assembly/signaler/anomaly var/area/impact_area var/lifespan = 990 @@ -23,8 +23,10 @@ START_PROCESSING(SSobj, src) impact_area = get_area(src) - aSignal = new(src) - aSignal.name = "[name] core" + if (!impact_area) + return INITIALIZE_HINT_QDEL + + aSignal = new aSignal(src) aSignal.code = rand(1,100) aSignal.anomaly_type = type @@ -75,7 +77,7 @@ /obj/effect/anomaly/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/analyzer)) + if(I.tool_behaviour == TOOL_ANALYZER) //revert if runtimed to_chat(user, "Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].") /////////////////////// @@ -85,6 +87,7 @@ icon_state = "shield2" density = FALSE var/boing = 0 + aSignal = /obj/item/assembly/signaler/anomaly/grav /obj/effect/anomaly/grav/anomalyEffect() ..() @@ -95,17 +98,23 @@ for(var/mob/living/M in range(0, src)) gravShock(M) for(var/mob/living/M in orange(4, src)) - step_towards(M,src) + if(!M.mob_negates_gravity()) //delete when runtimed + step_towards(M,src) for(var/obj/O in range(0,src)) if(!O.anchored) + //if(isturf(O.loc)) + // var/turf/T = O.loc + // if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) + // continue var/mob/living/target = locate() in view(4,src) if(target && !target.stat) O.throw_at(target, 5, 10) -/obj/effect/anomaly/grav/Crossed(mob/A) - gravShock(A) +/obj/effect/anomaly/grav/Crossed(atom/movable/AM) + . = ..() + gravShock(AM) -/obj/effect/anomaly/grav/Bump(mob/A) +/obj/effect/anomaly/grav/Bump(atom/A) gravShock(A) /obj/effect/anomaly/grav/Bumped(atom/movable/AM) @@ -138,6 +147,7 @@ name = "flux wave anomaly" icon_state = "electricity2" density = TRUE + aSignal = /obj/item/assembly/signaler/anomaly/flux var/canshock = FALSE var/shockdamage = 20 var/explosive = TRUE @@ -148,11 +158,12 @@ for(var/mob/living/M in range(0, src)) mobShock(M) -/obj/effect/anomaly/flux/Crossed(mob/living/M) - mobShock(M) +/obj/effect/anomaly/flux/Crossed(atom/movable/AM) + . = ..() + mobShock(AM) -/obj/effect/anomaly/flux/Bump(mob/living/M) - mobShock(M) +/obj/effect/anomaly/flux/Bump(atom/A) + mobShock(A) /obj/effect/anomaly/flux/Bumped(atom/movable/AM) mobShock(AM) @@ -160,7 +171,7 @@ /obj/effect/anomaly/flux/proc/mobShock(mob/living/M) if(canshock && istype(M)) canshock = FALSE //Just so you don't instakill yourself if you slam into the anomaly five times in a second. - M.electrocute_act(shockdamage, "[name]", flags = SHOCK_NOGLOVES) + M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES) /obj/effect/anomaly/flux/detonate() if(explosive) @@ -176,6 +187,7 @@ icon = 'icons/obj/projectiles.dmi' icon_state = "bluespace" density = TRUE + aSignal = /obj/item/assembly/signaler/anomaly/bluespace /obj/effect/anomaly/bluespace/anomalyEffect() ..() @@ -187,7 +199,7 @@ do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE) /obj/effect/anomaly/bluespace/detonate() - var/turf/T = safepick(get_area_turfs(impact_area)) + var/turf/T = pick(get_area_turfs(impact_area)) if(T) // Calculate new position (searches through beacons in world) var/obj/item/beacon/chosen @@ -224,21 +236,23 @@ if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving A.forceMove(newloc) - spawn() - if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect - var/mob/M = A - if(M.client) - var/obj/blueeffect = new /obj(src) - blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH" - blueeffect.icon = 'icons/effects/effects.dmi' - blueeffect.icon_state = "shieldsparkles" - blueeffect.layer = FLASH_LAYER - blueeffect.plane = FULLSCREEN_PLANE - blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT - M.client.screen += blueeffect - sleep(20) - M.client.screen -= blueeffect - qdel(blueeffect) + if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect + var/mob/M = A + if(M.client) + INVOKE_ASYNC(src, .proc/blue_effect, M) + +/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M) + var/obj/blueeffect = new /obj(src) + blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH" + blueeffect.icon = 'icons/effects/effects.dmi' + blueeffect.icon_state = "shieldsparkles" + blueeffect.layer = FLASH_LAYER + blueeffect.plane = FULLSCREEN_PLANE + blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + M.client.screen += blueeffect + sleep(20) + M.client.screen -= blueeffect + qdel(blueeffect) ///////////////////// @@ -246,6 +260,7 @@ name = "pyroclastic anomaly" icon_state = "mustard" var/ticks = 0 + aSignal = /obj/item/assembly/signaler/anomaly/pyro /obj/effect/anomaly/pyro/anomalyEffect() ..() @@ -278,6 +293,7 @@ name = "vortex anomaly" icon_state = "bhole3" desc = "That's a nice station you have there. It'd be a shame if something happened to it." + aSignal = /obj/item/assembly/signaler/anomaly/vortex /obj/effect/anomaly/bhole/anomalyEffect() ..() diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index c56731b3d3..8e2f39d0df 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -101,10 +101,7 @@ to_chat(user, "You carefully remove the poster from the wall.") roll_and_drop(user.loc) -/obj/structure/sign/poster/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/sign/poster/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(ruined) return visible_message("[user] rips [src] in a single, decisive motion!" ) @@ -212,6 +209,11 @@ desc = "A heretical poster depicting the titular star of an equally heretical book." icon_state = "poster4" +/obj/structure/sign/poster/contraband/post_ratvar + name = "Post This Ratvar" + desc = "Oh what in the hell? Those cultists have animated paper technology and they use it for a meme?" + icon_state = "postvar" + /obj/structure/sign/poster/contraband/syndicate_recruitment name = "Syndicate Recruitment" desc = "See the galaxy! Shatter corrupt megacorporations! Join today!" diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index a5acc7d394..fa16a95faf 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -91,7 +91,7 @@ var/mob/living/carbon/human/H = O var/obj/item/clothing/shoes/S = H.shoes if(S && S.bloody_shoes[blood_state]) - if(color != bloodtype_to_color(S.last_bloodtype)) + if(color != S.last_blood_color) return S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0) shoe_types |= S.type @@ -104,7 +104,7 @@ var/mob/living/carbon/human/H = O var/obj/item/clothing/shoes/S = H.shoes if(S && S.bloody_shoes[blood_state]) - if(color != bloodtype_to_color(S.last_bloodtype))//last entry - we check its color + if(color != S.last_blood_color)//last entry - we check its color return S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0) shoe_types |= S.type diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 2e45bbfca5..044c5c6e86 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -137,10 +137,7 @@ random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") beauty = -150 -/obj/effect/decal/cleanable/vomit/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/effect/decal/cleanable/vomit/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(ishuman(user)) var/mob/living/carbon/human/H = user if(isflyperson(H)) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index f98b4937ef..640675bea5 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -40,12 +40,11 @@ if(hotspot && istype(T) && T.air) qdel(hotspot) var/datum/gas_mixture/G = T.air - var/plas_amt = min(30,G.gases[/datum/gas/plasma]) //Absorb some plasma - G.gases[/datum/gas/plasma] -= plas_amt + var/plas_amt = min(30,G.get_moles(/datum/gas/plasma)) //Absorb some plasma + G.adjust_moles(/datum/gas/plasma,-plas_amt) absorbed_plasma += plas_amt - if(G.temperature > T20C) - G.temperature = max(G.temperature/2,T20C) - GAS_GARBAGE_COLLECT(G.gases) + if(G.return_temperature() > T20C) + G.set_temperature(max(G.return_temperature()/2,T20C)) T.air_update_turf() /obj/effect/particle_effect/foam/firefighting/kill_foam() @@ -269,6 +268,8 @@ gender = PLURAL max_integrity = 20 CanAtmosPass = ATMOS_PASS_DENSITY + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE /obj/structure/foamedmetal/Initialize() . = ..() @@ -285,11 +286,7 @@ /obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) -/obj/structure/foamedmetal/attack_hand(mob/user) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) +/obj/structure/foamedmetal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) to_chat(user, "You hit [src] but bounce off it!") playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) @@ -317,15 +314,13 @@ O.ClearWet() if(O.air) var/datum/gas_mixture/G = O.air - G.temperature = 293.15 + G.set_temperature(293.15) for(var/obj/effect/hotspot/H in O) qdel(H) - var/list/G_gases = G.gases - for(var/I in G_gases) + for(var/I in G.get_gases()) if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen) continue - G_gases[I] = 0 - GAS_GARBAGE_COLLECT(G.gases) + G.set_moles(I, 0) O.air_update_turf() for(var/obj/machinery/atmospherics/components/unary/U in O) if(!U.welded) diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index 80c0db2b7d..9a11f0e1d7 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -166,15 +166,13 @@ if(T.air) var/datum/gas_mixture/G = T.air if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air - G.temperature = temperature + G.set_temperature(temperature) T.air_update_turf() for(var/obj/effect/hotspot/H in T) qdel(H) - var/list/G_gases = G.gases - if(G_gases[/datum/gas/plasma]) - G_gases[/datum/gas/nitrogen] += (G_gases[/datum/gas/plasma]) - G_gases[/datum/gas/plasma] = 0 - GAS_GARBAGE_COLLECT(G.gases) + if(G.get_moles(/datum/gas/plasma)) + G.adjust_moles(/datum/gas/nitrogen, G.get_moles(/datum/gas/plasma)) + G.set_moles(/datum/gas/plasma, 0) if (weldvents) for(var/obj/machinery/atmospherics/components/unary/U in T) if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber. diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm index 19b0dc76dd..a388d3bc67 100644 --- a/code/game/objects/effects/effect_system/effects_sparks.dm +++ b/code/game/objects/effects/effect_system/effects_sparks.dm @@ -63,3 +63,23 @@ /datum/effect_system/lightning_spread effect_type = /obj/effect/particle_effect/sparks/electricity + +//fake sparks, not subtyped because we don't want light/heat, nor checks inside an often used proc for a rare subcase for saving like 10 lines of code +/obj/effect/particle_effect/fake_sparks + name = "lightning" + icon_state = "electricity" + +/obj/effect/particle_effect/fake_sparks/Initialize() + . = ..() + flick(icon_state, src) // replay the animation + playsound(src, "sparks", 100, TRUE) + QDEL_IN(src, 20) + +/datum/effect_system/fake_spark_spread + effect_type = /obj/effect/particle_effect/fake_sparks + +/proc/do_fake_sparks(n, c, source) + var/datum/effect_system/fake_spark_spread/sparks = new + sparks.set_up(n, c, source) + sparks.autocleanup = TRUE + sparks.start() diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 40104d5ea8..d5f53b2f1c 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -146,14 +146,13 @@ spawn(0) new /datum/hallucination/delusion(victim, TRUE, "demon",duration,0) - var/obj/item/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc) + var/obj/item/chainsaw/doomslayer/chainsaw = new(victim.loc) victim.log_message("entered a blood frenzy", LOG_ATTACK) ADD_TRAIT(chainsaw, TRAIT_NODROP, CHAINSAW_FRENZY_TRAIT) victim.drop_all_held_items() victim.put_in_hands(chainsaw, forced = TRUE) chainsaw.attack_self(victim) - chainsaw.wield(victim) victim.reagents.add_reagent(/datum/reagent/medicine/adminordrazine,25) to_chat(victim, "KILL, KILL, KILL! YOU HAVE NO ALLIES ANYMORE, KILL THEM ALL!") diff --git a/code/game/objects/effects/portals.dm b/code/game/objects/effects/portals.dm index 504b931685..a7b5091522 100644 --- a/code/game/objects/effects/portals.dm +++ b/code/game/objects/effects/portals.dm @@ -1,10 +1,10 @@ -/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override) +/proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override) if(!istype(source) || !istype(destination)) return var/turf/actual_destination = get_teleport_turf(destination, accuracy) - var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE, null, atmos_link_override) - var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, null, atmos_link_override) + var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override) + var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override) if(!istype(P1)||!istype(P2)) return P1.link_portal(P2) @@ -21,7 +21,6 @@ var/obj/effect/portal/linked var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted. var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE - var/creator var/turf/hard_target //For when a portal needs a hard target and isn't to be linked. var/atmos_link = FALSE //Link source/destination atmos. var/turf/open/atmos_source //Atmos link source @@ -35,6 +34,7 @@ name = "wormhole" icon = 'icons/obj/objects.dmi' icon_state = "anom" + layer = RIPPLE_LAYER mech_sized = TRUE teleport_channel = TELEPORT_CHANNEL_WORMHOLE @@ -49,7 +49,9 @@ user.forceMove(get_turf(src)) return TRUE -/obj/effect/portal/Crossed(atom/movable/AM, oldloc) +/obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0) + if(force_stop) + return ..() if(isobserver(AM)) return ..() if(linked && (get_turf(oldloc) == get_turf(linked))) @@ -60,16 +62,13 @@ /obj/effect/portal/attack_tk(mob/user) return -/obj/effect/portal/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/effect/portal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(get_turf(user) == get_turf(src)) teleport(user) if(Adjacent(user)) user.forceMove(get_turf(src)) -/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override) +/obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override) . = ..() GLOB.portals += src if(!istype(_linked) && automatic_link) @@ -81,7 +80,6 @@ atmos_link = atmos_link_override link_portal(_linked) hardlinked = automatic_link - creator = _creator if(isturf(hard_target_override)) hard_target = hard_target_override @@ -132,10 +130,7 @@ LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source) atmos_destination = null -/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call. - if(creator && hascall(creator, "on_portal_destroy")) - call(creator, "on_portal_destroy")(src, src.loc) - creator = null +/obj/effect/portal/Destroy() GLOB.portals -= src unlink_atmos() if(hardlinked && !QDELETED(linked)) @@ -156,8 +151,6 @@ return FALSE if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored)) return - if(ismegafauna(M)) - message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].") var/no_effect = FALSE if(last_effect == world.time) no_effect = TRUE diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index a0ae300c79..b5aaff5746 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -19,11 +19,11 @@ var/obj/item/tank/internals/plasma/PT = new(V) var/obj/item/tank/internals/oxygen/OT = new(V) - PT.air_contents.gases[/datum/gas/plasma] = pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p)) - PT.air_contents.temperature = CELSIUS_TO_KELVIN(temp_p) + PT.air_contents.set_moles(/datum/gas/plasma, pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p))) + PT.air_contents.set_temperature(CELSIUS_TO_KELVIN(temp_p)) - OT.air_contents.gases[/datum/gas/oxygen] = pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o)) - OT.air_contents.temperature = CELSIUS_TO_KELVIN(temp_o) + OT.air_contents.set_moles(/datum/gas/oxygen, pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o))) + OT.air_contents.set_temperature(CELSIUS_TO_KELVIN(temp_o)) V.tank_one = PT V.tank_two = OT diff --git a/code/game/objects/effects/spawners/bundle.dm b/code/game/objects/effects/spawners/bundle.dm index 3f2701c03f..b75df644eb 100644 --- a/code/game/objects/effects/spawners/bundle.dm +++ b/code/game/objects/effects/spawners/bundle.dm @@ -168,3 +168,26 @@ items = list( /obj/item/clothing/mask/gas/sexymime, /obj/item/clothing/under/rank/civilian/mime/sexy) + +/obj/effect/spawner/bundle/crate/Initialize(mapload) + if(items && items.len) + var/turf/T = get_turf(src) + var/obj/structure/closet/LC = locate(/obj/structure/closet) in T + if(LC) + for(var/path in items) + new path(LC) + return INITIALIZE_HINT_QDEL + +/obj/effect/spawner/bundle/crate/mosin + name = "Mosin-Nagant spawner" + items = list( + /obj/item/gun/ballistic/shotgun/boltaction, + /obj/item/ammo_box/a762 + ) + +/obj/effect/spawner/bundle/crate/surplusrifle + name = "surplus rifle spawner" + items = list( + /obj/item/gun/ballistic/automatic/surplus, + /obj/item/ammo_box/magazine/m10mm/rifle + ) diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 57b25a8901..6564a83729 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -380,8 +380,6 @@ name = "random keg spawner" lootcount = 1 loot = list(/obj/structure/reagent_dispensers/keg/mead = 5, - /obj/structure/reagent_dispensers/keg/aphro = 2, - /obj/structure/reagent_dispensers/keg/aphro/strong = 2, /obj/structure/reagent_dispensers/keg/gargle = 1) /obj/effect/spawner/lootdrop/coin @@ -451,7 +449,7 @@ lootcount = 1 spawn_on_turf = FALSE //Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that -//This is ment for "low" loot that anyone could fine in a toilet, for better gear use high loot toilet +//This is meant for "low" loot that anyone could find in a toilet, for better gear use high loot toilet loot = list("" = 30, /obj/item/lighter = 2, /obj/item/tape/random = 1, @@ -466,7 +464,7 @@ /obj/effect/spawner/lootdrop/cigars_cases/no_turf = 2, /obj/effect/spawner/lootdrop/space_cash/no_turf = 5, /obj/item/reagent_containers/food/snacks/grown/cannabis = 5, - /obj/item/storage/pill_bottle/dice = 5, + /obj/item/storage/box/dice = 5, /obj/item/toy/cards/deck = 5, /obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5 ) @@ -476,7 +474,7 @@ lootcount = 1 spawn_on_turf = FALSE //Note this is out of a 100 - Meaning the number you see is also the percent its going to pick that -//This is ment for "prison" loot that is rather rare and ment for "prisoners if they get a crowbar to fine, or sec. +//This is meant for "prison" loot that is rather rare and meant for "prisoners if they get a crowbar to fine, or sec. loot = list("" = 10, /obj/item/lighter = 5, /obj/item/poster/random_contraband = 5, @@ -485,7 +483,7 @@ /obj/effect/spawner/lootdrop/cig_packs/no_turf = 10, /obj/effect/spawner/lootdrop/cigars_cases/no_turf = 5, /obj/item/reagent_containers/food/snacks/grown/cannabis = 5, - /obj/item/storage/pill_bottle/dice = 5, + /obj/item/storage/box/dice = 5, /obj/item/toy/cards/deck = 5, /obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5, /obj/item/kitchen/knife = 5, @@ -666,28 +664,18 @@ lootcount = 1 spawn_on_turf = FALSE loot = list("" = 50, - /obj/item/weaponcrafting/improvised_parts/barrel_rifle = 10, - /obj/item/weaponcrafting/improvised_parts/barrel_shotgun = 5, - /obj/item/weaponcrafting/improvised_parts/barrel_pistol = 5, - /obj/item/weaponcrafting/improvised_parts/rifle_receiver = 10, - /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 3, - /obj/item/weaponcrafting/improvised_parts/pistol_receiver = 3, - /obj/item/weaponcrafting/improvised_parts/laser_receiver = 1, - /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 10, - /obj/item/weaponcrafting/improvised_parts/makeshift_lens = 3, + /obj/item/weaponcrafting/improvised_parts/rifle_receiver = 13, + /obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 13, + /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 12, ) /obj/effect/spawner/lootdrop/weapon_parts - name = "random weapon parts spawner 25%" + name = "random weapon parts spawner 20%" lootcount = 1 spawn_on_turf = FALSE - loot = list("" = 75, - /obj/item/weaponcrafting/improvised_parts/barrel_rifle = 5, - /obj/item/weaponcrafting/improvised_parts/barrel_pistol = 5, + loot = list("" = 80, /obj/item/weaponcrafting/improvised_parts/rifle_receiver = 5, - /obj/item/weaponcrafting/improvised_parts/pistol_receiver = 2, /obj/item/weaponcrafting/improvised_parts/trigger_assembly = 5, - /obj/item/weaponcrafting/improvised_parts/makeshift_lens = 3, ) /obj/effect/spawner/lootdrop/ammo @@ -695,8 +683,6 @@ lootcount = 1 spawn_on_turf = FALSE loot = list("" = 25, - /obj/item/ammo_box/c32mm = 15, - /obj/item/ammo_box/r32mm = 15, /obj/item/ammo_box/magazine/wt550m9 = 1, /obj/item/ammo_casing/shotgun/buckshot = 7, /obj/item/ammo_casing/shotgun/rubbershot = 7, @@ -709,8 +695,6 @@ lootcount = 1 spawn_on_turf = FALSE loot = list("" = 50, - /obj/item/ammo_box/c32mm = 7, - /obj/item/ammo_box/r32mm = 7, /obj/item/ammo_box/magazine/wt550m9 = 2, /obj/item/ammo_casing/shotgun/buckshot = 10, /obj/item/ammo_casing/shotgun/rubbershot = 10, diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm index 14b3c4e73e..4b04606401 100644 --- a/code/game/objects/effects/spiders.dm +++ b/code/game/objects/effects/spiders.dm @@ -69,6 +69,7 @@ if(prob(50)) to_chat(mover, "You get stuck in \the [src] for a moment.") return FALSE + return TRUE else if(istype(mover, /obj/item/projectile)) return prob(30) @@ -119,6 +120,8 @@ var/poison_type = "toxin" var/poison_per_bite = 5 var/list/faction = list("spiders") + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE /obj/structure/spider/spiderling/Destroy() new/obj/item/reagent_containers/food/snacks/spiderling(get_turf(src)) @@ -152,10 +155,9 @@ else ..() -/obj/structure/spider/spiderling/attack_hand(mob/user) +/obj/structure/spider/spiderling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(user.a_intent != INTENT_HELP) - user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) user.visible_message("[user] splats [src].", "You splat [src].", "You hear a splat...") playsound(loc, 'sound/effects/snap.ogg', 25) @@ -252,8 +254,6 @@ /obj/structure/spider/cocoon/container_resist(mob/living/user) var/breakout_time = 600 - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT to_chat(user, "You struggle against the tight bonds... (This will take about [DisplayTimeText(breakout_time)].)") visible_message("You see something struggling and writhing in \the [src]!") if(do_after(user,(breakout_time), target = src)) @@ -261,8 +261,6 @@ return qdel(src) - - /obj/structure/spider/cocoon/Destroy() var/turf/T = get_turf(src) src.visible_message("\The [src] splits open.") diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index 53adc46239..8d5458333c 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -139,6 +139,23 @@ /obj/effect/temp_visual/dir_setting/curse/hand icon_state = "cursehand" +/obj/effect/temp_visual/bsa_splash + name = "\improper Bluespace energy wave" + desc = "A massive, rippling wave of bluepace energy, all rapidly exhausting itself the moment it leaves the concentrated beam of light." + icon = 'icons/effects/beam_splash.dmi' + icon_state = "beam_splash_l" + layer = ABOVE_ALL_MOB_LAYER + pixel_y = -16 + duration = 50 + +/obj/effect/temp_visual/bsa_splash/Initialize(mapload, dir) + . = ..() + switch(dir) + if(WEST) + icon_state = "beam_splash_w" + if(EAST) + icon_state = "beam_splash_e" + /obj/effect/temp_visual/wizard name = "water" icon = 'icons/mob/mob.dmi' @@ -486,4 +503,15 @@ addtimer(CALLBACK(src, .proc/end), 15) /obj/effect/constructing_effect/proc/end() - qdel(src) \ No newline at end of file + qdel(src) + +/obj/effect/temp_visual/dir_setting/space_wind + icon = 'icons/effects/atmospherics.dmi' + icon_state = "space_wind" + layer = FLY_LAYER + duration = 20 + mouse_opacity = 0 + +/obj/effect/temp_visual/dir_setting/space_wind/Initialize(mapload, set_dir, set_alpha = 255) + . = ..() + alpha = set_alpha diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 5aa47cfb76..b4c114eb6a 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -11,6 +11,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb name = "item" icon = 'icons/obj/items_and_weapons.dmi' blocks_emissive = EMISSIVE_BLOCK_GENERIC + + attack_hand_speed = 0 + attack_hand_is_action = FALSE + attack_hand_unwieldlyness = 0 ///icon state name for inhand overlays var/item_state = null @@ -58,16 +62,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives. var/stagger_force - /** - * Set FALSE and then checked at the end of on mob/living/attackby(), set TRUE on living/pre_attacked_by(). - * Should it be FALSE by the end of the item/attack(), that means the item overrode the standard attack behaviour - * and the user still needs the delay applied. We can't be using return values since that'll stop afterattack() from being triggered. - */ - var/attack_delay_done = FALSE - ///next_move click/attack delay of this item. - var/click_delay = CLICK_CD_MELEE - var/slot_flags = 0 //This is used to determine on which slots an item can fit. + var/current_equipped_slot pass_flags = PASSTABLE pressure_resistance = 4 var/obj/item/master = null @@ -107,12 +103,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged - var/list/embedding = NONE + var/list/embedding var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES var/heat = 0 - ///All items with sharpness of IS_SHARP or higher will automatically get the butchering component. - var/sharpness = IS_BLUNT + ///All items with sharpness of SHARP_EDGED or higher will automatically get the butchering component. + var/sharpness = SHARP_NONE var/tool_behaviour = NONE var/toolspeed = 1 @@ -179,6 +175,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(damtype == "brute") hitsound = "swing_hit" + if(used_skills) + for(var/path in used_skills) + var/datum/skill/S = GLOB.skill_datums[path] + LAZYADD(used_skills[path], S.skill_traits) + /obj/item/Destroy() item_flags &= ~DROPDEL //prevent reqdels if(ismob(loc)) @@ -205,7 +206,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(GLOB.rpg_loot_items) AddComponent(/datum/component/fantasy) - if(sharpness) //give sharp objects butchering functionality, for consistency + if(sharpness && force > 5) //give sharp objects butchering functionality, for consistency AddComponent(/datum/component/butchering, 80 * toolspeed) /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) @@ -257,7 +258,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb . += "[src] is made of cold-resistant materials." if(resistance_flags & FIRE_PROOF) . += "[src] is made of fire-retardant materials." - + if(item_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY)) var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data) . += "[src] has the capacity to be used to block and/or parry. \[Show Stats\]" @@ -307,14 +308,15 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb add_fingerprint(usr) return ..() -/obj/item/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!user) return if(anchored) return + if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS) + if(current_equipped_slot in user.check_obscured_slots()) + to_chat(src, "You are unable to unequip that while wearing other garments over it!") + return FALSE if(resistance_flags & ON_FIRE) var/mob/living/carbon/C = user @@ -336,7 +338,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb C.update_damage_overlays() return - if(acid_level > 20 && !ismob(loc))// so we can still remove the clothes on us that have acid. + if(acid_level > 20 && ismob(loc))// so we can still remove the clothes on us that have acid. var/mob/living/carbon/C = user if(istype(C)) if(!C.gloves || (!(C.gloves.resistance_flags & (UNACIDABLE|ACID_PROOF)))) @@ -379,6 +381,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb return if(anchored) return + if(loc == user && current_equipped_slot && current_equipped_slot != SLOT_HANDS) + if(current_equipped_slot in user.check_obscured_slots()) + to_chat(src, "You are unable to unequip that while wearing other garments over it!") + return FALSE + SEND_SIGNAL(loc, COMSIG_TRY_STORAGE_TAKE, src, user.loc, TRUE) @@ -423,6 +430,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /obj/item/proc/dropped(mob/user) SHOULD_CALL_PARENT(TRUE) + current_equipped_slot = null for(var/X in actions) var/datum/action/A = X A.Remove(user) @@ -457,6 +465,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb usr.UnarmedAttack(src, TRUE) if(usr.get_active_held_item() == src) melee_attack_chain(usr, over) + usr.FlushCurrentAction() return TRUE //returning TRUE as a "is this overridden?" flag if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows @@ -470,7 +479,9 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb // for items that can be placed in multiple slots // note this isn't called during the initial dressing of a player /obj/item/proc/equipped(mob/user, slot) + SHOULD_CALL_PARENT(TRUE) . = SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot) + current_equipped_slot = slot if(!(. & COMPONENT_NO_GRANT_ACTIONS)) for(var/X in actions) var/datum/action/A = X @@ -496,11 +507,11 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb //if this is being done by a mob other than M, it will include the mob equipper, who is trying to equip the item to mob M. equipper will be null otherwise. //If you are making custom procs but would like to retain partial or complete functionality of this one, include a 'return ..()' to where you want this to happen. //Set disable_warning to TRUE if you wish it to not give you outputs. -/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) +/obj/item/proc/mob_can_equip(mob/living/M, mob/living/equipper, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) if(!M) return FALSE - return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self) + return M.can_equip(src, slot, disable_warning, bypass_equip_delay_self, clothing_check, return_warning) /obj/item/verb/verb_pickup() set src in oview(1) @@ -635,6 +646,18 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb var/itempush = 1 if(w_class < 4) itempush = 0 //too light to push anything + if(isliving(hit_atom)) //Living mobs handle hit sounds differently. + var/volume = get_volume_by_throwforce_and_or_w_class() + if (throwforce > 0) + if (throwhitsound) + playsound(hit_atom, throwhitsound, volume, TRUE, -1) + else if(hitsound) + playsound(hit_atom, hitsound, volume, TRUE, -1) + else + playsound(hit_atom, 'sound/weapons/genhit.ogg',volume, TRUE, -1) + else + playsound(hit_atom, 'sound/weapons/throwtap.ogg', 1, volume, -1) + return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum) /obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE) @@ -766,6 +789,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb ..() /obj/item/proc/microwave_act(obj/machinery/microwave/M) + SEND_SIGNAL(src, COMSIG_ITEM_MICROWAVE_ACT, M) if(istype(M) && M.dirty < 100) M.dirty++ @@ -822,7 +846,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb // 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, skill_gain_mult = 1, max_level = INFINITY) +/obj/item/proc/use_tool(atom/target, mob/living/user, delay, amount=0, volume=0, datum/callback/extra_checks, skill_gain_mult = STD_USE_TOOL_MULT) // 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)) @@ -867,7 +891,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb 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)) + var/datum/skill/S = GLOB.skill_datums[skill] + user.mind.auto_gain_experience(skill, gain*skill_gain_mult*S.item_skill_gain_multi) return TRUE @@ -1065,7 +1090,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /obj/item/proc/updateEmbedding() - if(!islist(embedding) || !LAZYLEN(embedding)) + if(!LAZYLEN(embedding)) return AddElement(/datum/element/embed,\ @@ -1081,4 +1106,4 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\ pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\ embed_chance_turf_mod = (!isnull(embedding["embed_chance_turf_mod"]) ? embedding["embed_chance_turf_mod"] : EMBED_CHANCE_TURF_MOD)) - return TRUE \ No newline at end of file + return TRUE diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 2fbb45173b..c89e318714 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -135,6 +135,14 @@ RLD flick("[icon_state]_empty", src) //somewhat hacky thing to make RCDs with ammo counters actually have a blinking yellow light return . + +/obj/item/construction/proc/check_menu(mob/living/user) + if(!istype(user)) + return FALSE + if(user.incapacitated() || !user.Adjacent(src)) + return FALSE + return TRUE + /obj/item/construction/proc/range_check(atom/A, mob/user) if(!(A in range(custom_range, get_turf(user)))) to_chat(user, "The \'Out of Range\' light on [src] blinks red.") @@ -276,13 +284,6 @@ RLD //Not scaling these down to button size because they look horrible then, instead just bumping up radius. return MA -/obj/item/construction/rcd/proc/check_menu(mob/living/user) - if(!istype(user)) - return FALSE - if(user.incapacitated() || !user.Adjacent(src)) - return FALSE - return TRUE - /obj/item/construction/rcd/proc/change_computer_dir(mob/user) if(!user) return @@ -856,6 +857,82 @@ RLD desc = "It contains the design for firelock, air alarm, fire alarm, apc circuits and crap power cells." upgrade = RCD_UPGRADE_SIMPLE_CIRCUITS +/obj/item/construction/plumbing + name = "Plumbing Constructor" + desc = "An expertly modified RCD outfitted to construct plumbing machinery. Reload with compressed matter cartridges." + icon = 'icons/obj/tools.dmi' + icon_state = "arcd" + item_state = "oldrcd" + has_ammobar = FALSE + matter = 200 + max_matter = 200 + + ///type of the plumbing machine + var/blueprint = null + ///index, used in the attack self to get the type. stored here since it doesnt change + var/list/choices = list() + ///index, used in the attack self to get the type. stored here since it doesnt change + var/list/name_to_type = list() + /// + var/list/machinery_data = list("cost" = list(), "delay" = list()) + +/obj/item/construction/plumbing/attack_self(mob/user) + ..() + if(!choices.len) + for(var/A in subtypesof(/obj/machinery/plumbing)) + var/obj/machinery/plumbing/M = A + if(initial(M.rcd_constructable)) + choices += list(initial(M.name) = image(icon = initial(M.icon), icon_state = initial(M.icon_state))) + name_to_type[initial(M.name)] = M + machinery_data["cost"][A] = initial(M.rcd_cost) + machinery_data["delay"][A] = initial(M.rcd_delay) + + var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE) + if(!check_menu(user)) + return + + blueprint = name_to_type[choice] + playsound(src, 'sound/effects/pop.ogg', 50, FALSE) + to_chat(user, "You change [name]s blueprint to '[choice]'.") + +///pretty much rcd_create, but named differently to make myself feel less bad for copypasting from a sibling-type +/obj/item/construction/plumbing/proc/create_machine(atom/A, mob/user) + if(!machinery_data || !isopenturf(A)) + return FALSE + + if(checkResource(machinery_data["cost"][blueprint], user) && blueprint) + if(do_after(user, machinery_data["delay"][blueprint], target = A)) + if(checkResource(machinery_data["cost"][blueprint], user) && canPlace(A)) + useResource(machinery_data["cost"][blueprint], user) + activate() + playsound(src.loc, 'sound/machines/click.ogg', 50, TRUE) + new blueprint (A, FALSE, FALSE) + return TRUE + +/obj/item/construction/plumbing/proc/canPlace(turf/T) + if(!isopenturf(T)) + return FALSE + . = TRUE + for(var/obj/O in T.contents) + if(O.density) //let's not built ontop of dense stuff, like big machines and other obstacles, it kills my immershion + return FALSE + +/obj/item/construction/plumbing/afterattack(atom/A, mob/user) + . = ..() + if(!range_check(A, user)) + return + if(istype(A, /obj/machinery/plumbing)) + var/obj/machinery/plumbing/P = A + if(P.anchored) + to_chat(user, "The [P.name] needs to be unanchored!") + return + if(do_after(user, 20, target = P)) + P.deconstruct() //Let's not substract matter + playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) //this is just such a great sound effect + else + create_machine(A, user) + + #undef GLOW_MODE #undef LIGHT_MODE #undef REMOVE_MODE diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm index f3ea461c74..6e305c30ee 100644 --- a/code/game/objects/items/RCL.dm +++ b/code/game/objects/items/RCL.dm @@ -1,4 +1,4 @@ -/obj/item/twohanded/rcl +/obj/item/rcl name = "rapid cable layer" desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables. Do not use without insulation!" icon = 'icons/obj/tools.dmi' @@ -23,15 +23,26 @@ var/datum/radial_menu/persistent/wiring_gui_menu var/mob/listeningTo -/obj/item/twohanded/rcl/Initialize() +/obj/item/rcl/Initialize() . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) update_icon() -/obj/item/twohanded/rcl/ComponentInitialize() +/obj/item/rcl/ComponentInitialize() . = ..() AddElement(/datum/element/update_icon_updates_onmob) + AddComponent(/datum/component/two_handed) -/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user) +/// triggered on wield of two handed item +/obj/item/rcl/proc/on_wield(obj/item/source, mob/user) + active = TRUE + +/// triggered on unwield of two handed item +/obj/item/rcl/proc/on_unwield(obj/item/source, mob/user) + active = FALSE + +/obj/item/rcl/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/stack/cable_coil)) var/obj/item/stack/cable_coil/C = W @@ -86,26 +97,26 @@ else ..() -/obj/item/twohanded/rcl/examine(mob/user) +/obj/item/rcl/examine(mob/user) . = ..() if(loaded) . += "It contains [loaded.amount]/[max_amount] cables." -/obj/item/twohanded/rcl/Destroy() +/obj/item/rcl/Destroy() QDEL_NULL(loaded) last = null listeningTo = null QDEL_NULL(wiring_gui_menu) return ..() -/obj/item/twohanded/rcl/update_icon_state() +/obj/item/rcl/update_icon_state() icon_state = initial(icon_state) item_state = initial(item_state) if(!loaded || !loaded.amount) icon_state += "-empty" item_state += "-0" -/obj/item/twohanded/rcl/update_overlays() +/obj/item/rcl/update_overlays() . = ..() if(!loaded || !loaded.amount) return @@ -113,7 +124,7 @@ cable_overlay.color = GLOB.cable_colors[colors[current_color_index]] . += cable_overlay -/obj/item/twohanded/rcl/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) +/obj/item/rcl/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) . = ..() if(!isinhands || !(loaded?.amount)) return @@ -121,7 +132,7 @@ cable_overlay.color = GLOB.cable_colors[colors[current_color_index]] . += cable_overlay -/obj/item/twohanded/rcl/proc/is_empty(mob/user, loud = 1) +/obj/item/rcl/proc/is_empty(mob/user, loud = 1) update_icon() if(!loaded || !loaded.amount) if(loud) @@ -130,26 +141,23 @@ QDEL_NULL(loaded) loaded = null QDEL_NULL(wiring_gui_menu) - unwield(user) - active = wielded return TRUE return FALSE -/obj/item/twohanded/rcl/pickup(mob/user) +/obj/item/rcl/pickup(mob/user) ..() getMobhook(user) -/obj/item/twohanded/rcl/dropped(mob/wearer) +/obj/item/rcl/dropped(mob/wearer) ..() UnregisterSignal(wearer, COMSIG_MOVABLE_MOVED) listeningTo = null last = null -/obj/item/twohanded/rcl/attack_self(mob/user) +/obj/item/rcl/attack_self(mob/user) ..() - active = wielded if(!active) last = null else if(!last) @@ -158,7 +166,7 @@ last = C break -obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) +obj/item/rcl/proc/getMobhook(mob/to_hook) if(listeningTo == to_hook) return if(listeningTo) @@ -166,7 +174,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) RegisterSignal(to_hook, COMSIG_MOVABLE_MOVED, .proc/trigger) listeningTo = to_hook -/obj/item/twohanded/rcl/proc/trigger(mob/user) +/obj/item/rcl/proc/trigger(mob/user) if(active) layCable(user) if(wiring_gui_menu) //update the wire options as you move @@ -174,7 +182,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) //previous contents of trigger(), lays cable each time the player moves -/obj/item/twohanded/rcl/proc/layCable(mob/user) +/obj/item/rcl/proc/layCable(mob/user) if(!isturf(user.loc)) return if(is_empty(user, 0)) @@ -207,7 +215,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) update_icon() //searches the current tile for a stub cable of the same colour -/obj/item/twohanded/rcl/proc/findLinkingCable(mob/user) +/obj/item/rcl/proc/findLinkingCable(mob/user) var/turf/T if(!isturf(user.loc)) return @@ -223,10 +231,8 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) continue if(C.d1 == 0) return C - return - -/obj/item/twohanded/rcl/proc/wiringGuiGenerateChoices(mob/user) +/obj/item/rcl/proc/wiringGuiGenerateChoices(mob/user) var/fromdir = 0 var/obj/structure/cable/linkingCable = findLinkingCable(user) if(linkingCable) @@ -243,12 +249,12 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) wiredirs[icondir] = img return wiredirs -/obj/item/twohanded/rcl/proc/showWiringGui(mob/user) +/obj/item/rcl/proc/showWiringGui(mob/user) var/list/choices = wiringGuiGenerateChoices(user) wiring_gui_menu = show_radial_menu_persistent(user, src , choices, select_proc = CALLBACK(src, .proc/wiringGuiReact, user), radius = 42) -/obj/item/twohanded/rcl/proc/wiringGuiUpdate(mob/user) +/obj/item/rcl/proc/wiringGuiUpdate(mob/user) if(!wiring_gui_menu) return @@ -259,7 +265,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) //Callback used to respond to interactions with the wiring menu -/obj/item/twohanded/rcl/proc/wiringGuiReact(mob/living/user,choice) +/obj/item/rcl/proc/wiringGuiReact(mob/living/user,choice) if(!choice) //close on a null choice (the center button) QDEL_NULL(wiring_gui_menu) return @@ -290,7 +296,7 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) wiringGuiUpdate(user) -/obj/item/twohanded/rcl/ui_action_click(mob/user, action) +/obj/item/rcl/ui_action_click(mob/user, action) if(istype(action, /datum/action/item_action/rcl_col)) current_color_index++; if (current_color_index > colors.len) @@ -308,13 +314,13 @@ obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) else //open the menu showWiringGui(user) -/obj/item/twohanded/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff +/obj/item/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff loaded = new() loaded.max_amount = max_amount loaded.amount = max_amount return ..() -/obj/item/twohanded/rcl/ghetto +/obj/item/rcl/ghetto actions_types = list() max_amount = 30 name = "makeshift rapid cable layer" diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index 665082d1d2..70e4441c66 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -6,6 +6,7 @@ RPD #define ATMOS_CATEGORY 0 #define DISPOSALS_CATEGORY 1 #define TRANSIT_CATEGORY 2 +#define PLUMBING_CATEGORY 3 #define BUILD_MODE (1<<0) #define WRENCH_MODE (1<<1) @@ -75,6 +76,13 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( ) )) +GLOBAL_LIST_INIT(fluid_duct_recipes, list( + "Fluid Ducts" = list( + new /datum/pipe_info/plumbing("Duct", /obj/machinery/duct, PIPE_ONEDIR), + new /datum/pipe_info/plumbing/multilayer("Duct Layer-Manifold",/obj/machinery/duct/multilayered, PIPE_STRAIGHT) + ) +)) + /datum/pipe_info var/name var/icon_state @@ -175,6 +183,15 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( if(dt == PIPE_UNARY_FLIPPABLE) icon_state = "[icon_state]_preview" +/datum/pipe_info/plumbing/New(label, obj/path, dt=PIPE_UNARY) + name = label + id = path + icon_state = initial(path.icon_state) + dirtype = dt + +/datum/pipe_info/plumbing/multilayer //exists as identifier so we can see the difference between multi_layer and just ducts properly later on + + /obj/item/pipe_dispenser name = "Rapid Piping Device (RPD)" desc = "A device used to rapidly pipe things." @@ -200,15 +217,19 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( var/atmos_build_speed = 5 //deciseconds (500ms) var/disposal_build_speed = 5 var/transit_build_speed = 5 + var/plumbing_build_speed = 5 var/destroy_speed = 5 var/paint_speed = 5 var/category = ATMOS_CATEGORY var/piping_layer = PIPING_LAYER_DEFAULT + var/ducting_layer = DUCT_LAYER_DEFAULT var/datum/pipe_info/recipe var/static/datum/pipe_info/first_atmos var/static/datum/pipe_info/first_disposal var/static/datum/pipe_info/first_transit var/mode = BUILD_MODE | DESTROY_MODE | WRENCH_MODE + var/static/datum/pipe_info/first_plumbing + var/locked = FALSE //wheter we can change categories. Useful for the plumber /obj/item/pipe_dispenser/New() . = ..() @@ -238,29 +259,30 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1) return(BRUTELOSS) -/obj/item/pipe_dispenser/ui_base_html(html) - var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes) - . = replacetext(html, "", assets.css_tag()) +/obj/item/pipe_dispenser/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/pipes), + ) -/obj/item/pipe_dispenser/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes) - assets.send(user) - - ui = new(user, src, ui_key, "rpd", name, 425, 472, master_ui, state) + ui = new(user, src, "RapidPipeDispenser", name) ui.open() /obj/item/pipe_dispenser/ui_data(mob/user) var/list/data = list( "category" = category, "piping_layer" = piping_layer, + + "ducting_layer" = ducting_layer, + "preview_rows" = recipe.get_preview(p_dir), "categories" = list(), "selected_color" = paint_color, "paint_colors" = GLOB.pipe_paint_colors, - "mode" = mode + "mode" = mode, + "locked" = locked ) var/list/recipes @@ -271,6 +293,8 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( recipes = GLOB.disposal_pipe_recipes if(TRANSIT_CATEGORY) recipes = GLOB.transit_tube_recipes + if(PLUMBING_CATEGORY) + recipes = GLOB.fluid_duct_recipes for(var/c in recipes) var/list/cat = recipes[c] var/list/r = list() @@ -284,7 +308,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( /obj/item/pipe_dispenser/ui_act(action, params) if(..()) return - if(!usr.canUseTopic(src)) + if(!usr.canUseTopic(src, BE_CLOSE)) return var/playeffect = TRUE switch(action) @@ -299,11 +323,16 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( recipe = first_atmos if(TRANSIT_CATEGORY) recipe = first_transit + if(PLUMBING_CATEGORY) + recipe = first_plumbing p_dir = NORTH playeffect = FALSE if("piping_layer") piping_layer = text2num(params["piping_layer"]) playeffect = FALSE + // if("ducting_layer") + // ducting_layer = text2num(params["ducting_layer"]) + // playeffect = FALSE if("pipe_type") var/static/list/recipes if(!recipes) @@ -320,11 +349,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( mode &= ~n else mode |= n - - if(playeffect && world.time >= effectcooldown) + if(playeffect) spark_system.start() - effectcooldown = world.time + 100 - playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0) + playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE) return TRUE /obj/item/pipe_dispenser/pre_attack(atom/A, mob/user) @@ -469,16 +496,56 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( if(mode & WRENCH_MODE) tube.wrench_act(user, src) return - + if(PLUMBING_CATEGORY) //Plumbing. + if(!can_make_pipe) + return ..() + A = get_turf(A) + if(isclosedturf(A)) + to_chat(user, "[src]'s error light flickers; there's something in the way!") + return + to_chat(user, "You start building a fluid duct...") + playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1) + if(do_after(user, plumbing_build_speed, target = A)) + var/obj/machinery/duct/D + if(recipe.type == /datum/pipe_info/plumbing/multilayer) + var/temp_connects = NORTH + SOUTH + if(queued_p_dir == EAST) + temp_connects = EAST + WEST + D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer, temp_connects) + else + D = new queued_p_type (A, TRUE, GLOB.pipe_paint_colors[paint_color], ducting_layer) + D.add_fingerprint(usr) + if(mode & WRENCH_MODE) + D.wrench_act(user, src) else return ..() /obj/item/pipe_dispenser/proc/activate() playsound(get_turf(src), 'sound/items/deconstruct.ogg', 50, 1) +/* unneeded, you can craft ducts from plastic +/obj/item/pipe_dispenser/plumbing + name = "Plumberinator" + desc = "A crude device to rapidly plumb things." + icon_state = "plumberer" + category = PLUMBING_CATEGORY + locked = TRUE + +/obj/item/pipe_dispenser/plumbing/Initialize() + . = ..() + spark_system = new + spark_system.set_up(5, 0, src) + spark_system.attach(src) + if(!first_plumbing) + first_plumbing = GLOB.fluid_duct_recipes[GLOB.fluid_duct_recipes[1]][1] + + recipe = first_plumbing + +*/ #undef ATMOS_CATEGORY #undef DISPOSALS_CATEGORY #undef TRANSIT_CATEGORY +#undef PLUMBING_CATEGORY #undef BUILD_MODE #undef DESTROY_MODE diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm index 01b351edd0..8fd2ed2377 100644 --- a/code/game/objects/items/RSF.dm +++ b/code/game/objects/items/RSF.dm @@ -26,6 +26,7 @@ RSF /obj/item/rsf/cyborg matter = 30 + /obj/item/rsf/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/rcd_ammo)) if((matter + 10) > 30) @@ -64,15 +65,16 @@ RSF return if (!(istype(A, /obj/structure/table) || isfloorturf(A))) return - - if(matter < 1) - to_chat(user, "\The [src] doesn't have enough matter left.") - return if(iscyborg(user)) + matter = 30 //borgs dont actually use the matter so this is mostly just so it doesnt fail the next check incase of shennanigans var/mob/living/silicon/robot/R = user if(!R.cell || R.cell.charge < 200) to_chat(user, "You do not have enough power to use [src].") return + if(matter < 1) + to_chat(user, "\The [src] doesn't have enough matter left.") + return + var/turf/T = get_turf(A) playsound(src.loc, 'sound/machines/click.ogg', 10, 1) @@ -91,7 +93,7 @@ RSF use_matter(50, user) if(4) to_chat(user, "Dispensing Dice Pack...") - new /obj/item/storage/pill_bottle/dice(T) + new /obj/item/storage/box/dice(T) use_matter(200, user) if(5) to_chat(user, "Dispensing Cigarette...") diff --git a/code/game/objects/items/airlock_painter.dm b/code/game/objects/items/airlock_painter.dm index c9a31a48c2..b28de437ed 100644 --- a/code/game/objects/items/airlock_painter.dm +++ b/code/game/objects/items/airlock_painter.dm @@ -180,10 +180,10 @@ 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) +/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "decal_painter", name, 500, 400, master_ui, state) + ui = new(user, src, "DecalPainter", name) ui.open() /obj/item/airlock_painter/decal/ui_data(mob/user) @@ -233,4 +233,4 @@ /obj/item/airlock_painter/decal/debug/Initialize() . = ..() - ink = new /obj/item/toner/extreme(src) \ No newline at end of file + ink = new /obj/item/toner/extreme(src) diff --git a/code/game/objects/items/armor_kits.dm b/code/game/objects/items/armor_kits.dm new file mode 100644 index 0000000000..fa88b77600 --- /dev/null +++ b/code/game/objects/items/armor_kits.dm @@ -0,0 +1,44 @@ +// Armor kits! Reinforcing uniforms to maintain fashion and also armor capabilities. + +/obj/item/armorkit + name = "durathread armor kit" + desc = "A glorified sewing kit with durathread sheets, thread, and a titanium needle, for reinforcing jumpsuits and uniforms." + icon = 'icons/obj/clothing/reinf_kits.dmi' + w_class = WEIGHT_CLASS_SMALL + icon_state = "durathread_kit" // shoutout to my guy Toriate for being good at sprites tho + +/obj/item/armorkit/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + // yeah have fun making subtypes and modifying the afterattack if you want to make variants + // idiot + // - hatter + var/used = FALSE + + if(isobj(target) && istype(target, /obj/item/clothing/under)) + var/obj/item/clothing/under/C = target + if(C.armor.melee < 10) + C.armor.melee = 10 + used = TRUE + if(C.armor.laser < 10) + C.armor.laser = 10 + used = TRUE + if(C.armor.fire < 40) + C.armor.fire = 40 + used = TRUE + if(C.armor.acid < 10) + C.armor.acid = 10 + used = TRUE + if(C.armor.bomb < 5) + C.armor.bomb = 5 + used = TRUE + + if(used) + user.visible_message("[user] uses [src] on [C], reinforcing it and tossing the empty case away afterwards.", \ + "You reinforce [C] with [src], making it a little more protective! You toss the empty casing away afterwards.") + C.name = "durathread [C.name]" // this disappears if it gets repaired, which is annoying + qdel(src) + return + else + to_chat(user, "You stare at [src] and [C], coming to the conclusion that you probably don't need to reinforce it any further.") + return + else + return diff --git a/code/game/objects/items/binoculars.dm b/code/game/objects/items/binoculars.dm new file mode 100644 index 0000000000..347f0ad3a7 --- /dev/null +++ b/code/game/objects/items/binoculars.dm @@ -0,0 +1,65 @@ +/obj/item/binoculars + name = "binoculars" + desc = "Used for long-distance surveillance." + item_state = "binoculars" + icon_state = "binoculars" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + slot_flags = ITEM_SLOT_BELT + w_class = WEIGHT_CLASS_SMALL + var/mob/listeningTo + var/zoom_out_amt = 6 + var/zoom_amt = 10 + +/obj/item/binoculars/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/binoculars/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12) + +/obj/item/binoculars/Destroy() + listeningTo = null + return ..() + +/obj/item/binoculars/proc/on_wield(obj/item/source, mob/user) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield) + listeningTo = user + user.visible_message("[user] holds [src] up to [user.p_their()] eyes.", "You hold [src] up to your eyes.") + item_state = "binoculars_wielded" + user.regenerate_icons() + if(!user?.client) + return + var/client/C = user.client + var/_x = 0 + var/_y = 0 + switch(user.dir) + if(NORTH) + _y = zoom_amt + if(EAST) + _x = zoom_amt + if(SOUTH) + _y = -zoom_amt + if(WEST) + _x = -zoom_amt + C.change_view(world.view + zoom_out_amt) + C.pixel_x = world.icon_size*_x + C.pixel_y = world.icon_size*_y +/obj/item/binoculars/proc/on_unwield(obj/item/source, mob/user) + unwield(user) + +/obj/item/binoculars/proc/unwield(mob/user) + if(listeningTo) + UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) + listeningTo = null + user.visible_message("[user] lowers [src].", "You lower [src].") + item_state = "binoculars" + user.regenerate_icons() + if(user && user.client) + user.regenerate_icons() + var/client/C = user.client + C.change_view(CONFIG_GET(string/default_view)) + user.client.pixel_x = 0 + user.client.pixel_y = 0 diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index dbc66b1899..428efe4abe 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -71,8 +71,6 @@ if(user.incapacitated()) to_chat(user, "You can't get out while you're restrained like this!") return - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT to_chat(user, "You claw at the fabric of [src], trying to tear it open...") to_chat(loc, "Someone starts trying to break free of [src]!") if(!do_after(user, 200, target = src)) diff --git a/code/game/objects/items/broom.dm b/code/game/objects/items/broom.dm new file mode 100644 index 0000000000..225644109f --- /dev/null +++ b/code/game/objects/items/broom.dm @@ -0,0 +1,69 @@ +/obj/item/broom + name = "broom" + desc = "This is my BROOMSTICK! It can be used manually or braced with two hands to sweep items as you move. It has a telescopic handle for compact storage." + icon = 'icons/obj/janitor.dmi' + icon_state = "broom0" + lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi' + force = 8 + throwforce = 10 + throw_speed = 3 + throw_range = 7 + w_class = WEIGHT_CLASS_NORMAL + attack_verb = list("swept", "brushed off", "bludgeoned", "whacked") + resistance_flags = FLAMMABLE + +/obj/item/broom/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/broom/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12, icon_wielded="broom1") + +/obj/item/broom/update_icon_state() + icon_state = "broom0" + +/// triggered on wield of two handed item +/obj/item/broom/proc/on_wield(obj/item/source, mob/user) + to_chat(user, "You brace the [src] against the ground in a firm sweeping stance.") + RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/sweep) + +/// triggered on unwield of two handed item +/obj/item/broom/proc/on_unwield(obj/item/source, mob/user) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + +/obj/item/broom/afterattack(atom/A, mob/user, proximity) + . = ..() + if(!proximity) + return + sweep(user, A, FALSE) + +/obj/item/broom/proc/sweep(mob/user, atom/A, moving = TRUE) + var/turf/target + if (!moving) + if (isturf(A)) + target = A + else + target = A.loc + else + target = user.loc + if (!isturf(target)) + return + if (locate(/obj/structure/table) in target.contents) + return + var/i = 0 + for(var/obj/item/garbage in target.contents) + if(!garbage.anchored) + garbage.Move(get_step(target, user.dir), user.dir) + i++ + if(i >= 20) + break + if(i >= 1) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 30, TRUE, -1) + +/obj/item/broom/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J) //bless you whoever fixes this copypasta + J.put_in_cart(src, user) + J.mybroom=src + J.update_icon() diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm index 6648db46c4..a8ff7b9004 100644 --- a/code/game/objects/items/cardboard_cutouts.dm +++ b/code/game/objects/items/cardboard_cutouts.dm @@ -6,6 +6,8 @@ icon_state = "cutout_basic" w_class = WEIGHT_CLASS_BULKY resistance_flags = FLAMMABLE + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE /// 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 @@ -43,8 +45,7 @@ "Monkey" = image(icon = src.icon, icon_state = "cutout_monky"), )) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/cardboard_cutout/attack_hand(mob/living/user) +/obj/item/cardboard_cutout/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.a_intent == INTENT_HELP || pushed_over) return ..() user.visible_message("[user] pushes over [src]!", "You push over [src]!") @@ -81,7 +82,6 @@ else if(I.hitsound) playsound(loc, I.hitsound, get_clamped_volume(), 1, -1) - user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) if(I.force) diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 58d907e14b..5b1b86b9e4 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -113,6 +113,26 @@ . = ..() . += "It has [uses ? uses : "no"] charges left." +/obj/item/card/id/examine_more(mob/user) + var/list/msg = list("You examine [src] closer, and note the following...") + + if(mining_points) + msg += "There's [mining_points] mining equipment redemption point\s loaded onto this card." + if(registered_account) + msg += "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) + msg += "The [D.account_holder] reports a balance of [D.account_balance] cr." + msg += "Alt-Click the ID to pull money from the linked account in the form of holochips." + msg += "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) + msg += "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 + msg += "There is no registered account linked to this card. Alt-Click to add one." + + return msg + /obj/item/card/emag/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/emagrecharge)) var/obj/item/emagrecharge/ER = W @@ -204,7 +224,7 @@ . = ..() if(.) switch(var_name) - if("assignment","registered_name") + if(NAMEOF(src, assignment),NAMEOF(src, registered_name)) //,NAMEOF(src, registered_age)) update_label() /obj/item/card/id/attack_self(mob/user) @@ -230,15 +250,13 @@ return ..() /obj/item/card/id/proc/insert_money(obj/item/I, mob/user, physical_currency) + if(!registered_account) + to_chat(user, "[src] doesn't have a linked account to deposit [I] into!") + return 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.") @@ -249,17 +267,20 @@ qdel(I) /obj/item/card/id/proc/mass_insert_money(list/money, mob/user) + if(!registered_account) + to_chat(user, "[src] doesn't have a linked account to deposit into!") + return FALSE + 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 += physical_money.get_item_credit_value() + CHECK_TICK - total += cash_money - - registered_account.adjust_money(cash_money) + registered_account.adjust_money(total) QDEL_LIST(money) diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/chainsaw.dm new file mode 100644 index 0000000000..ebb26fab93 --- /dev/null +++ b/code/game/objects/items/chainsaw.dm @@ -0,0 +1,89 @@ + +// CHAINSAW +/obj/item/chainsaw + name = "chainsaw" + desc = "A versatile power tool. Useful for limbing trees and delimbing humans." + icon_state = "chainsaw_off" + lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' + flags_1 = CONDUCT_1 + force = 13 + var/force_on = 24 + w_class = WEIGHT_CLASS_HUGE + throwforce = 13 + throw_speed = 2 + throw_range = 4 + custom_materials = list(/datum/material/iron=13000) + attack_verb = list("sawed", "torn", "cut", "chopped", "diced") + hitsound = "swing_hit" + sharpness = SHARP_EDGED + actions_types = list(/datum/action/item_action/startchainsaw) + tool_behaviour = TOOL_SAW + toolspeed = 0.5 + var/on = FALSE + var/wielded = FALSE // track wielded status on item + +/obj/item/chainsaw/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/chainsaw/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 30, 100, 0, 'sound/weapons/chainsawhit.ogg', TRUE) + AddComponent(/datum/component/two_handed, require_twohands=TRUE) + AddElement(/datum/element/update_icon_updates_onmob) + +/// triggered on wield of two handed item +/obj/item/chainsaw/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/chainsaw/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/chainsaw/suicide_act(mob/living/carbon/user) + if(on) + user.visible_message("[user] begins to tear [user.p_their()] head off with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(src, 'sound/weapons/chainsawhit.ogg', 100, 1) + var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD) + if(myhead) + myhead.dismember() + else + user.visible_message("[user] smashes [src] into [user.p_their()] neck, destroying [user.p_their()] esophagus! It looks like [user.p_theyre()] trying to commit suicide!") + playsound(src, 'sound/weapons/genhit1.ogg', 100, 1) + return(BRUTELOSS) + +/obj/item/chainsaw/attack_self(mob/user) + on = !on + to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]") + force = on ? force_on : initial(force) + throwforce = on ? force_on : force + update_icon() + var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering) + butchering.butchering_enabled = on + + if(on) + hitsound = 'sound/weapons/chainsawhit.ogg' + else + hitsound = "swing_hit" + +/obj/item/chainsaw/update_icon_state() + icon_state = "chainsaw_[on ? "on" : "off"]" + +/obj/item/chainsaw/doomslayer + name = "THE GREAT COMMUNICATOR" + desc = "VRRRRRRR!!!" + armour_penetration = 100 + force_on = 30 + +/obj/item/chainsaw/doomslayer/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = 100 + return ..() + +/obj/item/chainsaw/doomslayer/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(attack_type & ATTACK_TYPE_PROJECTILE) + owner.visible_message("Ranged attacks just make [owner] angrier!") + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return ..() diff --git a/code/game/objects/items/chromosome.dm b/code/game/objects/items/chromosome.dm index 1340e7f35b..8330a8e202 100644 --- a/code/game/objects/items/chromosome.dm +++ b/code/game/objects/items/chromosome.dm @@ -53,32 +53,32 @@ /obj/item/chromosome/stabilizer name = "stabilizer chromosome" - desc = "A chromosome that adjusts to the body to reduce genetic damage by 20%." + desc = "A chromosome that reduces mutation instability by 20%." icon_state = "stabilizer" stabilizer_coeff = 0.8 weight = 1 /obj/item/chromosome/synchronizer name = "synchronizer chromosome" - desc = "A chromosome that gives the mind more controle over the mutation, reducing knockback and downsides by 50%." + desc = "A chromosome that reduces mutation knockback and downsides by 50%." icon_state = "synchronizer" synchronizer_coeff = 0.5 /obj/item/chromosome/power name = "power chromosome" - desc = "A power chromosome for boosting certain mutation's power by 50%." + desc = "A chromosome that increases mutation power by 50%." icon_state = "power" power_coeff = 1.5 /obj/item/chromosome/energy name = "energetic chromosome" - desc = "A chromosome that reduces cooldown on action based mutations by 50%." + desc = "A chromosome that reduces action based mutation cooldowns by by 50%." icon_state = "energy" energy_coeff = 0.5 /obj/item/chromosome/reinforcer name = "reinforcement chromosome" - desc = "Renders the mutation immune to mutadone." + desc = "A chromosome that renders mutations immune to mutadone." icon_state = "reinforcer" weight = 3 diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm index 766c3d8636..16bc6897c8 100644 --- a/code/game/objects/items/chrono_eraser.dm +++ b/code/game/objects/items/chrono_eraser.dm @@ -246,9 +246,9 @@ /obj/effect/chrono_field/return_air() //we always have nominal air and temperature var/datum/gas_mixture/GM = new - GM.gases[/datum/gas/oxygen] = MOLES_O2STANDARD - GM.gases[/datum/gas/nitrogen] = MOLES_N2STANDARD - GM.temperature = T20C + GM.set_moles(/datum/gas/oxygen, MOLES_O2STANDARD) + GM.set_moles(/datum/gas/nitrogen, MOLES_N2STANDARD) + GM.set_temperature(T20C) return GM /obj/effect/chrono_field/Move() diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index bfbacb1a34..de32375642 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -794,6 +794,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM reagents.clear_reagents() /obj/item/clothing/mask/vape/equipped(mob/user, slot) + . = ..() if(slot == SLOT_WEAR_MASK) if(!screw) to_chat(user, "You start puffing on the vape.") diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index f94c8f3513..2fa48582f7 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -116,9 +116,9 @@ build_path = /obj/machinery/computer/cloning var/list/records = list() -/obj/item/circuitboard/computer/prototype_cloning +/obj/item/circuitboard/computer/cloning/prototype name = "Prototype Cloning (Computer Board)" - build_path = /obj/machinery/computer/prototype_cloning + build_path = /obj/machinery/computer/cloning/prototype /obj/item/circuitboard/computer/arcade/battle name = "Arcade Battle (Computer Board)" diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm index ea839ae12d..37d19783b5 100644 --- a/code/game/objects/items/circuitboards/machine_circuitboards.dm +++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm @@ -48,6 +48,13 @@ /obj/item/stack/cable_coil = 5, /obj/item/stack/sheet/glass = 1) +/obj/item/circuitboard/machine/medipen_refiller + name = "Medipen Refiller (Machine Board)" + icon_state = "medical" + build_path = /obj/machinery/medipen_refiller + req_components = list( + /obj/item/stock_parts/matter_bin = 1) + /obj/item/circuitboard/machine/clonepod name = "Clone Pod (Machine Board)" build_path = /obj/machinery/clonepod @@ -61,6 +68,14 @@ name = "Experimental Clone Pod (Machine Board)" build_path = /obj/machinery/clonepod/experimental +/obj/item/circuitboard/machine/sheetifier + name = "Sheet-meister 2000 (Machine Board)" + icon_state = "supply" + build_path = /obj/machinery/sheetifier + req_components = list( + /obj/item/stock_parts/manipulator = 2, + /obj/item/stock_parts/matter_bin = 2) + /obj/item/circuitboard/machine/abductor name = "alien board (Report This)" icon_state = "abductor_mod" @@ -504,6 +519,10 @@ /obj/item/stack/sheet/glass = 1) needs_anchored = FALSE +/obj/item/circuitboard/machine/hydroponics/automagic + name = "Automatic Hydroponics Tray (Machine Board)" + build_path = /obj/machinery/hydroponics/constructable/automagic + /obj/item/circuitboard/machine/seed_extractor name = "Seed Extractor (Machine Board)" build_path = /obj/machinery/seed_extractor diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 050427702d..f5477ae5f6 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -88,6 +88,7 @@ var/obj/effect/decal/cleanable/C = locate() in target qdel(C) target.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) + target.clean_blood() SEND_SIGNAL(target, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) target.wash_cream() return @@ -180,4 +181,4 @@ name = "Canned Laughter" desc = "Just looking at this makes you want to giggle." icon_state = "laughter" - list_reagents = list(/datum/reagent/consumable/laughter = 50) \ No newline at end of file + list_reagents = list(/datum/reagent/consumable/laughter = 50) diff --git a/code/game/objects/items/cosmetics.dm b/code/game/objects/items/cosmetics.dm index 4dcaed2cf7..592f238cec 100644 --- a/code/game/objects/items/cosmetics.dm +++ b/code/game/objects/items/cosmetics.dm @@ -188,4 +188,4 @@ else ..() else - ..() \ No newline at end of file + ..() diff --git a/code/game/objects/items/courtroom.dm b/code/game/objects/items/courtroom.dm index c0e81ed3d5..13b83c9425 100644 --- a/code/game/objects/items/courtroom.dm +++ b/code/game/objects/items/courtroom.dm @@ -32,6 +32,6 @@ if(istype(I, /obj/item/gavelhammer)) playsound(loc, 'sound/items/gavel.ogg', 100, 1) user.visible_message("[user] strikes [src] with [I].") - user.changeNext_move(CLICK_CD_MELEE) + return TRUE else - return ..() \ No newline at end of file + return ..() diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index a4ed8dedd1..7f8b720509 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -147,23 +147,23 @@ to_chat(user, "There is not enough of [src] left!") . = TRUE -/obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) - // tgui is a plague upon this codebase +/obj/item/toy/crayon/ui_state(mob/user) + return GLOB.hands_state - SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/toy/crayon/ui_interact(mob/user, datum/tgui/ui) + // tgui is a plague upon this codebase + // no u + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "crayon", name, 600, 600, - master_ui, state) + ui = new(user, src, "Crayon", name) ui.open() /obj/item/toy/crayon/spraycan/AltClick(mob/user) - . = ..() if(user.canUseTopic(src, BE_CLOSE, ismonkey(user))) if(has_cap) is_capped = !is_capped to_chat(user, "The cap on [src] is now [is_capped ? "on" : "off"].") update_icon() - return TRUE /obj/item/toy/crayon/CtrlClick(mob/user) if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user))) @@ -273,7 +273,9 @@ . = ..() if(!proximity || !check_allowed_items(target)) return + draw_on(target, user, proximity, params) +/obj/item/toy/crayon/proc/draw_on(atom/target, mob/user, proximity, params) var/static/list/punctuation = list("!","?",".",",","/","+","-","=","%","#","&") var/cost = 1 @@ -568,9 +570,9 @@ dye_color = DYE_RAINBOW charges = -1 -/obj/item/toy/crayon/rainbow/afterattack(atom/target, mob/user, proximity, params) +/obj/item/toy/crayon/rainbow/draw_on(atom/target, mob/user, proximity, params) paint_color = rgb(rand(0,255), rand(0,255), rand(0,255)) - . = ..() + return ..() /* * Crayon Box @@ -693,7 +695,7 @@ . += "It is empty." . += "Alt-click [src] to [ is_capped ? "take the cap off" : "put the cap on"]." -/obj/item/toy/crayon/spraycan/afterattack(atom/target, mob/user, proximity, params) +/obj/item/toy/crayon/spraycan/draw_on(atom/target, mob/user, proximity, params) if(!proximity) return @@ -737,12 +739,7 @@ to_chat(usr, "A color that dark on an object like this? Surely not...") return FALSE - - if(istype(target, /obj/structure/window)) - var/obj/structure/window/W = target - W.spraycan_paint(paint_color) - else - target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) + target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) . = use_charges(user, 2) var/fraction = min(1, . / reagents.maximum_volume) @@ -771,7 +768,7 @@ desc = "A metallic container containing shiny synthesised paint." charges = -1 -/obj/item/toy/crayon/spraycan/borg/afterattack(atom/target,mob/user,proximity, params) +/obj/item/toy/crayon/spraycan/borg/draw_on(atom/target,mob/user,proximity, params) var/diff = ..() if(!iscyborg(user)) to_chat(user, "How did you get this?") diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 7cc76da312..767f8fc395 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -19,7 +19,7 @@ var/on = FALSE //if the paddles are equipped (1) or on the defib (0) var/safety = TRUE //if you can zap people with the defibs on harm mode var/powered = FALSE //if there's a cell in the defib with enough power for a revive, blocks paddles from reviving otherwise - var/obj/item/twohanded/shockpaddles/paddles + var/obj/item/shockpaddles/paddles var/obj/item/stock_parts/cell/cell var/combat = FALSE //can we revive through space suits? var/grab_ghost = FALSE // Do we pull the ghost back into their body? @@ -77,8 +77,7 @@ /obj/item/defibrillator/ui_action_click() toggle_paddles() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/defibrillator/attack_hand(mob/user) +/obj/item/defibrillator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user) if(slot_flags == ITEM_SLOT_BACK) if(user.get_item_by_slot(SLOT_BACK) == src) @@ -106,7 +105,6 @@ /obj/item/defibrillator/attackby(obj/item/W, mob/user, params) if(W == paddles) - paddles.unwield() toggle_paddles() else if(istype(W, /obj/item/stock_parts/cell)) var/obj/item/stock_parts/cell/C = W @@ -170,7 +168,6 @@ return else //Remove from their hands and back onto the defib unit - paddles.unwield() remove_paddles(user) update_power() @@ -179,7 +176,7 @@ A.UpdateButtonIcon() /obj/item/defibrillator/proc/make_paddles() - return new /obj/item/twohanded/shockpaddles(src) + return new /obj/item/shockpaddles(src) /obj/item/defibrillator/equipped(mob/user, slot) ..() @@ -256,13 +253,12 @@ /obj/item/defibrillator/compact/combat/loaded/attackby(obj/item/W, mob/user, params) if(W == paddles) - paddles.unwield() toggle_paddles() return //paddles -/obj/item/twohanded/shockpaddles +/obj/item/shockpaddles name = "defibrillator paddles" desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks." icon = 'icons/obj/items_and_weapons.dmi' @@ -284,24 +280,48 @@ var/grab_ghost = FALSE var/tlimit = DEFIB_TIME_LIMIT * 10 var/disarm_shock_time = 10 + var/wielded = FALSE // track wielded status on item - var/mob/listeningTo +/obj/item/shockpaddles/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + if(!req_defib) + return //If it doesn't need a defib, just say it exists + if (!loc || !istype(loc, /obj/item/defibrillator)) //To avoid weird issues from admin spawns + return INITIALIZE_HINT_QDEL + defib = loc + busy = FALSE + update_icon() -/obj/item/twohanded/shockpaddles/ComponentInitialize() +/obj/item/shockpaddles/ComponentInitialize() . = ..() AddElement(/datum/element/update_icon_updates_onmob) + AddComponent(/datum/component/two_handed, force_unwielded=8, force_wielded=12) -/obj/item/twohanded/shockpaddles/equipped(mob/user, slot) +/// triggered on wield of two handed item +/obj/item/shockpaddles/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/shockpaddles/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/shockpaddles/Destroy() + defib = null + return ..() + +/obj/item/shockpaddles/equipped(mob/user, slot) . = ..() if(!req_defib) return RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/check_range) -/obj/item/twohanded/shockpaddles/Moved() +/obj/item/shockpaddles/Moved() . = ..() check_range() -/obj/item/twohanded/shockpaddles/proc/check_range() +/obj/item/shockpaddles/proc/check_range() if(!req_defib || !defib) return if(!in_range(src,defib)) @@ -312,7 +332,7 @@ visible_message("[src] snap back into [defib].") snap_back() -/obj/item/twohanded/shockpaddles/proc/recharge(var/time) +/obj/item/shockpaddles/proc/recharge(var/time) if(req_defib || !time) return cooldown = TRUE @@ -324,57 +344,36 @@ cooldown = FALSE update_icon() -/obj/item/twohanded/shockpaddles/New(mainunit) - ..() - if(check_defib_exists(mainunit, src) && req_defib) - defib = mainunit - forceMove(defib) - busy = FALSE - update_icon() - -/obj/item/twohanded/shockpaddles/update_icon_state() - icon_state = "defibpaddles[wielded]" - item_state = "defibpaddles[wielded]" - if(cooldown) - icon_state = "defibpaddles[wielded]_cooldown" - -/obj/item/twohanded/shockpaddles/suicide_act(mob/user) +/obj/item/shockpaddles/suicide_act(mob/user) user.visible_message("[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide!") if(req_defib) defib.deductcharge(revivecost) playsound(src, 'sound/machines/defib_zap.ogg', 50, 1, -1) return (OXYLOSS) -/obj/item/twohanded/shockpaddles/dropped(mob/user) +/obj/item/shockpaddles/update_icon_state() + icon_state = "defibpaddles[wielded]" + item_state = "defibpaddles[wielded]" + if(cooldown) + icon_state = "defibpaddles[wielded]_cooldown" + +/obj/item/shockpaddles/dropped(mob/user) if(!req_defib) return ..() if(user) UnregisterSignal(user, COMSIG_MOVABLE_MOVED) - var/obj/item/twohanded/offhand/O = user.get_inactive_held_item() - if(istype(O)) - O.unwield() if(user != loc) to_chat(user, "The paddles snap back into the main unit.") snap_back() - return unwield(user) -/obj/item/twohanded/shockpaddles/proc/snap_back() +/obj/item/shockpaddles/proc/snap_back() if(!defib) return defib.on = FALSE forceMove(defib) defib.update_power() -/obj/item/twohanded/shockpaddles/proc/check_defib_exists(mainunit, mob/living/carbon/M, obj/O) - if(!req_defib) - return TRUE //If it doesn't need a defib, just say it exists - if (!mainunit || !istype(mainunit, /obj/item/defibrillator)) //To avoid weird issues from admin spawns - qdel(O) - return FALSE - else - return TRUE - -/obj/item/twohanded/shockpaddles/attack(mob/M, mob/user) +/obj/item/shockpaddles/attack(mob/M, mob/user) if(busy) return @@ -426,7 +425,7 @@ do_help(H, user) -/obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H) +/obj/item/shockpaddles/proc/shock_touching(dmg, mob/H) if(!H.pulledby || !isliving(H.pulledby)) return if(req_defib && defib.pullshocksafely) @@ -437,7 +436,7 @@ M.visible_message("[M] is electrocuted by [M.p_their()] contact with [H]!") M.emote("scream") -/obj/item/twohanded/shockpaddles/proc/do_disarm(mob/living/M, mob/living/user) +/obj/item/shockpaddles/proc/do_disarm(mob/living/M, mob/living/user) if(req_defib && defib.safety) return if(!req_defib && !combat) @@ -465,7 +464,7 @@ else recharge(60) -/obj/item/twohanded/shockpaddles/proc/do_harm(mob/living/carbon/H, mob/living/user) +/obj/item/shockpaddles/proc/do_harm(mob/living/carbon/H, mob/living/user) if(req_defib && defib.safety) return if(!req_defib && !combat) @@ -520,7 +519,7 @@ busy = FALSE update_icon() -/obj/item/twohanded/shockpaddles/proc/do_help(mob/living/carbon/H, mob/living/user) +/obj/item/shockpaddles/proc/do_help(mob/living/carbon/H, mob/living/user) user.visible_message("[user] begins to place [src] on [H]'s chest.", "You begin to place [src] on [H]'s chest...") busy = TRUE update_icon() @@ -619,6 +618,13 @@ if(req_defib) if(defib.healdisk) H.heal_overall_damage(25, 25) + var/list/policies = CONFIG_GET(keyed_list/policyconfig) + var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) + var/late = timelimit && (tplus > timelimit) + var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT] + if(policy) + to_chat(H, policy) + H.log_message("revived using a defibrillator, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME) if(req_defib) defib.deductcharge(revivecost) cooldown = 1 @@ -677,14 +683,14 @@ return TRUE return ..() -/obj/item/twohanded/shockpaddles/cyborg +/obj/item/shockpaddles/cyborg name = "cyborg defibrillator paddles" icon = 'icons/obj/items_and_weapons.dmi' icon_state = "defibpaddles0" item_state = "defibpaddles0" req_defib = FALSE -/obj/item/twohanded/shockpaddles/cyborg/attack(mob/M, mob/user) +/obj/item/shockpaddles/cyborg/attack(mob/M, mob/user) if(iscyborg(user)) var/mob/living/silicon/robot/R = user if(R.emagged) @@ -696,7 +702,7 @@ . = ..() -/obj/item/twohanded/shockpaddles/syndicate +/obj/item/shockpaddles/syndicate name = "syndicate defibrillator paddles" desc = "A pair of paddles used to revive deceased operatives. It possesses both the ability to penetrate armor and to deliver powerful shocks offensively." combat = TRUE diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 2dabcca29f..ec68cdb40c 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -437,7 +437,6 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "Unable to obtain a reading.
    " else var/datum/gas_mixture/environment = T.return_air() - var/list/env_gases = environment.gases var/pressure = environment.return_pressure() var/total_moles = environment.total_moles() @@ -445,12 +444,12 @@ GLOBAL_LIST_EMPTY(PDAs) dat += "Air Pressure: [round(pressure,0.1)] kPa
    " if (total_moles) - for(var/id in env_gases) - var/gas_level = env_gases[id]/total_moles + for(var/id in environment.get_gases()) + var/gas_level = environment.get_moles(id)/total_moles if(gas_level > 0) dat += "[GLOB.meta_gas_names[id]]: [round(gas_level*100, 0.01)]%
    " - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " + dat += "Temperature: [round(environment.return_temperature()-T0C)]°C
    " dat += "
    " else//Else it links to the cart menu proc. Although, it really uses menu hub 4--menu 4 doesn't really exist as it simply redirects to hub. dat += cartridge.generate_menu() @@ -1028,6 +1027,7 @@ GLOBAL_LIST_EMPTY(PDAs) else if(is_type_in_list(C, contained_item)) //Checks if there is a pen if(inserted_item) to_chat(user, "There is already \a [inserted_item] in \the [src]!") + return ..() else if(!user.transferItemToLoc(C, src)) return diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index 38b117b132..503e2a9473 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -54,18 +54,20 @@ name = initial(name) icon_state = initial(icon_state) -/obj/item/aicard/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/aicard/ui_state(mob/user) + return GLOB.hands_state + +/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "intellicard", name, 500, 500, master_ui, state) + ui = new(user, src, "Intellicard", name) ui.open() /obj/item/aicard/ui_data() var/list/data = list() if(AI) data["name"] = AI.name - data["laws"] = AI.laws.get_law_list(include_zeroth = 1) + data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE) data["health"] = (AI.health + 100) / 2 data["wireless"] = !AI.control_disabled //todo disabled->enabled data["radio"] = AI.radio_enabled @@ -86,19 +88,19 @@ if(confirm == "Yes" && !..()) flush = TRUE if(AI && AI.loc == src) - to_chat(AI, "Your core files are being wiped!") + to_chat(AI, "Your core files are being wiped!") while(AI.stat != DEAD && flush) - AI.adjustOxyLoss(1) + AI.adjustOxyLoss(5) AI.updatehealth() sleep(5) flush = FALSE . = TRUE if("wireless") AI.control_disabled = !AI.control_disabled - to_chat(AI, "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!") + to_chat(AI, "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!") . = TRUE if("radio") AI.radio_enabled = !AI.radio_enabled - to_chat(AI, "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!") + to_chat(AI, "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!") . = TRUE update_icon() diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm index 57443de973..a45f26062b 100644 --- a/code/game/objects/items/devices/chameleonproj.dm +++ b/code/game/objects/items/devices/chameleonproj.dm @@ -132,8 +132,7 @@ /obj/effect/dummy/chameleon/attackby() master.disrupt() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/dummy/chameleon/attack_hand() +/obj/effect/dummy/chameleon/on_attack_hand() master.disrupt() /obj/effect/dummy/chameleon/attack_animal() diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm index 41a12136ef..1f91196b24 100644 --- a/code/game/objects/items/devices/dogborg_sleeper.dm +++ b/code/game/objects/items/devices/dogborg_sleeper.dm @@ -116,8 +116,6 @@ if(!hound) go_out(user) return - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT if(user.a_intent == INTENT_HELP) return var/voracious = TRUE @@ -165,12 +163,13 @@ return ui_interact(user) -/obj/item/dogborg/sleeper/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) +/obj/item/dogborg/sleeper/ui_state(mob/user) + return GLOB.notcontained_state - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/dogborg/sleeper/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state) + ui = new(user, src, "dogborg_sleeper", name, 375, 550) //UI DOES NOT EXIST ui.open() /obj/item/dogborg/sleeper/ui_data() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index fdc3aa30af..75024aec26 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -183,9 +183,21 @@ var/T = get_turf(target) if(locate(/mob/living) in T) new /obj/effect/temp_visual/medical_holosign(T,user) //produce a holographic glow - holo_cooldown = world.time + 100 + holo_cooldown = world.time + 10 SECONDS return +// see: [/datum/wound/burn/proc/uv()] +/obj/item/flashlight/pen/paramedic + name = "paramedic penlight" + desc = "A high-powered UV penlight intended to help stave off infection in the field on serious burned patients. Probably really bad to look into." + icon_state = "penlight_surgical" + /// Our current UV cooldown + var/uv_cooldown = 0 + /// How long between UV fryings + var/uv_cooldown_length = 1 MINUTES + /// How much sanitization to apply to the burn wound + var/uv_power = 1 + /obj/effect/temp_visual/medical_holosign name = "medical holosign" desc = "A small holographic glow that indicates a medic is coming to treat a patient." diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm index 03ca110ec8..9ef9d73705 100644 --- a/code/game/objects/items/devices/forcefieldprojector.dm +++ b/code/game/objects/items/devices/forcefieldprojector.dm @@ -43,7 +43,7 @@ user.visible_message("[user] projects a forcefield!","You project a forcefield.") var/obj/structure/projected_forcefield/F = new(T, src) current_fields += F - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) /obj/item/forcefield_projector/attack_self(mob/user) if(LAZYLEN(current_fields)) diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm index 5cab9e33de..f5d3014d35 100644 --- a/code/game/objects/items/devices/geiger_counter.dm +++ b/code/game/objects/items/devices/geiger_counter.dm @@ -18,6 +18,7 @@ righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' w_class = WEIGHT_CLASS_SMALL slot_flags = ITEM_SLOT_BELT + rad_flags = RAD_NO_CONTAMINATE custom_materials = list(/datum/material/iron = 150, /datum/material/glass = 150) var/grace = RAD_GRACE_PERIOD diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index 981a811bc3..bb46577702 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -1,4 +1,4 @@ -GLOBAL_LIST_EMPTY(GPS_list) + /obj/item/gps name = "global positioning system" desc = "Helping lost spacemen find their way through the planets since 2016." @@ -8,138 +8,10 @@ GLOBAL_LIST_EMPTY(GPS_list) slot_flags = ITEM_SLOT_BELT obj_flags = UNIQUE_RENAME var/gpstag = "COM0" - var/emped = FALSE - var/tracking = TRUE - var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user. - var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown - -/obj/item/gps/examine(mob/user) - . = ..() - var/turf/curr = get_turf(src) - . += "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])" - . += "Alt-click to switch it [tracking ? "off":"on"]." /obj/item/gps/Initialize() . = ..() - GLOB.GPS_list += src - name = "global positioning system ([gpstag])" - add_overlay("working") - -/obj/item/gps/Destroy() - GLOB.GPS_list -= src - return ..() - -/obj/item/gps/emp_act(severity) - . = ..() - if (. & EMP_PROTECT_SELF) - return - emped = TRUE - cut_overlay("working") - add_overlay("emp") - addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early - SStgui.close_uis(src) //Close the UI control if it is open. - -/obj/item/gps/proc/reboot() - emped = FALSE - cut_overlay("emp") - add_overlay("working") - -/obj/item/gps/AltClick(mob/user) - . = ..() - if(!user.canUseTopic(src, BE_CLOSE)) - return - toggletracking(user) - return TRUE - -/obj/item/gps/proc/toggletracking(mob/user) - if(!user.canUseTopic(src, BE_CLOSE)) - return //user not valid to use gps - if(emped) - to_chat(user, "It's busted!") - return - if(tracking) - cut_overlay("working") - to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.") - tracking = FALSE - else - add_overlay("working") - to_chat(user, "[src] is now tracking, and visible to other GPS devices.") - tracking = TRUE - - -/obj/item/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state. - if(emped) - to_chat(user, "[src] fizzles weakly.") - return - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - // Variable window height, depending on how many GPS units there are - // to show, clamped to relatively safe range. - var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700) - ui = new(user, src, ui_key, "gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height - ui.open() - - ui.set_autoupdate(state = updating) - - -/obj/item/gps/ui_data(mob/user) - var/list/data = list() - data["power"] = tracking - data["tag"] = gpstag - data["updating"] = updating - data["globalmode"] = global_mode - if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed - return data - - var/turf/curr = get_turf(src) - data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])" - data["currentArea"] = "[get_area_name(curr, TRUE)]" - data["currentCoords"] = "[curr.x], [curr.y], [curr.z]" - - var/list/signals = list() - data["signals"] = list() - - for(var/gps in GLOB.GPS_list) - var/obj/item/gps/G = gps - if(G.emped || !G.tracking || G == src) - continue - var/turf/pos = get_turf(G) - if(!global_mode && pos.z != curr.z) - continue - var/list/signal = list() - signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS - signal["coords"] = "[pos.x], [pos.y], [pos.z]" - if(pos.z == curr.z) //Distance/Direction calculations for same z-level only - signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs - signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision. - - signals += list(signal) //Add this signal to the list of signals - data["signals"] = signals - return data - - - -/obj/item/gps/ui_act(action, params) - if(..()) - return - switch(action) - if("rename") - var/a = input("Please enter desired tag.", name, gpstag) as text - a = copytext(sanitize(a), 1, 20) - gpstag = a - . = TRUE - name = "global positioning system ([gpstag])" - - if("power") - toggletracking(usr) - . = TRUE - if("updating") - updating = !updating - . = TRUE - if("globalmode") - global_mode = !global_mode - . = TRUE - + AddComponent(/datum/component/gps/item, gpstag) /obj/item/gps/science icon_state = "gps-s" diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm index 4d0ed362fc..7a8a523a18 100644 --- a/code/game/objects/items/devices/multitool.dm +++ b/code/game/objects/items/devices/multitool.dm @@ -263,3 +263,11 @@ icon = 'icons/obj/advancedtools.dmi' icon_state = "multitool" toolspeed = 0.2 + +/obj/item/multitool/advanced/brass + name = "clockwork multitool" + desc = "A brass...multitool? With three prongs arcing electricity between them. It vibrates subtly in your hand." + icon = 'icons/obj/tools.dmi' + icon_state = "clockitool" + toolspeed = 0.2 + diff --git a/code/game/objects/items/devices/polycircuit.dm b/code/game/objects/items/devices/polycircuit.dm index fb15ce45dc..0308f19b5f 100644 --- a/code/game/objects/items/devices/polycircuit.dm +++ b/code/game/objects/items/devices/polycircuit.dm @@ -11,7 +11,7 @@ /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) +/obj/item/stack/circuit_stack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/mob/living/carbon/human/H = user if(!user.get_inactive_held_item() == src) return ..() diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 5802909201..c3127c246f 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -97,10 +97,7 @@ GLOBAL_LIST_EMPTY(power_sinks) /obj/item/powersink/attack_ai() return -/obj/item/powersink/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/powersink/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) switch(mode) if(DISCONNECTED) ..() diff --git a/code/game/objects/items/devices/radio/electropack.dm b/code/game/objects/items/devices/radio/electropack.dm index e94d14a57d..e65325587c 100644 --- a/code/game/objects/items/devices/radio/electropack.dm +++ b/code/game/objects/items/devices/radio/electropack.dm @@ -16,6 +16,9 @@ var/on = TRUE var/shock_cooldown = FALSE + var/ui_x = 260 + var/ui_y = 137 + /obj/item/electropack/suicide_act(mob/living/carbon/user) user.visible_message("[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!") return (FIRELOSS) @@ -26,10 +29,9 @@ /obj/item/electropack/Destroy() SSradio.remove_object(src, frequency) - . = ..() + return ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/electropack/attack_hand(mob/user) +/obj/item/electropack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) var/mob/living/carbon/C = user if(src == C.back) @@ -37,7 +39,7 @@ return return ..() -/obj/item/electropack/attackby(obj/item/W, mob/living/user, params) +/obj/item/electropack/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/clothing/head/helmet)) var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user) A.icon = 'icons/obj/assemblies.dmi' @@ -57,56 +59,12 @@ else return ..() -/obj/item/electropack/Topic(href, href_list) - var/mob/living/carbon/C = usr - if(usr.stat || usr.restrained() || C.back == src) - return - - if(!usr.canUseTopic(src, BE_CLOSE)) - usr << browse(null, "window=radio") - onclose(usr, "radio") - return - - if(href_list["set"]) - if(href_list["set"] == "freq") - var/new_freq = input(usr, "Input a new receiving frequency", "Electropack Frequency", format_frequency(frequency)) as num|null - if(!usr.canUseTopic(src, BE_CLOSE)) - return - new_freq = unformat_frequency(new_freq) - new_freq = sanitize_frequency(new_freq, TRUE) - set_frequency(new_freq) - - if(href_list["set"] == "code") - var/new_code = input(usr, "Input a new receiving code", "Electropack Code", code) as num|null - if(!usr.canUseTopic(src, BE_CLOSE)) - return - new_code = round(new_code) - new_code = clamp(new_code, 1, 100) - code = new_code - - if(href_list["set"] == "power") - if(!usr.canUseTopic(src, BE_CLOSE)) - return - on = !(on) - icon_state = "electropack[on]" - - if(usr) - attack_self(usr) - - return - -/obj/item/electropack/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - SSradio.add_object(src, frequency, RADIO_SIGNALER) - return - /obj/item/electropack/receive_signal(datum/signal/signal) if(!signal || signal.data["code"] != code) return if(isliving(loc) && on) - if(shock_cooldown == TRUE) + if(shock_cooldown) return shock_cooldown = TRUE addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100) @@ -122,28 +80,59 @@ if(master) master.receive_signal() - return -/obj/item/electropack/ui_interact(mob/user) - if(!ishuman(user)) +/obj/item/electropack/proc/set_frequency(new_frequency) + SSradio.remove_object(src, frequency) + frequency = new_frequency + SSradio.add_object(src, frequency, RADIO_SIGNALER) + +/obj/item/electropack/ui_state(mob/user) + return GLOB.hands_state + +/obj/item/electropack/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Electropack", name) + ui.open() + +/obj/item/electropack/ui_data(mob/user) + var/list/data = list() + data["power"] = on + data["frequency"] = frequency + data["code"] = code + data["minFrequency"] = MIN_FREE_FREQ + data["maxFrequency"] = MAX_FREE_FREQ + return data + +/obj/item/electropack/ui_act(action, params) + if(..()) return - user.set_machine(src) - var/dat = {" - -Turned [on ? "On" : "Off"] - Toggle
    -Frequency/Code for electropack:
    -Frequency: -[format_frequency(src.frequency)] -Set
    + switch(action) + if("power") + on = !on + icon_state = "electropack[on]" + . = TRUE + if("freq") + var/value = unformat_frequency(params["freq"]) + if(value) + frequency = sanitize_frequency(value, TRUE) + set_frequency(frequency) + . = TRUE + if("code") + var/value = text2num(params["code"]) + if(value) + value = round(value) + code = clamp(value, 1, 100) + . = TRUE + if("reset") + if(params["reset"] == "freq") + frequency = initial(frequency) + . = TRUE + else if(params["reset"] == "code") + code = initial(code) + . = TRUE -Code: -[src.code] -Set
    -
    "} - user << browse(dat, "window=radio") - onclose(user, "radio") - return /obj/item/electropack/shockcollar name = "shock collar" @@ -153,7 +142,7 @@ Code: icon_state = "shockcollar" item_state = "shockcollar" body_parts_covered = NECK - slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers + slot_flags = ITEM_SLOT_NECK //no more pocket shockers. Now done without lazyness w_class = WEIGHT_CLASS_SMALL strip_delay = 60 equip_delay_other = 60 @@ -169,22 +158,24 @@ Code: materials = list(/datum/material/iron = 5000, /datum/material/glass =2000) category = list("hacked", "Misc") -/obj/item/electropack/shockcollar/attack_hand(mob/user) +/obj/item/electropack/shockcollar/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) 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 return ..() -/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) +/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) //we have to override this because of text if(!signal || signal.data["code"] != code) return - if(isliving(loc) && on) + if(isliving(loc) && on) //the "on" arg is currently useless + var/mob/living/L = loc + if(!L.get_item_by_slot(SLOT_NECK)) //**properly** stops pocket shockers + return if(shock_cooldown == TRUE) return shock_cooldown = TRUE addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100) - var/mob/living/L = loc step(L, pick(GLOB.cardinals)) to_chat(L, "You feel a sharp shock from the collar!") @@ -204,10 +195,13 @@ Code: if(t) tagname = t name = "[initial(name)] - [t]" + return + if(istype(W, /obj/item/clothing/head/helmet)) //lazy method of denying this + return else return ..() -/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this +/obj/item/electropack/shockcollar/ui_interact(mob/user) //note to src: use tgooey var/dat = {" Frequency/Code for shock collar:
    diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 5728a97dda..6ac2d310a1 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -258,6 +258,9 @@ GLOBAL_LIST_INIT(channel_tokens, list( name = "\proper mini Integrated Subspace Transceiver " subspace_transmission = FALSE +/obj/item/radio/headset/silicon/pai/ComponentInitialize() + . = ..() + AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) /obj/item/radio/headset/silicon/ai name = "\proper Integrated Subspace Transceiver " diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index f4c317c8ba..8657684ff4 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -86,10 +86,7 @@ /obj/item/radio/intercom/attack_ai(mob/user) interact(user) -/obj/item/radio/intercom/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/radio/intercom/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) interact(user) /obj/item/radio/intercom/interact(mob/user) diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 5fe9de75aa..4623a405de 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -107,19 +107,15 @@ else ..() -/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) - . = ..() - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/radio/ui_state(mob/user) + return GLOB.inventory_state + +/obj/item/radio/ui_interact(mob/user, datum/tgui/ui, datum/ui_state/state) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - var/ui_width = 360 - var/ui_height = 106 - if(subspace_transmission) - if(channels.len > 0) - ui_height += 6 + channels.len * 21 - else - ui_height += 24 - ui = new(user, src, ui_key, "radio", name, ui_width, ui_height, master_ui, state) + ui = new(user, src, "Radio", name) + if(state) + ui.set_state(state) ui.open() /obj/item/radio/ui_data(mob/user) diff --git a/code/game/objects/items/devices/reverse_bear_trap.dm b/code/game/objects/items/devices/reverse_bear_trap.dm index 20107373d3..f2a0ea5450 100644 --- a/code/game/objects/items/devices/reverse_bear_trap.dm +++ b/code/game/objects/items/devices/reverse_bear_trap.dm @@ -45,7 +45,7 @@ to_chat(loc, "*ding*") addtimer(CALLBACK(src, .proc/snap), 2) -/obj/item/reverse_bear_trap/attack_hand(mob/user) +/obj/item/reverse_bear_trap/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) var/mob/living/carbon/C = user if(C.get_item_by_slot(SLOT_HEAD) == src) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 28e1e1294f..fae2833c8a 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -10,6 +10,14 @@ NANITE SCANNER GENETICS SCANNER */ + +// Describes the three modes of scanning available for health analyzers +#define SCANMODE_HEALTH 0 +#define SCANMODE_CHEMICAL 1 +#define SCANMODE_WOUND 2 +#define SCANNER_CONDENSED 0 +#define SCANNER_VERBOSE 1 + /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." @@ -80,7 +88,7 @@ GENETICS SCANNER throw_range = 7 custom_materials = list(/datum/material/iron=200) var/mode = 1 - var/scanmode = 0 + var/scanmode = SCANMODE_HEALTH var/advanced = FALSE /obj/item/healthanalyzer/suicide_act(mob/living/carbon/user) @@ -88,37 +96,40 @@ GENETICS SCANNER return BRUTELOSS /obj/item/healthanalyzer/attack_self(mob/user) - if(!scanmode) - to_chat(user, "You switch the health analyzer to scan chemical contents.") - scanmode = 1 - else - to_chat(user, "You switch the health analyzer to check physical health.") - scanmode = 0 + scanmode = (scanmode + 1) % 3 + switch(scanmode) + if(SCANMODE_HEALTH) + to_chat(user, "You switch the health analyzer to check physical health.") + if(SCANMODE_CHEMICAL) + to_chat(user, "You switch the health analyzer to scan chemical contents.") + if(SCANMODE_WOUND) + to_chat(user, "You switch the health analyzer to report extra info on wounds.") /obj/item/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user) + flick("[icon_state]-scan", src) //makes it so that it plays the scan animation upon scanning, including clumsy scanning // Clumsiness/brain damage check if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) - to_chat(user, "You stupidly try to analyze the floor's vitals!") - user.visible_message("[user] has analyzed the floor's vitals!") - var/msg = "*---------*\nAnalyzing results for The floor:\n\tOverall status: Healthy\n" - msg += "Key: Suffocation/Toxin/Burn/Brute\n" - msg += "\tDamage specifics: 0-0-0-0\n" - msg += "Body temperature: ???\n" - msg += "*---------*" - to_chat(user, msg) + user.visible_message("[user] analyzes the floor's vitals!", \ + "You stupidly try to analyze the floor's vitals!") + to_chat(user, "Analyzing results for The floor:\n\tOverall status: Healthy\ + \nKey: Suffocation/Toxin/Burn/Brute\ + \n\tDamage specifics: 0-0-0-0\ + \nBody temperature: ???") return - user.visible_message("[user] has analyzed [M]'s vitals.") + user.visible_message("[user] analyzes [M]'s vitals.", \ + "You analyze [M]'s vitals.") - if(scanmode == 0) + if(scanmode == SCANMODE_HEALTH) healthscan(user, M, mode, advanced) - else if(scanmode == 1) + else if(scanmode == SCANMODE_CHEMICAL) chemscan(user, M) + else + woundscan(user, M, src) add_fingerprint(user) - // Used by the PDA medical scanner too /proc/healthscan(mob/user, mob/living/M, mode = 1, advanced = FALSE) if(isliving(user) && (user.incapacitated() || user.eye_blind)) @@ -402,6 +413,17 @@ GENETICS SCANNER msg += " Intervention recommended.\n" else msg += "\n" + // Wounds + if(iscarbon(M)) + var/mob/living/carbon/C = M + var/list/wounded_parts = C.get_wounded_bodyparts() + for(var/i in wounded_parts) + var/obj/item/bodypart/wounded_part = i + msg += "Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]" + for(var/k in wounded_part.wounds) + var/datum/wound/W = k + msg += "
    Type: [W.name]\nSeverity: [W.severity_text()]\nRecommended Treatment: [W.treat_text]
    \n" // less lines than in woundscan() so we don't overload people trying to get basic med info + msg += "
    \n" for(var/thing in M.diseases) var/datum/disease/D = thing @@ -414,7 +436,7 @@ GENETICS SCANNER var/blood_typepath = C.get_blood_id() if(blood_typepath) if(ishuman(C)) - if(H.bleed_rate) + if(H.is_bleeding()) msg += "Subject is bleeding!\n" var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100) var/blood_type = C.dna.blood_type @@ -505,6 +527,67 @@ GENETICS SCANNER desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy." advanced = TRUE +/// Displays wounds with extended information on their status vs medscanners +/proc/woundscan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/wound/scanner) + if(!istype(patient)) + return + + var/render_list = "" + for(var/i in patient.get_wounded_bodyparts()) + var/obj/item/bodypart/wounded_part = i + render_list += "Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]" + for(var/k in wounded_part.wounds) + var/datum/wound/W = k + render_list += "
    [W.get_scanner_description()]
    \n" + render_list += "
    " + + if(render_list == "") + if(istype(scanner)) + // Only emit the cheerful scanner message if this scan came from a scanner + playsound(scanner, 'sound/machines/ping.ogg', 50, FALSE) + to_chat(user, "\The [scanner] makes a happy ping and briefly displays a smiley face with several exclamation points! It's really excited to report that [patient] has no wounds!") + else + to_chat(user, "No wounds detected in subject.") + else + to_chat(user, jointext(render_list, "")) + +/obj/item/healthanalyzer/wound + name = "first aid analyzer" + icon_state = "adv_spectrometer" + desc = "A prototype MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds, but offers no further insight into the patient's health. You hope the final version is less annoying to read!" + var/next_encouragement + var/greedy + +/obj/item/healthanalyzer/wound/attack_self(mob/user) + if(next_encouragement < world.time) + playsound(src, 'sound/machines/ping.ogg', 50, FALSE) + var/list/encouragements = list("briefly displays a happy face, gazing emptily at you", "briefly displays a spinning cartoon heart", "displays an encouraging message about eating healthy and exercising", \ + "reminds you that everyone is doing their best", "displays a message wishing you well", "displays a sincere thank-you for your interest in first-aid", "formally absolves you of all your sins") + to_chat(user, "\The [src] makes a happy ping and [pick(encouragements)]!") + next_encouragement = world.time + 10 SECONDS + greedy = FALSE + else if(!greedy) + to_chat(user, "\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.") + greedy = TRUE + else + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + if(isliving(user)) + var/mob/living/L = user + to_chat(L, "\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!") + L.adjustBruteLoss(4) + L.dropItemToGround(src) + +/obj/item/healthanalyzer/wound/attack(mob/living/carbon/patient, mob/living/carbon/human/user) + add_fingerprint(user) + user.visible_message("[user] scans [patient] for serious injuries.", "You scan [patient] for serious injuries.") + + if(!istype(patient)) + playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE) + to_chat(user, "\The [src] makes a sad buzz and briefly displays a frowny face, indicating it can't scan [patient].") + return + + woundscan(user, patient, src) + /obj/item/analyzer desc = "A hand-held environmental scanner which reports current gas levels. Alt-Click to use the built in barometer function." name = "analyzer" @@ -541,57 +624,13 @@ GENETICS SCANNER if (user.stat || user.eye_blind) return - var/turf/location = user.loc + //Functionality moved down to proc/scan_turf() + var/turf/location = get_turf(user) 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.01)] kPa") - else - to_chat(user, "Pressure: [round(pressure, 0.01)] 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 - - if(abs(n2_concentration - N2STANDARD) < 20) - to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen], 0.01)] mol)") - else - to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen], 0.01)] mol)") - - if(abs(o2_concentration - O2STANDARD) < 2) - to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen], 0.01)] mol)") - else - to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen], 0.01)] mol)") - - if(co2_concentration > 0.01) - to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide], 0.01)] mol)") - else - to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide], 0.01)] mol)") - - if(plasma_concentration > 0.005) - to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma], 0.01)] mol)") - else - to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma], 0.01)] mol)") - - GAS_GARBAGE_COLLECT(environment.gases) - - 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)] % ([round(env_gases[id], 0.01)] mol)") - to_chat(user, "Temperature: [round(environment.temperature-T0C, 0.01)] °C ([round(environment.temperature, 0.01)] K)") - + + scan_turf(user, location) + /obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens . = ..() @@ -670,7 +709,7 @@ GENETICS SCANNER var/total_moles = air_contents.total_moles() var/pressure = air_contents.return_pressure() var/volume = air_contents.return_volume() //could just do mixture.volume... but safety, I guess? - var/temperature = air_contents.temperature + var/temperature = air_contents.return_temperature() var/cached_scan_results = air_contents.analyzer_results if(total_moles > 0) @@ -678,10 +717,9 @@ GENETICS SCANNER to_chat(user, "Volume: [volume] L") to_chat(user, "Pressure: [round(pressure,0.01)] kPa") - var/list/cached_gases = air_contents.gases - for(var/id in cached_gases) - var/gas_concentration = cached_gases[id]/total_moles - to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(cached_gases[id], 0.01)] mol)") + for(var/id in air_contents.get_gases()) + var/gas_concentration = air_contents.get_moles(id)/total_moles + to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(air_contents.get_moles(id), 0.01)] mol)") to_chat(user, "Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)") else @@ -697,6 +735,73 @@ GENETICS SCANNER to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.") return +/obj/item/analyzer/proc/scan_turf(mob/user, turf/location) + + var/datum/gas_mixture/environment = location.return_air() + + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + var/cached_scan_results = environment.analyzer_results + + to_chat(user, "Results:") + if(abs(pressure - ONE_ATMOSPHERE) < 10) + to_chat(user, "Pressure: [round(pressure, 0.01)] kPa") + else + to_chat(user, "Pressure: [round(pressure, 0.01)] kPa") + if(total_moles) + + var/o2_concentration = environment.get_moles(/datum/gas/oxygen)/total_moles + var/n2_concentration = environment.get_moles(/datum/gas/nitrogen)/total_moles + var/co2_concentration = environment.get_moles(/datum/gas/carbon_dioxide)/total_moles + var/plasma_concentration = environment.get_moles(/datum/gas/plasma)/total_moles + + if(abs(n2_concentration - N2STANDARD) < 20) + to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)") + else + to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)") + + if(abs(o2_concentration - O2STANDARD) < 2) + to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)") + else + to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)") + + if(co2_concentration > 0.01) + to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)") + else + to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)") + + if(plasma_concentration > 0.005) + to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)") + else + to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)") + + for(var/id in environment.get_gases()) + if(id in GLOB.hardcoded_gases) + continue + var/gas_concentration = environment.get_moles(id)/total_moles + to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)") + to_chat(user, "Temperature: [round(environment.return_temperature()-T0C, 0.01)] °C ([round(environment.return_temperature(), 0.01)] K)") + + if(cached_scan_results && cached_scan_results["fusion"]) //notify the user if a fusion reaction was detected + var/fusion_power = round(cached_scan_results["fusion"], 0.01) + var/tier = fusionpower2text(fusion_power) + to_chat(user, "Large amounts of free neutrons detected in the air indicate that a fusion reaction took place.") + to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.") + +/obj/item/analyzer/ranged + desc = "A hand-held scanner which uses advanced spectroscopy and infrared readings to analyze gases as a distance. Alt-Click to use the built in barometer function." + name = "long-range analyzer" + icon = 'icons/obj/device.dmi' + icon_state = "ranged_analyzer" + +/obj/item/analyzer/ranged/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(target.tool_act(user, src, tool_behaviour)) + return + // Tool act didn't scan it, so let's get it's turf. + var/turf/location = get_turf(target) + scan_turf(user, location) + //slime scanner /obj/item/slime_scanner @@ -882,3 +987,9 @@ GENETICS SCANNER return "[HM.name] ([HM.alias])" else return HM.alias + +#undef SCANMODE_HEALTH +#undef SCANMODE_CHEMICAL +#undef SCANMODE_WOUND +#undef SCANNER_CONDENSED +#undef SCANNER_VERBOSE \ No newline at end of file diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 78a1a3bfda..cef06bfde8 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -54,8 +54,7 @@ mytape.ruin() //Fires destroy the tape ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/taperecorder/attack_hand(mob/user) +/obj/item/taperecorder/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user) if(mytape) if(!user.is_holding(src)) diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm index b6261b9060..eb444cdb12 100644 --- a/code/game/objects/items/devices/traitordevices.dm +++ b/code/game/objects/items/devices/traitordevices.dm @@ -76,6 +76,9 @@ effective or pretty fucking useless. var/used = 0 // is it cooling down? var/stealth = FALSE + var/ui_x = 320 + var/ui_y = 335 + /obj/item/healthanalyzer/rad_laser/attack(mob/living/M, mob/living/user) if(!stealth || !irradiate) ..() @@ -83,93 +86,102 @@ effective or pretty fucking useless. return if(!used) log_combat(user, M, "irradiated", src) - var/cooldown = GetCooldown() - used = 1 + var/cooldown = get_cooldown() + used = TRUE icon_state = "health1" - handle_cooldown(cooldown) // splits off to handle the cooldown while handling wavelength + addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown) + addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown) to_chat(user, "Successfully irradiated [M].") - spawn((wavelength+(intensity*4))*5) - if(M) - if(intensity >= 5) - M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS) - M.rad_act(intensity*10) + addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5) else to_chat(user, "The radioactive microlaser is still recharging.") -/obj/item/healthanalyzer/rad_laser/proc/handle_cooldown(cooldown) - spawn(cooldown) - used = 0 - icon_state = "health" +/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M) + if(QDELETED(M)) + return + if(intensity >= 5) + M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS) + M.rad_act(intensity*10) + +/obj/item/healthanalyzer/rad_laser/proc/get_cooldown() + return round(max(10, (stealth*30 + intensity*5 - wavelength/4))) /obj/item/healthanalyzer/rad_laser/attack_self(mob/user) interact(user) -/obj/item/healthanalyzer/rad_laser/proc/GetCooldown() - return round(max(10, (stealth*30 + intensity*5 - wavelength/4))) - /obj/item/healthanalyzer/rad_laser/interact(mob/user) ui_interact(user) -/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user) - . = ..() +/obj/item/healthanalyzer/rad_laser/ui_state(mob/user) + return GLOB.hands_state - var/dat = "Irradiation: [irradiate ? "On" : "Off"]
    " - dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): [stealth ? "On" : "Off"]
    " - dat += "Scan Mode: " - if(!scanmode) - dat += "Scan Health" - else if(scanmode == 1) - dat += "Scan Reagents" - else - dat += "Disabled" - dat += "

    " +/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "RadioactiveMicrolaser") + ui.open() - dat += {" - Radiation Intensity: - -- - [intensity] - ++
    +/obj/item/healthanalyzer/rad_laser/ui_data(mob/user) + var/list/data = list() + data["irradiate"] = irradiate + data["stealth"] = stealth + data["scanmode"] = scanmode + data["intensity"] = intensity + data["wavelength"] = wavelength + data["on_cooldown"] = used + data["cooldown"] = DisplayTimeText(get_cooldown()) + return data - Radiation Wavelength: - -- - [(wavelength+(intensity*4))] - ++
    - Laser Cooldown: [DisplayTimeText(GetCooldown())]
    - "} +/obj/item/healthanalyzer/rad_laser/ui_act(action, params) + if(..()) + return - var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240) - popup.set_content(dat) - popup.open() - -/obj/item/healthanalyzer/rad_laser/Topic(href, href_list) - if(!usr.canUseTopic(src)) - return 1 - - usr.set_machine(src) - if(href_list["rad"]) - irradiate = !irradiate - - else if(href_list["stealthy"]) - stealth = !stealth - - else if(href_list["mode"]) - scanmode += 1 - if(scanmode > 2) - scanmode = 0 - - else if(href_list["radint"]) - var/amount = text2num(href_list["radint"]) - amount += intensity - intensity = max(1,(min(20,amount))) - - else if(href_list["radwav"]) - var/amount = text2num(href_list["radwav"]) - amount += wavelength - wavelength = max(0,(min(120,amount))) - - attack_self(usr) - add_fingerprint(usr) - return + switch(action) + if("irradiate") + irradiate = !irradiate + . = TRUE + if("stealth") + stealth = !stealth + . = TRUE + if("scanmode") + scanmode = !scanmode + . = TRUE + if("radintensity") + var/target = params["target"] + var/adjust = text2num(params["adjust"]) + if(target == "min") + target = 1 + . = TRUE + else if(target == "max") + target = 20 + . = TRUE + else if(adjust) + target = intensity + adjust + . = TRUE + else if(text2num(target) != null) + target = text2num(target) + . = TRUE + if(.) + target = round(target) + intensity = clamp(target, 1, 20) + if("radwavelength") + var/target = params["target"] + var/adjust = text2num(params["adjust"]) + if(target == "min") + target = 0 + . = TRUE + else if(target == "max") + target = 120 + . = TRUE + else if(adjust) + target = wavelength + adjust + . = TRUE + else if(text2num(target) != null) + target = text2num(target) + . = TRUE + if(.) + target = round(target) + wavelength = clamp(target, 0, 120) /obj/item/shadowcloak name = "cloaker belt" diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index b929642f33..32d9c02a27 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -13,6 +13,8 @@ var/mob/attacher = null var/valve_open = FALSE var/toggle = 1 + var/ui_x = 310 + var/ui_y = 320 /obj/item/transfer_valve/IsAssemblyHolder() return TRUE @@ -77,7 +79,7 @@ if(attached_device) attached_device.Crossed(AM) -/obj/item/transfer_valve/attack_hand()//Triggers mousetraps +/obj/item/transfer_valve/on_attack_hand()//Triggers mousetraps . = ..() if(.) return @@ -168,8 +170,8 @@ target_self = TRUE if(change_volume) if(!target_self) - target.volume += tank_two.volume - target.volume += tank_one.air_contents.volume + target.set_volume(target.return_volume() + tank_two.volume) + target.set_volume(target.return_volume() + tank_one.air_contents.return_volume()) var/datum/gas_mixture/temp temp = tank_one.air_contents.remove_ratio(1) target.merge(temp) @@ -180,17 +182,16 @@ /obj/item/transfer_valve/proc/split_gases() if (!valve_open || !tank_one || !tank_two) return - var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume + var/ratio1 = tank_one.air_contents.return_volume()/tank_two.air_contents.return_volume() var/datum/gas_mixture/temp temp = tank_two.air_contents.remove_ratio(ratio1) tank_one.air_contents.merge(temp) - tank_two.air_contents.volume -= tank_one.air_contents.volume + tank_two.air_contents.set_volume(tank_two.air_contents.return_volume() - tank_one.air_contents.return_volume()) - /* +/* Exadv1: I know this isn't how it's going to work, but this was just to check it explodes properly when it gets a signal (and it does). - */ - +*/ /obj/item/transfer_valve/proc/toggle_valve() if(!valve_open && tank_one && tank_two) valve_open = TRUE @@ -231,7 +232,60 @@ valve_open = FALSE update_icon() -// this doesn't do anything but the timer etc. expects it to be here -// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs +/* + This doesn't do anything but the timer etc. expects it to be here + eventually maybe have it update icon to show state (timer, prox etc.) like old bombs +*/ /obj/item/transfer_valve/proc/c_state() return + +/obj/item/transfer_valve/ui_state(mob/user) + return GLOB.hands_state + +/obj/item/transfer_valve/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TransferValve", name) + ui.open() + +/obj/item/transfer_valve/ui_data(mob/user) + var/list/data = list() + data["tank_one"] = tank_one + data["tank_two"] = tank_two + data["attached_device"] = attached_device + data["valve"] = valve_open + return data + +/obj/item/transfer_valve/ui_act(action, params) + if(..()) + return + + switch(action) + if("tankone") + if(tank_one) + split_gases() + valve_open = FALSE + tank_one.forceMove(drop_location()) + tank_one = null + . = TRUE + if("tanktwo") + if(tank_two) + split_gases() + valve_open = FALSE + tank_two.forceMove(drop_location()) + tank_two = null + . = TRUE + if("toggle") + toggle_valve() + . = TRUE + if("device") + if(attached_device) + attached_device.attack_self(usr) + . = TRUE + if("remove_device") + if(attached_device) + attached_device.on_detach() + attached_device = null + . = TRUE + + update_icon() diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 4fdb862288..2fe4c67362 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -1,10 +1,10 @@ -/obj/item/storage/pill_bottle/dice +/obj/item/storage/box/dice name = "bag of dice" desc = "Contains all the luck you'll ever need." icon = 'icons/obj/dice.dmi' icon_state = "dicebag" -/obj/item/storage/pill_bottle/dice/Initialize() +/obj/item/storage/box/dice/Initialize() . = ..() var/special_die = pick("1","2","fudge","space","00","8bd20","4dd6","100") if(special_die == "1") @@ -30,7 +30,7 @@ if(special_die == "100") new /obj/item/dice/d100(src) -/obj/item/storage/pill_bottle/dice/suicide_act(mob/user) +/obj/item/storage/box/dice/suicide_act(mob/user) user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!") return (OXYLOSS) diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm new file mode 100644 index 0000000000..cf5c3d4fc5 --- /dev/null +++ b/code/game/objects/items/dualsaber.dm @@ -0,0 +1,383 @@ +/* + * Double-Bladed Energy Swords - Cheridan + */ +/obj/item/dualsaber + icon_state = "dualsaber0" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + name = "double-bladed energy sword" + desc = "Handle with care." + force = 3 + throwforce = 5 + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_SMALL + item_flags = SLOWS_WHILE_IN_HAND + var/w_class_on = WEIGHT_CLASS_BULKY + hitsound = "swing_hit" + var/hitsound_on = 'sound/weapons/blade1.ogg' + armour_penetration = 35 + var/saber_color = "green" + light_color = "#00ff00"//green + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + max_integrity = 200 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70) + resistance_flags = FIRE_PROOF + wound_bonus = -110 + bare_wound_bonus = 20 + block_parry_data = /datum/block_parry_data/dual_esword + var/hacked = FALSE + /// Can this reflect all energy projectiles? + var/can_reflect = TRUE + var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD + var/list/possible_colors = list("red", "blue", "green", "purple") + var/list/rainbow_colors = list(LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER) + var/spinnable = TRUE + total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces. + var/total_mass_on = 3.4 + var/wielded = FALSE // track wielded status on item + var/slowdown_wielded = 0 + +/datum/block_parry_data/dual_esword + block_damage_absorption = 2 + block_damage_multiplier = 0.15 + block_damage_multiplier_override = list( + ATTACK_TYPE_MELEE = 0.25 + ) + block_start_delay = 0 // instantaneous block + block_stamina_cost_per_second = 2.5 + block_stamina_efficiency = 3 + block_lock_sprinting = TRUE + // no attacking while blocking + block_lock_attacking = TRUE + block_projectile_mitigation = 75 + // more efficient vs projectiles + block_stamina_efficiency_override = list( + TEXT_ATTACK_TYPE_PROJECTILE = 4 + ) + + parry_time_windup = 0 + parry_time_active = 8 + parry_time_spindown = 0 + // we want to signal to players the most dangerous phase, the time when automatic counterattack is a thing. + parry_time_windup_visual_override = 1 + parry_time_active_visual_override = 3 + parry_time_spindown_visual_override = 4 + parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // esword users can attack while parrying. + parry_time_perfect = 2 // first ds isn't perfect + parry_time_perfect_leeway = 1 + parry_imperfect_falloff_percent = 10 + parry_efficiency_to_counterattack = 100 + parry_efficiency_considered_successful = 25 // VERY generous + parry_failed_stagger_duration = 3 SECONDS + parry_failed_clickcd_duration = CLICK_CD_MELEE + +/obj/item/dualsaber/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction) + if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object)) + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT + return ..() + +/obj/item/dualsaber/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) + . = ..() + if(parry_efficiency >= 90) // perfect parry + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER + . |= BLOCK_SHOULD_REDIRECT + +/obj/item/dualsaber/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/dualsaber/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=3, force_wielded=34, \ + wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg') + +/obj/item/dualsaber/Initialize() + . = ..() + if(LAZYLEN(possible_colors)) + saber_color = pick(possible_colors) + switch(saber_color) + if("red") + light_color = LIGHT_COLOR_RED + if("green") + light_color = LIGHT_COLOR_GREEN + if("blue") + light_color = LIGHT_COLOR_LIGHT_CYAN + if("purple") + light_color = LIGHT_COLOR_LAVENDER + +/// Triggered on wield of two handed item +/// Specific hulk checks due to reflection chance for balance issues and switches hitsounds. +/obj/item/dualsaber/proc/on_wield(obj/item/source, mob/living/carbon/user) + if(user.has_dna() && user.dna.check_mutation(HULK)) + to_chat(user, "You lack the grace to wield this!") + return COMPONENT_TWOHANDED_BLOCK_WIELD + wielded = TRUE + sharpness = SHARP_EDGED + w_class = w_class_on + total_mass = total_mass_on + hitsound = 'sound/weapons/blade1.ogg' + slowdown += slowdown_wielded + START_PROCESSING(SSobj, src) + set_light(brightness_on) + AddElement(/datum/element/sword_point) + item_flags |= (ITEM_CAN_BLOCK|ITEM_CAN_PARRY) + +/// Triggered on unwield of two handed item +/// switch hitsounds +/obj/item/dualsaber/proc/on_unwield(obj/item/source, mob/living/carbon/user) + sharpness = initial(sharpness) + w_class = initial(w_class) + total_mass = initial(total_mass) + wielded = FALSE + hitsound = "swing_hit" + slowdown_wielded -= slowdown_wielded + STOP_PROCESSING(SSobj, src) + set_light(0) + RemoveElement(/datum/element/sword_point) + item_flags &= ~(ITEM_CAN_BLOCK|ITEM_CAN_PARRY) + +/obj/item/dualsaber/Destroy() + STOP_PROCESSING(SSobj, src) + . = ..() + +/obj/item/dualsaber/update_icon_state() + if(wielded) + icon_state = "dualsaber[saber_color][wielded]" + else + icon_state = "dualsaber0" + clean_blood() + +/obj/item/dualsaber/suicide_act(mob/living/carbon/user) + if(wielded) + user.visible_message("[user] begins spinning way too fast! It looks like [user.p_theyre()] trying to commit suicide!") + var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)//stole from chainsaw code + var/obj/item/organ/brain/B = user.getorganslot(ORGAN_SLOT_BRAIN) + B.organ_flags &= ~ORGAN_VITAL //this cant possibly be a good idea + var/randdir + for(var/i in 1 to 24)//like a headless chicken! + if(user.is_holding(src)) + randdir = pick(GLOB.alldirs) + user.Move(get_step(user, randdir),randdir) + user.emote("spin") + if (i == 3 && myhead) + myhead.drop_limb() + sleep(3) + else + user.visible_message("[user] panics and starts choking to death!") + return OXYLOSS + else + user.visible_message("[user] begins beating [user.p_them()]self to death with \the [src]'s handle! It probably would've been cooler if [user.p_they()] turned it on first!") + return BRUTELOSS + +/obj/item/dualsaber/attack(mob/target, mob/living/carbon/human/user) + if(user.has_dna() && user.dna.check_mutation(HULK)) + to_chat(user, "You grip the blade too hard and accidentally drop it!") + user.dropItemToGround(src) + return + ..() + if(HAS_TRAIT(user, TRAIT_CLUMSY) && (wielded) && prob(40)) + impale(user) + return + if(spinnable && (wielded) && prob(50)) + INVOKE_ASYNC(src, .proc/jedi_spin, user) + +/obj/item/dualsaber/proc/jedi_spin(mob/living/user) + for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) + user.setDir(i) + if(i == WEST) + user.emote("flip") + sleep(1) + +/obj/item/dualsaber/proc/impale(mob/living/user) + to_chat(user, "You twirl around a bit before losing your balance and impaling yourself on [src].") + if (force) + user.take_bodypart_damage(20,25) + else + user.adjustStaminaLoss(25) + +/obj/item/dualsaber/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(!wielded) + return NONE + if(can_reflect && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE)) + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER //no you + return BLOCK_SHOULD_REDIRECT | BLOCK_SUCCESS | BLOCK_REDIRECTED + return ..() + +/obj/item/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up + if(wielded) + to_chat(user, "You can't pick up such dangerous item with your meaty hands without losing fingers, better not to!") + return 1 + +/obj/item/dualsaber/process() + if(wielded) + if(hacked) + rainbow_process() + open_flame() + else + STOP_PROCESSING(SSobj, src) + +/obj/item/dualsaber/proc/rainbow_process() + light_color = pick(rainbow_colors) + +/obj/item/dualsaber/ignition_effect(atom/A, mob/user) + // same as /obj/item/melee/transforming/energy, mostly + if(!wielded) + return "" + var/in_mouth = "" + if(iscarbon(user)) + var/mob/living/carbon/C = user + if(C.wear_mask) + in_mouth = ", barely missing [user.p_their()] nose" + . = "[user] swings [user.p_their()] [name][in_mouth]. [user.p_they(TRUE)] light[user.p_s()] [user.p_their()] [A.name] in the process." + playsound(loc, hitsound, get_clamped_volume(), 1, -1) + add_fingerprint(user) + // Light your candles while spinning around the room + if(spinnable) + INVOKE_ASYNC(src, .proc/jedi_spin, user) + +/obj/item/dualsaber/green + possible_colors = list("green") + +/obj/item/dualsaber/red + possible_colors = list("red") + +/obj/item/dualsaber/blue + possible_colors = list("blue") + +/obj/item/dualsaber/purple + possible_colors = list("purple") + +/obj/item/dualsaber/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/multitool)) + if(!hacked) + hacked = TRUE + to_chat(user, "2XRNBW_ENGAGE") + saber_color = "rainbow" + update_icon() + else + to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") + else + return ..() + +///////////////////////////////////////////////////// +// HYPEREUTACTIC Blades ///////////////////////// +///////////////////////////////////////////////////// + +/obj/item/dualsaber/hypereutactic + icon = 'icons/obj/1x2.dmi' + icon_state = "hypereutactic" + lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' + righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' + item_state = "hypereutactic" + inhand_x_dimension = 64 + inhand_y_dimension = 64 + name = "hypereutactic blade" + desc = "A supermassive weapon envisioned to cleave the very fabric of space and time itself in twain, the hypereutactic blade dynamically flash-forges a hypereutactic crystaline nanostructure capable of passing through most known forms of matter like a hot knife through butter." + force = 7 + hitsound_on = 'sound/weapons/nebhit.ogg' + armour_penetration = 60 + light_color = "#37FFF7" + rainbow_colors = list("#FF0000", "#FFFF00", "#00FF00", "#00FFFF", "#0000FF","#FF00FF", "#3399ff", "#ff9900", "#fb008b", "#9800ff", "#00ffa3", "#ccff00") + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "destroyed", "ripped", "devastated", "shredded") + spinnable = FALSE + total_mass_on = 4 + slowdown_wielded = 1 + +/obj/item/dualsaber/hypereutactic/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=7, force_wielded=40, \ + wieldsound='sound/weapons/nebon.ogg', unwieldsound='sound/weapons/nebhit.ogg') + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/dualsaber/hypereutactic/update_icon_state() + return + +/obj/item/dualsaber/hypereutactic/update_overlays() + . = ..() + var/mutable_appearance/blade_overlay = mutable_appearance(icon, "hypereutactic_blade") + var/mutable_appearance/gem_overlay = mutable_appearance(icon, "hypereutactic_gem") + + if(light_color) + blade_overlay.color = light_color + gem_overlay.color = light_color + + . += gem_overlay + + if(wielded) + . += blade_overlay + + clean_blood() + +/obj/item/dualsaber/hypereutactic/AltClick(mob/living/user) + . = ..() + if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked) + return + if(user.incapacitated() || !istype(user)) + to_chat(user, "You can't do that right now!") + return + if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") + var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null + if(!energy_color_input || !user.canUseTopic(src, BE_CLOSE, FALSE) || hacked) + return + light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) + update_icon() + update_light() + return TRUE + +/obj/item/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) + . = ..() + if(isinhands) + var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem") + gem_inhand.color = light_color + . += gem_inhand + if(wielded) + var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade") + blade_inhand.color = light_color + . += blade_inhand + +/obj/item/dualsaber/hypereutactic/examine(mob/user) + . = ..() + if(!hacked) + . += "Alt-click to recolor it." + +/obj/item/dualsaber/hypereutactic/rainbow_process() + . = ..() + update_icon() + update_light() + +/obj/item/dualsaber/hypereutactic/chaplain + name = "divine lightblade" + desc = "A giant blade of bright and holy light, said to cut down the wicked with ease." + force = 5 + armour_penetration = 0 + block_parry_data = /datum/block_parry_data/chaplain + var/chaplain_spawnable = TRUE + can_reflect = FALSE + obj_flags = UNIQUE_RENAME + +/datum/block_parry_data/chaplain + parry_stamina_cost = 12 + parry_time_windup = 2 + parry_time_active = 5 + parry_time_spindown = 3 + // parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK + parry_time_perfect = 1 + parry_time_perfect_leeway = 1 + parry_imperfect_falloff_percent = 7.5 + parry_efficiency_to_counterattack = 100 + parry_efficiency_considered_successful = 80 + parry_efficiency_perfect = 120 + parry_efficiency_perfect_override = list( + TEXT_ATTACK_TYPE_PROJECTILE = 30, + ) + parry_failed_stagger_duration = 3 SECONDS + parry_failed_clickcd_duration = 2 SECONDS + +/obj/item/dualsaber/hypereutactic/chaplain/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=5, force_wielded=20, \ + wieldsound='sound/weapons/nebon.ogg', unwieldsound='sound/weapons/nebhit.ogg') + AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE) diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm index c4a15a1871..0d5c9a22aa 100644 --- a/code/game/objects/items/eightball.dm +++ b/code/game/objects/items/eightball.dm @@ -192,11 +192,13 @@ return top_vote -/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state) +/obj/item/toy/eightball/haunted/ui_state(mob/user) + return GLOB.observer_state - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/toy/eightball/haunted/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "eightball", name, 400, 600, master_ui, state) + ui = new(user, src, "EightBallVote", name) ui.open() /obj/item/toy/eightball/haunted/ui_data(mob/user) @@ -229,4 +231,4 @@ else votes[selected_answer] += 1 voted[user.ckey] = selected_answer - . = TRUE \ No newline at end of file + . = TRUE diff --git a/code/game/objects/items/electrostaff.dm b/code/game/objects/items/electrostaff.dm new file mode 100644 index 0000000000..9750994c87 --- /dev/null +++ b/code/game/objects/items/electrostaff.dm @@ -0,0 +1,264 @@ + +/obj/item/electrostaff + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "electrostaff" + item_state = "electrostaff" + lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' + name = "riot suppression electrostaff" + desc = "A large quarterstaff, with massive silver electrodes mounted at the end." + w_class = WEIGHT_CLASS_HUGE + slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING + throwforce = 15 //if you are a madman and finish someone off with this, power to you. + throw_speed = 1 + item_flags = NO_MAT_REDEMPTION + attack_verb = list("struck", "beaten", "thwacked", "pulped") + total_mass = 5 //yeah this is a heavy thing, beating people with it while it's off is not going to do you any favors. (to curb stun-kill rampaging without it being on) + block_parry_data = /datum/block_parry_data/electrostaff + attack_speed = CLICK_CD_MELEE + var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high + var/on = FALSE + var/can_block_projectiles = FALSE //can't block guns + var/lethal_cost = 400 //10000/400*20 = 500. decent enough? + var/lethal_damage = 20 + var/lethal_stam_cost = 4 + var/stun_cost = 333 //10000/333*25 = 750. stunbatons are at time of writing 10000/1000*49 = 490. + var/stun_status_effect = STATUS_EFFECT_ELECTROSTAFF //a small slowdown effect + var/stun_stamdmg = 40 + var/stun_status_duration = 25 + var/stun_stam_cost = 3.5 + var/wielded = FALSE // track wielded status on item + +// haha security desword time /s +/datum/block_parry_data/electrostaff + block_damage_absorption = 0 + block_damage_multiplier = 1 + can_block_attack_types = ~ATTACK_TYPE_PROJECTILE // only able to parry non projectiles + block_damage_multiplier_override = list( + TEXT_ATTACK_TYPE_MELEE = 0.5, // only useful on melee and unarmed + TEXT_ATTACK_TYPE_UNARMED = 0.3 + ) + block_start_delay = 0.5 // near instantaneous block + block_stamina_cost_per_second = 3 + block_stamina_efficiency = 2 // haha this is a horrible idea + // more slowdown that deswords because security + block_slowdown = 2 + // no attacking while blocking + block_lock_attacking = TRUE + + parry_time_windup = 1 + parry_time_active = 5 + parry_time_spindown = 0 + parry_time_spindown_visual_override = 1 + parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING // no attacking while parrying + parry_time_perfect = 0 + parry_time_perfect_leeway = 0.5 + parry_efficiency_perfect = 100 + parry_imperfect_falloff_percent = 1 + parry_imperfect_falloff_percent_override = list( + TEXT_ATTACK_TYPE_PROJECTILE = 45 // really crappy vs projectiles + ) + parry_time_perfect_leeway_override = list( + TEXT_ATTACK_TYPE_PROJECTILE = 1 // extremely harsh window for projectiles + ) + // not extremely punishing to fail, but no spamming the parry. + parry_cooldown = 2.5 SECONDS + parry_failed_stagger_duration = 1.5 SECONDS + parry_failed_clickcd_duration = 1 SECONDS + +/obj/item/electrostaff/Initialize(mapload) + . = ..() + if(ispath(cell)) + cell = new cell + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/turn_on) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/turn_off) + +/obj/item/electrostaff/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_multiplier=2, wieldsound="sparks", unwieldsound="sparks") + +/obj/item/electrostaff/Destroy() + STOP_PROCESSING(SSobj, src) + QDEL_NULL(cell) + return ..() + +/obj/item/electrostaff/get_cell() + . = cell + if(iscyborg(loc)) + var/mob/living/silicon/robot/R = loc + . = R.get_cell() + +/obj/item/electrostaff/proc/min_hitcost() + return min(stun_cost, lethal_cost) + +/obj/item/electrostaff/proc/turn_on(obj/item/source, mob/user) + wielded = TRUE + item_flags |= (ITEM_CAN_BLOCK|ITEM_CAN_PARRY) + if(!cell) + if(user) + to_chat(user, "[src] has no cell.") + return + if(cell.charge < min_hitcost()) + if(user) + to_chat(user, "[src] is out of charge.") + return + on = TRUE + START_PROCESSING(SSobj, src) + if(user) + to_chat(user, "You turn [src] on.") + +/obj/item/electrostaff/proc/turn_off(obj/item/source, mob/user) + wielded = FALSE + item_flags &= ~(ITEM_CAN_BLOCK|ITEM_CAN_PARRY) + if(user) + to_chat(user, "You turn [src] off.") + on = FALSE + STOP_PROCESSING(SSobj, src) + +/obj/item/electrostaff/update_icon_state() + if(!wielded) + icon_state = item_state = "electrostaff" + else + icon_state = item_state = (on? "electrostaff_1" : "electrostaff_0") + set_light(7, on? 1 : 0, LIGHT_COLOR_CYAN) + +/obj/item/electrostaff/examine(mob/living/user) + . = ..() + if(cell) + . += "The cell charge is [round(cell.percent())]%." + else + . += "There is no cell installed!" + +/obj/item/electrostaff/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/stock_parts/cell)) + var/obj/item/stock_parts/cell/C = W + if(cell) + to_chat(user, "[src] already has a cell!") + else + if(C.maxcharge < min_hit_cost()) + to_chat(user, "[src] requires a higher capacity cell.") + return + if(!user.transferItemToLoc(W, src)) + return + cell = C + to_chat(user, "You install a cell in [src].") + + else if(W.tool_behaviour == TOOL_SCREWDRIVER) + if(cell) + cell.update_icon() + cell.forceMove(get_turf(src)) + cell = null + to_chat(user, "You remove the cell from [src].") + turn_off(user, TRUE) + else + return ..() + +/obj/item/electrostaff/process() + deductcharge(50) //Wasteful! + +/obj/item/electrostaff/proc/min_hit_cost() + return min(lethal_cost, stun_cost) + +/obj/item/electrostaff/proc/deductcharge(amount) + var/obj/item/stock_parts/cell/C = get_cell() + if(!C) + turn_off() + return FALSE + C.use(min(amount, C.charge)) + if(QDELETED(src)) + return FALSE + if(C.charge < min_hit_cost()) + turn_off() + +/obj/item/electrostaff/attack(mob/living/target, mob/living/user) + if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit + to_chat(user, "You're too exhausted to use [src] properly.")//CIT CHANGE - ditto + return //CIT CHANGE - ditto + if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) + clowning_around(user) //ouch! + return + if(iscyborg(target)) + return ..() + var/list/return_list = list() + if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, return_list) & BLOCK_SUCCESS) //No message; run_block() handles that + playsound(target, 'sound/weapons/genhit.ogg', 50, 1) + return FALSE + if(user.a_intent != INTENT_HARM) + if(stun_act(target, user, null, return_list)) + user.do_attack_animation(target) + user.adjustStaminaLossBuffered(stun_stam_cost) + return + else if(!harm_act(target, user, null, return_list)) + return ..() //if you can't fry them just beat them with it + else //we did harm act them + user.do_attack_animation(target) + user.adjustStaminaLossBuffered(lethal_stam_cost) + +/obj/item/electrostaff/proc/stun_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list()) + var/stunforce = block_calculate_resultant_damage(stun_stamdmg, block_return) + if(!no_charge_and_force) + if(!on) + target.visible_message("[user] has bapped [target] with [src]. Luckily it was off.", \ + "[user] has bapped you with [src]. Luckily it was off") + turn_off() //if it wasn't already off + return FALSE + var/obj/item/stock_parts/cell/C = get_cell() + var/chargeleft = C.charge + deductcharge(stun_cost) + if(QDELETED(src) || QDELETED(C)) //boom + return FALSE + if(chargeleft < stun_cost) + stunforce *= round(chargeleft/stun_cost, 0.1) + target.adjustStaminaLoss(stunforce) + target.apply_effect(EFFECT_STUTTER, stunforce) + SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) + if(user) + target.lastattacker = user.real_name + target.lastattackerckey = user.ckey + target.visible_message("[user] has shocked [target] with [src]!", \ + "[user] has shocked you with [src]!") + log_combat(user, target, "stunned with an electrostaff") + playsound(src, 'sound/weapons/staff.ogg', 50, 1, -1) + target.apply_status_effect(stun_status_effect, stun_status_duration) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.forcesay(GLOB.hit_appends) + return TRUE + +/obj/item/electrostaff/proc/harm_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list()) + var/lethal_force = block_calculate_resultant_damage(lethal_damage, block_return) + if(!no_charge_and_force) + if(!on) + return FALSE //standard item attack + var/obj/item/stock_parts/cell/C = get_cell() + var/chargeleft = C.charge + deductcharge(lethal_cost) + if(QDELETED(src) || QDELETED(C)) //boom + return FALSE + if(chargeleft < stun_cost) + lethal_force *= round(chargeleft/lethal_cost, 0.1) + target.adjustFireLoss(lethal_force) //good against ointment spam + SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) + if(user) + target.lastattacker = user.real_name + target.lastattackerckey = user.ckey + target.visible_message("[user] has seared [target] with [src]!", \ + "[user] has seared you with [src]!") + log_combat(user, target, "burned with an electrostaff") + playsound(src, 'sound/weapons/sear.ogg', 50, 1, -1) + return TRUE + +/obj/item/electrostaff/proc/clowning_around(mob/living/user) + user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \ + "You accidentally hit yourself with [src]!") + SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK) + harm_act(user, user, TRUE) + stun_act(user, user, TRUE) + deductcharge(lethal_cost) + +/obj/item/electrostaff/emp_act(severity) + . = ..() + if (!(. & EMP_PROTECT_SELF)) + turn_off() + if(!iscyborg(loc)) + deductcharge(1000 / severity, TRUE, FALSE) diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 2d9d0b61c2..b1f51f608d 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -110,7 +110,7 @@ . += "The safety is [safety ? "on" : "off"]." if(reagents.total_volume) - . += "You can loose its screws to empty it." + . += "Alt-click to empty it." /obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user) if(istype(target, tanktype) && target.Adjacent(user)) @@ -230,7 +230,7 @@ repetition++ addtimer(CALLBACK(src, /obj/item/extinguisher/proc/move_chair, B, movementdirection, repetition), timer_seconds) -/obj/item/extinguisher/screwdriver_act(mob/user, obj/item/tool) +/obj/item/extinguisher/AltClick(mob/user) if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user))) return EmptyExtinguisher(user) @@ -244,7 +244,7 @@ var/turf/open/theturf = T theturf.MakeSlippery(TURF_WET_WATER, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) - user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "You quietly empty out \the [src] by loosing the release valve's screws.") + user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "You quietly empty out \the [src] by using its release valve.") //firebot assembly /obj/item/extinguisher/attackby(obj/O, mob/user, params) diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm new file mode 100644 index 0000000000..6fb7b89262 --- /dev/null +++ b/code/game/objects/items/fireaxe.dm @@ -0,0 +1,73 @@ +/* + * Fireaxe + */ +/obj/item/fireaxe // DEM AXES MAN, marker -Agouri + icon_state = "fireaxe0" + lefthand_file = 'icons/mob/inhands/weapons/axes_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/axes_righthand.dmi' + name = "fire axe" + desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" + force = 5 + throwforce = 15 + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK + attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") + hitsound = 'sound/weapons/bladeslice.ogg' + sharpness = SHARP_EDGED + max_integrity = 200 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) + resistance_flags = FIRE_PROOF + wound_bonus = -15 + bare_wound_bonus = 20 + var/wielded = FALSE // track wielded status on item + +/obj/item/fireaxe/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/fireaxe/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 100, 80, 0 , hitsound) //axes are not known for being precision butchering tools + AddComponent(/datum/component/two_handed, force_unwielded=5, force_wielded=24, icon_wielded="fireaxe1") + +/// triggered on wield of two handed item +/obj/item/fireaxe/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/fireaxe/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/fireaxe/update_icon_state() + icon_state = "fireaxe0" + +/obj/item/fireaxe/suicide_act(mob/user) + user.visible_message("[user] axes [user.p_them()]self from head to toe! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/fireaxe/afterattack(atom/A, mob/living/user, proximity) + . = ..() + if(!proximity || !wielded || IS_STAMCRIT(user)) + return + if(istype(A, /obj/structure/window)) //destroys windows and grilles in one hit (or more if it has a ton of health like plasmaglass) + var/obj/structure/window/W = A + W.take_damage(200, BRUTE, "melee", 0) + else if(istype(A, /obj/structure/grille)) + var/obj/structure/grille/G = A + G.take_damage(40, BRUTE, "melee", 0) + +/* + * Bone Axe + */ +/obj/item/fireaxe/boneaxe // Blatant imitation of the fireaxe, but made out of bone. + icon_state = "bone_axe0" + name = "bone axe" + desc = "A large, vicious axe crafted out of several sharpened bone plates and crudely tied together. Made of monsters, by killing monsters, for killing monsters." + +/obj/item/fireaxe/boneaxe/update_icon_state() + icon_state = "bone_axe0" + +/obj/item/fireaxe/boneaxe/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=5, force_wielded=23, icon_wielded="bone_axe1") diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm index c785c22813..515f5715dd 100644 --- a/code/game/objects/items/flamethrower.dm +++ b/code/game/objects/items/flamethrower.dm @@ -131,6 +131,7 @@ /obj/item/flamethrower/analyzer_act(mob/living/user, obj/item/I) if(ptank) ptank.analyzer_act(user, I) + return TRUE /obj/item/flamethrower/attack_self(mob/user) @@ -204,11 +205,10 @@ //TODO: DEFERRED Consider checking to make sure tank pressure is high enough before doing this... //Transfer 5% of current tank air contents to turf var/datum/gas_mixture/air_transfer = ptank.air_contents.remove_ratio(release_amount) - if(air_transfer.gases[/datum/gas/plasma]) - air_transfer.gases[/datum/gas/plasma] *= 5 + air_transfer.set_moles(/datum/gas/plasma, air_transfer.get_moles(/datum/gas/plasma) * 5) target.assume_air(air_transfer) //Burn it based on transfered gas - target.hotspot_expose((ptank.air_contents.temperature*2) + 380,500) + target.hotspot_expose((ptank.air_contents.return_temperature()*2) + 380,500) //location.hotspot_expose(1000,500,1) SSair.add_to_active(target, 0) diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm index bafffa18e3..979fa7e958 100644 --- a/code/game/objects/items/granters.dm +++ b/code/game/objects/items/granters.dm @@ -79,7 +79,7 @@ ADD_TRAIT(user, granted_trait, BOOK_TRAIT) /obj/item/book/granter/trait/rifleman - name = "\proper the Neo-Russian Rifleman\'s Primer" + name = "The Neo-Russian Rifleman\'s Primer" desc = "A book with stains of vodka and...blood? The back is hard to read, but says something about bolt-actions. Or pump-actions. Both, maybe." oneuse = FALSE granted_trait = TRAIT_FAST_PUMP @@ -253,7 +253,7 @@ user.set_nutrition(NUTRITION_LEVEL_STARVING + 50) /obj/item/book/granter/spell/blind - spell = /obj/effect/proc_holder/spell/targeted/trigger/blind + spell = /obj/effect/proc_holder/spell/pointed/trigger/blind spellname = "blind" icon_state ="bookblind" desc = "This book looks blurry, no matter how you look at it." @@ -265,7 +265,7 @@ user.blind_eyes(10) /obj/item/book/granter/spell/mindswap - spell = /obj/effect/proc_holder/spell/targeted/mind_transfer + spell = /obj/effect/proc_holder/spell/pointed/mind_transfer spellname = "mindswap" icon_state ="bookmindswap" desc = "This book's cover is pristine, though its pages look ragged and torn." @@ -289,7 +289,7 @@ if(stored_swap == user) to_chat(user,"You stare at the book some more, but there doesn't seem to be anything else to learn...") return - var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new + var/obj/effect/proc_holder/spell/pointed/mind_transfer/swapper = new if(swapper.cast(list(stored_swap), user, TRUE, TRUE)) to_chat(user,"You're suddenly somewhere else... and someone else?!") to_chat(stored_swap,"Suddenly you're staring at [src] again... where are you, who are you?!") @@ -324,7 +324,7 @@ user.DefaultCombatKnockdown(40) /obj/item/book/granter/spell/barnyard - spell = /obj/effect/proc_holder/spell/targeted/barnyardcurse + spell = /obj/effect/proc_holder/spell/pointed/barnyardcurse spellname = "barnyard" icon_state ="bookhorses" desc = "This book is more horse than your mind has room for." @@ -477,6 +477,23 @@ name = "empty scroll" icon_state = "blankscroll" +/obj/item/book/granter/martial/krav_maga + martial = /datum/martial_art/krav_maga + name = "parchment scroll" + martialname = "krav maga" + desc = "A worn parchment scrap written in an ancient language. Somehow you can still understand the lessons!" + greet = "You have learned the ancient martial art of Krav Maga. You have special attacks with which to take down your foes." + icon = 'icons/obj/wizard.dmi' + icon_state ="scroll2" + remarks = list("Sweep the legs...", "Chop the throat...", "Punch the lungs...", "Get the gold...", "Where are my sick gloves..?") + +/obj/item/book/granter/martial/krav_maga/onlearned(mob/living/carbon/user) + . = ..() + if(oneuse == TRUE) + desc = "It's completely blank." + name = "empty scroll" + icon_state = "blankscroll" + // I did not include mushpunch's grant, it is not a book and the item does it just fine. @@ -510,7 +527,7 @@ oneuse = FALSE remarks = list("So that is how icing is made!", "Placing fruit on top? How simple...", "Huh layering cake seems harder then this...", "This book smells like candy", "A clown must have made this page, or they forgot to spell check it before printing...", "Wait, a way to cook slime to be safe?") -/obj/item/book/granter/crafting_recipe/coldcooking //IceCream +/obj/item/book/granter/crafting_recipe/coldcooking //Icecream name = "Cooking with Ice" desc = "A cook book that teaches you many old icecream treats." crafting_recipe_types = list(/datum/crafting_recipe/food/banana_split, /datum/crafting_recipe/food/root_float, /datum/crafting_recipe/food/bluecharrie_float, /datum/crafting_recipe/food/charrie_float) diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 4ce0e811c3..f06dd634c6 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -97,7 +97,7 @@ to_chat(user, "You add [A] to the [initial(name)] assembly.") else if(stage == EMPTY && istype(I, /obj/item/stack/cable_coil)) - if (I.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC)) + if (I.use_tool(src, user, 0, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)) 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/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index f51db9fa4c..bf9fab5f04 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -60,6 +60,14 @@ shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/mega shrapnel_radius = 12 +/obj/item/grenade/stingbang/breaker + name = "breakbang" + shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/breaker + +/obj/item/grenade/stingbang/shred + name = "shredbang" + shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/shred + /obj/item/grenade/stingbang/prime(mob/living/lanced_by) if(iscarbon(loc)) var/mob/living/carbon/C = loc @@ -116,9 +124,11 @@ /obj/item/grenade/primer/attack_self(mob/user) . = ..() if(active) + if(!user.CheckActionCooldown()) + return user.playsound_local(user, 'sound/misc/box_deploy.ogg', 50, TRUE) rots++ - user.changeNext_move(CLICK_CD_RAPID) + user.DelayNextAction(CLICK_CD_RAPID) /obj/item/grenade/primer/prime(mob/living/lanced_by) shrapnel_radius = round(rots / rots_per_mag) diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index a2b0e3edd4..014487332c 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -60,7 +60,8 @@ if(target) if(!QDELETED(target)) location = get_turf(target) - target.cut_overlay(plastic_overlay, TRUE) + target.cut_overlay(plastic_overlay) + UnregisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay) if(!ismob(target) || full_damage_on_mobs) target.ex_act(EXPLODE_HEAVY, target) else @@ -126,13 +127,17 @@ I.embedding["embed_chance"] = 0 I.updateEmbedding() - target.add_overlay(plastic_overlay, TRUE) + RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/add_plastic_overlay) + target.update_icon() if(!nadeassembly) to_chat(user, "You plant the bomb. Timer counting down from [det_time].") addtimer(CALLBACK(src, .proc/prime), det_time*10) else qdel(src) //How? +/obj/item/grenade/plastic/proc/add_plastic_overlay(atom/source, list/overlay_list) + overlay_list += plastic_overlay + /obj/item/grenade/plastic/proc/shout_syndicate_crap(mob/M) if(!M) return diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index c7c9fa37a9..4c9ea06620 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -320,7 +320,7 @@ do_sparks(1, TRUE, src) qdel(src) -/obj/item/restraints/legcuffs/beartrap/energy/attack_hand(mob/user) +/obj/item/restraints/legcuffs/beartrap/energy/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) Crossed(user) //honk . = ..() diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 381257721e..58146be20f 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -168,6 +168,7 @@ icon_state = "witchhunterhat" item_state = "witchhunterhat" flags_cover = HEADCOVERSEYES + flags_inv = HIDEHAIR /obj/item/storage/box/holy/follower name = "Followers of the Chaplain Kit" @@ -224,6 +225,7 @@ throwforce = 10 w_class = WEIGHT_CLASS_TINY obj_flags = UNIQUE_RENAME + wound_bonus = -10 var/chaplain_spawnable = TRUE total_mass = TOTAL_MASS_MEDIEVAL_WEAPON @@ -350,7 +352,7 @@ w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT block_chance = 30 - sharpness = IS_SHARP + sharpness = SHARP_EDGED hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") @@ -450,7 +452,7 @@ w_class = WEIGHT_CLASS_BULKY armour_penetration = 35 slot_flags = ITEM_SLOT_BACK - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("chopped", "sliced", "cut", "reaped") /obj/item/nullrod/scythe/Initialize() @@ -573,7 +575,7 @@ righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' w_class = WEIGHT_CLASS_HUGE item_flags = ABSTRACT - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' total_mass = TOTAL_MASS_HAND_REPLACEMENT @@ -592,7 +594,7 @@ name = "clown dagger" desc = "Used for absolutely hilarious sacrifices." hitsound = 'sound/items/bikehorn.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") /obj/item/nullrod/pride_hammer @@ -643,7 +645,7 @@ throw_speed = 4 throw_range = 7 throwforce = 30 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("enlightened", "redpilled") /obj/item/nullrod/armblade @@ -655,7 +657,9 @@ righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' item_flags = ABSTRACT w_class = WEIGHT_CLASS_HUGE - sharpness = IS_SHARP + sharpness = SHARP_EDGED + wound_bonus = -20 + bare_wound_bonus = 25 total_mass = TOTAL_MASS_HAND_REPLACEMENT /obj/item/nullrod/armblade/Initialize() @@ -695,7 +699,7 @@ force = 15 block_chance = 40 slot_flags = ITEM_SLOT_BACK - sharpness = IS_BLUNT + sharpness = SHARP_NONE hitsound = "swing_hit" attack_verb = list("smashed", "slammed", "whacked", "thwacked") icon = 'icons/obj/items_and_weapons.dmi' @@ -750,7 +754,7 @@ name = "arrhythmic knife" w_class = WEIGHT_CLASS_HUGE desc = "They say fear is the true mind killer, but stabbing them in the head works too. Honour compels you to not sheathe it once drawn." - sharpness = IS_SHARP + sharpness = SHARP_EDGED slot_flags = null hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") @@ -778,7 +782,7 @@ desc = "Holding this makes you look absolutely devilish." attack_verb = list("poked", "impaled", "pierced", "jabbed") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/nullrod/egyptian name = "egyptian staff" diff --git a/code/game/objects/items/implants/implant_misc.dm b/code/game/objects/items/implants/implant_misc.dm index 6cdc5ee824..08d6a586c8 100644 --- a/code/game/objects/items/implants/implant_misc.dm +++ b/code/game/objects/items/implants/implant_misc.dm @@ -38,6 +38,23 @@ if(!uses) qdel(src) +/obj/item/implant/warp + name = "warp implant" + desc = "Saves your position somewhere, and then warps you back to it after five seconds." + icon_state = "warp" + uses = 15 + +/obj/item/implant/warp/activate() + . = ..() + uses-- + imp_in.do_adrenaline(20, TRUE, 0, 0, TRUE, list(/datum/reagent/fermi/eigenstate = 1.2), "You feel an internal prick as as the bluespace starts ramping up!") + to_chat(imp_in, "You feel an internal prick as as the bluespace starts ramping up!") + if(!uses) + qdel(src) + +/obj/item/implanter/warp + name = "implanter (warp)" + imp_type = /obj/item/implant/warp /obj/item/implant/emp name = "emp implant" @@ -69,4 +86,4 @@ healthstring = "Oxygen Deprivation Damage => [round(L.getOxyLoss())]
    Fire Damage => [round(L.getFireLoss())]
    Toxin Damage => [round(L.getToxLoss())]
    Brute Force Damage => [round(L.getBruteLoss())]
    " if (!healthstring) healthstring = "ERROR" - return healthstring \ No newline at end of file + return healthstring diff --git a/code/game/objects/items/implants/implant_radio.dm b/code/game/objects/items/implants/implant_radio.dm index 5d3d579a4e..6f42547004 100644 --- a/code/game/objects/items/implants/implant_radio.dm +++ b/code/game/objects/items/implants/implant_radio.dm @@ -10,7 +10,7 @@ /obj/item/implant/radio/activate() . = ..() // needs to be GLOB.deep_inventory_state otherwise it won't open - radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state) + radio.ui_interact(usr, state = GLOB.deep_inventory_state) /obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE) . = ..() diff --git a/code/game/objects/items/implants/implant_uplink.dm b/code/game/objects/items/implants/implant_uplink.dm index 9895c1e34c..0cac8f838a 100644 --- a/code/game/objects/items/implants/implant_uplink.dm +++ b/code/game/objects/items/implants/implant_uplink.dm @@ -9,7 +9,7 @@ /obj/item/implant/uplink/Initialize(mapload, _owner) . = ..() - AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc, GLOB.not_incapacitated_state) + AddComponent(/datum/component/uplink, _owner, TRUE, FALSE, null, starting_tc) /obj/item/implanter/uplink name = "implanter (uplink)" diff --git a/code/game/objects/items/implants/implantchair.dm b/code/game/objects/items/implants/implantchair.dm index 3ea27c84bb..7b05cf302e 100644 --- a/code/game/objects/items/implants/implantchair.dm +++ b/code/game/objects/items/implants/implantchair.dm @@ -26,14 +26,15 @@ open_machine() update_icon() +/obj/machinery/implantchair/ui_state(mob/user) + return GLOB.notcontained_state -/obj/machinery/implantchair/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) +/obj/machinery/implantchair/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state) + ui = new(user, src, "ImplantChair", name) ui.open() - /obj/machinery/implantchair/ui_data() var/list/data = list() data["occupied"] = occupant ? 1 : 0 @@ -121,8 +122,6 @@ update_icon() /obj/machinery/implantchair/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(breakout_time)].)", \ "You hear a metallic creaking from [src].") @@ -191,4 +190,4 @@ brainwash(C, objective) message_admins("[ADMIN_LOOKUPFLW(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.") log_game("[key_name(user)] brainwashed [key_name(C)] with objective '[objective]'.") - return TRUE \ No newline at end of file + return TRUE diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index dda41494ff..e7cf8defc9 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -18,7 +18,7 @@ name = "fork" desc = "Pointy." icon_state = "fork" - force = 5 + force = 4 w_class = WEIGHT_CLASS_TINY throwforce = 0 throw_speed = 3 @@ -28,6 +28,7 @@ attack_verb = list("attacked", "stabbed", "poked") hitsound = 'sound/weapons/bladeslice.ogg' armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + sharpness = SHARP_POINTY var/datum/reagent/forkload //used to eat omelette /obj/item/kitchen/fork/suicide_act(mob/living/carbon/user) @@ -54,6 +55,14 @@ else return ..() +/obj/item/kitchen/fork/throwing + name = "throwing fork" + desc = "A fork, sharpened to perfection, making it a great weapon for throwing." + throwforce = 15 + throw_speed = 4 + throw_range = 6 + embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) + sharpness = SHARP_EDGED /obj/item/kitchen/knife name = "kitchen knife" @@ -68,9 +77,11 @@ throw_range = 6 custom_materials = list(/datum/material/iron=12000) attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY 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? + wound_bonus = -5 + bare_wound_bonus = 10 custom_price = PRICE_NORMAL /obj/item/kitchen/knife/Initialize() diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index ef5b7b6cba..b2f8b4bee2 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -54,5 +54,5 @@ var/obj/item/tank/T = W blow(T, user) return - if (W.get_sharpness() || W.get_temperature() || is_pointed(W)) + if (W.get_sharpness() || W.get_temperature()) burst() diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm index 6c01e68a48..0673e1d489 100644 --- a/code/game/objects/items/manuals.dm +++ b/code/game/objects/items/manuals.dm @@ -506,7 +506,9 @@ if(prob(50)) step(W, pick(GLOB.alldirs)) ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC) - H.bleed_rate = 5 + for(var/i in H.bodyparts) + var/obj/item/bodypart/BP = i + BP.generic_bleedstacks += 5 H.gib_animation() sleep(3) H.adjustBruteLoss(1000) //to make the body super-bloody diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index aec3c333b7..679491aeb6 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -102,7 +102,7 @@ attack_verb_off = list("tapped", "poked") throw_speed = 3 throw_range = 5 - sharpness = IS_SHARP + sharpness = SHARP_EDGED embedding = list("embed_chance" = 75, "impact_pain_mult" = 10) armour_penetration = 35 item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY @@ -147,6 +147,12 @@ return NONE return ..() +/obj/item/melee/transforming/energy/sword/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) + . = ..() + if(parry_efficiency >= 80) // perfect parry + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER + . |= BLOCK_SHOULD_REDIRECT + /obj/item/melee/transforming/energy/sword/cyborg sword_color = "red" light_color = "#ff0000" @@ -174,7 +180,7 @@ sword_color = null //stops icon from breaking when turned on. hitcost = 75 //Costs more than a standard cyborg esword w_class = WEIGHT_CLASS_NORMAL - sharpness = IS_SHARP + sharpness = SHARP_EDGED light_color = "#40ceff" tool_behaviour = TOOL_SAW toolspeed = 0.7 @@ -249,7 +255,7 @@ throw_range = 1 w_class = WEIGHT_CLASS_BULKY//So you can't hide it in your pocket or some such. var/datum/effect_system/spark_spread/spark_system - sharpness = IS_SHARP + sharpness = SHARP_EDGED //Most of the other special functions are handled in their own files. aka special snowflake code so kewl /obj/item/melee/transforming/energy/blade/Initialize() @@ -285,7 +291,7 @@ attack_verb_off = list("tapped", "poked") throw_speed = 3 throw_range = 5 - sharpness = IS_SHARP + sharpness = SHARP_EDGED embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 20, "embedded_fall_chance" = 60) armour_penetration = 10 block_chance = 35 @@ -369,7 +375,7 @@ return else to_chat(user, "You combine the two light swords, making a single supermassive blade! You're cool.") - new /obj/item/twohanded/dualsaber/hypereutactic(user.drop_location()) + new /obj/item/dualsaber/hypereutactic(user.drop_location()) qdel(W) qdel(src) else diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 741607edc3..01d2924a90 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -19,6 +19,8 @@ slot_flags = ITEM_SLOT_BELT force = 14 throwforce = 10 + wound_bonus = 15 + bare_wound_bonus = 10 reach = 2 w_class = WEIGHT_CLASS_NORMAL attack_verb = list("flogged", "whipped", "lashed", "disciplined") @@ -42,7 +44,7 @@ throwforce = 10 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "impaled", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED total_mass = TOTAL_MASS_HAND_REPLACEMENT /obj/item/melee/synthetic_arm_blade/Initialize() @@ -62,7 +64,7 @@ throwforce = 15 w_class = WEIGHT_CLASS_BULKY armour_penetration = 75 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("slashed", "cut") hitsound = 'sound/weapons/rapierhit.ogg' custom_materials = list(/datum/material/iron = 1000) @@ -166,7 +168,7 @@ flags_1 = CONDUCT_1 obj_flags = UNIQUE_RENAME w_class = WEIGHT_CLASS_BULKY - sharpness = IS_SHARP_ACCURATE //It cant be sharpend cook -_- + sharpness = SHARP_POINTY //It cant be sharpend cook -_- attack_verb = list("stabs", "punctures", "pierces", "pokes") hitsound = 'sound/weapons/rapierhit.ogg' total_mass = 0.4 @@ -268,6 +270,8 @@ var/force_off // Damage when off - not stunning var/weight_class_on // What is the new size class when turned on + wound_bonus = 15 + /obj/item/melee/classic_baton/Initialize() . = ..() @@ -371,6 +375,7 @@ var/wait_desc = get_wait_description() if(wait_desc) to_chat(user, wait_desc) + return DISCARD_LAST_ACTION /obj/item/melee/classic_baton/telescopic name = "telescopic baton" @@ -393,6 +398,7 @@ force_off = 0 weight_class_on = WEIGHT_CLASS_BULKY total_mass = TOTAL_MASS_NORMAL_ITEM + bare_wound_bonus = 5 /obj/item/melee/classic_baton/telescopic/suicide_act(mob/user) var/mob/living/carbon/human/H = user @@ -621,7 +627,7 @@ to_chat(user, "[target] doesn't seem to want to get on [src]!") update_icon() -/obj/item/melee/roastingstick/attack_hand(mob/user) +/obj/item/melee/roastingstick/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) ..() if (held_sausage) user.put_in_hands(held_sausage) @@ -689,7 +695,7 @@ item_state = "mace_greyscale" lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS //Material type changes the prefix as well as the color. + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Material type changes the prefix as well as the color. custom_materials = list(/datum/material/iron = 12000) //Defaults to an Iron Mace. slot_flags = ITEM_SLOT_BELT force = 14 diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm index 386a6e9acc..8c44a15cd4 100644 --- a/code/game/objects/items/melee/transforming.dm +++ b/code/game/objects/items/melee/transforming.dm @@ -1,5 +1,5 @@ /obj/item/melee/transforming - sharpness = IS_SHARP + sharpness = SHARP_EDGED var/active = FALSE var/force_on = 30 //force when active var/faction_bonus_force = 0 //Bonus force dealt against certain factions @@ -84,4 +84,4 @@ /obj/item/melee/transforming/proc/clumsy_transform_effect(mob/living/user) if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) to_chat(user, "You accidentally cut yourself with [src], like a doofus!") - user.take_bodypart_damage(5,5) \ No newline at end of file + user.take_bodypart_damage(5,5) diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm index 7237a1788f..6f1aec287b 100644 --- a/code/game/objects/items/miscellaneous.dm +++ b/code/game/objects/items/miscellaneous.dm @@ -18,6 +18,8 @@ icon = 'icons/obj/device.dmi' icon_state = "gangtool-blue" item_state = "radio" + var/list/stored_options + var/force_refresh = FALSE //if set to true, the beacon will recalculate its display options whenever opened /obj/item/choice_beacon/attack_self(mob/user) if(canUseBeacon(user)) @@ -34,18 +36,22 @@ return FALSE /obj/item/choice_beacon/proc/generate_options(mob/living/M) - var/list/display_names = generate_display_names() - if(!display_names.len) + if(!stored_options || force_refresh) + stored_options = generate_display_names() + if(!stored_options.len) return - var/choice = input(M,"Which item would you like to order?","Select an Item") as null|anything in display_names + var/choice = input(M,"Which item would you like to order?","Select an Item") as null|anything in stored_options if(!choice || !M.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return - spawn_option(display_names[choice],M) + spawn_option(stored_options[choice],M) qdel(src) -/obj/item/choice_beacon/proc/spawn_option(obj/choice,mob/living/M) - var/obj/new_item = new choice() +/obj/item/choice_beacon/proc/create_choice_atom(atom/choice, mob/owner) + return new choice() + +/obj/item/choice_beacon/proc/spawn_option(atom/choice,mob/living/M) + var/obj/new_item = create_choice_atom(choice, M) var/obj/structure/closet/supplypod/bluespacepod/pod = new() pod.explosionSize = list(0,0,0,0) new_item.forceMove(pod) @@ -149,10 +155,116 @@ augment_list[initial(A.name)] = A return augment_list -/obj/item/choice_beacon/augments/spawn_option(obj/choice,mob/living/M) +/obj/item/choice_beacon/augments/spawn_option(atom/choice,mob/living/M) new choice(get_turf(M)) to_chat(M, "You hear something crackle from the beacon for a moment before a voice speaks. \"Please stand by for a message from S.E.L.F. Message as follows: Item request received. Your package has been transported, use the autosurgeon supplied to apply the upgrade. Message ends.\"") +/obj/item/choice_beacon/pet //donator beacon that summons a small friendly animal + name = "pet beacon" + desc = "Straight from the outerspace pet shop to your feet." + var/static/list/pets = list("Crab" = /mob/living/simple_animal/crab, + "Cat" = /mob/living/simple_animal/pet/cat, + "Space cat" = /mob/living/simple_animal/pet/cat/space, + "Kitten" = /mob/living/simple_animal/pet/cat/kitten, + "Dog" = /mob/living/simple_animal/pet/dog, + "Corgi" = /mob/living/simple_animal/pet/dog/corgi, + "Pug" = /mob/living/simple_animal/pet/dog/pug, + "Exotic Corgi" = /mob/living/simple_animal/pet/dog/corgi/exoticcorgi, + "Fox" = /mob/living/simple_animal/pet/fox, + "Red Panda" = /mob/living/simple_animal/pet/redpanda, + "Possum" = /mob/living/simple_animal/opossum) + var/pet_name + +/obj/item/choice_beacon/pet/generate_display_names() + return pets + +/obj/item/choice_beacon/pet/create_choice_atom(atom/choice, mob/owner) + var/mob/living/simple_animal/new_choice = new choice() + new_choice.butcher_results = null //please don't eat your pet, chef + var/obj/item/pet_carrier/donator/carrier = new() //a donator pet carrier is just a carrier that can't be shoved in an autolathe for metal + carrier.add_occupant(new_choice) + new_choice.mob_size = MOB_SIZE_TINY //yeah we're not letting you use this roundstart pet to hurt people / knock them down + new_choice.pass_flags = PASSTABLE | PASSMOB //your pet is not a bullet/person shield + new_choice.density = FALSE + new_choice.blood_volume = 0 //your pet cannot be used to drain blood from for a bloodsucker + new_choice.desc = "A pet [initial(choice.name)], owned by [owner]!" + new_choice.can_have_ai = FALSE //no it cant be sentient damnit + if(pet_name) + new_choice.name = pet_name + new_choice.unique_name = TRUE + return carrier + +/obj/item/choice_beacon/pet/spawn_option(atom/choice,mob/living/M) + pet_name = input(M, "What would you like to name the pet? (leave blank for default name)", "Pet Name") + ..() + +//choice boxes (they just open in your hand instead of making a pod) +/obj/item/choice_beacon/box + name = "choice box (default)" + desc = "Think really hard about what you want, and then rip it open!" + icon = 'icons/obj/storage.dmi' + icon_state = "deliverypackage3" + item_state = "deliverypackage3" + +/obj/item/choice_beacon/box/spawn_option(atom/choice,mob/living/M) + var/choice_text = choice + if(ispath(choice_text)) + choice_text = initial(choice.name) + to_chat(M, "The box opens, revealing the [choice_text]!") + playsound(src.loc, 'sound/items/poster_ripped.ogg', 50, 1) + M.temporarilyRemoveItemFromInventory(src, TRUE) + M.put_in_hands(new choice) + qdel(src) + +/obj/item/choice_beacon/box/plushie/spawn_option(choice,mob/living/M) + if(ispath(choice, /obj/item/toy/plush)) + ..() //regular plush, spawn it naturally + else + //snowflake plush + var/obj/item/toy/plush/snowflake_plushie = new(get_turf(M)) + snowflake_plushie.set_snowflake_from_config(choice) + M.temporarilyRemoveItemFromInventory(src, TRUE) + M.put_in_hands(new choice) + qdel(src) + +/obj/item/choice_beacon/box/carpet //donator carpet beacon + name = "choice box (carpet)" + desc = "Contains 50 of a selected carpet inside!" + var/static/list/carpet_list = list(/obj/item/stack/tile/carpet/black/fifty = "Black Carpet", + "Black & Red Carpet" = /obj/item/stack/tile/carpet/blackred/fifty, + "Monochrome Carpet" = /obj/item/stack/tile/carpet/monochrome/fifty, + "Blue Carpet" = /obj/item/stack/tile/carpet/blue/fifty, + "Cyan Carpet" = /obj/item/stack/tile/carpet/cyan/fifty, + "Green Carpet" = /obj/item/stack/tile/carpet/green/fifty, + "Orange Carpet" = /obj/item/stack/tile/carpet/orange/fifty, + "Purple Carpet" = /obj/item/stack/tile/carpet/purple/fifty, + "Red Carpet" = /obj/item/stack/tile/carpet/red/fifty, + "Royal Black Carpet" = /obj/item/stack/tile/carpet/royalblack/fifty, + "Royal Blue Carpet" = /obj/item/stack/tile/carpet/royalblue/fifty) + +/obj/item/choice_beacon/box/carpet/generate_display_names() + return carpet_list + +/obj/item/choice_beacon/box/plushie + name = "choice box (plushie)" + desc = "Using the power of quantum entanglement, this box contains every plush, until the moment it is opened!" + icon = 'icons/obj/plushes.dmi' + icon_state = "box" + item_state = "box" + +/obj/item/choice_beacon/box/plushie/generate_display_names() + var/list/plushie_list = list() + //plushie set 1: just subtypes of /obj/item/toy/plush + var/list/plushies_set_one = subtypesof(/obj/item/toy/plush) - list(/obj/item/toy/plush/narplush, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random_snowflake, /obj/item/toy/plush/random) //don't allow these special ones (you can still get narplush/hugbox) + for(var/V in plushies_set_one) + var/atom/A = V + plushie_list[initial(A.name)] = A + //plushie set 2: snowflake plushies + var/list/plushies_set_two = CONFIG_GET(keyed_list/snowflake_plushies) + for(var/V in plushies_set_two) + plushie_list[V] = V //easiest way to do this which works with how selecting options works, despite being snowflakey to have the key equal the value + return plushie_list + /obj/item/skub desc = "It's skub." name = "skub" diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm index 3a06c7d7fe..b420bfc002 100644 --- a/code/game/objects/items/mop.dm +++ b/code/game/objects/items/mop.dm @@ -58,7 +58,7 @@ if(T) user.visible_message("[user] cleans \the [T] with [src].", "You clean \the [T] with [src].") clean(T) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) user.do_attack_animation(T, used_item = src) if(istype(L)) L.adjustStaminaLossBuffered(stamusage) @@ -128,4 +128,4 @@ return ..() /obj/item/mop/advanced/cyborg - insertable = FALSE \ No newline at end of file + insertable = FALSE diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index 9d9409acf0..ef2fb44d3d 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -22,6 +22,15 @@ var/occupant_weight = 0 var/max_occupants = 3 //Hard-cap so you can't have infinite mice or something in one carrier var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants + var/entrance_name = "door" //name of the entrance to the item + var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this) + var/alternate_escape_time = 0 //how long it takes for mobs to escape when the entrance is open + var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier + var/has_lock_sprites = TRUE //whether to load the lock overlays or not + var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it? + +/obj/item/pet_carrier/donator + custom_materials = null //you cant just use the loadout item to get free metal! /obj/item/pet_carrier/Destroy() if(occupants.len) @@ -51,20 +60,20 @@ else . += "It has nothing inside." if(user.canUseTopic(src)) - . += "Activate it in your hand to [open ? "close" : "open"] its door." + . += "Activate it in your hand to [open ? "close" : "open"] its [entrance_name]." if(!open) - . += "Alt-click to [locked ? "unlock" : "lock"] its door." + . += "Alt-click to [locked ? "unlock" : "lock"] its [entrance_name]." /obj/item/pet_carrier/attack_self(mob/living/user) if(open) - to_chat(user, "You close [src]'s door.") + to_chat(user, "You close [src]'s [entrance_name].") playsound(user, 'sound/effects/bin_close.ogg', 50, TRUE) open = FALSE else if(locked) to_chat(user, "[src] is locked!") return - to_chat(user, "You open [src]'s door.") + to_chat(user, "You open [src]'s [entrance_name].") playsound(user, 'sound/effects/bin_open.ogg', 50, TRUE) open = TRUE update_icon() @@ -86,7 +95,7 @@ if(user.a_intent == INTENT_HARM) return ..() if(!open) - to_chat(user, "You need to open [src]'s door!") + to_chat(user, "You need to open [src]'s [entrance_name]!") return if(target.mob_size > max_occupant_weight) if(ishuman(target)) @@ -94,13 +103,16 @@ if(iscatperson(H)) to_chat(user, "You'd need a lot of catnip and treats, plus maybe a laser pointer, for that to work.") else - to_chat(user, "Humans, generally, do not fit into pet carriers.") + to_chat(user, "Humans, generally, do not fit into [name]s.") else to_chat(user, "You get the feeling [target] isn't meant for a [name].") return if(user == target) to_chat(user, "Why would you ever do that?") return + if((ishostile(target) && (!allows_hostiles || !istype(target, /mob/living/simple_animal/hostile/carp/cayenne))) || target.move_resist >= MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in! + to_chat(user, "You have a feeling you shouldn't keep this as a pet.") + return load_occupant(user, target) /obj/item/pet_carrier/relaymove(mob/living/user, direction) @@ -110,8 +122,8 @@ remove_occupant(user) return else if(!locked) - loc.visible_message("[user] pushes open the door to [src]!", \ - "[user] pushes open the door of [src]!") + loc.visible_message("[user] pushes open the [entrance_name] to [src]!", \ + "[user] pushes open the [entrance_name] of [src]!") open = TRUE update_icon() return @@ -119,12 +131,24 @@ container_resist(user) /obj/item/pet_carrier/container_resist(mob/living/user) - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT + //don't do the whole resist timer thing if it's open! + if(open) + if(alternate_escape_time > 0) + loc.visible_message("The [src] begins to shake!") + if(do_after(user, alternate_escape_time, target = user)) + loc.visible_message("[user] jumps out of [src]") + remove_occupant(user) + return + else //instant escape, different message + loc.visible_message("[user] climbs out of [src]!", \ + "[user] jumps out of [src]!") + remove_occupant(user) + return + if(user.mob_size <= MOB_SIZE_SMALL) - to_chat(user, "You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)") - to_chat(loc, "You see [user] reach through the bars and fumble for the lock switch!") - if(!do_after(user, rand(300, 400), target = user) || open || !locked || !(user in occupants)) + to_chat(user, "You begin to try escaping the [src] and start fumbling for the lock switch... (This will take some time.)") + to_chat(loc, "You see [user] attempting to unlock the [src]!") + if(!do_after(user, rand(escape_time * 1.5, escape_time * 2), target = user) || open || !locked || !(user in occupants)) return loc.visible_message("[user] flips the lock switch on [src] by reaching through!", null, null, null, user) to_chat(user, "Bingo! The lock pops open!") @@ -132,12 +156,12 @@ playsound(src, 'sound/machines/boltsup.ogg', 30, TRUE) update_icon() else - loc.visible_message("[src] starts rattling as something pushes against the door!", null, null, null, user) - to_chat(user, "You start pushing out of [src]... (This will take about 20 seconds.)") - if(!do_after(user, 200, target = user) || open || !locked || !(user in occupants)) + loc.visible_message("[src] starts rattling as something pushes against the [entrance_name]!", null, null, null, user) + to_chat(user, "You start pushing out of [src]... (This will take about [escape_time/10] seconds.)") + if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants)) return loc.visible_message("[user] shoves out of [src]!", null, null, null, user) - to_chat(user, "You shove open [src]'s door against the lock's resistance and fall out!") + to_chat(user, "You shove open [src]'s [entrance_name] against the lock's resistance and fall out!") locked = FALSE open = TRUE update_icon() @@ -151,7 +175,7 @@ /obj/item/pet_carrier/update_overlays() . = ..() - if(!open) + if(!open && has_lock_sprites) . += "[locked ? "" : "un"]locked" /obj/item/pet_carrier/MouseDrop(atom/over_atom) @@ -166,21 +190,22 @@ /obj/item/pet_carrier/proc/load_occupant(mob/living/user, mob/living/target) if(pet_carrier_full(src)) to_chat(user, "[src] is already carrying too much!") - return + return FALSE user.visible_message("[user] starts loading [target] into [src].", \ "You start loading [target] into [src]...", null, null, target) to_chat(target, "[user] starts loading you into [user.p_their()] [name]!") - if(!do_mob(user, target, 30)) - return + if(!do_mob(user, target, load_time)) + return FALSE if(target in occupants) - return + return FALSE if(pet_carrier_full(src)) //Run the checks again, just in case to_chat(user, "[src] is already carrying too much!") - return + return FALSE user.visible_message("[user] loads [target] into [src]!", \ "You load [target] into [src].", null, null, target) to_chat(target, "[user] loads you into [user.p_their()] [name]!") add_occupant(target) + return TRUE /obj/item/pet_carrier/proc/add_occupant(mob/living/occupant) if(occupant in occupants || !istype(occupant)) @@ -192,9 +217,137 @@ /obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf) if(!(occupant in occupants) || !istype(occupant)) return - occupant.forceMove(new_turf ? new_turf : drop_location()) + occupant.forceMove(new_turf ? new_turf : get_turf(src)) occupants -= occupant occupant_weight -= occupant.mob_size occupant.setDir(SOUTH) +//bluespace jar, a reskin of the pet carrier that can fit people and smashes when thrown +/obj/item/pet_carrier/bluespace + name = "bluespace jar" + desc = "A jar, that seems to be bigger on the inside, somehow allowing lifeforms to fit through its narrow entrance." + open = FALSE //starts closed so it looks better on menus + icon_state = "bluespace_jar" + item_state = "bluespace_jar" + lefthand_file = "" + righthand_file = "" + max_occupant_weight = MOB_SIZE_HUMAN //can fit people, like a bluespace bodybag! + load_time = 40 //loading things into a jar takes longer than a regular pet carrier + entrance_name = "lid" + w_class = WEIGHT_CLASS_SMALL //it's a jar + throw_speed = 3 + throw_range = 7 + max_occupants = 1 //far less than a regular carrier or bluespace bodybag, because it can be thrown to release the contents + allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless + has_lock_sprites = FALSE //jar doesn't show the regular lock overlay + custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600) + escape_time = 200 //equal to the time of a bluespace bodybag + alternate_escape_time = 100 + + ///gas supply for simplemobs so they don't die + var/datum/gas_mixture/occupant_gas_supply + ///level until the reagent gets INGEST ed instead of TOUCH + var/sipping_level = 150 + ///prob50 level of sipping + var/sipping_probably = 99 + ///chem transfer rate / second + var/transfer_rate = 5 + +/obj/item/pet_carrier/bluespace/Initialize() + . = ..() + create_reagents(300, OPENCONTAINER, DEFAULT_REAGENTS_VALUE) //equivalent of bsbeakers + +/obj/item/pet_carrier/bluespace/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/pet_carrier/bluespace/attack_self(mob/living/user) + ..() + if(reagents) + if(open) + reagents.reagents_holder_flags = OPENCONTAINER + else + reagents.reagents_holder_flags = NONE + +/obj/item/pet_carrier/bluespace/update_icon_state() + if(open) + icon_state = "bluespace_jar_open" + else + icon_state = "bluespace_jar" + +/obj/item/pet_carrier/bluespace/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + . = ..() + //delete the item upon impact, releasing the creature inside (this is handled by its deletion) + if(occupants.len) + loc.visible_message("The bluespace jar smashes, releasing [occupants[1]]!") + + if(reagents?.total_volume && ismob(hit_atom) && hit_atom.reagents) + reagents.total_volume *= rand(5,10) * 0.1 //Not all of it makes contact with the target + var/mob/M = hit_atom + var/R = reagents.log_list() + hit_atom.visible_message("[M] has been splashed with something!", \ + "[M] has been splashed with something!") + var/turf/TT = get_turf(hit_atom) + var/throwerstring + if(thrownby) + log_combat(thrownby, M, "splashed", R) + var/turf/AT = get_turf(thrownby) + throwerstring = " THROWN BY [key_name(thrownby)] at [AT] (AREACOORD(AT)]" + log_reagent("SPLASH: [src] mob throw_impact() onto [key_name(hit_atom)] at [TT] ([AREACOORD(TT)])[throwerstring] - [R]") + reagents.reaction(hit_atom, TOUCH) + reagents.clear_reagents() + + playsound(src, "shatter", 70, 1) + qdel(src) + +/obj/item/pet_carrier/bluespace/add_occupant(mob/living/occupant) //update the gas supply as required, this acts like magical internals + . = ..() + if(!occupant_gas_supply) + occupant_gas_supply = new + + if(isanimal(occupant)) + var/mob/living/simple_animal/animal = occupant + occupant_gas_supply[/datum/gas/oxygen] = 0.0064 //make sure it has some gas in so it isn't depressurized + occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature/pressure when their turf isnt a location + + if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside + START_PROCESSING(SSobj, src) + ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist") + ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist") + ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath") + ADD_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure") + ADD_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure") + +/obj/item/pet_carrier/bluespace/remove_occupant(mob/living/occupant) + . = ..() + if(ishuman(occupant)) + STOP_PROCESSING(SSobj, src) + REMOVE_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist") + REMOVE_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist") + REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath") + REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure") + REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure") + name = initial(name) + +/obj/item/pet_carrier/bluespace/return_air() + if(!occupant_gas_supply) + occupant_gas_supply = new + return occupant_gas_supply + +/obj/item/pet_carrier/bluespace/process() + if(!reagents) + return + for(var/mob/living/L in occupants) + if(!ishuman(L)) + continue + if((reagents.total_volume >= sipping_level) || ((reagents.total_volume >= sipping_probably) && prob(50))) //sipp + reagents.reaction(L, INGEST) //consume + reagents.trans_to(L, transfer_rate) + else + reagents.reaction(L, TOUCH, show_message = FALSE) + +/obj/item/pet_carrier/bluespace/load_occupant(mob/living/user, mob/living/target) + if(..()) + name = "[initial(name)] ([target])" + #undef pet_carrier_full diff --git a/code/game/objects/items/pitchfork.dm b/code/game/objects/items/pitchfork.dm new file mode 100644 index 0000000000..b296e2d0cb --- /dev/null +++ b/code/game/objects/items/pitchfork.dm @@ -0,0 +1,101 @@ +/obj/item/pitchfork + icon_state = "pitchfork0" + lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' + name = "pitchfork" + desc = "A simple tool used for moving hay." + force = 7 + throwforce = 15 + w_class = WEIGHT_CLASS_BULKY + attack_verb = list("attacked", "impaled", "pierced") + hitsound = 'sound/weapons/bladeslice.ogg' + sharpness = SHARP_EDGED + max_integrity = 200 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) + resistance_flags = FIRE_PROOF + var/wielded = FALSE // track wielded status on item + +/obj/item/pitchfork/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/pitchfork/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=7, force_wielded=15, icon_wielded="pitchfork1") + AddElement(/datum/element/sword_point) + +/// triggered on wield of two handed item +/obj/item/pitchfork/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/pitchfork/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/pitchfork/update_icon_state() + icon_state = "pitchfork0" + +/obj/item/pitchfork/demonic + name = "demonic pitchfork" + desc = "A red pitchfork, it looks like the work of the devil." + force = 19 + throwforce = 24 + +/obj/item/pitchfork/demonic/Initialize() + . = ..() + set_light(3,6,LIGHT_COLOR_RED) + +/obj/item/pitchfork/demonic/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=19, force_wielded=25) + +/obj/item/pitchfork/demonic/greater + force = 24 + throwforce = 50 + +/obj/item/pitchfork/demonic/greater/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=24, force_wielded=34) + +/obj/item/pitchfork/demonic/ascended + force = 100 + throwforce = 100 + +/obj/item/pitchfork/demonic/ascended/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=100, force_wielded=500000) // Kills you DEAD + +/obj/item/pitchfork/suicide_act(mob/user) + user.visible_message("[user] impales [user.p_them()]self in [user.p_their()] abdomen with [src]! It looks like [user.p_theyre()] trying to commit suicide!") + return (BRUTELOSS) + +/obj/item/pitchfork/demonic/pickup(mob/living/user) + . = ..() + if(isliving(user) && user.mind && user.owns_soul() && !is_devil(user)) + var/mob/living/U = user + U.visible_message("As [U] picks [src] up, [U]'s arms briefly catch fire.", \ + "\"As you pick up [src] your arms ignite, reminding you of all your past sins.\"") + if(ishuman(U)) + var/mob/living/carbon/human/H = U + H.apply_damage(rand(force/2, force), BURN, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + else + U.adjustFireLoss(rand(force/2,force)) + +/obj/item/pitchfork/demonic/attack(mob/target, mob/living/carbon/human/user) + if(user.mind && user.owns_soul() && !is_devil(user)) + to_chat(user, "[src] burns in your hands.") + user.apply_damage(rand(force/2, force), BURN, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + ..() + +/obj/item/pitchfork/demonic/ascended/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity || !wielded) + return + if(iswallturf(target)) + var/turf/closed/wall/W = target + user.visible_message("[user] blasts \the [target] with \the [src]!") + playsound(target, 'sound/magic/disintegrate.ogg', 100, TRUE) + W.break_wall() + W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) + return diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 00a9ff22f4..a3da49ed89 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -8,6 +8,7 @@ resistance_flags = FLAMMABLE var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this var/stuffed = TRUE //If the plushie has stuffing in it + var/unstuffable = FALSE //for plushies that can't be stuffed var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses* //--love ~<3-- gender = NEUTER @@ -174,6 +175,9 @@ /obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params) if(I.get_sharpness()) if(!grenade) + if(unstuffable) + to_chat(user, "Nothing to do here.") + return if(!stuffed) to_chat(user, "You already murdered it!") return @@ -187,6 +191,13 @@ grenade = null return if(istype(I, /obj/item/grenade)) + if(unstuffable) + to_chat(user, "No... you should destroy it now!") + sleep(10) + if(QDELETED(user) || QDELETED(src)) + return + SEND_SOUND(user, 'sound/weapons/armbomb.ogg') + return if(stuffed) to_chat(user, "You need to remove some stuffing first!") return @@ -677,6 +688,18 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) icon_state = "scrubpuppy" item_state = "scrubpuppy" +/obj/item/toy/plush/borgplushie/meddrake + name = "MediDrake Plushie" + desc = "An adorable stuffed toy of a Medidrake." + icon_state = "meddrake" + item_state = "meddrake" + +/obj/item/toy/plush/borgplushie/secdrake + name = "SecDrake Plushie" + desc = "An adorable stuffed toy of a Secdrake." + icon_state = "secdrake" + item_state = "secdrake" + /obj/item/toy/plush/aiplush name = "AI plushie" desc = "A little stuffed toy AI core... it appears to be malfunctioning." @@ -743,3 +766,14 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) attack_verb = list("headbutt", "scritched", "bit") squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1) can_random_spawn = FALSE + + +/obj/item/toy/plush/hairball + name = "Hairball" + desc = "A bundle of undigested fibers and scales. Yuck." + icon_state = "Hairball" + unstuffable = TRUE + young = TRUE // Your own mouth-baby. + squeak_override = list('sound/misc/splort.ogg'=1) + attack_verb = list("sploshed", "splorted", "slushed") + can_random_spawn = FALSE diff --git a/code/game/objects/items/powerfist.dm b/code/game/objects/items/powerfist.dm index b7e2d22d2f..2834b3b758 100644 --- a/code/game/objects/items/powerfist.dm +++ b/code/game/objects/items/powerfist.dm @@ -14,12 +14,11 @@ w_class = WEIGHT_CLASS_NORMAL armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 40) resistance_flags = FIRE_PROOF - click_delay = CLICK_CD_MELEE * 1.5 + attack_speed = CLICK_CD_MELEE * 1.5 var/fisto_setting = 1 var/gasperfist = 3 var/obj/item/tank/internals/tank = null //Tank used for the gauntlet's piston-ram. - /obj/item/melee/powerfist/examine(mob/user) . = ..() if(!in_range(user, src)) @@ -98,7 +97,7 @@ target.visible_message("[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!", \ "[user]'s punch strikes with force!") return - target.apply_damage(totalitemdamage * fisto_setting, BRUTE) + target.apply_damage(totalitemdamage * fisto_setting, BRUTE, wound_bonus = -25*fisto_setting**2) target.visible_message("[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!", \ "You cry out in pain as [user]'s punch flings you backwards!") new /obj/effect/temp_visual/kinetic_blast(target.loc) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index 4b8728e426..6513b53e1d 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -355,6 +355,7 @@ emaggedhitdamage = 0 /obj/item/borg/lollipop/equipped() + . = ..() check_amount() /obj/item/borg/lollipop/dropped(mob/user) @@ -745,8 +746,8 @@ ***********************************************************************/ /obj/item/weapon/gripper - name = "circuit gripper" - desc = "A simple grasping tool for inserting circuitboards into machinary." + name = "engineering gripper" + desc = "A simple grasping tool for interacting with various engineering related items, such as circuits, gas tanks, conveyer belts and more. Alt click to drop instead of use." icon = 'icons/obj/device.dmi' icon_state = "gripper" @@ -754,18 +755,36 @@ //Has a list of items that it can hold. var/list/can_hold = list( - /obj/item/circuitboard + /obj/item/circuitboard, + /obj/item/light, + /obj/item/electronics, + /obj/item/tank, + /obj/item/conveyor_switch_construct, + /obj/item/stack/conveyor, + /obj/item/wallframe, + /obj/item/vending_refill, + /obj/item/stack/sheet, + /obj/item/stack/tile, + /obj/item/stack/rods, + /obj/item/stock_parts + ) + //Basically a blacklist for any subtypes above we dont want + var/list/cannot_hold = list( + /obj/item/stack/sheet/mineral/plasma, + /obj/item/stack/sheet/plasteel ) var/obj/item/wrapped = null // Item currently being held. -/obj/item/weapon/gripper/attack_self() +//Used to interact with UI's of held items, such as gas tanks and airlock electronics. +/obj/item/weapon/gripper/AltClick(mob/user) if(wrapped) wrapped.forceMove(get_turf(wrapped)) + to_chat(user, "You drop the [wrapped].") wrapped = null return ..() -/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/user, proximity, params) +/obj/item/weapon/gripper/pre_attack(var/atom/target, var/mob/living/silicon/robot/user, proximity, params) if(!proximity) return @@ -791,18 +810,21 @@ return else if(istype(target,/obj/item)) - var/obj/item/I = target - var/grab = 0 + for(var/typepath in can_hold) if(istype(I,typepath)) grab = 1 - break + for(var/badpath in cannot_hold) + if(istype(I,badpath)) + if(!user.emagged) + grab = 0 + continue //We can grab the item, finally. if(grab) - to_chat(user, "You collect \the [I].") + to_chat(user, "You collect \the [I].") I.loc = src wrapped = I return @@ -811,18 +833,24 @@ /obj/item/weapon/gripper/mining name = "shelter capsule deployer" - desc = "A simple grasping tool for carrying and deploying shelter capsules." + desc = "A simple grasping tool for carrying and deploying shelter capsules. Alt click to drop instead of use." icon_state = "gripper_mining" can_hold = list( /obj/item/survivalcapsule ) -/obj/item/weapon/gripper/mining/attack_self() - if(wrapped) - wrapped.forceMove(get_turf(wrapped)) - wrapped.attack_self() - wrapped = null - return +/obj/item/weapon/gripper/medical + name = "medical gripper" + desc = "A simple grasping tool for interacting with medical equipment, such as beakers, blood bags, chem bags and more. Alt click to drop instead of use." + icon_state = "gripper_medical" + can_hold = list( + /obj/item/storage/bag/bio, + /obj/item/storage/bag/chemistry, + /obj/item/storage/pill_bottle, + /obj/item/reagent_containers/glass, + /obj/item/reagent_containers/pill, + /obj/item/reagent_containers/blood + ) /obj/item/gun/energy/plasmacutter/cyborg name = "cyborg plasma cutter" @@ -906,6 +934,9 @@ icon_state = "data_1" +/********************************************************************** + Dogborg stuff +***********************************************************************/ ///Mere cosmetic dogborg items, remnants of what were once the most annoying cyborg modules. /obj/item/dogborg_tongue name = "synthetic tongue" diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index 08ce73109c..80fd177d84 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -6,21 +6,24 @@ desc = "Protected by FRM." icon = 'icons/obj/module.dmi' icon_state = "cyborg_upgrade" + w_class = WEIGHT_CLASS_SMALL var/locked = FALSE var/installed = 0 var/require_module = 0 var/list/module_type + /// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories. + var/module_flags = NONE // if true, is not stored in the robot to be ejected // if module is reset var/one_use = FALSE /obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R, user = usr) if(R.stat == DEAD) - to_chat(user, "[src] will not function on a deceased cyborg.") + to_chat(user, "[src] will not function on a deceased cyborg.") return FALSE if(module_type && !is_type_in_list(R.module, module_type)) - to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!") - to_chat(user, "There's no mounting point for the module!") + to_chat(R, "Upgrade mounting error! No suitable hardpoint detected.") + to_chat(user, "There's no mounting point for the module!") return FALSE return TRUE @@ -37,7 +40,7 @@ one_use = TRUE /obj/item/borg/upgrade/rename/attack_self(mob/user) - heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN) + heldname = sanitize_name(stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)) /obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R) . = ..() @@ -95,6 +98,7 @@ desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate." icon_state = "cyborg_upgrade3" require_module = 1 + module_flags = BORG_MODULE_SECURITY /obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -147,6 +151,7 @@ icon_state = "cyborg_upgrade3" require_module = 1 module_type = list(/obj/item/robot_module/miner) + module_flags = BORG_MODULE_MINER /obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -207,6 +212,7 @@ icon_state = "cyborg_upgrade3" require_module = 1 module_type = list(/obj/item/robot_module/butler) + module_flags = BORG_MODULE_JANITOR /obj/item/borg/upgrade/tboh/action(mob/living/silicon/robot/R) . = ..() @@ -234,6 +240,7 @@ icon_state = "cyborg_upgrade3" require_module = 1 module_type = list(/obj/item/robot_module/butler) + module_flags = BORG_MODULE_JANITOR /obj/item/borg/upgrade/amop/action(mob/living/silicon/robot/R) . = ..() @@ -241,9 +248,9 @@ for(var/obj/item/mop/cyborg/M in R.module.modules) R.module.remove_module(M, TRUE) - var/obj/item/mop/advanced/cyborg/A = new /obj/item/mop/advanced/cyborg(R.module) - R.module.basic_modules += A - R.module.add_module(A, FALSE, TRUE) + var/obj/item/mop/advanced/cyborg/A = new /obj/item/mop/advanced/cyborg(R.module) + R.module.basic_modules += A + R.module.add_module(A, FALSE, TRUE) /obj/item/borg/upgrade/amop/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() @@ -283,6 +290,7 @@ resistance_flags = LAVA_PROOF | FIRE_PROOF require_module = 1 module_type = list(/obj/item/robot_module/miner) + module_flags = BORG_MODULE_MINER /obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -402,6 +410,7 @@ module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical) var/list/additional_reagents = list() + module_flags = BORG_MODULE_MEDICAL /obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -459,7 +468,7 @@ /obj/item/borg/upgrade/defib/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() if (.) - var/obj/item/twohanded/shockpaddles/cyborg/S = locate() in R.module + var/obj/item/shockpaddles/cyborg/S = locate() in R.module R.module.remove_module(S, TRUE) /obj/item/borg/upgrade/processor @@ -471,6 +480,7 @@ require_module = 1 module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical) + module_flags = BORG_MODULE_MEDICAL /obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -545,7 +555,7 @@ to_chat(usr, "This unit already has an expand module installed!") return FALSE - R.notransform = TRUE + R.mob_transforming = TRUE var/prev_locked_down = R.locked_down R.SetLockdown(1) R.anchored = TRUE @@ -559,14 +569,14 @@ if(!prev_locked_down) R.SetLockdown(0) R.anchored = FALSE - R.notransform = FALSE + R.mob_transforming = FALSE R.resize = 2 R.hasExpanded = TRUE R.update_transform() /obj/item/borg/upgrade/expand/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() - if (.) + if (. && R.hasExpanded) R.resize = 0.5 R.hasExpanded = FALSE R.update_transform() @@ -578,6 +588,7 @@ icon_state = "borg_BS_RPED" require_module = TRUE module_type = list(/obj/item/robot_module/engineering, /obj/item/robot_module/saboteur) + module_flags = BORG_MODULE_ENGINEERING /obj/item/borg/upgrade/rped/action(mob/living/silicon/robot/R, user = usr) . = ..() @@ -612,8 +623,8 @@ icon = 'icons/obj/device.dmi' icon_state = "pinpointer_crew" require_module = TRUE - module_type = list(/obj/item/robot_module/medical, - /obj/item/robot_module/syndicate_medical) + module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical) + module_flags = BORG_MODULE_MEDICAL /obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr) . = ..() diff --git a/code/game/objects/items/sharpener.dm b/code/game/objects/items/sharpener.dm index 014d4cb159..fc19e61cd6 100644 --- a/code/game/objects/items/sharpener.dm +++ b/code/game/objects/items/sharpener.dm @@ -24,24 +24,22 @@ if(istype(I, /obj/item/melee/transforming/energy)) to_chat(user, "You don't think \the [I] will be the thing getting modified if you use it on \the [src]!") return - if(istype(I, /obj/item/twohanded))//some twohanded items should still be sharpenable, but handle force differently. therefore i need this stuff - var/obj/item/twohanded/TH = I - if(TH.force_wielded >= max) - to_chat(user, "[TH] is much too powerful to sharpen further!") - return - if(TH.wielded) - to_chat(user, "[TH] must be unwielded before it can be sharpened!") - return - if(TH.force_wielded > initial(TH.force_wielded)) - to_chat(user, "[TH] has already been refined before. It cannot be sharpened further!") - return - TH.force_wielded = clamp(TH.force_wielded + increment, 0, max)//wieldforce is increased since normal force wont stay - if(I.force > initial(I.force)) + + var/signal_out = SEND_SIGNAL(I, COMSIG_ITEM_SHARPEN_ACT, increment, max) + if(signal_out & COMPONENT_BLOCK_SHARPEN_MAXED) + to_chat(user, "[I] is much too powerful to sharpen further!") + return + if(signal_out & COMPONENT_BLOCK_SHARPEN_BLOCKED) + to_chat(user, "[I] is not able to be sharpened right now!") + return + if((signal_out & COMPONENT_BLOCK_SHARPEN_ALREADY) || (I.force > initial(I.force) && !signal_out)) to_chat(user, "[I] has already been refined before. It cannot be sharpened further!") return + if(!(signal_out & COMPONENT_BLOCK_SHARPEN_APPLIED)) + I.force = clamp(I.force + increment, 0, max) + user.visible_message("[user] sharpens [I] with [src]!", "You sharpen [I], making it much more deadly than before.") - I.sharpness = IS_SHARP_ACCURATE - I.force = clamp(I.force + increment, 0, max) + I.sharpness = SHARP_POINTY I.throwforce = clamp(I.throwforce + increment, 0, max) I.name = "[prefix] [I.name]" name = "worn out [name]" diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index aefa5d3cc8..4952c93928 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -26,7 +26,7 @@ /datum/block_parry_data/shield block_damage_multiplier = 0.25 block_stamina_efficiency = 2.5 - block_stamina_cost_per_second = 3.5 + block_stamina_cost_per_second = 2.5 block_slowdown = 0 block_lock_attacking = FALSE block_lock_sprinting = TRUE @@ -106,8 +106,8 @@ var/disarming = (target_downed && (shield_flags & SHIELD_BASH_GROUND_SLAM_DISARM)) || (shield_flags & SHIELD_BASH_ALWAYS_DISARM) || (wallhit && (shield_flags & SHIELD_BASH_WALL_DISARM)) var/knockdown = !target_downed && ((shield_flags & SHIELD_BASH_ALWAYS_KNOCKDOWN) || (wallhit && (shield_flags & SHIELD_BASH_WALL_KNOCKDOWN))) if(shieldbash_stagger_duration || knockdown) - target.visible_message("[target] is knocked [knockdown? "to the floor" : "off balanace"]!", - "You are knocked [knockdown? "to the floor" : "off balanace"]!") + target.visible_message("[target] is knocked [knockdown? "to the floor" : "off balance"]!", + "You are knocked [knockdown? "to the floor" : "off balance"]!") if(knockdown) target.KnockToFloor(disarming) else if(disarming) @@ -386,7 +386,7 @@ obj/item/shield/riot/bullet_proof max_integrity = 100 obj_integrity = 100 can_shatter = FALSE - item_flags = SLOWS_WHILE_IN_HAND + item_flags = SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK var/recharge_timerid var/recharge_delay = 15 SECONDS @@ -446,6 +446,12 @@ obj/item/shield/riot/bullet_proof return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT return ..() +/obj/item/shield/energy/active_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction) + if((attack_type & ATTACK_TYPE_PROJECTILE) && is_energy_reflectable_projectile(object)) + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT + return ..() + /obj/item/shield/energy/attack_self(mob/living/carbon/human/user) if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) to_chat(user, "You beat yourself in the head with [src]!") diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 2f40604719..ced0ee3160 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -31,10 +31,7 @@ to_chat(user, "You slice off [src]'s uneven chunks of aluminium and scorch marks.") return TRUE -/obj/item/target/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/target/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(pinnedLoc) pinnedLoc.removeTarget(user) diff --git a/code/game/objects/items/shrapnel.dm b/code/game/objects/items/shrapnel.dm index 7108080ecc..5904cb6c0b 100644 --- a/code/game/objects/items/shrapnel.dm +++ b/code/game/objects/items/shrapnel.dm @@ -7,11 +7,13 @@ icon_state = "large" w_class = WEIGHT_CLASS_TINY item_flags = DROPDEL + sharpness = SHARP_EDGED /obj/item/shrapnel/stingball // stingbang grenades name = "stingball" embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15, embed_chance_turf_mod=-100) icon_state = "tiny" + sharpness = SHARP_NONE /obj/item/shrapnel/bullet // bullets name = "bullet" @@ -28,21 +30,24 @@ /obj/item/projectile/bullet/shrapnel name = "flying shrapnel shard" - damage = 9 - range = 10 + damage = 14 + range = 20 armour_penetration = -30 dismemberment = 5 ricochets_max = 2 - ricochet_chance = 40 + ricochet_chance = 70 shrapnel_type = /obj/item/shrapnel ricochet_incidence_leeway = 60 + sharpness = SHARP_EDGED + wound_bonus = 40 /obj/item/projectile/bullet/shrapnel/mega name = "flying shrapnel hunk" - range = 25 - dismemberment = 10 - ricochets_max = 4 - ricochet_chance = 90 + range = 45 + dismemberment = 15 + ricochets_max = 6 + ricochet_chance = 130 + ricochet_incidence_leeway = 0 ricochet_decay_chance = 0.9 /obj/item/projectile/bullet/pellet/stingball @@ -62,3 +67,15 @@ name = "megastingball pellet" ricochets_max = 6 ricochet_chance = 110 + +/obj/item/projectile/bullet/pellet/stingball/breaker + name = "breakbang pellet" + damage = 10 + wound_bonus = 40 + sharpness = SHARP_NONE + +/obj/item/projectile/bullet/pellet/stingball/shred + name = "shredbang pellet" + damage = 10 + wound_bonus = 30 + sharpness = SHARP_EDGED diff --git a/code/game/objects/items/signs.dm b/code/game/objects/items/signs.dm index cf7373b700..67bc28b2ea 100644 --- a/code/game/objects/items/signs.dm +++ b/code/game/objects/items/signs.dm @@ -40,4 +40,3 @@ user.visible_message("[user] waves around \the \"[label]\" sign.") else user.visible_message("[user] waves around blank sign.") - user.changeNext_move(CLICK_CD_MELEE) \ No newline at end of file diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm index dc761ee3bf..7a6c159160 100644 --- a/code/game/objects/items/singularityhammer.dm +++ b/code/game/objects/items/singularityhammer.dm @@ -1,4 +1,4 @@ -/obj/item/twohanded/singularityhammer +/obj/item/singularityhammer name = "singularity hammer" desc = "The pinnacle of close combat technology, the hammer harnesses the power of a miniaturized singularity to deal crushing blows." icon_state = "mjollnir0" @@ -7,35 +7,47 @@ flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BACK force = 5 - force_unwielded = 5 - force_wielded = 20 throwforce = 15 throw_range = 1 w_class = WEIGHT_CLASS_HUGE - var/charged = 5 armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) resistance_flags = FIRE_PROOF | ACID_PROOF force_string = "LORD SINGULOTH HIMSELF" total_mass = TOTAL_MASS_MEDIEVAL_WEAPON + var/charged = 5 + var/wielded = FALSE // track wielded status on item -/obj/item/twohanded/singularityhammer/New() +/obj/item/singularityhammer/New() ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) START_PROCESSING(SSobj, src) -/obj/item/twohanded/singularityhammer/Destroy() +/obj/item/singularityhammer/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_multiplier=4, icon_wielded="mjollnir1") + +/// triggered on wield of two handed item +/obj/item/singularityhammer/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/singularityhammer/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/singularityhammer/update_icon_state() + icon_state = "mjollnir0" + +/obj/item/singularityhammer/Destroy() STOP_PROCESSING(SSobj, src) return ..() -/obj/item/twohanded/singularityhammer/process() +/obj/item/singularityhammer/process() if(charged < 5) charged++ return -/obj/item/twohanded/singularityhammer/update_icon_state() //Currently only here to fuck with the on-mob icons. - icon_state = "mjollnir[wielded]" - return - -/obj/item/twohanded/singularityhammer/proc/vortex(turf/pull, mob/wielder) +/obj/item/singularityhammer/proc/vortex(turf/pull, mob/wielder) for(var/atom/X in orange(5,pull)) if(ismovable(X)) var/atom/movable/A = X @@ -55,9 +67,8 @@ step_towards(H,pull) step_towards(H,pull) step_towards(H,pull) - return -/obj/item/twohanded/singularityhammer/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity) +/obj/item/singularityhammer/afterattack(atom/A as mob|obj|turf|area, mob/user, proximity) . = ..() if(!proximity) return @@ -71,7 +82,7 @@ var/turf/target = get_turf(A) vortex(target,user) -/obj/item/twohanded/mjollnir +/obj/item/mjollnir name = "Mjolnir" desc = "A weapon worthy of a god, able to strike with the force of a lightning bolt. It crackles with barely contained energy." icon_state = "mjollnir0" @@ -80,14 +91,33 @@ flags_1 = CONDUCT_1 slot_flags = ITEM_SLOT_BACK force = 5 - force_unwielded = 5 - force_wielded = 25 throwforce = 30 throw_range = 7 w_class = WEIGHT_CLASS_HUGE total_mass = TOTAL_MASS_MEDIEVAL_WEAPON + var/wielded = FALSE // track wielded status on item -/obj/item/twohanded/mjollnir/proc/shock(mob/living/target) +/obj/item/mjollnir/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/mjollnir/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_multiplier=5, icon_wielded="mjollnir1", attacksound="sparks") + +/// triggered on wield of two handed item +/obj/item/mjollnir/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/mjollnir/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/mjollnir/update_icon_state() + icon_state = "mjollnir0" + +/obj/item/mjollnir/proc/shock(mob/living/target) target.Stun(60) var/datum/effect_system/lightning_spread/s = new /datum/effect_system/lightning_spread s.set_up(5, 1, target.loc) @@ -99,17 +129,12 @@ target.throw_at(throw_target, 200, 4) return -/obj/item/twohanded/mjollnir/attack(mob/living/M, mob/user) +/obj/item/mjollnir/attack(mob/living/M, mob/user) ..() if(wielded) - playsound(src.loc, "sparks", 50, 1) shock(M) -/obj/item/twohanded/mjollnir/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) +/obj/item/mjollnir/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(isliving(hit_atom)) shock(hit_atom) - -/obj/item/twohanded/mjollnir/update_icon_state() //Currently only here to fuck with the on-mob icons. - icon_state = "mjollnir[wielded]" - return diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm new file mode 100644 index 0000000000..f40c774551 --- /dev/null +++ b/code/game/objects/items/spear.dm @@ -0,0 +1,187 @@ +//spears +/obj/item/spear + icon_state = "spearglass0" + lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' + name = "spear" + desc = "A haphazardly-constructed yet still deadly weapon of ancient design." + force = 10 + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK + throwforce = 20 + throw_speed = 4 + embedding = list("impact_pain_mult" = 3) + armour_penetration = 10 + custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075) + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") + sharpness = SHARP_EDGED + max_integrity = 200 + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + var/obj/item/grenade/explosive = null + var/war_cry = "AAAAARGH!!!" + var/icon_prefix = "spearglass" + var/wielded = FALSE // track wielded status on item + wound_bonus = -15 + bare_wound_bonus = 15 + +/obj/item/spear/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/spear/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 100, 70) //decent in a pinch, but pretty bad. + AddComponent(/datum/component/jousting) + AddElement(/datum/element/sword_point) + AddComponent(/datum/component/two_handed, force_unwielded=10, force_wielded=18, icon_wielded="[icon_prefix]1") + +/// triggered on wield of two handed item +/obj/item/spear/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/spear/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/spear/rightclick_attack_self(mob/user) + if(explosive) + explosive.attack_self(user) + return + . = ..() + +/obj/item/spear/update_icon_state() + icon_state = "[icon_prefix]0" + +/obj/item/spear/update_overlays() + . = ..() + if(explosive) + . += "spearbomb_overlay" + +/obj/item/spear/suicide_act(mob/living/carbon/user) + user.visible_message("[user] begins to sword-swallow \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") + if(explosive) //Citadel Edit removes qdel and explosive.forcemove(AM) + user.say("[war_cry]", forced="spear warcry") + explosive.prime() + user.gib() + return BRUTELOSS + return BRUTELOSS + +/obj/item/spear/examine(mob/user) + . = ..() + if(explosive) + . += "Alt-click to set your war cry." + . += "Right-click in combat mode to activate the attached explosive." + +/obj/item/spear/afterattack(atom/movable/AM, mob/user, proximity) + . = ..() + if(!proximity) + return + if(isopenturf(AM)) //So you can actually melee with it + return + if(explosive && wielded) //Citadel edit removes qdel and explosive.forcemove(AM) + user.say("[war_cry]", forced="spear warcry") + explosive.prime() + +/obj/item/spear/grenade_prime_react(obj/item/grenade/nade) //Citadel edit, removes throw_impact because memes + nade.forceMove(get_turf(src)) + qdel(src) + +/obj/item/spear/AltClick(mob/user) + . = ..() + if(user.canUseTopic(src, BE_CLOSE)) + ..() + if(!explosive) + return + if(istype(user) && loc == user) + var/input = stripped_input(user,"What do you want your war cry to be? You will shout it when you hit someone in melee.", ,"", 50) + if(input) + src.war_cry = input + return TRUE + +/obj/item/spear/CheckParts(list/parts_list) + var/obj/item/shard/tip = locate() in parts_list + if (istype(tip, /obj/item/shard/plasma)) + throwforce = 21 + embedding = list(embed_chance = 75, pain_mult = 1.5) //plasmaglass spears are sharper + updateEmbedding() + icon_prefix = "spearplasma" + AddComponent(/datum/component/two_handed, force_unwielded=11, force_wielded=19, icon_wielded="[icon_prefix]1") + qdel(tip) + var/obj/item/spear/S = locate() in parts_list + if(S) + if(S.explosive) + S.explosive.forceMove(get_turf(src)) + S.explosive = null + parts_list -= S + qdel(S) + ..() + var/obj/item/grenade/G = locate() in contents + if(G) + explosive = G + name = "explosive lance" + embedding = list(embed_chance = 0, pain_mult = 1)//elances should not be embeddable + updateEmbedding() + desc = "A makeshift spear with \a [G] attached to it." + update_icon() + +//GREY TIDE +/obj/item/spear/grey_tide + icon_state = "spearglass0" + name = "\improper Grey Tide" + desc = "Recovered from the aftermath of a revolt aboard Defense Outpost Theta Aegis, in which a seemingly endless tide of Assistants caused heavy casualities among Nanotrasen military forces." + throwforce = 20 + throw_speed = 4 + attack_verb = list("gored") + var/clonechance = 50 + var/clonedamage = 12 + var/clonespeed = 0 + var/clone_replication_chance = 30 + var/clone_lifespan = 100 + +/obj/item/spear/grey_tide/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=15, force_wielded=25, icon_wielded="[icon_prefix]1") + +/obj/item/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) + . = ..() + if(!proximity) + return + user.faction |= "greytide([REF(user)])" + if(isliving(AM)) + var/mob/living/L = AM + if(istype (L, /mob/living/simple_animal/hostile/illusion)) + return + if(!L.stat && prob(clonechance)) + var/mob/living/simple_animal/hostile/illusion/M = new(user.loc) + M.faction = user.faction.Copy() + M.set_varspeed(clonespeed) + M.Copy_Parent(user, clone_lifespan, user.health/2.5, clonedamage, clone_replication_chance) + M.GiveTarget(L) + +/* + * Bone Spear + */ +/obj/item/spear/bonespear //Blatant imitation of spear, but made out of bone. Not valid for explosive modification. + icon_state = "bone_spear0" + lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' + name = "bone spear" + desc = "A haphazardly-constructed yet still deadly weapon. The pinnacle of modern technology." + force = 11 + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK + reach = 2 + throwforce = 22 + embedding = list("embedded_impact_pain_multiplier" = 3) + armour_penetration = 15 //Enhanced armor piercing + custom_materials = null + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") + sharpness = SHARP_EDGED + icon_prefix = "bone_spear" + +/obj/item/spear/bonespear/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, force_unwielded=11, force_wielded=20, icon_wielded="[icon_prefix]1") diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index 00e48fd12a..3b4be37cee 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -74,8 +74,7 @@ /obj/item/stack/sheet/bluespace_crystal/attack_self(mob/user)// to prevent the construction menu from ever happening to_chat(user, "You cannot crush the polycrystal in-hand, try breaking one off.") -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/stack/sheet/bluespace_crystal/attack_hand(mob/user) +/obj/item/stack/sheet/bluespace_crystal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.get_inactive_held_item() == src) if(zero_amount()) return diff --git a/code/game/objects/items/stacks/cash.dm b/code/game/objects/items/stacks/cash.dm index ce0bc6591a..954950f5e6 100644 --- a/code/game/objects/items/stacks/cash.dm +++ b/code/game/objects/items/stacks/cash.dm @@ -11,6 +11,7 @@ w_class = WEIGHT_CLASS_TINY full_w_class = WEIGHT_CLASS_TINY resistance_flags = FLAMMABLE + grind_results = list(/datum/reagent/cellulose = 10) var/value = 0 /obj/item/stack/spacecash/Initialize() diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index e6403e83cc..7ba2196184 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -15,11 +15,20 @@ var/self_delay = 50 var/other_delay = 0 var/repeating = FALSE + /// How much brute we heal per application + var/heal_brute + /// How much burn we heal per application + var/heal_burn + /// How much we reduce bleeding per application on cut wounds + var/stop_bleeding + /// How much sanitization to apply to burns on application + var/sanitization + /// How much we add to flesh_healing for burn wounds on application + var/flesh_regeneration /obj/item/stack/medical/attack(mob/living/M, mob/user) . = ..() - try_heal(M, user) - + INVOKE_ASYNC(src, .proc/try_heal, M, user) /obj/item/stack/medical/proc/try_heal(mob/living/M, mob/user, silent = FALSE) if(!M.can_inject(user, TRUE)) @@ -70,8 +79,9 @@ icon_state = "brutepack" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' - var/heal_brute = 20 - self_delay = 20 + heal_brute = 40 + self_delay = 40 + other_delay = 20 grind_results = list(/datum/reagent/medicine/styptic_powder = 10) /obj/item/stack/medical/bruise_pack/one @@ -95,7 +105,8 @@ M.heal_bodypart_damage((heal_brute/2)) return TRUE if(iscarbon(M)) - return heal_carbon(M, user, heal_brute, 0) + return heal_carbon(M, user, heal_brute, heal_burn) + to_chat(user, "You can't heal [M] with \the [src]!") to_chat(user, "You can't heal [M] with the \the [src]!") /obj/item/stack/medical/bruise_pack/suicide_act(mob/user) @@ -104,24 +115,52 @@ /obj/item/stack/medical/gauze name = "medical gauze" - desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, heals minor wounds." + desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns to broken bones." gender = PLURAL singular_name = "medical gauze" icon_state = "gauze" - var/stop_bleeding = 1800 - var/heal_brute = 5 - self_delay = 10 + heal_brute = 5 + self_delay = 50 + other_delay = 20 + amount = 10 + max_amount = 10 + absorption_rate = 0.25 + absorption_capacity = 5 + splint_factor = 0.35 custom_price = PRICE_REALLY_CHEAP + grind_results = list(/datum/reagent/cellulose = 2) -/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression - H.suppress_bloodloss(stop_bleeding) - to_chat(user, "You stop the bleeding of [M]!") - H.adjustBruteLoss(-(heal_brute)) - return TRUE - to_chat(user, "You can not use \the [src] on [M]!") +// gauze is only relevant for wounds, which are handled in the wounds themselves +/obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent) + var/obj/item/bodypart/limb = M.get_bodypart(check_zone(user.zone_selected)) + if(!limb) + to_chat(user, "There's nothing there to bandage!") + return + if(!LAZYLEN(limb.wounds)) + to_chat(user, "There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!") // good problem to have imo + return + + var/gauzeable_wound = FALSE + for(var/i in limb.wounds) + var/datum/wound/woundies = i + if(woundies.wound_flags & ACCEPTS_GAUZE) + gauzeable_wound = TRUE + break + if(!gauzeable_wound) + to_chat(user, "There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!") // good problem to have imo + return + + if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 0.8 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row + to_chat(user, "The bandage currently on [user==M ? "your" : "[M]'s"] [limb.name] is still in good condition!") + return + + user.visible_message("[user] begins wrapping the wounds on [M]'s [limb.name] with [src]...", "You begin wrapping the wounds on [user == M ? "your" : "[M]'s"] [limb.name] with [src]...") + + if(!do_after(user, (user == M ? self_delay : other_delay), target=M)) + return + + user.visible_message("[user] applies [src] to [M]'s [limb.name].", "You bandage the wounds on [user == M ? "yourself" : "[M]'s"] [limb.name].") + limb.apply_gauze(src) /obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params) if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness()) @@ -133,6 +172,14 @@ "You cut [src] into pieces of cloth with [I].", \ "You hear cutting.") use(2) + else if(I.is_drainable() && I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine)) + if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 10)) + to_chat(user, "There's not enough sterilizine in [I] to sterilize [src]!") + return + user.visible_message("[user] pours the contents of [I] onto [src], sterilizing it.", "You pour the contents of [I] onto [src], sterilizing it.") + I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 10) + new /obj/item/stack/medical/gauze/adv/one(user.drop_location()) + use(1) else return ..() @@ -143,15 +190,22 @@ /obj/item/stack/medical/gauze/improvised name = "improvised gauze" singular_name = "improvised gauze" - desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds." - stop_bleeding = 900 heal_brute = 0 + desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently than real medical gauze." + self_delay = 60 + other_delay = 30 + absorption_rate = 0.15 + absorption_capacity = 4 /obj/item/stack/medical/gauze/adv name = "sterilized medical gauze" - desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding, heals minor wounds and cleans them." singular_name = "sterilized medical gauze" - self_delay = 5 + desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding and covering burns." + heal_brute = 6 + self_delay = 45 + other_delay = 15 + absorption_rate = 0.4 + absorption_capacity = 6 /obj/item/stack/medical/gauze/adv/one amount = 1 @@ -161,38 +215,9 @@ is_cyborg = 1 cost = 250 -/obj/item/stack/medical/ointment - name = "ointment" - desc = "Used to treat those nasty burn wounds." - gender = PLURAL - singular_name = "ointment" - icon_state = "ointment" - lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' - var/heal_burn = 20 - 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()]!") - return - if(iscarbon(M)) - return heal_carbon(M, user, 0, heal_burn) - if(AmBloodsucker(M)) - return - to_chat(user, "You can't heal [M] with the \the [src]!") - -/obj/item/stack/medical/ointment/suicide_act(mob/living/user) - user.visible_message("[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?") - return TOXLOSS - /obj/item/stack/medical/suture name = "suture" - desc = "Sterile sutures used to seal up cuts and lacerations." + desc = "Basic sterile sutures used to seal up cuts and lacerations and stop bleeding." gender = PLURAL singular_name = "suture" icon_state = "suture" @@ -201,9 +226,30 @@ amount = 15 max_amount = 15 repeating = TRUE - var/heal_brute = 10 + heal_brute = 10 + stop_bleeding = 0.6 grind_results = list(/datum/reagent/medicine/spaceacillin = 2) +/obj/item/stack/medical/suture/emergency + name = "emergency suture" + desc = "A value pack of cheap sutures, not very good at repairing damage, but still decent at stopping bleeding." + heal_brute = 5 + amount = 5 + max_amount = 5 + +/obj/item/stack/medical/suture/one + amount = 1 + +/obj/item/stack/medical/suture/five + amount = 5 + +/obj/item/stack/medical/suture/medicated + name = "medicated suture" + icon_state = "suture_purp" + desc = "A suture infused with drugs that speed up wound healing of the treated laceration." + heal_brute = 15 + grind_results = list(/datum/reagent/medicine/polypyr = 2) + /obj/item/stack/medical/suture/one amount = 1 @@ -223,10 +269,39 @@ to_chat(user, "[M] is at full health.") return FALSE user.visible_message("[user] applies \the [src] on [M].", "You apply \the [src] on [M].") - M.heal_bodypart_damage(heal_brute) - return TRUE + return heal_carbon(M, user, heal_brute, heal_burn) - to_chat(user, "You can't heal [M] with the \the [src]!") + to_chat(user, "You can't heal [M] with \the [src]!") + +/obj/item/stack/medical/ointment + name = "ointment" + desc = "Basic burn ointment, rated effective for second degree burns with proper bandaging, though it's still an effective stabilizer for worse burns. Not terribly good at outright healing burns though." + gender = PLURAL + singular_name = "ointment" + icon_state = "ointment" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + amount = 12 + max_amount = 12 + self_delay = 40 + other_delay = 20 + + heal_burn = 5 + flesh_regeneration = 2.5 + sanitization = 0.3 + grind_results = list(/datum/reagent/medicine/kelotane = 10) + +/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()].") + return + if(iscarbon(M)) + return heal_carbon(M, user, heal_brute, heal_burn) + to_chat(user, "You can't heal [M] with \the [src]!") + +/obj/item/stack/medical/ointment/suicide_act(mob/living/user) + user.visible_message("[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?") + return TOXLOSS /obj/item/stack/medical/mesh name = "regenerative mesh" @@ -238,20 +313,43 @@ other_delay = 10 amount = 15 max_amount = 15 + heal_burn = 10 repeating = TRUE - var/heal_burn = 10 + sanitization = 0.75 + flesh_regeneration = 3 var/is_open = TRUE ///This var determines if the sterile packaging of the mesh has been opened. grind_results = list(/datum/reagent/medicine/spaceacillin = 2) /obj/item/stack/medical/mesh/one amount = 1 +/obj/item/stack/medical/mesh/five + amount = 5 + +/obj/item/stack/medical/mesh/advanced + name = "advanced regenerative mesh" + desc = "An advanced mesh made with aloe extracts and sterilizing chemicals, used to treat burns." + gender = PLURAL + singular_name = "advanced regenerative mesh" + icon_state = "aloe_mesh" + heal_burn = 15 + grind_results = list(/datum/reagent/consumable/aloejuice = 1) + +/obj/item/stack/medical/mesh/advanced/one + amount = 1 + /obj/item/stack/medical/mesh/Initialize() . = ..() if(amount == max_amount) //only seal full mesh packs is_open = FALSE update_icon() +/obj/item/stack/medical/mesh/advanced/update_icon_state() + if(!is_open) + icon_state = "aloe_mesh_closed" + else + return ..() + /obj/item/stack/medical/mesh/update_icon_state() if(!is_open) icon_state = "regen_mesh_closed" @@ -264,8 +362,8 @@ to_chat(user, "[M] is dead! You can not help [M.p_them()].") return if(iscarbon(M)) - return heal_carbon(M, user, 0, heal_burn) - to_chat(user, "You can't heal [M] with the \the [src]!") + return heal_carbon(M, user, heal_brute, heal_burn) + to_chat(user, "You can't heal [M] with \the [src]!") /obj/item/stack/medical/mesh/try_heal(mob/living/M, mob/user, silent = FALSE) @@ -280,7 +378,7 @@ return . = ..() -/obj/item/stack/medical/mesh/attack_hand(mob/user) +/obj/item/stack/medical/mesh/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!is_open & user.get_inactive_held_item() == src) to_chat(user, "You need to open [src] first.") return @@ -294,3 +392,83 @@ playsound(src, 'sound/items/poster_ripped.ogg', 20, TRUE) return . = ..() + +/obj/item/stack/medical/bone_gel + name = "bone gel" + singular_name = "bone gel" + desc = "A potent medical gel that, when applied to a damaged bone in a proper surgical setting, triggers an intense melding reaction to repair the wound. Can be directly applied alongside surgical sticky tape to a broken bone in dire circumstances, though this is very harmful to the patient and not recommended." + + icon = 'icons/obj/surgery.dmi' + icon_state = "bone-gel" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + + amount = 4 + self_delay = 20 + grind_results = list(/datum/reagent/medicine/bicaridine = 10) + novariants = TRUE + +/obj/item/stack/medical/bone_gel/attack(mob/living/M, mob/user) + to_chat(user, "Bone gel can only be used on fractured limbs while aggressively holding someone!") + return + +/obj/item/stack/medical/bone_gel/suicide_act(mob/user) + if(iscarbon(user)) + var/mob/living/carbon/C = user + C.visible_message("[C] is squirting all of \the [src] into [C.p_their()] mouth! That's not proper procedure! It looks like [C.p_theyre()] trying to commit suicide!") + if(do_after(C, 2 SECONDS)) + C.emote("scream") + for(var/i in C.bodyparts) + var/obj/item/bodypart/bone = i + var/datum/wound/blunt/severe/oof_ouch = new + oof_ouch.apply_wound(bone) + var/datum/wound/blunt/critical/oof_OUCH = new + oof_OUCH.apply_wound(bone) + + for(var/i in C.bodyparts) + var/obj/item/bodypart/bone = i + bone.receive_damage(brute=60) + use(1) + return (BRUTELOSS) + else + C.visible_message("[C] screws up like an idiot and still dies anyway!") + return (BRUTELOSS) + +/obj/item/stack/medical/bone_gel/cyborg + custom_materials = null + is_cyborg = 1 + cost = 250 + +/obj/item/stack/medical/aloe + name = "aloe cream" + desc = "A healing paste you can apply on wounds." + + icon_state = "aloe_paste" + self_delay = 20 + other_delay = 10 + novariants = TRUE + amount = 20 + max_amount = 20 + var/heal = 3 + grind_results = list(/datum/reagent/consumable/aloejuice = 1) + +/obj/item/stack/medical/aloe/heal(mob/living/M, mob/user) + . = ..() + if(M.stat == DEAD) + to_chat(user, "[M] is dead! You can not help [M.p_them()].") + return FALSE + if(iscarbon(M)) + return heal_carbon(M, user, heal, heal) + if(isanimal(M)) + var/mob/living/simple_animal/critter = M + if (!(critter.healable)) + to_chat(user, "You cannot use \the [src] on [M]!") + return FALSE + else if (critter.health == critter.maxHealth) + to_chat(user, "[M] is at full health.") + return FALSE + user.visible_message("[user] applies \the [src] on [M].", "You apply \the [src] on [M].") + M.heal_bodypart_damage(heal, heal) + return TRUE + + to_chat(user, "You can't heal [M] with the \the [src]!") diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 6fdea26683..efcc075110 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -17,7 +17,6 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ throw_speed = 3 throw_range = 7 custom_materials = list(/datum/material/iron=1000) - mats_per_stack = 1000 max_amount = 50 attack_verb = list("hit", "bludgeoned", "whacked") hitsound = 'sound/weapons/grenadelaunch.ogg' diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index 57af862b69..29b4dea6d8 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) @@ -289,7 +289,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( resistance_flags = ACID_PROOF armor = list("melee" = 100, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 100) max_integrity = 40 - sharpness = IS_SHARP + sharpness = SHARP_EDGED var/icon_prefix embedding = list("embed_chance" = 65) diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm index d28ae52b52..7692278ba3 100644 --- a/code/game/objects/items/stacks/sheets/mineral.dm +++ b/code/game/objects/items/stacks/sheets/mineral.dm @@ -39,9 +39,11 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \ item_state = "sheet-sandstone" throw_speed = 3 throw_range = 5 - custom_materials = list(/datum/material/glass=MINERAL_MATERIAL_AMOUNT) + custom_materials = list(/datum/material/sandstone=MINERAL_MATERIAL_AMOUNT) sheettype = "sandstone" merge_type = /obj/item/stack/sheet/mineral/sandstone + walltype = /turf/closed/wall/mineral/sandstone + material_type = /datum/material/sandstone /obj/item/stack/sheet/mineral/sandstone/get_main_recipes() . = ..() @@ -107,6 +109,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \ point_value = 25 merge_type = /obj/item/stack/sheet/mineral/diamond material_type = /datum/material/diamond + walltype = /turf/closed/wall/mineral/diamond GLOBAL_LIST_INIT(diamond_recipes, list ( \ new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \ @@ -135,6 +138,7 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \ point_value = 20 merge_type = /obj/item/stack/sheet/mineral/uranium material_type = /datum/material/uranium + walltype = /turf/closed/wall/mineral/uranium GLOBAL_LIST_INIT(uranium_recipes, list ( \ new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = 1, on_floor = 1), \ @@ -163,6 +167,7 @@ GLOBAL_LIST_INIT(uranium_recipes, list ( \ point_value = 20 merge_type = /obj/item/stack/sheet/mineral/plasma material_type = /datum/material/plasma + walltype = /turf/closed/wall/mineral/plasma /obj/item/stack/sheet/mineral/plasma/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins licking \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -205,6 +210,7 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \ point_value = 20 merge_type = /obj/item/stack/sheet/mineral/gold material_type = /datum/material/gold + walltype = /turf/closed/wall/mineral/gold GLOBAL_LIST_INIT(gold_recipes, list ( \ new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = 1, on_floor = 1), \ @@ -236,6 +242,7 @@ GLOBAL_LIST_INIT(gold_recipes, list ( \ merge_type = /obj/item/stack/sheet/mineral/silver material_type = /datum/material/silver tableVariant = /obj/structure/table/optable + walltype = /turf/closed/wall/mineral/silver GLOBAL_LIST_INIT(silver_recipes, list ( \ new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = 1, on_floor = 1), \ @@ -266,6 +273,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \ point_value = 50 merge_type = /obj/item/stack/sheet/mineral/bananium material_type = /datum/material/bananium + walltype = /turf/closed/wall/mineral/bananium GLOBAL_LIST_INIT(bananium_recipes, list ( \ new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \ @@ -294,6 +302,7 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \ point_value = 20 merge_type = /obj/item/stack/sheet/mineral/titanium material_type = /datum/material/titanium + walltype = /turf/closed/wall/mineral/titanium GLOBAL_LIST_INIT(titanium_recipes, list ( \ new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20), \ @@ -324,6 +333,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \ custom_materials = list(/datum/material/titanium=MINERAL_MATERIAL_AMOUNT, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT) point_value = 45 merge_type = /obj/item/stack/sheet/mineral/plastitanium + walltype = /turf/closed/wall/mineral/plastitanium /obj/item/stack/sheet/mineral/plastitanium/fifty amount = 50 @@ -390,11 +400,14 @@ GLOBAL_LIST_INIT(adamantine_recipes, list( name = "snow" icon_state = "sheet-snow" item_state = "sheet-snow" + custom_materials = list(/datum/material/snow = MINERAL_MATERIAL_AMOUNT) singular_name = "snow block" force = 1 throwforce = 2 grind_results = list(/datum/reagent/consumable/ice = 20) merge_type = /obj/item/stack/sheet/mineral/snow + walltype = /turf/closed/wall/mineral/snow + material_type = /datum/material/snow GLOBAL_LIST_INIT(snow_recipes, list ( \ new/datum/stack_recipe("Snow Wall", /turf/closed/wall/mineral/snow, 5, one_per_turf = 1, on_floor = 1), \ @@ -417,6 +430,7 @@ GLOBAL_LIST_INIT(snow_recipes, list ( \ singular_name = "alien alloy sheet" sheettype = "abductor" merge_type = /obj/item/stack/sheet/mineral/abductor + walltype = /turf/closed/wall/mineral/abductor GLOBAL_LIST_INIT(abductor_recipes, list ( \ new/datum/stack_recipe("alien bed", /obj/structure/bed/abductor, 2, one_per_turf = 1, on_floor = 1), \ diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 55719c2758..645051b7c2 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -184,13 +184,13 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ new /datum/stack_recipe("trash cart", /obj/structure/closet/crate/trashcart, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("medical crate", /obj/structure/closet/crate/medical, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("freezer crate", /obj/structure/closet/crate/freezer, 8, time = 50, one_per_turf = 1, on_floor = 1), \ - new /datum/stack_recipe("blood bag crate", /obj/structure/closet/crate/freezer/blood, 8, time = 50, one_per_turf = 1, on_floor = 1), \ - new /datum/stack_recipe("surplus limbs crate", /obj/structure/closet/crate/freezer/surplus_limbs, 8, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("blood bag crate", /obj/structure/closet/crate/freezer/blood/fake, 8, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("surplus limbs crate", /obj/structure/closet/crate/freezer/surplus_limbs/fake, 8, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("radiation containment crate", /obj/structure/closet/crate/radiation, 8, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("hydroponics crate", /obj/structure/closet/crate/hydroponics, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("engineering crate", /obj/structure/closet/crate/engineering, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("eletrical crate", /obj/structure/closet/crate/engineering/electrical, 5, time = 50, one_per_turf = 1, on_floor = 1), \ - new /datum/stack_recipe("RCD storage crate", /obj/structure/closet/crate/rcd, 5, time = 50, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("RCD storage crate", /obj/structure/closet/crate/rcd/fake, 5, time = 50, one_per_turf = 1, on_floor = 1), \ new /datum/stack_recipe("science crate", /obj/structure/closet/crate/science, 5, time = 50, one_per_turf = 1, on_floor = 1), \ )), \ new /datum/stack_recipe_list("airlock assemblies", list( \ @@ -205,7 +205,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \ desc = "This sheet is an alloy of iron and plasma." icon_state = "sheet-plasteel" item_state = "sheet-metal" - custom_materials = list(/datum/material/iron=2000, /datum/material/plasma=2000) + custom_materials = list(/datum/material/iron=MINERAL_MATERIAL_AMOUNT, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT) throwforce = 10 flags_1 = CONDUCT_1 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80) @@ -240,13 +240,14 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ new /datum/stack_recipe("pew (right)", /obj/structure/chair/pew/right, 3, one_per_turf = TRUE, on_floor = TRUE),\ )), null, \ - new/datum/stack_recipe("wooden firearm body", /obj/item/weaponcrafting/improvised_parts/wooden_body, 10, time = 40), \ - new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \ - new/datum/stack_recipe("pistol grip", /obj/item/weaponcrafting/improvised_parts/wooden_grip, 5, time = 40), \ + new/datum/stack_recipe("wooden firearm body", /obj/item/weaponcrafting/improvised_parts/wooden_body, 10, time = 20), \ + new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 20), \ new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \ new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \ + new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\ new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \ new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\ + new/datum/stack_recipe("training bokken", /obj/item/melee/bokken, 10, time = 15),\ null, \ new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \ @@ -288,7 +289,8 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ merge_type = /obj/item/stack/sheet/mineral/wood novariants = TRUE material_type = /datum/material/wood - grind_results = list(/datum/reagent/carbon = 20) + grind_results = list(/datum/reagent/cellulose = 20) + walltype = /turf/closed/wall/mineral/wood /obj/item/stack/sheet/mineral/wood/attackby(obj/item/W, mob/user, params) // NOTE: sheet_types.dm is where the WOOD stack lives. Maybe move this over there. // Taken from /obj/item/stack/rods/attackby in [rods.dm] @@ -344,11 +346,13 @@ GLOBAL_LIST_INIT(bamboo_recipes, list ( \ icon_state = "sheet-bamboo" item_state = "sheet-bamboo" icon = 'icons/obj/stack_objects.dmi' + custom_materials = list(/datum/material/bamboo = MINERAL_MATERIAL_AMOUNT) throwforce = 15 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) resistance_flags = FLAMMABLE merge_type = /obj/item/stack/sheet/mineral/bamboo - grind_results = list(/datum/reagent/carbon = 5) + grind_results = list(/datum/reagent/cellulose = 10) + material_type = /datum/material/bamboo /obj/item/stack/sheet/mineral/bamboo/get_main_recipes() . = ..() @@ -379,6 +383,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \ new/datum/stack_recipe("chemistry bag", /obj/item/storage/bag/chemistry, 4), \ new/datum/stack_recipe("bio bag", /obj/item/storage/bag/bio, 4), \ null, \ + new/datum/stack_recipe("string", /obj/item/weaponcrafting/string, 1, time = 10), \ new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 6), \ new/datum/stack_recipe("rag", /obj/item/reagent_containers/rag, 1), \ new/datum/stack_recipe("towel", /obj/item/reagent_containers/rag/towel, 3), \ @@ -407,6 +412,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \ force = 0 throwforce = 0 merge_type = /obj/item/stack/sheet/cloth + grind_results = list(/datum/reagent/cellulose = 2) /obj/item/stack/sheet/cloth/get_main_recipes() . = ..() @@ -426,7 +432,6 @@ 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 @@ -513,12 +518,14 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \ desc = "Large sheets of card, like boxes folded flat." singular_name = "cardboard sheet" icon_state = "sheet-card" + custom_materials = list(/datum/material/cardboard = MINERAL_MATERIAL_AMOUNT) item_state = "sheet-card" resistance_flags = FLAMMABLE force = 0 throwforce = 0 merge_type = /obj/item/stack/sheet/cardboard novariants = TRUE + material_type = /datum/material/cardboard /obj/item/stack/sheet/cardboard/get_main_recipes() . = ..() @@ -558,10 +565,12 @@ GLOBAL_LIST_INIT(runed_metal_recipes, list ( \ icon_state = "sheet-runed" item_state = "sheet-runed" icon = 'icons/obj/stack_objects.dmi' + custom_materials = list(/datum/material/runedmetal = MINERAL_MATERIAL_AMOUNT) sheettype = "runed" merge_type = /obj/item/stack/sheet/runed_metal novariants = TRUE grind_results = list(/datum/reagent/iron = 5, /datum/reagent/blood = 15) + material_type = /datum/material/runedmetal /obj/item/stack/sheet/runed_metal/ratvar_act() new /obj/item/stack/tile/brass(loc, amount) @@ -664,6 +673,10 @@ GLOBAL_LIST_INIT(brass_recipes, list ( \ GLOBAL_LIST_INIT(bronze_recipes, list ( \ new/datum/stack_recipe("wall gear", /obj/structure/girder/bronze, 2, time = 20, one_per_turf = TRUE, on_floor = TRUE), \ null, + new/datum/stack_recipe("directional bronze window", /obj/structure/window/bronze/unanchored, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe("fulltile bronze window", /obj/structure/window/bronze/fulltile/unanchored, 2, time = 0, on_floor = TRUE, window_checks = TRUE), \ + new/datum/stack_recipe("pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), \ + new/datum/stack_recipe("bronze pinion airlock assembly", /obj/structure/door_assembly/door_assembly_bronze/seethru, 4, time = 50, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bronze hat", /obj/item/clothing/head/bronze), \ new/datum/stack_recipe("bronze suit", /obj/item/clothing/suit/bronze), \ new/datum/stack_recipe("bronze boots", /obj/item/clothing/shoes/bronze), \ @@ -671,36 +684,33 @@ GLOBAL_LIST_INIT(bronze_recipes, list ( \ new/datum/stack_recipe("bronze chair", /obj/structure/chair/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bronze bar stool", /obj/structure/chair/stool/bar/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ new/datum/stack_recipe("bronze stool", /obj/structure/chair/stool/bronze, 1, time = 0, one_per_turf = TRUE, on_floor = TRUE), \ + new /datum/stack_recipe("bronze floor tiles", /obj/item/stack/tile/bronze, 1, 4, 20), \ )) -/obj/item/stack/tile/bronze +/obj/item/stack/sheet/bronze name = "brass" desc = "On closer inspection, what appears to be wholly-unsuitable-for-building brass is actually more structurally stable bronze." singular_name = "bronze sheet" icon_state = "sheet-brass" item_state = "sheet-brass" icon = 'icons/obj/stack_objects.dmi' + custom_materials = list(/datum/material/bronze = MINERAL_MATERIAL_AMOUNT) resistance_flags = FIRE_PROOF | ACID_PROOF - throwforce = 10 - max_amount = 50 - throw_speed = 1 - throw_range = 3 - turf_type = /turf/open/floor/bronze - novariants = FALSE grind_results = list(/datum/reagent/iron = 5, /datum/reagent/copper = 3) //we have no "tin" reagent so this is the closest thing - merge_type = /obj/item/stack/tile/bronze + merge_type = /obj/item/stack/sheet/bronze tableVariant = /obj/structure/table/bronze + material_type = /datum/material/bronze -/obj/item/stack/tile/bronze/attack_self(mob/living/user) +/obj/item/stack/sheet/bronze/attack_self(mob/living/user) if(is_servant_of_ratvar(user)) //still lets them build with it, just gives a message to_chat(user, "Wha... what is this cheap imitation crap? This isn't brass at all!") ..() -/obj/item/stack/tile/bronze/get_main_recipes() +/obj/item/stack/sheet/bronze/get_main_recipes() . = ..() . += GLOB.bronze_recipes -/obj/item/stack/tile/bronze/thirty +/obj/item/stack/sheet/bronze/thirty amount = 30 /* @@ -737,6 +747,7 @@ GLOBAL_LIST_INIT(bone_recipes, list( icon = 'icons/obj/mining.dmi' icon_state = "bone" item_state = "sheet-bone" + custom_materials = list(/datum/material/bone = MINERAL_MATERIAL_AMOUNT) singular_name = "bone" desc = "Someone's been drinking their milk." force = 7 @@ -747,6 +758,7 @@ GLOBAL_LIST_INIT(bone_recipes, list( throw_range = 3 grind_results = list(/datum/reagent/carbon = 10) merge_type = /obj/item/stack/sheet/bone + material_type = /datum/material/bone /obj/item/stack/sheet/bone/get_main_recipes() . = ..() @@ -762,6 +774,7 @@ GLOBAL_LIST_INIT(plastic_recipes, list( new /datum/stack_recipe("water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/empty), \ new /datum/stack_recipe("large water bottle", /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty,3), \ new /datum/stack_recipe("shower curtain", /obj/structure/curtain, 10, time = 10, one_per_turf = 1, on_floor = 1), \ + new /datum/stack_recipe("duct", /obj/item/stack/ducts,1), \ new /datum/stack_recipe("laser pointer case", /obj/item/glasswork/glass_base/laserpointer_shell, 30), \ new /datum/stack_recipe("wet floor sign", /obj/item/caution, 2))) @@ -774,11 +787,15 @@ GLOBAL_LIST_INIT(plastic_recipes, list( custom_materials = list(/datum/material/plastic=MINERAL_MATERIAL_AMOUNT) throwforce = 7 grind_results = list(/datum/reagent/glitter/white = 60) + material_type = /datum/material/plastic merge_type = /obj/item/stack/sheet/plastic /obj/item/stack/sheet/plastic/fifty amount = 50 +/obj/item/stack/sheet/plastic/twenty + amount = 20 + /obj/item/stack/sheet/plastic/five amount = 5 @@ -796,9 +813,11 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra singular_name = "paper frame" icon_state = "sheet-paper" item_state = "sheet-paper" + custom_materials = list(/datum/material/paper = MINERAL_MATERIAL_AMOUNT) merge_type = /obj/item/stack/sheet/paperframes resistance_flags = FLAMMABLE merge_type = /obj/item/stack/sheet/paperframes + material_type = /datum/material/paper /obj/item/stack/sheet/paperframes/get_main_recipes() . = ..() @@ -824,6 +843,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra merge_type = /obj/item/stack/sheet/cotton var/pull_effort = 30 var/loom_result = /obj/item/stack/sheet/cloth + grind_results = list(/datum/reagent/cellulose = 5) /obj/item/stack/sheet/cotton/ten amount = 10 @@ -839,3 +859,56 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra merge_type = /obj/item/stack/sheet/cotton/durathread pull_effort = 70 loom_result = /obj/item/stack/sheet/durathread + grind_results = list(/datum/reagent/cellulose = 10) + +/obj/item/stack/sheet/meat + name = "meat sheets" + desc = "Something's bloody meat compressed into a nice solid sheet" + singular_name = "meat sheet" + icon_state = "sheet-meat" + material_flags = MATERIAL_COLOR + custom_materials = list(/datum/material/meat = MINERAL_MATERIAL_AMOUNT) + merge_type = /obj/item/stack/sheet/meat + material_type = /datum/material/meat + material_modifier = 1 //None of that wussy stuff + +/obj/item/stack/sheet/meat/fifty + amount = 50 +/obj/item/stack/sheet/meat/twenty + amount = 20 +/obj/item/stack/sheet/meat/five + amount = 5 + +/obj/item/stack/sheet/pizza + name = "pepperoni sheetzzas" + desc = "It's a delicious pepperoni sheetzza!" + singular_name = "pepperoni sheetzza" + icon_state = "sheet-pizza" + custom_materials = list(/datum/material/pizza = MINERAL_MATERIAL_AMOUNT) + merge_type = /obj/item/stack/sheet/pizza + material_type = /datum/material/pizza + material_modifier = 1 + +/obj/item/stack/sheet/pizza/fifty + amount = 50 +/obj/item/stack/sheet/pizza/twenty + amount = 20 +/obj/item/stack/sheet/pizza/five + amount = 5 + +/obj/item/stack/sheet/sandblock + name = "blocks of sand" + desc = "You're too old to be playing with sandcastles. Now you build... sandstations." + singular_name = "block of sand" + icon_state = "sheet-sandstone" + custom_materials = list(/datum/material/sand = MINERAL_MATERIAL_AMOUNT) + merge_type = /obj/item/stack/sheet/sandblock + material_type = /datum/material/sand + material_modifier = 1 + +/obj/item/stack/sheet/sandblock/fifty + amount = 50 +/obj/item/stack/sheet/sandblock/twenty + amount = 20 +/obj/item/stack/sheet/sandblock/five + amount = 5 diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm index dfba533247..57c8ba75d8 100644 --- a/code/game/objects/items/stacks/sheets/sheets.dm +++ b/code/game/objects/items/stacks/sheets/sheets.dm @@ -10,10 +10,14 @@ throw_range = 3 attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed") novariants = FALSE - mats_per_stack = MINERAL_MATERIAL_AMOUNT - var/sheettype = null //this is used for girders in the creation of walls/false walls - var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity - var/shard_type // the shard debris typepath left over by solar panels and windows etc. + ///this is used for girders in the creation of walls/false walls + var/sheettype = null + ///turn-in value for the gulag stacker - loosely relative to its rarity + var/point_value = 0 + /// the shard debris typepath left over by solar panels and windows etc. + var/shard_type + ///What type of wall does this sheet spawn + var/walltype /obj/item/stack/sheet/Initialize(mapload, new_amount, merge) . = ..() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 2c8e700316..3e2bb675fa 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -22,12 +22,21 @@ var/merge_type = null // This path and its children should merge with this stack, defaults to src.type var/full_w_class = WEIGHT_CLASS_NORMAL //The weight class the stack should have at amount > 2/3rds max_amount var/novariants = TRUE //Determines whether the item should update it's sprites based on amount. - var/mats_per_stack = 0 + var/list/mats_per_unit //list that tells you how much is in a single unit. ///Datum material type that this stack is made of var/material_type + max_integrity = 100 //NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind() var/obj/structure/table/tableVariant // we tables now (stores table variant to be built from this stack) + // The following are all for medical treatment, they're here instead of /stack/medical because sticky tape can be used as a makeshift bandage or splint + /// If set and this used as a splint for a broken bone wound, this is used as a multiplier for applicable slowdowns (lower = better) (also for speeding up burn recoveries) + var/splint_factor + /// How much blood flow this stack can absorb if used as a bandage on a cut wound, note that absorption is how much we lower the flow rate, not the raw amount of blood we suck up + var/absorption_capacity + /// How quickly we lower the blood flow on a cut wound we're bandaging. Expected lifetime of this bandage in ticks is thus absorption_capacity/absorption_rate, or until the cut heals, whichever comes first + var/absorption_rate + /obj/item/stack/on_grind() for(var/i in 1 to grind_results.len) //This should only call if it's ground, so no need to check if grind_results exists grind_results[grind_results[i]] *= get_amount() //Gets the key at position i, then the reagent amount of that key, then multiplies it by stack size @@ -47,8 +56,11 @@ if(!merge_type) merge_type = type if(custom_materials && custom_materials.len) + mats_per_unit = list() + var/in_process_mat_list = custom_materials.Copy() for(var/i in custom_materials) - custom_materials[SSmaterials.GetMaterialRef(i)] = mats_per_stack * amount + mats_per_unit[SSmaterials.GetMaterialRef(i)] = in_process_mat_list[i] + custom_materials[i] *= amount . = ..() if(merge) for(var/obj/item/stack/S in loc) @@ -60,7 +72,7 @@ var/datum/material/M = SSmaterials.GetMaterialRef(material_type) //First/main material for(var/i in M.categories) switch(i) - if(MAT_CATEGORY_RIGID) + if(MAT_CATEGORY_BASE_RECIPES) var/list/temp = SSmaterials.rigid_stack_recipes.Copy() recipes += temp update_weight() @@ -221,7 +233,7 @@ return T.PlaceOnTop(R.result_type, flags = CHANGETURF_INHERIT_AIR) else - O = new R.result_type(usr.drop_location()) + O = new R.result_type(get_turf(usr)) if(O) O.setDir(usr.dir) log_craft("[O] crafted by [usr] at [loc_name(O.loc)]") @@ -315,10 +327,13 @@ if (amount < used) return FALSE amount -= used - if(check) - zero_amount() - for(var/i in custom_materials) - custom_materials[i] = amount * mats_per_stack + if(check && zero_amount()) + return TRUE + if(length(mats_per_unit)) + var/temp_materials = custom_materials.Copy() + for(var/i in mats_per_unit) + temp_materials[i] = mats_per_unit[i] * src.amount + set_custom_materials(temp_materials) update_icon() update_weight() return TRUE @@ -350,10 +365,11 @@ source.add_charge(amount * cost) else src.amount += amount - if(custom_materials && custom_materials.len) - for(var/i in custom_materials) - custom_materials[SSmaterials.GetMaterialRef(i)] = MINERAL_MATERIAL_AMOUNT * src.amount - set_custom_materials() //Refresh + if(length(mats_per_unit)) + var/temp_materials = custom_materials.Copy() + for(var/i in mats_per_unit) + temp_materials[i] = mats_per_unit[i] * src.amount + set_custom_materials(temp_materials) update_icon() update_weight() @@ -382,8 +398,7 @@ merge(AM) . = ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/stack/attack_hand(mob/user) +/obj/item/stack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.get_inactive_held_item() == src) if(zero_amount()) return diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm index 177260febb..bbfee8dece 100644 --- a/code/game/objects/items/stacks/tape.dm +++ b/code/game/objects/items/stacks/tape.dm @@ -7,14 +7,21 @@ icon = 'icons/obj/tapes.dmi' icon_state = "tape_w" var/prefix = "sticky" + w_class = WEIGHT_CLASS_TINY + full_w_class = WEIGHT_CLASS_TINY item_flags = NOBLUDGEON amount = 5 max_amount = 5 resistance_flags = FLAMMABLE + splint_factor = 0.8 + grind_results = list(/datum/reagent/cellulose = 5) var/list/conferred_embed = EMBED_HARMLESS var/overwrite_existing = FALSE + var/endless = FALSE + var/apply_time = 30 + /obj/item/stack/sticky_tape/afterattack(obj/item/I, mob/living/user) if(!istype(I)) return @@ -25,17 +32,24 @@ user.visible_message("[user] begins wrapping [I] with [src].", "You begin wrapping [I] with [src].") - if(do_after(user, 30, target=I)) + if(do_after(user, apply_time, target=I)) I.embedding = conferred_embed I.updateEmbedding() to_chat(user, "You finish wrapping [I] with [src].") - use(1) + if(!endless) + use(1) I.name = "[prefix] [I.name]" if(istype(I, /obj/item/grenade)) var/obj/item/grenade/sticky_bomb = I sticky_bomb.sticky = TRUE +/obj/item/stack/sticky_tape/infinite //endless tape that applies far faster, for maximum honks + name = "endless sticky tape" + desc = "This roll of sticky tape somehow has no end." + endless = TRUE + apply_time = 10 + /obj/item/stack/sticky_tape/super name = "super sticky tape" singular_name = "super sticky tape" @@ -43,6 +57,7 @@ icon_state = "tape_y" prefix = "super sticky" conferred_embed = EMBED_HARMLESS_SUPERIOR + splint_factor = 0.6 /obj/item/stack/sticky_tape/pointy name = "pointy tape" @@ -58,4 +73,14 @@ desc = "You didn't know tape could look so sinister. Welcome to Space Station 13." icon_state = "tape_spikes" prefix = "super pointy" - conferred_embed = EMBED_POINTY_SUPERIOR \ No newline at end of file + conferred_embed = EMBED_POINTY_SUPERIOR + +/obj/item/stack/sticky_tape/surgical + name = "surgical tape" + singular_name = "surgical tape" + desc = "Made for patching broken bones back together alongside bone gel, not for playing pranks." + //icon_state = "tape_spikes" + prefix = "surgical" + conferred_embed = list("embed_chance" = 30, "pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE) + splint_factor = 0.4 + custom_price = 500 diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm index 9b5ca2b066..54824940c1 100644 --- a/code/game/objects/items/stacks/telecrystal.dm +++ b/code/game/objects/items/stacks/telecrystal.dm @@ -4,6 +4,7 @@ singular_name = "telecrystal" icon = 'icons/obj/telescience.dmi' icon_state = "telecrystal" + grind_results = list(/datum/reagent/telecrystal = 20) w_class = WEIGHT_CLASS_TINY max_amount = 50 item_flags = NOBLUDGEON diff --git a/code/game/objects/items/stacks/tickets.dm b/code/game/objects/items/stacks/tickets.dm new file mode 100644 index 0000000000..22cb895277 --- /dev/null +++ b/code/game/objects/items/stacks/tickets.dm @@ -0,0 +1,31 @@ +/obj/item/stack/arcadeticket + name = "arcade tickets" + desc = "Wow! With enough of these, you could buy a bike! ...Pssh, yeah right." + singular_name = "arcade ticket" + icon_state = "arcade-ticket" + item_state = "tickets" + w_class = WEIGHT_CLASS_TINY + max_amount = 30 + +/obj/item/stack/arcadeticket/Initialize(mapload, new_amount, merge = TRUE) + . = ..() + update_icon() + +/obj/item/stack/arcadeticket/update_icon() + var/amount = get_amount() + if((amount >= 12) && (amount > 0)) + icon_state = "arcade-ticket_4" + else if((amount >= 6) && (amount > 0)) + icon_state = "arcade-ticket_3" + else if((amount >= 2) && (amount > 0)) + icon_state = "arcade-ticket_2" + else + icon_state = "arcade-ticket" + +/obj/item/stack/arcadeticket/proc/pay_tickets() + amount -= 2 + if (amount == 0) + qdel(src) + +/obj/item/stack/arcadeticket/thirty + amount = 30 diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index ff81b4340a..0d85e897d2 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -9,16 +9,35 @@ throw_speed = 3 throw_range = 7 max_amount = 60 - mats_per_stack = 500 var/turf_type = null var/mineralType = null novariants = TRUE + var/human_maxHealth = 100 /obj/item/stack/tile/Initialize(mapload, amount) . = ..() pixel_x = rand(-3, 3) pixel_y = rand(-3, 3) //randomize a little +/obj/item/stack/tile/examine(mob/user) + . = ..() + if(throwforce && !is_cyborg) //do not want to divide by zero or show the message to borgs who can't throw + var/verb + switch(CEILING(human_maxHealth / throwforce, 1)) //throws to crit a human + if(1 to 3) + verb = "superb" + if(4 to 6) + verb = "great" + if(7 to 9) + verb = "good" + if(10 to 12) + verb = "fairly decent" + if(13 to 15) + verb = "mediocre" + if(!verb) + return + . += "Those could work as a [verb] throwing weapon." + /obj/item/stack/tile/attackby(obj/item/W, mob/user, params) if (istype(W, /obj/item/weldingtool)) @@ -266,6 +285,9 @@ /obj/item/stack/tile/carpet/blackred/twenty amount = 20 +/obj/item/stack/tile/carpet/blackred/thirty + amount = 30 + /obj/item/stack/tile/carpet/blackred/fifty amount = 50 @@ -275,6 +297,9 @@ /obj/item/stack/tile/carpet/monochrome/twenty amount = 20 +/obj/item/stack/tile/carpet/monochrome/thirty + amount = 30 + /obj/item/stack/tile/carpet/monochrome/fifty amount = 50 @@ -284,6 +309,9 @@ /obj/item/stack/tile/carpet/blue/twenty amount = 20 +/obj/item/stack/tile/carpet/blue/thirty + amount = 30 + /obj/item/stack/tile/carpet/blue/fifty amount = 50 @@ -293,6 +321,9 @@ /obj/item/stack/tile/carpet/cyan/twenty amount = 20 +/obj/item/stack/tile/carpet/cyan/thirty + amount = 30 + /obj/item/stack/tile/carpet/cyan/fifty amount = 50 @@ -302,6 +333,9 @@ /obj/item/stack/tile/carpet/green/twenty amount = 20 +/obj/item/stack/tile/carpet/green/thirty + amount = 30 + /obj/item/stack/tile/carpet/green/fifty amount = 50 @@ -311,6 +345,9 @@ /obj/item/stack/tile/carpet/orange/twenty amount = 20 +/obj/item/stack/tile/carpet/orange/thirty + amount = 30 + /obj/item/stack/tile/carpet/orange/fifty amount = 50 @@ -320,6 +357,9 @@ /obj/item/stack/tile/carpet/purple/twenty amount = 20 +/obj/item/stack/tile/carpet/purple/thirty + amount = 30 + /obj/item/stack/tile/carpet/purple/fifty amount = 50 @@ -329,6 +369,9 @@ /obj/item/stack/tile/carpet/red/twenty amount = 20 +/obj/item/stack/tile/carpet/red/thirty + amount = 30 + /obj/item/stack/tile/carpet/red/fifty amount = 50 @@ -338,6 +381,9 @@ /obj/item/stack/tile/carpet/royalblack/twenty amount = 20 +/obj/item/stack/tile/carpet/royalblack/thirty + amount = 30 + /obj/item/stack/tile/carpet/royalblack/fifty amount = 50 @@ -347,6 +393,9 @@ /obj/item/stack/tile/carpet/royalblue/twenty amount = 20 +/obj/item/stack/tile/carpet/royalblue/thirty + amount = 30 + /obj/item/stack/tile/carpet/royalblue/fifty amount = 50 @@ -440,7 +489,7 @@ /obj/item/stack/tile/plasteel name = "floor tile" singular_name = "floor tile" - desc = "Those could work as a pretty decent throwing weapon." + desc = "The ground you walk on." icon_state = "tile" force = 6 custom_materials = list(/datum/material/iron=500) @@ -452,7 +501,24 @@ resistance_flags = FIRE_PROOF /obj/item/stack/tile/plasteel/cyborg - desc = "The ground you walk on." //Not the usual floor tile desc as that refers to throwing, Cyborgs can't do that - RR custom_materials = null // All other Borg versions of items have no Metal or Glass - RR is_cyborg = 1 cost = 125 + +/obj/item/stack/tile/material + name = "floor tile" + singular_name = "floor tile" + desc = "The ground you walk on." + throwforce = 10 + icon_state = "material_tile" + turf_type = /turf/open/floor/material + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + +/obj/item/stack/tile/bronze + name = "bronze tile" + singular_name = "bronze floor tile" + desc = "A tile made out of bronze. Looks like clockwork." + icon_state = "material_tile" + color = "#92661A" + turf_type = /turf/open/floor/bronze + custom_materials = list(/datum/material/bronze = 250) diff --git a/code/game/objects/items/stacks/wrap.dm b/code/game/objects/items/stacks/wrap.dm index 10240e902b..6ae63e640f 100644 --- a/code/game/objects/items/stacks/wrap.dm +++ b/code/game/objects/items/stacks/wrap.dm @@ -35,6 +35,7 @@ amount = 25 max_amount = 25 resistance_flags = FLAMMABLE + grind_results = list(/datum/reagent/cellulose = 5) /obj/item/stack/packageWrap/suicide_act(mob/living/user) user.visible_message("[user] begins wrapping [user.p_them()]self in \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") diff --git a/code/game/objects/items/storage/_storage.dm b/code/game/objects/items/storage/_storage.dm index fd4cc793ab..2fc1b6484d 100644 --- a/code/game/objects/items/storage/_storage.dm +++ b/code/game/objects/items/storage/_storage.dm @@ -19,8 +19,9 @@ return TRUE /obj/item/storage/contents_explosion(severity, target) + var/in_storage = istype(loc, /obj/item/storage)? (max(0, severity - 1)) : (severity) for(var/atom/A in contents) - A.ex_act(severity, target) + A.ex_act(in_storage, target) CHECK_TICK //Cyberboss says: "USE THIS TO FILL IT, NOT INITIALIZE OR NEW" diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm index 3d5f0dc924..f15588a7f1 100644 --- a/code/game/objects/items/storage/backpack.dm +++ b/code/game/objects/items/storage/backpack.dm @@ -369,6 +369,7 @@ new /obj/item/circular_saw(src) new /obj/item/surgicaldrill(src) new /obj/item/cautery(src) + new /obj/item/bonesetter(src) new /obj/item/surgical_drapes(src) new /obj/item/clothing/mask/surgical(src) new /obj/item/reagent_containers/medspray/sterilizine(src) @@ -391,6 +392,7 @@ new /obj/item/circular_saw(src) new /obj/item/surgicaldrill(src) new /obj/item/cautery(src) + new /obj/item/bonesetter(src) new /obj/item/surgical_drapes(src) new /obj/item/clothing/mask/surgical(src) new /obj/item/reagent_containers/medspray/sterilizine(src) @@ -485,6 +487,7 @@ new /obj/item/circular_saw(src) new /obj/item/surgicaldrill(src) new /obj/item/cautery(src) + new /obj/item/bonesetter(src) new /obj/item/surgical_drapes(src) new /obj/item/clothing/suit/straight_jacket(src) new /obj/item/clothing/mask/muzzle(src) @@ -501,8 +504,8 @@ new /obj/item/scalpel/advanced(src) new /obj/item/retractor/advanced(src) new /obj/item/surgicaldrill/advanced(src) + new /obj/item/bonesetter(src) new /obj/item/surgical_drapes(src) - new /obj/item/storage/firstaid/tactical(src) new /obj/item/clothing/suit/straight_jacket(src) new /obj/item/clothing/mask/muzzle(src) new /obj/item/mmi/syndie(src) @@ -648,3 +651,9 @@ obj/item/storage/backpack/duffelbag/syndie/shredderbundle new /obj/item/gun/ballistic/automatic/flechette/shredder(src) new /obj/item/storage/belt/military(src) new /obj/item/clothing/suit/space/hardsuit/syndi/elite(src) + +/obj/item/storage/backpack/snail + name = "snail shell" + desc = "Worn by snails as armor and storage compartment." + icon_state = "snailshell" + item_state = "snailshell" diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm index 315b342ea7..b64aa60cac 100644 --- a/code/game/objects/items/storage/bags.dm +++ b/code/game/objects/items/storage/bags.dm @@ -48,7 +48,8 @@ STR.max_w_class = WEIGHT_CLASS_SMALL STR.max_combined_w_class = 30 STR.max_items = 30 - STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear)) + STR.can_hold_extra = typecacheof(list(/obj/item/organ/lungs, /obj/item/organ/liver, /obj/item/organ/stomach, /obj/item/clothing/shoes)) - typesof(/obj/item/clothing/shoes/magboots, /obj/item/clothing/shoes/clown_shoes, /obj/item/clothing/shoes/jackboots, /obj/item/clothing/shoes/workboots) + STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear, /obj/item/storage/wallet, /obj/item/organ/brain)) STR.limited_random_access = TRUE STR.limited_random_access_stack_position = 3 @@ -326,6 +327,7 @@ w_class = WEIGHT_CLASS_BULKY flags_1 = CONDUCT_1 custom_materials = list(/datum/material/iron=3000) + var/max_items = 7 /obj/item/storage/bag/tray/ComponentInitialize() . = ..() @@ -333,6 +335,7 @@ STR.max_w_class = WEIGHT_CLASS_NORMAL STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food, /obj/item/reagent_containers/glass, /datum/reagent/consumable, /obj/item/kitchen/knife, /obj/item/kitchen/rollingpin, /obj/item/kitchen/fork, /obj/item/storage/box)) //Should cover: Bottles, Beakers, Bowls, Booze, Glasses, Food, Kitchen Tools, and ingredient boxes. STR.insert_preposition = "on" + STR.max_items = max_items /obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user) . = ..() @@ -373,6 +376,14 @@ . = ..() update_icon() +//bluespace tray, holds more items +/obj/item/storage/bag/tray/bluespace + name = "bluespace tray" + icon_state = "bluespace_tray" + desc = "A tray created using bluespace technology to fit more food on it." + max_items = 30 // far more items + custom_materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500) + /* * Chemistry bag */ @@ -391,7 +402,7 @@ STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT STR.max_volume = STORAGE_VOLUME_CHEMISTRY_BAG STR.insert_preposition = "in" - STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe/dart)) + STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe/dart, /obj/item/reagent_containers/chem_pack)) /* * Biowaste bag (mostly for xenobiologists) @@ -444,4 +455,22 @@ STR.max_combined_w_class = 30 STR.max_items = 3 STR.display_numerical_stacking = FALSE - STR.can_hold = typecacheof(list(/obj/item/ammo_box/magazine, /obj/item/ammo_casing)) \ No newline at end of file + STR.can_hold = typecacheof(list(/obj/item/ammo_box/magazine, /obj/item/ammo_casing)) + +/obj/item/storage/bag/material + name = "material pouch" + desc = "A pouch for sheets and RCD ammunition that manages to hang where you would normally put things in your pocket." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "materialpouch" + slot_flags = ITEM_SLOT_POCKET + w_class = WEIGHT_CLASS_BULKY + resistance_flags = FLAMMABLE + +/obj/item/storage/bag/material/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_w_class = WEIGHT_CLASS_NORMAL + STR.max_combined_w_class = INFINITY + STR.max_items = 2 + STR.display_numerical_stacking = TRUE + STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet)) diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 684f8709ac..0001494fdd 100755 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -83,7 +83,7 @@ new /obj/item/multitool(src) new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange")) new /obj/item/extinguisher/mini(src) - new /obj/item/analyzer(src) + new /obj/item/analyzer/ranged(src) //much roomier now that we've managed to remove two tools /obj/item/storage/belt/utility/full/PopulateContents() @@ -120,7 +120,7 @@ new /obj/item/wrench/brass(src) new /obj/item/crowbar/brass(src) new /obj/item/weldingtool/experimental/brass(src) - new /obj/item/multitool(src) + new /obj/item/multitool/advanced/brass(src) new /obj/item/stack/cable_coil(src, 30, "yellow") /obj/item/storage/belt/medical @@ -162,6 +162,7 @@ /obj/item/surgical_drapes, //for true paramedics /obj/item/scalpel, /obj/item/circular_saw, + /obj/item/bonesetter, /obj/item/surgicaldrill, /obj/item/retractor, /obj/item/cautery, @@ -180,7 +181,9 @@ /obj/item/implantcase, /obj/item/implant, /obj/item/implanter, - /obj/item/pinpointer/crew + /obj/item/pinpointer/crew, + /obj/item/reagent_containers/chem_pack, + /obj/item/stack/sticky_tape //surgical tape )) /obj/item/storage/belt/medical/surgery_belt_adv @@ -443,10 +446,11 @@ /obj/item/storage/belt/durathread name = "durathread toolbelt" - desc = "A toolbelt made out of durathread, it seems resistant enough to hold even big tools like an RCD, it also has higher capacity." + desc = "A toolbelt made out of durathread, it seems robust enough to hold bigger tools like RCDs or RPDs, with enough pouches to hold more gear than a normal belt." icon_state = "webbing-durathread" item_state = "webbing-durathread" resistance_flags = FIRE_PROOF + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //If normal belts get this, the upgraded version should too /obj/item/storage/belt/durathread/ComponentInitialize() . = ..() @@ -466,7 +470,7 @@ /obj/item/t_scanner, /obj/item/analyzer, /obj/item/geiger_counter, - /obj/item/extinguisher/mini, + /obj/item/extinguisher, /obj/item/radio, /obj/item/clothing/gloves, /obj/item/holosign_creator, @@ -474,7 +478,7 @@ /obj/item/assembly/signaler, /obj/item/lightreplacer, /obj/item/rcd_ammo, - /obj/item/construction/rcd, + /obj/item/construction, /obj/item/pipe_dispenser, /obj/item/stack/rods, /obj/item/stack/tile/plasteel, @@ -487,6 +491,7 @@ desc = "A belt for holding grenades." icon_state = "grenadebeltnew" item_state = "security" + rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE /obj/item/storage/belt/grenade/ComponentInitialize() . = ..() @@ -585,7 +590,7 @@ /obj/item/key/janitor, /obj/item/clothing/gloves, /obj/item/melee/flyswatter, - /obj/item/twohanded/broom, + /obj/item/broom, /obj/item/paint/paint_remover, /obj/item/assembly/mousetrap, /obj/item/screwdriver, @@ -810,4 +815,3 @@ attack_verb = list("bashed", "slashes", "prods", "pokes") fitting_swords = list(/obj/item/melee/rapier) starting_sword = /obj/item/melee/rapier - diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index e3f590aa2a..28850e79a2 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -47,41 +47,58 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", user.visible_message("[user] is offering [user.p_them()]self to [deity_name]! It looks like [user.p_theyre()] trying to commit suicide!") return (BRUTELOSS) -/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/H) - if(!istype(H)) +/obj/item/storage/book/bible/attack_self(mob/living/carbon/human/user) + if(!istype(user)) return - // If H is the Chaplain, we can set the icon_state of the bible (but only once!) - if(!GLOB.bible_icon_state && H.job == "Chaplain") - var/dat = "Pick Bible Style

    Pick a bible style

    " - for(var/i in 1 to GLOB.biblestates.len) - var/icon/bibleicon = icon('icons/obj/storage.dmi', GLOB.biblestates[i]) - var/nicename = GLOB.biblenames[i] - H << browse_rsc(bibleicon, nicename) - dat += {""} - dat += "
    [nicename]
    " - H << browse(dat, "window=editicon;can_close=0;can_minimize=0;size=250x650") + if(GLOB.bible_icon_state) // if there is already a bible icon return FALSE + return FALSE + if(user.job != "Chaplain") // if the user is not the chaplain, return FALSE + return FALSE -/obj/item/storage/book/bible/Topic(href, href_list) - if(!usr.canUseTopic(src)) - return - if(href_list["seticon"] && GLOB && !GLOB.bible_icon_state) - var/iconi = text2num(href_list["seticon"]) - var/biblename = GLOB.biblenames[iconi] - var/obj/item/storage/book/bible/B = locate(href_list["src"]) - B.icon_state = GLOB.biblestates[iconi] - B.item_state = GLOB.bibleitemstates[iconi] + var/list/skins = list() + for(var/i in 1 to GLOB.biblestates.len) + var/image/bible_image = image(icon = 'icons/obj/storage.dmi', icon_state = GLOB.biblestates[i]) + skins += list("[GLOB.biblenames[i]]" = bible_image) - if(B.icon_state == "honk1" || B.icon_state == "honk2") - var/mob/living/carbon/human/H = usr - H.dna.add_mutation(CLOWNMUT) - H.dna.add_mutation(SMILE) - H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK) + var/choice = show_radial_menu(user, src, skins, custom_check = CALLBACK(src, .proc/check_menu, user), radius = 40, require_near = TRUE) + if(!choice) + return FALSE + var/bible_index = GLOB.biblenames.Find(choice) + if(!bible_index) + return FALSE + icon_state = GLOB.biblestates[bible_index] + item_state = GLOB.bibleitemstates[bible_index] - GLOB.bible_icon_state = B.icon_state - GLOB.bible_item_state = B.item_state + if(icon_state == "honk1" || icon_state == "honk2") + var/mob/living/carbon/human/H = usr + H.dna.add_mutation(CLOWNMUT) + H.dna.add_mutation(SMILE) + H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), SLOT_WEAR_MASK) - SSblackbox.record_feedback("text", "religion_book", 1, "[biblename]") - usr << browse(null, "window=editicon") + GLOB.bible_icon_state = icon_state + GLOB.bibleitemstates = item_state + SSblackbox.record_feedback("text", "religion_book", 1, "[choice]") + +/** + * Checks if we are allowed to interact with the radial + * + * Arguements: user The mob interacting with the menu + */ + +/obj/item/storage/book/bible/proc/check_menu(mob/living/carbon/human/user) + if(GLOB.bible_icon_state) + return FALSE + if(!istype(user)) + return FALSE + if(!user.is_holding(src)) + return FALSE + if(!user.can_read(src)) + return FALSE + if(user.incapacitated()) + return FALSE + if(user.job != "Chaplain") + return FALSE + return TRUE /obj/item/storage/book/bible/proc/bless(mob/living/carbon/human/H, mob/living/user) for(var/X in H.bodyparts) @@ -104,7 +121,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "blessing", /datum/mood_event/blessing) return 1 -/obj/item/storage/book/bible/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE) +/obj/item/storage/book/bible/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1, heal_mode = TRUE) if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") @@ -173,12 +190,12 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", var/unholy2clean = A.reagents.get_reagent_amount(/datum/reagent/fuel/unholywater) A.reagents.del_reagent(/datum/reagent/fuel/unholywater) A.reagents.add_reagent(/datum/reagent/water/holywater,unholy2clean) - if(istype(A, /obj/item/twohanded/required/cult_bastard) || istype(A, /obj/item/melee/cultblade) && !iscultist(user)) + if(istype(A, /obj/item/cult_bastard) || istype(A, /obj/item/melee/cultblade) && !iscultist(user)) to_chat(user, "You begin to exorcise [A].") playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1) if(do_after(user, 40, target = A)) playsound(src,'sound/effects/pray_chaplain.ogg',60,1) - if(istype(A, /obj/item/twohanded/required/cult_bastard)) + if(istype(A, /obj/item/cult_bastard)) for(var/obj/item/soulstone/SS in A.contents) SS.usability = TRUE for(var/mob/living/simple_animal/shade/EX in SS) @@ -238,11 +255,10 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", var/ownername = H.real_name desc += "The name [ownername] is written in blood inside the cover." -/obj/item/storage/book/bible/syndicate/attack(mob/living/M, mob/living/carbon/human/user, heal_mode = TRUE) - if (user.a_intent == INTENT_HELP) - return ..() - else - return ..(M,user,heal_mode = FALSE) +/obj/item/storage/book/bible/syndicate/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1, heal_mode = TRUE) + if(user.a_intent != INTENT_HELP) + heal_mode = FALSE //args pass over + return ..() // to ..() /obj/item/storage/book/bible/syndicate/add_blood_DNA(list/blood_dna) return FALSE diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index cdd3781748..975621ead1 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -726,9 +726,9 @@ obj/item/storage/box/stingbangs return (BRUTELOSS) /obj/item/storage/box/hug/attack_self(mob/user) - ..() - user.changeNext_move(CLICK_CD_MELEE) - playsound(loc, "rustle", 50, 1, -5) + . = ..() + user.DelayNextAction(CLICK_CD_MELEE) + playsound(src, "rustle", 50, 1, -5) user.visible_message("[user] hugs \the [src].","You hug \the [src].") SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"hugbox", /datum/mood_event/hugbox) @@ -1418,3 +1418,9 @@ obj/item/storage/box/stingbangs new /obj/item/reagent_containers/glass/beaker/meta(src) new /obj/item/reagent_containers/glass/beaker/noreact(src) new /obj/item/reagent_containers/glass/beaker/bluespace(src) + +/obj/item/storage/box/strange_seeds_5pack + +/obj/item/storage/box/strange_seeds_5pack/PopulateContents() + for(var/i in 1 to 5) + new /obj/item/seeds/random(src) diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm index 826a00b90d..454475625d 100644 --- a/code/game/objects/items/storage/briefcase.dm +++ b/code/game/objects/items/storage/briefcase.dm @@ -106,10 +106,10 @@ /obj/item/storage/briefcase/medical name = "medical briefcase" icon_state = "medbriefcase" - desc = "A white with a blue cross brieface, this is ment to hold medical gear that would not be able to normally fit in a bag." + desc = "A white with a blue cross brieface, this is meant to hold medical gear that would not be able to normally fit in a bag." /obj/item/storage/briefcase/medical/PopulateContents() new /obj/item/clothing/neck/stethoscope(src) new /obj/item/healthanalyzer(src) - ..() //In case of paperwork + ..() //Incase of paperwork diff --git a/code/game/objects/items/storage/dakis.dm b/code/game/objects/items/storage/dakis.dm index 1939593c8e..29f12df4c4 100644 --- a/code/game/objects/items/storage/dakis.dm +++ b/code/game/objects/items/storage/dakis.dm @@ -47,6 +47,6 @@ if(INTENT_HARM) user.visible_message("[user] punches the [name]!") playsound(src, 'sound/effects/shieldbash.ogg', 50, 1) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) //////////////////////////// diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm index b78bd99d92..cde6f5bd5a 100644 --- a/code/game/objects/items/storage/fancy.dm +++ b/code/game/objects/items/storage/fancy.dm @@ -138,6 +138,22 @@ icon_type = "cigarette" spawn_type = /obj/item/clothing/mask/cigarette/space_cigarette custom_price = PRICE_ALMOST_CHEAP + var/spawn_coupon = TRUE + +/obj/item/storage/fancy/cigarettes/attack_self(mob/user) + if(contents.len == 0 && spawn_coupon) + to_chat(user, "You rip the back off \the [src] and get a coupon!") + var/obj/item/coupon/attached_coupon = new + user.put_in_hands(attached_coupon) + attached_coupon.generate() + attached_coupon = null + spawn_coupon = FALSE + name = "discarded cigarette packet" + desc = "An old cigarette packet with the back torn off, worth less than nothing now." + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_items = 0 + return + return ..() /obj/item/storage/fancy/cigarettes/ComponentInitialize() . = ..() @@ -148,15 +164,23 @@ /obj/item/storage/fancy/cigarettes/examine(mob/user) . = ..() . += "Alt-click to extract contents." + if(spawn_coupon) + . += "There's a coupon on the back of the pack! You can tear it off once it's empty." /obj/item/storage/fancy/cigarettes/AltClick(mob/living/carbon/user) + . = ..() if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) return - var/obj/item/clothing/mask/cigarette/W = locate(/obj/item/clothing/mask/cigarette) in contents + var/obj/item/lighter/L = locate() in contents + if(L) + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, L, user) + user.put_in_hands(L) + to_chat(user, "You take \a [L] out of the pack.") + return TRUE + var/obj/item/clothing/mask/cigarette/W = locate() in contents if(W && contents.len > 0) SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, user) user.put_in_hands(W) - contents -= W to_chat(user, "You take \a [W] out of the pack.") else to_chat(user, "There are no [icon_type]s left in the pack.") @@ -189,18 +213,18 @@ cig_position++ /obj/item/storage/fancy/cigarettes/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) - if(!ismob(M)) - return + if(M != user || !istype(M)) + return ..() var/obj/item/clothing/mask/cigarette/cig = locate(/obj/item/clothing/mask/cigarette) in contents if(cig) - if(M == user && contents.len > 0 && !user.wear_mask) + if(!user.wear_mask && !(SLOT_WEAR_MASK in M.check_obscured_slots())) var/obj/item/clothing/mask/cigarette/W = cig SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, M) M.equip_to_slot_if_possible(W, SLOT_WEAR_MASK) contents -= W to_chat(user, "You take \a [W] out of the pack.") else - ..() + return ..() else to_chat(user, "There are no [icon_type]s left in the pack.") @@ -308,6 +332,7 @@ w_class = WEIGHT_CLASS_NORMAL icon_type = "premium cigar" spawn_type = /obj/item/clothing/mask/cigarette/cigar + spawn_coupon = FALSE /obj/item/storage/fancy/cigarettes/cigars/ComponentInitialize() . = ..() @@ -379,6 +404,20 @@ STR.max_items = 6 STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/nugget)) +/obj/item/storage/fancy/cracker_pack + name = "cracker pack" + desc = "A pack of delicious crackers. Keep away from parrots!" + icon = 'icons/obj/food/containers.dmi' + icon_state = "crackerbox" + icon_type = "cracker" + spawn_type = /obj/item/reagent_containers/food/snacks/cracker + +/obj/item/storage/fancy/cracker_pack/ComponentInitialize() + . = ..() + var/datum/component/storage/STR = GetComponent(/datum/component/storage) + STR.max_items = 6 + STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/cracker)) + /* * Ring Box */ diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm index e082c15741..480e1966e9 100644 --- a/code/game/objects/items/storage/firstaid.dm +++ b/code/game/objects/items/storage/firstaid.dm @@ -41,9 +41,25 @@ new /obj/item/stack/medical/suture(src) new /obj/item/stack/medical/mesh(src) new /obj/item/stack/medical/mesh(src) - new /obj/item/reagent_containers/hypospray/medipen(src) + new /obj/item/reagent_containers/hypospray/medipen/ekit(src) new /obj/item/healthanalyzer(src) +/obj/item/storage/firstaid/emergency + icon_state = "medbriefcase" + name = "emergency first-aid kit" + desc = "A very simple first aid kit meant to secure and stabilize serious wounds for later treatment." + +/obj/item/storage/firstaid/emergency/PopulateContents() + if(empty) + return + var/static/items_inside = list( + /obj/item/healthanalyzer/wound = 1, + /obj/item/stack/medical/gauze = 1, + /obj/item/stack/medical/suture/emergency = 1, + /obj/item/stack/medical/ointment = 1, + /obj/item/reagent_containers/hypospray/medipen/ekit = 2) + generate_items_inside(items_inside,src) + /obj/item/storage/firstaid/ancient icon_state = "firstaid" desc = "A first aid kit with the ability to heal common types of injuries." @@ -229,6 +245,25 @@ STR.click_gather = TRUE STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice)) +/obj/item/storage/pill_bottle/AltClick(mob/living/carbon/user) + if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) + return + if(!length(user.get_empty_held_indexes())) + to_chat(user, "Your hands are full!") + return + var/obj/item/reagent_containers/pill/P = locate() in contents + if(P) + SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, P, user) + if(!user.put_in_hands(P)) + P.forceMove(user.drop_location()) // make sure it's not stuck in the user if the put in hands somehow fails + to_chat(user, "[P] drops to the floor!") + else + to_chat(user, "You take \a [P] out of [src].") + else + to_chat(user, "There are no pills left in the bottle.") + return TRUE + + /obj/item/storage/pill_bottle/suicide_act(mob/user) user.visible_message("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!") return (TOXLOSS) @@ -370,6 +405,14 @@ for(var/i in 1 to 7) new /obj/item/reagent_containers/pill/breast_enlargement(src) +/obj/item/storage/pill_bottle/neurine + name = "bottle of neurine pills" + desc = "Contains pills to treat non-severe mental traumas." + +/obj/item/storage/pill_bottle/neurine/PopulateContents() + for(var/i in 1 to 5) + new /obj/item/reagent_containers/pill/neurine(src) + ///////////// //Organ Box// ///////////// @@ -408,6 +451,7 @@ /obj/item/retractor, /obj/item/cautery, /obj/item/surgical_drapes, + /obj/item/bonesetter, /obj/item/autosurgeon, /obj/item/organ, /obj/item/implant, @@ -418,7 +462,8 @@ /obj/item/circuitboard/computer/crew, /obj/item/stack/sheet/glass, /obj/item/stack/sheet/mineral/silver, - /obj/item/organ_storage + /obj/item/organ_storage, + /obj/item/reagent_containers/chem_pack )) //hijacking the minature first aids for hypospray boxes. <3 diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm index 5b6089d430..ce4e8b9df1 100644 --- a/code/game/objects/items/storage/lockbox.dm +++ b/code/game/objects/items/storage/lockbox.dm @@ -188,19 +188,52 @@ new /obj/item/clothing/accessory/medal/plasma/nobel_science(src) /obj/item/storage/lockbox/medal/engineering - name = "engineering medal box" - desc = "A locked box used to store medals to be given to the members of the engineering department." - req_access = list(ACCESS_CE) + name = "engineering medal box" + desc = "A locked box used to store medals to be given to the members of the engineering department." + req_access = list(ACCESS_CE) /obj/item/storage/lockbox/medal/engineering/PopulateContents() - for(var/i in 1 to 3) - new /obj/item/clothing/accessory/medal/engineer(src) + for(var/i in 1 to 3) + new /obj/item/clothing/accessory/medal/engineer(src) /obj/item/storage/lockbox/medal/medical - name = "medical medal box" - desc = "A locked box used to store medals to be given to the members of the medical department." - req_access = list(ACCESS_CMO) + name = "medical medal box" + desc = "A locked box used to store medals to be given to the members of the medical department." + req_access = list(ACCESS_CMO) /obj/item/storage/lockbox/medal/medical/PopulateContents() - for(var/i in 1 to 3) - new /obj/item/clothing/accessory/medal/ribbon/medical_doctor(src) \ No newline at end of file + for(var/i in 1 to 3) + new /obj/item/clothing/accessory/medal/ribbon/medical_doctor(src) + +/obj/item/storage/lockbox/order + name = "order lockbox" + desc = "A box used to secure small cargo orders from being looted by those who didn't order it. Yeah, cargo tech, that means you." + icon = 'icons/obj/storage.dmi' + icon_state = "secure" + item_state = "sec-case" + lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi' + w_class = WEIGHT_CLASS_HUGE + var/datum/bank_account/buyer_account + var/privacy_lock = TRUE + +/obj/item/storage/lockbox/order/Initialize(datum/bank_account/_buyer_account) + . = ..() + buyer_account = _buyer_account + +/obj/item/storage/lockbox/order/attackby(obj/item/W, mob/user, params) + if(!istype(W, /obj/item/card/id)) + return ..() + + var/obj/item/card/id/id_card = W + if(iscarbon(user)) + add_fingerprint(user) + + if(id_card.registered_account != buyer_account) + to_chat(user, "Bank account does not match with buyer![user] [privacy_lock ? "" : "un"]locks [src]'s privacy lock.", + "You [privacy_lock ? "" : "un"]lock [src]'s privacy lock.") diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm index 0e9a9fda61..4e6a0b3463 100644 --- a/code/game/objects/items/storage/secure.dm +++ b/code/game/objects/items/storage/secure.dm @@ -205,10 +205,7 @@ new /obj/item/paper(src) new /obj/item/pen(src) -/obj/item/storage/secure/safe/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/storage/secure/safe/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) return attack_self(user) /obj/item/storage/secure/safe/HoS diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 7e89ddbd8d..73246276c2 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -20,12 +20,14 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) var/has_latches = TRUE var/can_rubberify = TRUE rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //very protecc too + wound_bonus = -10 + bare_wound_bonus = 5 /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 + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS /obj/item/storage/toolbox/Initialize(mapload) if(has_latches) @@ -243,19 +245,20 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) new /obj/item/stack/cable_coil/white(src) /obj/item/storage/toolbox/ammo - name = "ammo box" - desc = "It contains a few clips." + name = "ammunition case (7.62mm stripper clips)" + desc = "It contains a few 7.62 stripper clips." icon_state = "ammobox" item_state = "ammobox" + var/ammotype = /obj/item/ammo_box/a762 // make sure this is a typepath thanks /obj/item/storage/toolbox/ammo/PopulateContents() - new /obj/item/ammo_box/a762(src) - new /obj/item/ammo_box/a762(src) - new /obj/item/ammo_box/a762(src) - new /obj/item/ammo_box/a762(src) - new /obj/item/ammo_box/a762(src) - new /obj/item/ammo_box/a762(src) - new /obj/item/ammo_box/a762(src) + for (var/i = 0, i < 7, i++) + new ammotype(src) + +/obj/item/storage/toolbox/ammo/surplus + name = "ammunition case (10mm rifle magazines)" + desc = "It contains a few 10mm rifle magazines." + ammotype = /obj/item/ammo_box/magazine/m10mm/rifle /obj/item/storage/toolbox/infiltrator name = "insidious case" @@ -278,6 +281,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) /obj/item/clothing/suit/armor/vest/infiltrator, /obj/item/clothing/under/syndicate/bloodred, /obj/item/clothing/gloves/color/latex/nitrile/infiltrator, + /obj/item/clothing/gloves/tackler/combat/insulated/infiltrator, /obj/item/clothing/mask/infiltrator, /obj/item/clothing/shoes/combat/sneakboots, /obj/item/gun/ballistic/automatic/pistol, @@ -289,7 +293,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) new /obj/item/clothing/head/helmet/infiltrator(src) new /obj/item/clothing/suit/armor/vest/infiltrator(src) new /obj/item/clothing/under/syndicate/bloodred(src) - new /obj/item/clothing/gloves/color/latex/nitrile/infiltrator(src) + new /obj/item/clothing/gloves/tackler/combat/insulated/infiltrator(src) new /obj/item/clothing/mask/infiltrator(src) new /obj/item/clothing/shoes/combat/sneakboots(src) diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index ffa3d83304..442228ef31 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -117,7 +117,7 @@ new /obj/item/pizzabox/bomb if("darklord") //20 tc + tk + summon item close enough for now - new /obj/item/twohanded/dualsaber(src) + new /obj/item/dualsaber(src) new /obj/item/dnainjector/telemut/darkbundle(src) new /obj/item/clothing/suit/hooded/chaplain_hoodie(src) new /obj/item/card/id/syndicate(src) @@ -169,6 +169,14 @@ O.imp = new /obj/item/implant/freedom(O) O.update_icon() +/obj/item/storage/box/syndie_kit/imp_warp + name = "boxed warp implant (with injector)" + +/obj/item/storage/box/syndie_kit/imp_warp/PopulateContents() + var/obj/item/implanter/O = new(src) + O.imp = new /obj/item/implant/warp(O) + O.update_icon() + /obj/item/storage/box/syndie_kit/imp_microbomb name = "Microbomb Implant (with injector)" @@ -327,6 +335,7 @@ new /obj/item/reagent_containers/glass/bottle/romerol(src) new /obj/item/reagent_containers/syringe(src) new /obj/item/reagent_containers/dropper(src) + new /obj/item/paper/guides/antag/romerol_instructions(src) /obj/item/storage/box/syndie_kit/ez_clean/PopulateContents() for(var/i in 1 to 3) @@ -401,7 +410,7 @@ /obj/item/storage/box/syndie_kit/revolver /obj/item/storage/box/syndie_kit/revolver/PopulateContents() - new /obj/item/gun/ballistic/revolver(src) + new /obj/item/gun/ballistic/revolver/syndicate(src) new /obj/item/ammo_box/a357(src) /obj/item/storage/box/syndie_kit/pistol diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index fa0c9ba693..1a84b85a1a 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -14,6 +14,7 @@ w_class = WEIGHT_CLASS_NORMAL attack_verb = list("beaten") armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) + attack_speed = CLICK_CD_MELEE var/stamforce = 35 var/turned_on = FALSE @@ -144,8 +145,9 @@ return ..() /obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params) + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return . = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming. - user.changeNext_move(CLICK_CD_MELEE) //return TRUE to interrupt attack chain. /obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE) @@ -156,6 +158,7 @@ if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit to_chat(user, "You're too exhausted to use [src] properly.") return TRUE + user.DelayNextAction() if(ishuman(M)) var/mob/living/carbon/human/L = M if(check_martial_counter(L, user)) diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index 817258d1c7..7cf25098e1 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -21,7 +21,7 @@ /obj/item/tank/jetpack/populate_gas() if(gas_type) - air_contents.gases[gas_type] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) + air_contents.set_moles(gas_type, ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))) /obj/item/tank/jetpack/ui_action_click(mob/user, action) diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index b4c8d8adf0..1c90a83c0a 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -18,8 +18,9 @@ force = 10 dog_fashion = /datum/dog_fashion/back + /obj/item/tank/internals/oxygen/populate_gas() - air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/oxygen, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return @@ -47,8 +48,9 @@ force = 10 /obj/item/tank/internals/anesthetic/populate_gas() - air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD - air_contents.gases[/datum/gas/nitrous_oxide] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD + air_contents.set_moles(/datum/gas/oxygen, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) + air_contents.set_moles(/datum/gas/nitrous_oxide, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) + return /* * Air @@ -62,8 +64,9 @@ dog_fashion = /datum/dog_fashion/back /obj/item/tank/internals/air/populate_gas() - air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD - air_contents.gases[/datum/gas/nitrogen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD + air_contents.set_moles(/datum/gas/oxygen, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD) + air_contents.set_moles(/datum/gas/nitrogen, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD) + return /* @@ -79,7 +82,8 @@ /obj/item/tank/internals/plasma/populate_gas() - air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/plasma, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + return /obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/flamethrower)) @@ -93,12 +97,16 @@ F.update_icon() else return ..() + +/obj/item/tank/internals/plasma/full/populate_gas() + air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + //Makes empty oxygen tanks spawn without gas /obj/item/tank/internals/plasma/empty/populate_gas() return /obj/item/tank/internals/plasma/full/populate_gas() - air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) /* * Plasmaman Plasma Tank @@ -113,10 +121,11 @@ distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE /obj/item/tank/internals/plasmaman/populate_gas() - air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/plasma, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) + return /obj/item/tank/internals/plasmaman/full/populate_gas() - air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return @@ -129,7 +138,7 @@ w_class = WEIGHT_CLASS_SMALL //thanks i forgot this /obj/item/tank/internals/plasmaman/belt/full/populate_gas() - air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/plasma, (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return //makes empty plasma tanks spawn without gas. @@ -152,7 +161,7 @@ /obj/item/tank/internals/emergency_oxygen/populate_gas() - air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) + air_contents.set_moles(/datum/gas/oxygen, (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)) return /obj/item/tank/internals/emergency_oxygen/empty/populate_gas() @@ -172,4 +181,4 @@ volume = 10 /obj/item/tank/internals/emergency_oxygen/double/empty/populate_gas() - return \ No newline at end of file + return diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 00fbc41516..08b91332ef 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -64,7 +64,7 @@ . = ..() air_contents = new(volume) //liters - air_contents.temperature = T20C + air_contents.set_temperature(T20C) populate_gas() @@ -92,7 +92,7 @@ . += "The pressure gauge reads [round(src.air_contents.return_pressure(),0.01)] kPa." - var/celsius_temperature = src.air_contents.temperature-T0C + var/celsius_temperature = src.air_contents.return_temperature()-T0C var/descriptive if (celsius_temperature < 20) @@ -123,6 +123,7 @@ /obj/item/tank/analyzer_act(mob/living/user, obj/item/I) atmosanalyzer_scan(air_contents, user, src) + return TRUE /obj/item/tank/deconstruct(disassembled = TRUE) if(!disassembled) @@ -143,7 +144,6 @@ if(prob(50)) step(W, pick(GLOB.alldirs)) ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC) - H.bleed_rate = 5 H.gib_animation() sleep(3) H.adjustBruteLoss(1000) //to make the body super-bloody @@ -164,11 +164,13 @@ else . = ..() -/obj/item/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ - datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/tank/ui_state(mob/user) + return GLOB.hands_state + +/obj/item/tank/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "tanks", name, 400, 120, master_ui, state) + ui = new(user, src, "Tank", name) ui.open() /obj/item/tank/ui_data(mob/user) @@ -205,10 +207,6 @@ else if(pressure == "max") pressure = TANK_MAX_RELEASE_PRESSURE . = TRUE - else if(pressure == "input") - pressure = input("New release pressure ([TANK_MIN_RELEASE_PRESSURE]-[TANK_MAX_RELEASE_PRESSURE] kPa):", name, distribute_pressure) as num|null - if(!isnull(pressure) && !..()) - . = TRUE else if(text2num(pressure) != null) pressure = text2num(pressure) . = TRUE @@ -235,7 +233,7 @@ if(tank_pressure < distribute_pressure) distribute_pressure = tank_pressure - var/moles_needed = distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.temperature) + var/moles_needed = distribute_pressure*volume_to_return/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature()) return remove_air(moles_needed) diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm index b1c0d3dfbb..16a91b6358 100644 --- a/code/game/objects/items/tanks/watertank.dm +++ b/code/game/objects/items/tanks/watertank.dm @@ -72,7 +72,7 @@ QDEL_NULL(noz) return ..() -/obj/item/watertank/attack_hand(mob/user) +/obj/item/watertank/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if (user.get_item_by_slot(user.getBackSlot()) == src) toggle_mister(user) else diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index 881e4d5f1a..f9ede407ca 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -1,4 +1,3 @@ - #define SOURCE_PORTAL 1 #define DESTINATION_PORTAL 2 @@ -25,90 +24,72 @@ throw_speed = 3 throw_range = 7 custom_materials = list(/datum/material/iron=400) + var/tracking_range = 20 -/obj/item/locator/attack_self(mob/user) - user.set_machine(src) - var/dat - if (temp) - dat = "[temp]

    Clear" - else - dat = {" -Persistent Signal Locator
    -Refresh"} - user << browse(dat, "window=radio") - onclose(user, "radio") - return +/obj/item/locator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "BluespaceLocator", name) + ui.open() -/obj/item/locator/Topic(href, href_list) - ..() - if (usr.stat || usr.restrained()) - return - var/turf/current_location = get_turf(usr)//What turf is the user on? - if(!current_location || is_centcom_level(current_location.z))//If turf was not found or they're on CentCom - to_chat(usr, "[src] is malfunctioning.") - return - if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc))) - usr.set_machine(src) - if (href_list["refresh"]) - temp = "Persistent Signal Locator
    " - var/turf/sr = get_turf(src) +/obj/item/locator/ui_data(mob/user) + var/list/data = list() - if (sr) - temp += "Beacon Signals:
    " - for(var/obj/item/beacon/W in GLOB.teleportbeacons) - if (!W.renamed) - continue - var/turf/tr = get_turf(W) - if (tr.z == sr.z && tr) - var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) - if (direct < 5) - direct = "very strong" - else - if (direct < 10) - direct = "strong" - else - if (direct < 20) - direct = "weak" - else - direct = "very weak" - temp += "[W.name]-[dir2text(get_dir(sr, tr))]-[direct]
    " + data["trackingrange"] = tracking_range - temp += "Implant Signals:
    " - for (var/obj/item/implant/tracking/W in GLOB.tracked_implants) - if (!isliving(W.imp_in)) - continue - var/mob/living/M = W.imp_in - if (M.stat == DEAD) - if (M.timeofdeath + W.lifespan_postmortem < world.time) - continue + // Get our current turf location. + var/turf/sr = get_turf(src) - var/turf/tr = get_turf(M) - if (tr.z == sr.z && tr) - var/direct = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) - if (direct < 20) - if (direct < 5) - direct = "very strong" - else - if (direct < 10) - direct = "strong" - else - direct = "weak" - temp += "[W.imp_in.name]-[dir2text(get_dir(sr, tr))]-[direct]
    " + if (sr) + // Check every teleport beacon. + var/list/tele_beacons = list() + for(var/obj/item/beacon/W in GLOB.teleportbeacons) - temp += "You are at \[[sr.x],[sr.y],[sr.z]\] in orbital coordinates.

    Refresh
    " + // Get the tracking beacon's turf location. + var/turf/tr = get_turf(W) + + // Make sure it's on a turf and that its Z-level matches the tracker's Z-level + if (tr && tr.z == sr.z) + // Get the distance between the beacon's turf and our turf + var/distance = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) + + // If the target is too far away, skip over this beacon. + if(distance > tracking_range) + continue + + var/beacon_name + + if(W.renamed) + beacon_name = W.name + else + var/area/A = get_area(W) + beacon_name = A.name + + var/D = dir2text(get_dir(sr, tr)) + tele_beacons += list(list(name = beacon_name, direction = D, distance = distance)) + + data["telebeacons"] = tele_beacons + + var/list/track_implants = list() + + for (var/obj/item/implant/tracking/W in GLOB.tracked_implants) + if (!W.imp_in || !isliving(W.loc)) + continue else - temp += "Processing Error: Unable to locate orbital position.
    " - else - if (href_list["temp"]) - temp = null - if (ismob(src.loc)) - attack_self(src.loc) - else - for(var/mob/M in fov_viewers(1, src)) - if (M.client) - src.attack_self(M) - return + var/mob/living/M = W.loc + if (M.stat == DEAD) + if (M.timeofdeath + W.lifespan_postmortem < world.time) + continue + var/turf/tr = get_turf(W) + var/distance = max(abs(tr.x - sr.x), abs(tr.y - sr.y)) + if(distance > tracking_range) + continue + + var/D = dir2text(get_dir(sr, tr)) + track_implants += list(list(name = W.imp_in.name, direction = D, distance = distance)) + data["trackimplants"] = track_implants + return data /* * Hand-tele @@ -190,13 +171,8 @@ user.show_message("\The [src] is recharging!") return var/atom/T = L[t1] - var/implantcheckmate = FALSE - if(isliving(T)) - var/mob/living/M = T - if(!locate(/obj/item/implant/tracking) in M.implants) //The user was too slow and let the target mob's tracking implant expire or get removed. - implantcheckmate = TRUE var/area/A = get_area(T) - if(A.noteleport || implantcheckmate) + if(A.noteleport) to_chat(user, "\The [src] is malfunctioning.") return current_location = get_turf(user) //Recheck. @@ -205,10 +181,12 @@ to_chat(user, "\The [src] is malfunctioning.") return user.show_message("Locked In.", MSG_AUDIBLE) - var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), src, 300, 1, null, atmos_link_override) + var/list/obj/effect/portal/created = create_portal_pair(current_location, get_teleport_turf(get_turf(T)), 300, 1, null, atmos_link_override) if(!(LAZYLEN(created) == 2)) return - try_move_adjacent(created[1]) + RegisterSignal(created[1], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy) //Gosh darn it kevinz. + RegisterSignal(created[2], COMSIG_PARENT_QDELETING, .proc/on_portal_destroy) + try_move_adjacent(created[1], user.dir) active_portal_pairs[created[1]] = created[2] var/obj/effect/portal/c1 = created[1] var/obj/effect/portal/c2 = created[2] diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 91e8c49e5a..6159ab7ba0 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -18,6 +18,9 @@ toolspeed = 1 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + wound_bonus = -10 + bare_wound_bonus = 5 + /obj/item/crowbar/suicide_act(mob/user) user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) @@ -90,6 +93,7 @@ /obj/item/crowbar/power/attack_self(mob/user) playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power(drop_location()) + cutjaws.name = name to_chat(user, "You attach the cutting jaws to [src].") qdel(src) user.put_in_active_hand(cutjaws) diff --git a/code/game/objects/items/tools/saw.dm b/code/game/objects/items/tools/saw.dm deleted file mode 100644 index aab59c00be..0000000000 --- a/code/game/objects/items/tools/saw.dm +++ /dev/null @@ -1,47 +0,0 @@ -/obj/item/hatchet/saw - name = "handsaw" - desc = "A very sharp handsaw, it's compact." - icon = 'icons/obj/tools.dmi' - icon_state = "saw" - item_state = "sawhandle_greyscale" - lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi' - tool_behaviour = TOOL_SAW - force = 10 - throwforce = 8 - throw_speed = 3 - throw_range = 5 - custom_materials = list(/datum/material/iron = 5000) - attack_verb = list("sawed", "sliced", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP - var/random_color = TRUE //code taken from screwdrivers.dm; cool handles are cool. - var/static/list/saw_colors = list( - "blue" = rgb(24, 97, 213), - "red" = rgb(255, 0, 0), - "pink" = rgb(213, 24, 141), - "brown" = rgb(160, 82, 18), - "green" = rgb(14, 127, 27), - "cyan" = rgb(24, 162, 213), - "yellow" = rgb(255, 165, 0) - ) - -/obj/item/hatchet/saw/Initialize() - . = ..() - if(random_color) - icon_state = "sawhandle_greyscale" - var/our_color = pick(saw_colors) - add_atom_colour(saw_colors[our_color], FIXED_COLOUR_PRIORITY) - update_icon() - if(prob(75)) - pixel_y = rand(-8, 8) - -/obj/item/hatchet/saw/update_overlays() - . = ..() - if(!random_color) //icon override - return - var/mutable_appearance/base_overlay = mutable_appearance(icon, "sawblade") - base_overlay.appearance_flags = RESET_COLOR - . += base_overlay - -// END \ No newline at end of file diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index e9f517a9f1..86c223606d 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -31,6 +31,9 @@ "yellow" = rgb(255, 165, 0) ) + wound_bonus = -10 + bare_wound_bonus = 5 + /obj/item/screwdriver/suicide_act(mob/user) user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") return(BRUTELOSS) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 6bcac76824..4cada03307 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -33,6 +33,8 @@ heat = 3800 tool_behaviour = TOOL_WELDER toolspeed = 1 + wound_bonus = 0 + bare_wound_bonus = 5 /obj/item/weldingtool/Initialize() . = ..() diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm index ac5a02b9fc..53a578a45d 100644 --- a/code/game/objects/items/tools/wirecutters.dm +++ b/code/game/objects/items/tools/wirecutters.dm @@ -117,6 +117,7 @@ /obj/item/wirecutters/power/attack_self(mob/user) playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1) var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power(drop_location()) + pryjaws.name = name to_chat(user, "You attach the pry jaws to [src].") qdel(src) user.put_in_active_hand(pryjaws) diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index 678096db28..e1c09f394e 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -18,6 +18,9 @@ toolspeed = 1 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + wound_bonus = -10 + bare_wound_bonus = 5 + /obj/item/wrench/suicide_act(mob/user) user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index cd630a2c82..4e82df2452 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -272,7 +272,7 @@ return else to_chat(user, "You attach the ends of the two plastic swords, making a single double-bladed toy! You're fake-cool.") - var/obj/item/twohanded/dualsaber/toy/newSaber = new /obj/item/twohanded/dualsaber/toy(user.loc) + var/obj/item/dualsaber/toy/newSaber = new /obj/item/dualsaber/toy(user.loc) if(hacked) // That's right, we'll only check the "original" "sword". newSaber.hacked = TRUE qdel(W) @@ -363,7 +363,7 @@ return else to_chat(user, "You combine the two plastic swords, making a single supermassive toy! You're fake-cool.") - new /obj/item/twohanded/dualsaber/hypereutactic/toy(user.loc) + new /obj/item/dualsaber/hypereutactic/toy(user.loc) qdel(W) qdel(src) else @@ -437,41 +437,44 @@ /* * Subtype of Double-Bladed Energy Swords */ -/obj/item/twohanded/dualsaber/toy +/obj/item/dualsaber/toy name = "double-bladed toy sword" desc = "A cheap, plastic replica of TWO energy swords. Double the fun!" force = 0 throwforce = 0 throw_speed = 3 throw_range = 5 - force_unwielded = 0 - force_wielded = 0 block_parry_data = null attack_verb = list("attacked", "struck", "hit") total_mass_on = TOTAL_MASS_TOY_SWORD - sharpness = IS_BLUNT + sharpness = SHARP_NONE -/obj/item/twohanded/dualsaber/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +/obj/item/dualsaber/toy/ComponentInitialize() + AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg') + +/obj/item/dualsaber/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) return BLOCK_NONE -/obj/item/twohanded/dualsaber/hypereutactic/toy +/obj/item/dualsaber/hypereutactic/toy name = "\improper DX Hyper-Euplastic LightSword" desc = "A supermassive toy envisioned to cleave the very fabric of space and time itself in twain. Realistic visuals and sounds! Ages 8 and up." force = 0 throwforce = 0 throw_speed = 3 throw_range = 5 - force_unwielded = 0 - force_wielded = 0 + attack_verb = list("attacked", "struck", "hit") total_mass_on = TOTAL_MASS_TOY_SWORD slowdown_wielded = 0 - sharpness = IS_BLUNT + sharpness = SHARP_NONE -/obj/item/twohanded/dualsaber/hypereutactic/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +/obj/item/dualsaber/hypereutactic/toy/ComponentInitialize() + AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg') + +/obj/item/dualsaber/hypereutactic/toy/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) return BLOCK_NONE -/obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow +/obj/item/dualsaber/hypereutactic/toy/rainbow name = "\improper Hyper-Euclidean Reciprocating Trigonometric Zweihander" desc = "A custom-built toy with fancy rainbow lights built-in." hacked = TRUE @@ -571,10 +574,7 @@ else . = ..() -/obj/item/toy/prize/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/toy/prize/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user) attack_self(user) @@ -808,9 +808,8 @@ cards += "Ace of Clubs" cards += "Ace of Diamonds" -//ATTACK HAND IGNORING PARENT RETURN VALUE //ATTACK HAND NOT CALLING PARENT -/obj/item/toy/cards/deck/attack_hand(mob/user) +/obj/item/toy/cards/deck/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) draw_card(user) /obj/item/toy/cards/deck/proc/draw_card(mob/user) @@ -823,12 +822,11 @@ var/obj/item/toy/cards/singlecard/H = new/obj/item/toy/cards/singlecard(user.loc) if(holo) holo.spawned += H // track them leaving the holodeck - choice = cards[1] + choice = popleft(cards) H.cardname = choice H.parentdeck = src var/O = src H.apply_card_vars(H,O) - src.cards -= choice H.pickup(user) user.put_in_hands(H) user.visible_message("[user] draws a card from the deck.", "You draw a card from the deck.") @@ -1232,7 +1230,7 @@ name = "steampunk watch" desc = "A stylish steampunk watch made out of thousands of tiny cogwheels." icon = 'icons/obj/clockwork_objects.dmi' - icon_state = "dread_ipad" + icon_state = "clockwork_slab" slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_SMALL var/cooldown = 0 diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 4c6bcc08b4..2109d1038e 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -35,6 +35,10 @@ name = "syndi-cakes" icon_state = "syndi_cakes" +/obj/item/trash/energybar + name = "energybar wrapper" + icon_state = "energybar" + /obj/item/trash/waffles name = "waffles tray" icon_state = "waffles" diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm deleted file mode 100644 index 8c9cde5b76..0000000000 --- a/code/game/objects/items/twohanded.dm +++ /dev/null @@ -1,1411 +0,0 @@ -/* Two-handed Weapons - * Contains: - * Twohanded - * Fireaxe - * Double-Bladed Energy Swords - * Spears - * CHAINSAWS - * Bone Axe and Spear - * And more - */ - -/*################################################################## -##################### TWO HANDED WEAPONS BE HERE~ -Agouri :3 ######## -####################################################################*/ - -//Rewrote TwoHanded weapons stuff and put it all here. Just copypasta fireaxe to make new ones ~Carn -//This rewrite means we don't have two variables for EVERY item which are used only by a few weapons. -//It also tidies stuff up elsewhere. - - - - -/* - * Twohanded - */ -/obj/item/twohanded - var/wielded = FALSE - var/force_unwielded // default to null, the number force will be set to on unwield() - var/force_wielded // same as above but for wield() - var/wieldsound = null - var/unwieldsound = null - var/slowdown_wielded = 0 - /// Do we need to be wielded to actively block/parry? - var/requires_wield_to_block_parry = TRUE - item_flags = SLOWS_WHILE_IN_HAND - -/obj/item/twohanded/proc/unwield(mob/living/carbon/user, show_message = TRUE) - if(!wielded || !user) - return - wielded = 0 - if(!isnull(force_unwielded)) - force = force_unwielded - var/sf = findtext(name, " (Wielded)", -10)//10 == length(" (Wielded)") - if(sf) - name = copytext(name, 1, sf) - else //something wrong - name = "[initial(name)]" - update_icon() - if(user.get_item_by_slot(SLOT_BACK) == src) - user.update_inv_back() - else - user.update_inv_hands() - if(show_message) - if(iscyborg(user)) - to_chat(user, "You free up your module.") - else - to_chat(user, "You are now carrying [src] with one hand.") - if(unwieldsound) - playsound(loc, unwieldsound, 50, 1) - var/obj/item/twohanded/offhand/O = user.get_inactive_held_item() - if(O && istype(O)) - O.unwield() - set_slowdown(slowdown - slowdown_wielded) - -/obj/item/twohanded/proc/wield(mob/living/carbon/user) - if(wielded) - return - if(ismonkey(user)) - to_chat(user, "It's too heavy for you to wield fully.") - return - if(user.get_inactive_held_item()) - to_chat(user, "You need your other hand to be empty!") - return - if(user.get_num_arms() < 2) - to_chat(user, "You don't have enough intact hands.") - return - wielded = 1 - if(!isnull(force_wielded)) - force = force_wielded - name = "[name] (Wielded)" - update_icon() - if(iscyborg(user)) - to_chat(user, "You dedicate your module to [src].") - else - to_chat(user, "You grab [src] with both hands.") - if (wieldsound) - playsound(loc, wieldsound, 50, 1) - var/obj/item/twohanded/offhand/O = new(user) ////Let's reserve his other hand~ - O.name = "[name] - offhand" - O.desc = "Your second grip on [src]." - O.wielded = TRUE - user.put_in_inactive_hand(O) - set_slowdown(slowdown + slowdown_wielded) - -/obj/item/twohanded/can_active_block() - return ..() && (!requires_wield_to_block_parry || wielded) - -/obj/item/twohanded/can_active_parry() - return ..() && (!requires_wield_to_block_parry || wielded) - -/obj/item/twohanded/dropped(mob/user) - . = ..() - //handles unwielding a twohanded weapon when dropped as well as clearing up the offhand - if(!wielded) - return - unwield(user) - -/obj/item/twohanded/attack_self(mob/user) - . = ..() - if(wielded) //Trying to unwield it - unwield(user) - else //Trying to wield it - wield(user) - -/obj/item/twohanded/equip_to_best_slot(mob/M) - if(..()) - if(istype(src, /obj/item/twohanded/required)) - return // unwield forces twohanded-required items to be dropped. - unwield(M) - return - -/obj/item/twohanded/equipped(mob/user, slot) - ..() - if(!user.is_holding(src) && wielded && !istype(src, /obj/item/twohanded/required)) - unwield(user) - -///////////OFFHAND/////////////// -/obj/item/twohanded/offhand - name = "offhand" - icon_state = "offhand" - w_class = WEIGHT_CLASS_HUGE - item_flags = ABSTRACT - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - -/obj/item/twohanded/offhand/Destroy() - wielded = FALSE - return ..() - -/obj/item/twohanded/offhand/dropped(mob/living/user, show_message = TRUE) //Only utilized by dismemberment since you can't normally switch to the offhand to drop it. - . = ..() - var/obj/I = user.get_active_held_item() - if(I && istype(I, /obj/item/twohanded)) - var/obj/item/twohanded/thw = I - thw.unwield(user, show_message) - if(istype(thw, /obj/item/twohanded/required)) - user.dropItemToGround(thw) - if(!QDELETED(src)) - qdel(src) - -/obj/item/twohanded/offhand/unwield() - if(wielded)//Only delete if we're wielded - wielded = FALSE - qdel(src) - -/obj/item/twohanded/offhand/wield() - if(wielded)//Only delete if we're wielded - wielded = FALSE - qdel(src) - -/obj/item/twohanded/offhand/attack_self(mob/living/carbon/user) //You should never be able to do this in standard use of two handed items. This is a backup for lingering offhands. - var/obj/item/twohanded/O = user.get_inactive_held_item() - if (istype(O) && !istype(O, /obj/item/twohanded/offhand/)) //If you have a proper item in your other hand that the offhand is for, do nothing. This should never happen. - return - if (QDELETED(src)) - return - qdel(src) //If it's another offhand, or literally anything else, qdel. If I knew how to add logging messages I'd put one here. - -///////////Two hand required objects/////////////// -//This is for objects that require two hands to even pick up -/obj/item/twohanded/required - w_class = WEIGHT_CLASS_HUGE - -/obj/item/twohanded/required/attack_self() - return - -/obj/item/twohanded/required/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0) - if(wielded && !slot_flags) - if(!disable_warning) - to_chat(M, "[src] is too cumbersome to carry with anything but your hands!") - return 0 - return ..() - -/obj/item/twohanded/required/attack_hand(mob/user)//Can't even pick it up without both hands empty - var/obj/item/twohanded/required/H = user.get_inactive_held_item() - if(get_dist(src,user) > 1) - return - if(H != null) - to_chat(user, "[src] is too cumbersome to carry in one hand!") - return - if(loc != user) - wield(user) - . = ..() - -/obj/item/twohanded/required/equipped(mob/user, slot) - ..() - var/slotbit = slotdefine2slotbit(slot) - if(slot_flags & slotbit) - var/datum/O = user.is_holding_item_of_type(/obj/item/twohanded/offhand) - if(!O || QDELETED(O)) - return - qdel(O) - return - if(slot == SLOT_HANDS) - wield(user) - else - unwield(user) - -/obj/item/twohanded/required/dropped(mob/living/user, show_message = TRUE) - unwield(user, show_message) - ..() - -/obj/item/twohanded/required/wield(mob/living/carbon/user) - ..() - if(!wielded) - user.dropItemToGround(src) - -/obj/item/twohanded/required/unwield(mob/living/carbon/user, show_message = TRUE) - if(!wielded) - return - if(show_message) - to_chat(user, "You drop [src].") - ..(user, FALSE) - -/* - * Fireaxe - */ -/obj/item/twohanded/fireaxe // DEM AXES MAN, marker -Agouri - icon_state = "fireaxe0" - lefthand_file = 'icons/mob/inhands/weapons/axes_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/axes_righthand.dmi' - name = "fire axe" - desc = "Truly, the weapon of a madman. Who would think to fight fire with an axe?" - force = 5 - throwforce = 15 - w_class = WEIGHT_CLASS_BULKY - slot_flags = ITEM_SLOT_BACK - force_unwielded = 5 - force_wielded = 24 - attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP - max_integrity = 200 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) - resistance_flags = FIRE_PROOF - -/obj/item/twohanded/fireaxe/Initialize() - . = ..() - AddComponent(/datum/component/butchering, 100, 80, 0 , hitsound) //axes are not known for being precision butchering tools - -/obj/item/twohanded/fireaxe/update_icon_state() //Currently only here to fuck with the on-mob icons. - icon_state = "fireaxe[wielded]" - return - -/obj/item/twohanded/fireaxe/suicide_act(mob/user) - user.visible_message("[user] axes [user.p_them()]self from head to toe! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/twohanded/fireaxe/afterattack(atom/A, mob/living/user, proximity) - . = ..() - if(!proximity || IS_STAMCRIT(user)) //don't make stamcrit message they'll already have gotten one from the primary attack. - return - if(wielded) //destroys windows and grilles in one hit (or more if it has a ton of health like plasmaglass) - if(istype(A, /obj/structure/window)) - var/obj/structure/window/W = A - W.take_damage(200, BRUTE, "melee", 0) - else if(istype(A, /obj/structure/grille)) - var/obj/structure/grille/G = A - G.take_damage(40, BRUTE, "melee", 0) - - -/* - * Double-Bladed Energy Swords - Cheridan - */ -/obj/item/twohanded/dualsaber - icon_state = "dualsaber0" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - name = "double-bladed energy sword" - desc = "Handle with care." - force = 3 - throwforce = 5 - throw_speed = 3 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - var/w_class_on = WEIGHT_CLASS_BULKY - item_flags = ITEM_CAN_PARRY | SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK - block_parry_data = /datum/block_parry_data/dual_esword - force_unwielded = 3 - force_wielded = 34 - wieldsound = 'sound/weapons/saberon.ogg' - unwieldsound = 'sound/weapons/saberoff.ogg' - hitsound = "swing_hit" - var/hitsound_on = 'sound/weapons/blade1.ogg' - armour_penetration = 35 - var/saber_color = "green" - light_color = "#00ff00"//green - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - max_integrity = 200 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70) - resistance_flags = FIRE_PROOF - var/hacked = FALSE - /// Can this reflect all energy projectiles? - var/can_reflect = TRUE - var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD - var/list/possible_colors = list("red", "blue", "green", "purple") - var/list/rainbow_colors = list(LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER) - var/spinnable = TRUE - total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces. - var/total_mass_on = 3.4 - -/datum/block_parry_data/dual_esword - block_damage_absorption = 2 - block_damage_multiplier = 0.15 - block_damage_multiplier_override = list( - ATTACK_TYPE_MELEE = 0.25 - ) - block_start_delay = 0 // instantaneous block - block_stamina_cost_per_second = 2.5 - block_stamina_efficiency = 3 - block_lock_sprinting = TRUE - // no attacking while blocking - block_lock_attacking = TRUE - block_projectile_mitigation = 75 - - parry_time_windup = 0 - parry_time_active = 8 - parry_time_spindown = 0 - // we want to signal to players the most dangerous phase, the time when automatic counterattack is a thing. - parry_time_windup_visual_override = 1 - parry_time_active_visual_override = 3 - parry_time_spindown_visual_override = 4 - parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // esword users can attack while parrying. - parry_time_perfect = 2 // first ds isn't perfect - parry_time_perfect_leeway = 1 - parry_imperfect_falloff_percent = 10 - parry_efficiency_to_counterattack = 100 - parry_efficiency_considered_successful = 25 // VERY generous - parry_efficiency_perfect = 90 - parry_failed_stagger_duration = 3 SECONDS - parry_failed_clickcd_duration = CLICK_CD_MELEE - - // more efficient vs projectiles - block_stamina_efficiency_override = list( - TEXT_ATTACK_TYPE_PROJECTILE = 4 - ) - -/obj/item/twohanded/dualsaber/suicide_act(mob/living/carbon/user) - if(wielded) - user.visible_message("[user] begins spinning way too fast! It looks like [user.p_theyre()] trying to commit suicide!") - - var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD)//stole from chainsaw code - var/obj/item/organ/brain/B = user.getorganslot(ORGAN_SLOT_BRAIN) - B.organ_flags &= ~ORGAN_VITAL //this cant possibly be a good idea - var/randdir - for(var/i in 1 to 24)//like a headless chicken! - if(user.is_holding(src)) - randdir = pick(GLOB.alldirs) - user.Move(get_step(user, randdir),randdir) - user.emote("spin") - if (i == 3 && myhead) - myhead.drop_limb() - sleep(3) - else - user.visible_message("[user] panics and starts choking to death!") - return OXYLOSS - - - else - user.visible_message("[user] begins beating [user.p_them()]self to death with \the [src]'s handle! It probably would've been cooler if [user.p_they()] turned it on first!") - return BRUTELOSS - -/obj/item/twohanded/dualsaber/Initialize() - . = ..() - if(LAZYLEN(possible_colors)) - saber_color = pick(possible_colors) - switch(saber_color) - if("red") - light_color = LIGHT_COLOR_RED - if("green") - light_color = LIGHT_COLOR_GREEN - if("blue") - light_color = LIGHT_COLOR_LIGHT_CYAN - if("purple") - light_color = LIGHT_COLOR_LAVENDER - -/obj/item/twohanded/dualsaber/Destroy() - STOP_PROCESSING(SSobj, src) - . = ..() - -/obj/item/twohanded/dualsaber/update_icon_state() - if(wielded) - icon_state = "dualsaber[saber_color][wielded]" - else - icon_state = "dualsaber0" - clean_blood() - -/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user) - if(user.has_dna()) - if(user.dna.check_mutation(HULK)) - to_chat(user, "You grip the blade too hard and accidentally close it!") - unwield() - return - ..() - if(HAS_TRAIT(user, TRAIT_CLUMSY) && (wielded) && prob(40)) - impale(user) - return - if(spinnable && (wielded) && prob(50)) - INVOKE_ASYNC(src, .proc/jedi_spin, user) - -/obj/item/twohanded/dualsaber/proc/jedi_spin(mob/living/user) - for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) - user.setDir(i) - if(i == WEST) - user.emote("flip") - sleep(1) - -/obj/item/twohanded/dualsaber/proc/impale(mob/living/user) - to_chat(user, "You twirl around a bit before losing your balance and impaling yourself on [src].") - if (force_wielded) - user.take_bodypart_damage(20,25) - else - user.adjustStaminaLoss(25) - -/obj/item/twohanded/dualsaber/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) - if(!wielded) - return NONE - if(can_reflect && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE)) - block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_RETURN_TO_SENDER //no you - return BLOCK_SHOULD_REDIRECT | BLOCK_SUCCESS | BLOCK_REDIRECTED - return ..() - -/obj/item/twohanded/dualsaber/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) //In case thats just so happens that it is still activated on the groud, prevents hulk from picking it up - if(wielded) - to_chat(user, "You can't pick up such dangerous item with your meaty hands without losing fingers, better not to!") - return 1 - -/obj/item/twohanded/dualsaber/wield(mob/living/carbon/M) //Specific wield () hulk checks due to reflection chance for balance issues and switches hitsounds. - if(M.has_dna()) - if(M.dna.check_mutation(HULK)) - to_chat(M, "You lack the grace to wield this!") - return - ..() - if(wielded) - sharpness = IS_SHARP - w_class = w_class_on - total_mass = total_mass_on - hitsound = 'sound/weapons/blade1.ogg' - START_PROCESSING(SSobj, src) - set_light(brightness_on) - AddElement(/datum/element/sword_point) - -/obj/item/twohanded/dualsaber/unwield() //Specific unwield () to switch hitsounds. - sharpness = initial(sharpness) - w_class = initial(w_class) - total_mass = initial(total_mass) - ..() - hitsound = "swing_hit" - STOP_PROCESSING(SSobj, src) - set_light(0) - RemoveElement(/datum/element/sword_point) - -/obj/item/twohanded/dualsaber/process() - if(wielded) - if(hacked) - rainbow_process() - open_flame() - else - STOP_PROCESSING(SSobj, src) - -/obj/item/twohanded/dualsaber/proc/rainbow_process() - light_color = pick(rainbow_colors) - -/obj/item/twohanded/dualsaber/ignition_effect(atom/A, mob/user) - // same as /obj/item/melee/transforming/energy, mostly - if(!wielded) - return "" - var/in_mouth = "" - if(iscarbon(user)) - var/mob/living/carbon/C = user - if(C.wear_mask) - in_mouth = ", barely missing [user.p_their()] nose" - . = "[user] swings [user.p_their()] [name][in_mouth]. [user.p_they(TRUE)] light[user.p_s()] [user.p_their()] [A.name] in the process." - playsound(loc, hitsound, get_clamped_volume(), 1, -1) - add_fingerprint(user) - // Light your candles while spinning around the room - if(spinnable) - INVOKE_ASYNC(src, .proc/jedi_spin, user) - -/obj/item/twohanded/dualsaber/green - possible_colors = list("green") - -/obj/item/twohanded/dualsaber/red - possible_colors = list("red") - -/obj/item/twohanded/dualsaber/blue - possible_colors = list("blue") - -/obj/item/twohanded/dualsaber/purple - possible_colors = list("purple") - -/obj/item/twohanded/dualsaber/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/multitool)) - if(!hacked) - hacked = TRUE - to_chat(user, "2XRNBW_ENGAGE") - saber_color = "rainbow" - update_icon() - else - to_chat(user, "It's starting to look like a triple rainbow - no, nevermind.") - else - return ..() - -///////////////////////////////////////////////////// -// HYPEREUTACTIC Blades ///////////////////////// -///////////////////////////////////////////////////// - -/obj/item/twohanded/dualsaber/hypereutactic - icon = 'icons/obj/1x2.dmi' - icon_state = "hypereutactic" - lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' - righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' - item_state = "hypereutactic" - inhand_x_dimension = 64 - inhand_y_dimension = 64 - name = "hypereutactic blade" - desc = "A supermassive weapon envisioned to cleave the very fabric of space and time itself in twain, the hypereutactic blade dynamically flash-forges a hypereutactic crystaline nanostructure capable of passing through most known forms of matter like a hot knife through butter." - force = 7 - force_unwielded = 7 - force_wielded = 40 - wieldsound = 'sound/weapons/nebon.ogg' - unwieldsound = 'sound/weapons/neboff.ogg' - hitsound_on = 'sound/weapons/nebhit.ogg' - slowdown_wielded = 1 - armour_penetration = 60 - light_color = "#37FFF7" - rainbow_colors = list("#FF0000", "#FFFF00", "#00FF00", "#00FFFF", "#0000FF","#FF00FF", "#3399ff", "#ff9900", "#fb008b", "#9800ff", "#00ffa3", "#ccff00") - attack_verb = list("attacked", "slashed", "stabbed", "sliced", "destroyed", "ripped", "devastated", "shredded") - spinnable = FALSE - total_mass_on = 4 - -/obj/item/twohanded/dualsaber/hypereutactic/ComponentInitialize() - . = ..() - AddElement(/datum/element/update_icon_updates_onmob) - -/obj/item/twohanded/dualsaber/hypereutactic/update_icon_state() - return - -/obj/item/twohanded/dualsaber/hypereutactic/update_overlays() - . = ..() - var/mutable_appearance/blade_overlay = mutable_appearance(icon, "hypereutactic_blade") - var/mutable_appearance/gem_overlay = mutable_appearance(icon, "hypereutactic_gem") - - if(light_color) - blade_overlay.color = light_color - gem_overlay.color = light_color - - . += gem_overlay - - if(wielded) - . += blade_overlay - - clean_blood() - -/obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user) - . = ..() - if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked) - return - if(user.incapacitated() || !istype(user)) - to_chat(user, "You can't do that right now!") - return - if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes") - var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null - if(!energy_color_input || !user.canUseTopic(src, BE_CLOSE, FALSE) || hacked) - return - light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1) - update_icon() - update_light() - return TRUE - -/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file, used_state, style_flags = NONE) - . = ..() - if(isinhands) - var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem") - gem_inhand.color = light_color - . += gem_inhand - if(wielded) - var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade") - blade_inhand.color = light_color - . += blade_inhand - -/obj/item/twohanded/dualsaber/hypereutactic/examine(mob/user) - . = ..() - if(!hacked) - . += "Alt-click to recolor it." - -/obj/item/twohanded/dualsaber/hypereutactic/rainbow_process() - . = ..() - update_icon() - update_light() - -/obj/item/twohanded/dualsaber/hypereutactic/chaplain - name = "divine lightblade" - desc = "A giant blade of bright and holy light, said to cut down the wicked with ease." - force = 5 - force_unwielded = 5 - force_wielded = 20 - block_chance = 50 - armour_penetration = 0 - var/chaplain_spawnable = TRUE - can_reflect = FALSE - obj_flags = UNIQUE_RENAME - -/obj/item/twohanded/dualsaber/hypereutactic/chaplain/ComponentInitialize() - . = ..() - AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE) - -//spears -/obj/item/twohanded/spear - icon_state = "spearglass0" - lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' - name = "spear" - desc = "A haphazardly-constructed yet still deadly weapon of ancient design." - force = 10 - w_class = WEIGHT_CLASS_BULKY - slot_flags = ITEM_SLOT_BACK - force_unwielded = 10 - force_wielded = 18 - throwforce = 20 - throw_speed = 4 - embedding = list("impact_pain_mult" = 3) - armour_penetration = 10 - custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075) - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - sharpness = IS_SHARP - max_integrity = 200 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) - var/obj/item/grenade/explosive = null - var/war_cry = "AAAAARGH!!!" - var/icon_prefix = "spearglass" - -/obj/item/twohanded/spear/Initialize() - . = ..() - AddComponent(/datum/component/butchering, 100, 70) //decent in a pinch, but pretty bad. - AddComponent(/datum/component/jousting) - AddElement(/datum/element/sword_point) - -/obj/item/twohanded/spear/attack_self(mob/user) - if(explosive) - explosive.attack_self(user) - return - . = ..() - -//Citadel additions : attack_self and rightclick_attack_self - -/obj/item/twohanded/rightclick_attack_self(mob/user) - if(wielded) //Trying to unwield it - unwield(user) - else //Trying to wield it - wield(user) - return TRUE - -/obj/item/twohanded/spear/suicide_act(mob/living/carbon/user) - user.visible_message("[user] begins to sword-swallow \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") - if(explosive) //Citadel Edit removes qdel and explosive.forcemove(AM) - user.say("[war_cry]", forced="spear warcry") - explosive.prime() - user.gib() - return BRUTELOSS - return BRUTELOSS - -/obj/item/twohanded/spear/examine(mob/user) - . = ..() - if(explosive) - . += "Use in your hands to activate the attached explosive.
    Alt-click to set your war cry.
    Right-click in combat mode to wield" - -/obj/item/twohanded/spear/update_icon_state() - if(explosive) - icon_state = "spearbomb[wielded]" - else - icon_state = "[icon_prefix][wielded]" - -/obj/item/twohanded/spear/afterattack(atom/movable/AM, mob/user, proximity) - . = ..() - if(!proximity) - return - if(isopenturf(AM)) //So you can actually melee with it - return - if(explosive && wielded) //Citadel edit removes qdel and explosive.forcemove(AM) - user.say("[war_cry]", forced="spear warcry") - explosive.prime() - -/obj/item/twohanded/spear/grenade_prime_react(obj/item/grenade/nade) //Citadel edit, removes throw_impact because memes - nade.forceMove(get_turf(src)) - qdel(src) - -/obj/item/twohanded/spear/AltClick(mob/user) - . = ..() - if(user.canUseTopic(src, BE_CLOSE)) - ..() - if(!explosive) - return - if(istype(user) && loc == user) - var/input = stripped_input(user,"What do you want your war cry to be? You will shout it when you hit someone in melee.", ,"", 50) - if(input) - src.war_cry = input - return TRUE - -/obj/item/twohanded/spear/CheckParts(list/parts_list) - var/obj/item/shard/tip = locate() in parts_list - if (istype(tip, /obj/item/shard/plasma)) - force_wielded = 19 - force_unwielded = 11 - throwforce = 21 - embedding = list(embed_chance = 75, pain_mult = 1.5) //plasmaglass spears are sharper - icon_prefix = "spearplasma" - qdel(tip) - var/obj/item/twohanded/spear/S = locate() in parts_list - if(S) - if(S.explosive) - S.explosive.forceMove(get_turf(src)) - S.explosive = null - parts_list -= S - qdel(S) - ..() - var/obj/item/grenade/G = locate() in contents - if(G) - explosive = G - name = "explosive lance" - embedding = list(embed_chance = 0, pain_mult = 1)//elances should not be embeddable - desc = "A makeshift spear with [G] attached to it." - update_icon() - -// CHAINSAW -/obj/item/twohanded/required/chainsaw - name = "chainsaw" - desc = "A versatile power tool. Useful for limbing trees and delimbing humans." - icon_state = "chainsaw_off" - lefthand_file = 'icons/mob/inhands/weapons/chainsaw_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' - flags_1 = CONDUCT_1 - force = 13 - var/force_on = 24 - w_class = WEIGHT_CLASS_HUGE - throwforce = 13 - throw_speed = 2 - throw_range = 4 - custom_materials = list(/datum/material/iron=13000) - attack_verb = list("sawed", "torn", "cut", "chopped", "diced") - hitsound = "swing_hit" - sharpness = IS_SHARP - actions_types = list(/datum/action/item_action/startchainsaw) - var/on = FALSE - tool_behaviour = TOOL_SAW - toolspeed = 0.5 - -/obj/item/twohanded/required/chainsaw/ComponentInitialize() - . = ..() - AddComponent(/datum/component/butchering, 30, 100, 0, 'sound/weapons/chainsawhit.ogg', TRUE) - AddElement(/datum/element/update_icon_updates_onmob) - -/obj/item/twohanded/required/chainsaw/suicide_act(mob/living/carbon/user) - if(on) - user.visible_message("[user] begins to tear [user.p_their()] head off with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(src, 'sound/weapons/chainsawhit.ogg', 100, 1) - var/obj/item/bodypart/head/myhead = user.get_bodypart(BODY_ZONE_HEAD) - if(myhead) - myhead.dismember() - else - user.visible_message("[user] smashes [src] into [user.p_their()] neck, destroying [user.p_their()] esophagus! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(src, 'sound/weapons/genhit1.ogg', 100, 1) - return(BRUTELOSS) - -/obj/item/twohanded/required/chainsaw/attack_self(mob/user) - on = !on - to_chat(user, "As you pull the starting cord dangling from [src], [on ? "it begins to whirr." : "the chain stops moving."]") - force = on ? force_on : initial(force) - throwforce = on ? force_on : force - update_icon() - var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering) - butchering.butchering_enabled = on - - if(on) - hitsound = 'sound/weapons/chainsawhit.ogg' - else - hitsound = "swing_hit" - -/obj/item/twohanded/required/chainsaw/update_icon_state() - icon_state = "chainsaw_[on ? "on" : "off"]" - -/obj/item/twohanded/required/chainsaw/get_dismemberment_chance() - if(wielded) - . = ..() - -/obj/item/twohanded/required/chainsaw/doomslayer - name = "THE GREAT COMMUNICATOR" - desc = "VRRRRRRR!!!" - armour_penetration = 100 - force_on = 30 - -/obj/item/twohanded/required/chainsaw/doomslayer/check_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) - block_return[BLOCK_RETURN_REFLECT_PROJECTILE_CHANCE] = 100 - return ..() - -/obj/item/twohanded/required/chainsaw/doomslayer/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) - if(attack_type & ATTACK_TYPE_PROJECTILE) - owner.visible_message("Ranged attacks just make [owner] angrier!") - playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) - return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL - return ..() - -//GREY TIDE -/obj/item/twohanded/spear/grey_tide - icon_state = "spearglass0" - name = "\improper Grey Tide" - desc = "Recovered from the aftermath of a revolt aboard Defense Outpost Theta Aegis, in which a seemingly endless tide of Assistants caused heavy casualities among Nanotrasen military forces." - force_unwielded = 15 - force_wielded = 25 - throwforce = 20 - throw_speed = 4 - attack_verb = list("gored") - var/clonechance = 50 - var/clonedamage = 12 - var/clonespeed = 0 - var/clone_replication_chance = 30 - var/clone_lifespan = 100 - -/obj/item/twohanded/spear/grey_tide/afterattack(atom/movable/AM, mob/living/user, proximity) - . = ..() - if(!proximity) - return - user.faction |= "greytide([REF(user)])" - if(isliving(AM)) - var/mob/living/L = AM - if(istype (L, /mob/living/simple_animal/hostile/illusion)) - return - if(!L.stat && prob(clonechance)) - var/mob/living/simple_animal/hostile/illusion/M = new(user.loc) - M.faction = user.faction.Copy() - M.set_varspeed(clonespeed) - M.Copy_Parent(user, clone_lifespan, user.health/2.5, clonedamage, clone_replication_chance) - M.GiveTarget(L) - -/obj/item/twohanded/pitchfork - icon_state = "pitchfork0" - lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' - name = "pitchfork" - desc = "A simple tool used for moving hay." - force = 7 - throwforce = 15 - w_class = WEIGHT_CLASS_BULKY - force_unwielded = 7 - force_wielded = 15 - attack_verb = list("attacked", "impaled", "pierced") - hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP - max_integrity = 200 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) - resistance_flags = FIRE_PROOF - -/obj/item/twohanded/pitchfork/Initialize(mapload) - AddElement(/datum/element/sword_point) - -/obj/item/twohanded/pitchfork/demonic - name = "demonic pitchfork" - desc = "A red pitchfork, it looks like the work of the devil." - force = 19 - throwforce = 24 - force_unwielded = 19 - force_wielded = 25 - -/obj/item/twohanded/pitchfork/demonic/Initialize() - . = ..() - set_light(3,6,LIGHT_COLOR_RED) - -/obj/item/twohanded/pitchfork/demonic/greater - force = 24 - throwforce = 50 - force_unwielded = 24 - force_wielded = 34 - -/obj/item/twohanded/pitchfork/demonic/ascended - force = 100 - throwforce = 100 - force_unwielded = 100 - force_wielded = 500000 // Kills you DEAD. - -/obj/item/twohanded/pitchfork/update_icon_state() - icon_state = "pitchfork[wielded]" - -/obj/item/twohanded/pitchfork/suicide_act(mob/user) - user.visible_message("[user] impales [user.p_them()]self in [user.p_their()] abdomen with [src]! It looks like [user.p_theyre()] trying to commit suicide!") - return (BRUTELOSS) - -/obj/item/twohanded/pitchfork/demonic/pickup(mob/living/user) - . = ..() - if(isliving(user) && user.mind && user.owns_soul() && !is_devil(user)) - var/mob/living/U = user - U.visible_message("As [U] picks [src] up, [U]'s arms briefly catch fire.", \ - "\"As you pick up [src] your arms ignite, reminding you of all your past sins.\"") - if(ishuman(U)) - var/mob/living/carbon/human/H = U - H.apply_damage(rand(force/2, force), BURN, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) - else - U.adjustFireLoss(rand(force/2,force)) - -/obj/item/twohanded/pitchfork/demonic/attack(mob/target, mob/living/carbon/human/user) - if(user.mind && user.owns_soul() && !is_devil(user)) - to_chat(user, "[src] burns in your hands.") - user.apply_damage(rand(force/2, force), BURN, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) - ..() - -/obj/item/twohanded/pitchfork/demonic/ascended/afterattack(atom/target, mob/user, proximity) - . = ..() - if(!proximity || !wielded) - return - if(iswallturf(target)) - var/turf/closed/wall/W = target - user.visible_message("[user] blasts \the [target] with \the [src]!") - playsound(target, 'sound/magic/disintegrate.ogg', 100, 1) - W.break_wall() - W.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) - return - -//HF blade - -/obj/item/twohanded/vibro_weapon - icon_state = "hfrequency0" - lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - name = "vibro sword" - desc = "A potent weapon capable of cutting through nearly anything. Wielding it in two hands will allow you to deflect gunfire." - force_unwielded = 20 - force_wielded = 40 - armour_penetration = 100 - block_chance = 40 - throwforce = 20 - throw_speed = 4 - sharpness = IS_SHARP - attack_verb = list("cut", "sliced", "diced") - w_class = WEIGHT_CLASS_BULKY - slot_flags = ITEM_SLOT_BACK - hitsound = 'sound/weapons/bladeslice.ogg' - -/obj/item/twohanded/vibro_weapon/Initialize() - . = ..() - AddComponent(/datum/component/butchering, 20, 105) - AddElement(/datum/element/sword_point) - -/obj/item/twohanded/vibro_weapon/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) - if(wielded) - final_block_chance *= 2 - if(wielded || !(attack_type & ATTACK_TYPE_PROJECTILE)) - if(prob(final_block_chance)) - if(attack_type & ATTACK_TYPE_PROJECTILE) - owner.visible_message("[owner] deflects [attack_text] with [src]!") - playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) - block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT - return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL - else - owner.visible_message("[owner] parries [attack_text] with [src]!") - return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL - return NONE - -/obj/item/twohanded/vibro_weapon/update_icon_state() - icon_state = "hfrequency[wielded]" - -/* - * Bone Axe - */ -/obj/item/twohanded/fireaxe/boneaxe // Blatant imitation of the fireaxe, but made out of bone. - icon_state = "bone_axe0" - name = "bone axe" - desc = "A large, vicious axe crafted out of several sharpened bone plates and crudely tied together. Made of monsters, by killing monsters, for killing monsters." - force_wielded = 23 - -/obj/item/twohanded/fireaxe/boneaxe/update_icon_state() - icon_state = "bone_axe[wielded]" - -/* - * Bone Spear - */ -/obj/item/twohanded/bonespear //Blatant imitation of spear, but made out of bone. Not valid for explosive modification. - icon_state = "bone_spear0" - lefthand_file = 'icons/mob/inhands/weapons/polearms_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' - name = "bone spear" - desc = "A haphazardly-constructed yet still deadly weapon. The pinnacle of modern technology." - force = 11 - w_class = WEIGHT_CLASS_BULKY - slot_flags = ITEM_SLOT_BACK - force_unwielded = 11 - force_wielded = 20 //I have no idea how to balance - reach = 2 - throwforce = 22 - throw_speed = 4 - embedding = list("embedded_impact_pain_multiplier" = 3) - armour_penetration = 15 //Enhanced armor piercing - hitsound = 'sound/weapons/bladeslice.ogg' - attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - sharpness = IS_SHARP - -/obj/item/twohanded/bonespear/update_icon_state() - icon_state = "bone_spear[wielded]" - -/obj/item/twohanded/binoculars - name = "binoculars" - desc = "Used for long-distance surveillance." - item_state = "binoculars" - icon_state = "binoculars" - lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' - righthand_file = 'icons/mob/inhands/items_righthand.dmi' - slot_flags = ITEM_SLOT_BELT - w_class = WEIGHT_CLASS_SMALL - var/mob/listeningTo - var/zoom_out_amt = 6 - var/zoom_amt = 10 - -/obj/item/twohanded/binoculars/Destroy() - listeningTo = null - return ..() - -/obj/item/twohanded/binoculars/wield(mob/user) - . = ..() - if(!wielded) - return - RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield) - listeningTo = user - user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.") - item_state = "binoculars_wielded" - user.regenerate_icons() - if(!user?.client) - return - var/client/C = user.client - var/_x = 0 - var/_y = 0 - switch(user.dir) - if(NORTH) - _y = zoom_amt - if(EAST) - _x = zoom_amt - if(SOUTH) - _y = -zoom_amt - if(WEST) - _x = -zoom_amt - C.change_view(world.view + zoom_out_amt) - C.pixel_x = world.icon_size*_x - C.pixel_y = world.icon_size*_y - -/obj/item/twohanded/binoculars/unwield(mob/user) - . = ..() - UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) - listeningTo = null - user.visible_message("[user] lowers [src].","You lower [src].") - item_state = "binoculars" - user.regenerate_icons() - if(user && user.client) - user.regenerate_icons() - var/client/C = user.client - C.change_view(CONFIG_GET(string/default_view)) - user.client.pixel_x = 0 - user.client.pixel_y = 0 - -/obj/item/twohanded/electrostaff - icon = 'icons/obj/items_and_weapons.dmi' - icon_state = "electrostaff" - item_state = "electrostaff" - lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' - righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' - name = "riot suppression electrostaff" - desc = "A large quarterstaff, with massive silver electrodes mounted at the end." - w_class = WEIGHT_CLASS_HUGE - slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_OCLOTHING - force_unwielded = 5 - force_wielded = 10 - throwforce = 15 //if you are a madman and finish someone off with this, power to you. - throw_speed = 1 - item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK | ITEM_CAN_PARRY - block_parry_data = /datum/block_parry_data/electrostaff - attack_verb = list("struck", "beaten", "thwacked", "pulped") - total_mass = 5 //yeah this is a heavy thing, beating people with it while it's off is not going to do you any favors. (to curb stun-kill rampaging without it being on) - var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high - var/on = FALSE - var/lethal_cost = 400 //10000/400*20 = 500. decent enough? - var/lethal_damage = 20 - var/lethal_stam_cost = 4 - var/stun_cost = 333 //10000/333*25 = 750. stunbatons are at time of writing 10000/1000*49 = 490. - var/stun_status_effect = STATUS_EFFECT_ELECTROSTAFF //a small slowdown effect - var/stun_stamdmg = 40 - var/stun_status_duration = 25 - var/stun_stam_cost = 3.5 - -// haha security desword time /s -/datum/block_parry_data/electrostaff - block_damage_absorption = 0 - block_damage_multiplier = 1 - can_block_attack_types = ~ATTACK_TYPE_PROJECTILE // only able to parry non projectiles - block_damage_multiplier_override = list( - TEXT_ATTACK_TYPE_MELEE = 0.5, // only useful on melee and unarmed - TEXT_ATTACK_TYPE_UNARMED = 0.3 - ) - block_start_delay = 0.5 // near instantaneous block - block_stamina_cost_per_second = 3 - block_stamina_efficiency = 2 // haha this is a horrible idea - // more slowdown that deswords because security - block_slowdown = 2 - // no attacking while blocking - block_lock_attacking = TRUE - - parry_time_windup = 1 - parry_time_active = 5 - parry_time_spindown = 0 - parry_time_spindown_visual_override = 1 - parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING // no attacking while parrying - parry_time_perfect = 0 - parry_time_perfect_leeway = 0.5 - parry_efficiency_perfect = 100 - parry_imperfect_falloff_percent = 1 - parry_imperfect_falloff_percent_override = list( - TEXT_ATTACK_TYPE_PROJECTILE = 45 // really crappy vs projectiles - ) - parry_time_perfect_leeway_override = list( - TEXT_ATTACK_TYPE_PROJECTILE = 1 // extremely harsh window for projectiles - ) - // not extremely punishing to fail, but no spamming the parry. - parry_cooldown = 2.5 SECONDS - parry_failed_stagger_duration = 1.5 SECONDS - parry_failed_clickcd_duration = 1 SECONDS - -/obj/item/twohanded/electrostaff/Initialize(mapload) - . = ..() - if(ispath(cell)) - cell = new cell - -/obj/item/twohanded/electrostaff/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/item/twohanded/electrostaff/get_cell() - . = cell - if(iscyborg(loc)) - var/mob/living/silicon/robot/R = loc - . = R.get_cell() - -/obj/item/twohanded/electrostaff/proc/min_hitcost() - return min(stun_cost, lethal_cost) - -/obj/item/twohanded/electrostaff/proc/turn_on(mob/user, silent = FALSE) - if(on) - return - if(!cell) - if(user) - to_chat(user, "[src] has no cell.") - return - if(cell.charge < min_hitcost()) - if(user) - to_chat(user, "[src] is out of charge.") - return - on = TRUE - START_PROCESSING(SSobj, src) - if(user) - to_chat(user, "You turn [src] on.") - update_icon() - if(!silent) - playsound(src, "sparks", 75, 1, -1) - -/obj/item/twohanded/electrostaff/proc/turn_off(mob/user, silent = FALSE) - if(!on) - return - if(user) - to_chat(user, "You turn [src] off.") - on = FALSE - STOP_PROCESSING(SSobj, src) - update_icon() - if(!silent) - playsound(src, "sparks", 75, 1, -1) - -/obj/item/twohanded/electrostaff/proc/toggle(mob/user, silent = FALSE) - if(on) - turn_off(user, silent) - else - turn_on(user, silent) - -/obj/item/twohanded/electrostaff/wield(mob/user) - . = ..() - if(wielded) - turn_on(user) - add_fingerprint(user) - -/obj/item/twohanded/electrostaff/unwield(mob/user) - . = ..() - if(!wielded) - turn_off(user) - add_fingerprint(user) - -/obj/item/twohanded/electrostaff/update_icon_state() - . = ..() - if(!wielded) - icon_state = "electrostaff" - item_state = "electrostaff" - else - icon_state = item_state = (on? "electrostaff_1" : "electrostaff_0") - set_light(7, on? 1 : 0, LIGHT_COLOR_CYAN) - -/obj/item/twohanded/electrostaff/examine(mob/living/user) - . = ..() - if(cell) - . += "The cell charge is [round(cell.percent())]%." - else - . += "There is no cell installed!" - -/obj/item/twohanded/electrostaff/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/stock_parts/cell)) - var/obj/item/stock_parts/cell/C = W - if(cell) - to_chat(user, "[src] already has a cell!") - else - if(C.maxcharge < min_hit_cost()) - to_chat(user, "[src] requires a higher capacity cell.") - return - if(!user.transferItemToLoc(W, src)) - return - cell = C - to_chat(user, "You install a cell in [src].") - - else if(W.tool_behaviour == TOOL_SCREWDRIVER) - if(cell) - cell.update_icon() - cell.forceMove(get_turf(src)) - cell = null - to_chat(user, "You remove the cell from [src].") - turn_off(user, TRUE) - else - return ..() - -/obj/item/twohanded/electrostaff/process() - deductcharge(50) //Wasteful! - -/obj/item/twohanded/electrostaff/proc/min_hit_cost() - return min(lethal_cost, stun_cost) - -/obj/item/twohanded/electrostaff/proc/deductcharge(amount) - var/obj/item/stock_parts/cell/C = get_cell() - if(!C) - turn_off() - return FALSE - C.use(min(amount, C.charge)) - if(QDELETED(src)) - return FALSE - if(C.charge < min_hit_cost()) - turn_off() - -/obj/item/twohanded/electrostaff/attack(mob/living/target, mob/living/user) - if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit - to_chat(user, "You're too exhausted to use [src] properly.")//CIT CHANGE - ditto - return //CIT CHANGE - ditto - if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) - clowning_around(user) //ouch! - return - if(iscyborg(target)) - return ..() - var/list/return_list = list() - if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, return_list) & BLOCK_SUCCESS) //No message; run_block() handles that - playsound(target, 'sound/weapons/genhit.ogg', 50, 1) - return FALSE - if(user.a_intent != INTENT_HARM) - if(stun_act(target, user, null, return_list)) - user.do_attack_animation(target) - user.adjustStaminaLossBuffered(stun_stam_cost) - return - else if(!harm_act(target, user, null, return_list)) - return ..() //if you can't fry them just beat them with it - else //we did harm act them - user.do_attack_animation(target) - user.adjustStaminaLossBuffered(lethal_stam_cost) - -/obj/item/twohanded/electrostaff/proc/stun_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list()) - var/stunforce = block_calculate_resultant_damage(stun_stamdmg, block_return) - if(!no_charge_and_force) - if(!on) - target.visible_message("[user] has bapped [target] with [src]. Luckily it was off.", \ - "[user] has bapped you with [src]. Luckily it was off") - turn_off() //if it wasn't already off - return FALSE - var/obj/item/stock_parts/cell/C = get_cell() - var/chargeleft = C.charge - deductcharge(stun_cost) - if(QDELETED(src) || QDELETED(C)) //boom - return FALSE - if(chargeleft < stun_cost) - stunforce *= round(chargeleft/stun_cost, 0.1) - target.adjustStaminaLoss(stunforce) - target.apply_effect(EFFECT_STUTTER, stunforce) - SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) - if(user) - target.lastattacker = user.real_name - target.lastattackerckey = user.ckey - target.visible_message("[user] has shocked [target] with [src]!", \ - "[user] has shocked you with [src]!") - log_combat(user, target, "stunned with an electrostaff") - playsound(src, 'sound/weapons/staff.ogg', 50, 1, -1) - target.apply_status_effect(stun_status_effect, stun_status_duration) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.forcesay(GLOB.hit_appends) - return TRUE - -/obj/item/twohanded/electrostaff/proc/harm_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list()) - var/lethal_force = block_calculate_resultant_damage(lethal_damage, block_return) - if(!no_charge_and_force) - if(!on) - return FALSE //standard item attack - var/obj/item/stock_parts/cell/C = get_cell() - var/chargeleft = C.charge - deductcharge(lethal_cost) - if(QDELETED(src) || QDELETED(C)) //boom - return FALSE - if(chargeleft < stun_cost) - lethal_force *= round(chargeleft/lethal_cost, 0.1) - target.adjustFireLoss(lethal_force) //good against ointment spam - SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK) - if(user) - target.lastattacker = user.real_name - target.lastattackerckey = user.ckey - target.visible_message("[user] has seared [target] with [src]!", \ - "[user] has seared you with [src]!") - log_combat(user, target, "burned with an electrostaff") - playsound(src, 'sound/weapons/sear.ogg', 50, 1, -1) - return TRUE - -/obj/item/twohanded/electrostaff/proc/clowning_around(mob/living/user) - user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \ - "You accidentally hit yourself with [src]!") - SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK) - harm_act(user, user, TRUE) - stun_act(user, user, TRUE) - deductcharge(lethal_cost) - -/obj/item/twohanded/electrostaff/emp_act(severity) - . = ..() - if (!(. & EMP_PROTECT_SELF)) - turn_off() - if(!iscyborg(loc)) - deductcharge(1000 / severity, TRUE, FALSE) - -/obj/item/twohanded/broom - name = "broom" - desc = "This is my BROOMSTICK! It can be used manually or braced with two hands to sweep items as you move. It has a telescopic handle for compact storage." //LIES - icon = 'icons/obj/janitor.dmi' - icon_state = "broom0" - lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi' - force = 8 - throwforce = 10 - throw_speed = 3 - throw_range = 7 - w_class = WEIGHT_CLASS_NORMAL - force_unwielded = 8 - force_wielded = 12 - attack_verb = list("swept", "brushed off", "bludgeoned", "whacked") - resistance_flags = FLAMMABLE - -/obj/item/twohanded/broom/update_icon_state() - icon_state = "broom[wielded]" - -/obj/item/twohanded/broom/wield(mob/user) - . = ..() - if(!wielded) - return - to_chat(user, "You brace the [src] against the ground in a firm sweeping stance.") - RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/sweep) - -/obj/item/twohanded/broom/unwield(mob/user) - . = ..() - UnregisterSignal(user, COMSIG_MOVABLE_MOVED) - -/obj/item/twohanded/broom/afterattack(atom/A, mob/user, proximity) - . = ..() - if(!proximity) - return - sweep(user, A, FALSE) - -/obj/item/twohanded/broom/proc/sweep(mob/user, atom/A, moving = TRUE) - var/turf/target - if (!moving) - if (isturf(A)) - target = A - else - target = A.loc - if(!isturf(target)) //read: Mob inventories. - return - else - target = user.loc - if (locate(/obj/structure/table) in target.contents) - return - var/i = 0 - for(var/obj/item/garbage in target.contents) - if(!garbage.anchored) - garbage.Move(get_step(target, user.dir), user.dir) - i++ - if(i >= 20) - break - if(i >= 1) - playsound(loc, 'sound/weapons/thudswoosh.ogg', 5, TRUE, -1) - -/obj/item/twohanded/broom/proc/janicart_insert(mob/user, obj/structure/janitorialcart/J) //bless you whoever fixes this copypasta - J.put_in_cart(src, user) - J.mybroom=src - J.update_icon() diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 67dcd71e65..653e95c21e 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -65,7 +65,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 w_class = WEIGHT_CLASS_NORMAL attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF @@ -231,7 +231,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF @@ -249,6 +249,196 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1) return(BRUTELOSS) +/obj/item/katana/timestop + name = "temporal katana" + desc = "Delicately balanced, this finely-crafted blade hums with barely-restrained potential." + icon_state = "temporalkatana" + item_state = "temporalkatana" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + block_chance = 0 // oops + force = 27.5 // oops + item_flags = ITEM_CAN_PARRY + block_parry_data = /datum/block_parry_data/bokken/quick_parry/proj + +/obj/item/katana/timestop/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) + if(ishuman(owner)) + var/mob/living/carbon/human/flynn = owner + flynn.emote("smirk") + new /obj/effect/timestop/magic(get_turf(owner), 1, 50, list(owner)) // null roddies counter + +/obj/item/katana/timestop/suicide_act(mob/living/user) // stolen from hierophant staff + new /obj/effect/timestop/magic(get_turf(user), 1, 50, list(user)) // free usage for dying + user.visible_message("[user] poses menacingly with the [src]! It looks like [user.p_theyre()] trying to teleport behind someone!") + user.say("Heh.. Nothing personnel, kid..", forced = "temporal katana suicide") + sleep(20) + if(!user) + return + user.visible_message("[user] vanishes into a cloud of falling dust and burning embers, likely off to style on some poor sod in the distance!") + playsound(user,'sound/magic/blink.ogg', 75, TRUE) + for(var/obj/item/I in user) + if(I != src) + user.dropItemToGround(I) + user.dropItemToGround(src) //Drop us last, so it goes on top of their stuff + qdel(user) + +/obj/item/melee/bokken // parrying stick + name = "bokken" + desc = "A space-Japanese training sword made of wood and shaped like a katana." + icon_state = "bokken" + item_state = "bokken" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK + w_class = WEIGHT_CLASS_BULKY + force = 7 //how much harm mode damage we do + var/stamina_damage_increment = 4 //how much extra damage do we do when in non-harm mode + throwforce = 10 + damtype = STAMINA + attack_verb = list("whacked", "smacked", "struck") + total_mass = TOTAL_MASS_MEDIEVAL_WEAPON + hitsound = 'sound/weapons/grenadelaunch.ogg' // no good wood thunk sounds + var/harm = FALSE // TRUE = brute, FALSE = stam + var/reinforced = FALSE + var/burnt = FALSE + var/burned_in // text you burned in (with a welder) + var/quick_parry = FALSE // false = default parry, true = really small parry window + item_flags = ITEM_CAN_PARRY + block_parry_data = /datum/block_parry_data/bokken + bare_wound_bonus = 0 + wound_bonus = 0 + +/datum/block_parry_data/bokken // fucked up parry data, emphasizing quicker, shorter parries + parry_stamina_cost = 8 // be wise about when you parry, though, else you won't be able to fight enough to make it count + parry_time_windup = 0 + parry_time_active = 10 // small parry window + parry_time_spindown = 0 + // parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // bokken users can no longer strike while parrying + parry_time_perfect = 1.5 + parry_time_perfect_leeway = 1 + parry_imperfect_falloff_percent = 7.5 + parry_efficiency_to_counterattack = 120 + parry_efficiency_considered_successful = 65 // VERY generous + parry_efficiency_perfect = 120 + parry_efficiency_perfect_override = list( + TEXT_ATTACK_TYPE_PROJECTILE = 30, + ) + parry_failed_stagger_duration = 3 SECONDS + parry_data = list( + PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25 + ) + +/datum/block_parry_data/bokken/quick_parry // emphasizing REALLY SHORT PARRIES + parry_stamina_cost = 6 // still more costly than most parries, but less than a full bokken parry + parry_time_active = 5 // REALLY small parry window + parry_time_perfect = 2.5 // however... + parry_time_perfect_leeway = 2 // the entire time, the parry is perfect + parry_failed_stagger_duration = 1 SECONDS + parry_failed_clickcd_duration = 1 SECONDS // more forgiving punishments for missed parries + // still, don't fucking miss your parries or you're down stamina and staggered to shit + +/datum/block_parry_data/bokken/quick_parry/proj + parry_efficiency_perfect_override = list() + +/obj/item/melee/bokken/Initialize() + . = ..() + AddElement(/datum/element/sword_point) + if(!harm) //if initialised in non-harm mode, setup force accordingly + force = force + stamina_damage_increment + +/obj/item/melee/bokken/attack_self(mob/user) + harm = !harm + if(harm) + force -= stamina_damage_increment + damtype = BRUTE + attack_verb = list("bashed", "smashed", "attacked") + bare_wound_bonus = 15 // having your leg smacked by a wooden stick is probably not great for it if it's naked + wound_bonus = 0 + else + force += stamina_damage_increment + damtype = STAMINA + attack_verb = list("whacked", "smacked", "struck") + bare_wound_bonus = 0 + wound_bonus = 0 + to_chat(user, "[src] is now [harm ? "harmful" : "not quite as harmful"].") + +/obj/item/melee/bokken/AltClick(mob/user) + . = ..() + quick_parry = !quick_parry + if(quick_parry) + block_parry_data = /datum/block_parry_data/bokken/quick_parry + else + block_parry_data = /datum/block_parry_data/bokken + to_chat(user, "[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].") + +/obj/item/melee/bokken/attackby(obj/item/I, mob/living/user, params) + if(istype(I, /obj/item/pen)) + var/new_name = stripped_input(user, "What do you wish to name [src]?", "New Name", "bokken", 30) + if(new_name) + name = new_name + if(I.tool_behaviour == TOOL_WELDER) + var/new_burn = stripped_input(user, "What do you wish to burn into [src]?", "Burnt Inscription","", 140) + if(new_burn) + burned_in = new_burn + if(!burnt) + icon_state += "_burnt" + item_state += "_burnt" + burnt = TRUE + update_icon() + update_icon_state() + if(istype(I, /obj/item/stack/rods)) + var/obj/item/stack/rods/R = I + if(!reinforced) + if(R.use(1)) + force++ + reinforced = TRUE + to_chat(user, "You slide a metal rod into [src]\'s hilt. It feels a little heftier in your hands.") + else + to_chat(user, "[src] already has a weight slid into the hilt.") + +/obj/item/melee/bokken/examine(mob/user) + . = ..() + if(quick_parry) + . += " [src] is gripped in a way to emphasize quicker parries." + if(reinforced) + . += " There's a metal rod shoved into the base." + if(burnt) + . += " Burned into the \"blade\" is [burned_in]." + +/obj/item/melee/bokken/debug + name = "funny debug parrying stick" + desc = "if you see this you've fucked up somewhere my good man" + block_parry_data = /datum/block_parry_data/bokken/debug + +/obj/item/melee/bokken/debug/AltClick(mob/user) + quick_parry = !quick_parry + if(quick_parry) + block_parry_data = /datum/block_parry_data/bokken/quick_parry/debug + else + block_parry_data = /datum/block_parry_data/bokken/debug + to_chat(user, "[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].") + +/datum/block_parry_data/bokken/debug + parry_efficiency_perfect_override = list() + parry_data = list( + PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25 + PARRY_DISARM_ATTACKER = TRUE, + PARRY_KNOCKDOWN_ATTACKER = 10, + PARRY_STAGGER_ATTACKER = 10, + PARRY_DAZE_ATTACKER = 10, + ) + +/datum/block_parry_data/bokken/quick_parry/debug + parry_efficiency_perfect_override = list() + parry_data = list( + PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5, // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25 + PARRY_DISARM_ATTACKER = TRUE, + PARRY_KNOCKDOWN_ATTACKER = 10, + PARRY_STAGGER_ATTACKER = 10, + PARRY_DAZE_ATTACKER = 10, + ) + + /obj/item/wirerod name = "wired rod" desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit." @@ -260,10 +450,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 w_class = WEIGHT_CLASS_NORMAL custom_materials = list(/datum/material/iron=1150, /datum/material/glass=75) attack_verb = list("hit", "bludgeoned", "whacked", "bonked") + wound_bonus = -10 /obj/item/wirerod/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/shard)) - var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear + var/obj/item/spear/S = new /obj/item/spear remove_item_from_storage(user) if (!user.transferItemToLoc(I, S)) @@ -297,13 +488,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' force = 2 - throwforce = 20 //This is never used on mobs since this has a 100% embed chance. + throwforce = 10 //This is never used on mobs since this has a 100% embed chance. throw_speed = 4 embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) armour_penetration = 40 w_class = WEIGHT_CLASS_SMALL - sharpness = IS_SHARP + sharpness = SHARP_EDGED custom_materials = list(/datum/material/iron=500, /datum/material/glass=500) resistance_flags = FIRE_PROOF @@ -316,7 +507,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/throwing_star/toy name = "toy throwing star" desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security." - sharpness = IS_BLUNT + sharpness = SHARP_NONE force = 0 throwforce = 0 embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0) @@ -353,7 +544,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = extended_icon_state attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED else force = initial(force) w_class = WEIGHT_CLASS_SMALL @@ -361,7 +552,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = retracted_icon_state attack_verb = list("stubbed", "poked") hitsound = 'sound/weapons/genhit.ogg' - sharpness = IS_BLUNT + sharpness = SHARP_NONE /obj/item/switchblade/suicide_act(mob/user) user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -462,7 +653,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throwforce = 0 throw_range = 0 throw_speed = 0 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' total_mass = TOTAL_MASS_HAND_REPLACEMENT @@ -475,7 +666,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/mounted_chainsaw/Destroy() var/obj/item/bodypart/part - new /obj/item/twohanded/required/chainsaw(get_turf(src)) + new /obj/item/chainsaw(get_turf(src)) if(iscarbon(loc)) var/mob/living/carbon/holder = loc var/index = holder.get_held_index_of_item(src) @@ -574,6 +765,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' force = 10 + wound_bonus = -10 throwforce = 12 attack_verb = list("beat", "smacked") custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5) @@ -590,6 +782,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 obj_flags = UNIQUE_RENAME var/chaplain_spawnable = TRUE total_mass = TOTAL_MASS_MEDIEVAL_WEAPON + wound_bonus = -5 /obj/item/melee/baseball_bat/chaplain/Initialize() . = ..() @@ -626,7 +819,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 homerun_ready = 0 return else if(!target.anchored) - target.throw_at(throw_target, rand(1,2), 7, user) + var/whack_speed = (prob(60) ? 1 : 4) + target.throw_at(throw_target, rand(1, 2), whack_speed, user) // sorry friends, 7 speed batting caused wounds to absolutely delete whoever you knocked your target into (and said target) /obj/item/melee/baseball_bat/ablative name = "metal baseball bat" @@ -706,6 +900,92 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 item_flags = DROPDEL | ABSTRACT attack_verb = list("bopped") +/obj/item/circlegame/Initialize() + . = ..() + var/mob/living/owner = loc + if(!istype(owner)) + return + RegisterSignal(owner, COMSIG_PARENT_EXAMINE, .proc/ownerExamined) + +/obj/item/circlegame/Destroy() + var/mob/owner = loc + if(istype(owner)) + UnregisterSignal(owner, COMSIG_PARENT_EXAMINE) + return ..() + +/obj/item/circlegame/dropped(mob/user) + UnregisterSignal(user, COMSIG_PARENT_EXAMINE) //loc will have changed by the time this is called, so Destroy() can't catch it + // this is a dropdel item. + return ..() + +/// Stage 1: The mistake is made +/obj/item/circlegame/proc/ownerExamined(mob/living/owner, mob/living/sucker) + if(!istype(sucker) || !in_range(owner, sucker)) + return + addtimer(CALLBACK(src, .proc/waitASecond, owner, sucker), 4) + +/// Stage 2: Fear sets in +/obj/item/circlegame/proc/waitASecond(mob/living/owner, mob/living/sucker) + if(QDELETED(sucker) || QDELETED(src) || QDELETED(owner)) + return + + if(owner == sucker) // big mood + to_chat(owner, "Wait a second... you just looked at your own [src.name]!") + addtimer(CALLBACK(src, .proc/selfGottem, owner), 10) + else + to_chat(sucker, "Wait a second... was that a-") + addtimer(CALLBACK(src, .proc/GOTTEM, owner, sucker), 6) + +/// Stage 3A: We face our own failures +/obj/item/circlegame/proc/selfGottem(mob/living/owner) + if(QDELETED(src) || QDELETED(owner)) + return + + playsound(get_turf(owner), 'sound/effects/hit_punch.ogg', 50, TRUE, -1) + owner.visible_message("[owner] shamefully bops [owner.p_them()]self with [owner.p_their()] [src.name].", "You shamefully bop yourself with your [src.name].", \ + "You hear a dull thud!") + log_combat(owner, owner, "bopped", src.name, "(self)") + owner.do_attack_animation(owner) + owner.apply_damage(100, STAMINA) + owner.Knockdown(10) + qdel(src) + +/// Stage 3B: We face our reckoning (unless we moved away or they're incapacitated) +/obj/item/circlegame/proc/GOTTEM(mob/living/owner, mob/living/sucker) + if(QDELETED(sucker)) + return + + if(QDELETED(src) || QDELETED(owner)) + to_chat(sucker, "Nevermind... must've been your imagination...") + return + + if(!in_range(owner, sucker) || !(owner.mobility_flags & MOBILITY_USE)) + to_chat(sucker, "Phew... you moved away before [owner] noticed you saw [owner.p_their()] [src.name]...") + return + + to_chat(owner, "[sucker] looks down at your [src.name] before trying to avert [sucker.p_their()] eyes, but it's too late!") + to_chat(sucker, "[owner] sees the fear in your eyes as you try to look away from [owner.p_their()] [src.name]!") + + playsound(get_turf(owner), 'sound/effects/hit_punch.ogg', 50, TRUE, -1) + owner.do_attack_animation(sucker) + + if(HAS_TRAIT(owner, TRAIT_HULK)) + owner.visible_message("[owner] bops [sucker] with [owner.p_their()] [src.name] much harder than intended, sending [sucker.p_them()] flying!", \ + "You bop [sucker] with your [src.name] much harder than intended, sending [sucker.p_them()] flying!", "You hear a sickening sound of flesh hitting flesh!", ignored_mobs=list(sucker)) + to_chat(sucker, "[owner] bops you incredibly hard with [owner.p_their()] [src.name], sending you flying!") + sucker.apply_damage(50, STAMINA) + sucker.Knockdown(50) + log_combat(owner, sucker, "bopped", src.name, "(setup- Hulk)") + var/atom/throw_target = get_edge_target_turf(sucker, owner.dir) + sucker.throw_at(throw_target, 6, 3, owner) + else + owner.visible_message("[owner] bops [sucker] with [owner.p_their()] [src.name]!", "You bop [sucker] with your [src.name]!", \ + "You hear a dull thud!", ignored_mobs=list(sucker)) + sucker.apply_damage(15, STAMINA) + log_combat(owner, sucker, "bopped", src.name, "(setup)") + to_chat(sucker, "[owner] bops you with [owner.p_their()] [src.name]!") + qdel(src) + /obj/item/slapper name = "slapper" desc = "This is how real men fight." @@ -759,3 +1039,59 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 to_chat(user, "[M] is too close to use [src] on.") return M.attack_hand(user) + +//HF blade + +/obj/item/vibro_weapon + icon_state = "hfrequency0" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + name = "vibro sword" + desc = "A potent weapon capable of cutting through nearly anything. Wielding it in two hands will allow you to deflect gunfire." + armour_penetration = 100 + block_chance = 40 + throwforce = 20 + throw_speed = 4 + sharpness = SHARP_EDGED + attack_verb = list("cut", "sliced", "diced") + w_class = WEIGHT_CLASS_BULKY + slot_flags = ITEM_SLOT_BACK + hitsound = 'sound/weapons/bladeslice.ogg' + var/wielded = FALSE // track wielded status on item + +/obj/item/vibro_weapon/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/vibro_weapon/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 20, 105) + AddComponent(/datum/component/two_handed, force_multiplier=2, icon_wielded="hfrequency1") + AddElement(/datum/element/sword_point) + +/// triggered on wield of two handed item +/obj/item/vibro_weapon/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/vibro_weapon/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/vibro_weapon/update_icon_state() + icon_state = "hfrequency0" + +/obj/item/vibro_weapon/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(wielded) + final_block_chance *= 2 + if(wielded || !(attack_type & ATTACK_TYPE_PROJECTILE)) + if(prob(final_block_chance)) + if(attack_type & ATTACK_TYPE_PROJECTILE) + owner.visible_message("[owner] deflects [attack_text] with [src]!") + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) + block_return[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT + return BLOCK_SUCCESS | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT | BLOCK_PHYSICAL_EXTERNAL + else + owner.visible_message("[owner] parries [attack_text] with [src]!") + return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL + return NONE diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 54ac2a5559..f5003e035b 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -103,15 +103,21 @@ take_damage(400, BRUTE, "melee", 0, get_dir(src, B)) /obj/proc/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, armor_penetration = 0) //used by attack_alien, attack_animal, and attack_slime + if(SEND_SIGNAL(src, COMSIG_OBJ_ATTACK_GENERIC, user, damage_amount, damage_type, damage_flag, sound_effect, armor_penetration) & COMPONENT_STOP_GENERIC_ATTACK) + return FALSE + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return user.do_attack_animation(src) - user.changeNext_move(CLICK_CD_MELEE) - return take_damage(damage_amount, damage_type, damage_flag, sound_effect, get_dir(src, user), armor_penetration) + . = take_damage(damage_amount, damage_type, damage_flag, sound_effect, get_dir(src, user), armor_penetration) + user.DelayNextAction() /obj/attack_alien(mob/living/carbon/alien/humanoid/user) if(attack_generic(user, 60, BRUTE, "melee", 0)) playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1) /obj/attack_animal(mob/living/simple_animal/M) + if(!M.CheckActionCooldown(CLICK_CD_MELEE)) + return if(!M.melee_damage_upper && !M.obj_damage) M.emote("custom", message = "[M.friendly_verb_continuous] [src].") return 0 @@ -180,7 +186,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e if(!acid_level) SSacid.processing[src] = src - add_overlay(GLOB.acid_overlay, TRUE) + update_icon() var/acid_cap = acidpwr * 300 //so we cannot use huge amounts of weak acids to do as well as strong acids. if(acid_level < acid_cap) acid_level = min(acid_level + acidpwr * acid_volume, acid_cap) @@ -218,7 +224,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e if(!(resistance_flags & ON_FIRE) && (resistance_flags & FLAMMABLE)) resistance_flags |= ON_FIRE SSfire_burning.processing[src] = src - add_overlay(GLOB.fire_overlay, TRUE) + update_icon() return 1 //called when the obj is destroyed by fire @@ -230,7 +236,7 @@ GLOBAL_DATUM_INIT(acid_overlay, /mutable_appearance, mutable_appearance('icons/e /obj/proc/extinguish() if(resistance_flags & ON_FIRE) resistance_flags &= ~ON_FIRE - cut_overlay(GLOB.fire_overlay, TRUE) + update_icon() SSfire_burning.processing -= src /obj/zap_act(power, zap_flags, shocked_targets) diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index ba3eba9bd3..99b302e9ce 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -10,6 +10,11 @@ var/damtype = BRUTE var/force = 0 + /// How good a given object is at causing wounds on carbons. Higher values equal better shots at creating serious wounds. + var/wound_bonus = 0 + /// If this attacks a human with no wound armor on the affected body part, add this to the wound mod. Some attacks may be significantly worse at wounding if there's even a slight layer of armor to absorb some of it vs bare flesh + var/bare_wound_bonus = 0 + var/datum/armor/armor var/obj_integrity //defaults to max_integrity var/max_integrity = 500 @@ -37,13 +42,9 @@ if("anchored") setAnchored(vval) return TRUE - if("obj_flags") + if(NAMEOF(src, obj_flags)) if ((obj_flags & DANGEROUS_POSSESSION) && !(vval & DANGEROUS_POSSESSION)) return FALSE - if("control_object") - var/obj/O = vval - if(istype(O) && (O.obj_flags & DANGEROUS_POSSESSION)) - return FALSE return ..() /obj/Initialize() @@ -316,6 +317,13 @@ icon_state = unique_reskin[choice] to_chat(M, "[src] is now skinned as '[choice]'.") +/obj/update_overlays() + . = ..() + if(acid_level) + . += GLOB.acid_overlay + if(resistance_flags & ON_FIRE) + . += GLOB.fire_overlay + //Called when the object is constructed by an autolathe //Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes /obj/proc/autolathe_crafted(obj/machinery/autolathe/A) @@ -328,3 +336,6 @@ . = ..() if(. && ricochet_damage_mod) take_damage(P.damage * ricochet_damage_mod, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) // pass along ricochet_damage_mod damage to the structure for the ricochet + +/obj/proc/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) + return diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index d30f617919..52036427c8 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -9,8 +9,10 @@ var/mob/living/structureclimber var/broken = 0 //similar to machinery's stat BROKEN layer = BELOW_OBJ_LAYER - flags_ricochet = RICOCHET_HARD - ricochet_chance_mod = 0.5 + //ricochets on structures commented out for now because there's a lot of structures that /shouldnt/ be ricocheting and those need to be reviewed first + //flags_1 = DEFAULT_RICOCHET_1 + //flags_ricochet = RICOCHET_HARD + //ricochet_chance_mod = 0.5 /obj/structure/Initialize() if (!armor) @@ -28,12 +30,10 @@ queue_smooth_neighbors(src) return ..() -/obj/structure/attack_hand(mob/user) +/obj/structure/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() - if(.) - return if(structureclimber && structureclimber != user) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) user.do_attack_animation(src) structureclimber.DefaultCombatKnockdown(40) structureclimber.visible_message("[structureclimber] has been knocked off [src].", "You're knocked off [src]!", "You see [structureclimber] get knocked off [src].") @@ -112,3 +112,6 @@ if(0 to 25) if(!broken) return "It's falling apart!" + +/obj/structure/rust_heretic_act() + take_damage(500, BRUTE, "melee", 1) diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm index a793459c5d..ce11daec54 100644 --- a/code/game/objects/structures/aliens.dm +++ b/code/game/objects/structures/aliens.dm @@ -249,7 +249,7 @@ /obj/structure/alien/egg/attack_alien(mob/living/carbon/alien/user) return attack_hand(user) -/obj/structure/alien/egg/attack_hand(mob/living/user) +/obj/structure/alien/egg/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -269,8 +269,7 @@ return else to_chat(user, "It feels slimy.") - user.changeNext_move(CLICK_CD_MELEE) - + user.DelayNextAction(CLICK_CD_MELEE) /obj/structure/alien/egg/proc/Grow() status = GROWN diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index fcc26d1313..47584a1775 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -45,8 +45,6 @@ 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 @@ -75,12 +73,16 @@ . = ..() 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) +/obj/item/canvas/ui_state(mob/user) + if(finalized) + return GLOB.physical_obscured_state + else + return GLOB.default_state - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/canvas/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "canvas", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "Canvas", name) ui.set_autoupdate(FALSE) ui.open() @@ -190,8 +192,6 @@ icon_state = "19x19" width = 19 height = 19 - ui_x = 600 - ui_y = 600 pixel_x = 6 pixel_y = 9 framed_offset_x = 8 @@ -201,8 +201,6 @@ icon_state = "23x19" width = 23 height = 19 - ui_x = 800 - ui_y = 600 pixel_x = 4 pixel_y = 10 framed_offset_x = 6 @@ -212,8 +210,6 @@ icon_state = "23x23" width = 23 height = 23 - ui_x = 800 - ui_y = 800 pixel_x = 5 pixel_y = 9 framed_offset_x = 5 @@ -262,7 +258,7 @@ /obj/structure/sign/painting/examine(mob/user) . = ..() if(C) - C.ui_interact(user,state = GLOB.physical_obscured_state) + C.ui_interact(user) /obj/structure/sign/painting/wirecutter_act(mob/living/user, obj/item/I) . = ..() diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm index 821409c26b..905888c904 100644 --- a/code/game/objects/structures/barsigns.dm +++ b/code/game/objects/structures/barsigns.dm @@ -52,10 +52,7 @@ /obj/structure/sign/barsign/attack_ai(mob/user) return attack_hand(user) -/obj/structure/sign/barsign/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/sign/barsign/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!allowed(user)) to_chat(user, "Access denied.") return diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index 2225c4c0c2..39bef1a9c0 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -155,7 +155,7 @@ ///Material chair /obj/structure/chair/greyscale icon_state = "chair_greyscale" - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS item_chair = /obj/item/chair/greyscale buildstacktype = null //Custom mats handle this @@ -319,10 +319,43 @@ throwforce = 10 throw_range = 3 hitsound = 'sound/items/trayhit1.ogg' - block_chance = 50 custom_materials = list(/datum/material/iron = 2000) var/break_chance = 5 //Likely hood of smashing the chair. var/obj/structure/chair/origin_type = /obj/structure/chair + item_flags = ITEM_CAN_PARRY | ITEM_CAN_BLOCK + block_parry_data = /datum/block_parry_data/chair + +/obj/item/chair/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, require_twohands = TRUE) + +/datum/block_parry_data/chair + block_damage_multiplier = 0.7 + block_stamina_efficiency = 2 + block_stamina_cost_per_second = 1.5 + block_slowdown = 0.5 + block_lock_attacking = FALSE + block_lock_sprinting = TRUE + block_start_delay = 1.5 + block_damage_absorption = 7 + block_damage_limit = 20 + block_resting_stamina_penalty_multiplier = 2 + block_projectile_mitigation = 20 + parry_stamina_cost = 5 + parry_time_windup = 1 + parry_time_active = 11 + parry_time_spindown = 2 + parry_time_perfect = 1.5 + parry_time_perfect_leeway = 1 + parry_imperfect_falloff_percent = 7.5 + parry_efficiency_to_counterattack = 100 + parry_efficiency_considered_successful = 50 + parry_efficiency_perfect = 120 + parry_efficiency_perfect_override = list( + TEXT_ATTACK_TYPE_PROJECTILE = 30, + ) + parry_failed_stagger_duration = 3.5 SECONDS + parry_data = list(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5) /obj/item/chair/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins hitting [user.p_them()]self with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -384,7 +417,7 @@ /obj/item/chair/greyscale icon_state = "chair_greyscale_toppled" item_state = "chair_greyscale" - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS origin_type = /obj/structure/chair/greyscale /obj/item/chair/stool @@ -454,7 +487,7 @@ desc = "A bronze bar stool with red silk for a pillow." icon_state = "barbrass" item_chair = /obj/item/chair/stool/bar/bronze - buildstacktype = /obj/item/stack/tile/bronze + buildstacktype = /obj/item/stack/sheet/bronze buildstackamount = 1 /obj/structure/chair/stool/brass @@ -470,7 +503,7 @@ desc = "A bronze stool with a silk top for comfort." icon_state = "stoolbrass" item_chair = /obj/item/chair/stool/bronze - buildstacktype = /obj/item/stack/tile/bronze + buildstacktype = /obj/item/stack/sheet/bronze buildstackamount = 1 /obj/item/chair/stool/brass @@ -536,7 +569,6 @@ buildstacktype = /obj/item/stack/tile/brass buildstackamount = 1 item_chair = null - var/turns = 0 /obj/structure/chair/brass/ComponentInitialize() return //it spins with the power of ratvar, not components. @@ -548,16 +580,12 @@ /obj/structure/chair/brass/process() setDir(turn(dir,-90)) playsound(src, 'sound/effects/servostep.ogg', 50, FALSE) - turns++ - if(turns >= 8) - STOP_PROCESSING(SSfastprocess, src) /obj/structure/chair/brass/ratvar_act() return /obj/structure/chair/brass/AltClick(mob/living/user) . = ..() - turns = 0 if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user))) return if(!(datum_flags & DF_ISPROCESSING)) @@ -575,7 +603,7 @@ desc = "A spinny chair made of bronze. It has little cogs for wheels!" anchored = FALSE icon_state = "brass_chair" - buildstacktype = /obj/item/stack/tile/bronze + buildstacktype = /obj/item/stack/sheet/bronze buildstackamount = 1 item_chair = null diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index a4ee2f16e2..c36fba96cb 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -243,10 +243,24 @@ LINEN BINS /obj/item/bedsheet/random/Initialize() ..() - var/type = pick(typesof(/obj/item/bedsheet) - /obj/item/bedsheet/random) + var/type = pick(typesof(/obj/item/bedsheet) - list(/obj/item/bedsheet/random, /obj/item/bedsheet/chameleon)) new type(loc) return INITIALIZE_HINT_QDEL +/obj/item/bedsheet/chameleon //donator chameleon bedsheet + name = "chameleon bedsheet" + desc = "Bedsheet technology has truly gone too far." + var/datum/action/item_action/chameleon/change/chameleon_action + +/obj/item/bedsheet/chameleon/New() + ..() + chameleon_action = new(src) + chameleon_action.chameleon_type = /obj/item/bedsheet + chameleon_action.chameleon_name = "Bedsheet" + chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/bedsheet/chameleon, /obj/item/bedsheet/random), only_root_path = TRUE) + chameleon_action.initialize_disguises() + +//bedsheet bin /obj/structure/bedsheetbin name = "linen bin" desc = "It looks rather cosy." @@ -311,10 +325,7 @@ LINEN BINS /obj/structure/bedsheetbin/attack_paw(mob/user) return attack_hand(user) -/obj/structure/bedsheetbin/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/bedsheetbin/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.incapacitated()) return if(amount >= 1) diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 5da04a6686..5c5b2bb132 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -37,12 +37,13 @@ var/lock_in_use = FALSE //Someone is doing some stuff with the lock here, better not proceed further var/eigen_teleport = FALSE //If the closet leads to Mr Tumnus. var/obj/structure/closet/eigen_target //Where you go to. - + var/should_populate_contents = TRUE /obj/structure/closet/Initialize(mapload) . = ..() update_icon() - PopulateContents() + if(should_populate_contents) + PopulateContents() if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents addtimer(CALLBACK(src, .proc/take_contents), 0) if(secure) @@ -110,6 +111,9 @@ var/mob/living/L = user if(HAS_TRAIT(L, TRAIT_SKITTISH)) . += "Ctrl-Shift-click [src] to jump inside." + if(isobserver(user)) + . += "It contains: [english_list(contents)]." + investigate_log("had its contents examined by [user] as a ghost.", INVESTIGATE_GHOST) /obj/structure/closet/CanPass(atom/movable/mover, turf/target) if(wall_mounted) @@ -458,10 +462,7 @@ return container_resist(user) -/obj/structure/closet/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/closet/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.lying && get_dist(src, user) > 0) return @@ -506,8 +507,6 @@ if(opened) return if(ismovable(loc)) - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT var/atom/movable/AM = loc AM.relay_container_resist(user, src) return @@ -516,8 +515,6 @@ return //okay, so the closet is either welded or locked... resist!!! - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT user.visible_message("[src] begins to shake violently!", \ "You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)", \ "You hear banging from [src].") diff --git a/code/game/objects/structures/crates_lockers/closets/genpop.dm b/code/game/objects/structures/crates_lockers/closets/genpop.dm index 2b263bb1ed..7be12a4819 100644 --- a/code/game/objects/structures/crates_lockers/closets/genpop.dm +++ b/code/game/objects/structures/crates_lockers/closets/genpop.dm @@ -91,7 +91,7 @@ locked = TRUE return ..() -/obj/structure/closet/secure_closet/genpop/attack_hand(mob/user) +/obj/structure/closet/secure_closet/genpop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.lying && get_dist(src, user) > 0) return @@ -114,4 +114,4 @@ return - ..() \ No newline at end of file + ..() diff --git a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm index 57520f6f40..0c314d988c 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/secure_closets.dm @@ -6,8 +6,16 @@ max_integrity = 250 armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) secure = TRUE + var/melee_min_damage = 20 /obj/structure/closet/secure_closet/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) - if(damage_flag == "melee" && damage_amount < 20) + if(damage_flag == "melee" && damage_amount < melee_min_damage) return 0 - . = ..() \ No newline at end of file + . = ..() + +// Exists to work around the minimum 700 cr price for goodies / small items +/obj/structure/closet/secure_closet/goodies + icon_state = "goodies" + desc = "A sturdier card-locked storage unit used for bulky shipments." + max_integrity = 500 // Same as crates. + melee_min_damage = 25 // Idem. diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 9f4da351fa..ad7680f2f9 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -273,8 +273,8 @@ icon_state = "tac" /obj/structure/closet/secure_closet/lethalshots/PopulateContents() ..() - new /obj/item/twohanded/electrostaff(src) - new /obj/item/twohanded/electrostaff(src) + new /obj/item/electrostaff(src) + new /obj/item/electrostaff(src) for(var/i in 1 to 3) new /obj/item/storage/box/lethalshot(src) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 2c977a34d6..ee202f9504 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -41,10 +41,8 @@ if(manifest) . += "manifest" -/obj/structure/closet/crate/attack_hand(mob/user) +/obj/structure/closet/crate/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() - if(.) - return if(manifest) tear_manifest(user) @@ -144,6 +142,9 @@ desc = "A freezer containing packs of blood." icon_state = "surgery" +/obj/structure/closet/crate/freezer/blood/fake + should_populate_contents = FALSE + /obj/structure/closet/crate/freezer/blood/PopulateContents() . = ..() new /obj/item/reagent_containers/blood(src) @@ -164,6 +165,9 @@ name = "surplus prosthetic limbs" desc = "A crate containing an assortment of cheap prosthetic limbs." +/obj/structure/closet/crate/freezer/surplus_limbs/fake + should_populate_contents = FALSE + /obj/structure/closet/crate/freezer/surplus_limbs/PopulateContents() . = ..() new /obj/item/bodypart/l_arm/robot/surplus(src) @@ -198,6 +202,9 @@ name = "\improper RCD crate" icon_state = "engi_crate" +/obj/structure/closet/crate/rcd/fake + should_populate_contents = FALSE + /obj/structure/closet/crate/rcd/PopulateContents() ..() for(var/i in 1 to 4) diff --git a/code/game/objects/structures/crates_lockers/crates/large.dm b/code/game/objects/structures/crates_lockers/crates/large.dm index 880460a23c..3cee96e435 100644 --- a/code/game/objects/structures/crates_lockers/crates/large.dm +++ b/code/game/objects/structures/crates_lockers/crates/large.dm @@ -8,7 +8,7 @@ delivery_icon = "deliverybox" integrity_failure = 0 //Makes the crate break when integrity reaches 0, instead of opening and becoming an invisible sprite. -/obj/structure/closet/crate/large/attack_hand(mob/user) +/obj/structure/closet/crate/large/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) if(manifest) tear_manifest(user) @@ -40,4 +40,4 @@ else to_chat(user, "You need a crowbar to pry this open!") return FALSE //Just stop. Do nothing. Don't turn into an invisible sprite. Don't open like a locker. - //The large crate has no non-attack interactions other than the crowbar, anyway. \ No newline at end of file + //The large crate has no non-attack interactions other than the crowbar, anyway. diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm index c332a07edf..19c0f0aed1 100644 --- a/code/game/objects/structures/displaycase.dm +++ b/code/game/objects/structures/displaycase.dm @@ -9,6 +9,8 @@ armor = list("melee" = 30, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100) max_integrity = 200 integrity_failure = 0.25 + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE var/obj/item/showpiece = null var/alert = TRUE var/open = FALSE @@ -157,11 +159,7 @@ /obj/structure/displaycase/attack_paw(mob/user) return attack_hand(user) -/obj/structure/displaycase/attack_hand(mob/user) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) +/obj/structure/displaycase/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if (showpiece && (broken || open)) to_chat(user, "You deactivate the hover field built into the case.") log_combat(user, src, "deactivates the hover field of") @@ -347,3 +345,212 @@ name = initial(I.name) icon = initial(I.icon) icon_state = initial(I.icon_state) +/* Selling people in jars is currently disabled. +/obj/structure/displaycase/forsale + name = "vend-a-tray" + icon = 'icons/obj/stationobjs.dmi' + icon_state = "laserbox0" + desc = "A display case with an ID-card swiper. Use your ID to purchase the contents." + density = FALSE + max_integrity = 100 + req_access = null + showpiece_type = /obj/item/reagent_containers/food + alert = FALSE //No, we're not calling the fire department because someone stole your cookie. + glass_fix = FALSE //Fixable with tools instead. + ///The price of the item being sold. Altered by grab intent ID use. + var/sale_price = 20 + ///The Account which will receive payment for purchases. Set by the first ID to swipe the tray. + var/datum/bank_account/payments_acc = null + ///We're using the same trick as paper does in order to cache the image, and only load the UI when messed with. + var/list/viewing_ui = list() + +/obj/structure/displaycase/forsale/update_icon() //remind me to fix my shitcode later + var/icon/I + if(open) + I = icon('icons/obj/stationobjs.dmi',"laserboxb0") + else + I = icon('icons/obj/stationobjs.dmi',"laserbox0") + if(!showpiece && !open) + I = icon('icons/obj/stationobjs.dmi',"laserbox_open") + if(broken) + I = icon('icons/obj/stationobjs.dmi',"laserbox_broken") + if(showpiece) + var/icon/S = getFlatIcon(showpiece) + S.Scale(17,17) + I.Blend(S,ICON_UNDERLAY,8,12) + src.icon = I + return + +/obj/structure/displaycase/forsale/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Vendatray", name) + ui.set_autoupdate(FALSE) + viewing_ui[user] = ui + ui.open() + +/obj/structure/displaycase/forsale/ui_data(mob/user) + var/list/data = list() + var/register = FALSE + if(payments_acc) + register = TRUE + data["owner_name"] = payments_acc.account_holder + if(showpiece) + data["product_name"] = capitalize(showpiece.name) + var/base64 = icon2base64(icon(showpiece.icon, showpiece.icon_state)) + data["product_icon"] = base64 + data["registered"] = register + data["product_cost"] = sale_price + data["tray_open"] = open + return data + +/obj/structure/displaycase/forsale/ui_act(action, params) + if(..()) + return + var/obj/item/card/id/potential_acc = usr.get_idcard(hand_first = TRUE) + switch(action) + if("Buy") + if(!showpiece) + to_chat(usr, "There's nothing for sale.") + return TRUE + if(broken) + to_chat(usr, "[src] appears to be broken.") + return TRUE + if(!payments_acc) + to_chat(usr, "[src] hasn't been registered yet.") + return TRUE + if(!usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + return TRUE + if(!potential_acc) + to_chat(usr, "No ID card detected.") + return + var/datum/bank_account/account = potential_acc.registered_account + if(!account) + to_chat(usr, "[potential_acc] has no account registered!") + return + if(!account.has_money(sale_price)) + to_chat(usr, "You do not possess the funds to purchase this.") + return TRUE + else + account.adjust_money(-sale_price) + if(payments_acc) + payments_acc.adjust_money(sale_price) + usr.put_in_hands(showpiece) + to_chat(usr, "You purchase [showpiece] for [sale_price] credits.") + playsound(src, 'sound/effects/cashregister.ogg', 40, TRUE) + icon = 'icons/obj/stationobjs.dmi' + flick("laserbox_vend", src) + showpiece = null + update_icon() + SStgui.update_uis(src) + return TRUE + if("Open") + if(!payments_acc) + to_chat(usr, "[src] hasn't been registered yet.") + return TRUE + if(!potential_acc || !potential_acc.registered_account) + return + if(!check_access(potential_acc)) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return + toggle_lock() + SStgui.update_uis(src) + if("Register") + if(payments_acc) + return + if(!potential_acc || !potential_acc.registered_account) + return + if(!check_access(potential_acc)) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return + payments_acc = potential_acc.registered_account + playsound(src, 'sound/machines/click.ogg', 20, TRUE) + if("Adjust") + if(!check_access(potential_acc) || potential_acc.registered_account != payments_acc) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return + + var/new_price_input = input(usr,"Set the sale price for this vend-a-tray.","new price",0) as num|null + if(isnull(new_price_input) || (payments_acc != potential_acc.registered_account)) + to_chat(usr, "[src] rejects your new price.") + return + if(!usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) ) + to_chat(usr, "You need to get closer!") + return + new_price_input = clamp(round(new_price_input, 1), 10, 1000) + sale_price = new_price_input + to_chat(usr, "The cost is now set to [sale_price].") + SStgui.update_uis(src) + return TRUE + . = TRUE +/obj/structure/displaycase/forsale/attackby(obj/item/I, mob/living/user, params) + if(isidcard(I)) + //Card Registration + var/obj/item/card/id/potential_acc = I + if(!potential_acc.registered_account) + to_chat(user, "This ID card has no account registered!") + return + if(payments_acc == potential_acc.registered_account) + playsound(src, 'sound/machines/click.ogg', 20, TRUE) + toggle_lock() + return + if(istype(I, /obj/item/pda)) + return TRUE + SStgui.update_uis(src) + . = ..() + + +/obj/structure/displaycase/forsale/multitool_act(mob/living/user, obj/item/I) + . = ..() + if(obj_integrity <= (integrity_failure * max_integrity)) + to_chat(user, "You start recalibrating [src]'s hover field...") + if(do_after(user, 20, target = src)) + broken = 0 + obj_integrity = max_integrity + update_icon() + return TRUE + +/obj/structure/displaycase/forsale/wrench_act(mob/living/user, obj/item/I) + . = ..() + if(open && user.a_intent == INTENT_HELP ) + if(anchored) + to_chat(user, "You start unsecuring [src]...") + else + to_chat(user, "You start securing [src]...") + if(I.use_tool(src, user, 16, volume=50)) + if(QDELETED(I)) + return + if(anchored) + to_chat(user, "You unsecure [src].") + else + to_chat(user, "You secure [src].") + anchored = !anchored + return + else if(!open && user.a_intent == INTENT_HELP) + to_chat(user, "[src] must be open to move it.") + return + +/obj/structure/displaycase/forsale/emag_act(mob/user) + . = ..() + payments_acc = null + req_access = list() + to_chat(user, "[src]'s card reader fizzles and smokes, and the account owner is reset.") + +/obj/structure/displaycase/forsale/examine(mob/user) + . = ..() + if(showpiece && !open) + . += "[showpiece] is for sale for [sale_price] credits." + if(broken) + . += "[src] is sparking and the hover field generator seems to be overloaded. Use a multitool to fix it." + +/obj/structure/displaycase/forsale/obj_break(damage_flag) + if(!broken && !(flags_1 & NODECONSTRUCT_1)) + broken = TRUE + playsound(src, "shatter", 70, TRUE) + update_icon() + trigger_alarm() //In case it's given an alarm anyway. + +/obj/structure/displaycase/forsale/kitchen + desc = "A display case with an ID-card swiper. Use your ID to purchase the contents. Meant for the bartender and chef." + req_one_access = list(ACCESS_KITCHEN, ACCESS_BAR) +*/ \ No newline at end of file diff --git a/code/game/objects/structures/divine.dm b/code/game/objects/structures/divine.dm index bca96e67d1..f64397df09 100644 --- a/code/game/objects/structures/divine.dm +++ b/code/game/objects/structures/divine.dm @@ -7,7 +7,7 @@ density = FALSE can_buckle = 1 -/obj/structure/sacrificealtar/attack_hand(mob/living/user) +/obj/structure/sacrificealtar/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -30,7 +30,7 @@ var/time_between_uses = 1800 var/last_process = 0 -/obj/structure/healingfountain/attack_hand(mob/living/user) +/obj/structure/healingfountain/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -48,4 +48,4 @@ if(last_process + time_between_uses > world.time) icon_state = "fountain" else - icon_state = "fountain-red" \ No newline at end of file + icon_state = "fountain-red" diff --git a/code/game/objects/structures/door_assembly_types.dm b/code/game/objects/structures/door_assembly_types.dm index fe9c4e7bbc..5fb454b5bc 100644 --- a/code/game/objects/structures/door_assembly_types.dm +++ b/code/game/objects/structures/door_assembly_types.dm @@ -240,3 +240,14 @@ airlock_type = /obj/machinery/door/airlock/wood mineral = "wood" glass_type = /obj/machinery/door/airlock/wood/glass + +/obj/structure/door_assembly/door_assembly_bronze + name = "bronze airlock assembly" + icon = 'icons/obj/doors/airlocks/clockwork/pinion_airlock.dmi' + base_name = "bronze airlock" + airlock_type = /obj/machinery/door/airlock/bronze + noglass = TRUE + material_type = /obj/item/stack/tile/bronze + +/obj/structure/door_assembly/door_assembly_bronze/seethru + airlock_type = /obj/machinery/door/airlock/bronze/seethru diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm index 528153324d..7fdec9b3d9 100644 --- a/code/game/objects/structures/dresser.dm +++ b/code/game/objects/structures/dresser.dm @@ -19,7 +19,7 @@ new /obj/item/stack/sheet/mineral/wood(drop_location(), 10) qdel(src) -/obj/structure/dresser/attack_hand(mob/user) +/obj/structure/dresser/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(. || !ishuman(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return @@ -46,7 +46,7 @@ switch(choice) if("Underwear") var/new_undies = input(H, "Select your underwear", "Changing") as null|anything in GLOB.underwear_list - if(H.underwear) + if(new_undies) H.underwear = new_undies H.saved_underwear = new_undies var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[new_undies] diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index 3bc84deb4d..84926ccfb0 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -69,10 +69,7 @@ return ..() -/obj/structure/extinguisher_cabinet/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/extinguisher_cabinet/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscyborg(user) || isalien(user)) return if(stored_extinguisher) diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm index 679a755321..b654f4f5c0 100644 --- a/code/game/objects/structures/false_walls.dm +++ b/code/game/objects/structures/false_walls.dm @@ -41,7 +41,7 @@ new /obj/structure/falsewall/brass(loc) qdel(src) -/obj/structure/falsewall/attack_hand(mob/user) +/obj/structure/falsewall/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(opening) return . = ..() @@ -180,7 +180,7 @@ radiate() return ..() -/obj/structure/falsewall/uranium/attack_hand(mob/user) +/obj/structure/falsewall/uranium/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) radiate() . = ..() diff --git a/code/game/objects/structures/femur_breaker.dm b/code/game/objects/structures/femur_breaker.dm index 7331285161..2ac56ec4fb 100644 --- a/code/game/objects/structures/femur_breaker.dm +++ b/code/game/objects/structures/femur_breaker.dm @@ -32,7 +32,7 @@ if (LAZYLEN(buckled_mobs)) . += "Someone appears to be strapped in. You can help them unbuckle, or activate the femur breaker." -/obj/structure/femur_breaker/attack_hand(mob/user) +/obj/structure/femur_breaker/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) // Currently being used diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm index 35891fa607..f90161f587 100644 --- a/code/game/objects/structures/fence.dm +++ b/code/game/objects/structures/fence.dm @@ -120,7 +120,7 @@ open = TRUE density = TRUE -/obj/structure/fence/door/attack_hand(mob/user) +/obj/structure/fence/door/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(can_open(user)) toggle(user) @@ -156,4 +156,4 @@ #undef NO_HOLE #undef MEDIUM_HOLE #undef LARGE_HOLE -#undef MAX_HOLE_SIZE \ No newline at end of file +#undef MAX_HOLE_SIZE diff --git a/code/game/objects/structures/fireaxe.dm b/code/game/objects/structures/fireaxe.dm index f4c1dd5ab9..412730910f 100644 --- a/code/game/objects/structures/fireaxe.dm +++ b/code/game/objects/structures/fireaxe.dm @@ -11,7 +11,7 @@ integrity_failure = 0.33 var/locked = TRUE var/open = FALSE - var/obj/item/twohanded/fireaxe/fireaxe + var/obj/item/fireaxe/fireaxe /obj/structure/fireaxecabinet/Initialize() . = ..() @@ -50,8 +50,8 @@ obj_integrity = max_integrity update_icon() else if(open || broken) - if(istype(I, /obj/item/twohanded/fireaxe) && !fireaxe) - var/obj/item/twohanded/fireaxe/F = I + if(istype(I, /obj/item/fireaxe) && !fireaxe) + var/obj/item/fireaxe/F = I if(F.wielded) to_chat(user, "Unwield the [F.name] first.") return @@ -105,10 +105,7 @@ fireaxe = null qdel(src) -/obj/structure/fireaxecabinet/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/fireaxecabinet/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(open || broken) if(fireaxe) user.put_in_hands(fireaxe) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index c1f8af43f0..b587e57c3a 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -65,7 +65,7 @@ var/gift_type = /obj/item/a_gift/anything var/list/ckeys_that_took = list() -/obj/structure/flora/tree/pine/xmas/presents/attack_hand(mob/living/user) +/obj/structure/flora/tree/pine/xmas/presents/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -288,7 +288,7 @@ icon_state = "fullgrass_[rand(1, 3)]" . = ..() -/obj/item/twohanded/required/kirbyplants +/obj/item/kirbyplants name = "potted plant" icon = 'icons/obj/flora/plants.dmi' icon_state = "plant-01" @@ -300,24 +300,25 @@ throw_speed = 2 throw_range = 4 -/obj/item/twohanded/required/kirbyplants/Initialize() +/obj/item/kirbyplants/ComponentInitialize() . = ..() AddElement(/datum/element/tactical) addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 500)), 0) + AddComponent(/datum/component/two_handed, require_twohands=TRUE, force_unwielded=10, force_wielded=10) -/obj/item/twohanded/required/kirbyplants/random +/obj/item/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' icon_state = "random_plant" var/list/static/states -/obj/item/twohanded/required/kirbyplants/random/Initialize() +/obj/item/kirbyplants/random/Initialize() . = ..() icon = 'icons/obj/flora/plants.dmi' if(!states) generate_states() icon_state = pick(states) -/obj/item/twohanded/required/kirbyplants/random/proc/generate_states() +/obj/item/kirbyplants/random/proc/generate_states() states = list() for(var/i in 1 to 25) var/number @@ -329,12 +330,12 @@ states += "applebush" -/obj/item/twohanded/required/kirbyplants/dead +/obj/item/kirbyplants/dead name = "RD's potted plant" desc = "A gift from the botanical staff, presented after the RD's reassignment. There's a tag on it that says \"Y'all come back now, y'hear?\"\nIt doesn't look very healthy..." icon_state = "plant-25" -/obj/item/twohanded/required/kirbyplants/photosynthetic +/obj/item/kirbyplants/photosynthetic name = "photosynthetic potted plant" desc = "A bioluminescent plant." icon_state = "plant-09" diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index 736e58143e..bd7ddb36d5 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -110,7 +110,7 @@ desc = "Space Jesus is my copilot." icon_state = "driverseat" -/obj/structure/fluff/bus/passable/seat/driver/attack_hand(mob/user) +/obj/structure/fluff/bus/passable/seat/driver/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) playsound(src, 'sound/items/carhorn.ogg', 50, 1) . = ..() diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 4455c8820d..4d500837d9 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -186,10 +186,7 @@ else new_spawn.mind.assigned_role = "Free Golem" -/obj/effect/mob_spawn/human/golem/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/effect/mob_spawn/human/golem/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(isgolem(user) && can_transfer) var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No") if(transfer_choice != "Yes" || QDELETED(src) || uses <= 0 || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERY, NO_TK)) diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index cacf361722..87cfbb56e0 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -170,7 +170,7 @@ qdel(src) return - if(S.sheettype && S.sheettype != "runed") + if(S.sheettype != "runed") var/M = S.sheettype if(state == GIRDER_DISPLACED) var/F = text2path("/obj/structure/falsewall/[M]") @@ -188,9 +188,13 @@ transfer_fingerprints_to(FW) qdel(src) else - var/F = text2path("/turf/closed/wall/mineral/[M]") + var/list/material_list + var/F = S.walltype if(!F) - return + F = /turf/closed/wall/material + if(S.material_type) + material_list = list() + material_list[SSmaterials.GetMaterialRef(S.material_type)] = MINERAL_MATERIAL_AMOUNT * 2 if(S.get_amount() < 2) to_chat(user, "You need at least two sheets to add plating!") return @@ -201,7 +205,9 @@ S.use(2) to_chat(user, "You add the plating.") var/turf/T = get_turf(src) - T.PlaceOnTop(F) + var/turf/newturf = T.PlaceOnTop(F) + if(material_list) + newturf.set_custom_materials(material_list) transfer_fingerprints_to(T) qdel(src) return @@ -436,19 +442,19 @@ to_chat(user, "You start slicing apart [src]...") if(W.use_tool(src, user, 40, volume=50)) to_chat(user, "You slice apart [src].") - var/obj/item/stack/tile/bronze/B = new(drop_location(), 2) + var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2) transfer_fingerprints_to(B) qdel(src) else if(istype(W, /obj/item/pickaxe/drill/jackhammer)) to_chat(user, "Your jackhammer smashes through the girder!") - var/obj/item/stack/tile/bronze/B = new(drop_location(), 2) + var/obj/item/stack/sheet/bronze/B = new(drop_location(), 2) transfer_fingerprints_to(B) W.play_tool_sound(src) qdel(src) - else if(istype(W, /obj/item/stack/tile/bronze)) - var/obj/item/stack/tile/bronze/B = W + else if(istype(W, /obj/item/stack/sheet/bronze)) + var/obj/item/stack/sheet/bronze/B = W if(B.get_amount() < 2) to_chat(user, "You need at least two bronze sheets to build a bronze wall!") return 0 diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 20151a0bdb..7853b9619c 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -10,6 +10,8 @@ layer = BELOW_OBJ_LAYER armor = list("melee" = 50, "bullet" = 70, "laser" = 70, "energy" = 100, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) max_integrity = 50 + attack_hand_is_action = TRUE + attack_hand_speed = 8 integrity_failure = 0.4 var/rods_type = /obj/item/stack/rods var/rods_amount = 2 @@ -84,6 +86,10 @@ /obj/structure/grille/attack_animal(mob/user) . = ..() + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return + user.DelayNextAction(flush = TRUE) + user.do_attack_animation(src) if(!shock(user, 70) && !QDELETED(src)) //Last hit still shocks but shouldn't deal damage to the grille) take_damage(rand(5,10), BRUTE, "melee", 1) @@ -99,11 +105,10 @@ ..(user, 1) return TRUE -/obj/structure/grille/attack_hand(mob/living/user) +/obj/structure/grille/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return - user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_KICK) user.visible_message("[user] hits [src].", null, null, COMBAT_MESSAGE_RANGE) log_combat(user, src, "hit") @@ -111,13 +116,14 @@ take_damage(rand(5,10), BRUTE, "melee", 1) /obj/structure/grille/attack_alien(mob/living/user) + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return + user.DelayNextAction(flush = TRUE) user.do_attack_animation(src) - user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] mangles [src].", null, null, COMBAT_MESSAGE_RANGE) if(!shock(user, 70)) take_damage(20, BRUTE, "melee", 1) - /obj/structure/grille/CanPass(atom/movable/mover, turf/target) if(istype(mover) && (mover.pass_flags & PASSGRILLE)) return TRUE @@ -134,7 +140,7 @@ . = . || (mover.pass_flags & PASSGRILLE) /obj/structure/grille/attackby(obj/item/W, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) add_fingerprint(user) if(istype(W, /obj/item/wirecutters)) if(!shock(user, 100)) diff --git a/code/game/objects/structures/guillotine.dm b/code/game/objects/structures/guillotine.dm index 0a5ba6a68c..4773c07657 100644 --- a/code/game/objects/structures/guillotine.dm +++ b/code/game/objects/structures/guillotine.dm @@ -51,7 +51,7 @@ if (LAZYLEN(buckled_mobs)) . += "Someone appears to be strapped in. You can help them out, or you can harm them by activating the guillotine." -/obj/structure/guillotine/attack_hand(mob/user) +/obj/structure/guillotine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) // Currently being used by something @@ -108,7 +108,7 @@ if (QDELETED(head)) return - playsound(src, 'sound/weapons/bladeslice.ogg', 100, 1) + playsound(src, 'sound/weapons/guillotine.ogg', 100, TRUE) if (blade_sharpness >= GUILLOTINE_DECAP_MIN_SHARP || head.brute_dam >= 100) head.dismember() log_combat(user, H, "beheaded", src) @@ -256,4 +256,4 @@ #undef GUILLOTINE_ACTIVATE_DELAY #undef GUILLOTINE_WRENCH_DELAY #undef GUILLOTINE_ACTION_INUSE -#undef GUILLOTINE_ACTION_WRENCH \ No newline at end of file +#undef GUILLOTINE_ACTION_WRENCH diff --git a/code/game/objects/structures/guncase.dm b/code/game/objects/structures/guncase.dm index ede7e31e0d..e7ff9d4abf 100644 --- a/code/game/objects/structures/guncase.dm +++ b/code/game/objects/structures/guncase.dm @@ -53,10 +53,7 @@ else return ..() -/obj/structure/guncase/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/guncase/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscyborg(user) || isalien(user)) return if(contents.len && open) diff --git a/code/game/objects/structures/headpike.dm b/code/game/objects/structures/headpike.dm index 581ce850de..6aed11701d 100644 --- a/code/game/objects/structures/headpike.dm +++ b/code/game/objects/structures/headpike.dm @@ -6,7 +6,7 @@ density = FALSE anchored = TRUE var/bonespear = FALSE - var/obj/item/twohanded/spear/spear + var/obj/item/spear/spear var/obj/item/bodypart/head/victim /obj/structure/headpike/bone //for bone spears @@ -20,9 +20,9 @@ name = "[victim.name] on a spear" update_icon() if(bonespear) - spear = locate(/obj/item/twohanded/bonespear) in parts_list + spear = locate(/obj/item/spear/bonespear) in parts_list else - spear = locate(/obj/item/twohanded/spear) in parts_list + spear = locate(/obj/item/spear) in parts_list /obj/structure/headpike/Initialize() . = ..() @@ -37,14 +37,11 @@ MA.pixel_y = 12 . += H -/obj/structure/headpike/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/headpike/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) to_chat(user, "You take down [src].") if(victim) victim.forceMove(drop_location()) victim = null spear.forceMove(drop_location()) spear = null - qdel(src) \ No newline at end of file + qdel(src) diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm index 7ac3aba246..dc5355e9d8 100644 --- a/code/game/objects/structures/holosign.dm +++ b/code/game/objects/structures/holosign.dm @@ -25,12 +25,12 @@ projector = null return ..() -/obj/structure/holosign/attack_hand(mob/living/user) +/obj/structure/holosign/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) take_damage(5 , BRUTE, "melee", 1) /obj/structure/holosign/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) @@ -94,7 +94,7 @@ alpha = 150 resistance_flags = FIRE_PROOF -/obj/structure/holosign/barrier/firelock/blocksTemperature() +/obj/structure/holosign/barrier/firelock/BlockSuperconductivity() return TRUE /obj/structure/holosign/barrier/combifan @@ -110,7 +110,7 @@ CanAtmosPass = ATMOS_PASS_NO resistance_flags = FIRE_PROOF -/obj/structure/holosign/barrier/combifan/blocksTemperature() +/obj/structure/holosign/barrier/combifan/BlockSuperconductivity() return TRUE /obj/structure/holosign/barrier/combifan/Initialize() @@ -162,7 +162,7 @@ return TRUE //nice or benign diseases! return TRUE -/obj/structure/holosign/barrier/medical/attack_hand(mob/living/user) +/obj/structure/holosign/barrier/medical/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(CanPass(user) && user.a_intent == INTENT_HELP) force_allaccess = !force_allaccess to_chat(user, "You [force_allaccess ? "deactivate" : "activate"] the biometric scanners.") //warning spans because you can make the station sick! @@ -182,7 +182,7 @@ /obj/structure/holosign/barrier/cyborg/hacked/proc/cooldown() shockcd = FALSE -/obj/structure/holosign/barrier/cyborg/hacked/attack_hand(mob/living/user) +/obj/structure/holosign/barrier/cyborg/hacked/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index 38133d9089..10a9f2afd4 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -8,7 +8,7 @@ //copypaste sorry var/obj/item/storage/bag/trash/mybag var/obj/item/mop/mymop - var/obj/item/twohanded/broom/mybroom + var/obj/item/broom/mybroom var/obj/item/reagent_containers/spray/cleaner/myspray var/obj/item/lightreplacer/myreplacer var/signs = 0 @@ -48,9 +48,9 @@ m.janicart_insert(user, src) else to_chat(user, fail_msg) - else if(istype(I, /obj/item/twohanded/broom)) + else if(istype(I, /obj/item/broom)) if(!mybroom) - var/obj/item/twohanded/broom/b=I + var/obj/item/broom/b=I b.janicart_insert(user,src) else to_chat(user, fail_msg) @@ -91,10 +91,7 @@ else return ..() -/obj/structure/janitorialcart/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/janitorialcart/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/list/items = list() if(mybag) diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm index 05a7e1c958..a23dd3a21e 100644 --- a/code/game/objects/structures/kitchen_spike.dm +++ b/code/game/objects/structures/kitchen_spike.dm @@ -60,8 +60,7 @@ deconstruct(TRUE) return TRUE -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/kitchenspike/attack_hand(mob/user) +/obj/structure/kitchenspike/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(VIABLE_MOB_CHECK(user.pulling) && user.a_intent == INTENT_GRAB && !has_buckled_mobs()) var/mob/living/L = user.pulling if(HAS_TRAIT(user, TRAIT_PACIFISM) && L.stat != DEAD) diff --git a/code/game/objects/structures/ladders.dm b/code/game/objects/structures/ladders.dm index f321498bfd..e844461952 100644 --- a/code/game/objects/structures/ladders.dm +++ b/code/game/objects/structures/ladders.dm @@ -122,10 +122,7 @@ return FALSE return TRUE -/obj/structure/ladder/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/ladder/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) use(user) /obj/structure/ladder/attack_paw(mob/user) diff --git a/code/game/objects/structures/lavaland/geyser.dm b/code/game/objects/structures/lavaland/geyser.dm index 4f6256e9c4..263b47aab2 100644 --- a/code/game/objects/structures/lavaland/geyser.dm +++ b/code/game/objects/structures/lavaland/geyser.dm @@ -9,7 +9,7 @@ var/erupting_state = null //set to null to get it greyscaled from "[icon_state]_soup". Not very usable with the whole random thing, but more types can be added if you change the spawn prob var/activated = FALSE //whether we are active and generating chems - var/reagent_id = /datum/reagent/fuel/oil + var/reagent_id = /datum/reagent/oil var/potency = 2 //how much reagents we add every process (2 seconds) var/max_volume = 500 var/start_volume = 50 @@ -77,10 +77,10 @@ /obj/item/plunger/reinforced name = "reinforced plunger" - desc = "It's an M. 7 Reinforced Plunger© for heavy duty plunging." + desc = "It's an M. 7 Reinforced Plunger� for heavy duty plunging." icon_state = "reinforced_plunger" reinforced = TRUE plunge_mod = 0.8 - custom_premium_price = 1200 + custom_premium_price = 600 diff --git a/code/game/objects/structures/life_candle.dm b/code/game/objects/structures/life_candle.dm index a64dc6c6a9..52986a44d7 100644 --- a/code/game/objects/structures/life_candle.dm +++ b/code/game/objects/structures/life_candle.dm @@ -24,10 +24,7 @@ var/respawn_time = 50 var/respawn_sound = 'sound/magic/staff_animation.ogg' -/obj/structure/life_candle/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/life_candle/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!user.mind) return if(user.mind in linked_minds) @@ -38,7 +35,7 @@ linked_minds |= user.mind update_icon() - float(linked_minds.len) + INVOKE_ASYNC(src, /atom/movable.proc/float, linked_minds.len) if(linked_minds.len) START_PROCESSING(SSobj, src) set_light(lit_luminosity) diff --git a/code/game/objects/structures/manned_turret.dm b/code/game/objects/structures/manned_turret.dm index 79489e4ae6..e8fbafa42b 100644 --- a/code/game/objects/structures/manned_turret.dm +++ b/code/game/objects/structures/manned_turret.dm @@ -198,10 +198,6 @@ /obj/item/gun_control/CanItemAutoclick() return TRUE -/obj/item/gun_control/attack_obj(obj/O, mob/living/user) - user.changeNext_move(CLICK_CD_MELEE) - O.attacked_by(src, user) - /obj/item/gun_control/attack(mob/living/M, mob/living/user) M.lastattacker = user.real_name M.lastattackerckey = user.ckey diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index f52fa0576a..b2f1de8750 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -50,10 +50,7 @@ /obj/structure/mineral_door/attack_paw(mob/user) return attack_hand(user) -/obj/structure/mineral_door/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/mineral_door/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) return TryToSwitchState(user) /obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target) diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 65e1b7dd9a..237cfdbf0b 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -15,10 +15,7 @@ if(icon_state == "mirror_broke" && !broken) obj_break(null, mapload) -/obj/structure/mirror/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/mirror/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(broken || !Adjacent(user)) return @@ -118,10 +115,7 @@ choosable_races += S.id ..() -/obj/structure/mirror/magic/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/mirror/magic/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!ishuman(user)) return diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 79a7ce0519..82ca59161c 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -22,7 +22,8 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an anchored = TRUE max_integrity = 400 - var/obj/structure/tray/connected = null + var/obj/structure/tray/connected + var/starting_tray var/locked = FALSE dir = SOUTH var/message_cooldown @@ -30,6 +31,9 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/Initialize() . = ..() + if(starting_tray) + connected = new starting_tray(src) + connected.connected = src GLOB.bodycontainers += src recursive_organ_check(src) @@ -37,8 +41,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an GLOB.bodycontainers -= src open() if(connected) - qdel(connected) - connected = null + QDEL_NULL(connected) return ..() /obj/structure/bodycontainer/on_log(login) @@ -58,10 +61,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an /obj/structure/bodycontainer/attack_paw(mob/user) return attack_hand(user) -/obj/structure/bodycontainer/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/bodycontainer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(locked) to_chat(user, "It's locked.") return @@ -106,8 +106,6 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an if(!locked) open() return - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT user.visible_message(null, \ "You lean on the back of [src] and start pushing the tray open... (this will take about [DisplayTimeText(breakout_time)].)", \ "You hear a metallic creaking from [src].") @@ -150,15 +148,11 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an desc = "Used to keep bodies in until someone fetches them. Now includes a high-tech alert system." icon_state = "morgue1" dir = EAST + starting_tray = /obj/structure/tray/m_tray var/beeper = TRUE var/beep_cooldown = 50 var/next_beep = 0 -/obj/structure/bodycontainer/morgue/New() - connected = new/obj/structure/tray/m_tray(src) - connected.connected = src - ..() - /obj/structure/bodycontainer/morgue/examine(mob/user) . = ..() . += "The speaker is [beeper ? "enabled" : "disabled"]. Alt-click to toggle it." @@ -208,6 +202,7 @@ GLOBAL_LIST_EMPTY(crematoriums) desc = "A human incinerator. Works well on barbecue nights." icon_state = "crema1" dir = SOUTH + starting_tray = /obj/structure/tray/c_tray var/id = 1 /obj/structure/bodycontainer/crematorium/attack_robot(mob/user) //Borgs can't use crematoriums without help @@ -218,14 +213,14 @@ GLOBAL_LIST_EMPTY(crematoriums) GLOB.crematoriums.Remove(src) return ..() -/obj/structure/bodycontainer/crematorium/New() - connected = new/obj/structure/tray/c_tray(src) - connected.connected = src - +/obj/structure/bodycontainer/crematorium/Initialize() + . = ..() GLOB.crematoriums.Add(src) - ..() -/obj/structure/bodycontainer/crematorium/update_icon_state() +/obj/structure/bodycontainer/crematorium/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) + id = "[idnum][id]" + +/obj/structure/bodycontainer/crematorium/update_icon() if(!connected || connected.loc != src) icon_state = "crema0" else @@ -322,10 +317,7 @@ GLOBAL_LIST_EMPTY(crematoriums) /obj/structure/tray/attack_paw(mob/user) return attack_hand(user) -/obj/structure/tray/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/tray/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if (src.connected) connected.close() add_fingerprint(user) diff --git a/code/game/objects/structures/spirit_board.dm b/code/game/objects/structures/spirit_board.dm index 4a9a1bdce6..1b3093e4e7 100644 --- a/code/game/objects/structures/spirit_board.dm +++ b/code/game/objects/structures/spirit_board.dm @@ -14,10 +14,7 @@ desc = "[initial(desc)] The planchette is sitting at \"[planchette]\"." return ..() -/obj/structure/spirit_board/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/spirit_board/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) spirit_board_pick_letter(user) @@ -76,4 +73,4 @@ to_chat(M, "There aren't enough people to use the [src.name]!") return 0 - return 1 \ No newline at end of file + return 1 diff --git a/code/game/objects/structures/stairs.dm b/code/game/objects/structures/stairs.dm index d1a2a6f9f6..1358b2e296 100644 --- a/code/game/objects/structures/stairs.dm +++ b/code/game/objects/structures/stairs.dm @@ -3,7 +3,7 @@ #define STAIR_TERMINATOR_YES 2 // dir determines the direction of travel to go upwards (due to lack of sprites, currently only 1 and 2 make sense) -// stairs require /turf/open/openspace as the tile above them to work +// stairs require /turf/open/transparent/openspace as the tile above them to work // multiple stair objects can be chained together; the Z level transition will happen on the final stair object in the chain /obj/structure/stairs @@ -12,7 +12,7 @@ icon_state = "stairs" anchored = TRUE - var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/openspace + var/force_open_above = FALSE // replaces the turf above this stair obj with /turf/open/transparent/openspace var/terminator_mode = STAIR_TERMINATOR_AUTOMATIC var/turf/listeningTo @@ -95,20 +95,20 @@ /obj/structure/stairs/proc/build_signal_listener() if(listeningTo) UnregisterSignal(listeningTo, COMSIG_TURF_MULTIZ_NEW) - var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) + var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP) RegisterSignal(T, COMSIG_TURF_MULTIZ_NEW, .proc/on_multiz_new) listeningTo = T /obj/structure/stairs/proc/force_open_above() - var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) + var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP) if(T && !istype(T)) - T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR) + T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR) /obj/structure/stairs/proc/on_multiz_new(turf/source, dir) if(dir == UP) - var/turf/open/openspace/T = get_step_multiz(get_turf(src), UP) + var/turf/open/transparent/openspace/T = get_step_multiz(get_turf(src), UP) if(T && !istype(T)) - T.ChangeTurf(/turf/open/openspace, flags = CHANGETURF_INHERIT_AIR) + T.ChangeTurf(/turf/open/transparent/openspace, flags = CHANGETURF_INHERIT_AIR) /obj/structure/stairs/intercept_zImpact(atom/movable/AM, levels = 1) . = ..() diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index 466912f93e..f8b54d04b6 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -74,7 +74,7 @@ radiate() ..() -/obj/structure/statue/uranium/attack_hand(mob/user) +/obj/structure/statue/uranium/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) radiate() . = ..() @@ -240,7 +240,7 @@ honk() return ..() -/obj/structure/statue/bananium/attack_hand(mob/user) +/obj/structure/statue/bananium/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) honk() . = ..() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 012d92e103..9f91d2c5e0 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -23,6 +23,8 @@ climbable = TRUE obj_flags = CAN_BE_HIT|SHOVABLE_ONTO pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.") + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE var/frame = /obj/structure/table_frame var/framestack = /obj/item/stack/rods var/buildstack = /obj/item/stack/sheet/metal @@ -60,7 +62,7 @@ /obj/structure/table/attack_paw(mob/user) return attack_hand(user) -/obj/structure/table/attack_hand(mob/living/user) +/obj/structure/table/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(Adjacent(user) && user.pulling) if(isliving(user.pulling)) var/mob/living/pushed_mob = user.pulling @@ -71,7 +73,10 @@ if(user.grab_state < GRAB_AGGRESSIVE) to_chat(user, "You need a better grip to do that!") return - tablepush(user, pushed_mob) + if(user.grab_state >= GRAB_NECK) + tablelimbsmash(user, pushed_mob) + else + tablepush(user, pushed_mob) if(user.a_intent == INTENT_HELP) pushed_mob.visible_message("[user] begins to place [pushed_mob] onto [src]...", \ "[user] begins to place [pushed_mob] onto [src]...") @@ -134,8 +139,26 @@ if(!ishuman(pushed_mob)) return var/mob/living/carbon/human/H = pushed_mob + if(iscatperson(H)) + H.emote("nya") SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table) +/obj/structure/table/proc/tablelimbsmash(mob/living/user, mob/living/pushed_mob) + pushed_mob.Knockdown(30) + var/obj/item/bodypart/banged_limb = pushed_mob.get_bodypart(user.zone_selected) || pushed_mob.get_bodypart(BODY_ZONE_HEAD) + var/extra_wound = 0 + if(HAS_TRAIT(user, TRAIT_HULK)) + extra_wound = 20 + banged_limb.receive_damage(30, wound_bonus = extra_wound) + pushed_mob.apply_damage(60, STAMINA) + take_damage(50) + + playsound(pushed_mob, 'sound/effects/bang.ogg', 90, TRUE) + pushed_mob.visible_message("[user] smashes [pushed_mob]'s [banged_limb.name] against \the [src]!", + "[user] smashes your [banged_limb.name] against \the [src]") + log_combat(user, pushed_mob, "head slammed", null, "against [src]") + SEND_SIGNAL(pushed_mob, COMSIG_ADD_MOOD_EVENT, "table", /datum/mood_event/table_limbsmash, banged_limb) + /obj/structure/table/shove_act(mob/living/target, mob/living/user) if(CHECK_MOBILITY(target, MOBILITY_STAND)) target.DefaultCombatKnockdown(SHOVE_KNOCKDOWN_TABLE) @@ -189,8 +212,10 @@ return /obj/structure/table/alt_attack_hand(mob/user) + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return + user.DelayNextAction() if(user && Adjacent(user) && !user.incapacitated()) - 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) @@ -218,7 +243,7 @@ /obj/structure/table/greyscale icon = 'icons/obj/smooth_structures/table_greyscale.dmi' icon_state = "table" - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS buildstack = null //No buildstack, so generate from mat datums ///Table on wheels @@ -551,7 +576,7 @@ change_construction_value(-2) return ..() -/obj/structure/table/reinforced/brass/tablepush(mob/living/user, mob/living/pushed_mob) +/obj/structure/table/reinforced/brass/tablelimbsmash(mob/living/user, mob/living/pushed_mob) .= ..() playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 50, TRUE) @@ -572,10 +597,10 @@ icon = 'icons/obj/smooth_structures/brass_table.dmi' icon_state = "brass_table" resistance_flags = FIRE_PROOF | ACID_PROOF - buildstack = /obj/item/stack/tile/bronze + buildstack = /obj/item/stack/sheet/bronze canSmoothWith = list(/obj/structure/table/reinforced/brass, /obj/structure/table/bronze) -/obj/structure/table/bronze/tablepush(mob/living/user, mob/living/pushed_mob) +/obj/structure/table/bronze/tablelimbsmash(mob/living/user, mob/living/pushed_mob) ..() playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 50, TRUE) @@ -604,7 +629,7 @@ computer.table = src break -/obj/structure/table/optable/tablepush(mob/living/user, mob/living/pushed_mob) +/obj/structure/table/optable/tablelimbsmash(mob/living/user, mob/living/pushed_mob) pushed_mob.forceMove(loc) pushed_mob.set_resting(TRUE, TRUE) visible_message("[user] has laid [pushed_mob] on [src].") @@ -633,6 +658,8 @@ anchored = TRUE pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density. max_integrity = 20 + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE /obj/structure/rack/examine(mob/user) . = ..() @@ -674,13 +701,12 @@ /obj/structure/rack/attack_paw(mob/living/user) attack_hand(user) -/obj/structure/rack/attack_hand(mob/living/user) +/obj/structure/rack/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return if(CHECK_MULTIPLE_BITFIELDS(user.mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) || user.get_num_legs() < 2) return - user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src, ATTACK_EFFECT_KICK) user.visible_message("[user] kicks [src].", null, null, COMBAT_MESSAGE_RANGE) take_damage(rand(4,8), BRUTE, "melee", 1) diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 6a8175b921..2a441ff0f2 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -67,11 +67,13 @@ to_chat(user, "You put [I] in [src].") update_icon() -/obj/structure/tank_dispenser/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) +/obj/structure/tank_dispenser/ui_state(mob/user) + return GLOB.physical_state + +/obj/structure/tank_dispenser/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "tank_dispenser", name, 275, 103, master_ui, state) + ui = new(user, src, "TankDispenser", name) ui.open() /obj/structure/tank_dispenser/ui_data(mob/user) diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index 9dcfec43bf..c5f3a089f7 100644 --- a/code/game/objects/structures/target_stake.dm +++ b/code/game/objects/structures/target_stake.dm @@ -48,10 +48,7 @@ handle_density() to_chat(user, "You slide the target into the stake.") -/obj/structure/target_stake/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/target_stake/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(pinned_target) removeTarget(user) diff --git a/code/game/objects/structures/transit_tubes/station.dm b/code/game/objects/structures/transit_tubes/station.dm index c3b388fc29..3a5eb135f4 100644 --- a/code/game/objects/structures/transit_tubes/station.dm +++ b/code/game/objects/structures/transit_tubes/station.dm @@ -58,10 +58,7 @@ qdel(R) -/obj/structure/transit_tube/station/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/transit_tube/station/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!pod_moving) if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling)) if(open_status == STATION_TUBE_OPEN) @@ -152,8 +149,8 @@ pod_moving = 0 if(!QDELETED(pod)) var/datum/gas_mixture/floor_mixture = loc.return_air() - ARCHIVE(floor_mixture) - ARCHIVE(pod.air_contents) + floor_mixture.archive() + pod.air_contents.archive() 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/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm index 04f113a0c8..cf68341b2c 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm @@ -10,9 +10,9 @@ /obj/structure/transit_tube_pod/Initialize() . = ..() - air_contents.gases[/datum/gas/oxygen] = MOLES_O2STANDARD - air_contents.gases[/datum/gas/nitrogen] = MOLES_N2STANDARD - air_contents.temperature = T20C + air_contents.set_moles(/datum/gas/oxygen, MOLES_O2STANDARD) + air_contents.set_moles(/datum/gas/nitrogen, MOLES_N2STANDARD) + air_contents.set_temperature(T20C) /obj/structure/transit_tube_pod/Destroy() @@ -69,8 +69,6 @@ empty_pod() return if(!moving) - user.changeNext_move(CLICK_CD_BREAKOUT) - user.last_special = world.time + CLICK_CD_BREAKOUT to_chat(user, "You start trying to escape from the pod...") if(do_after(user, 600, target = src)) to_chat(user, "You manage to open the pod.") @@ -181,4 +179,4 @@ return /obj/structure/transit_tube_pod/return_temperature() - return air_contents.temperature + return air_contents.return_temperature() diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 5eecc6962a..c52249686a 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -13,6 +13,8 @@ var/mob/living/swirlie = null //the mob being given a swirlie var/buildstacktype = /obj/item/stack/sheet/metal //they're metal now, shut up var/buildstackamount = 1 + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE /obj/structure/toilet/Initialize() . = ..() @@ -26,18 +28,16 @@ AM.forceMove(loc) return ..() -/obj/structure/toilet/attack_hand(mob/living/user) +/obj/structure/toilet/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return if(swirlie) - user.changeNext_move(CLICK_CD_MELEE) playsound(src.loc, "swing_hit", 25, 1) swirlie.visible_message("[user] slams the toilet seat onto [swirlie]'s head!", "[user] slams the toilet seat onto your head!", "You hear reverberating porcelain.") swirlie.adjustBruteLoss(5) else if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling)) - user.changeNext_move(CLICK_CD_MELEE) var/mob/living/GM = user.pulling if(user.grab_state >= GRAB_AGGRESSIVE) if(GM.loc != get_turf(src)) @@ -157,7 +157,6 @@ secret_type = /obj/effect/spawner/lootdrop/prison_loot_toilet /obj/structure/toilet/greyscale - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR buildstacktype = null @@ -168,6 +167,8 @@ icon_state = "urinal" density = FALSE anchored = TRUE + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE var/exposed = 0 // can you currently put an item inside var/obj/item/hiddenitem = null // what's in the urinal @@ -175,17 +176,13 @@ ..() hiddenitem = new /obj/item/reagent_containers/food/urinalcake -/obj/structure/urinal/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/urinal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling)) var/mob/living/GM = user.pulling if(user.grab_state >= GRAB_AGGRESSIVE) if(GM.loc != get_turf(src)) to_chat(user, "[GM.name] needs to be on [src].") return - user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] slams [GM] into [src]!", "You slam [GM] into [src]!") GM.adjustBruteLoss(8) else @@ -493,7 +490,7 @@ var/buildstacktype = /obj/item/stack/sheet/metal var/buildstackamount = 1 -/obj/structure/sink/attack_hand(mob/living/user) +/obj/structure/sink/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -582,6 +579,12 @@ G.use(1) return + if(istype(O, /obj/item/stack/ore/glass)) + new /obj/item/stack/sheet/sandblock(loc) + to_chat(user, "You wet the sand in the sink and form it into a block.") + O.use(1) + return + if(!istype(O)) return if(O.item_flags & ABSTRACT) //Abstract items like grabs won't wash. No-drop items will though because it's still technically an item in your hand. @@ -673,7 +676,7 @@ if(steps == 4 && istype(S, /obj/item/stack/sheet/mineral/wood)) if(S.use(3)) steps = 5 - desc = "A dug out well, A dug out well with out rope. Just add some cloth!" + desc = "A dug out well, A dug out well without rope. Just add some cloth!" icon_state = "well_4" return TRUE else @@ -702,13 +705,7 @@ icon_state = "puddle" resistance_flags = UNACIDABLE -/obj/structure/sink/greyscale - icon_state = "sink_greyscale" - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR - buildstacktype = null - -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/sink/puddle/attack_hand(mob/M) +/obj/structure/sink/puddle/on_attack_hand(mob/M) icon_state = "puddle-splash" . = ..() icon_state = "puddle" @@ -722,6 +719,7 @@ qdel(src) /obj/structure/sink/greyscale + icon_state = "sink_greyscale" material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR buildstacktype = null @@ -783,10 +781,7 @@ return TRUE -/obj/structure/curtain/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/curtain/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) playsound(loc, 'sound/effects/curtain.ogg', 50, 1) toggle() diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index e896f8072b..74f006296f 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -17,7 +17,6 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) layer = ABOVE_OBJ_LAYER //Just above doors pressure_resistance = 4*ONE_ATMOSPHERE anchored = TRUE //initially is 0 for tile smoothing - flags_1 = ON_BORDER_1 max_integrity = 25 var/ini_dir = null var/state = WINDOW_OUT_OF_FRAME @@ -38,8 +37,11 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) var/hitsound = 'sound/effects/Glasshit.ogg' rad_insulation = RAD_VERY_LIGHT_INSULATION rad_flags = RAD_PROTECT_CONTENTS - flags_ricochet = RICOCHET_HARD + flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1 + flags_ricochet = RICOCHET_HARD ricochet_chance_mod = 0.4 + attack_hand_speed = CLICK_CD_MELEE + attack_hand_is_action = TRUE /// Electrochromatic status var/electrochromatic_status = NOT_ELECTROCHROMATIC @@ -157,7 +159,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) return 1 /obj/structure/window/attack_tk(mob/user) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) user.visible_message("Something knocks on [src].") add_fingerprint(user) playsound(src, 'sound/effects/Glassknock.ogg', 50, 1) @@ -167,18 +169,15 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) return 1 . = ..() -/obj/structure/window/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/window/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!can_be_reached(user)) return - user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] knocks on [src].") add_fingerprint(user) playsound(src, 'sound/effects/Glassknock.ogg', 50, 1) /obj/structure/window/attack_paw(mob/user) + user.DelayNextAction() return attack_hand(user) /obj/structure/window/attack_generic(mob/user, damage_amount = 0, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) //used by attack_alien, attack_animal, and attack_slime @@ -271,29 +270,27 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) air_update_turf(TRUE) update_nearby_icons() -/obj/structure/window/proc/spraycan_paint(paint_color) - if(color_hex2num(paint_color) < 255) - set_opacity(255) - else - set_opacity(initial(opacity)) - add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) - /obj/structure/window/proc/electrochromatic_dim() if(electrochromatic_status == ELECTROCHROMATIC_DIMMED) return electrochromatic_status = ELECTROCHROMATIC_DIMMED - animate(src, color = "#222222", time = 2) - set_opacity(TRUE) + var/current = color + add_atom_colour("#222222", FIXED_COLOUR_PRIORITY) + var/newcolor = color + if(color != current) + color = current + animate(src, color = newcolor, time = 2) /obj/structure/window/proc/electrochromatic_off() if(electrochromatic_status == ELECTROCHROMATIC_OFF) return electrochromatic_status = ELECTROCHROMATIC_OFF var/current = color - update_atom_colour() + remove_atom_colour(FIXED_COLOUR_PRIORITY, "#222222") var/newcolor = color - color = current - animate(src, color = newcolor, time = 2) + if(color != current) + color = current + animate(src, color = newcolor, time = 2) /obj/structure/window/proc/remove_electrochromatic() electrochromatic_off() @@ -348,11 +345,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) GLOB.electrochromatic_window_lookup[electrochromatic_id] |= src /obj/structure/window/update_atom_colour() - if((electrochromatic_status != ELECTROCHROMATIC_OFF) && (electrochromatic_status != ELECTROCHROMATIC_DIMMED)) - return FALSE . = ..() - if(color && (color_hex2num(color) < 255)) - set_opacity(255) + if(electrochromatic_status == ELECTROCHROMATIC_DIMMED || (color && (color_hex2num(color) < 255))) + set_opacity(TRUE) else set_opacity(FALSE) @@ -840,13 +835,9 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) for (var/i in 1 to rand(1,4)) . += new /obj/item/paper/natural(location) -/obj/structure/window/paperframe/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/window/paperframe/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) if(user.a_intent != INTENT_HARM) - user.changeNext_move(CLICK_CD_MELEE) user.visible_message("[user] knocks on [src].") playsound(src, "pageturn", 50, 1) else @@ -884,3 +875,26 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup) return ..() update_icon() + +/obj/structure/window/bronze + name = "brass window" + desc = "A paper-thin pane of translucent yet reinforced brass. Nevermind, this is just weak bronze!" + icon = 'icons/obj/smooth_structures/clockwork_window.dmi' + icon_state = "clockwork_window_single" + glass_type = /obj/item/stack/tile/bronze + +/obj/structure/window/bronze/unanchored + anchored = FALSE + +/obj/structure/window/bronze/fulltile + icon_state = "clockwork_window" + canSmoothWith = null + smooth = SMOOTH_TRUE + fulltile = TRUE + flags_1 = PREVENT_CLICK_UNDER_1 + dir = FULLTILE_WINDOW_DIR + max_integrity = 50 + glass_amount = 2 + +/obj/structure/window/bronze/fulltile/unanchored + anchored = FALSE diff --git a/code/game/say.dm b/code/game/say.dm index 35a1b1d072..a5691ad11f 100644 --- a/code/game/say.dm +++ b/code/game/say.dm @@ -110,6 +110,8 @@ GLOBAL_LIST_INIT(freqtospan, list( /// Quirky citadel proc for our custom sayverbs to strip the verb out. Snowflakey as hell, say rewrite 3.0 when? /atom/movable/proc/quoteless_say_quote(input, list/spans = list(speech_span), message_mode) + if((input[1] == "!") && (length_char(input) > 1)) + return "" var/pos = findtext(input, "*") return pos? copytext(input, pos + 1) : input @@ -144,6 +146,8 @@ GLOBAL_LIST_INIT(freqtospan, list( return "[copytext_char("[freq]", 1, 4)].[copytext_char("[freq]", 4, 5)]" /atom/movable/proc/attach_spans(input, list/spans) + if((input[1] == "!") && (length(input) > 2)) + return var/customsayverb = findtext(input, "*") if(customsayverb) input = capitalize(copytext(input, customsayverb + length(input[customsayverb]))) diff --git a/code/game/sound.dm b/code/game/sound.dm index 577b058178..b012ba4e2a 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -130,6 +130,10 @@ /proc/get_sfx(soundin) if(istext(soundin)) switch(soundin) + if ("explosion_creaking") // from skyrat-ss13/skyrat13/pull/3295 + soundin = pick('sound/effects/explosioncreak1.ogg', 'sound/effects/explosioncreak2.ogg') + if ("hull_creaking") // from skyrat-ss13/skyrat13/pull/3295 + soundin = pick('sound/effects/creak1.ogg', 'sound/effects/creak2.ogg', 'sound/effects/creak3.ogg') if ("shatter") soundin = pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg') if ("explosion") @@ -226,5 +230,9 @@ soundin = pick('sound/effects/clangsmall1.ogg', 'sound/effects/clangsmall2.ogg') if("slosh") soundin = pick('sound/effects/slosh1.ogg', 'sound/effects/slosh2.ogg') + if("smcalm") + soundin = pick('sound/machines/sm/accent/normal/1.ogg', 'sound/machines/sm/accent/normal/2.ogg', 'sound/machines/sm/accent/normal/3.ogg', 'sound/machines/sm/accent/normal/4.ogg', 'sound/machines/sm/accent/normal/5.ogg', 'sound/machines/sm/accent/normal/6.ogg', 'sound/machines/sm/accent/normal/7.ogg', 'sound/machines/sm/accent/normal/8.ogg', 'sound/machines/sm/accent/normal/9.ogg', 'sound/machines/sm/accent/normal/10.ogg', 'sound/machines/sm/accent/normal/11.ogg', 'sound/machines/sm/accent/normal/12.ogg', 'sound/machines/sm/accent/normal/13.ogg', 'sound/machines/sm/accent/normal/14.ogg', 'sound/machines/sm/accent/normal/15.ogg', 'sound/machines/sm/accent/normal/16.ogg', 'sound/machines/sm/accent/normal/17.ogg', 'sound/machines/sm/accent/normal/18.ogg', 'sound/machines/sm/accent/normal/19.ogg', 'sound/machines/sm/accent/normal/20.ogg', 'sound/machines/sm/accent/normal/21.ogg', 'sound/machines/sm/accent/normal/22.ogg', 'sound/machines/sm/accent/normal/23.ogg', 'sound/machines/sm/accent/normal/24.ogg', 'sound/machines/sm/accent/normal/25.ogg', 'sound/machines/sm/accent/normal/26.ogg', 'sound/machines/sm/accent/normal/27.ogg', 'sound/machines/sm/accent/normal/28.ogg', 'sound/machines/sm/accent/normal/29.ogg', 'sound/machines/sm/accent/normal/30.ogg', 'sound/machines/sm/accent/normal/31.ogg', 'sound/machines/sm/accent/normal/32.ogg', 'sound/machines/sm/accent/normal/33.ogg') + if("smdelam") + soundin = pick('sound/machines/sm/accent/delam/1.ogg', 'sound/machines/sm/accent/normal/2.ogg', 'sound/machines/sm/accent/normal/3.ogg', 'sound/machines/sm/accent/normal/4.ogg', 'sound/machines/sm/accent/normal/5.ogg', 'sound/machines/sm/accent/normal/6.ogg', 'sound/machines/sm/accent/normal/7.ogg', 'sound/machines/sm/accent/normal/8.ogg', 'sound/machines/sm/accent/normal/9.ogg', 'sound/machines/sm/accent/normal/10.ogg', 'sound/machines/sm/accent/normal/11.ogg', 'sound/machines/sm/accent/normal/12.ogg', 'sound/machines/sm/accent/normal/13.ogg', 'sound/machines/sm/accent/normal/14.ogg', 'sound/machines/sm/accent/normal/15.ogg', 'sound/machines/sm/accent/normal/16.ogg', 'sound/machines/sm/accent/normal/17.ogg', 'sound/machines/sm/accent/normal/18.ogg', 'sound/machines/sm/accent/normal/19.ogg', 'sound/machines/sm/accent/normal/20.ogg', 'sound/machines/sm/accent/normal/21.ogg', 'sound/machines/sm/accent/normal/22.ogg', 'sound/machines/sm/accent/normal/23.ogg', 'sound/machines/sm/accent/normal/24.ogg', 'sound/machines/sm/accent/normal/25.ogg', 'sound/machines/sm/accent/normal/26.ogg', 'sound/machines/sm/accent/normal/27.ogg', 'sound/machines/sm/accent/normal/28.ogg', 'sound/machines/sm/accent/normal/29.ogg', 'sound/machines/sm/accent/normal/30.ogg', 'sound/machines/sm/accent/normal/31.ogg', 'sound/machines/sm/accent/normal/32.ogg', 'sound/machines/sm/accent/normal/33.ogg') //END OF CIT CHANGES return soundin diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 38e0839617..66e7ebd424 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -148,6 +148,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( . = ..() if (!.) // changeturf failed or didn't do anything QDEL_NULL(stashed_air) + update_air_ref() return var/turf/open/newTurf = . newTurf.air.copy_from(stashed_air) @@ -308,24 +309,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( return var/datum/gas_mixture/total = new//Holders to assimilate air from nearby turfs - var/list/total_gases = total.gases for(var/T in atmos_adjacent_turfs) var/turf/open/S = T if(!S.air) continue - var/list/S_gases = S.air.gases - for(var/id in S_gases) - total_gases[id] += S_gases[id] - total.temperature += S.air.temperature + total.merge(S.air) - air.copy_from(total) - - var/list/air_gases = air.gases - for(var/id in air_gases) - air_gases[id] /= turf_count //Averages contents of the turfs, ignoring walls and the like - - air.temperature /= turf_count + air.copy_from(total.remove_ratio(1/turf_count)) SSair.add_to_active(src) /turf/proc/ReplaceWithLattice() diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 24af2ed5bd..be0c444541 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -7,9 +7,14 @@ rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE rad_insulation = RAD_MEDIUM_INSULATION +/turf/closed/Initialize() + . = ..() + update_air_ref() + /turf/closed/AfterChange() . = ..() SSair.high_pressure_delta -= src + update_air_ref() /turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) return FALSE @@ -24,6 +29,9 @@ icon = 'icons/turf/walls.dmi' explosion_block = 50 +/turf/closed/indestructible/rust_heretic_act() + return + /turf/closed/indestructible/TerraformTurf(path, new_baseturf, flags, defer_change = FALSE, ignore_air = FALSE) return @@ -78,7 +86,7 @@ . = ..() if(.) switch(var_name) - if("icon") + if(NAMEOF(src, icon)) SStitle.icon = icon /turf/closed/indestructible/riveted @@ -87,6 +95,11 @@ smooth = SMOOTH_TRUE explosion_block = INFINITY +/turf/closed/indestructible/syndicate + icon = 'icons/turf/walls/plastitanium_wall.dmi' + icon_state = "map-shuttle" + smooth = SMOOTH_TRUE + /turf/closed/indestructible/riveted/uranium icon = 'icons/turf/walls/uranium_wall.dmi' icon_state = "uranium" @@ -188,13 +201,13 @@ /turf/closed/indestructible/rock/glacierrock name = "unaturally hard ice wall" - desc = "Ice, hardened over thousands of years, you're not breaking through this." + desc = "Ice, hardened over thousands of years, you're not breaking through this." icon = 'icons/turf/walls.dmi' icon_state = "snow_rock" /turf/closed/indestructible/rock/glacierrock/blue name = "blue ice wall" - desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color." + desc = "The incredible compressive forces that formed this sturdy ice wall gave it a blue color." icon = 'icons/turf/walls.dmi' icon_state = "ice" canSmoothWith = list(/turf/closed/indestructible/rock/glacierrock/blue) diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index b81c5be44c..6552e29246 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -199,7 +199,7 @@ flash_color(L, flash_color = "#C80000", flash_time = 10) /turf/open/Initalize_Atmos(times_fired) - excited = 0 + set_excited(FALSE) update_visuals() current_cycle = times_fired @@ -207,19 +207,19 @@ for(var/i in atmos_adjacent_turfs) var/turf/open/enemy_tile = i var/datum/gas_mixture/enemy_air = enemy_tile.return_air() - if(!excited && air.compare(enemy_air)) + if(!get_excited() && air.compare(enemy_air)) //testing("Active turf found. Return value of compare(): [is_active]") - excited = TRUE + set_excited(TRUE) SSair.active_turfs |= src /turf/open/proc/GetHeatCapacity() . = air.heat_capacity() /turf/open/proc/GetTemperature() - . = air.temperature + . = air.return_temperature() /turf/open/proc/TakeTemperature(temp) - air.temperature += temp + air.set_temperature(air.return_temperature() + temp) air_update_turf() /turf/open/proc/freon_gas_act() @@ -304,9 +304,8 @@ /turf/open/rad_act(pulse_strength) . = ..() - if (air.gases[/datum/gas/carbon_dioxide] && air.gases[/datum/gas/oxygen]) - pulse_strength = min(pulse_strength,air.gases[/datum/gas/carbon_dioxide]*1000,air.gases[/datum/gas/oxygen]*2000) //Ensures matter is conserved properly - air.gases[/datum/gas/carbon_dioxide]=max(air.gases[/datum/gas/carbon_dioxide]-(pulse_strength/1000),0) - air.gases[/datum/gas/oxygen]=max(air.gases[/datum/gas/oxygen]-(pulse_strength/2000),0) - air.gases[/datum/gas/pluoxium]+=(pulse_strength/4000) - GAS_GARBAGE_COLLECT(air.gases) + if (air.get_moles(/datum/gas/carbon_dioxide) && air.get_moles(/datum/gas/oxygen)) + pulse_strength = min(pulse_strength,air.get_moles(/datum/gas/carbon_dioxide)*1000,air.get_moles(/datum/gas/oxygen)*2000) //Ensures matter is conserved properly + air.set_moles(/datum/gas/carbon_dioxide, max(air.get_moles(/datum/gas/carbon_dioxide)-(pulse_strength/1000),0)) + air.set_moles(/datum/gas/oxygen, max(air.get_moles(/datum/gas/oxygen)-(pulse_strength/2000),0)) + air.adjust_moles(/datum/gas/pluoxium, pulse_strength/4000) diff --git a/code/game/turfs/openspace/openspace.dm b/code/game/turfs/openspace/openspace.dm index 90fab29611..ea539ce5b5 100644 --- a/code/game/turfs/openspace/openspace.dm +++ b/code/game/turfs/openspace/openspace.dm @@ -11,66 +11,47 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr mouse_opacity = MOUSE_OPACITY_TRANSPARENT layer = SPLASHSCREEN_LAYER -/turf/open/openspace +/turf/open/transparent/openspace name = "open space" desc = "Watch your step!" icon_state = "transparent" - baseturfs = /turf/open/openspace + baseturfs = /turf/open/transparent/openspace CanAtmosPassVertical = ATMOS_PASS_YES //mouse_opacity = MOUSE_OPACITY_TRANSPARENT var/can_cover_up = TRUE var/can_build_on = TRUE -/turf/open/openspace/debug/update_multiz() +/turf/open/transparent/openspace/airless + initial_gas_mix = AIRLESS_ATMOS + +/turf/open/transparent/openspace/debug/update_multiz() ..() return TRUE -/turf/open/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker +///No bottom level for openspace. +/turf/open/transparent/openspace/show_bottom_level() + return FALSE + +/turf/open/transparent/openspace/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker . = ..() - plane = OPENSPACE_PLANE - layer = OPENSPACE_LAYER + vis_contents += GLOB.openspace_backdrop_one_for_all //Special grey square for projecting backdrop darkness filter on it. - return INITIALIZE_HINT_LATELOAD -/turf/open/openspace/LateInitialize() - update_multiz(TRUE, TRUE) +/turf/open/transparent/openspace/can_have_cabling() + if(locate(/obj/structure/lattice/catwalk, src)) + return TRUE + return FALSE -/turf/open/openspace/Destroy() - vis_contents.len = 0 - return ..() - -/turf/open/openspace/update_multiz(prune_on_fail = FALSE, init = FALSE) - . = ..() - var/turf/T = below() - if(!T) - vis_contents.len = 0 - if(prune_on_fail) - ChangeTurf(/turf/open/floor/plating) - return FALSE - if(init) - vis_contents += T +/turf/open/transparent/openspace/zAirIn() return TRUE -/turf/open/openspace/multiz_turf_del(turf/T, dir) - if(dir != DOWN) - return - update_multiz() - -/turf/open/openspace/multiz_turf_new(turf/T, dir) - if(dir != DOWN) - return - update_multiz() - -/turf/open/openspace/zAirIn() +/turf/open/transparent/openspace/zAirOut() return TRUE -/turf/open/openspace/zAirOut() +/turf/open/transparent/openspace/zPassIn(atom/movable/A, direction, turf/source) return TRUE -/turf/open/openspace/zPassIn(atom/movable/A, direction, turf/source) - return TRUE - -/turf/open/openspace/zPassOut(atom/movable/A, direction, turf/destination) +/turf/open/transparent/openspace/zPassOut(atom/movable/A, direction, turf/destination) if(A.anchored) return FALSE for(var/obj/O in contents) @@ -78,13 +59,13 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr return FALSE return TRUE -/turf/open/openspace/proc/CanCoverUp() +/turf/open/transparent/openspace/proc/CanCoverUp() return can_cover_up -/turf/open/openspace/proc/CanBuildHere() +/turf/open/transparent/openspace/proc/CanBuildHere() return can_build_on -/turf/open/openspace/attackby(obj/item/C, mob/user, params) +/turf/open/transparent/openspace/attackby(obj/item/C, mob/user, params) ..() if(!CanBuildHere()) return @@ -98,14 +79,14 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr if(L) if(R.use(1)) to_chat(user, "You construct a catwalk.") - playsound(src, 'sound/weapons/genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) new/obj/structure/lattice/catwalk(src) else to_chat(user, "You need two rods to build a catwalk!") return if(R.use(1)) to_chat(user, "You construct a lattice.") - playsound(src, 'sound/weapons/genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) ReplaceWithLattice() else to_chat(user, "You need one rod to build a lattice.") @@ -118,7 +99,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr var/obj/item/stack/tile/plasteel/S = C if(S.use(1)) qdel(L) - playsound(src, 'sound/weapons/genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) to_chat(user, "You build a floor.") PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else @@ -126,7 +107,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr else to_chat(user, "The plating is going to need some support! Place metal rods first.") -/turf/open/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) +/turf/open/transparent/openspace/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) if(!CanBuildHere()) return FALSE @@ -139,7 +120,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr return list("mode" = RCD_FLOORWALL, "delay" = 0, "cost" = 3) return FALSE -/turf/open/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) +/turf/open/transparent/openspace/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) switch(passed_mode) if(RCD_FLOORWALL) to_chat(user, "You build a floor.") @@ -147,12 +128,12 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr return TRUE return FALSE -/turf/open/openspace/icemoon +/turf/open/transparent/openspace/icemoon name = "ice chasm" - baseturfs = /turf/open/openspace/icemoon - can_cover_up = FALSE - can_build_on = FALSE + baseturfs = /turf/open/transparent/openspace/icemoon + can_cover_up = TRUE + can_build_on = TRUE initial_gas_mix = ICEMOON_DEFAULT_ATMOS -/turf/open/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target) +/turf/open/transparent/openspace/icemoon/can_zFall(atom/movable/A, levels = 1, turf/target) return TRUE diff --git a/code/game/turfs/openspace/transparent.dm b/code/game/turfs/openspace/transparent.dm new file mode 100644 index 0000000000..8efc60a15b --- /dev/null +++ b/code/game/turfs/openspace/transparent.dm @@ -0,0 +1,95 @@ +/turf/open/transparent + baseturfs = /turf/open/transparent/openspace + intact = FALSE //this means wires go on top + +/turf/open/transparent/Initialize() // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker + . = ..() + plane = OPENSPACE_PLANE + layer = OPENSPACE_LAYER + + return INITIALIZE_HINT_LATELOAD + +/turf/open/transparent/LateInitialize() + update_multiz(TRUE, TRUE) + +/turf/open/transparent/Destroy() + vis_contents.len = 0 + return ..() + +/turf/open/transparent/update_multiz(prune_on_fail = FALSE, init = FALSE) + . = ..() + var/turf/T = below() + if(!T) + vis_contents.len = 0 + if(!show_bottom_level() && prune_on_fail) //If we cant show whats below, and we prune on fail, change the turf to plating as a fallback + ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) + return FALSE + if(init) + vis_contents += T + return TRUE + +/turf/open/transparent/multiz_turf_del(turf/T, dir) + if(dir != DOWN) + return + update_multiz() + +/turf/open/transparent/multiz_turf_new(turf/T, dir) + if(dir != DOWN) + return + update_multiz() + +///Called when there is no real turf below this turf +/turf/open/transparent/proc/show_bottom_level() + var/turf/path = SSmapping.level_trait(z, ZTRAIT_BASETURF) || /turf/open/space + if(!ispath(path)) + path = text2path(path) + if(!ispath(path)) + warning("Z-level [z] has invalid baseturf '[SSmapping.level_trait(z, ZTRAIT_BASETURF)]'") + path = /turf/open/space + var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = TURF_LAYER, plane = PLANE_SPACE) + underlays += underlay_appearance + return TRUE + + +/turf/open/transparent/glass + name = "Glass floor" + desc = "Dont jump on it, or do, I'm not your mom." + icon = 'icons/turf/floors/glass.dmi' + icon_state = "floor_glass" + smooth = SMOOTH_MORE + var/floor_tile = /obj/item/stack/sheet/glass + canSmoothWith = list(/turf/open/transparent/glass, /turf/open/transparent/glass/reinforced) + footstep = FOOTSTEP_PLATING + barefootstep = FOOTSTEP_HARD_BAREFOOT + clawfootstep = FOOTSTEP_HARD_CLAW + heavyfootstep = FOOTSTEP_GENERIC_HEAVY + +/turf/open/transparent/glass/Initialize() + icon_state = "" //Prevent the normal icon from appearing behind the smooth overlays + return ..() + +/turf/open/transparent/glass/wrench_act(mob/living/user, obj/item/I) + to_chat(user, "You begin removing glass...") + if(I.use_tool(src, user, 30, volume=80)) + if(!istype(src, /turf/open/transparent/glass)) + return TRUE + if(floor_tile) + new floor_tile(src, 2) + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) + return TRUE + +/turf/open/transparent/glass/reinforced + name = "Reinforced glass floor" + desc = "Do jump on it, it can take it." + icon = 'icons/turf/floors/reinf_glass.dmi' + floor_tile = /obj/item/stack/sheet/rglass + +/turf/open/transparent/glass/reinforced/wrench_act(mob/living/user, obj/item/I) + to_chat(user, "You begin removing reinforced glass...") + if(I.use_tool(src, user, 30, volume=80)) + if(!istype(src, /turf/open/transparent/glass/reinforced)) + return TRUE + if(floor_tile) + new floor_tile(src, 2) + ScrapeAway(flags = CHANGETURF_INHERIT_AIR) + return TRUE diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 9f5ce679f9..758f824727 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -162,7 +162,7 @@ return 0 /turf/open/floor/crowbar_act(mob/living/user, obj/item/I) - return intact ? pry_tile(I, user) : FALSE + return intact ? FORCE_BOOLEAN(pry_tile(I, user)) : FALSE /turf/open/floor/proc/try_replace_tile(obj/item/stack/tile/T, mob/user, params) if(T.turf_type == type) @@ -189,9 +189,12 @@ if(user && !silent) to_chat(user, "You remove the floor tile.") if(floor_tile && make_tile) - new floor_tile(src) + spawn_tile() return make_plating() +/turf/open/floor/proc/spawn_tile() + new floor_tile(src) + /turf/open/floor/singularity_pull(S, current_size) . = ..() switch(current_size) @@ -205,7 +208,7 @@ if(floor_tile) if(prob(70)) remove_tile() - else if(prob(50)) + else if(prob(50) && (/turf/open/space in baseturfs)) ReplaceWithLattice() /turf/open/floor/narsie_act(force, ignore_mobs, probability = 20) @@ -293,3 +296,13 @@ return TRUE return FALSE + +/turf/open/floor/material + name = "floor" + icon_state = "materialfloor" + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + +/turf/open/floor/material/spawn_tile() + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(src, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index 2f4e2e0eee..5024a4bada 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -26,7 +26,8 @@ /turf/open/floor/wood/screwdriver_act(mob/living/user, obj/item/I) if(..()) return TRUE - return pry_tile(I, user) + . = STOP_ATTACK_PROC_CHAIN + pry_tile(I, user) /turf/open/floor/wood/try_replace_tile(obj/item/stack/tile/T, mob/user, params) if(T.turf_type == type) @@ -62,6 +63,11 @@ to_chat(user, "You forcefully pry off the planks, destroying them in the process.") return make_plating() +/turf/open/floor/wood/rust_heretic_act() + if(prob(70)) + new /obj/effect/temp_visual/glowing_rune(src) + ChangeTurf(/turf/open/floor/plating/rust) + /turf/open/floor/wood/cold temperature = 255.37 @@ -157,7 +163,7 @@ planetary_atmos = TRUE floor_tile = null initial_gas_mix = FROZEN_ATMOS - slowdown = 1.5 //So digging it out paths are usefull. + slowdown = 1.5 //So digging it out paths are useful. bullet_sizzle = TRUE footstep = FOOTSTEP_SAND barefootstep = FOOTSTEP_SAND diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index f9376c0672..4bca25f96c 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -52,10 +52,7 @@ set_light(0) return ..() -/turf/open/floor/light/attack_hand(mob/user) - . = ..() - if(.) - return +/turf/open/floor/light/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!can_modify_colour) return if(!on) diff --git a/code/game/turfs/simulated/floor/mineral_floor.dm b/code/game/turfs/simulated/floor/mineral_floor.dm index f0ac0053ce..fe6ed2da9b 100644 --- a/code/game/turfs/simulated/floor/mineral_floor.dm +++ b/code/game/turfs/simulated/floor/mineral_floor.dm @@ -58,6 +58,12 @@ if(exposed_temperature > 300) PlasmaBurn(exposed_temperature) +// Plasma floor that can't be removed, for disco + +/turf/open/floor/mineral/plasma/disco + name = "disco floor" +/turf/open/floor/mineral/plasma/disco/crowbar_act(mob/living/user, obj/item/I) + return //GOLD @@ -149,7 +155,7 @@ if(!.) honk() -/turf/open/floor/mineral/bananium/attack_hand(mob/user) +/turf/open/floor/mineral/bananium/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) .=..() if(!.) honk() @@ -202,7 +208,7 @@ if(!.) radiate() -/turf/open/floor/mineral/uranium/attack_hand(mob/user) +/turf/open/floor/mineral/uranium/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) .=..() if(!.) radiate() diff --git a/code/game/turfs/simulated/floor/misc_floor.dm b/code/game/turfs/simulated/floor/misc_floor.dm index f6e70f8ef5..c70332eacb 100644 --- a/code/game/turfs/simulated/floor/misc_floor.dm +++ b/code/game/turfs/simulated/floor/misc_floor.dm @@ -259,7 +259,7 @@ desc = "Some heavy bronze tiles." icon = 'icons/obj/clockwork_objects.dmi' icon_state = "clockwork_floor" - floor_tile = /obj/item/stack/tile/bronze + floor_tile = /obj/item/stack/sheet/bronze /turf/open/floor/padded name = "padded floor" @@ -267,3 +267,15 @@ icon = 'icons/turf/floors.dmi' icon_state = "floor_padded" floor_tile = /obj/item/stack/tile/padded + +/turf/open/floor/plating/rust + name = "rusted plating" + desc = "Corrupted steel." + icon_state = "plating_rust" + footstep = FOOTSTEP_RUST + barefootstep = FOOTSTEP_RUST + clawfootstep = FOOTSTEP_RUST + heavyfootstep = FOOTSTEP_RUST + +/turf/open/floor/plating/rust/rust_heretic_act() + return diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm index af48160ef1..614c63a14c 100644 --- a/code/game/turfs/simulated/floor/plasteel_floor.dm +++ b/code/game/turfs/simulated/floor/plasteel_floor.dm @@ -8,6 +8,11 @@ . = ..() . += "There's a small crack on the edge of it." +/turf/open/floor/plasteel/rust_heretic_act() + if(prob(70)) + new /obj/effect/temp_visual/glowing_rune(src) + ChangeTurf(/turf/open/floor/plating/rust) + /turf/open/floor/plasteel/update_icon() if(!..()) return 0 diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 8e0eace9cd..35ee06a584 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -66,6 +66,40 @@ R.use(2) to_chat(user, "You reinforce the floor.") return + if(istype(C, /obj/item/stack/sheet/glass)) + if(broken || burnt) + to_chat(user, "Repair the plating first!") + return + var/obj/item/stack/sheet/glass/G = C + if (G.get_amount() < 2) + to_chat(user, "You need two glass sheets to make a glass floor!") + return + else + to_chat(user, "You begin adding glass to the floor...") + if(do_after(user, 5, target = src)) + if (G.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass)) + PlaceOnTop(/turf/open/transparent/glass, flags = CHANGETURF_INHERIT_AIR) + playsound(src, 'sound/items/deconstruct.ogg', 80, 1) + G.use(2) + to_chat(user, "You add glass to the floor.") + return + if(istype(C, /obj/item/stack/sheet/rglass)) + if(broken || burnt) + to_chat(user, "Repair the plating first!") + return + var/obj/item/stack/sheet/rglass/RG = C + if (RG.get_amount() < 2) + to_chat(user, "You need two reinforced glass sheets to make a reinforced glass floor!") + return + else + to_chat(user, "You begin adding reinforced glass to the floor...") + if(do_after(user, 10, target = src)) + if (RG.get_amount() >= 2 && !istype(src, /turf/open/transparent/glass/reinforced)) + PlaceOnTop(/turf/open/transparent/glass/reinforced, flags = CHANGETURF_INHERIT_AIR) + playsound(src, 'sound/items/deconstruct.ogg', 80, 1) + RG.use(2) + to_chat(user, "You add reinforced glass to the floor.") + return else if(istype(C, /obj/item/stack/tile)) if(!broken && !burnt) for(var/obj/O in src) @@ -76,11 +110,15 @@ var/obj/item/stack/tile/W = C if(!W.use(1)) return - var/turf/open/floor/T = PlaceOnTop(W.turf_type, flags = CHANGETURF_INHERIT_AIR) - if(istype(W, /obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow - var/obj/item/stack/tile/light/L = W - var/turf/open/floor/light/F = T - F.state = L.state + if(istype(W, /obj/item/stack/tile/material)) + var/turf/newturf = PlaceOnTop(/turf/open/floor/material, flags = CHANGETURF_INHERIT_AIR) + newturf.set_custom_materials(W.custom_materials) + else if(W.turf_type) + var/turf/open/floor/T = PlaceOnTop(W.turf_type, flags = CHANGETURF_INHERIT_AIR) + if(istype(W, /obj/item/stack/tile/light)) //TODO: get rid of this ugly check somehow + var/obj/item/stack/tile/light/L = W + var/turf/open/floor/light/F = T + F.state = L.state playsound(src, 'sound/weapons/genhit.ogg', 50, 1) else to_chat(user, "This section is too damaged to support a tile! Use a welder to fix the damage.") @@ -94,6 +132,11 @@ return TRUE +/turf/open/floor/plating/rust_heretic_act() + if(prob(70)) + new /obj/effect/temp_visual/glowing_rune(src) + ChangeTurf(/turf/open/floor/plating/rust) + /turf/open/floor/plating/make_plating() return @@ -120,7 +163,7 @@ ChangeTurf(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else playsound(src, 'sound/weapons/tap.ogg', 100, TRUE) //The attack sound is muffled by the foam itself - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) user.do_attack_animation(src) if(prob(I.force * 20 - 25)) user.visible_message("[user] smashes through [src]!", \ diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index 1fbeee7523..6e7dbaf904 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -149,6 +149,8 @@ var/list/megafauna_spawn_list /// Flora that can spawn in the tunnel, weighted list var/list/flora_spawn_list + //terrain to spawn weighted list + var/list/terrain_spawn_list /// Turf type to choose when spawning in tunnel at 1% chance, weighted list var/list/choose_turf_type /// if the tunnel should keep being created @@ -230,7 +232,8 @@ megafauna_spawn_list = list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = SPAWN_BUBBLEGUM) if (!flora_spawn_list) flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2) - + if(!terrain_spawn_list) + terrain_spawn_list = list(/obj/structure/geyser/random = 1) . = ..() if(!has_data) produce_tunnel_from_data() @@ -334,8 +337,19 @@ spawned_flora = SpawnFlora(T) if(!spawned_flora) // no rocks beneath mob spawners / mobs. SpawnMonster(T) + SpawnTerrain(T) T.ChangeTurf(turf_type, null, CHANGETURF_IGNORE_AIR) +/turf/open/floor/plating/asteroid/airless/cave/proc/SpawnTerrain(turf/T) + if(prob(1)) + if(istype(loc, /area/mine/explored) || istype(loc, /area/lavaland/surface/outdoors/explored)) + return + var/randumb = pickweight(terrain_spawn_list) + for(var/obj/structure/geyser/F in range(7, T)) + if(istype(F, randumb)) + return + new randumb(T) + /// Spawns a random mob or megafauna in the tunnel /turf/open/floor/plating/asteroid/airless/cave/proc/SpawnMonster(turf/T) if(!isarea(loc)) diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index 7816341a0a..03045674e4 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -89,10 +89,7 @@ /turf/open/floor/engine/attack_paw(mob/user) return attack_hand(user) -/turf/open/floor/engine/attack_hand(mob/user) - . = ..() - if(.) - return +/turf/open/floor/engine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) user.Move_Pulled(src) //air filled floors; used in atmos pressure chambers diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 048394b942..0f1ec6fa85 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -803,7 +803,7 @@ stage = GIBTONITE_DETONATE explosion(bombturf,1,2,5, adminlog = 0) if(stage == GIBTONITE_STABLE) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore. - var/obj/item/twohanded/required/gibtonite/G = new (src) + var/obj/item/gibtonite/G = new (src) if(det_time <= 0) G.quality = 3 G.icon_state = "Gibtonite ore 3" diff --git a/code/game/turfs/simulated/wall/material_walls.dm b/code/game/turfs/simulated/wall/material_walls.dm new file mode 100644 index 0000000000..d3952609e0 --- /dev/null +++ b/code/game/turfs/simulated/wall/material_walls.dm @@ -0,0 +1,22 @@ +/turf/closed/wall/material + name = "wall" + desc = "A huge chunk of material used to separate rooms." + icon = 'icons/turf/walls/materialwall.dmi' + icon_state = "wall" + canSmoothWith = list(/turf/closed/wall/material) + smooth = SMOOTH_TRUE + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS + +/turf/closed/wall/material/break_wall() + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(src, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) + return new girder_type(src) + +/turf/closed/wall/material/devastate_wall() + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(src, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) + +/turf/closed/wall/material/mat_update_desc(mat) + desc = "A huge chunk of [mat] used to separate rooms." diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm index 5c74eb4ecc..ed48c24462 100644 --- a/code/game/turfs/simulated/wall/mineral_walls.dm +++ b/code/game/turfs/simulated/wall/mineral_walls.dm @@ -72,7 +72,7 @@ return return -/turf/closed/wall/mineral/uranium/attack_hand(mob/user) +/turf/closed/wall/mineral/uranium/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) radiate() . = ..() @@ -136,7 +136,7 @@ /turf/closed/wall/mineral/wood/attackby(obj/item/W, mob/user) if(W.sharpness && W.force) var/duration = (48/W.force) * 2 //In seconds, for now. - if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/twohanded/fireaxe)) + if(istype(W, /obj/item/hatchet) || istype(W, /obj/item/fireaxe)) duration /= 4 //Much better with hatchets and axes. var/src_type = type if(do_after(user, duration*10, target=src) && type == src_type) //Into deciseconds. @@ -192,6 +192,7 @@ icon_state = "map-shuttle" explosion_block = 3 flags_1 = CAN_BE_DIRTY_1 | DEFAULT_RICOCHET_1 + flags_ricochet = RICOCHET_SHINY | RICOCHET_HARD sheet_type = /obj/item/stack/sheet/mineral/titanium smooth = SMOOTH_MORE|SMOOTH_DIAGONAL canSmoothWith = list(/turf/closed/wall/mineral/titanium, /obj/machinery/door/airlock/shuttle, /obj/machinery/door/airlock, /obj/structure/window/shuttle, /obj/structure/shuttle/engine/heater, /obj/structure/falsewall/titanium) diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm index d445be91cb..e4d991a082 100644 --- a/code/game/turfs/simulated/wall/misc_walls.dm +++ b/code/game/turfs/simulated/wall/misc_walls.dm @@ -188,17 +188,25 @@ icon = 'icons/turf/walls/rusty_wall.dmi' hardness = 45 +/turf/closed/wall/rust/rust_heretic_act() + ScrapeAway() + /turf/closed/wall/r_wall/rust name = "rusted reinforced wall" desc = "A huge chunk of rusted reinforced metal." icon = 'icons/turf/walls/rusty_reinforced_wall.dmi' hardness = 15 +/turf/closed/wall/r_wall/rust/rust_heretic_act() + if(prob(50)) + return + ScrapeAway() + /turf/closed/wall/mineral/bronze name = "clockwork wall" desc = "A huge chunk of bronze, decorated like gears and cogs." icon = 'icons/turf/walls/clockwork_wall.dmi' icon_state = "clockwork_wall" - sheet_type = /obj/item/stack/tile/bronze + sheet_type = /obj/item/stack/sheet/bronze sheet_amount = 2 girder_type = /obj/structure/girder/bronze diff --git a/code/game/turfs/simulated/wall/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm index a1d2c1757c..5e60f65ccc 100644 --- a/code/game/turfs/simulated/wall/reinf_walls.dm +++ b/code/game/turfs/simulated/wall/reinf_walls.dm @@ -36,7 +36,8 @@ new /obj/item/stack/sheet/metal(src, 2) /turf/closed/wall/r_wall/attack_animal(mob/living/simple_animal/M) - M.changeNext_move(CLICK_CD_MELEE) + if(!M.CheckActionCooldown()) + return M.do_attack_animation(src) if(!M.environment_smash) return @@ -46,6 +47,7 @@ else playsound(src, 'sound/effects/bang.ogg', 50, 1) to_chat(M, "This wall is far too strong for you to destroy.") + M.DelayNextAction() /turf/closed/wall/r_wall/try_destroy(obj/item/I, mob/user, turf/T) if(istype(I, /obj/item/pickaxe/drill/jackhammer)) @@ -233,6 +235,13 @@ if(the_rcd.canRturf) return ..() +/turf/closed/wall/r_wall/rust_heretic_act() + if(prob(50)) + return + if(prob(70)) + new /obj/effect/temp_visual/glowing_rune(src) + ChangeTurf(/turf/closed/wall/r_wall/rust) + /turf/closed/wall/r_wall/syndicate name = "hull" desc = "The armored hull of an ominous looking ship." diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index b01a1df2c0..9ff4f668a4 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -6,9 +6,12 @@ icon = 'icons/turf/walls/wall.dmi' icon_state = "wall" explosion_block = 1 - + flags_1 = DEFAULT_RICOCHET_1 + flags_ricochet = RICOCHET_HARD thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m plasteel wall + attack_hand_speed = 8 + attack_hand_is_action = TRUE baseturfs = /turf/open/floor/plating @@ -113,41 +116,65 @@ return FALSE /turf/closed/wall/attack_paw(mob/living/user) - user.changeNext_move(CLICK_CD_MELEE) return attack_hand(user) - /turf/closed/wall/attack_animal(mob/living/simple_animal/M) - M.changeNext_move(CLICK_CD_MELEE) + if(!M.CheckActionCooldown(CLICK_CD_MELEE)) + return + M.DelayNextAction() M.do_attack_animation(src) if((M.environment_smash & ENVIRONMENT_SMASH_WALLS) || (M.environment_smash & ENVIRONMENT_SMASH_RWALLS)) playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) dismantle_wall(1) return -/turf/closed/wall/attack_hulk(mob/user, does_attack_animation = 0) - ..(user, 1) +/turf/closed/wall/attack_hulk(mob/living/carbon/user) + ..() + var/obj/item/bodypart/arm = user.hand_bodyparts[user.active_hand_index] + if(!arm) + return + if(arm.disabled) + return if(prob(hardness)) - playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) + playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") + hulk_recoil(arm, user) dismantle_wall(1) + else - playsound(src, 'sound/effects/bang.ogg', 50, 1) + playsound(src, 'sound/effects/bang.ogg', 50, TRUE) add_dent(WALL_DENT_HIT) - to_chat(user, text("You punch the wall.")) + user.visible_message("[user] smashes \the [src]!", \ + "You smash \the [src]!", \ + "You hear a booming smash!") return TRUE -/turf/closed/wall/attack_hand(mob/user) - . = ..() - if(.) +/** + *Deals damage back to the hulk's arm. + * + *When a hulk manages to break a wall using their hulk smash, this deals back damage to the arm used. + *This is in its own proc just to be easily overridden by other wall types. Default allows for three + *smashed walls per arm. Also, we use CANT_WOUND here because wounds are random. Wounds are applied + *by hulk code based on arm damage and checked when we call break_an_arm(). + *Arguments: + **arg1 is the arm to deal damage to. + **arg2 is the hulk + */ +/turf/closed/wall/proc/hulk_recoil(obj/item/bodypart/arm, mob/living/carbon/human/hulkman, var/damage = 20) + arm.receive_damage(brute = damage, blocked = 0, wound_bonus = CANT_WOUND) + var/datum/mutation/human/hulk/smasher = locate(/datum/mutation/human/hulk) in hulkman.dna.mutations + if(!smasher || !damage) //sanity check but also snow and wood walls deal no recoil damage, so no arm breaky return - user.changeNext_move(CLICK_CD_MELEE) + smasher.break_an_arm(arm) + +/turf/closed/wall/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) to_chat(user, "You push the wall but nothing happens!") playsound(src, 'sound/weapons/genhit.ogg', 25, 1) add_fingerprint(user) /turf/closed/wall/attackby(obj/item/W, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return if (!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") return @@ -156,6 +183,7 @@ if(!isturf(user.loc)) return //can't do this stuff whilst inside objects and such + user.DelayNextAction() add_fingerprint(user) var/turf/T = user.loc //get user's location for delay checks @@ -297,4 +325,9 @@ add_overlay(dent_decals) +/turf/closed/wall/rust_heretic_act() + if(prob(70)) + new /obj/effect/temp_visual/glowing_rune(src) + ChangeTurf(/turf/closed/wall/rust) + #undef MAX_DENT_DECALS diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index 26daa32107..0e028ed4af 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -27,6 +27,7 @@ /turf/open/space/Initialize() icon_state = SPACE_ICON_STATE air = space_gas + update_air_ref() vis_contents.Cut() //removes inherited overlays visibilityChanged() @@ -132,10 +133,13 @@ else to_chat(user, "The plating is going to need some support! Place metal rods first.") -/turf/open/space/Entered(atom/movable/A) - ..() - if ((!(A) || src != A.loc)) - return +/turf/open/space/Entered(atom/movable/A, atom/OldLoc) + . = ..() + + var/turf/old = get_turf(OldLoc) + if(!isspaceturf(old) && ismob(A)) + var/mob/M = A + M.update_gravity(M.mob_has_gravity()) if(destination_z && destination_x && destination_y && !(A.pulledby || !A.can_be_z_moved)) var/tx = destination_x @@ -169,6 +173,12 @@ stoplag()//Let a diagonal move finish, if necessary A.newtonian_move(A.inertia_dir) +/turf/open/space/Exited(atom/movable/AM, atom/OldLoc) + . = ..() + var/turf/old = get_turf(OldLoc) + if(!isspaceturf(old) && ismob(AM)) + var/mob/M = AM + M.update_gravity(M.mob_has_gravity()) /turf/open/space/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent) return diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 88f6dd6962..55d945535d 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -85,6 +85,9 @@ if (opacity) has_opaque_atom = TRUE + // apply materials properly from the default custom_materials value + set_custom_materials(custom_materials) + ComponentInitialize() return INITIALIZE_HINT_NORMAL @@ -119,10 +122,7 @@ requires_activation = FALSE ..() -/turf/attack_hand(mob/user) - . = ..() - if(.) - return +/turf/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) user.Move_Pulled(src) /turf/proc/multiz_turf_del(turf/T, dir) @@ -179,7 +179,7 @@ target.zImpact(A, levels, src) return TRUE -/turf/proc/handleRCL(obj/item/twohanded/rcl/C, mob/user) +/turf/proc/handleRCL(obj/item/rcl/C, mob/user) if(C.loaded) for(var/obj/structure/cable/LC in src) if(!LC.d1 || !LC.d2) @@ -202,7 +202,7 @@ coil.place_turf(src, user) return TRUE - else if(istype(C, /obj/item/twohanded/rcl)) + else if(istype(C, /obj/item/rcl)) handleRCL(C, user) return FALSE @@ -274,7 +274,7 @@ /turf/open/Entered(atom/movable/AM) ..() //melting - if(isobj(AM) && air && air.temperature > T0C) + if(isobj(AM) && air && air.return_temperature() > T0C) var/obj/O = AM if(O.obj_flags & FROZEN) O.make_unfrozen() diff --git a/code/game/world.dm b/code/game/world.dm index 999480062f..a342200b3d 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -9,10 +9,12 @@ GLOBAL_LIST(topic_status_cache) //This happens after the Master subsystem new(s) (it's a global datum) //So subsystems globals exist, but are not initialised /world/New() - var/extools = world.GetConfig("env", "EXTOOLS_DLL") || "./byond-extools.dll" - if (fexists(extools)) - call(extools, "maptick_initialize")() + if (fexists(EXTOOLS)) + call(EXTOOLS, "maptick_initialize")() enable_debugger() +#ifdef REFERENCE_TRACKING + enable_reference_tracking() +#endif world.Profile(PROFILE_START) @@ -120,6 +122,7 @@ GLOBAL_LIST(topic_status_cache) GLOB.world_game_log = "[GLOB.log_directory]/game.log" GLOB.world_virus_log = "[GLOB.log_directory]/virus.log" + GLOB.world_asset_log = "[GLOB.log_directory]/asset.log" GLOB.world_attack_log = "[GLOB.log_directory]/attack.log" GLOB.world_pda_log = "[GLOB.log_directory]/pda.log" GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log" @@ -131,11 +134,13 @@ GLOBAL_LIST(topic_status_cache) GLOB.world_runtime_log = "[GLOB.log_directory]/runtime.log" GLOB.query_debug_log = "[GLOB.log_directory]/query_debug.log" GLOB.world_job_debug_log = "[GLOB.log_directory]/job_debug.log" + GLOB.world_paper_log = "[GLOB.log_directory]/paper.log" GLOB.tgui_log = "[GLOB.log_directory]/tgui.log" 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" + GLOB.world_asset_log = "[GLOB.log_directory]/asset.log" #ifdef UNIT_TESTS @@ -275,6 +280,15 @@ GLOBAL_LIST(topic_status_cache) shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss. ..() +/world/Del() + // memory leaks bad + var/num_deleted = 0 + for(var/datum/gas_mixture/GM) + GM.__gasmixture_unregister() + num_deleted++ + log_world("Deallocated [num_deleted] gas mixtures") + ..() + /world/proc/update_status() var/list/features = list() @@ -343,3 +357,6 @@ GLOBAL_LIST(topic_status_cache) maxz++ SSmobs.MaxZChanged() SSidlenpcpool.MaxZChanged() + world.refresh_atmos_grid() + +/world/proc/refresh_atmos_grid() diff --git a/code/modules/NTNet/relays.dm b/code/modules/NTNet/relays.dm index 0d855f15bb..8c33dd1eba 100644 --- a/code/modules/NTNet/relays.dm +++ b/code/modules/NTNet/relays.dm @@ -9,8 +9,6 @@ icon_state = "bus" density = TRUE circuit = /obj/item/circuitboard/machine/ntnet_relay - ui_x = 400 - ui_y = 300 var/datum/ntnet/NTNet = null // This is mostly for backwards reference and to allow varedit modifications from ingame. var/enabled = 1 // Set to 0 if the relay was turned off @@ -64,15 +62,12 @@ SSnetworks.station_network.add_log("Quantum relay switched from overload recovery mode to normal operation mode.") ..() -/obj/machinery/ntnet_relay/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) - - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - +/obj/machinery/ntnet_relay/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "ntnet_relay", "NTNet Quantum Relay", ui_x, ui_y, master_ui, state) + ui = new(user, src, "NtnetRelay") ui.open() - /obj/machinery/ntnet_relay/ui_data(mob/user) var/list/data = list() data["enabled"] = enabled @@ -81,7 +76,6 @@ data["dos_crashed"] = dos_failure return data - /obj/machinery/ntnet_relay/ui_act(action, params) if(..()) return @@ -118,4 +112,4 @@ D.target = null D.error = "Connection to quantum relay severed" - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm index 26ae200990..cc59fe10ab 100644 --- a/code/modules/VR/vr_sleeper.dm +++ b/code/modules/VR/vr_sleeper.dm @@ -71,22 +71,22 @@ /obj/machinery/vr_sleeper/update_icon_state() icon_state = "[initial(icon_state)][state_open ? "-open" : ""]" -/obj/machinery/vr_sleeper/open_machine() - if(state_open) - return - if(occupant) - SStgui.close_user_uis(occupant, src) - return ..() /obj/machinery/vr_sleeper/MouseDrop_T(mob/target, mob/user) if(user.lying || !iscarbon(target) || !Adjacent(target) || !user.canUseTopic(src, BE_CLOSE, TRUE, NO_TK)) return close_machine(target) + ui_interact(user) -/obj/machinery/vr_sleeper/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/vr_sleeper/ui_state(mob/user) + if(user == occupant) + return GLOB.contained_state + return GLOB.default_state + +/obj/machinery/vr_sleeper/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "vr_sleeper", "VR Sleeper", 475, 340, master_ui, state) + ui = new(user, src, "VrSleeper", "VR Sleeper") ui.open() /obj/machinery/vr_sleeper/ui_act(action, params) @@ -130,11 +130,13 @@ /obj/machinery/vr_sleeper/ui_data(mob/user) var/list/data = list() + var/is_living if(vr_mob && !QDELETED(vr_mob)) + is_living = isliving(vr_mob) data["can_delete_avatar"] = TRUE data["vr_avatar"] = list("name" = vr_mob.name) - data["isliving"] = istype(vr_mob) - if(data["isliving"]) + data["isliving"] = is_living + if(is_living) var/status switch(vr_mob.stat) if(CONSCIOUS) @@ -146,6 +148,11 @@ if(SOFT_CRIT) status = "Barely Conscious" data["vr_avatar"] += list("status" = status, "health" = vr_mob.health, "maxhealth" = vr_mob.maxHealth) + else + data["can_delete_avatar"] = FALSE + data["vr_avatar"] = FALSE + data["isliving"] = FALSE + data["toggle_open"] = state_open data["emagged"] = you_die_in_the_game_you_die_for_real data["isoccupant"] = (user == occupant) diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index a2e2b3c122..8cfae3820a 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -40,6 +40,11 @@ if(M.client) body += "
    \[First Seen: [M.client.player_join_date]\]\[Byond account registered on: [M.client.account_join_date]\]" + body += "

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

    Show related accounts by: " body += "\[ CID | " body += "IP \]" diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 289abbe250..e9abb7db87 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -62,7 +62,7 @@ GLOBAL_PROTECT(admin_verbs_admin) /client/proc/cmd_admin_check_player_exp, /* shows players by playtime */ /client/proc/toggle_combo_hud, // toggle display of the combination pizza antag and taco sci/med/eng hud /client/proc/toggle_AI_interact, /*toggle admin ability to interact with machines as an AI*/ - /client/proc/open_shuttle_manipulator, /* Opens shuttle manipulator UI */ + /datum/admins/proc/open_shuttlepanel, /* Opens shuttle manipulator UI */ /client/proc/respawn_character, /client/proc/secrets, /client/proc/toggle_hear_radio, /*allows admins to hide all radio output*/ @@ -171,7 +171,11 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug()) /client/proc/cmd_display_overlay_log, /client/proc/reload_configuration, /datum/admins/proc/create_or_modify_area, - /client/proc/generate_wikichem_list //DO NOT PRESS UNLESS YOU WANT SUPERLAG +#ifdef REFERENCE_TRACKING + /datum/admins/proc/view_refs, + /datum/admins/proc/view_del_failures, +#endif + /client/proc/generate_wikichem_list, //DO NOT PRESS UNLESS YOU WANT SUPERLAG ) GLOBAL_PROTECT(admin_verbs_debug) GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release)) diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm index 9b15729a9e..bab74300f5 100644 --- a/code/modules/admin/chat_commands.dm +++ b/code/modules/admin/chat_commands.dm @@ -84,7 +84,7 @@ GLOBAL_LIST(round_end_notifiees) if(!SSticker.IsRoundInProgress() && SSticker.HasRoundStarted()) return "[sender.mention], the round has already ended!" LAZYINITLIST(GLOB.round_end_notifiees) - GLOB.round_end_notifiees["<@[sender.mention]>"] = TRUE + GLOB.round_end_notifiees[sender.mention] = TRUE return "I will notify [sender.mention] when the round ends." /datum/tgs_chat_command/sdql @@ -150,7 +150,7 @@ GLOBAL_LIST(round_end_notifiees) /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/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 removal","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" diff --git a/code/modules/admin/fun_balloon.dm b/code/modules/admin/fun_balloon.dm index 44dcfc0ae6..417663fcb7 100644 --- a/code/modules/admin/fun_balloon.dm +++ b/code/modules/admin/fun_balloon.dm @@ -126,7 +126,7 @@ L.forceMove(LA) L.hallucination = 0 to_chat(L, "The battle is won. Your bloodlust subsides.") - for(var/obj/item/twohanded/required/chainsaw/doomslayer/chainsaw in L) + for(var/obj/item/chainsaw/doomslayer/chainsaw in L) qdel(chainsaw) else to_chat(L, "You are not yet worthy of passing. Drag a severed head to the barrier to be allowed entry to the hall of champions.") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 042a6e0fe9..13e8877440 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -863,7 +863,7 @@ if(jobban_isbanned(M, ROLE_TRAITOR) || isbanned_dept) dat += "Traitor" else - dat += "Traitor" + dat += "Traitor" //Changeling if(jobban_isbanned(M, ROLE_CHANGELING) || isbanned_dept) @@ -2184,8 +2184,18 @@ if(!ishuman(H)) to_chat(usr, "This can only be used on instances of type /mob/living/carbon/human.") return - - var/obj/item/reagent_containers/food/snacks/cookie/cookie = new(H) + //let's keep it simple + //milk to plasmemes and skeletons, meat to lizards, electricity bars to ethereals, cookies to everyone else + var/cookiealt = /obj/item/reagent_containers/food/snacks/cookie + if(isskeleton(H)) + cookiealt = /obj/item/reagent_containers/food/condiment/milk + else if(isplasmaman(H)) + cookiealt = /obj/item/reagent_containers/food/condiment/milk + else if(isethereal(H)) + cookiealt = /obj/item/reagent_containers/food/snacks/energybar + else if(islizard(H)) + cookiealt = /obj/item/reagent_containers/food/snacks/meat/slab + var/obj/item/cookie = new cookiealt(H) if(H.put_in_hands(cookie)) H.update_inv_hands() else @@ -2834,6 +2844,60 @@ usr << browse(dat.Join("
    "), "window=related_[C];size=420x300") + else if(href_list["centcomlookup"]) + if(!check_rights(R_ADMIN)) + return + + if(!CONFIG_GET(string/centcom_ban_db)) + to_chat(usr, "Centcom Galactic Ban DB is disabled!") + return + + var/ckey = href_list["centcomlookup"] + + // Make the request + var/datum/http_request/request = new() + request.prepare(RUSTG_HTTP_METHOD_GET, "[CONFIG_GET(string/centcom_ban_db)]/[ckey]", "", "") + request.begin_async() + UNTIL(request.is_complete() || !usr) + if (!usr) + return + var/datum/http_response/response = request.into_response() + + var/list/bans + + var/list/dat = list("") + + if(response.errored) + dat += "
    Failed to connect to CentCom." + else if(response.status_code != 200) + dat += "
    Failed to connect to CentCom. Status code: [response.status_code]" + else + if(response.body == "[]") + dat += "
    0 bans detected for [ckey]
    " + else + bans = json_decode(response["body"]) + dat += "
    [bans.len] ban\s detected for [ckey]
    " + for(var/list/ban in bans) + dat += "Server: [sanitize(ban["sourceName"])]
    " + dat += "RP Level: [sanitize(ban["sourceRoleplayLevel"])]
    " + dat += "Type: [sanitize(ban["type"])]
    " + dat += "Banned By: [sanitize(ban["bannedBy"])]
    " + dat += "Reason: [sanitize(ban["reason"])]
    " + dat += "Datetime: [sanitize(ban["bannedOn"])]
    " + var/expiration = ban["expires"] + dat += "Expires: [expiration ? "[sanitize(expiration)]" : "Permanent"]
    " + if(ban["type"] == "job") + dat += "Jobs: " + var/list/jobs = ban["jobs"] + dat += sanitize(jobs.Join(", ")) + dat += "
    " + dat += "
    " + + dat += "
    " + var/datum/browser/popup = new(usr, "centcomlookup-[ckey]", "
    Central Command Galactic Ban Database
    ", 700, 600) + popup.set_content(dat.Join()) + popup.open(0) + else if(href_list["modantagrep"]) if(!check_rights(R_ADMIN)) return diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2.dm b/code/modules/admin/verbs/SDQL2/SDQL_2.dm index bff431a6c7..b757028ea2 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2.dm @@ -666,8 +666,8 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null obj_count_finished = select_refs var/n = 0 for(var/i in found) - if(++n == 20000) - text_list += "
    TRUNCATED - 20000 OBJECT LIMIT HIT" + if(++n == 2500) + text_list += "
    TRUNCATED - 2500 OBJECT LIMIT HIT" SDQL_print(i, text_list, print_nulls) select_refs[REF(i)] = TRUE SDQL2_TICK_CHECK @@ -909,10 +909,9 @@ GLOBAL_DATUM_INIT(sdql2_vv_statobj, /obj/effect/statclick/SDQL2_VV_all, new(null assoc = SDQL_expression(object, expressions_list[expression_list]) if(assoc != null) // Need to insert the key like this to prevent duplicate keys fucking up. - var/list/dummy = list() - dummy[result] = assoc - result = dummy - val += result + val[result] = assoc + else + val += list(result) else val = world.SDQL_var(object, expression, i, object, superuser, src) i = expression.len diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm index 24149e7e6c..4f518b7f8e 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -234,3 +234,7 @@ for(var/turf/T in v) . += T return pick(.) + +/proc/__nan() + var/list/L = json_decode("{\"value\":NaN}") + return L["value"] diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index 14cf0d7ee2..edf95dc47e 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -254,6 +254,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) //message from the initiator without a target, all admins will see this //won't bug irc /datum/admin_help/proc/MessageNoRecipient(msg) + msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN)) var/ref_src = "[REF(src)]" //Message to be sent to all admins var/admin_msg = "Ticket [TicketHref("#[id]", ref_src)]: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]: [keywords_lookup(msg)]" @@ -371,8 +372,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) return var/msg = "- AdminHelp marked as IC issue by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! -
    " - msg += "Losing is part of the game!
    " - msg += "It is also possible that your ahelp is unable to be answered properly, due to events occurring in the round." + msg += "Your ahelp is unable to be answered properly due to events occurring in the round. Your question probably has an IC answer, which means you should deal with it IC!" if(initiator) to_chat(initiator, msg) diff --git a/code/modules/admin/verbs/adminpm.dm b/code/modules/admin/verbs/adminpm.dm index bbd6b55e4f..b7f05740a3 100644 --- a/code/modules/admin/verbs/adminpm.dm +++ b/code/modules/admin/verbs/adminpm.dm @@ -55,7 +55,7 @@ if(AH) message_admins("[key_name_admin(src)] has started replying to [key_name(C, 0, 0)]'s admin help.") - var/msg = input(src,"Message:", "Private message to [key_name(C, 0, 0)]") as message|null + var/msg = input(src,"Message:", "Private message to [C.holder?.fakekey ? "an Administrator" : key_name(C, 0, 0)].") as message|null if (!msg) message_admins("[key_name_admin(src)] has cancelled their reply to [key_name(C, 0, 0)]'s admin help.") return @@ -87,10 +87,10 @@ if(irc) - if(!ircreplyamount) //to prevent people from spamming irc + if(!ircreplyamount) //to prevent people from spamming irc/discord return if(!msg) - msg = input(src,"Message:", "Private message to Administrator") as text|null + msg = input(src,"Message:", "Private message to Administrator") as message|null if(!msg) return @@ -112,7 +112,7 @@ //get message text, limit it's length.and clean/escape html if(!msg) - msg = input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]") as message|null + msg = input(src,"Message:", "Private message to [recipient.holder?.fakekey ? "an Administrator" : key_name(recipient, 0, 0)].") as message|null msg = trim(msg) if(!msg) return @@ -133,7 +133,7 @@ //clean the message if it's not sent by a high-rank admin if(!check_rights(R_SERVER|R_DEBUG,0)||irc)//no sending html to the poor bots - msg = trim(sanitize(msg), MAX_MESSAGE_LEN) + msg = sanitize(copytext_char(msg, 1, MAX_MESSAGE_LEN)) if(!msg) return @@ -188,10 +188,10 @@ //AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn if(CONFIG_GET(flag/popup_admin_pm)) - spawn() //so we don't hold the caller proc up + spawn() //so we don't hold the caller proc up. Please functionalize this var/sender = src var/sendername = key - var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as text|null //show message and await a reply + var/reply = input(recipient, msg,"Admin PM from-[sendername]", "") as message|null //show message and await a reply if(recipient && reply) if(sender) recipient.cmd_admin_pm(sender,reply) //sender is still about, let's reply to them diff --git a/code/modules/admin/verbs/borgpanel.dm b/code/modules/admin/verbs/borgpanel.dm index 869e44e4f5..35f4ddb3e5 100644 --- a/code/modules/admin/verbs/borgpanel.dm +++ b/code/modules/admin/verbs/borgpanel.dm @@ -36,7 +36,7 @@ /datum/borgpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) - ui = new(user, src, ui_key, "borgopanel", "Borg Panel", 700, 700, master_ui, state) + ui = new(user, src, ui_key, "BorgPanel", "Borg Panel", 700, 700, master_ui, state) ui.open() /datum/borgpanel/ui_data(mob/user) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 8406248164..f068f05a4a 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -573,7 +573,7 @@ if(Rad.anchored) if(!Rad.loaded_tank) var/obj/item/tank/internals/plasma/Plasma = new/obj/item/tank/internals/plasma(Rad) - Plasma.air_contents.gases[/datum/gas/plasma] = 70 + Plasma.air_contents.set_moles(/datum/gas/plasma,70) Rad.drainratio = 0 Rad.loaded_tank = Plasma Plasma.forceMove(Rad) diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm index 072fbaa123..6f8e9e703f 100644 --- a/code/modules/admin/verbs/diagnostics.dm +++ b/code/modules/admin/verbs/diagnostics.dm @@ -1,15 +1,14 @@ /proc/show_air_status_to(turf/target, mob/user) var/datum/gas_mixture/env = target.return_air() - var/list/env_gases = env.gases var/burning = FALSE if(isopenturf(target)) var/turf/open/T = target if(T.active_hotspot) burning = TRUE - var/list/lines = list("[AREACOORD(target)]: [env.temperature] K ([env.temperature - T0C] C), [env.return_pressure()] kPa[(burning)?(", burning"):(null)]") - for(var/id in env_gases) - var/moles = env_gases[id] + var/list/lines = list("[AREACOORD(target)]: [env.return_temperature()] K ([env.return_temperature() - T0C] C), [env.return_pressure()] kPa[(burning)?(", burning"):(null)]") + for(var/id in env.get_gases()) + var/moles = env.get_moles(id) if (moles >= 0.00001) lines += "[GLOB.meta_gas_names[id]]: [moles] mol" to_chat(usr, lines.Join("\n")) @@ -23,37 +22,6 @@ show_air_status_to(target, usr) SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Air Status") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! -/client/proc/fix_next_move() - set category = "Debug" - set name = "Unfreeze Everyone" - var/largest_move_time = 0 - var/largest_click_time = 0 - var/mob/largest_move_mob = null - var/mob/largest_click_mob = null - for(var/mob/M in world) - if(!M.client) - continue - if(M.next_move >= largest_move_time) - largest_move_mob = M - if(M.next_move > world.time) - largest_move_time = M.next_move - world.time - else - largest_move_time = 1 - if(M.next_click >= largest_click_time) - largest_click_mob = M - if(M.next_click > world.time) - largest_click_time = M.next_click - world.time - else - largest_click_time = 0 - log_admin("DEBUG: [key_name(M)] next_move = [M.next_move] lastDblClick = [M.next_click] world.time = [world.time]") - M.next_move = 1 - M.next_click = 0 - message_admins("[ADMIN_LOOKUPFLW(largest_move_mob)] had the largest move delay with [largest_move_time] frames / [DisplayTimeText(largest_move_time)]!") - message_admins("[ADMIN_LOOKUPFLW(largest_click_mob)] had the largest click delay with [largest_click_time] frames / [DisplayTimeText(largest_click_time)]!") - message_admins("world.time = [world.time]") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Unfreeze Everyone") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - /client/proc/radio_report() set category = "Debug" set name = "Radio report" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index d335cfb171..5997558c60 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -421,7 +421,7 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character.real_name = record_found.fields["name"] new_character.gender = record_found.fields["gender"] new_character.age = record_found.fields["age"] - new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"]) + new_character.hardset_dna(record_found.fields["identity"], record_found.fields["enzymes"], null, record_found.fields["name"], record_found.fields["blood_type"], new record_found.fields["species"], record_found.fields["features"]) else var/datum/preferences/A = new() A.copy_to(new_character) @@ -1058,13 +1058,6 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits var/datum/atom_hud/A = GLOB.huds[ANTAG_HUD_TRAITOR] return A.hudusers[mob] -/client/proc/open_shuttle_manipulator() - set category = "Admin" - set name = "Shuttle Manipulator" - set desc = "Opens the shuttle manipulator UI." - - for(var/obj/machinery/shuttle_manipulator/M in GLOB.machines) - M.ui_interact(usr) /client/proc/run_weather() set category = "Fun" @@ -1276,7 +1269,23 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(!check_rights(R_ADMIN) || !check_rights(R_FUN)) return - var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, ADMIN_PUNISHMENT_CUSTOM_PIE, ADMIN_PUNISHMENT_FIREBALL, ADMIN_PUNISHMENT_LIGHTNING, ADMIN_PUNISHMENT_BRAINDAMAGE, ADMIN_PUNISHMENT_BSA, ADMIN_PUNISHMENT_GIB, ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, ADMIN_PUNISHMENT_SUPPLYPOD, ADMIN_PUNISHMENT_MAZING, ADMIN_PUNISHMENT_ROD) + var/list/punishment_list = list(ADMIN_PUNISHMENT_PIE, + ADMIN_PUNISHMENT_CUSTOM_PIE, + ADMIN_PUNISHMENT_FIREBALL, + ADMIN_PUNISHMENT_LIGHTNING, + ADMIN_PUNISHMENT_BRAINDAMAGE, + ADMIN_PUNISHMENT_BSA, + ADMIN_PUNISHMENT_GIB, + ADMIN_PUNISHMENT_SUPPLYPOD_QUICK, + ADMIN_PUNISHMENT_SUPPLYPOD, + ADMIN_PUNISHMENT_MAZING, + ADMIN_PUNISHMENT_ROD, + ADMIN_PUNISHMENT_SHOES, + ADMIN_PUNISHMENT_PICKLE, + ADMIN_PUNISHMENT_FRY, + ADMIN_PUNISHMENT_CRACK, + ADMIN_PUNISHMENT_BLEED, + ADMIN_PUNISHMENT_SCARIFY) var/punishment = input("Choose a punishment", "DIVINE SMITING") as null|anything in punishment_list @@ -1341,7 +1350,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(ADMIN_PUNISHMENT_PIE) var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/creamy = new(get_turf(target)) creamy.splat(target) - if (ADMIN_PUNISHMENT_CUSTOM_PIE) + if(ADMIN_PUNISHMENT_CUSTOM_PIE) var/obj/item/reagent_containers/food/snacks/pie/cream/nostun/A = new() if(!A.reagents) var/amount = input(usr, "Specify the reagent size of [A]", "Set Reagent Size", 50) as num|null @@ -1354,9 +1363,122 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(amount) A.reagents.add_reagent(chosen_id, amount) A.splat(target) + if(ADMIN_PUNISHMENT_CRACK) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + var/mob/living/carbon/C = target + for(var/i in C.bodyparts) + var/obj/item/bodypart/squish_part = i + var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate)) + squish_part.force_wound_upwards(type_wound, smited=TRUE) + if(ADMIN_PUNISHMENT_BLEED) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + var/mob/living/carbon/C = target + for(var/i in C.bodyparts) + var/obj/item/bodypart/slice_part = i + var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate)) + slice_part.force_wound_upwards(type_wound, smited=TRUE) + type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate)) + slice_part.force_wound_upwards(type_wound, smited=TRUE) + type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe)) + slice_part.force_wound_upwards(type_wound, smited=TRUE) + if(ADMIN_PUNISHMENT_SCARIFY) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + var/mob/living/carbon/dude = target + dude.generate_fake_scars(rand(1, 4)) + to_chat(dude, "You feel your body grow jaded and torn...") + if(ADMIN_PUNISHMENT_PERFORATE) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + + var/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE") + var/hatred = input("How much do you hate this guy?") in how_fucked_is_this_dude + var/repetitions + var/shots_per_limb_per_rep = 2 + var/damage + switch(hatred) + if("A little") + repetitions = 1 + damage = 5 + if("A lot") + repetitions = 2 + + damage = 8 + if("So fucking much") + repetitions = 3 + damage = 10 + if("FUCK THIS DUDE") + repetitions = 4 + damage = 10 + + var/mob/living/carbon/dude = target + var/list/open_adj_turfs = get_adjacent_open_turfs(dude) + var/list/wound_bonuses = list(15, 70, 110, 250) + + var/delay_per_shot = 1 + var/delay_counter = 1 + + dude.Immobilize(5 SECONDS) + for(var/wound_bonus_rep in 1 to repetitions) + for(var/i in dude.bodyparts) + var/obj/item/bodypart/slice_part = i + var/shots_this_limb = 0 + for(var/t in shuffle(open_adj_turfs)) + var/turf/iter_turf = t + addtimer(CALLBACK(GLOBAL_PROC, .proc/firing_squad, dude, iter_turf, slice_part.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter) + delay_counter += delay_per_shot + shots_this_limb++ + if(shots_this_limb > shots_per_limb_per_rep) + break + if(ADMIN_PUNISHMENT_PICKLE) + target.turn_into_pickle() + if(ADMIN_PUNISHMENT_FRY) + target.fry() + + if(ADMIN_PUNISHMENT_SHOES) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.") + return + var/mob/living/carbon/C = target + var/obj/item/clothing/shoes/sick_kicks = C.shoes + if(!sick_kicks?.can_be_tied) + to_chat(usr,"[C] does not have knottable shoes!") + return + sick_kicks.adjust_laces(SHOES_KNOTTED) punish_log(target, punishment) +/** + * firing_squad is a proc for the :B:erforate smite to shoot each individual bullet at them, so that we can add actual delays without sleep() nonsense + * + * Hilariously, if you drag someone away mid smite, the bullets will still chase after them from the original spot, possibly hitting other people. Too funny to fix imo + * + * Arguments: + * * target- guy we're shooting obviously + * * source_turf- where the bullet begins, preferably on a turf next to the target + * * body_zone- which bodypart we're aiming for, if there is one there + * * wound_bonus- the wounding power we're assigning to the bullet, since we don't care about the base one + * * damage- the damage we're assigning to the bullet, since we don't care about the base one + */ +/proc/firing_squad(mob/living/carbon/target, turf/source_turf, body_zone, wound_bonus, damage) + if(!target.get_bodypart(body_zone)) + return + playsound(target, 'sound/weapons/shot.ogg', 100) + var/obj/item/projectile/bullet/smite/divine_wrath = new(source_turf) + divine_wrath.damage = damage + divine_wrath.wound_bonus = wound_bonus + divine_wrath.original = target + divine_wrath.def_zone = body_zone + divine_wrath.spread = 0 + divine_wrath.preparePixelProjectile(target, source_turf) + divine_wrath.fire() + /client/proc/punish_log(var/whom, var/punishment) var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]." message_admins(msg) diff --git a/code/modules/admin/verbs/shuttlepanel.dm b/code/modules/admin/verbs/shuttlepanel.dm new file mode 100644 index 0000000000..a80eafae02 --- /dev/null +++ b/code/modules/admin/verbs/shuttlepanel.dm @@ -0,0 +1,76 @@ +/datum/admins/proc/open_shuttlepanel() + set category = "Admin" + set name = "Shuttle Manipulator" + set desc = "Opens the shuttle manipulator UI." + + if(!check_rights(R_ADMIN)) + return + + SSshuttle.ui_interact(usr) + + +/obj/docking_port/mobile/proc/admin_fly_shuttle(mob/user) + var/list/options = list() + + for(var/port in SSshuttle.stationary) + if (istype(port, /obj/docking_port/stationary/transit)) + continue // please don't do this + var/obj/docking_port/stationary/S = port + if (canDock(S) == SHUTTLE_CAN_DOCK) + options[S.name || S.id] = S + + options += "--------" + options += "Infinite Transit" + options += "Delete Shuttle" + options += "Into The Sunset (delete & greentext 'escape')" + + var/selection = input(user, "Select where to fly [name || id]:", "Fly Shuttle") as null|anything in options + if(!selection) + return + + switch(selection) + if("Infinite Transit") + destination = null + mode = SHUTTLE_IGNITING + setTimer(ignitionTime) + + if("Delete Shuttle") + if(alert(user, "Really delete [name || id]?", "Delete Shuttle", "Cancel", "Really!") != "Really!") + return + jumpToNullSpace() + + if("Into The Sunset (delete & greentext 'escape')") + if(alert(user, "Really delete [name || id] and greentext escape objectives?", "Delete Shuttle", "Cancel", "Really!") != "Really!") + return + intoTheSunset() + + else + if(options[selection]) + request(options[selection]) + +/obj/docking_port/mobile/emergency/admin_fly_shuttle(mob/user) + return // use the existing verbs for this + +/obj/docking_port/mobile/arrivals/admin_fly_shuttle(mob/user) + switch(alert(user, "Would you like to fly the arrivals shuttle once or change its destination?", "Fly Shuttle", "Fly", "Retarget", "Cancel")) + if("Cancel") + return + if("Fly") + return ..() + + var/list/options = list() + + for(var/port in SSshuttle.stationary) + if (istype(port, /obj/docking_port/stationary/transit)) + continue // please don't do this + var/obj/docking_port/stationary/S = port + if (canDock(S) == SHUTTLE_CAN_DOCK) + options[S.name || S.id] = S + + var/selection = input(user, "Select the new arrivals destination:", "Fly Shuttle") as null|anything in options + if(!selection) + return + target_dock = options[selection] + if(!QDELETED(target_dock)) + destination = target_dock + diff --git a/code/modules/admin/view_variables/reference_tracking.dm b/code/modules/admin/view_variables/reference_tracking.dm new file mode 100644 index 0000000000..70aac2f107 --- /dev/null +++ b/code/modules/admin/view_variables/reference_tracking.dm @@ -0,0 +1,225 @@ +#ifdef REFERENCE_TRACKING + +GLOBAL_LIST_EMPTY(deletion_failures) + +/world/proc/enable_reference_tracking() + if (fexists(EXTOOLS)) + call(EXTOOLS, "ref_tracking_initialize")() + +/proc/get_back_references(datum/D) + CRASH("/proc/get_back_references not hooked by extools, reference tracking will not function!") + +/proc/get_forward_references(datum/D) + CRASH("/proc/get_forward_references not hooked by extools, reference tracking will not function!") + +/proc/clear_references(datum/D) + return + +/datum/admins/proc/view_refs(atom/D in world) //it actually supports datums as well but byond no likey + set category = "Debug" + set name = "View References" + + if(!check_rights(R_DEBUG) || !D) + return + + var/list/backrefs = get_back_references(D) + if(isnull(backrefs)) + var/datum/browser/popup = new(usr, "ref_view", "
    Error
    ") + popup.set_content("Reference tracking not enabled") + popup.open(FALSE) + return + + var/list/frontrefs = get_forward_references(D) + var/list/dat = list() + dat += "

    References of \ref[D] - [D]


    \[Refresh\]
    " + dat += "

    Back references - these things hold references to this object.

    " + dat += "" + dat += "" + for(var/ref in backrefs) + var/datum/backreference = ref + if(isnull(backreference)) + dat += "" + if(istype(backreference)) + dat += "" + else if(islist(backreference)) + dat += "" + else + dat += "" + dat += "
    RefTypeVariable NameFollow
    GC'd Reference
    [REF(backreference)][backreference.type][backrefs[backreference]]\[Follow\]
    [REF(backreference)]list[backrefs[backreference]]\[Follow\]
    Weird reference type. Add more debugging checks.

    " + dat += "

    Forward references - this object is referencing those things.

    " + dat += "" + dat += "" + for(var/ref in frontrefs) + var/datum/backreference = frontrefs[ref] + dat += "" + dat += "
    Variable nameRefTypeFollow
    [ref][REF(backreference)][backreference.type]\[Follow\]

    " + dat = dat.Join() + + var/datum/browser/popup = new(usr, "ref_view", "
    References of \ref[D]
    ") + popup.set_content(dat) + popup.open(FALSE) + + +/datum/admins/proc/view_del_failures() + set category = "Debug" + set name = "View Deletion Failures" + + if(!check_rights(R_DEBUG)) + return + + var/list/dat = list("") + for(var/t in GLOB.deletion_failures) + if(isnull(t)) + dat += "" + continue + var/datum/thing = t + dat += "" + dat += "
    GC'd Reference | Clear Nulls
    \ref[thing] | [thing.type][thing.gc_destroyed ? " (destroyed)" : ""] [ADMIN_VV(thing)]

    " + dat = dat.Join() + + var/datum/browser/popup = new(usr, "del_failures", "
    Deletion Failures
    ") + popup.set_content(dat) + popup.open(FALSE) + + +/datum/proc/find_references() + testing("Beginning search for references to a [type].") + var/list/backrefs = get_back_references(src) + for(var/ref in backrefs) + if(isnull(ref)) + log_world("## TESTING: Datum reference found, but gone now.") + continue + if(islist(ref)) + log_world("## TESTING: Found [type] \ref[src] in list.") + continue + var/datum/datum_ref = ref + if(!istype(datum_ref)) + log_world("## TESTING: Found [type] \ref[src] in unknown type reference: [datum_ref].") + return + log_world("## TESTING: Found [type] \ref[src] in [datum_ref.type][datum_ref.gc_destroyed ? " (destroyed)" : ""]") + message_admins("Found [type] \ref[src] [ADMIN_VV(src)] in [datum_ref.type][datum_ref.gc_destroyed ? " (destroyed)" : ""] [ADMIN_VV(datum_ref)]") + testing("Completed search for references to a [type].") + +#endif + +#ifdef LEGACY_REFERENCE_TRACKING + +/datum/verb/legacy_find_refs() + set category = "Debug" + set name = "Find References" + set src in world + + find_references(FALSE) + + +/datum/proc/find_references_legacy(skip_alert) + running_find_references = type + if(usr?.client) + if(usr.client.running_find_references) + testing("CANCELLED search for references to a [usr.client.running_find_references].") + usr.client.running_find_references = null + running_find_references = null + //restart the garbage collector + SSgarbage.can_fire = TRUE + SSgarbage.next_fire = world.time + world.tick_lag + return + + if(!skip_alert && alert("Running this will lock everything up for about 5 minutes. Would you like to begin the search?", "Find References", "Yes", "No") != "Yes") + running_find_references = null + return + + //this keeps the garbage collector from failing to collect objects being searched for in here + SSgarbage.can_fire = FALSE + + if(usr?.client) + usr.client.running_find_references = type + + testing("Beginning search for references to a [type].") + last_find_references = world.time + + DoSearchVar(GLOB) //globals + for(var/datum/thing in world) //atoms (don't beleive its lies) + DoSearchVar(thing, "World -> [thing]") + + for(var/datum/thing) //datums + DoSearchVar(thing, "World -> [thing]") + + for(var/client/thing) //clients + DoSearchVar(thing, "World -> [thing]") + + testing("Completed search for references to a [type].") + if(usr?.client) + usr.client.running_find_references = null + running_find_references = null + + //restart the garbage collector + SSgarbage.can_fire = TRUE + SSgarbage.next_fire = world.time + world.tick_lag + + +/datum/verb/qdel_then_find_references() + set category = "Debug" + set name = "qdel() then Find References" + set src in world + + qdel(src, TRUE) //force a qdel + if(!running_find_references) + find_references(TRUE) + + +/datum/verb/qdel_then_if_fail_find_references() + set category = "Debug" + set name = "qdel() then Find References if GC failure" + set src in world + + qdel_and_find_ref_if_fail(src, TRUE) + + +/datum/proc/DoSearchVar(potential_container, container_name, recursive_limit = 64) + if(usr?.client && !usr.client.running_find_references) + return + + if(!recursive_limit) + return + + if(istype(potential_container, /datum)) + var/datum/datum_container = potential_container + if(datum_container.last_find_references == last_find_references) + return + + datum_container.last_find_references = last_find_references + var/list/vars_list = datum_container.vars + + for(var/varname in vars_list) + if (varname == "vars") + continue + var/variable = vars_list[varname] + + if(variable == src) + testing("Found [type] \ref[src] in [datum_container.type]'s [varname] var. [container_name]") + + else if(islist(variable)) + DoSearchVar(variable, "[container_name] -> list", recursive_limit - 1) + + else if(islist(potential_container)) + var/normal = IS_NORMAL_LIST(potential_container) + for(var/element_in_list in potential_container) + if(element_in_list == src) + testing("Found [type] \ref[src] in list [container_name].") + + else if(element_in_list && !isnum(element_in_list) && normal && potential_container[element_in_list] == src) + testing("Found [type] \ref[src] in list [container_name]\[[element_in_list]\]") + + else if(islist(element_in_list)) + DoSearchVar(element_in_list, "[container_name] -> list", recursive_limit - 1) + + #ifndef FIND_REF_NO_CHECK_TICK + CHECK_TICK + #endif + + +/proc/qdel_and_find_ref_if_fail(datum/thing_to_del, force = FALSE) + SSgarbage.reference_find_on_fail[REF(thing_to_del)] = TRUE + qdel(thing_to_del, force) + +#endif diff --git a/code/modules/admin/view_variables/topic_basic.dm b/code/modules/admin/view_variables/topic_basic.dm index d6e4c2b944..9ee7103562 100644 --- a/code/modules/admin/view_variables/topic_basic.dm +++ b/code/modules/admin/view_variables/topic_basic.dm @@ -45,6 +45,16 @@ usr.client.admin_delete(target) if (isturf(src)) // show the turf that took its place usr.client.debug_variables(src) + return + #ifdef REFERENCE_TRACKING + if(href_list[VV_HK_VIEW_REFERENCES]) + var/datum/D = locate(href_list[VV_HK_TARGET]) + if(!D) + to_chat(usr, "Unable to locate item.") + return + usr.client.holder.view_refs(target) + return + #endif if(href_list[VV_HK_MARK]) usr.client.mark_datum(target) if(href_list[VV_HK_ADDCOMPONENT]) diff --git a/code/modules/admin/view_variables/view_variables.dm b/code/modules/admin/view_variables/view_variables.dm index abe445589f..a4dff725f7 100644 --- a/code/modules/admin/view_variables/view_variables.dm +++ b/code/modules/admin/view_variables/view_variables.dm @@ -61,6 +61,7 @@ "Set len" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SET_LENGTH), "Shuffle" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SHUFFLE), "Show VV To Player" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_EXPOSE), + "View References" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_VIEW_REFERENCES), "---" ) for(var/i in 1 to length(dropdownoptions)) diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm index b5ed6c18df..14f7b34309 100644 --- a/code/modules/antagonists/_common/antag_datum.dm +++ b/code/modules/antagonists/_common/antag_datum.dm @@ -14,6 +14,8 @@ GLOBAL_LIST_EMPTY(antagonists) var/list/objectives = list() var/antag_memory = ""//These will be removed with antag datum var/antag_moodlet //typepath of moodlet that the mob will gain with their status + var/antag_hud_type + var/antag_hud_name /// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed(). var/hijack_speed = 0 @@ -23,6 +25,7 @@ GLOBAL_LIST_EMPTY(antagonists) var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type 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/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors var/list/skill_modifiers @@ -76,6 +79,17 @@ GLOBAL_LIST_EMPTY(antagonists) hud.leave_hud(mob_override) set_antag_hud(mob_override, null) +// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects +/datum/antagonist/proc/handle_clown_mutation(mob/living/mob_override, message, removing = TRUE) + var/mob/living/carbon/human/H = mob_override + if(H && istype(H) && owner.assigned_role == "Clown") + if(removing) // They're a clown becoming an antag, remove clumsy + H.dna.remove_mutation(CLOWNMUT) + if(!silent && message) + to_chat(H, "[message]") + else + H.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy + //Assign default team and creates one for one of a kind team antagonists /datum/antagonist/proc/create_team(datum/team/team) return @@ -94,6 +108,9 @@ GLOBAL_LIST_EMPTY(antagonists) if(skill_modifiers) for(var/A in skill_modifiers) ADD_SINGLETON_SKILL_MODIFIER(owner, A, type) + var/datum/skill_modifier/job/M = GLOB.skill_modifiers[GET_SKILL_MOD_ID(A, type)] + if(istype(M)) + M.name = "[name] Training" SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src) /datum/antagonist/proc/is_banned(mob/M) @@ -264,7 +281,6 @@ GLOBAL_LIST_EMPTY(antagonists) . = CONFIG_GET(keyed_list/antag_threat)[lowertext(name)] if(. == null) return threat - return threat //This one is created by admin tools for custom objectives /datum/antagonist/custom diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm index 9132288415..7eb7ec2af2 100644 --- a/code/modules/antagonists/abductor/abductor.dm +++ b/code/modules/antagonists/abductor/abductor.dm @@ -7,6 +7,7 @@ job_rank = ROLE_ABDUCTOR show_in_antagpanel = FALSE //should only show subtypes threat = 5 + show_to_ghosts = TRUE var/datum/team/abductor_team/team var/sub_role var/outfit @@ -59,8 +60,10 @@ /datum/antagonist/abductor/greet() to_chat(owner.current, "You are the [owner.special_role]!") - to_chat(owner.current, "With the help of your teammate, kidnap and experiment on station crew members!") - to_chat(owner.current, "Try not to disturb the habitat, it could lead to dead specimens.") + to_chat(owner.current, "You are an operative for your home planet's government. Your mission is to detain, experiment, and observe.") + to_chat(owner.current, "Work together with your teammate to bring live subjects from the space station nearby onto your ship for experimentation.") + to_chat(owner.current, "For the sake of the mission, do not damage the integrity of the station, do not kill anyone unless in self defense, always capture specimens first if you can, and do not steal equipment or belongings from abducted specimens.") + to_chat(owner.current, "Your task is to observe and take notes of the effects of your experiments.") to_chat(owner.current, "[greet_text]") owner.announce_objectives() diff --git a/code/modules/antagonists/abductor/equipment/orderable_gear.dm b/code/modules/antagonists/abductor/equipment/orderable_gear.dm new file mode 100644 index 0000000000..f21294b041 --- /dev/null +++ b/code/modules/antagonists/abductor/equipment/orderable_gear.dm @@ -0,0 +1,79 @@ +GLOBAL_LIST_INIT(abductor_gear, subtypesof(/datum/abductor_gear)) + +/datum/abductor_gear + /// Name of the gear + var/name = "Generic Abductor Gear" + /// Description of the gear + var/description = "Generic description." + /// Unique ID of the gear + var/id = "abductor_generic" + /// Credit cost of the gear + var/cost = 1 + /// Build path of the gear itself + var/build_path = null + /// Category of the gear + var/category = "Basic Gear" + +/datum/abductor_gear/agent_helmet + name = "Agent Helmet" + description = "Abduct with style - spiky style. Prevents digital tracking." + id = "agent_helmet" + build_path = /obj/item/clothing/head/helmet/abductor + +/datum/abductor_gear/agent_vest + name = "Agent Vest" + description = "A vest outfitted with advanced stealth technology. It has two modes - combat and stealth." + id = "agent_vest" + build_path = /obj/item/clothing/suit/armor/abductor/vest + +/datum/abductor_gear/radio_silencer + name = "Radio Silencer" + description = "A compact device used to shut down communications equipment." + id = "radio_silencer" + build_path = /obj/item/abductor/silencer + +/datum/abductor_gear/science_tool + name = "Science Tool" + description = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras." + id = "science_tool" + build_path = /obj/item/abductor/gizmo + +/datum/abductor_gear/advanced_baton + name = "Advanced Baton" + description = "A quad-mode baton used for incapacitation and restraining of specimens." + id = "advanced_baton" + cost = 2 + build_path = /obj/item/abductor/baton //does not exist? + +/datum/abductor_gear/superlingual_matrix + name = "Superlingual Matrix" + description = "A mysterious structure that allows for instant communication between users. Pretty impressive until you need to eat something." + id = "superlingual_matrix" + build_path = /obj/item/organ/tongue/abductor + category = "Advanced Gear" + +/datum/abductor_gear/mental_interface + name = "Mental Interface Device" + description = "A dual-mode tool for directly communicating with sentient brains. It can be used to send a direct message to a target, \ + or to send a command to a test subject with a charged gland." + id = "mental_interface" + cost = 2 + build_path = /obj/item/abductor/mind_device + category = "Advanced Gear" + +/datum/abductor_gear/reagent_synthesizer + name = "Reagent Synthesizer" + description = "Synthesizes a variety of reagents using proto-matter." + id = "reagent_synthesizer" + cost = 2 + build_path = /obj/item/abductor_machine_beacon/chem_dispenser + category = "Advanced Gear" + +/datum/abductor_gear/shrink_ray + name = "Shrink Ray Blaster" + description = "This is a piece of frightening alien tech that enhances the magnetic pull of atoms in a localized space to temporarily make an object shrink. \ + That or it's just space magic. Either way, it shrinks stuff." + id = "shrink_ray" + cost = 2 + build_path = /obj/item/gun/energy/shrink_ray + category = "Advanced Gear" diff --git a/code/modules/antagonists/abductor/ice_abductor.dm b/code/modules/antagonists/abductor/ice_abductor.dm new file mode 100644 index 0000000000..426e4057eb --- /dev/null +++ b/code/modules/antagonists/abductor/ice_abductor.dm @@ -0,0 +1,12 @@ +/obj/structure/fluff/iced_abductor ///Unless more non-machine ayy structures made, it will stay in fluff. + name = "Mysterious Block of Ice" + desc = "A shadowy figure lies in this sturdy-looking block of ice. Who knows where it came from?" + icon = 'icons/effects/freeze.dmi' + icon_state = "ice_ayy" + density = TRUE + deconstructible = FALSE + +/obj/structure/fluff/iced_abductor/Destroy() + var/turf/T = get_turf(src) + new /obj/effect/mob_spawn/human/abductor(T) + . = ..() \ No newline at end of file diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm index b8d5b1bf6d..2e244fa272 100644 --- a/code/modules/antagonists/abductor/machinery/console.dm +++ b/code/modules/antagonists/abductor/machinery/console.dm @@ -23,102 +23,121 @@ var/obj/machinery/abductor/pad/pad var/obj/machinery/computer/camera_advanced/abductor/camera var/list/datum/icon_snapshot/disguises = list() + /// Currently selected gear category + var/selected_cat + /// Dictates if the compact mode of the interface is on or off + var/compact_mode = FALSE + /// Possible gear to be dispensed + var/list/possible_gear -/obj/machinery/abductor/console/attack_hand(mob/user) +/obj/machinery/abductor/console/Initialize(mapload) . = ..() - if(.) - return + possible_gear = get_abductor_gear() + +/** + * get_abductor_gear: Returns a list of a filtered abductor gear sorted by categories + */ +/obj/machinery/abductor/console/proc/get_abductor_gear() + var/list/filtered_modules = list() + for(var/path in GLOB.abductor_gear) + var/datum/abductor_gear/AG = new path + if(!filtered_modules[AG.category]) + filtered_modules[AG.category] = list() + filtered_modules[AG.category][AG] = AG + return filtered_modules + +/obj/machinery/abductor/console/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING)) to_chat(user, "You start mashing alien buttons at random!") if(do_after(user,100, target = src)) TeleporterSend() - return - user.set_machine(src) - var/dat = "" - dat += "

    Abductsoft 3000

    " +/obj/machinery/abductor/console/ui_status(mob/user) + if(!isabductor(user) && !isobserver(user)) + return UI_CLOSE + return ..() + +/obj/machinery/abductor/console/ui_state(mob/user) + return GLOB.physical_state + +/obj/machinery/abductor/console/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "AbductorConsole", name) + ui.open() + +/obj/machinery/abductor/console/ui_static_data(mob/user) + var/list/data = list() + data["categories"] = list() + for(var/category in possible_gear) + var/list/cat = list( + "name" = category, + "items" = (category == selected_cat ? list() : null)) + for(var/gear in possible_gear[category]) + var/datum/abductor_gear/AG = possible_gear[category][gear] + cat["items"] += list(list( + "name" = AG.name, + "cost" = AG.cost, + "desc" = AG.description, + )) + data["categories"] += list(cat) + return data + +/obj/machinery/abductor/console/ui_data(mob/user) + var/list/data = list() + data["compactMode"] = compact_mode + data["experiment"] = experiment ? TRUE : FALSE if(experiment) - var/points = experiment.points - var/credits = experiment.credits - dat += "Collected Samples : [points]
    " - dat += "Gear Credits: [credits]
    " - dat += "Transfer data in exchange for supplies:
    " - dat += "Advanced Baton (2 Credits)
    " - dat += "Mental Interface Device (2 Credits)
    " - dat += "Reagent Synthesizer (2 Credits)
    " - dat += "Agent Helmet (1 Credit)
    " - dat += "Agent Vest (1 Credit)
    " - dat += "Radio Silencer (1 Credit)
    " - dat += "Science Tool (1 Credit)
    " - dat += "Superlingual Matrix (1 Credit)
    " - else - dat += "NO EXPERIMENT MACHINE DETECTED
    " - + data["points"] = experiment.points + data["credits"] = experiment.credits + data["pad"] = pad ? TRUE : FALSE if(pad) - dat += "Emergency Teleporter System." - dat += "Consider using primary observation console first." - dat += "Activate Teleporter
    " - if(gizmo && gizmo.marked) - dat += "Retrieve Mark
    " - else - dat += "Retrieve Mark
    " - else - dat += "NO TELEPAD DETECTED
    " - + data["gizmo"] = gizmo && gizmo.marked ? TRUE : FALSE + data["vest"] = vest ? TRUE : FALSE if(vest) - dat += "

    Agent Vest Mode


    " - var/mode = vest.mode - if(mode == VEST_STEALTH) - dat += "Combat" - dat += "Stealth" - else - dat += "Combat" - dat += "Stealth" + data["vest_mode"] = vest.mode + data["vest_lock"] = HAS_TRAIT_FROM(vest, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT) + return data - dat+="
    " - dat += "Select Agent Vest Disguise
    " - dat += "[HAS_TRAIT_FROM(vest, TRAIT_NODROP, ABDUCTOR_VEST_TRAIT) ? "Unlock" : "Lock"] Vest
    " - else - dat += "NO AGENT VEST DETECTED" - var/datum/browser/popup = new(user, "computer", "Abductor Console", 400, 500) - popup.set_content(dat) - popup.open() - -/obj/machinery/abductor/console/Topic(href, href_list) - if(..()) +/obj/machinery/abductor/console/ui_act(action, list/params) + . = ..() + if(.) return - usr.set_machine(src) - if(href_list["teleporter_send"]) - TeleporterSend() - else if(href_list["teleporter_retrieve"]) - TeleporterRetrieve() - else if(href_list["flip_vest"]) - FlipVest() - else if(href_list["toggle_vest"]) - if(vest) + switch(action) + if("buy") + var/item_name = params["name"] + var/list/buyable_items = list() + for(var/category in possible_gear) + buyable_items += possible_gear[category] + for(var/key in buyable_items) + var/datum/abductor_gear/AG = buyable_items[key] + if(AG.name == item_name) + Dispense(AG.build_path, AG.cost) + return TRUE + if("teleporter_send") + TeleporterSend() + return TRUE + if("teleporter_retrieve") + TeleporterRetrieve() + return TRUE + if("flip_vest") + FlipVest() + return TRUE + if("toggle_vest") + if(!vest) + return vest.toggle_nodrop() - else if(href_list["select_disguise"]) - SelectDisguise() - else if(href_list["dispense"]) - switch(href_list["dispense"]) - if("baton") - Dispense(/obj/item/abductor/baton,cost=2) - if("helmet") - Dispense(/obj/item/clothing/head/helmet/abductor) - if("silencer") - Dispense(/obj/item/abductor/silencer) - if("tool") - Dispense(/obj/item/abductor/gizmo) - if("vest") - Dispense(/obj/item/clothing/suit/armor/abductor/vest) - if("mind_device") - Dispense(/obj/item/abductor/mind_device,cost=2) - if("chem_dispenser") - Dispense(/obj/item/abductor_machine_beacon/chem_dispenser,cost=2) - if("tongue") - Dispense(/obj/item/organ/tongue/abductor) - updateUsrDialog() + return TRUE + if("select_disguise") + SelectDisguise() + return TRUE + if("select") + selected_cat = params["category"] + return TRUE + if("compact_toggle") + compact_mode = !compact_mode + return TRUE /obj/machinery/abductor/console/proc/TeleporterRetrieve() if(pad && gizmo && gizmo.marked) @@ -159,7 +178,6 @@ pad.teleport_target = location to_chat(user, "Location marked as test subject release point.") - /obj/machinery/abductor/console/Initialize(mapload) ..() return INITIALIZE_HINT_LATELOAD diff --git a/code/modules/antagonists/abductor/machinery/dispenser.dm b/code/modules/antagonists/abductor/machinery/dispenser.dm index 17fa311c8f..f5bc0946e6 100644 --- a/code/modules/antagonists/abductor/machinery/dispenser.dm +++ b/code/modules/antagonists/abductor/machinery/dispenser.dm @@ -22,41 +22,44 @@ gland_colors[i] = random_color() amounts[i] = rand(1,5) -/obj/machinery/abductor/gland_dispenser/attack_hand(mob/user) +/obj/machinery/abductor/gland_dispenser/ui_status(mob/user) + if(!isabductor(user) && !isobserver(user)) + return UI_CLOSE + return ..() + +/obj/machinery/abductor/gland_dispenser/ui_state(mob/user) + return GLOB.physical_state + +/obj/machinery/abductor/gland_dispenser/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "GlandDispenser", name) + ui.open() + +/obj/machinery/abductor/gland_dispenser/ui_data(mob/user) + var/list/data = list() + data["glands"] = list() + for(var/gland_number=1,gland_number<=gland_colors.len,gland_number++) + var/list/gland_information = list( + "color" = gland_colors[gland_number], + "amount" = amounts[gland_number], + "id" = gland_number, + ) + data["glands"] += list(gland_information) + return data + +/obj/machinery/abductor/gland_dispenser/ui_act(action, list/params) . = ..() if(.) return - if(!isabductor(user)) - return - user.set_machine(src) - var/box_css = {" - "} - var/dat = "" - var/item_count = 0 - for(var/i=1,i<=gland_colors.len,i++) - item_count++ - var/g_color = gland_colors[i] - var/amount = amounts[i] - dat += "[amount]" - if(item_count == 4) // Four boxes per line - dat +="

    " - item_count = 0 - var/datum/browser/popup = new(user, "glands", "Gland Dispenser", 200, 200) - popup.add_head_content(box_css) - popup.set_content(dat) - popup.open() - return + + switch(action) + if("dispense") + var/gland_id = text2num(params["gland_id"]) + if(!gland_id) + return + Dispense(gland_id) + return TRUE /obj/machinery/abductor/gland_dispenser/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/organ/heart/gland)) @@ -68,15 +71,6 @@ else return ..() -/obj/machinery/abductor/gland_dispenser/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - - if(href_list["dispense"]) - Dispense(text2num(href_list["dispense"])) - updateUsrDialog() - /obj/machinery/abductor/gland_dispenser/proc/Dispense(count) if(amounts[count]>0) amounts[count]-- diff --git a/code/modules/antagonists/abductor/machinery/experiment.dm b/code/modules/antagonists/abductor/machinery/experiment.dm index f92cb987d0..604730cff2 100644 --- a/code/modules/antagonists/abductor/machinery/experiment.dm +++ b/code/modules/antagonists/abductor/machinery/experiment.dm @@ -15,19 +15,13 @@ var/breakout_time = 450 /obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user) - if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target)) + var/mob/living/L = user + if(user.stat || (isliving(user) && (!(L.mobility_flags & MOBILITY_STAND) || !(L.mobility_flags & MOBILITY_UI))) || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target)) return if(isabductor(target)) return close_machine(target) -/obj/machinery/abductor/experiment/attack_hand(mob/user) - . = ..() - if(.) - return - - experimentUI(user) - /obj/machinery/abductor/experiment/open_machine() if(!state_open && !panel_open) ..() @@ -47,11 +41,9 @@ to_chat(user, "[src]'s door won't budge!") /obj/machinery/abductor/experiment/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(breakout_time)].)", \ - "You hear a metallic creaking from [src].") + "You hear a metallic creaking from [src].") if(do_after(user,(breakout_time), target = src)) if(!user || user.stat != CONSCIOUS || user.loc != src || state_open) return @@ -59,122 +51,84 @@ "You successfully break out of [src]!") open_machine() -/obj/machinery/abductor/experiment/proc/dissection_icon(mob/living/carbon/human/H) - var/icon/photo = null - var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m" - if(H.dna.species.use_skintones) - photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.skin_tone]_[g]") - else - photo = icon("icon" = 'icons/mob/human.dmi', "icon_state" = "[H.dna.species.id]_[g]") - photo.Blend("#[H.dna.features["mcolor"]]", ICON_MULTIPLY) +/obj/machinery/abductor/experiment/ui_status(mob/user) + if(user == occupant) + return UI_CLOSE + return ..() - var/icon/eyes - if(EYECOLOR in H.dna.species.species_traits) - eyes = icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "eyes") - eyes.Blend("#[H.eye_color]", ICON_MULTIPLY) +/obj/machinery/abductor/experiment/ui_state(mob/user) + return GLOB.physical_state - var/datum/sprite_accessory/S - S = GLOB.hair_styles_list[H.hair_style] - if(S && (HAIR in H.dna.species.species_traits)) - var/icon/hair = icon("icon" = S.icon, "icon_state" = "[S.icon_state]") - hair.Blend("#[H.hair_color]", ICON_MULTIPLY) - eyes.Blend(hair, ICON_OVERLAY) +/obj/machinery/abductor/experiment/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ProbingConsole", name) + ui.open() - S = GLOB.facial_hair_styles_list[H.facial_hair_style] - if(S && (FACEHAIR in H.dna.species.species_traits)) - var/icon/facial = icon("icon" = S.icon, "icon_state" = "[S.icon_state]") - facial.Blend("#[H.facial_hair_color]", ICON_MULTIPLY) - eyes.Blend(facial, ICON_OVERLAY) - - if(eyes) - photo.Blend(eyes, ICON_OVERLAY) - - var/icon/splat = icon("icon" = 'icons/mob/dam_mob.dmi',"icon_state" = "chest30") - photo.Blend(splat,ICON_OVERLAY) - - return photo - -/obj/machinery/abductor/experiment/proc/experimentUI(mob/user) - var/dat - dat += "

    Experiment

    " - if(occupant) - var/obj/item/photo/P = new - P.picture = new - P.picture.picture_image = icon(dissection_icon(occupant), dir = SOUTH) - user << browse_rsc(P.picture.picture_image, "dissection_img") - dat += "
    " - dat += "" //Avert your eyes - dat += "" - dat += "Probe
    " - dat += "Dissect
    " - dat += "Analyze
    " - dat += "
    " - else - dat += "Experiment " - - if(!occupant) - dat += "

    Machine Unoccupied

    " - else - dat += "

    Subject Status :

    " - dat += "[occupant.name] => " - var/mob/living/mob_occupant = occupant - switch(mob_occupant.stat) - if(CONSCIOUS) - dat += "Conscious" - if(UNCONSCIOUS) - dat += "Unconscious" - else // DEAD - dat += "Deceased" - dat += "
    " - dat += "[flash]" - dat += "
    " - dat += "Scan" - dat += "Close" : "open=1'>Open"]" - var/datum/browser/popup = new(user, "experiment", "Probing Console", 300, 300) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.set_content(dat) - popup.open() - -/obj/machinery/abductor/experiment/Topic(href, href_list) - if(..() || usr == occupant) - return - usr.set_machine(src) - if(href_list["refresh"]) - updateUsrDialog() - return - if(href_list["open"]) - open_machine() - return - if(href_list["close"]) - close_machine() - return +/obj/machinery/abductor/experiment/ui_data(mob/user) + var/list/data = list() + data["open"] = state_open + data["feedback"] = flash + data["occupant"] = occupant ? TRUE : FALSE + data["occupant_name"] = null + data["occupant_status"] = null if(occupant) var/mob/living/mob_occupant = occupant - if(mob_occupant.stat != DEAD) - if(href_list["experiment"]) - flash = Experiment(occupant,href_list["experiment"],usr) - updateUsrDialog() - add_fingerprint(usr) + data["occupant_name"] = mob_occupant.name + data["occupant_status"] = mob_occupant.stat + return data -/obj/machinery/abductor/experiment/proc/Experiment(mob/occupant,type,mob/user) +/obj/machinery/abductor/experiment/ui_act(action, list/params) + . = ..() + if(.) + return + + switch(action) + if("door") + if(state_open) + close_machine() + return TRUE + else + open_machine() + return TRUE + if("experiment") + if(!occupant) + return + var/mob/living/mob_occupant = occupant + if(mob_occupant.stat == DEAD) + return + flash = experiment(occupant, params["experiment_type"], usr) + return TRUE + +/** + * experiment: Performs selected experiment on occupant mob, resulting in a point reward on success + * + * Arguments: + * * occupant The mob inside the machine + * * type The type of experiment to be performed + * * user The mob starting the experiment + */ +/obj/machinery/abductor/experiment/proc/experiment(mob/occupant, type, mob/user) LAZYINITLIST(history) var/mob/living/carbon/human/H = occupant var/datum/antagonist/abductor/user_abductor = user.mind.has_antag_datum(/datum/antagonist/abductor) if(!user_abductor) - return "Authorization failure. Contact mothership immidiately." + return "Authorization failure. Contact mothership immediately." var/point_reward = 0 + if(!H) + return "Invalid or missing specimen." if(H in history) - return "Specimen already in database." + return "Specimen already in database." if(H.stat == DEAD) say("Specimen deceased - please provide fresh sample.") - return "Specimen deceased." + return "Specimen deceased." var/obj/item/organ/heart/gland/GlandTest = locate() in H.internal_organs if(!GlandTest) say("Experimental dissection not detected!") - return "No glands detected!" - if(H.mind != null && (H.voluntary_ghosted || (H.ckey != null))) + return "No glands detected!" + if(H.mind != null && H.ckey != null) LAZYINITLIST(abductee_minds) LAZYADD(history, H) LAZYADD(abductee_minds, H.mind) @@ -196,22 +150,27 @@ point_reward++ if(point_reward > 0) open_machine() - SendBack(H) - playsound(src.loc, 'sound/machines/ding.ogg', 50, 1) + send_back(H) + playsound(src.loc, 'sound/machines/ding.ogg', 50, TRUE) points += point_reward credits += point_reward - return "Experiment successful! [point_reward] new data-points collected." + return "Experiment successful! [point_reward] new data-points collected." else - playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, 1) - return "Experiment failed! No replacement organ detected." + playsound(src.loc, 'sound/machines/buzz-sigh.ogg', 50, TRUE) + return "Experiment failed! No replacement organ detected." else say("Brain activity nonexistent - disposing sample...") open_machine() - SendBack(H) - return "Specimen braindead - disposed." + send_back(H) + return "Specimen braindead - disposed." - -/obj/machinery/abductor/experiment/proc/SendBack(mob/living/carbon/human/H) +/** + * send_back: Sends a mob back to a selected teleport location if safe + * + * Arguments: + * * H The human mob to be sent back + */ +/obj/machinery/abductor/experiment/proc/send_back(mob/living/carbon/human/H) H.Sleeping(160) H.uncuff() if(console && console.pad && console.pad.teleport_target) @@ -221,7 +180,6 @@ SSjob.SendToLateJoin(H, FALSE) return - /obj/machinery/abductor/experiment/update_icon_state() if(state_open) icon_state = "experiment-open" diff --git a/code/modules/antagonists/blob/blob.dm b/code/modules/antagonists/blob/blob.dm index 1b076c9302..c449bd3012 100644 --- a/code/modules/antagonists/blob/blob.dm +++ b/code/modules/antagonists/blob/blob.dm @@ -2,12 +2,19 @@ name = "Blob" roundend_category = "blobs" antagpanel_category = "Blob" + show_to_ghosts = TRUE job_rank = ROLE_BLOB - threat = 20 + threat = 50 var/datum/action/innate/blobpop/pop_action var/starting_points_human_blob = 60 var/point_rate_human_blob = 2 +/datum/antagonist/blob/threat() + . = ..() + if(isovermind(owner.current)) + var/mob/camera/blob/overmind = owner.current + . *= (overmind.blobs_legit.len / overmind.max_count) + /datum/antagonist/blob/roundend_report() var/basic_report = ..() //Display max blobpoints for blebs that lost diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm index 91fb538ca3..f9763b92fd 100644 --- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm +++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm @@ -75,7 +75,6 @@ desc = "A floating, fragile spore." icon_state = "blobpod" icon_living = "blobpod" - threat = 0.2 health = 30 maxHealth = 30 verb_say = "psychically pulses" @@ -103,7 +102,9 @@ factory.spores += src . = ..() -/mob/living/simple_animal/hostile/blob/blobspore/Life() +/mob/living/simple_animal/hostile/blob/blobspore/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!is_zombie && isturf(src.loc)) for(var/mob/living/carbon/human/H in view(src,1)) //Only for corpse right next to/on same tile if(H.stat == DEAD) @@ -111,7 +112,6 @@ break if(factory && z != factory.z) death() - ..() /mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H) is_zombie = 1 @@ -233,39 +233,40 @@ return FALSE return ..() -/mob/living/simple_animal/hostile/blob/blobbernaut/Life() - if(..()) - var/list/blobs_in_area = range(2, src) - if(independent) - return // strong independent blobbernaut that don't need no blob - var/damagesources = 0 - if(!(locate(/obj/structure/blob) in blobs_in_area)) - damagesources++ - if(!factory) - damagesources++ - else - if(locate(/obj/structure/blob/core) in blobs_in_area) - adjustHealth(-maxHealth*0.1) - var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed - if(overmind) - H.color = overmind.blobstrain.complementary_color - else - H.color = "#000000" - if(locate(/obj/structure/blob/node) in blobs_in_area) - adjustHealth(-maxHealth*0.05) - var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) - if(overmind) - H.color = overmind.blobstrain.complementary_color - else - H.color = "#000000" - if(damagesources) - for(var/i in 1 to damagesources) - adjustHealth(maxHealth*0.025) //take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both - var/image/I = new('icons/mob/blob.dmi', src, "nautdamage", MOB_LAYER+0.01) - I.appearance_flags = RESET_COLOR +/mob/living/simple_animal/hostile/blob/blobbernaut/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + var/list/blobs_in_area = range(2, src) + if(independent) + return // strong independent blobbernaut that don't need no blob + var/damagesources = 0 + if(!(locate(/obj/structure/blob) in blobs_in_area)) + damagesources++ + if(!factory) + damagesources++ + else + if(locate(/obj/structure/blob/core) in blobs_in_area) + adjustHealth(-maxHealth*0.1) + var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) //hello yes you are being healed if(overmind) - I.color = overmind.blobstrain.complementary_color - flick_overlay_view(I, src, 8) + H.color = overmind.blobstrain.complementary_color + else + H.color = "#000000" + if(locate(/obj/structure/blob/node) in blobs_in_area) + adjustHealth(-maxHealth*0.05) + var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(src)) + if(overmind) + H.color = overmind.blobstrain.complementary_color + else + H.color = "#000000" + if(damagesources) + for(var/i in 1 to damagesources) + adjustHealth(maxHealth*0.025) //take 2.5% of max health as damage when not near the blob or if the naut has no factory, 5% if both + var/image/I = new('icons/mob/blob.dmi', src, "nautdamage", MOB_LAYER+0.01) + I.appearance_flags = RESET_COLOR + if(overmind) + I.color = overmind.blobstrain.complementary_color + flick_overlay_view(I, src, 8) /mob/living/simple_animal/hostile/blob/blobbernaut/adjustHealth(amount, updating_health = TRUE, forced = FALSE) . = ..() diff --git a/code/modules/antagonists/blob/blob/blobs/shield.dm b/code/modules/antagonists/blob/blob/blobs/shield.dm index a2a6ce94d3..a3a1403e58 100644 --- a/code/modules/antagonists/blob/blob/blobs/shield.dm +++ b/code/modules/antagonists/blob/blob/blobs/shield.dm @@ -45,11 +45,8 @@ desc = "A solid wall of slightly twitching tendrils with a reflective glow." damaged_desc = "A wall of twitching tendrils with a reflective glow." icon_state = "blob_glow" + flags_ricochet = RICOCHET_SHINY point_return = 8 max_integrity = 100 brute_resist = 1 explosion_block = 2 - -/obj/structure/blob/shield/reflective/check_projectile_ricochet(obj/item/projectile/P) - return PROJECTILE_RICOCHET_FORCE - diff --git a/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm b/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm index 97b974e28f..f97e271e72 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/blazing_oil.dm @@ -36,6 +36,6 @@ M.adjust_fire_stacks(round(reac_volume/10)) M.IgniteMob() if(M) - M.apply_damage(0.8*reac_volume, BURN) + M.apply_damage(0.8*reac_volume, BURN, wound_bonus=CANT_WOUND) if(iscarbon(M)) M.emote("scream") diff --git a/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm b/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm index 9b8edcd0e5..f8ef269986 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/cryogenic_poison.dm @@ -22,7 +22,7 @@ M.reagents.add_reagent("frostoil", 0.3*reac_volume) M.reagents.add_reagent("ice", 0.3*reac_volume) M.reagents.add_reagent("cryogenic_poison", 0.3*reac_volume) - M.apply_damage(0.2*reac_volume, BRUTE) + M.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) /datum/reagent/blob/cryogenic_poison/on_mob_life(mob/living/carbon/M) M.adjustBruteLoss(0.3*REAGENTS_EFFECT_MULTIPLIER, 0) diff --git a/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm b/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm index 0e665603c9..45bf2b1e1d 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/electromagnetic_web.dm @@ -30,4 +30,4 @@ if(prob(reac_volume*2)) M.emp_act(EMP_LIGHT) if(M) - M.apply_damage(reac_volume, BURN) + M.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm b/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm index f8fd2e2f0d..3d005ba913 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/explosive_lattice.dm @@ -33,8 +33,8 @@ if(ROLE_BLOB in L.faction) //no friendly fire continue var/aoe_volume = ..(L, TOUCH, initial_volume, 0, L.get_permeability_protection(), O) - L.apply_damage(0.4*aoe_volume, BRUTE) + L.apply_damage(0.4*aoe_volume, BRUTE, wound_bonus=CANT_WOUND) if(M) - M.apply_damage(0.6*reac_volume, BRUTE) + M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) else - M.apply_damage(0.6*reac_volume, BRUTE) + M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm b/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm index fac3470c7a..8ccf2b9c99 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/networked_fibers.dm @@ -33,6 +33,6 @@ /datum/reagent/blob/networked_fibers/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) reac_volume = ..() - M.apply_damage(0.6*reac_volume, BRUTE) + M.apply_damage(0.6*reac_volume, BRUTE, wound_bonus=CANT_WOUND) if(M) - M.apply_damage(0.6*reac_volume, BURN) + M.apply_damage(0.6*reac_volume, BURN, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm b/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm index 6a984e66a2..11477712e7 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/pressurized_slime.dm @@ -44,7 +44,7 @@ T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = 5 SECONDS) M.adjust_fire_stacks(-(reac_volume / 10)) M.ExtinguishMob() - M.apply_damage(0.4*reac_volume, BRUTE) + M.apply_damage(0.4*reac_volume, BRUTE, wound_bonus=CANT_WOUND) if(M) M.apply_damage(0.4*reac_volume, OXY) if(M) diff --git a/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm b/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm index 00743c671e..5565135c63 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/replicating_foam.dm @@ -31,4 +31,4 @@ /datum/reagent/blob/replicating_foam/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) reac_volume = ..() - M.apply_damage(0.7*reac_volume, BRUTE) + M.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm b/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm index dbb3d6fb9b..9265158e1b 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/shifting_fragments.dm @@ -32,4 +32,4 @@ /datum/reagent/blob/shifting_fragments/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) reac_volume = ..() - M.apply_damage(0.7*reac_volume, BRUTE) + M.apply_damage(0.7*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm b/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm index d58fb5b37d..daad0068e2 100644 --- a/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm +++ b/code/modules/antagonists/blob/blob/blobstrains/synchronous_mesh.dm @@ -30,9 +30,9 @@ /datum/reagent/blob/synchronous_mesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O) reac_volume = ..() - M.apply_damage(0.2*reac_volume, BRUTE) + M.apply_damage(0.2*reac_volume, BRUTE, wound_bonus=CANT_WOUND) if(M && reac_volume) for(var/obj/structure/blob/B in range(1, M)) //if the target is completely surrounded, this is 2.4*reac_volume bonus damage, total of 2.6*reac_volume if(M) B.blob_attack_animation(M) //show them they're getting a bad time - M.apply_damage(0.3*reac_volume, BRUTE) + M.apply_damage(0.3*reac_volume, BRUTE, wound_bonus=CANT_WOUND) diff --git a/code/modules/antagonists/blob/blob/theblob.dm b/code/modules/antagonists/blob/blob/theblob.dm index 6a73dc579b..ed85726a4a 100644 --- a/code/modules/antagonists/blob/blob/theblob.dm +++ b/code/modules/antagonists/blob/blob/theblob.dm @@ -225,7 +225,7 @@ /obj/structure/blob/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/analyzer)) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) to_chat(user, "The analyzer beeps once, then reports:
    ") SEND_SOUND(user, sound('sound/machines/ping.ogg')) if(overmind) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index 47a98623db..4117fc2b36 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -10,27 +10,24 @@ // // Show as dead when... -/datum/antagonist/bloodsucker/proc/LifeTick()// Should probably run from life.dm, same as handle_changeling, but will be an utter pain to move - set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side. - var/notice_healing - while(owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src - if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_FAKEDEATH)) // Deduct Blood - AddBloodVolume(passive_blood_drain) // -.1 currently - if(HandleHealing(1)) // Heal - if(!notice_healing && owner.current.blood_volume > 0) - to_chat(owner, "The power of your blood begins knitting your wounds...") - notice_healing = TRUE - else if(notice_healing == TRUE) - notice_healing = FALSE // Apply Low Blood Effects - HandleStarving() // Death - HandleDeath() // Standard Update - update_hud()// Daytime Sleep in Coffin - if(SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker")) - if(istype(owner.current.loc, /obj/structure/closet/crate/coffin)) - Torpor_Begin() - // Wait before next pass - sleep(10) - FreeAllVassals() // Free my Vassals! (if I haven't yet) +/datum/antagonist/bloodsucker/proc/LifeTick() //Runs from BiologicalLife, handles all the bloodsucker constant proccesses + if(!owner || AmFinalDeath()) + return + if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_FAKEDEATH)) // Deduct Blood + AddBloodVolume(passive_blood_drain) // -.1 currently + if(HandleHealing(1)) // Heal + if(!notice_healing && owner.current.blood_volume > 0) + to_chat(owner, "The power of your blood begins knitting your wounds...") + notice_healing = TRUE + else if(notice_healing) + notice_healing = FALSE // Apply Low Blood Effects + HandleStarving() // Death + HandleDeath() // Standard Update + update_hud()// Daytime Sleep in Coffin + if(SSticker.mode.is_daylight() && !HAS_TRAIT_FROM(owner.current, TRAIT_FAKEDEATH, "bloodsucker")) + if(istype(owner.current.loc, /obj/structure/closet/crate/coffin)) + Torpor_Begin() + // Wait before next pass ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -272,13 +269,15 @@ /datum/antagonist/bloodsucker/AmFinalDeath() return owner && owner.AmFinalDeath() -/datum/antagonist/changeling/AmFinalDeath() - return owner && owner.AmFinalDeath() /datum/mind/proc/AmFinalDeath() return !current || QDELETED(current) || !isliving(current) || isbrain(current) || !get_turf(current) // NOTE: "isliving()" is not the same as STAT == CONSCIOUS. This is to make sure you're not a BORG (aka silicon) /datum/antagonist/bloodsucker/proc/FinalDeath() + //Dont bother if we are already supposed to be dead + if(FinalDeath) + return + FinalDeath = TRUE //We are now supposed to die. Lets not spam it. if(!iscarbon(owner.current)) //Check for non carbons. owner.current.gib() return @@ -308,6 +307,7 @@ + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // HUMAN FOOD diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 888db8193b..1fcffff810 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -37,6 +37,8 @@ var/had_toxlover var/level_bloodcost var/passive_blood_drain = -0.1 //The amount of blood we loose each bloodsucker life() tick + var/notice_healing //Var to see if you are healing for preventing spam of the chat message inform the user of such + var/FinalDeath //Have we reached final death? Used to prevent spam. // 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_NODECAP, TRAIT_NOGUT) @@ -50,7 +52,6 @@ AssignStarterPowersAndStats()// Give Powers & Stats forge_bloodsucker_objectives()// Objectives & Team update_bloodsucker_icons_added(owner.current, "bloodsucker") // Add Antag HUD - LifeTick() // Run Life Function . = ..() @@ -683,6 +684,8 @@ owner.current.hud_used.sunlight_display.invisibility = INVISIBILITY_ABSTRACT /datum/antagonist/bloodsucker/proc/update_hud(updateRank=FALSE) + if(FinalDeath) + return // No Hud? Get out. if(!owner.current.hud_used) return diff --git a/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm b/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm index 640c53946f..25de64fe34 100644 --- a/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm +++ b/code/modules/antagonists/bloodsucker/items/bloodsucker_organs.dm @@ -31,10 +31,6 @@ beating = 0 var/fakingit = 0 -/obj/item/organ/heart/vampheart/prepare_eat() - ..() - // Do cool stuff for eating vamp heart? - /obj/item/organ/heart/vampheart/Restart() beating = 0 // DONT run ..(). We don't want to start beating again. return 0 diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm index e85d3af5a0..a555677719 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_coffin.dm @@ -110,7 +110,7 @@ if (bloodsuckerdatum && bloodsuckerdatum.coffin == src) bloodsuckerdatum.coffin = null bloodsuckerdatum.lair = null - to_chat(resident, "You sense that the link with your coffin, your sacred place of rest, has been brokem! You will need to seek another.") + to_chat(resident, "You sense that the link with your coffin, your sacred place of rest, has been broken! You will need to seek another.") resident = null // Remove resident. Because this object isnt removed from the game immediately (GC?) we need to give them a way to see they don't have a home anymore. /obj/structure/closet/crate/coffin/can_open(mob/living/user) diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index 090ef45d89..536c07cd62 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -217,7 +217,7 @@ return FALSE return ..() -/obj/structure/bloodsucker/vassalrack/attack_hand(mob/user) +/obj/structure/bloodsucker/vassalrack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) //. = ..() // Taken from sacrificial altar in divine.dm //if(.) // return @@ -361,9 +361,9 @@ torture_time -= I.force / 4 torture_dmg_brute += I.force / 4 //torture_dmg_burn += I. - if(I.sharpness == IS_SHARP) + if(I.sharpness == SHARP_EDGED) torture_time -= 1 - else if(I.sharpness == IS_SHARP_ACCURATE) + else if(I.sharpness == SHARP_POINTY) torture_time -= 2 if(istype(I, /obj/item/weldingtool)) var/obj/item/weldingtool/welder = I @@ -469,7 +469,7 @@ . += {"This is a magical candle which drains at the sanity of the fools who havent yet accepted your master, as long as it is active.\n You can turn it on and off by clicking on it while you are next to it"} */ -/obj/structure/bloodsucker/candelabrum/attack_hand(mob/user) +/obj/structure/bloodsucker/candelabrum/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/datum/antagonist/vassal/T = user.mind.has_antag_datum(ANTAG_DATUM_VASSAL) if(AmBloodsucker(user) || istype(T)) toggle() diff --git a/code/modules/antagonists/bloodsucker/powers/feed.dm b/code/modules/antagonists/bloodsucker/powers/feed.dm index a113f9c083..caca020b32 100644 --- a/code/modules/antagonists/bloodsucker/powers/feed.dm +++ b/code/modules/antagonists/bloodsucker/powers/feed.dm @@ -226,7 +226,9 @@ playsound(get_turf(target), 'sound/effects/splat.ogg', 40, 1) if(ishuman(target)) var/mob/living/carbon/human/H = target - H.bleed_rate += 5 + var/obj/item/bodypart/head_part = H.get_bodypart(BODY_ZONE_HEAD) + if(head_part) + head_part.generic_bleedstacks += 5 target.add_splatter_floor(get_turf(target)) user.add_mob_blood(target) // Put target's blood on us. The donor goes in the ( ) target.add_mob_blood(target) diff --git a/code/modules/antagonists/bloodsucker/powers/fortitude.dm b/code/modules/antagonists/bloodsucker/powers/fortitude.dm index 76f3cc77a4..740ec81782 100644 --- a/code/modules/antagonists/bloodsucker/powers/fortitude.dm +++ b/code/modules/antagonists/bloodsucker/powers/fortitude.dm @@ -23,6 +23,7 @@ ADD_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude") ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude") ADD_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude") + ADD_TRAIT(user, TRAIT_NORUNNING, "fortitude") if(ishuman(owner)) var/mob/living/carbon/human/H = owner fortitude_resist = max(0.3, 0.7 - level_current * 0.1) @@ -53,6 +54,7 @@ REMOVE_TRAIT(user, TRAIT_PIERCEIMMUNE, "fortitude") REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude") REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude") + REMOVE_TRAIT(user, TRAIT_NORUNNING, "fortitude") if(!ishuman(owner)) return var/mob/living/carbon/human/H = owner diff --git a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm index eea80d52f3..efdd312c6e 100644 --- a/code/modules/antagonists/bloodsucker/powers/mesmerize.dm +++ b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm @@ -128,11 +128,9 @@ target.face_atom(L) target.Stun(power_time) to_chat(L, "[target] is fixed in place by your hypnotic gaze.") - target.next_move = world.time + power_time // <--- Use direct change instead. We want an unmodified delay to their next move // target.changeNext_move(power_time) // check click.dm - target.notransform = TRUE // <--- Fuck it. We tried using next_move, but they could STILL resist. We're just doing a hard freeze. + target.DelayNextAction(power_time) spawn(power_time) if(istype(target) && success) - target.notransform = FALSE 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/bloodsucker/powers/recuperate.dm b/code/modules/antagonists/bloodsucker/powers/recuperate.dm index 6b8795ea02..90a2e3ff38 100644 --- a/code/modules/antagonists/bloodsucker/powers/recuperate.dm +++ b/code/modules/antagonists/bloodsucker/powers/recuperate.dm @@ -27,8 +27,9 @@ C.blood_volume -= 0.2 C.adjustStaminaLoss(-15) // Stop Bleeding - if(istype(H) && H.bleed_rate > 0 && rand(20) == 0) - H.bleed_rate -- + if(istype(H) && H.is_bleeding() && rand(20) == 0) + for(var/obj/item/bodypart/part in H.bodyparts) + part.generic_bleedstacks -- C.Jitter(5) sleep(10) // DONE! diff --git a/code/modules/antagonists/bloodsucker/powers/trespass.dm b/code/modules/antagonists/bloodsucker/powers/trespass.dm index c91b924bb7..56b72a562e 100644 --- a/code/modules/antagonists/bloodsucker/powers/trespass.dm +++ b/code/modules/antagonists/bloodsucker/powers/trespass.dm @@ -20,7 +20,7 @@ . = ..() if(!.) return - if(owner.notransform || !get_turf(owner)) + if(owner.mob_transforming || !get_turf(owner)) return FALSE return TRUE @@ -81,9 +81,7 @@ var/mist_delay = max(5, 20 - level_current * 2.5) // Level up and do this faster. // Freeze Me - user.next_move = world.time + mist_delay user.Stun(mist_delay, ignore_canstun = TRUE) - user.notransform = TRUE user.density = FALSE var/invis_was = user.invisibility user.invisibility = INVISIBILITY_MAXIMUM @@ -96,7 +94,6 @@ // Move & Freeze if(isturf(target_turf)) do_teleport(owner, target_turf, no_effects=TRUE, channel = TELEPORT_CHANNEL_QUANTUM) // in teleport.dm? - user.next_move = world.time + mist_delay / 2 user.Stun(mist_delay / 2, ignore_canstun = TRUE) // Wait... @@ -104,9 +101,7 @@ // Un-Hide & Freeze user.dir = get_dir(my_turf, target_turf) - user.next_move = world.time + mist_delay / 2 user.Stun(mist_delay / 2, ignore_canstun = TRUE) - user.notransform = FALSE user.density = 1 user.invisibility = invis_was diff --git a/code/modules/antagonists/bloodsucker/powers/veil.dm b/code/modules/antagonists/bloodsucker/powers/veil.dm index 422d645ad2..b170b9d442 100644 --- a/code/modules/antagonists/bloodsucker/powers/veil.dm +++ b/code/modules/antagonists/bloodsucker/powers/veil.dm @@ -101,7 +101,7 @@ H.update_hair() H.update_body_parts() - // Wait here til we deactivate power or go unconscious + // Wait here until we deactivate power or go unconscious var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) while (ContinueActive(owner) && istype(bloodsuckerdatum))//active && owner && owner.stat == CONSCIOUS) bloodsuckerdatum.AddBloodVolume(-0.2) diff --git a/code/modules/antagonists/changeling/cellular_emporium.dm b/code/modules/antagonists/changeling/cellular_emporium.dm index b2c1a52a4a..2538394db7 100644 --- a/code/modules/antagonists/changeling/cellular_emporium.dm +++ b/code/modules/antagonists/changeling/cellular_emporium.dm @@ -13,10 +13,13 @@ changeling = null . = ..() -/datum/cellular_emporium/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/cellular_emporium/ui_state(mob/user) + return GLOB.always_state + +/datum/cellular_emporium/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "cellular_emporium", name, 900, 480, master_ui, state) + ui = new(user, src, "CellularEmporium", name) ui.open() /datum/cellular_emporium/ui_data(mob/user) diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm index 35639bfd97..d06ebe9d9d 100644 --- a/code/modules/antagonists/changeling/changeling.dm +++ b/code/modules/antagonists/changeling/changeling.dm @@ -20,6 +20,8 @@ var/datum/changelingprofile/first_prof = null var/dna_max = 6 //How many extra DNA strands the changeling can store for transformation. var/absorbedcount = 0 + /// did we get succed by another changeling + var/hostile_absorbed = FALSE var/trueabsorbs = 0//dna gained using absorb, not dna sting var/chem_charges = 20 var/chem_storage = 75 @@ -397,20 +399,31 @@ escape_objective_possible = FALSE break var/changeling_objective = rand(1,3) + var/generic_absorb_objective = FALSE + var/multiple_lings = length(get_antag_minds(/datum/antagonist/changeling,TRUE)) > 1 switch(changeling_objective) if(1) - var/datum/objective/absorb/absorb_objective = new - absorb_objective.owner = owner - absorb_objective.gen_amount_goal(6, 8) - objectives += absorb_objective + generic_absorb_objective = TRUE if(2) - var/datum/objective/absorb_changeling/ac = new - ac.owner = owner - objectives += ac + if(multiple_lings) + var/datum/objective/absorb_changeling/ac = new + ac.owner = owner + objectives += ac + else + generic_absorb_objective = TRUE if(3) - var/datum/objective/absorb_most/ac = new - ac.owner = owner - objectives += ac + if(multiple_lings) + var/datum/objective/absorb_most/ac = new + ac.owner = owner + objectives += ac + else + generic_absorb_objective = TRUE + + if(generic_absorb_objective) + var/datum/objective/absorb/absorb_objective = new + absorb_objective.owner = owner + absorb_objective.gen_amount_goal(6, 8) + objectives += absorb_objective if(prob(60)) if(prob(85)) diff --git a/code/modules/antagonists/changeling/powers/absorb.dm b/code/modules/antagonists/changeling/powers/absorb.dm index 3e2ff6f3dd..208fefee70 100644 --- a/code/modules/antagonists/changeling/powers/absorb.dm +++ b/code/modules/antagonists/changeling/powers/absorb.dm @@ -92,7 +92,7 @@ var/datum/antagonist/changeling/target_ling = target.mind.has_antag_datum(/datum/antagonist/changeling) - if(target_ling)//If the target was a changeling, suck out their extra juice and objective points! + if(target_ling && !target_ling.hostile_absorbed)//If the target was a changeling, suck out their extra juice and objective points! to_chat(user, "[target] was one of us. We have absorbed their power.") target_ling.remove_changeling_powers() changeling.geneticpoints += round(target_ling.geneticpoints/2) @@ -102,6 +102,7 @@ changeling.chem_storage += round(target_ling.chem_storage/2) changeling.chem_charges += min(target_ling.chem_charges, changeling.chem_storage) target_ling.chem_charges = 0 + target_ling.hostile_absorbed = TRUE target_ling.chem_storage = 0 changeling.absorbedcount += (target_ling.absorbedcount) target_ling.stored_profiles.len = 1 diff --git a/code/modules/antagonists/changeling/powers/fleshmend.dm b/code/modules/antagonists/changeling/powers/fleshmend.dm index afef2a10c7..0299abb09a 100644 --- a/code/modules/antagonists/changeling/powers/fleshmend.dm +++ b/code/modules/antagonists/changeling/powers/fleshmend.dm @@ -1,6 +1,6 @@ /obj/effect/proc_holder/changeling/fleshmend name = "Fleshmend" - 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." + desc = "Our flesh rapidly regenerates, healing our burns, bruises, and shortness of breath, as well as hiding all of our scars. Costs 20 chemicals." 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 diff --git a/code/modules/antagonists/changeling/powers/humanform.dm b/code/modules/antagonists/changeling/powers/humanform.dm index 91119e1c06..c38bfe3b5b 100644 --- a/code/modules/antagonists/changeling/powers/humanform.dm +++ b/code/modules/antagonists/changeling/powers/humanform.dm @@ -21,7 +21,7 @@ var/datum/changelingprofile/chosen_prof = changeling.get_dna(chosen_name) if(!chosen_prof) return - if(!user || user.notransform) + if(!user || user.mob_transforming) return 0 to_chat(user, "We transform our appearance.") diff --git a/code/modules/antagonists/changeling/powers/lesserform.dm b/code/modules/antagonists/changeling/powers/lesserform.dm index 1f9ca0b3ff..f3690ef5c5 100644 --- a/code/modules/antagonists/changeling/powers/lesserform.dm +++ b/code/modules/antagonists/changeling/powers/lesserform.dm @@ -11,9 +11,9 @@ //Transform into a monkey. /obj/effect/proc_holder/changeling/lesserform/sting_action(mob/living/carbon/human/user) - if(!user || user.notransform) + if(!user || user.mob_transforming) return 0 to_chat(user, "Our genes cry out!") user.monkeyize(TR_KEEPITEMS | TR_KEEPIMPLANTS | TR_KEEPORGANS | TR_KEEPDAMAGE | TR_KEEPVIRUS | TR_KEEPSE) - return TRUE \ No newline at end of file + return TRUE diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index e4417a6d64..24288be078 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -164,7 +164,9 @@ armour_penetration = 20 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED + wound_bonus = -60 + bare_wound_bonus = 20 var/can_drop = FALSE var/fake = FALSE total_mass = TOTAL_MASS_HAND_REPLACEMENT diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm index 1b27fa9694..a88422e7eb 100644 --- a/code/modules/antagonists/changeling/powers/regenerate.dm +++ b/code/modules/antagonists/changeling/powers/regenerate.dm @@ -29,6 +29,9 @@ C.emote("scream") C.regenerate_limbs(1) C.regenerate_organs() + for(var/i in C.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.remove_wound() if(!user.getorganslot(ORGAN_SLOT_BRAIN)) var/obj/item/organ/brain/B if(C.has_dna() && C.dna.species.mutant_brain) diff --git a/code/modules/antagonists/changeling/powers/revive.dm b/code/modules/antagonists/changeling/powers/revive.dm index 6c2220648d..f193fb6736 100644 --- a/code/modules/antagonists/changeling/powers/revive.dm +++ b/code/modules/antagonists/changeling/powers/revive.dm @@ -36,9 +36,10 @@ . = ..() if(!.) return - - if(HAS_TRAIT(user, CHANGELING_DRAIN) || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA)))) - var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) + var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling) + if(!changeling) + return FALSE + if(changeling.hostile_absorbed || ((user.stat != DEAD) && !(HAS_TRAIT(user, TRAIT_DEATHCOMA)))) changeling.purchasedpowers -= src return FALSE diff --git a/code/modules/antagonists/changeling/powers/spiders.dm b/code/modules/antagonists/changeling/powers/spiders.dm index 6bd15fea92..69900ea8f9 100644 --- a/code/modules/antagonists/changeling/powers/spiders.dm +++ b/code/modules/antagonists/changeling/powers/spiders.dm @@ -1,7 +1,7 @@ /obj/effect/proc_holder/changeling/spiders name = "Spread Infestation" desc = "Our form divides, creating arachnids which will grow into deadly beasts." - helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 3 DNA gained through Absorb, and not through DNA sting. This ability is very loud, and will guarantee that our blood will react violently to heat." + helptext = "The spiders are thoughtless creatures, and may attack their creators when fully grown. Requires at least 3 DNA gained through Absorb (regardless of current amount), and not through DNA sting. This ability is very loud, and will guarantee that our blood will react violently to heat." chemical_cost = 45 dna_cost = 1 loudness = 4 diff --git a/code/modules/antagonists/changeling/powers/transform.dm b/code/modules/antagonists/changeling/powers/transform.dm index 795ba772d6..8e3a36740b 100644 --- a/code/modules/antagonists/changeling/powers/transform.dm +++ b/code/modules/antagonists/changeling/powers/transform.dm @@ -17,8 +17,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/glasses/changeling/attack_hand(mob/user) +/obj/item/clothing/glasses/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -33,8 +32,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/under/changeling/attack_hand(mob/user) +/obj/item/clothing/under/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -50,8 +48,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/suit/changeling/attack_hand(mob/user) +/obj/item/clothing/suit/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -65,8 +62,7 @@ . = ..() ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/head/changeling/attack_hand(mob/user) +/obj/item/clothing/head/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -81,8 +77,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/shoes/changeling/attack_hand(mob/user) +/obj/item/clothing/shoes/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -97,8 +92,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/gloves/changeling/attack_hand(mob/user) +/obj/item/clothing/gloves/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -113,8 +107,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/mask/changeling/attack_hand(mob/user) +/obj/item/clothing/mask/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) @@ -131,8 +124,7 @@ ADD_TRAIT(src, TRAIT_NODROP, CHANGELING_TRAIT) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/changeling/attack_hand(mob/user) +/obj/item/changeling/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.mind && user.mind.has_antag_datum(/datum/antagonist/changeling)) to_chat(user, "You reabsorb [src] into your body.") qdel(src) diff --git a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm index 21d0035ef1..3ea4668df8 100644 --- a/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm +++ b/code/modules/antagonists/clockcult/clock_effects/city_of_cogs_rift.dm @@ -36,8 +36,7 @@ return . = ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/clockwork/city_of_cogs_rift/attack_hand(atom/movable/AM) +/obj/effect/clockwork/city_of_cogs_rift/on_attack_hand(atom/movable/AM) beckon(AM) /obj/effect/clockwork/city_of_cogs_rift/Bumped(atom/movable/AM) diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm index 036ea37ada..454870d1e1 100644 --- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm +++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm @@ -27,8 +27,7 @@ /obj/effect/clockwork/sigil/attack_tk(mob/user) return //you can't tk stomp sigils, but you can hit them with something -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/clockwork/sigil/attack_hand(mob/user) +/obj/effect/clockwork/sigil/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user) && !user.stat) if(is_servant_of_ratvar(user) && user.a_intent != INTENT_HARM) return ..() @@ -217,6 +216,20 @@ else if(get_clockwork_power()) to_chat(L, "You feel a slight, static shock.") +/obj/effect/clockwork/sigil/transmission/process() + var/power_drained = 0 + var/power_mod = 0.005 + for(var/t in spiral_range_turfs(SIGIL_ACCESS_RANGE, src)) + var/turf/T = t + for(var/M in T) + var/atom/movable/A = M + power_drained += A.power_drain(TRUE) + + CHECK_TICK + + adjust_clockwork_power(power_drained * power_mod * 15) + new /obj/effect/temp_visual/ratvar/sigil/transmission(loc, 1 + (power_drained * 0.0035)) + /obj/effect/clockwork/sigil/transmission/proc/charge_cyborg(mob/living/silicon/robot/cyborg) if(!cyborg_checks(cyborg)) return @@ -392,3 +405,49 @@ animation_number = initial(animation_number) sigil_active = FALSE animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW) + +/obj/effect/clockwork/sigil/rite + name = "radiant sigil" + desc = "A glowing sigil glowing with barely-contained power." + clockwork_desc = "A sigil that will allow you to perform certain rites on it, provided you have access to sufficient power and materials." + icon_state = "sigiltransmission" //am big lazy - recolored transmission sigil + sigil_name = "Sigil of Rites" + alpha = 255 + var/performing_rite = FALSE + color = "#ffe63a" + light_color = "#ffe63a" + light_range = 1 + light_power = 2 + +/obj/effect/clockwork/sigil/rite/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) + . = ..() + if(.) + return + if(!is_servant_of_ratvar(user)) + return + if(!GLOB.all_clockwork_rites.len) //Did we already generate the list? + generate_all_rites() + if(performing_rite) + to_chat(user, "Someone is already performing a rite here!") + return + var/list/possible_rites = list() + for(var/datum/clockwork_rite/R in GLOB.all_clockwork_rites) + possible_rites[R] = R + var/input_key = input(user, "Choose a rite", "Choosing a rite") as null|anything in possible_rites + if(!input_key) + return + var/datum/clockwork_rite/CR = possible_rites[input_key] + if(!CR) + return + var/choice = alert(user, "What to do with this rite?", "What to do?", "Cast", "Show Info", "Cancel") + switch(choice) + if("Cast") + CR.try_cast(src, user) + if("Show Info") + var/infotext = CR.build_info() + to_chat(user, infotext) + +/obj/effect/clockwork/sigil/rite/proc/generate_all_rites() //The first time someone uses a sigil of rites, all the rites are actually generated. No need to have a bunch of random datums laying around all the time. + for(var/V in subtypesof(/datum/clockwork_rite)) + var/datum/clockwork_rite/R = new V + GLOB.all_clockwork_rites += R diff --git a/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm b/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm index 36aaa27716..00c52e4a59 100644 --- a/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm +++ b/code/modules/antagonists/clockcult/clock_effects/spatial_gateway.dm @@ -14,6 +14,8 @@ var/uses = 1 //How many objects or mobs can go through the portal var/obj/effect/clockwork/spatial_gateway/linked_gateway //The gateway linked to this one var/timerid + var/is_stable = FALSE + var/busy = FALSE //If someone is already working on closing the gateway, only needed for stable gateways but in the parent to not need typecasting /obj/effect/clockwork/spatial_gateway/Initialize() . = ..() @@ -31,11 +33,16 @@ clockwork_desc = "A gateway in reality. It can both send and receive objects." else clockwork_desc = "A gateway in reality. It can only [sender ? "send" : "receive"] objects." - timerid = QDEL_IN(src, lifetime) + if(is_stable) + return + timerid = QDEL_IN(src, lifetime) //We only need this if the gateway is not stable //set up a gateway with another gateway /obj/effect/clockwork/spatial_gateway/proc/setup_gateway(obj/effect/clockwork/spatial_gateway/gatewayB, set_duration, set_uses, two_way) - if(!gatewayB || !set_duration || !uses) + if(!gatewayB) + return FALSE + + if((!set_duration || !uses) && !is_stable) return FALSE linked_gateway = gatewayB gatewayB.linked_gateway = src @@ -55,7 +62,7 @@ /obj/effect/clockwork/spatial_gateway/examine(mob/user) . = ..() if(is_servant_of_ratvar(user) || isobserver(user)) - . += "It has [uses] use\s remaining." + . += " [is_stable ? "It is stabilised and can be used as much as is neccessary." : "It has [uses] use\s remaining."]" //ATTACK GHOST IGNORING PARENT RETURN VALUE /obj/effect/clockwork/spatial_gateway/attack_ghost(mob/user) @@ -63,8 +70,7 @@ user.forceMove(get_turf(linked_gateway)) ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/clockwork/spatial_gateway/attack_hand(mob/living/user) +/obj/effect/clockwork/spatial_gateway/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(!uses) return FALSE if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling)) @@ -122,9 +128,9 @@ /obj/effect/clockwork/spatial_gateway/Bumped(atom/movable/AM) ..() if(!QDELETED(AM)) - pass_through_gateway(AM, FALSE) + pass_through_gateway(AM) -/obj/effect/clockwork/spatial_gateway/proc/pass_through_gateway(atom/movable/A, no_cost) +/obj/effect/clockwork/spatial_gateway/proc/pass_through_gateway(atom/movable/A, no_cost = FALSE) if(!linked_gateway) qdel(src) return FALSE @@ -198,6 +204,10 @@ return procure_gateway(invoker, time_duration, gateway_uses, two_way) var/istargetobelisk = istype(target, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) var/issrcobelisk = istype(src, /obj/structure/destructible/clockwork/powered/clockwork_obelisk) + if(!issrcobelisk && target.z != invoker.z && (is_reebe(invoker.z) || is_reebe(target.z)) && !GLOB.ratvar_awakens) //You need obilisks to get from and to reebe. Costs alot of power, unless you use stable gateways. + to_chat(invoker, "The distance between reebe and the mortal realm is far too vast to bridge with a gateway your slab can create, my child. \ + Use an obilisk instead!") + return procure_gateway(invoker, time_duration, gateway_uses, two_way) if(issrcobelisk) if(!anchored) to_chat(invoker, "[src] is no longer secured!") @@ -218,12 +228,63 @@ gateway_uses = round(gateway_uses * (2 * efficiency), 1) time_duration = round(time_duration * (2 * efficiency), 1) CO.active = TRUE //you'd be active in a second but you should update immediately - invoker.visible_message("The air in front of [invoker] ripples before suddenly tearing open!", \ - "With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [DisplayTimeText(time_duration)] and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].") - var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir)) - var/obj/effect/clockwork/spatial_gateway/S2 = new(istargetobelisk ? get_turf(target) : get_step(get_turf(target), target.dir)) + if(issrcobelisk && istargetobelisk && src.z != target.z && (is_reebe(src.z) || is_reebe(target.z))) + invoker.visible_message("The air in front of [invoker] ripples before suddenly tearing open!", \ + "With a word, you rip open a stable two-way rift between reebe and the mortal realm.") + var/obj/effect/clockwork/spatial_gateway/stable/stable_S1 = new(get_turf(src)) + var/obj/effect/clockwork/spatial_gateway/stable/stable_S2 = new(get_turf(target)) + stable_S1.setup_gateway(stable_S2) + stable_S2.visible_message("The air in front of [target] ripples before suddenly tearing open!") + else + invoker.visible_message("The air in front of [invoker] ripples before suddenly tearing open!", \ + "With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [DisplayTimeText(time_duration)] and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].") + var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir)) + var/obj/effect/clockwork/spatial_gateway/S2 = new(istargetobelisk ? get_turf(target) : get_step(get_turf(target), target.dir)) - //Set up the portals now that they've spawned - S1.setup_gateway(S2, time_duration, gateway_uses, two_way) - S2.visible_message("The air in front of [target] ripples before suddenly tearing open!") + //Set up the portals now that they've spawned + S1.setup_gateway(S2, time_duration, gateway_uses, two_way) + S2.visible_message("The air in front of [target] ripples before suddenly tearing open!") return TRUE + +//Stable Gateway: Used to travel to and from reebe without any further powercost. Needs a clockwork obilisk to keep active, but stays active as long as it is not deactivated via an null rod or a slab, or the obilisk is destroyed +/obj/effect/clockwork/spatial_gateway/stable + name = "stable gateway" + is_stable = TRUE + +/obj/effect/clockwork/spatial_gateway/stable/ex_act(severity) + if(severity == 1) + start_shutdown() //Yes, you can chain devastation-level explosions to delay a gateway shutdown, if you somehow manage to do it without breaking the obelisk. Is it worth it? Probably not. + return TRUE + return FALSE + +/obj/effect/clockwork/spatial_gateway/stable/setup_gateway(obj/effect/clockwork/spatial_gateway/stable/gatewayB) //Reduced setup call due to some things being irrelevant for stable gateways + return ..(gatewayB, 1, 1, TRUE) //Uses and time irrelevant due to is_stable + +/obj/effect/clockwork/spatial_gateway/stable/attackby(obj/item/I, mob/living/user, params) + if(!istype(I, /obj/item/clockwork/slab) || !is_servant_of_ratvar(user) || busy) + return ..() + busy = TRUE + linked_gateway.busy = TRUE + user.visible_message("The rift begins to ripple as [user] points [user.p_their()] slab at it!", " You begin to shutdown the stabilised gateway with your slab.") + linked_gateway.visible_message("") + var/datum/beam/B = user.Beam(src, icon_state = "nzcrentrs_power", maxdistance = 50, time = 80) //Not too fancy, but this'll do.. for now. + if(do_after(user, 80, target = src)) //Eight seconds to initiate the closing, then another two before is closes. + to_chat(user, "You successfully set the gateway to shutdown in another two seconds.") + start_shutdown() + qdel(B) + busy = FALSE + linked_gateway.busy = FALSE + return TRUE + +/obj/effect/clockwork/spatial_gateway/stable/proc/start_shutdown() + deltimer(timerid) + deltimer(linked_gateway.timerid) + timerid = QDEL_IN(src, 20) + linked_gateway.timerid = QDEL_IN(linked_gateway, 20) + animate(src, alpha = 0, transform = matrix()*2, time = 20, flags = ANIMATION_END_NOW) + animate(linked_gateway, alpha = 0, transform = matrix()*2, time = 20, flags = ANIMATION_END_NOW) + src.visible_message("[src] begins to destabilise!") + linked_gateway.visible_message("[linked_gateway] begins to destabilise!") + +/obj/effect/clockwork/spatial_gateway/stable/pass_through_gateway(atom/movable/A, no_cost = TRUE) + return ..() \ No newline at end of file diff --git a/code/modules/antagonists/clockcult/clock_helpers/clock_rites.dm b/code/modules/antagonists/clockcult/clock_helpers/clock_rites.dm new file mode 100644 index 0000000000..7dabb18f03 --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_helpers/clock_rites.dm @@ -0,0 +1,196 @@ +//This file is for clock rites, mainly used by the Sigil of Rites in clock_sigils.dm +//The rites themselves are in this file to prevent bloating the other file too much, aswell as for easier access + +#define INFINITE -1 + +//The base clockwork rite. This should never be visible +/datum/clockwork_rite + var/name = "Rite of THE frog" //The name of the rite + var/desc = "This rite is used to summon the legendary frog whose-name-shall-not-be-spoken, ender of many worlds." //What does this rite do? Shown to cultists if they choose 'Show Info' after selecting the rite. + var/list/required_ingredients = list(/obj/item/clockwork) //What does this rite require? + var/power_cost = 0 //How much power does this rite cost.. or does it even add power? + var/requires_human = FALSE //Does the rite require a ../carbon/human on the rune? + var/must_be_servant = TRUE //If the above is true, does the human need to be a servant? + var/target_can_be_invoker = TRUE //Does this rite work if the invoker is also the target? + var/cast_time = 0 //How long does the rite take to cast? + var/limit = INFINITE //How often can this rite be used per round? Set this to INFINITE for unlimited, 0 for disallowed, anything above 0 for a limit + var/times_used = 0 //How often has the rite already been used this shift? + var/rite_cast_sound = 'sound/items/bikehorn.ogg' //The sound played when successfully casting the rite. If it honks, the one adding the rite forgot to set one (or was just lazy). + +/datum/clockwork_rite/proc/try_cast(var/obj/effect/clockwork/sigil/rite/R, var/mob/living/invoker) //Performs a ton of checks to see if the invoker can cast the rite + if(!istype(R)) + return FALSE + if(!R || !R.loc) + return FALSE + var/turf/T = R.loc + if(!T) //Uh oh something is fucky + return FALSE + + if(limit != INFINITE && times_used >= limit) //Is the limit on casts exceeded? + to_chat(invoker, "There are no more uses left for this rite!") + return FALSE + + var/mob/living/carbon/human/H //This is only used if requires_human is TRUE + if(requires_human) //In case this requires a target + for(var/mob/living/carbon/human/possible_H in T) + if((!must_be_servant || is_servant_of_ratvar(possible_H)) && (target_can_be_invoker || invoker != possible_H)) + H = possible_H + break + if(!H) + to_chat(invoker, "There is no target for the rite on the sigil!") + return FALSE + + if(required_ingredients.len) //In case this requires materials + var/is_missing_materials = FALSE + for(var/I in required_ingredients) + var/obj/item/Material = locate(I) in T + if(!Material) + is_missing_materials = TRUE + break + if(is_missing_materials) + var/still_required_string = "" + for(var/i = 1 to required_ingredients.len) + var/obj/O = required_ingredients[i] + if(i != 1) + still_required_string += ", " + still_required_string += "a [initial(O.name)]" + to_chat(invoker, "There are still materials missing for this rite. You require [still_required_string].") + return FALSE + + if(power_cost) //If this costs power + if(!get_clockwork_power(power_cost)) + to_chat(invoker, "There is not enough power for this rite!") + return FALSE + R.performing_rite = TRUE + if(!do_after(invoker, cast_time, target = R)) + to_chat(invoker, "Your rite is disrupted.") + R.performing_rite = FALSE + return FALSE + . = cast(invoker, T, H) + if(!.) + to_chat(invoker, " You fail casting [name]") + post_cast(FALSE) + else + to_chat(invoker, "You successfully cast [name]") + post_cast(TRUE) + R.performing_rite = FALSE + return + +/datum/clockwork_rite/proc/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target) //Casts the rite and uses up ingredients. Doublechecks some things to prevent bypassing some restrictions via funky timing or badminnery. + if(!T || !invoker) + return FALSE + if(requires_human && !target) + return FALSE + if(power_cost && !get_clockwork_power(power_cost)) + return FALSE + adjust_clockwork_power(-power_cost) + if(limit != INFINITE && times_used >= limit) + return FALSE + if(required_ingredients.len) + var/is_missing_materials = FALSE + for(var/I in required_ingredients) + var/obj/item/Material = locate(I) in T + if(!Material) + is_missing_materials = TRUE + break + qdel(Material) + if(is_missing_materials) + return FALSE + playsound(T, rite_cast_sound, 50, 2) + return TRUE + +/datum/clockwork_rite/proc/post_cast(var/cast_succeeded) + if(cast_succeeded) + times_used++ + return TRUE + +/datum/clockwork_rite/proc/build_info() //Constructs the info text of a given rite, based on the vars of the rite + . = "" + . += "This is the [name].\n" + . += "[desc]\n" + . += "It requires: " + if(required_ingredients.len) + var/material_string = "" + for(var/i = 1 to required_ingredients.len) + var/obj/O = required_ingredients[i] + if(i != 1) + material_string += ", " + material_string += "a [initial(O.name)]" + . += "[material_string].\n" + else + . += "no materials.\n" + . += "It [power_cost >= 0 ? "costs" : "generates"] [power_cost ? "[power_cost]" : "no"] power.\n" + . += "It requires [requires_human ? " a human" : " no"] target.\n" + if(requires_human) + . += "The target [must_be_servant ? "cannot be" : "can be"] a nonservant.\n" + . += "The target [target_can_be_invoker ? "can be" : "cannot be"] the invoker.\n" + . += "It requires [cast_time/10] seconds to cast.\n" + . += "It has been used [times_used] time[times_used != 1 ? "s" : ""], out of [limit != INFINITE ? "[limit]" : "infinite"] available uses." + +//Adds a organ or cybernetic implant to a servant without the need for surgery. Cannot be used with brains for.. reasons. +/datum/clockwork_rite/advancement + name = "Rite of Advancement" + desc = "This rite is used to augment a servant with organs or cybernetic implants. The organ of choice, aswell as the servant and the required ingredients must be placed on the sigil for this rite to take place." + required_ingredients = list(/obj/item/assembly/prox_sensor, /obj/item/stock_parts/cell) + power_cost = 500 + requires_human = TRUE + cast_time = 40 + rite_cast_sound = 'sound/magic/blind.ogg' + +/datum/clockwork_rite/advancement/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target) + var/obj/item/organ/O = locate(/obj/item/organ) in T + if(!O) + return FALSE + if(istype(O, /obj/item/organ/brain)) //NOPE + return FALSE + . = ..() + if(!.) + return FALSE + O.Insert(target) + new /obj/effect/temp_visual/ratvar/sigil/transgression(T) + +//Heals all wounds (not damage) on the target, causing toxloss proportional to amount of wounds healed. 10 damage per wound. +/datum/clockwork_rite/treat_wounds + name = "Rite of Woundmending" + desc = "This rite is used to heal wounds of the servant on the rune. It causes toxins damage proportional to the amount of wounds healed. This can be lethal if performed on an critically injured target." + required_ingredients = list(/obj/item/stock_parts/cell, /obj/item/healthanalyzer, /obj/item/reagent_containers/food/drinks/bottle/holyoil) + power_cost = 300 + requires_human = TRUE + must_be_servant = FALSE + target_can_be_invoker = FALSE + cast_time = 80 + rite_cast_sound = 'sound/magic/staff_healing.ogg' + +/datum/clockwork_rite/treat_wounds/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target) + if(!target) + return FALSE + if(!target.all_wounds.len) + to_chat(invoker, "This one does not require mending.") + return FALSE + .= ..() + if(!.) + return FALSE + target.adjustToxLoss(10 * target.all_wounds.len) + QDEL_LIST(target.all_wounds) + to_chat(target, "You feel your wounds heal, but are overcome with deep nausea.") + new /obj/effect/temp_visual/ratvar/sigil/vitality(T) + +//Summons a brass claw implant on the sigil, which can extend a claw that benefits from repeatedly attacking a single target. Can only be cast a limited amount of times. +/datum/clockwork_rite/summon_claw + name = "Rite of the Claw" + desc = "Summons a special arm implant that, when added to a servant's limb, will allow them to extend and retract a claw at will. Don't leave any implants you want to keep on this rune when casting the rite." + required_ingredients = list(/obj/item/stock_parts/cell, /obj/item/organ/cyberimp, /obj/item/assembly/flash) + power_cost = 1000 + cast_time = 60 + limit = 4 + rite_cast_sound = 'sound/magic/clockwork/fellowship_armory.ogg' + +/datum/clockwork_rite/summon_claw/cast(var/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target) + . = ..() + if(!.) + return FALSE + var/obj/item/organ/cyberimp/arm/clockwork/claw/CL = new /obj/item/organ/cyberimp/arm/clockwork/claw(T) + CL.visible_message("[CL] materialises out of thin air!") + new /obj/effect/temp_visual/ratvar/sigil/transmission(T,2) + +#undef INFINITE diff --git a/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm b/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm index e5497d7c9f..66e20b6e87 100644 --- a/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm +++ b/code/modules/antagonists/clockcult/clock_helpers/scripture_checks.dm @@ -38,10 +38,11 @@ set_slab.update_quickbind() /proc/generate_all_scripture() - if(!GLOB.all_scripture.len) - for(var/V in sortList(subtypesof(/datum/clockwork_scripture), /proc/cmp_clockscripture_priority)) - var/datum/clockwork_scripture/S = new V - GLOB.all_scripture[S.type] = S + if(GLOB.all_scripture.len) + return + for(var/V in sortList(subtypesof(/datum/clockwork_scripture) - list(/datum/clockwork_scripture/channeled, /datum/clockwork_scripture/create_object, /datum/clockwork_scripture/create_object/construct), /proc/cmp_clockscripture_priority)) + var/datum/clockwork_scripture/S = new V + GLOB.all_scripture[S.type] = S //changes construction value /proc/change_construction_value(amount) diff --git a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm index 81ad7ddc26..89ed669e7b 100644 --- a/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm +++ b/code/modules/antagonists/clockcult/clock_helpers/slab_abilities.dm @@ -113,8 +113,7 @@ for(var/i in 1 to healseverity) new /obj/effect/temp_visual/heal(targetturf, "#1E8CE1") if(totaldamage) - L.adjustBruteLoss(-brutedamage) - L.adjustFireLoss(-burndamage) + L.heal_overall_damage(brutedamage, burndamage, only_organic = FALSE) //Maybe a machine god shouldn't murder augmented followers instead of healing them L.adjustOxyLoss(-oxydamage) L.adjustToxLoss(totaldamage * 0.5, TRUE, TRUE) clockwork_say(ranged_ability_user, text2ratvar("[has_holy_water ? "Heal tainted" : "Mend wounded"] flesh!")) diff --git a/code/modules/antagonists/clockcult/clock_items/clock_augments.dm b/code/modules/antagonists/clockcult/clock_items/clock_augments.dm new file mode 100644 index 0000000000..2131aa7160 --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_items/clock_augments.dm @@ -0,0 +1,32 @@ +//This file is for snowflakey clock augmentations and clock-themed cybernetic implants. + +//The base clockie arm implant, which only clock cultist can use unless it is emagged. THIS SHOULD NEVER ACTUALLY EXIST +/obj/item/organ/cyberimp/arm/clockwork + name = "clock-themed arm-mounted implant" + var/clockwork_desc = "According to Ratvar, this really shouldn't exist. Tell Him about this immediately." + syndicate_implant = TRUE + icon_state = "clock_arm_implant" + +/obj/item/organ/cyberimp/arm/clockwork/ui_action_click() + if(is_servant_of_ratvar(owner) || (obj_flags & EMAGGED)) //If you somehow manage to steal a clockie's implant AND have an emag AND manage to get it implanted for yourself, good on ya! + return ..() + to_chat(owner, "The implant refuses to activate..") + +/obj/item/organ/cyberimp/arm/clockwork/examine(mob/user) + if((is_servant_of_ratvar(user) || isobserver(user)) && clockwork_desc) + desc = clockwork_desc + . = ..() + desc = initial(desc) + +/obj/item/organ/cyberimp/arm/clockwork/emag_act() + if(obj_flags & EMAGGED) + return + obj_flags |= EMAGGED + to_chat(usr, "You emag [src], hoping it'll achieve something..") + +//Brass claw implant. Holds the brass claw from brass_claw.dm and can extend / retract it at will. +/obj/item/organ/cyberimp/arm/clockwork/claw + name = "brass claw implant" + desc = "Yikes, the claw attached to this looks pretty darn sharp." + clockwork_desc = "This implant, when added to a servant's arm, allows them to extend and retract a claw at will, though this is mildly painful to do. It will refuse to work for any non-servants." + contents = newlist(/obj/item/clockwork/brass_claw) diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm index 40aca961fc..a6f2ee6d90 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/_call_weapon.dm @@ -29,7 +29,7 @@ owner.visible_message("[owner]'s [weapon.name] flickers and disappears!") to_chat(owner, "You dismiss [weapon].") QDEL_NULL(weapon) - weapon_reset(RATVARIAN_SPEAR_COOLDOWN * 0.5) + weapon_reset(RATVARIAN_WEAPON_COOLDOWN * 0.5) return else weapon.visible_message("[weapon] suddenly flickers and disappears!") diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm new file mode 100644 index 0000000000..340f01f6f8 --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm @@ -0,0 +1,51 @@ +//Brass claw, an armblade-like weapon used by a clock implant. Stealthy if retracted, very obvious if active. +//Bit weaker than an armblade strength-wise but gains combo on consecutive attacks against the same target, which causes bonus damage + +/obj/item/clockwork/brass_claw + name = "brass claw" + desc = "A very sharp claw made out of brass." + clockwork_desc = "A incredibly sharp claw made out of brass. It is quite effective at crippling enemies, though very obvious when extended.\nGains combo on consecutive attacks against a target, causing bonus damage." + icon_state = "brass_claw" //Codersprite moment + item_state = "brass_claw" + lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi' + righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi' + w_class = WEIGHT_CLASS_HUGE + force = 15 //Doesn't generate vitality like the spear does / has somewhat less damage, but quite good at wounding and gets through armor pretty well. Also gains 2 bonus damage per consecutive attack on the same target + throwforce = 0 //haha yes lets be safe about this + throw_range = 0 + throw_speed = 0 + armour_penetration = 20 + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") + sharpness = SHARP_EDGED + wound_bonus = 5 + bare_wound_bonus = 15 + total_mass = TOTAL_MASS_HAND_REPLACEMENT + var/mob/living/last_attacked + var/combo = 0 + var/damage_per_combo = 2 + var/maximum_combo_damage = 18 //33 damage on max stacks. Usually the target will already be dead by then but if they somehow aren't, better to have this capped + +/obj/item/clockwork/brass_claw/Initialize() + . = ..() + AddComponent(/datum/component/butchering, 60, 80) + +/obj/item/clockwork/brass_claw/examine(mob/user) + if(is_servant_of_ratvar(user)) + clockwork_desc += "\nIt has [combo] combo stacks built up against the current target, causing [min(maximum_combo_damage, combo * damage_per_combo)] bonus damage." + . = ..() + clockwork_desc = initial(clockwork_desc) + +/obj/item/clockwork/brass_claw/attack(mob/living/target, mob/living/carbon/human/user) + . = ..() + if(QDELETED(target) || target.anti_magic_check(chargecost = 0) || is_servant_of_ratvar(target)) + return + if(target != last_attacked) //Loses all combat on switching targets + last_attacked = target + combo = 0 + else + if(!iscultist(target)) //Hostile cultists being hit stacks up combo far faster than usual + combo++ + else + combo += 3 + target.adjustBruteLoss(min(maximum_combo_damage, combo * damage_per_combo)) diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm index 234f0445e0..aa69478217 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm @@ -8,10 +8,12 @@ force = 15 //Extra damage is dealt to targets in attack() throwforce = 25 armour_penetration = 10 - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY attack_verb = list("stabbed", "poked", "slashed") hitsound = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_BULKY + block_parry_data = /datum/block_parry_data/ratvarian_spear + item_flags = ITEM_CAN_PARRY var/bonus_burn = 5 /obj/item/clockwork/weapon/ratvarian_spear/ratvar_act() @@ -43,7 +45,7 @@ else if(iscultist(target) || isconstruct(target)) to_chat(target, "Your body flares with agony at [src]'s presence!") bonus_damage *= 3 //total 30 damage on cultists, 50 with ratvar - GLOB.clockwork_vitality += target.adjustFireLoss(bonus_damage) //adds the damage done to existing vitality + GLOB.clockwork_vitality += max(0, target.adjustFireLoss(bonus_damage)) //adds the damage done to existing vitality /obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) var/turf/T = get_turf(hit_atom) @@ -78,5 +80,17 @@ if(T) //make sure we're not in null or something T.visible_message("[src] [pick("cracks in two and fades away", "snaps in two and dematerializes")]!") new /obj/effect/temp_visual/ratvar/spearbreak(T) - action.weapon_reset(RATVARIAN_SPEAR_COOLDOWN) + action.weapon_reset(RATVARIAN_WEAPON_COOLDOWN) +//A very short, very effective parry that counts on you predicting when the enemy will attack. +/datum/block_parry_data/ratvarian_spear + parry_time_windup = 0 //Very good for predicting + parry_time_active = 3 //Very short + parry_time_spindown = 1 + parry_time_perfect = 2 + parry_efficiency_perfect = 110 //Very low leeway for counterattacks... + parry_efficiency_considered_successful = 0.8 + parry_efficiency_to_counterattack = 1 + parry_cooldown = 15 //But also very low cooldown.. + parry_failed_stagger_duration = 2 SECONDS //And relatively small penalties for failing. + parry_failed_clickcd_duration = 1 SECONDS diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm index a4f8bf8062..d08caa39d7 100644 --- a/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm +++ b/code/modules/antagonists/clockcult/clock_items/clockwork_armor.dm @@ -8,7 +8,7 @@ resistance_flags = FIRE_PROOF | ACID_PROOF flags_inv = HIDEEARS|HIDEHAIR|HIDEFACE|HIDESNOUT mutantrace_variation = STYLE_MUZZLE - armor = list("melee" = 50, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + armor = list("melee" = 50, "bullet" = 70, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100, "magic" = 60, "wound" = 65) /obj/item/clothing/head/helmet/clockwork/Initialize() . = ..() @@ -21,17 +21,17 @@ /obj/item/clothing/head/helmet/clockwork/ratvar_act() if(GLOB.ratvar_awakens) - armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100) + armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100, magic = 100, wound = 100) clothing_flags |= STOPSPRESSUREDAMAGE max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else if(GLOB.ratvar_approaches) - armor = getArmor(melee = 70, bullet = 80, laser = -15, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100) + armor = getArmor(melee = 70, bullet = 80, laser = 10, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100,, magic = 70, wound = 75) clothing_flags |= STOPSPRESSUREDAMAGE max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else - armor = getArmor(melee = 60, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100) + armor = getArmor(melee = 60, bullet = 70, laser = 0, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100, magic = 60, wound = 65) clothing_flags &= ~STOPSPRESSUREDAMAGE max_heat_protection_temperature = initial(max_heat_protection_temperature) min_cold_protection_temperature = initial(min_cold_protection_temperature) @@ -68,7 +68,7 @@ cold_protection = CHEST|GROIN|LEGS heat_protection = CHEST|GROIN|LEGS resistance_flags = FIRE_PROOF | ACID_PROOF - armor = list("melee" = 60, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 70, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100, "magic" = 60, "wound" = 65) allowed = list(/obj/item/clockwork, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor, /obj/item/mmi/posibrain/soul_vessel, /obj/item/reagent_containers/food/drinks/bottle/holyoil) mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC @@ -83,17 +83,17 @@ /obj/item/clothing/suit/armor/clockwork/ratvar_act() if(GLOB.ratvar_awakens) - armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100) + armor = getArmor(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100, fire = 100, acid = 100, magic = 100, wound = 100) clothing_flags |= STOPSPRESSUREDAMAGE max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else if(GLOB.ratvar_approaches) - armor = getArmor(melee = 70, bullet = 80, laser = -15, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100) + armor = getArmor(melee = 70, bullet = 80, laser = 10, energy = 25, bomb = 70, bio = 0, rad = 0, fire = 100, acid = 100, magic = 70, wound = 75) clothing_flags |= STOPSPRESSUREDAMAGE max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else - armor = getArmor(melee = 60, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100) + armor = getArmor(melee = 60, bullet = 70, laser = 0, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100, magic = 60, wound = 65) clothing_flags &= ~STOPSPRESSUREDAMAGE max_heat_protection_temperature = initial(max_heat_protection_temperature) min_cold_protection_temperature = initial(min_cold_protection_temperature) @@ -135,7 +135,7 @@ siemens_coefficient = 0 permeability_coefficient = 0.05 resistance_flags = FIRE_PROOF | ACID_PROOF - armor = list("melee" = 80, "bullet" = 70, "laser" = -25, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 70, "laser" = 0, "energy" = 0, "bomb" = 60, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100, "magic" = 70, "wound" = 85) /obj/item/clothing/gloves/clockwork/Initialize() . = ..() @@ -153,7 +153,7 @@ max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT else - armor = getArmor(melee = 80, bullet = 70, laser = -25, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100) + armor = getArmor(melee = 80, bullet = 70, laser = 0, energy = 0, bomb = 60, bio = 0, rad = 0, fire = 100, acid = 100, magic = 70, wound = 85) clothing_flags &= ~STOPSPRESSUREDAMAGE max_heat_protection_temperature = initial(max_heat_protection_temperature) min_cold_protection_temperature = initial(min_cold_protection_temperature) diff --git a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm index 5837ac302d..0bae7d3539 100644 --- a/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm +++ b/code/modules/antagonists/clockcult/clock_items/clockwork_slab.dm @@ -1,10 +1,10 @@ /obj/item/clockwork/slab //Clockwork slab: The most important tool in Ratvar's arsenal. Allows scripture recital, tutorials, and generates components. name = "clockwork slab" desc = "A strange metal tablet. A clock in the center turns around and around." - clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant.
    \ + clockwork_desc = "A link between you and the Celestial Derelict. It contains information, recites scripture, and is your most vital tool as a Servant.\ It can be used to link traps and triggers by attacking them with the slab. Keep in mind that traps linked with one another will activate in tandem!" - icon_state = "dread_ipad" + icon_state = "clockwork_slab" lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi' righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi' var/inhand_overlay //If applicable, this overlay will be applied to the slab's inhand @@ -15,13 +15,13 @@ var/busy //If the slab is currently being used by something var/no_cost = FALSE //If the slab is admin-only and needs no components and has no scripture locks var/speed_multiplier = 1 //multiples how fast this slab recites scripture - var/selected_scripture = SCRIPTURE_DRIVER + // var/selected_scripture = SCRIPTURE_DRIVER //handled UI side var/obj/effect/proc_holder/slab/slab_ability //the slab's current bound ability, for certain scripture - var/recollecting = FALSE //if we're looking at fancy recollection + var/recollecting = TRUE //if we're looking at fancy recollection. tutorial enabled by default var/recollection_category = "Default" - var/list/quickbound = list(/datum/clockwork_scripture/abscond, \ + var/list/quickbound = list(/datum/clockwork_scripture/spatial_gateway, \ /datum/clockwork_scripture/ranged_ability/kindle, /datum/clockwork_scripture/ranged_ability/hateful_manacles) //quickbound scripture, accessed by index var/maximum_quickbound = 5 //how many quickbound scriptures we can have @@ -36,6 +36,11 @@ speed_multiplier = 0 no_cost = TRUE +/obj/item/clockwork/slab/debug/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) + if(!is_servant_of_ratvar(user)) + add_servant_of_ratvar(user) + return ..() + /obj/item/clockwork/slab/traitor var/spent = FALSE @@ -54,12 +59,6 @@ to_chat(user, "[src] falls dark. It appears you weren't worthy.") return ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clockwork/slab/debug/attack_hand(mob/living/user) - if(!is_servant_of_ratvar(user)) - add_servant_of_ratvar(user) - return ..() - /obj/item/clockwork/slab/cyborg //three scriptures, plus a spear and fabricator clockwork_desc = "A divine link to the Celestial Derelict, allowing for limited recital of scripture." quickbound = list(/datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/ranged_ability/linked_vanguard, \ @@ -67,29 +66,32 @@ maximum_quickbound = 6 //we usually have one or two unique scriptures, so if ratvar is up let us bind one more actions_types = list() -/obj/item/clockwork/slab/cyborg/engineer //three scriptures, plus a fabricator - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transmission, /datum/clockwork_scripture/create_object/stargazer) +/obj/item/clockwork/slab/cyborg/engineer //six scriptures, plus a fabricator. Might revert this if its too OP, I just thought that engineering borgs should get the all the structures + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transmission, /datum/clockwork_scripture/create_object/stargazer, \ + /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/clockwork_obelisk, /datum/clockwork_scripture/create_object/mania_motor) -/obj/item/clockwork/slab/cyborg/medical //five scriptures, plus a spear - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/ranged_ability/sentinels_compromise, \ - /datum/clockwork_scripture/create_object/vitality_matrix) +/obj/item/clockwork/slab/cyborg/medical //six scriptures, plus a spear + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/ranged_ability/sentinels_compromise, \ + /datum/clockwork_scripture/create_object/vitality_matrix, /datum/clockwork_scripture/channeled/mending_mantra) -/obj/item/clockwork/slab/cyborg/security //twoscriptures, plus a spear - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/hateful_manacles, /datum/clockwork_scripture/ranged_ability/judicial_marker) - -/obj/item/clockwork/slab/cyborg/peacekeeper //two scriptures, plus a spear - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/hateful_manacles, /datum/clockwork_scripture/ranged_ability/judicial_marker) +/obj/item/clockwork/slab/cyborg/security //four scriptures, plus a spear + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/channeled/volt_blaster, /datum/clockwork_scripture/ranged_ability/hateful_manacles, \ + /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/channeled/belligerent) +/obj/item/clockwork/slab/cyborg/peacekeeper //four scriptures, plus a spear + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/channeled/volt_blaster, /datum/clockwork_scripture/ranged_ability/hateful_manacles, \ + /datum/clockwork_scripture/ranged_ability/judicial_marker, /datum/clockwork_scripture/channeled/belligerent) +/*//this module was commented out so why wasn't this? /obj/item/clockwork/slab/cyborg/janitor //six scriptures, plus a fabricator - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \ + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \ /datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor) - +*/ /obj/item/clockwork/slab/cyborg/service //six scriptures, plus xray vision - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant,/datum/clockwork_scripture/create_object/stargazer, \ + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/create_object/replicant,/datum/clockwork_scripture/create_object/stargazer, \ /datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/create_object/clockwork_obelisk) -/obj/item/clockwork/slab/cyborg/miner //two scriptures, plus a spear and xray vision - quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/spatial_gateway) +/obj/item/clockwork/slab/cyborg/miner //three scriptures, plus a spear and xray vision + quickbound = list(/datum/clockwork_scripture/spatial_gateway, /datum/clockwork_scripture/ranged_ability/linked_vanguard, /datum/clockwork_scripture/channeled/belligerent, /datum/clockwork_scripture/channeled/volt_blaster) /obj/item/clockwork/slab/cyborg/access_display(mob/living/user) if(!GLOB.ratvar_awakens) @@ -140,14 +142,15 @@ /obj/item/clockwork/slab/examine(mob/user) . = ..() - if(is_servant_of_ratvar(user) || isobserver(user)) - if(LAZYLEN(quickbound)) - for(var/i in 1 to quickbound.len) - if(!quickbound[i]) - continue - var/datum/clockwork_scripture/quickbind_slot = quickbound[i] - . += "Quickbind button: [initial(quickbind_slot.name)]." - . += "Available power: [DisplayPower(get_clockwork_power())]." + if(!is_servant_of_ratvar(user) || !isobserver(user)) + return + if(LAZYLEN(quickbound)) + for(var/i in 1 to quickbound.len) + if(!quickbound[i]) + continue + var/datum/clockwork_scripture/quickbind_slot = quickbound[i] + . += "Quickbind button: [initial(quickbind_slot.name)]." + . += "Available power: [DisplayPower(get_clockwork_power())]." //Slab actions; Hierophant, Quickbind /obj/item/clockwork/slab/ui_action_click(mob/user, action) @@ -165,18 +168,19 @@ user.emote("scream") user.apply_damage(5, BURN, BODY_ZONE_L_ARM) user.apply_damage(5, BURN, BODY_ZONE_R_ARM) - return 0 + return FALSE if(!is_servant_of_ratvar(user)) to_chat(user, "The information on [src]'s display shifts rapidly. After a moment, your head begins to pound, and you tear your eyes away.") - user.confused += 5 - user.dizziness += 5 - return 0 + if(user.confused || user.dizziness) + user.confused += 5 + user.dizziness += 5 + return FALSE if(busy) to_chat(user, "[src] refuses to work, displaying the message: \"[busy]!\"") - return 0 + return FALSE if(!no_cost && !can_recite_scripture(user)) to_chat(user, "[src] hums fitfully in your hands, but doesn't seem to do anything...") - return 0 + return FALSE access_display(user) /obj/item/clockwork/slab/AltClick(mob/living/user) @@ -192,14 +196,6 @@ ui_interact(user) return TRUE -/obj/item/clockwork/slab/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "clockwork_slab", name, 800, 420, master_ui, state) - ui.set_autoupdate(FALSE) //we'll update this occasionally, but not as often as possible - ui.set_style("clockwork") - ui.open() - /obj/item/clockwork/slab/proc/recite_scripture(datum/clockwork_scripture/scripture, mob/living/user) if(!scripture || !user || !user.canUseTopic(src) || (!no_cost && !can_recite_scripture(user))) return FALSE @@ -207,294 +203,156 @@ to_chat(user, "You need to hold the slab in your active hand to recite scripture!") return FALSE var/initial_tier = initial(scripture.tier) - if(initial_tier != SCRIPTURE_PERIPHERAL) - if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier]) - to_chat(user, "That scripture is not unlocked, and cannot be recited!") - return FALSE + if(initial_tier == SCRIPTURE_PERIPHERAL) + to_chat(user, "Nice try using href exploits") + return + if(!GLOB.ratvar_awakens && !no_cost && !SSticker.scripture_states[initial_tier]) + to_chat(user, "That scripture is not unlocked, and cannot be recited!") + return FALSE var/datum/clockwork_scripture/scripture_to_recite = new scripture scripture_to_recite.slab = src scripture_to_recite.invoker = user scripture_to_recite.run_scripture() return TRUE - -//Guide to Serving Ratvar -/obj/item/clockwork/slab/proc/recollection() - var/list/textlist = list("If you're seeing this, file a bug report.") - if(GLOB.ratvar_awakens) - textlist = list("") - for(var/i in 1 to 100) - textlist += "HONOR RATVAR " - textlist += "" - else - textlist = list("
    [text2ratvar("Purge all untruths and honor Engine.")]

    \ - \ - NOTICE: This information is out of date. Read the Ark & You primer in your backpack or read the wiki page for current info.
    \ -

    \ - These pages serve as the archives of Ratvar, the Clockwork Justiciar. This section of your slab has information on being as a Servant, advice for what to do next, and \ - pointers for serving the master well. You should recommended that you check this area for help if you get stuck or need guidance on what to do next.

    \ - \ - Disclaimer: Many objects, terms, and phrases, such as Servant, Cache, and Slab, are capitalized like proper nouns. This is a quirk of the Ratvarian language; \ - do not let it confuse you! You are free to use the names in pronoun form when speaking in normal languages.
    ") - return textlist.Join() - -//Gets text for a certain section. "Default" is used for when you first open Recollection. -//Current sections (make sure to update this if you add one: -//- Basics -//- Terminology -//- Components -//- Scripture -//- Power -//- Conversion -/obj/item/clockwork/slab/proc/get_recollection_text(section) - var/list/dat = list() - switch(section) +/* + * Gets text for a certain section. "Default" is used for when you first open Recollection. + * Current sections (make sure to update this if you add one: + * Basics + * Terminology + * Components + * Scripture + * Power + * Conversion + * * what - What section? + */ +/obj/item/clockwork/slab/proc/get_recollection(what) //Now DMDOC compliant!* + . = list() + switch(what) //need someone to rewrite info for this. if("Default") - dat += "You can browse the above sections as you please. They're designed to be read in order, but feel free to pick and choose between them." - if("Getting Started") - dat += "Getting Started

    " - dat += "Welcome, Servant! This section houses the utmost basics of being a Servant of Ratvar, and is much more informal than the other sections. Being a Servant of \ - Ratvar is a very complex role, with many systems, objects, and resources to use effectively and creatively.

    " - dat += "This section of your clockwork slab covers everything that Servants have to be aware of, but is a long read because of how in-depth the systems are. Knowing \ - how to use the tools at your disposal makes all the difference between a clueless Servant and a great one.

    " - dat += "If this is your first time being a Servant, relax. It's very much possible that you'll fail, but it's impossible to learn without making mistakes. For the time \ - being, use the Hierophant Network button in the top left-hand corner of your screen to try and get in touch with your fellow Servants; ignore the others for now. This button \ - will let you send messages across space and time to all other Servants. This makes it great for coordinating, and you should use it often! Note: Using \ - this will cause you to whisper your message aloud, so doing so in a public place is very suspicious and you should try to restrict it to private use.

    " - dat += "If you aren't willing or don't have the time to read through every section, you can still help your teammates! Ask if they've set up a base. If they have, head there \ - and ask however you can help; chances are there's always something. If not, it's your job as a Servant to get one up and running! Try to find a secluded, low-traffic area, \ - like the auxiliary base or somewhere deep in maintenance. You'll want to go into the Drivers section of the slab and look for Tinkerer's Cache. Find a nice spot and \ - create one. This serves as a storage for components, the cult's primary resource. (Your slab's probably produced a few by now.) By attacking that cache with this \ - slab, you'll offload all your components into it, and all Servants will be able to use those components from any distance - all Tinkerer's Caches are linked!

    " - dat += "Once you have a base up and running, contact your fellows and let them know. You should come back here often to drop off the slab's components, and your fellows \ - should do the same, either in this cache or in ones of their own.

    " - dat += "If you think you're confident in taking further steps to help the cult, feel free to move onto the other sections. If not, let your allies know that you're new and \ - would appreciate the help they might offer you. Most experienced Servants would be happy to help; if everyone is inexperienced, then you'll have to step out of your comfort \ - zone and read onto the other sections. It's very likely that you might fail, but don't worry too much about it; you can't learn effectively without making mistakes.

    " - dat += "For now, welcome! If you're looking to learn, you should start with the Basics section, then move onto Components and Scripture. At the very \ - least, you should read the Conversion section, as it outlines the most important aspects of being a Servant. Good luck!

    " - dat += "-=-=-=-=-=-" + .["title"] = "Default" + .["info"] = "Hello servant! Currently these categories dosen't work!" + /* if("Basics") - dat += "Servant Basics

    " - dat += "The first thing any Servant should know is their slab, inside and out. The clockwork slab is by far your most important tool. It allows you to speak with your \ - fellow Servants, create components that fuel many of your abilities, use those abilities, and should be kept safe and hidden on your person at all times. If you have not \ - done so already, it's a good idea to check for any fellow Servants using the Hierophant Network button in the top-left corner of your screen; due to the cult's nature, \ - teamwork is an instrumental component of your success.

    " //get it? component? ha! - dat += "As a Servant of Ratvar, the tools you are given focus around building and maintaining bases and outposts. A great deal of your power comes from stationary \ - structures, and without constructing a base somewhere, it's essentially impossible to succeed. Finding a good spot to build a base can be difficult, and it's recommended \ - that you choose an area in low-traffic part of the station (such as the auxiliary base). Make sure to disconnect any cameras in the area beforehand.

    " - dat += "Because of how complex being a Servant is, it isn't possible to fit much information into this section. It's highly recommended that you read the Components \ - and Scripture sections next. Not knowing how these two systems work will cripple both you and your fellows, and lead to a frustrating experience for everyone.

    " - dat += "-=-=-=-=-=-" + .["title"] = "Basics" + .["info"] = "# MARKDOWN WITH HTML?" if("Terminology") - dat += "Common Servant Terminology
    " - dat += "This isn't intended to be read all at once; you are advised to treat it moreso as a glossary.

    " - dat += "General
    " - dat += "Servant: A person or robot who serves Ratvar. You are one of these.
    " - dat += "Cache: A Tinkerer's Cache, which is a structure that stores and creates components.
    " - dat += "CV: Construction Value. All clockwork structures, floors, and walls increase this number.
    " - dat += "Vitality: Used for healing effects, produced by Ratvarian spear attacks and Vitality Matrices.
    " - dat += "Geis: An important scripture used to make normal crew and robots into Servants of Ratvar.
    " - dat += "Ark: The cult's win condition, a huge structure that needs to be defended.

    " - dat += "Items
    " - dat += "Slab: A clockwork slab, a Servant's most important tool. You're holding one! Keep it safe and hidden.
    " - dat += "Visor: A judicial visor, which is a pair of glasses that can smite an area for a brief stun and delayed explosion.
    " - dat += "Wraith Specs: Wraith spectacles, which provide true sight (X-ray, night vision) but damage the wearer's eyes.
    " - dat += "Spear: A Ratvarian spear, which is a very powerful melee weapon that produces Vitality.
    " - dat += "Fabricator: A replica fabricator, which converts objects into clockwork versions.

    " - dat += "Constructs
    " - dat += "Marauder: A clockwork marauder, which is a powerful bodyguard that hides in its owner.

    " - dat += "Structures (* = requires power)
    " - dat += "Warden: An ocular warden, which is a ranged turret that damages non-Servants that see it.
    " - dat += "Prism*: A prolonging prism, which delays the shuttle for two minutes at a huge power cost.

    " - dat += "Motor*: A mania motor, which serves as area-denial through negative effects and eventual conversion.
    " - dat += "Daemon*: A tinkerer's daemon, which quickly creates components.
    " - dat += "Obelisk*: A clockwork obelisk, which can broadcast large messages and allows limited teleportation.
    " - dat += "Sigils
    " - dat += "Note: Sigils can be stacked on top of one another, making certain sigils very effective when paired!
    " - dat += "Transgression: Stuns the first non-Servant to cross it for ten seconds and blinds others nearby. Disappears on use.
    " - dat += "Submission: Converts the first non-Servant to stand on the sigil for seven seconds. Disappears on use.
    " - dat += "Matrix: Drains health from non-Servants, producing Vitality. Can heal and revive Servants.
    " - dat += "Accession: Identical to the Sigil of Submission, but doesn't disappear on use. It can also convert a single mindshielded target, but will disappear after doing this.
    " - dat += "Transmission: Drains and stores power for clockwork structures. Feeding it brass sheets will create additional power.

    " - dat += "-=-=-=-=-=-" + .["title"] = "Terminology" + .["info"] = "# MARKDOWN WITH HTML?" if("Components") - dat += "Components & Their Uses

    " - dat += "Components are your primary resource as a Servant. There are five types of component, with each one being used in different roles:

    " - dat += "Although this is a good rule of thumb, their effects become much more nuanced when used together. For instance, a turret might have both belligerent eyes and \ - vanguard cogwheels as construction requirements, because it defends its allies by harming its enemies.

    " - dat += "Components' primary use is fueling scripture (covered in its own section), and they can be created through various ways. This clockwork slab, for instance, \ - will make a random component of every type - or a specific one, if you choose a target component from the interface - every remove me already. This number will increase \ - as the amount of Servants in the covenant increase; additionally, slabs can only produce components when held by a Servant, and holding more than one slab will cause both \ - of them to halt progress until one of them is removed from their person.

    " - dat += "Your slab has an internal storage of components, but it isn't meant to be the main one. Instead, there's a global storage of components that can be \ - added to through various ways. Anything that needs components will first draw them from the global storage before attempting to draw them from the slab. Most methods of \ - component production add to the global storage. You can also offload components from your slab into the global storage by using it on a Tinkerer's Cache, a structure whose \ - primary purpose is to do just that (although it will also slowly produce components when placed near a brass wall.)

    " - dat += "-=-=-=-=-=-" + .["title"] = "Default" + .["info"] = "# MARKDOWN WITH HTML?" if("Scripture") - dat += "The Ancient Scripture

    " - dat += "If you have experience with the Nar'Sian cult (or the \"blood cult\") then you will know of runes. They are the manifestations of the Geometer's power, and where most \ - of the cult's supernatural ability comes from. The Servant equivalent of runes is called scripture, and unlike runes, scripture is loaded into your clockwork slab.

    " - dat += "Each piece of scripture has widely-varying effects. Your most important scripture, Geis, is obvious and suspicious, but charges your slab with energy and allows \ - you to attack a non-Servant in melee range to restrain them and begin converting them into a Servant. This is just one example; each piece of scripture can be simple or \ - complex, be obvious or have hidden mechanics that can only be found through trial and error.

    " - dat += "Any given piece of scripture has a component cost listed in its \"Recite\" button. The acronyms for the components should be obvious if you've read about components \ - already; reciting this piece of scripture will consume the listed components, first from the global storage and then from your slab. Note that failing to recite a piece of \ - scripture will not consume the components required to recite it.

    " - dat += "It should also be noted that some scripture cannot be recited alone. Especially with more powerful scripture, you may need multiple Servants to recite a piece of \ - scripture; both of you will need to stand still until the recital completes. Only human and silicon Servants are valid for scripture recital! Constructs cannot help \ - in reciting scripture.

    " - dat += "Finally, scripture is separated into three \"tiers\" based on power: Drivers, Scripts, and Applications.[prob(1) ? " (The Revenant tier was removed a long time ago. \ - Get with the times.)" : ""] You can view the requirements to unlock each tier in its scripture list. Once a tier is unlocked, it's unlocked permanently; the cult only needs to fill the \ - requirement for unlocking a tier once!

    " - dat += "-=-=-=-=-=-" + .["title"] = "Default" + .["info"] = "# MARKDOWN WITH HTML?" if("Power") - dat += "Power! Unlimited Power!

    " - dat += "In the early stages of the cult, the only resource that must be actively worried about is components. However, as new scripture is unlocked, a new resource \ - becomes necessary: power. Almost all clockwork structures require power to function in some way. There is nothing special about this power; it's mere electricity, \ - and can be harnessed in several ways.

    " - dat += "To begin with, if there is no other source of power nearby, structures will draw from the area's APC, assuming it has one. This is inefficient and ill-advised as \ - anything but a last resort. Instead, it is recommended that a Sigil of Transmission is created. This sigil serves as both battery and power generator for nearby clockwork \ - structures, and those structures will happily draw power from the sigil before they resort to APCs.

    " - dat += "Generating power is less easy. The most reliable and efficient way is using brass sheets; attacking a sigil of transmission with brass sheets will convert them \ - to power, at a rate of [DisplayPower(POWER_FLOOR)] per sheet. (Brass sheets are created from replica fabricators, which are explained more in detail in the Conversion section.) \ - Activating a sigil of transmission will also cause it to drain power from the nearby area, which, while effective, serves as an obvious tell that there is something wrong.

    " - dat += "Without power, many structures will not function, making a base vulnerable to attack. For this reason, it is critical that you keep an eye on your power reserves and \ - ensure that they remain comfortably high.

    " - dat += "-=-=-=-=-=-" + .["title"] = "Power" + .["info"] = "# MARKDOWN WITH HTML?" if("Conversion") - dat += "Growing the Ranks

    " - dat += "Because the Servants of Ratvar are a cult, the main method to gain more power is to \"enlighten\" normal crew into new Servants. When a crewmember is converted, \ - they become a full-fledged Servant, ready and willing to serve the cause of Ratvar. It should also be noted that silicon crew, such as cyborgs and the AI, can be \ - converted just like normal crew and will gain special abilities; this is covered later. This section will also cover converting the station's structure itself; walls, \ - floors, windows, tables, and other objects can all be converted into clockwork versions, and serve an important purpose.

    " - dat += "A Note on Geis: There are several ways to convert humans and silicons. However, the most important tool to making them work is \ - Geis, a Driver-tier scripture. Using it whispers an invocation very quickly and charges your slab with power. In addition to making the slab visible in your hand, \ - you can now use it on a target within melee range to bind and mute them. It is by far your most reliable tool for capturing potential converts and targets, though it is incredibly \ - obvious. In addition, you are unable to take any actions other than moving while your target is bound. The binding will last for 25 seconds and mute for about 13 seconds, though \ - allies can use Geis to refresh these effects.

    " - dat += "Converting: The two methods of conversion are the sigil of submission, whose purpose is to do so, and the mania motor. \ - The sigil of submission is a sigil that, when stood on by a non-Servant for eight seconds, will convert that non-Servant. This is the only practical way to convert targets. \ - Sigils of submission are cheap, early, and permanent! Make sure sigils of submission are placed only in bases or otherwise hidden spots, or with a sigil of transgression on them. \ - The mania motor, however, is generally unreliable and unlocked later, only converting those who stand near it for an extended period.

    " - dat += "Converting Humans: For obvious reasons, humans are the most common conversion target. Because every crew member is different, and \ - may be armed with different equipment, you should take precautions to ensure that they aren't able to resist. If able, removing a headset is essential, as is restraining \ - them through handcuffs, cable ties, or other restraints. Some crew, like security, are also implanted with mindshield implants; these will prevent conversion and must be \ - surgically removed before they are an eligible convert. Note: The captain is never an eligible convert and should instead be killed or imprisoned. If security \ - begins administering mindshield implants, this will greatly inhibit conversion. Also note that mindshield implants can be broken by a sigil of accession automatically, but \ - the sigil will disappear.

    " - dat += "Converting Silicons: Due to their robotic nature, silicons are generally more predictable than humans in terms of conversion. \ - However, they are also much, much harder to subdue, especially cyborgs. The easiest way to convert a cyborg is by using Geis to restrain them, then dragging them to a sigil \ - of submission. If you stack a sigil of transgression and a sigil of submission, a crossing cyborg will be stunned and helpless to escape before they are converted.

    " - dat += "Converting AIs is very often the hardest task of the cult, and has been the downfall of countless successful Servants. Their omnipresence across the station, \ - coupled with their secure location and ability to lock themselves securely, makes them a powerful target. However, once the AI itself is reached, it is usually completely \ - helpless to resist its own conversion. A very common tactic is to take advantage of a converted cyborg to rush the AI before it is able to react.

    " - dat += "Even once an AI is converted, care must be taken to ensure that it remains hidden. Not only does the AI's core become brassy and thus obvious to an outside \ - observer, but the AI loses the ability to speak in anything but Ratvarian. For this reason, it has to remain completely silent over common radio channels if stealth \ - is at all a priority. This is suspicious and will rapidly lead to the crew checking on it, which usually results in the cult's outing. It is, however, necessary to convert \ - all AIs present on the station before the Ark becomes invokable, so this must be done at some point.

    " - dat += "Converting the Station: Converted objects all serve a purpose and are important to the cult's success. To convert objects, \ - a Servant needs to use a replica fabricator, a handheld tool that uses power to replace objects with clockwork versions. Different clockwork objects have different \ - effects and are often crucial. The most noteworthy are clockwork walls, which automatically \"link\" to any nearby Tinkerer's Caches, causing them to slowly \ - generate components. This is incredibly useful for obvious reasons, and creating a clockwork wall near every Tinkerer's Cache should be prioritized. Clockwork floors \ - will slowly heal any toxin damage suffered by Servants standing on them, and clockwork airlocks can only be opened by Servants.

    " - dat += "The replica fabricator itself is also worth noting. In addition to replacing objects, it can also create brass sheets at the cost of power by using the \ - fabricator in-hand. It can also be used to repair any damaged clockwork structures.

    " - dat += "Replacing objects is almost as, if not as important as, converting new Servants. A base is impossible to manage without clockwork walls at the very least, and \ - once the cult has been outed and the crew are actively searching, there is little reason not to use as many as possible.

    " - dat += "-=-=-=-=-=-" + .["title"] = "Conversion" + .["info"] = "# MARKDOWN WITH HTML?" + */ else - dat += "404: [section ? section : "Section"] Not Found!

    \ - One of the cogscarabs must've misplaced this section, because the game wasn't able to find any info regarding it. Report this to the coders!" - return "

    [dat.Join()]

    " - -//Gets the quickbound scripture as a text block. -/obj/item/clockwork/slab/proc/get_recollection_quickbinds() - var/list/dat = list() - dat += "Quickbound Scripture
    \ - You can have up to five scriptures bound to action buttons for easy use.

    " - if(LAZYLEN(quickbound)) - for(var/i in 1 to maximum_quickbound) - if(LAZYLEN(quickbound) < i || !quickbound[i]) - dat += "A Quickbind slot, currently set to Nothing.
    " - else - var/datum/clockwork_scripture/quickbind_slot = quickbound[i] - dat += "A Quickbind slot, currently set to [initial(quickbind_slot.name)].
    " - return dat.Join() + return null //error text handled tgui side. should not cause BSOD +/obj/item/clockwork/slab/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ClockworkSlab", name) + ui.open() /obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI - var/list/data = list() - data["power"] = "[DisplayPower(get_clockwork_power())] power is available for scripture and other consumers." - - switch(selected_scripture) //display info based on selected scripture tier - if(SCRIPTURE_DRIVER) - data["tier_info"] = "These scriptures are permanently unlocked." - if(SCRIPTURE_SCRIPT) - if(SSticker.scripture_states[SCRIPTURE_SCRIPT]) - data["tier_info"] = "These scriptures are permanently unlocked." - else - data["tier_info"] = "These scriptures will automatically unlock when the Ark is halfway ready or if [DisplayPower(SCRIPT_UNLOCK_THRESHOLD)] of power is reached." - if(SCRIPTURE_APPLICATION) - if(SSticker.scripture_states[SCRIPTURE_APPLICATION]) - data["tier_info"] = "These scriptures are permanently unlocked." - else - data["tier_info"] = "Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached.." - - data["selected"] = selected_scripture - data["scripturecolors"] = "Scriptures in yellow are related to construction and building.
    \ - Scriptures in red are related to attacking and offense.
    \ - Scriptures in blue are related to healing and defense.
    \ - Scriptures in purple are niche but still important!
    \ - Scriptures with italicized names are important to success." - generate_all_scripture() - - data["scripture"] = list() - for(var/s in GLOB.all_scripture) + . = list() + .["recollection"] = recollecting + .["power"] = DisplayPower(get_clockwork_power()) + .["power_unformatted"] = get_clockwork_power() + .["HONOR_RATVAR"] = GLOB.ratvar_awakens + .["scripture"] = list() + for(var/s in GLOB.all_scripture) //don't block this, even when ratvar spawns for roundend griff. var/datum/clockwork_scripture/S = GLOB.all_scripture[s] - if(S.tier == selected_scripture) //display only scriptures of the selected tier - var/scripture_color = get_component_color_bright(S.primary_component) - var/list/temp_info = list("name" = "[S.name]", - "descname" = "([S.descname])", - "tip" = "[S.desc]\n[S.usage_tip]", - "required" = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])", - "type" = "[S.type]", - "quickbind" = S.quickbind) - if(S.important) - temp_info["name"] = "[temp_info["name"]]" - var/found = quickbound.Find(S.type) - if(found) - temp_info["bound"] = "[found]" - if(S.invokers_required > 1) - temp_info["invokers"] = "Invokers: [S.invokers_required]" - data["scripture"] += list(temp_info) - data["recollection"] = recollecting - if(recollecting) - data["recollection_categories"] = GLOB.ratvar_awakens ? list() : list(\ - list("name" = "Getting Started", "desc" = "First-time servant? Read this first."), \ - list("name" = "Basics", "desc" = "A primer on how to play as a servant."), \ - list("name" = "Terminology", "desc" = "Common acronyms, words, and terms."), \ - list("name" = "Components", "desc" = "Information on components, your primary resource."), \ - list("name" = "Scripture", "desc" = "Information on scripture, ancient tools used by the cult."), \ - list("name" = "Power", "desc" = "The power system that certain objects use to function."), \ - list("name" = "Conversion", "desc" = "Converting the crew, cyborgs, and very walls to your cause."), \ - ) - data["rec_text"] = recollection() - data["rec_section"] = GLOB.ratvar_awakens ? "" : get_recollection_text(recollection_category) - data["rec_binds"] = GLOB.ratvar_awakens ? "" : get_recollection_quickbinds() - return data + if(S.tier == SCRIPTURE_PERIPHERAL) // This tier is skiped because this contains basetype stuff + continue + + var/list/data = list() + data["name"] = S.name + data["descname"] = S.descname + data["tip"] = "[S.desc]\n[S.usage_tip]" + data["required"] = "([DisplayPower(S.power_cost)][S.special_power_text ? "+ [replacetext(S.special_power_text, "POWERCOST", "[DisplayPower(S.special_power_cost)]")]" : ""])" + data["required_unformatted"] = S.power_cost + data["type"] = "[S.type]" + data["quickbind"] = S.quickbind //this is if it cant quickbind (bool) + data["fontcolor"] = get_component_color_bright(S.primary_component) + data["important"] = S.important //italic! + + var/found = quickbound.Find(S.type) + if(found) + data["bound"] = found //number (pos) on where is it on the list + if(S.invokers_required > 1) + data["invokers"] = "Invokers: [S.invokers_required]" + + .["rec_binds"] = list() + for(var/i in 1 to maximum_quickbound) + if(LAZYLEN(quickbound) < i || !quickbound[i]) + .["rec_binds"] += list(list()) //a blank json. + else + var/datum/clockwork_scripture/quickbind_slot = quickbound[i] + .["rec_binds"] += list(list( + "name" = initial(quickbind_slot.name), + "color" = get_component_color_bright(initial(quickbind_slot.primary_component)) + )) + + .["scripture"][S.tier] += list(data) + +/obj/item/clockwork/slab/ui_static_data(mob/user) + . = list() + .["tier_infos"] = list() //HEY!! WHEN ADDING NEW TIER, ADD IT HERE + .["tier_infos"][SCRIPTURE_PERIPHERAL] = list( + "requirement" = "Breaking the code DM side. Report to coggerbus if this appears!!", + "ready" = FALSE //just in case. Should NOT exist at all + ) + .["tier_infos"][SCRIPTURE_DRIVER] = list( + "requirement" = "None, this is already unlocked", + "ready" = TRUE //to bold it on JS side, and to say "These scriptures are permanently unlocked." + ) + .["tier_infos"][SCRIPTURE_SCRIPT] = list( + "requirement" = "These scriptures will automatically unlock when the Ark is halfway ready or if [DisplayPower(SCRIPT_UNLOCK_THRESHOLD)] of power is reached.", + "ready" = SSticker.scripture_states[SCRIPTURE_SCRIPT] //huh, on the gamemode ticker? okay... + ) + .["tier_infos"][SCRIPTURE_APPLICATION] = list( + "requirement" = "Unlock these optional scriptures by converting another servant or if [DisplayPower(APPLICATION_UNLOCK_THRESHOLD)] of power is reached..", + "ready" = SSticker.scripture_states[SCRIPTURE_APPLICATION] + ) + .["tier_infos"][SCRIPTURE_JUDGEMENT] = list( + "requirement" = "Unlock powerful equipment and structures by converting five servants or if [DisplayPower(JUDGEMENT_UNLOCK_THRESHOLD)] of power is reached..", + "ready" = SSticker.scripture_states[SCRIPTURE_JUDGEMENT] + ) + .["recollection_categories"] = list() + if(GLOB.ratvar_awakens) + return + .["recollection_categories"] = list( + list("name" = "Getting Started", "desc" = "First-time servant? Read this first."), + list("name" = "Basics", "desc" = "A primer on how to play as a servant."), + list("name" = "Terminology", "desc" = "Common acronyms, words, and terms."), + list("name" = "Components", "desc" = "Information on components, your primary resource."), + list("name" = "Scripture", "desc" = "Information on scripture, ancient tools used by the cult."), + list("name" = "Power", "desc" = "The power system that certain objects use to function."), + list("name" = "Conversion", "desc" = "Converting the crew, cyborgs, and very walls to your cause.") + ) + .["rec_section"] = get_recollection(recollection_category) + generate_all_scripture() + //needs a new place to live, preferably when clockcult unlocks/downgrades a tier. Smart enough to earlyreturn. /obj/item/clockwork/slab/ui_act(action, params) switch(action) if("toggle") recollecting = !recollecting if("recite") - INVOKE_ASYNC(src, .proc/recite_scripture, text2path(params["category"]), usr, FALSE) - if("select") - selected_scripture = params["category"] + INVOKE_ASYNC(src, .proc/recite_scripture, text2path(params["script"]), usr, FALSE) if("bind") - var/datum/clockwork_scripture/path = text2path(params["category"]) //we need a path and not a string + var/datum/clockwork_scripture/path = text2path(params["script"]) //we need a path and not a string + if(!ispath(path, /datum/clockwork_scripture) || !initial(path.quickbind) || initial(path.tier) == SCRIPTURE_PERIPHERAL) //fuck you href bus + to_chat(usr, "Nice try using href exploits") + return var/found_index = quickbound.Find(path) if(found_index) //hey, we already HAVE this bound if(LAZYLEN(quickbound) == found_index) //if it's the last scripture, remove it instead of leaving a null @@ -512,8 +370,8 @@ quickbind_to_slot(path, target_index) if("rec_category") recollection_category = params["category"] - ui_interact(usr) - return 1 + update_static_data() + return TRUE /obj/item/clockwork/slab/proc/quickbind_to_slot(datum/clockwork_scripture/scripture, index) //takes a typepath(typecast for initial()) and binds it to a slot if(!ispath(scripture) || !scripture || (scripture in quickbound)) diff --git a/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm b/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm index 43c05b8556..daee9f5c2c 100644 --- a/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm +++ b/code/modules/antagonists/clockcult/clock_items/construct_chassis.dm @@ -31,8 +31,7 @@ . = ..() clockwork_desc = initial(clockwork_desc) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clockwork/construct_chassis/attack_hand(mob/living/user) +/obj/item/clockwork/construct_chassis/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(w_class >= WEIGHT_CLASS_HUGE) to_chat(user, "[src] is too cumbersome to carry! Drag it around instead!") return @@ -90,17 +89,17 @@ creation_message = "The cogscarab clicks and whirrs as it hops up and springs to life!" construct_type = /mob/living/simple_animal/drone/cogscarab w_class = WEIGHT_CLASS_SMALL - var/infinite_resources = TRUE + var/infinite_resources = FALSE //No. var/static/obj/item/seasonal_hat //Share it with all other scarabs, since we're from the same cult! /obj/item/clockwork/construct_chassis/cogscarab/Initialize() . = ..() if(GLOB.servants_active) - infinite_resources = FALSE //For any that are somehow spawned in late + infinite_resources = FALSE //This check is relatively irrelevant until *someone* makes the infinite resources var default to true again, so, leaving it in. /obj/item/clockwork/construct_chassis/cogscarab/pre_spawn() if(infinite_resources) - //During rounds where they can't interact with the station, let them experiment with builds + //During rounds where they can't interact with the station, let them experiment with builds, if an admin allows them to. construct_type = /mob/living/simple_animal/drone/cogscarab/ratvar if(!seasonal_hat) var/obj/item/drone_shell/D = locate() in GLOB.poi_list diff --git a/code/modules/antagonists/clockcult/clock_items/integration_cog.dm b/code/modules/antagonists/clockcult/clock_items/integration_cog.dm index 0ce70336fe..ab8e30c8bb 100644 --- a/code/modules/antagonists/clockcult/clock_items/integration_cog.dm +++ b/code/modules/antagonists/clockcult/clock_items/integration_cog.dm @@ -30,6 +30,7 @@ var/obj/item/stock_parts/cell/cell = apc.cell if(cell && (cell.charge / cell.maxcharge > COG_MAX_SIPHON_THRESHOLD)) cell.use(1) + apc.cog_drained++ adjust_clockwork_power(2) //Power is shared, so only do it once; this runs very quickly so it's about 10 W/second else adjust_clockwork_power(1) //Continue generating power when the cell has run dry; 5 W/second diff --git a/code/modules/antagonists/clockcult/clock_mobs.dm b/code/modules/antagonists/clockcult/clock_mobs.dm index 87466d65f2..2f00fd4e4a 100644 --- a/code/modules/antagonists/clockcult/clock_mobs.dm +++ b/code/modules/antagonists/clockcult/clock_mobs.dm @@ -6,7 +6,6 @@ unique_name = 1 minbodytemp = 0 unsuitable_atmos_damage = 0 - threat = 1 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) //Robotic damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) healable = FALSE diff --git a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm index faa5e025ca..2f6a018a4c 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/_eminence.dm @@ -114,24 +114,27 @@ superheat_wall(A) return if(modifiers["middle"] || modifiers["ctrl"]) - issue_command(A) + INVOKE_ASYNC(src, .proc/issue_command, A) return if(GLOB.ark_of_the_clockwork_justiciar == A) var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar - if(G.recalling) - return - if(!G.recalls_remaining) - to_chat(src, "The Ark can no longer recall!") - return - if(alert(src, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(src) || QDELETED(G) || !G.obj_integrity) - return - G.initiate_mass_recall() //wHOOPS LOOKS LIKE A HULK GOT THROUGH + INVOKE_ASYNC(src, .proc/attempt_recall, G) else if(istype(A, /obj/structure/destructible/clockwork/trap/trigger)) var/obj/structure/destructible/clockwork/trap/trigger/T = A T.visible_message("[T] clunks as it's activated remotely.") to_chat(src, "You activate [T].") T.activate() +/mob/camera/eminence/proc/attempt_recall(obj/structure/destructible/clockwork/massive/celestial_gateway/G) + if(G.recalling) + return + if(!G.recalls_remaining) + to_chat(src, "The Ark can no longer recall!") + return + if(alert(src, "Initiate mass recall?", "Mass Recall", "Yes", "No") != "Yes" || QDELETED(src) || QDELETED(G) || !G.obj_integrity) + return + G.initiate_mass_recall() //wHOOPS LOOKS LIKE A HULK GOT THROUGH + /mob/camera/eminence/ratvar_act() name = "\improper Radiance" real_name = "\improper Radiance" diff --git a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm index dd37f3727c..76c9db7231 100644 --- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm +++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm @@ -9,7 +9,6 @@ desc = "The stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield." icon_state = "clockwork_marauder" mob_biotypes = MOB_HUMANOID - threat = 3 health = 120 maxHealth = 120 force_threshold = 8 @@ -40,8 +39,9 @@ if(!shield_health) return "Its shield has been destroyed!" -/mob/living/simple_animal/hostile/clockwork/marauder/Life() - ..() +/mob/living/simple_animal/hostile/clockwork/marauder/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return var/turf/T = get_turf(src) var/turf/open/space/S = isspaceturf(T)? T : null var/less_space_damage @@ -123,3 +123,437 @@ #undef MARAUDER_SLOWDOWN_PERCENTAGE #undef MARAUDER_SHIELD_REGEN_TIME + +//Clockwork guardian: Slow but with high damage, resides inside of a servant. Created via the Memory Allocation scripture. +/mob/living/simple_animal/hostile/clockwork/marauder/guardian + name = "clockwork guardian" + desc = "A stalwart apparition of a soldier, blazing with crimson flames. It's armed with a gladius and shield and stands ready by its master." + icon_state = "clockwork_marauder" + health = 300 + maxHealth = 300 + speed = 1 + obj_damage = 40 + melee_damage_lower = 12 + melee_damage_upper = 12 + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" + attack_sound = 'sound/weapons/bladeslice.ogg' + weather_immunities = list("lava") + movement_type = FLYING + AIStatus = AI_OFF //this has to be manually set so that the guardian doesn't start bashing the host, how annoying -_- + loot = list(/obj/item/clockwork/component/geis_capacitor/fallen_armor) + max_shield_health = 0 + shield_health = 0 + var/true_name = "Meme Master 69" //Required to call forth the guardian + var/global/list/possible_true_names = list("Servant", "Warden", "Serf", "Page", "Usher", "Knave", "Vassal", "Escort") + var/mob/living/host //The mob that the guardian is living inside of + var/recovering = FALSE //If the guardian is recovering from recalling + var/blockchance = 17 //chance to block attacks entirely + var/counterchance = 30 //chance to counterattack after blocking + var/static/list/damage_heal_order = list(OXY, BURN, BRUTE, TOX) //we heal our host's damage in this order + light_range = 2 + light_power = 1.1 + playstyle_string = "You are a clockwork guardian, a living extension of Sevtug's will. As a guardian, you are somewhat slow, but may block attacks, \ + and have a chance to also counter blocked melee attacks for extra damage, in addition to being immune to extreme temperatures and pressures. \ + Your primary goal is to serve the creature that you are now a part of, as well as The Clockwork Justiciar, Ratvar. You can use The Hierophant Network to communicate silently with your master and their allies, \ + but can only exit if your master calls your true name or if they are exceptionally damaged. \ + \n\n\ + Stay near your host to protect and heal them; being too far from your host will rapidly cause you massive damage. Recall to your host if you are too weak and believe you cannot continue \ + fighting safely. As a final note, you should probably avoid harming any fellow servants of Ratvar.
    " + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Initialize() + . = ..() + true_name = pick(possible_true_names) + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/BiologicalLife(seconds, times_fired) + ..() + if(is_in_host()) + if(!is_servant_of_ratvar(host)) + emerge_from_host(FALSE, TRUE) + unbind_from_host() + return + if(!GLOB.ratvar_awakens && host.stat == DEAD) + death() + return + if(GLOB.ratvar_awakens) + adjustHealth(-50) + else + adjustHealth(-10) + if(!recovering) + heal_host() //also heal our host if inside of them and we aren't recovering + else if(health == maxHealth) + to_chat(src, "Your strength has returned. You can once again come forward!") + to_chat(host, "Your guardian is now strong enough to come forward again!") + recovering = FALSE + else + if(GLOB.ratvar_awakens) //If Ratvar is alive, guardians don't need a host and are downright impossible to kill + adjustHealth(-5) + heal_host() + else if(host) + if(!is_servant_of_ratvar(host)) + unbind_from_host() + return + if(host.stat == DEAD) + adjustHealth(50) + to_chat(src, "Your host is dead!") + return + if(z && host.z && z == host.z) + switch(get_dist(get_turf(src), get_turf(host))) + if(2) + adjustHealth(-1) + if(3) + //EQUILIBRIUM + if(4) + adjustHealth(1) + if(5) + adjustHealth(3) + if(6) + adjustHealth(6) + if(7) + adjustHealth(9) + if(8 to INFINITY) + adjustHealth(15) + to_chat(src, "You're too far from your host and rapidly taking damage!") + else //right next to or on top of host + adjustHealth(-2) + heal_host() //gradually heal host if nearby and host is very weak + else //well then, you're not even in the same zlevel + adjustHealth(15) + to_chat(src, "You're too far from your host and rapidly taking damage!") + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/death(gibbed) + emerge_from_host(FALSE, TRUE) + unbind_from_host() + visible_message("[src]'s equipment clatters lifelessly to the ground as the red flames within dissipate.", \ + "Your equipment falls away. You feel a moment of confusion before your fragile form is annihilated.") + . = ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Stat() + ..() + if(statpanel("Status")) + stat(null, "Current True Name: [true_name]") + stat(null, "Host: [host ? host : "NONE"]") + if(host) + var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5) + if(iscarbon(host)) + resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100) + stat(null, "Host Health: [resulthealth]%") + if(GLOB.ratvar_awakens) + stat(null, "You are [recovering ? "un" : ""]able to deploy!") + else + if(resulthealth > GUARDIAN_EMERGE_THRESHOLD) + stat(null, "You are [recovering ? "unable to deploy" : "able to deploy on hearing your True Name"]!") + else + stat(null, "You are [recovering ? "unable to deploy" : "able to deploy to protect your host"]!") + stat(null, "You do [melee_damage_upper] damage on melee attacks.") + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/Process_Spacemove(movement_dir = 0) + return 1 + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/bind_to_host(mob/living/new_host) + if(!new_host) + return FALSE + host = new_host + var/datum/action/innate/summon_guardian/SG = new() + SG.linked_guardian = src + SG.Grant(host) + var/datum/action/innate/linked_minds/LM = new() + LM.linked_guardian = src + LM.Grant(host) + return TRUE + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/unbind_from_host() + if(host) + for(var/datum/action/innate/summon_guardian/SG in host.actions) + qdel(SG) + for(var/datum/action/innate/linked_minds/LM in host.actions) + qdel(LM) + host = null + return TRUE + return FALSE + +//DAMAGE and FATIGUE +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/heal_host() + if(!host) + return + var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5) + if(iscarbon(host)) + resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100) + if(GLOB.ratvar_awakens || resulthealth <= GUARDIAN_EMERGE_THRESHOLD) + new /obj/effect/temp_visual/heal(host.loc, "#AF0AAF") + host.heal_ordered_damage(4, damage_heal_order) + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/adjustHealth(amount, updating_health = TRUE, forced = FALSE) + if(amount > 0) + for(var/mob/living/L in view(2, src)) + if(L.is_holding_item_of_type(/obj/item/nullrod)) + to_chat(src, "The presence of a brandished holy artifact weakens your armor!") + amount *= 4 //if a wielded null rod is nearby, it takes four times the health damage + break + . = ..() + if(src && updating_health) + update_health_hud() + update_stats() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/update_health_hud() + if(hud_used && hud_used.healths) + if(istype(hud_used, /datum/hud/marauder)) + var/datum/hud/marauder/G = hud_used + var/resulthealth + if(host) + if(iscarbon(host)) + resulthealth = "[round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100)]%" + else + resulthealth = "[round((host.health / host.maxHealth) * 100, 0.5)]%" + else + resulthealth = "NONE" + G.hosthealth.maptext = "
    HOST
    [resulthealth]
    " + hud_used.healths.maptext = "
    [round((health / maxHealth) * 100, 0.5)]%" + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/update_stats() + if(GLOB.ratvar_awakens) + speed = 0 + melee_damage_lower = 20 + melee_damage_upper = 20 + attack_verb_continuous = "devastates" + else + var/healthpercent = (health/maxHealth) * 100 + switch(healthpercent) + if(100 to 70) //Bonuses to speed and damage at high health + speed = 0 + melee_damage_lower = 16 + melee_damage_upper = 16 + attack_verb_continuous = "viciously slashes" + if(70 to 40) + speed = initial(speed) + melee_damage_lower = initial(melee_damage_lower) + melee_damage_upper = initial(melee_damage_upper) + attack_verb_continuous = initial(attack_verb_continuous) + if(40 to 30) //Damage decrease, but not speed + speed = initial(speed) + melee_damage_lower = 10 + melee_damage_upper = 10 + attack_verb_continuous = "lightly slashes" + if(30 to 20) //Speed decrease + speed = 2 + melee_damage_lower = 8 + melee_damage_upper = 8 + attack_verb_continuous = "lightly slashes" + if(20 to 10) //Massive speed decrease and weak melee attacks + speed = 3 + melee_damage_lower = 6 + melee_damage_upper = 6 + attack_verb_continuous = "weakly slashes" + if(10 to 0) //We are super weak and going to die + speed = 4 + melee_damage_lower = 4 + melee_damage_upper = 4 + attack_verb_continuous = "taps" + +//ATTACKING, BLOCKING, and COUNTERING + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/AttackingTarget() + if(is_in_host()) + return FALSE + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/bullet_act(obj/item/projectile/Proj) + if(blockOrCounter(null, Proj)) + return + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/hitby(atom/movable/AM, skipcatch, hitpush, blocked, atom/movable/AM, datum/thrownthing/throwingdatum) + if(blockOrCounter(null, AM)) + return + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_animal(mob/living/simple_animal/M) + if(istype(M, /mob/living/simple_animal/hostile/clockwork/marauder/guardian) || !blockOrCounter(M, M)) //we don't want infinite blockcounter loops if fighting another guardian + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_paw(mob/living/carbon/monkey/M) + if(!blockOrCounter(M, M)) + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_alien(mob/living/carbon/alien/humanoid/M) + if(!blockOrCounter(M, M)) + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_slime(mob/living/simple_animal/slime/M) + if(!blockOrCounter(M, M)) + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attack_hand(mob/living/carbon/human/M) + if(!blockOrCounter(M, M)) + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/nullrod) || !blockOrCounter(user, I)) + return ..() + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/blockOrCounter(mob/target, atom/textobject) + if(GLOB.ratvar_awakens) //if ratvar has woken, we block nearly everything at a very high chance + blockchance = 90 + counterchance = 90 + if(prob(blockchance)) + . = TRUE + if(target) + target.do_attack_animation(src) + target.DelayNextAction(CLICK_CD_MELEE) + blockchance = initial(blockchance) + playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 30, 1, 0, 1) //clang + visible_message("[src] blocks [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!", \ + "You block [target && isitem(textobject) ? "[target]'s [textobject.name]":"\the [textobject]"]!") + if(target && Adjacent(target)) + if(prob(counterchance)) + counterchance = initial(counterchance) + var/previousattack_verb_continuous = attack_verb_continuous + attack_verb_continuous = "counters" + UnarmedAttack(target) + attack_verb_continuous = previousattack_verb_continuous + else + counterchance = min(counterchance + initial(counterchance), 100) + else + blockchance = min(blockchance + initial(blockchance), 100) + if(GLOB.ratvar_awakens) + blockchance = 90 + counterchance = 90 + +//COMMUNICATION and EMERGENCE +/* +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/handle_inherent_channels(message, message_mode) + if(host && (is_in_host() || message_mode == MODE_BINARY)) + guardian_comms(message) + return TRUE + return ..() +*/ +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/guardian_comms(message) + var/name_part = "[src] ([true_name])" + message = "\"[message]\"" //Processed output + to_chat(src, "[name_part]: [message]") + to_chat(host, "[name_part]: [message]") + for(var/M in GLOB.mob_list) + if(isobserver(M)) + var/link = FOLLOW_LINK(M, src) + to_chat(M, "[link] [name_part] (to [findtextEx(host.name, host.real_name) ? "[host.name]" : "[host.real_name] (as [host.name])"]): [message] ") + return TRUE + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/return_to_host() + if(is_in_host()) + return FALSE + if(!host) + to_chat(src, "You don't have a host!") + return FALSE + var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5) + if(iscarbon(host)) + resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100) + host.visible_message("[host]'s skin flashes crimson!", "You feel [true_name]'s consciousness settle in your mind.") + visible_message("[src] suddenly disappears!", "You return to [host].") + forceMove(host) + if(resulthealth > GUARDIAN_EMERGE_THRESHOLD && health != maxHealth) + recovering = TRUE + to_chat(src, "You have weakened and will need to recover before manifesting again!") + to_chat(host, "[true_name] has weakened and will need to recover before manifesting again!") + return TRUE + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/try_emerge() + if(!host) + to_chat(src, "You don't have a host!") + return FALSE + if(!GLOB.ratvar_awakens) + var/resulthealth = round((host.health / host.maxHealth) * 100, 0.5) + if(iscarbon(host)) + resulthealth = round((abs(HEALTH_THRESHOLD_DEAD - host.health) / abs(HEALTH_THRESHOLD_DEAD - host.maxHealth)) * 100) + if(host.stat != DEAD && resulthealth > GUARDIAN_EMERGE_THRESHOLD) //if above 20 health, fails + to_chat(src, "Your host must be at [GUARDIAN_EMERGE_THRESHOLD]% or less health to emerge like this!") + return FALSE + return emerge_from_host(FALSE) + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/emerge_from_host(hostchosen, force) //Notice that this is a proc rather than a verb - guardians can NOT exit at will, but they CAN return + if(!is_in_host()) + return FALSE + if(!force && recovering) + if(hostchosen) + to_chat(host, "[true_name] is too weak to come forth!") + else + to_chat(host, "[true_name] tries to emerge to protect you, but it's too weak!") + to_chat(src, "You try to come forth, but you're too weak!") + return FALSE + if(!force) + if(hostchosen) //guardian approved + to_chat(host, "Your words echo with power as [true_name] emerges from your body!") + else + to_chat(host, "[true_name] emerges from your body to protect you!") + forceMove(host.loc) + visible_message("[host]'s skin glows red as [name] emerges from their body!", "You exit the safety of [host]'s body!") + return TRUE + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/get_alt_name() + return " ([text2ratvar(true_name)])" + +/mob/living/simple_animal/hostile/clockwork/marauder/guardian/proc/is_in_host() //Checks if the guardian is inside of their host + return host && loc == host + +//HOST ACTIONS + +//Summon guardian action: Calls forth or recalls your guardian +/datum/action/innate/summon_guardian + name = "Force Guardian to Emerge/Recall" + desc = "Allows you to force your clockwork guardian to emerge or recall as required." + button_icon_state = "clockwork_marauder" + background_icon_state = "bg_clock" + check_flags = AB_CHECK_CONSCIOUS + buttontooltipstyle = "clockcult" + var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian + var/list/defend_phrases = list("Defend me", "Come forth", "Assist me", "Protect me", "Give aid", "Help me") + var/list/return_phrases = list("Return", "Return to me", "Your job is done", "You have served", "Come back", "Retreat") + +/datum/action/innate/summon_guardian/IsAvailable() + if(!linked_guardian) + return FALSE + if(isliving(owner)) + var/mob/living/L = owner + if(!L.can_speak_vocal() || L.stat) + return FALSE + return ..() + +/datum/action/innate/summon_guardian/Activate() + if(linked_guardian.is_in_host()) + clockwork_say(owner, text2ratvar("[pick(defend_phrases)], [linked_guardian.true_name]!")) + linked_guardian.emerge_from_host(TRUE) + else + clockwork_say(owner, text2ratvar("[pick(return_phrases)], [linked_guardian.true_name]!")) + linked_guardian.return_to_host() + return TRUE + +//Linked Minds action: talks to your guardian +/datum/action/innate/linked_minds + name = "Linked Minds" + desc = "Allows you to silently communicate with your guardian." + button_icon_state = "linked_minds" + background_icon_state = "bg_clock" + check_flags = AB_CHECK_CONSCIOUS + buttontooltipstyle = "clockcult" + var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/linked_guardian + +/datum/action/innate/linked_minds/IsAvailable() + if(!linked_guardian) + return FALSE + return ..() + +/datum/action/innate/linked_minds/Activate() + var/message = stripped_input(owner, "Enter a message to tell your guardian.", "Telepathy") + if(!owner || !message) + return FALSE + if(!linked_guardian) + to_chat(owner, "Your guardian seems to have been destroyed!") + return FALSE + var/name_part = "Servant [findtextEx(owner.name, owner.real_name) ? "[owner.name]" : "[owner.real_name] (as [owner.name])"]" + message = "\"[message]\"" //Processed output + to_chat(owner, "[name_part]: [message]") + to_chat(linked_guardian, "[name_part]: [message]") + for(var/M in GLOB.mob_list) + if(isobserver(M)) + var/link = FOLLOW_LINK(M, src) + to_chat(M, "[link] [name_part] (to [linked_guardian] ([linked_guardian.true_name])): [message]") + return TRUE diff --git a/code/modules/antagonists/clockcult/clock_scripture.dm b/code/modules/antagonists/clockcult/clock_scripture.dm index 1ebefe4d05..a85245e9d0 100644 --- a/code/modules/antagonists/clockcult/clock_scripture.dm +++ b/code/modules/antagonists/clockcult/clock_scripture.dm @@ -3,8 +3,9 @@ Tiers and Requirements Pieces of scripture require certain follower counts, contruction value, and active caches in order to recite. Drivers: Unlocked by default -Scripts: 5 servants and a cache -Applications: 8 servants, 3 caches, and 100 CV +Scripts: 35k power or one convert +Applications: 50k or three converts +Judgement 5 converts */ /datum/clockwork_scripture @@ -129,11 +130,11 @@ Applications: 8 servants, 3 caches, and 100 CV SEND_SOUND(invoker, sound('sound/magic/clockwork/invoke_general.ogg')) return TRUE -/datum/clockwork_scripture/proc/check_offstation_penalty() +/datum/clockwork_scripture/proc/check_offstation_penalty()//don't cast spells away from the station var/turf/T = get_turf(invoker) if(!T || (!is_centcom_level(T.z) && !is_station_level(T.z) && !is_mining_level(T.z) && !is_reebe(T.z))) - channel_time *= 2 - power_cost *= 2 + channel_time *= 3 + power_cost *= 3 return TRUE /datum/clockwork_scripture/proc/check_special_requirements() //Special requirements for scriptures, checked multiple times during invocation diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm index ffe9ecfa80..cbf3bdaa38 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm @@ -1,5 +1,5 @@ ////////////////// -// APPLICATIONS // +// APPLICATIONS // For various structures and base building, as well as advanced power generation. ////////////////// @@ -23,6 +23,37 @@ quickbind = TRUE quickbind_desc = "Creates a Sigil of Transmission, which can drain and will store power for clockwork structures." +//Prolonging Prism: Creates a prism that will delay the shuttle at a power cost +/datum/clockwork_scripture/create_object/prolonging_prism + descname = "Powered Structure, Delay Emergency Shuttles" + name = "Prolonging Prism" + desc = "Creates a mechanized prism which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost." + invocations = list("May this prism...", "...grant us time to enact his will!") + channel_time = 80 + power_cost = 300 + object_path = /obj/structure/destructible/clockwork/powered/prolonging_prism + creator_message = "You form a prolonging prism, which will delay the arrival of an emergency shuttle at a massive power cost." + observer_message = "An onyx prism forms in midair and sprouts tendrils to support itself!" + invokers_required = 2 + multiple_invokers_used = TRUE + usage_tip = "The power cost to delay a shuttle increases based on the number of times activated." + tier = SCRIPTURE_APPLICATION + one_per_tile = TRUE + primary_component = VANGUARD_COGWHEEL + sort_priority = 4 + important = TRUE + quickbind = TRUE + quickbind_desc = "Creates a Prolonging Prism, which will delay the arrival of an emergency shuttle by 2 minutes at a massive power cost." + +/datum/clockwork_scripture/create_object/prolonging_prism/check_special_requirements() + if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) + to_chat(invoker, "\"It is too late to construct one of these, champion.\"") + return FALSE + var/turf/T = get_turf(invoker) + if(!T || !is_station_level(T.z)) + to_chat(invoker, "\"You must be on the station to construct one of these, champion.\"") + return FALSE + return ..() //Mania Motor: Creates a malevolent transmitter that will broadcast the whispers of Sevtug into the minds of nearby nonservants, causing a variety of mental effects at a power cost. /datum/clockwork_scripture/create_object/mania_motor @@ -44,6 +75,7 @@ sort_priority = 2 quickbind = TRUE quickbind_desc = "Creates a Mania Motor, which causes minor damage and negative mental effects in non-Servants." + requires_full_power = TRUE //Clockwork Obelisk: Creates a powerful obelisk that can be used to broadcast messages or open a gateway to any servant or clockwork obelisk at a power cost. @@ -67,6 +99,64 @@ quickbind = TRUE quickbind_desc = "Creates a Clockwork Obelisk, which can send messages or open Spatial Gateways with power." +//Memory Allocation: Finds a willing ghost and makes them into a clockwork guardian for the invoker. +/datum/clockwork_scripture/memory_allocation + descname = "Personal Guardian, A Peice Of Your Mind." + name = "Memory Allocation" + desc = "Allocates part of your consciousness to a Clockwork Guardian, a variant of Marauder that lives within you, able to be \ + called forth by Speaking its True Name or if you become exceptionally low on health.
    \ + If it remains close to you, you will gradually regain health up to a low amount, but it will die if it goes too far from you." + invocations = list("Fright's will...", "...call forth...") + channel_time = 100 + power_cost = 8000 + usage_tip = "guardians are useful as personal bodyguards and frontline warriors." + tier = SCRIPTURE_APPLICATION + primary_component = GEIS_CAPACITOR + sort_priority = 5 + +/datum/clockwork_scripture/memory_allocation/check_special_requirements() + for(var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M in GLOB.all_clockwork_mobs) + if(M.host == invoker) + to_chat(invoker, "You can only house one guardian at a time!") + return FALSE + return TRUE + +/datum/clockwork_scripture/memory_allocation/scripture_effects() + return create_guardian() + +/datum/clockwork_scripture/memory_allocation/proc/create_guardian() + invoker.visible_message("A purple tendril appears from [invoker]'s [slab.name] and impales itself in [invoker.p_their()] forehead!", \ + "A tendril flies from [slab] into your forehead. You begin waiting while it painfully rearranges your thought pattern...") + //invoker.notransform = TRUE //Vulnerable during the process + slab.busy = "Thought Modification in progress" + if(!do_after(invoker, 50, target = invoker)) + invoker.visible_message("The tendril, covered in blood, retracts from [invoker]'s head and back into the [slab.name]!", \ + "Total agony overcomes you as the tendril is forced out early!") + invoker.Knockdown(100) + invoker.apply_damage(50, BRUTE, "head")//Sevtug leaves a gaping hole in your face if interrupted. + slab.busy = null + return FALSE + clockwork_say(invoker, text2ratvar("...the mind made...")) + //invoker.notransform = FALSE + slab.busy = "Guardian Selection in progress" + if(!check_special_requirements()) + return FALSE + to_chat(invoker, "The tendril shivers slightly as it selects a guardian...") + var/list/marauder_candidates = pollGhostCandidates("Do you want to play as the clockwork guardian of [invoker.real_name]?", ROLE_SERVANT_OF_RATVAR, null, FALSE, 50, POLL_IGNORE_HOLOPARASITE) + if(!check_special_requirements()) + return FALSE + if(!marauder_candidates.len) + invoker.visible_message("The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!", \ + "The tendril was unsuccessful! Perhaps you should try again another time.") + return FALSE + clockwork_say(invoker, text2ratvar("...sword and shield!")) + var/mob/dead/observer/theghost = pick(marauder_candidates) + var/mob/living/simple_animal/hostile/clockwork/marauder/guardian/M = new(invoker) + M.key = theghost.key + M.bind_to_host(invoker) + invoker.visible_message("The tendril retracts from [invoker]'s head, sealing the entry wound as it does so!", \ + "[M.true_name], a clockwork guardian, has taken up residence in your mind. Communicate with it via the \"Linked Minds\" action button.") + return TRUE //Clockwork Marauder: Creates a construct shell for a clockwork marauder, a well-rounded frontline fighter. /datum/clockwork_scripture/create_object/construct/clockwork_marauder @@ -81,7 +171,7 @@ tier = SCRIPTURE_APPLICATION one_per_tile = TRUE primary_component = BELLIGERENT_EYE - sort_priority = 4 + sort_priority = 6 quickbind = TRUE quickbind_desc = "Creates a clockwork marauder, used for frontline combat." object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder @@ -117,14 +207,13 @@ /datum/clockwork_scripture/create_object/summon_arbiter descname = "Powerful Assault Mech" name = "Summon Neovgre, the Anima Bulwark" - desc = "Calls forth the mighty Anima Bulwark, a weapon of unmatched power,\ - mech with superior defensive and offensive capabilities. It will \ + desc = "Calls forth the mighty Anima Bulwark, a mech with superior defensive and offensive capabilities. It will \ steadily regenerate HP and triple its regeneration speed while standing \ on a clockwork tile. It will automatically draw power from nearby sigils of \ transmission should the need arise. Its Arbiter laser cannon can decimate foes \ from a range and is capable of smashing through any barrier presented to it. \ - Be warned, choosing to pilot Neovgre is a lifetime commitment, once you are \ - in you cannot leave and when it is destroyed it will explode catastrophically with you inside." + Be warned however, choosing to pilot Neovgre is a lifetime commitment, once you are \ + in you cannot leave and when it is destroyed it will explode catastrophically, with you inside." invocations = list("By the strength of the alloy...!!", "...call forth the Arbiter!!") channel_time = 200 // This is a strong fucking weapon, 20 seconds channel time is getting off light I tell ya. power_cost = 75000 //75 KW @@ -134,7 +223,7 @@ object_path = /obj/mecha/combat/neovgre tier = SCRIPTURE_APPLICATION primary_component = BELLIGERENT_EYE - sort_priority = 2 + sort_priority = 7 creator_message = "Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come." /datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements() diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm index 819dfac72e..3dacecf6b4 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_cyborg.dm @@ -1,5 +1,5 @@ ///////////////// -// CYBORG ONLY // +// CYBORG ONLY // Cyborgs only, fleshed ones. ///////////////// //Linked Vanguard: grants Vanguard to the invoker and a target diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm index 6349ecb581..b7c94d56df 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm @@ -1,5 +1,5 @@ ///////////// -// DRIVERS // +// DRIVERS // Starter spells ///////////// //Stargazer: Creates a stargazer, a cheap power generator that utilizes starlight. @@ -97,7 +97,7 @@ desc = "Charges your slab with divine energy, allowing you to overwhelm a target with Ratvar's light." invocations = list("Divinity, show them your light!") whispered = TRUE - channel_time = 20 // I think making kindle channel a third of the time less is a good make up for the fact that it silences people for such a little amount of time. + channel_time = 25 //2.5 seconds should be a okay compromise between being able to use it when needed, and not being able to just pause in combat for a second and hardstunning your enemy power_cost = 125 usage_tip = "The light can be used from up to two tiles away. Damage taken will GREATLY REDUCE the stun's duration." tier = SCRIPTURE_DRIVER @@ -113,7 +113,6 @@ quickbind = TRUE quickbind_desc = "Stuns and mutes a target from a short range." - //Hateful Manacles: Applies restraints from melee over several seconds. The restraints function like handcuffs and break on removal. /datum/clockwork_scripture/ranged_ability/hateful_manacles descname = "Handcuffs" @@ -138,6 +137,30 @@ quickbind_desc = "Applies handcuffs to a struck target." +//Belligerent: Channeled for up to fifteen times over thirty seconds. Forces non-servants that can hear the chant to walk, doing minor damage. Nar-Sian cultists are burned. +/datum/clockwork_scripture/channeled/belligerent + descname = "Channeled, Area Slowdown" + name = "Belligerent" + desc = "Forces all nearby non-servants to walk rather than run, doing minor damage. Chanted every two seconds for up to thirty seconds." + chant_invocations = list("Punish their blindness!", "Take time, make slow!", "Kneel before The Justiciar!", "Halt their charges!", "Cease the tides!") + chant_amount = 15 + chant_interval = 20 + channel_time = 20 + power_cost = 300 + usage_tip = "Useful for crowd control in a populated area and disrupting mass movement." + tier = SCRIPTURE_DRIVER + primary_component = BELLIGERENT_EYE + sort_priority = 7 + quickbind = TRUE + quickbind_desc = "Forces nearby non-Servants to walk, doing minor damage with each chant.
    Maximum 15 chants." + +/datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number) + for(var/mob/living/carbon/C in hearers(7, invoker)) + C.apply_status_effect(STATUS_EFFECT_BELLIGERENT) + new /obj/effect/temp_visual/ratvar/belligerent(get_turf(invoker)) + return TRUE + + //Vanguard: Provides twenty seconds of greatly increased stamina regeneration and stun immunity. At the end of the twenty seconds, 25% of all stuns absorbed aswell as 50% of healed stamloss are applied to the invoker. /datum/clockwork_scripture/vanguard descname = "Self Stun Immunity" @@ -150,7 +173,7 @@ usage_tip = "You cannot reactivate Vanguard while still shielded by it." tier = SCRIPTURE_DRIVER primary_component = VANGUARD_COGWHEEL - sort_priority = 7 + sort_priority = 8 quickbind = TRUE quickbind_desc = "Allows you to temporarily have quickly regenerating stamina and absorb stuns. Part of the stuns absorbed and staminaloss healed will affect you when disabled." @@ -182,7 +205,7 @@ usage_tip = "The Compromise is very fast to invoke, and will remove holy water from the target Servant." tier = SCRIPTURE_DRIVER primary_component = VANGUARD_COGWHEEL - sort_priority = 8 + sort_priority = 9 quickbind = TRUE quickbind_desc = "Allows you to convert a Servant's brute, burn, and oxygen damage to half toxin damage.
    Click your slab to disable." slab_overlay = "compromise" @@ -192,43 +215,39 @@ Click your slab to cancel.
    " +/*//commenting this out until its reworked to actually do random teleports //Abscond: Used to return to Reebe. /datum/clockwork_scripture/abscond - descname = "Return to Reebe" + descname = "Safety warp, teleports you somewhere random. moderately high power cost to use." name = "Abscond" - desc = "Yanks you through space, returning you to home base." + desc = "Yanks you through space, putting you in hopefully a safe location." invocations = list("As we bid farewell, and return to the stars...", "...we shall find our way home.") whispered = TRUE - channel_time = 50 - power_cost = 5 - special_power_text = "POWERCOST to bring pulled creature" - special_power_cost = ABSCOND_ABDUCTION_COST + channel_time = 3.5 + power_cost = 10000 usage_tip = "This can't be used while on Reebe, for obvious reasons." tier = SCRIPTURE_DRIVER primary_component = GEIS_CAPACITOR sort_priority = 9 important = TRUE quickbind = TRUE - quickbind_desc = "Returns you to Reebe." + quickbind_desc = "Teleports you somewhere random, or to an active Ark if one exists. Use in emergencies." var/client_color requires_full_power = TRUE /datum/clockwork_scripture/abscond/check_special_requirements() if(is_reebe(invoker.z)) - to_chat(invoker, "You're already at Reebe.") + to_chat(invoker, "You're at Reebe, attempting to warp in the void could cause you to share your masters fate of banishment!.") return if(!isturf(invoker.loc)) - to_chat(invoker, "You must be visible to return!") + to_chat(invoker, "You must be visible to warp!") return return TRUE /datum/clockwork_scripture/abscond/recital() - client_color = invoker.client.color - animate(invoker.client, color = "#AF0AAF", time = 50) . = ..() /datum/clockwork_scripture/abscond/scripture_effects() - var/mob/living/pulled_mob = (invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST)) ? invoker.pulling : null var/turf/T if(GLOB.ark_of_the_clockwork_justiciar) T = get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH) @@ -237,21 +256,12 @@ if(!do_teleport(invoker, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) return invoker.visible_message("[invoker] flickers and phases out of existence!", \ - "You feel a dizzying sense of vertigo as you're yanked back to Reebe!") + "You feel a dizzying sense of vertigo as you're yanked through the fabric of reality!") T.visible_message("[invoker] flickers and phases into existence!") playsound(invoker, 'sound/magic/magic_missile.ogg', 50, TRUE) playsound(T, 'sound/magic/magic_missile.ogg', 50, TRUE) do_sparks(5, TRUE, invoker) - do_sparks(5, TRUE, T) - if(pulled_mob && do_teleport(pulled_mob, T, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)) - adjust_clockwork_power(-special_power_cost) - invoker.start_pulling(pulled_mob) //forcemove resets pulls, so we need to re-pull - if(invoker.client) - animate(invoker.client, color = client_color, time = 25) - -/datum/clockwork_scripture/abscond/scripture_fail() - if(invoker && invoker.client) - animate(invoker.client, color = client_color, time = 10) + do_sparks(5, TRUE, T)*/ //Replicant: Creates a new clockwork slab. @@ -265,11 +275,11 @@ whispered = TRUE object_path = /obj/item/clockwork/slab creator_message = "You copy a piece of replicant alloy and command it into a new slab." - usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components." + usage_tip = "This is inefficient as a way to produce power, as the slab produced must be held by someone with no other slabs to produce any." tier = SCRIPTURE_DRIVER space_allowed = TRUE primary_component = GEIS_CAPACITOR - sort_priority = 10 + sort_priority = 11 important = TRUE quickbind = TRUE quickbind_desc = "Creates a new Clockwork Slab." @@ -290,6 +300,53 @@ tier = SCRIPTURE_DRIVER space_allowed = TRUE primary_component = GEIS_CAPACITOR - sort_priority = 11 + sort_priority = 12 quickbind = TRUE quickbind_desc = "Creates a pair of Wraith Spectacles, which grant true sight but cause gradual vision loss." + +//Spatial Gateway: Allows the invoker to teleport themselves and any nearby allies to a conscious servant or clockwork obelisk. +/datum/clockwork_scripture/spatial_gateway + descname = "Teleport Gate" + name = "Spatial Gateway" + desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \ + Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration." + invocations = list("Spatial Gateway...", "...activate!") + channel_time = 30 + power_cost = 400 + whispered = TRUE + multiple_invokers_used = TRUE + multiple_invokers_optional = TRUE + usage_tip = "This gateway is strictly one-way and will only allow things through the invoker's portal." + tier = SCRIPTURE_DRIVER + primary_component = GEIS_CAPACITOR + sort_priority = 10 + quickbind = TRUE + quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk." + +/datum/clockwork_scripture/spatial_gateway/check_special_requirements() + if(!isturf(invoker.loc)) + to_chat(invoker, "You must not be inside an object to use this scripture!") + return FALSE + var/other_servants = 0 + for(var/mob/living/L in GLOB.alive_mob_list) + if(is_servant_of_ratvar(L) && !L.stat && L != invoker) + other_servants++ + for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects) + if(O.anchored) + other_servants++ + if(!other_servants) + to_chat(invoker, "There are no other conscious servants or anchored clockwork obelisks!") + return FALSE + return TRUE + +/datum/clockwork_scripture/spatial_gateway/scripture_effects() + var/portal_uses = 0 + var/duration = 0 + for(var/mob/living/L in range(1, invoker)) + if(!L.stat && is_servant_of_ratvar(L)) + portal_uses++ + duration += 40 //4 seconds + if(GLOB.ratvar_awakens) + portal_uses = max(portal_uses, 100) //Very powerful if Ratvar has been summoned + duration = max(duration, 100) + return slab.procure_gateway(invoker, duration, portal_uses) \ No newline at end of file diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm new file mode 100644 index 0000000000..5075840e76 --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_judgement.dm @@ -0,0 +1,44 @@ +/////////////// +// JUDGEMENT // For the big game changing things. TODO: Summonable generals, just need mob sprites for them. +/////////////// + +//Ark of the Clockwork Justiciar: Creates a Gateway to the Celestial Derelict, summoning ratvar. +/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar + descname = "Structure, Win Condition" + name = "Ark of the Clockwork Justiciar" + desc = "Tears apart a rift in spacetime to Reebe, the Celestial Derelict, using a massive amount of power.\n\ + This gateway will, after some time, call forth Ratvar from his exile and massively empower all scriptures and tools." + invocations = list("ARMORER! FRIGHT! AMPERAGE! VANGUARD! WE CALL UPON YOU!!", \ + "THE TIME HAS COME FOR OUR MASTER TO BREAK THE CHAINS OF EXILE!!", \ + "LEND US YOUR AID! ENGINE COMES!!") + channel_time = 150 + power_cost = 70000 //70 KW. It's literally the thing wrenching the god out of another dimension why wouldn't it be costly. + invokers_required = 6 + multiple_invokers_used = TRUE + object_path = /obj/structure/destructible/clockwork/massive/celestial_gateway + creator_message = "The Ark swirls into existance before you with the help of the Generals. After all this time, he shall, finally, be free" + usage_tip = "The gateway is completely vulnerable to attack during its five-minute duration. It will periodically give indication of its general position to everyone on the station \ + as well as being loud enough to be heard throughout the entire sector. Defend it with your life!" + tier = SCRIPTURE_APPLICATION + sort_priority = 8 + requires_full_power = TRUE + +/datum/clockwork_scripture/create_object/ark_of_the_clockwork_justiciar/check_special_requirements() + if(!slab.no_cost) + if(GLOB.ratvar_awakens) + to_chat(invoker, "\"I am already here, there is no point in that.\"") + return FALSE + for(var/obj/structure/destructible/clockwork/massive/celestial_gateway/G in GLOB.all_clockwork_objects) + var/area/gate_area = get_area(G) + to_chat(invoker, "There is already an Ark at [gate_area.map_name]!") + return FALSE + var/area/A = get_area(invoker) + var/turf/T = get_turf(invoker) + if(!T || !is_station_level(T.z) || istype(A, /area/shuttle) || !A.blob_allowed) + to_chat(invoker, "You must be on the station to activate the Ark!") + return FALSE + if(GLOB.clockwork_gateway_activated) + to_chat(invoker, "Ratvar's recent banishment renders him too weak to be wrung forth from Reebe!") + return FALSE + return ..() + diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm index d22a2f69b7..eaec652f68 100644 --- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm +++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_scripts.dm @@ -1,5 +1,5 @@ ///////////// -// SCRIPTS // +// SCRIPTS // Various miscellanious spells for offense/defense/construction. ///////////// @@ -81,6 +81,25 @@ return /obj/effect/clockwork/sigil/vitality/neutered return ..() +//Sigil of Rites: Creates a sigil that allows to perform certain rites on it. More information on these can be found in clock_rites.dm, they usually require power, materials and sometimes a target. +/datum/clockwork_scripture/create_object/sigil_of_rites + descname = "Sigil, Access to rites" + name = "Sigil of Rites" + desc = "Places a sigil that, when interacted with, will allow for a variety of rites to be performed on the sigil. These usually require power cells, clockwork power, and some other components." + invocations = list("Engine, allow us..", ".. to be blessed with your rites.") + channel_time = 80 + power_cost = 1400 + invokers_required = 2 + multiple_invokers_used = TRUE + whispered = TRUE + object_path = /obj/effect/clockwork/sigil/rite + creator_message = "A sigil of Rites appears beneath you. It will allow you to perform certain rites, given sufficient materials and power." + usage_tip = "It may be useful to coordinate to acquire needed materials quickly." + tier = SCRIPTURE_SCRIPT + one_per_tile = TRUE + primary_component = HIEROPHANT_ANSIBLE + sort_priority = 4 + //Judicial Visor: Creates a judicial visor, which can smite an area. /datum/clockwork_scripture/create_object/judicial_visor descname = "Delayed Area Knockdown Glasses" @@ -96,7 +115,7 @@ tier = SCRIPTURE_SCRIPT space_allowed = TRUE primary_component = BELLIGERENT_EYE - sort_priority = 4 + sort_priority = 5 quickbind = TRUE quickbind_desc = "Creates a Judicial Visor, which can smite an area, applying Belligerent and briefly stunning." @@ -115,7 +134,7 @@ tier = SCRIPTURE_SCRIPT space_allowed = TRUE primary_component = VANGUARD_COGWHEEL - sort_priority = 6 + sort_priority = 7 quickbind = TRUE quickbind_desc = "Creates a Ratvarian shield, which can absorb energy from attacks for use in powerful bashes." @@ -131,7 +150,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 = 7 + sort_priority = 8 important = TRUE quickbind = TRUE quickbind_desc = "Permanently binds clockwork armor and a Ratvarian spear to you." @@ -217,53 +236,6 @@ weapon_type = /obj/item/clockwork/weapon/ratvarian_spear -//Spatial Gateway: Allows the invoker to teleport themselves and any nearby allies to a conscious servant or clockwork obelisk. -/datum/clockwork_scripture/spatial_gateway - descname = "Teleport Gate" - name = "Spatial Gateway" - desc = "Tears open a miniaturized gateway in spacetime to any conscious servant that can transport objects or creatures to its destination. \ - Each servant assisting in the invocation adds one additional use and four additional seconds to the gateway's uses and duration." - invocations = list("Spatial Gateway...", "...activate!") - channel_time = 80 - power_cost = 400 - multiple_invokers_used = TRUE - multiple_invokers_optional = TRUE - 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 = 9 - quickbind = TRUE - quickbind_desc = "Allows you to create a one-way Spatial Gateway to a living Servant or Clockwork Obelisk." - -/datum/clockwork_scripture/spatial_gateway/check_special_requirements() - if(!isturf(invoker.loc)) - to_chat(invoker, "You must not be inside an object to use this scripture!") - return FALSE - var/other_servants = 0 - for(var/mob/living/L in GLOB.alive_mob_list) - if(is_servant_of_ratvar(L) && !L.stat && L != invoker) - other_servants++ - for(var/obj/structure/destructible/clockwork/powered/clockwork_obelisk/O in GLOB.all_clockwork_objects) - if(O.anchored) - other_servants++ - if(!other_servants) - to_chat(invoker, "There are no other conscious servants or anchored clockwork obelisks!") - return FALSE - return TRUE - -/datum/clockwork_scripture/spatial_gateway/scripture_effects() - var/portal_uses = 0 - var/duration = 0 - for(var/mob/living/L in range(1, invoker)) - if(!L.stat && is_servant_of_ratvar(L)) - portal_uses++ - duration += 40 //4 seconds - if(GLOB.ratvar_awakens) - portal_uses = max(portal_uses, 100) //Very powerful if Ratvar has been summoned - duration = max(duration, 100) - return slab.procure_gateway(invoker, duration, portal_uses) - - //Mending Mantra: Channeled for up to ten times over twenty seconds to repair structures and heal allies /datum/clockwork_scripture/channeled/mending_mantra descname = "Channeled, Area Healing and Repair" @@ -276,7 +248,7 @@ usage_tip = "This is a very effective way to rapidly reinforce a base after an attack." tier = SCRIPTURE_SCRIPT primary_component = VANGUARD_COGWHEEL - sort_priority = 8 + sort_priority = 9 quickbind = TRUE quickbind_desc = "Repairs nearby structures and constructs. Servants wearing clockwork armor will also be healed.
    Maximum 10 chants." var/heal_attempts = 4 @@ -389,7 +361,7 @@ usage_tip = "Though it requires you to stand still, this scripture can do massive damage." tier = SCRIPTURE_SCRIPT primary_component = BELLIGERENT_EYE - sort_priority = 5 + sort_priority = 6 quickbind = TRUE quickbind_desc = "Allows you to fire energy rays at target locations.
    Maximum 5 chants." var/static/list/nzcrentr_insults = list("You're not very good at aiming.", "You hunt badly.", "What a waste of energy.", "Almost funny to watch.", @@ -438,7 +410,7 @@ usage_tip = "It may be useful to end channelling early if the burning becomes too much to handle.." tier = SCRIPTURE_SCRIPT primary_component = GEIS_CAPACITOR - sort_priority = 10 + sort_priority = 11 quickbind = TRUE quickbind_desc = "Quickly drains power in an area around the invoker, causing burns proportional to the amount of energy drained.
    Maximum of 20 chants." diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm index 297856f531..7478d45b08 100644 --- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm +++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm @@ -1,5 +1,3 @@ -#define ARK_GRACE_PERIOD 300 //In seconds, how long the crew has before the Ark truly "begins" - /proc/clockwork_ark_active() //A helper proc so the Ark doesn't have to be typecast every time it's checked; returns null if there is no Ark and its active var otherwise var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar if(!G) @@ -11,7 +9,7 @@ name = "\improper Ark of the Clockwork Justicar" desc = "A massive, hulking amalgamation of parts. It seems to be maintaining a very unstable bluespace anomaly." clockwork_desc = "Nezbere's magnum opus: a hulking clockwork machine capable of combining bluespace and steam power to summon Ratvar. Once activated, \ - its instability will cause one-way bluespace rifts to open across the station to the City of Cogs, so be prepared to defend it at all costs." + its instability will alert the entire area, so be prepared to defend it at all costs." max_integrity = 500 mouse_opacity = MOUSE_OPACITY_OPAQUE icon = 'icons/effects/clockwork_effects.dmi' @@ -22,9 +20,8 @@ immune_to_servant_attacks = TRUE var/active = FALSE var/progress_in_seconds = 0 //Once this reaches GATEWAY_RATVAR_ARRIVAL, it's game over - var/grace_period = ARK_GRACE_PERIOD //This exists to allow the crew to gear up and prepare for the invasion - var/initial_activation_delay = -1 //How many seconds the Ark will have initially taken to activate - var/seconds_until_activation = -1 //How many seconds until the Ark activates; if it should never activate, set this to -1 + var/initial_activation_delay = 5 //How many seconds the Ark will have initially taken to activate + var/seconds_until_activation = 5 //How many seconds until the Ark activates; if it should never activate, set this to -1 var/purpose_fulfilled = FALSE var/first_sound_played = FALSE var/second_sound_played = FALSE @@ -38,10 +35,21 @@ /obj/structure/destructible/clockwork/massive/celestial_gateway/Initialize() . = ..() + INVOKE_ASYNC(src, .proc/spawn_animation) glow = new(get_turf(src)) if(!GLOB.ark_of_the_clockwork_justiciar) GLOB.ark_of_the_clockwork_justiciar = src - START_PROCESSING(SSprocessing, src) + +/obj/structure/destructible/clockwork/massive/celestial_gateway/on_attack_hand(mob/user, act_intent, unarmed_attack_flags) + if(!active && is_servant_of_ratvar(user) && user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) + if(alert(user, "Are you sure you want to activate the ark? Once enabled, there will be no turning back.", "Enabling the ark", "Activate!", "Cancel") == "Activate!") + if(active) + return + log_game("[key_name(user)] has activated an Ark of the Clockwork Justicar at [COORD(src)].") + START_PROCESSING(SSprocessing, src) + SSshuttle.registerHostileEnvironment(src) + else + to_chat(user, "You decide against activating the ark.. for now.") /obj/structure/destructible/clockwork/massive/celestial_gateway/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() @@ -49,7 +57,7 @@ flick("clockwork_gateway_damaged", glow) playsound(src, 'sound/machines/clockcult/ark_damage.ogg', 75, FALSE) if(last_scream < world.time) - audible_message("An unearthly screaming sound resonates throughout Reebe!") + audible_message("An unearthly screaming sound resonates throughout the area!") for(var/V in GLOB.player_list) var/mob/M = V var/turf/T = get_turf(M) @@ -60,31 +68,19 @@ /obj/structure/destructible/clockwork/massive/celestial_gateway/proc/final_countdown(ark_time) //WE'RE LEAVING TOGETHEEEEEEEEER if(!ark_time) - ark_time = 30 //minutes - initial_activation_delay = ark_time * 60 - seconds_until_activation = ark_time * 60 //60 seconds in a minute * number of minutes + ark_time = 5 //5 minutes for(var/obj/item/clockwork/construct_chassis/cogscarab/C in GLOB.all_clockwork_objects) C.infinite_resources = FALSE GLOB.servants_active = TRUE SSshuttle.registerHostileEnvironment(src) -/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/cry_havoc() - visible_message("[src] shudders and roars to life, its parts beginning to whirr and screech!") - hierophant_message("The Ark is activating! You will be transported there soon!") - for(var/mob/M in GLOB.player_list) - var/turf/T = get_turf(M) - if(is_servant_of_ratvar(M) || isobserver(M) || (T && T.z == z)) - M.playsound_local(M, 'sound/magic/clockwork/ark_activation_sequence.ogg', 30, FALSE, pressure_affected = FALSE) - addtimer(CALLBACK(src, .proc/let_slip_the_dogs), 300) - /obj/structure/destructible/clockwork/massive/celestial_gateway/proc/let_slip_the_dogs() - spawn_animation() first_sound_played = TRUE active = TRUE + visible_message("[src] shudders and roars to life, its parts beginning to whirr and screech!") priority_announce("Massive [Gibberish("bluespace", 100)] anomaly detected on all frequencies. All crew are directed to \ @!$, [text2ratvar("PURGE ALL UNTRUTHS")] <&. the anomalies and destroy their source to prevent further damage to corporate property. This is \ - not a drill.[grace_period ? " Estimated time of appearance: [grace_period] seconds. Use this time to prepare for an attack on [station_name()]." : ""]", \ - "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation.ogg') + not a drill.", "Central Command Higher Dimensional Affairs", 'sound/magic/clockwork/ark_activation_sequence.ogg') set_security_level("delta") for(var/V in SSticker.mode.servants_of_ratvar) var/datum/mind/M = V @@ -92,15 +88,6 @@ continue if(ishuman(M.current)) M.current.add_overlay(mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER)) - for(var/V in GLOB.brass_recipes) - var/datum/stack_recipe/R = V - if(!R) - continue - if(R.title == "wall gear") - R.time *= 2 //Building walls becomes slower when the Ark activates - mass_recall() - recalls_remaining++ //So it doesn't use up a charge - var/turf/T = get_turf(src) var/list/open_turfs = list() for(var/turf/open/OT in orange(1, T)) @@ -110,14 +97,35 @@ for(var/mob/living/L in T) L.forceMove(pick(open_turfs)) -/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/open_portal(turf/T) - new/obj/effect/clockwork/city_of_cogs_rift(T) - /obj/structure/destructible/clockwork/massive/celestial_gateway/proc/spawn_animation() - hierophant_message("The Ark has activated! [grace_period ? "You have [round(grace_period / 60)] minutes until the crew invades! " : ""]Defend it at all costs!", FALSE, src) - sound_to_playing_players(volume = 10, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE)) - seconds_until_activation = 0 - SSshuttle.registerHostileEnvironment(src) + var/turf/T = get_turf(src) + new/obj/effect/clockwork/general_marker/inathneq(T) + hierophant_message("\"[text2ratvar("Engine, come forth and show your servants your mercy")]!\"") + playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 30, 0) + sleep(10) + new/obj/effect/clockwork/general_marker/sevtug(T) + hierophant_message("\"[text2ratvar("Engine, come forth and show this station your decorating skills")]!\"") + playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 45, 0) + sleep(10) + new/obj/effect/clockwork/general_marker/nezbere(T) + hierophant_message("\"[text2ratvar("Engine, come forth and shine your light across this realm")]!!\"") + playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 60, 0) + sleep(10) + new/obj/effect/clockwork/general_marker/nzcrentr(T) + hierophant_message("\"[text2ratvar("Engine, come forth")].\"") + playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 75, 0) + sleep(10) + playsound(T, 'sound/magic/clockwork/invoke_general.ogg', 100, 0) + var/list/open_turfs = list() + for(var/turf/open/OT in orange(1, T)) + if(!is_blocked_turf(OT, TRUE)) + open_turfs |= OT + if(open_turfs.len) + for(var/mob/living/L in T) + L.forceMove(pick(open_turfs)) + glow = new(get_turf(src)) + var/area/gate_area = get_area(src) + hierophant_message("An Ark of the Clockwork Justicar has been created in [gate_area.map_name]!", FALSE, src) /obj/structure/destructible/clockwork/massive/celestial_gateway/proc/initiate_mass_recall() recalling = TRUE @@ -141,35 +149,22 @@ transform = matrix() * 2 animate(src, transform = matrix() * 0.5, time = 30, flags = ANIMATION_END_NOW) -/obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy() +obj/structure/destructible/clockwork/massive/celestial_gateway/Destroy() STOP_PROCESSING(SSprocessing, src) + if(!purpose_fulfilled) + var/area/gate_area = get_area(src) + hierophant_message("An Ark of the Clockwork Justicar has fallen at [gate_area.map_name]!") + send_to_playing_players(sound(null, 0, channel = CHANNEL_JUSTICAR_ARK)) + var/was_stranded = SSshuttle.emergency.mode == SHUTTLE_STRANDED SSshuttle.clearHostileEnvironment(src) - if(!purpose_fulfilled && istype(SSticker.mode, /datum/game_mode/clockwork_cult)) - hierophant_message("The Ark has fallen!") - sound_to_playing_players(null, channel = CHANNEL_JUSTICAR_ARK) - SSticker.force_ending = TRUE //rip + if(!was_stranded && !purpose_fulfilled) + priority_announce("Massive energy anomaly no longer on short-range scanners, bluespace distortions still detected.","Central Command Higher Dimensional Affairs") if(glow) qdel(glow) glow = null if(countdown) qdel(countdown) countdown = null - for(var/mob/L in GLOB.player_list) - var/turf/T = get_turf(L) - if(T && T.z == z) - var/atom/movable/target = L - if(isobj(L.loc)) - target = L.loc - target.forceMove(get_turf(pick(GLOB.generic_event_spawns))) - L.overlay_fullscreen("flash", /obj/screen/fullscreen/flash/static) - L.clear_fullscreen("flash", 30) - if(isliving(L)) - var/mob/living/LI = L - LI.Stun(50) - for(var/obj/effect/clockwork/city_of_cogs_rift/R in GLOB.all_clockwork_objects) - qdel(R) - if(GLOB.ark_of_the_clockwork_justiciar == src) - GLOB.ark_of_the_clockwork_justiciar = null . = ..() /obj/structure/destructible/clockwork/massive/celestial_gateway/deconstruct(disassembled = TRUE) @@ -203,8 +198,6 @@ /obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_time(var/deciseconds = TRUE) if(seconds_until_activation) . = seconds_until_activation - else if(grace_period) - . = grace_period else if(GATEWAY_RATVAR_ARRIVAL - progress_in_seconds > 0) . = round(max((GATEWAY_RATVAR_ARRIVAL - progress_in_seconds) / (GATEWAY_SUMMON_RATE), 0), 1) if(deciseconds) @@ -213,8 +206,6 @@ /obj/structure/destructible/clockwork/massive/celestial_gateway/proc/get_arrival_text(s_on_time) if(seconds_until_activation) return "[get_arrival_time()][s_on_time ? "S" : ""]" - if(grace_period) - return "[get_arrival_time()][s_on_time ? "S" : ""]" . = "IMMINENT" if(!obj_integrity) . = "DETONATING" @@ -229,17 +220,14 @@ if(!active) . += "Time until the Ark's activation: [DisplayTimeText(get_arrival_time())]" else - if(grace_period) - . += "Crew grace period time remaining: [DisplayTimeText(get_arrival_time())]" - else - . += "Time until Ratvar's arrival: [DisplayTimeText(get_arrival_time())]" - switch(progress_in_seconds) - if(-INFINITY to GATEWAY_REEBE_FOUND) - . += "The Ark is feeding power into the bluespace field." - if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING) - . += "The field is ripping open a copy of itself in Ratvar's prison." - if(GATEWAY_RATVAR_COMING to INFINITY) - . += "With the bluespace field established, Ratvar is preparing to come through!" + . += "Time until Ratvar's arrival: [DisplayTimeText(get_arrival_time())]" + switch(progress_in_seconds) + if(-INFINITY to GATEWAY_REEBE_FOUND) + . += "The Ark is feeding power into the bluespace field." + if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING) + . += "The field is ripping open a copy of itself in Ratvar's prison." + if(GATEWAY_RATVAR_COMING to INFINITY) + . += "With the bluespace field established, Ratvar is preparing to come through!" else if(!active) . += "Whatever it is, it doesn't seem to be active." @@ -253,20 +241,14 @@ . += "The anomaly is stable! Something is coming through!" /obj/structure/destructible/clockwork/massive/celestial_gateway/process() - if(seconds_until_activation == -1) //we never do anything - return adjust_clockwork_power(2.5) //Provides weak power generation on its own if(seconds_until_activation) if(!countdown) countdown = new(src) countdown.start() seconds_until_activation-- - if(!GLOB.script_scripture_unlocked && initial_activation_delay * 0.5 > seconds_until_activation) - GLOB.script_scripture_unlocked = TRUE - hierophant_message("The Ark is halfway prepared. Script scripture is now available!") if(!seconds_until_activation) - cry_havoc() - seconds_until_activation = -1 //we'll set this after cry_havoc() + let_slip_the_dogs() return if(!first_sound_played || prob(7)) for(var/mob/M in GLOB.player_list) @@ -285,6 +267,9 @@ if(!step_away(O, src, 2) || get_dist(O, src) < 2) O.take_damage(50, BURN, "bomb") O.update_icon() + + conversion_pulse() //Converts the nearby area into clockcult-style + for(var/V in GLOB.player_list) var/mob/M = V var/turf/T = get_turf(M) @@ -292,29 +277,24 @@ M.forceMove(get_step(src, SOUTH)) M.overlay_fullscreen("flash", /obj/screen/fullscreen/flash) M.clear_fullscreen("flash", 5) - if(grace_period) - grace_period-- - return progress_in_seconds += GATEWAY_SUMMON_RATE switch(progress_in_seconds) if(-INFINITY to GATEWAY_REEBE_FOUND) if(!second_sound_played) - for(var/V in GLOB.generic_event_spawns) - addtimer(CALLBACK(src, .proc/open_portal, get_turf(V)), rand(100, 600)) sound_to_playing_players('sound/magic/clockwork/invoke_general.ogg', 30, FALSE) - sound_to_playing_players(volume = 20, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE)) + sound_to_playing_players(volume = 10, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_charging.ogg', TRUE)) second_sound_played = TRUE make_glow() glow.icon_state = "clockwork_gateway_charging" if(GATEWAY_REEBE_FOUND to GATEWAY_RATVAR_COMING) if(!third_sound_played) - sound_to_playing_players(volume = 25, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_active.ogg', TRUE)) + sound_to_playing_players(volume = 30, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_active.ogg', TRUE)) third_sound_played = TRUE make_glow() glow.icon_state = "clockwork_gateway_active" if(GATEWAY_RATVAR_COMING to GATEWAY_RATVAR_ARRIVAL) if(!fourth_sound_played) - sound_to_playing_players(volume = 30, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_closing.ogg', TRUE)) + sound_to_playing_players(volume = 70, channel = CHANNEL_JUSTICAR_ARK, S = sound('sound/effects/clockcult_gateway_closing.ogg', TRUE)) fourth_sound_played = TRUE make_glow() glow.icon_state = "clockwork_gateway_closing" @@ -334,7 +314,6 @@ GLOB.clockwork_gateway_activated = TRUE var/turf/T = SSmapping.get_station_center() new /obj/structure/destructible/clockwork/massive/ratvar(T) - SSticker.force_ending = TRUE var/x0 = T.x var/y0 = T.y for(var/I in spiral_range_turfs(255, T, tick_checked = TRUE)) @@ -349,6 +328,17 @@ T.ratvar_act(dist) CHECK_TICK +//Converts nearby turfs into their clockwork equivalent, with ever-increasing range the closer the ark is to summoning Ratvar +/obj/structure/destructible/clockwork/massive/celestial_gateway/proc/conversion_pulse() + var/convert_dist = 1 + (round(FLOOR(progress_in_seconds, 15) * 0.067)) + for(var/t in RANGE_TURFS(convert_dist, loc)) + var/turf/T = t + if(!T) + continue + var/dist = cheap_hypotenuse(T.x, T.y, x, y) + if(dist < convert_dist) + T.ratvar_act(FALSE, TRUE, 3) + //ATTACK GHOST IGNORING PARENT RETURN VALUE /obj/structure/destructible/clockwork/massive/celestial_gateway/attack_ghost(mob/user) if(!IsAdminGhost(user)) @@ -361,9 +351,9 @@ if(alert(user, "You're REALLY SURE? This cannot be undone.", name, "Yes - Activate the Ark", "No") == "Yes - Activate the Ark") message_admins("Admin [key_name_admin(user)] started the Ark's countdown!") log_admin("Admin [key_name(user)] started the Ark's countdown on a non-clockcult mode!") - to_chat(user, "The gamemode is now being treated as clockwork cult, and the Ark is counting down from 30 \ + to_chat(user, "The gamemode is now being treated as clockwork cult, and the Ark is counting down from 5 \ minutes. You will need to create servant players yourself.") - final_countdown(35) + final_countdown(5) diff --git a/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm b/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm index 058bd9d24e..2b4b797b4d 100644 --- a/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm +++ b/code/modules/antagonists/clockcult/clock_structures/clockwork_obelisk.dm @@ -41,14 +41,19 @@ affected += try_use_power(MIN_CLOCKCULT_POWER*4) return affected -/obj/structure/destructible/clockwork/powered/clockwork_obelisk/attack_hand(mob/living/user) +/obj/structure/destructible/clockwork/powered/clockwork_obelisk/Destroy() + for(var/obj/effect/clockwork/spatial_gateway/SG in loc) + SG.ex_act(EXPLODE_DEVASTATE) + return ..() + +/obj/structure/destructible/clockwork/powered/clockwork_obelisk/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return if(!is_servant_of_ratvar(user) || !can_access_clockwork_power(src, hierophant_cost) || !anchored) to_chat(user, "You place your hand on [src], but it doesn't react.") return - var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel") + var/choice = alert(user,"You place your hand on [src]...",,"Hierophant Broadcast","Spatial Gateway","Cancel") //Will create a stable gateway instead if between two obelisks one of which is onstation and the other on reebe switch(choice) if("Hierophant Broadcast") if(active) @@ -96,7 +101,7 @@ if(!anchored) return var/obj/effect/clockwork/spatial_gateway/SG = locate(/obj/effect/clockwork/spatial_gateway) in loc - if(SG && SG.timerid) //it's a valid gateway, we're active + if(SG && (SG.timerid || SG.is_stable)) //it's a valid gateway, we're active icon_state = active_icon density = FALSE active = TRUE diff --git a/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm b/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm index c01c7f0f57..5302153b9c 100644 --- a/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm +++ b/code/modules/antagonists/clockcult/clock_structures/eminence_spire.dm @@ -11,7 +11,7 @@ var/selection_timer //Timer ID; this is canceled if the vote is canceled var/kingmaking -/obj/structure/destructible/clockwork/eminence_spire/attack_hand(mob/living/user) +/obj/structure/destructible/clockwork/eminence_spire/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -27,9 +27,6 @@ if(C.clock_team.eminence) to_chat(user, "There's already an Eminence!") return - if(!GLOB.servants_active) - to_chat(user, "The Ark isn't active!") - return if(eminence_nominee) //This could be one large proc, but is split into three for ease of reading if(eminence_nominee == user) cancelation(user) diff --git a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm index 7d8b206f41..f8a3afbf91 100644 --- a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm +++ b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm @@ -1,3 +1,5 @@ + + //Used to "declare war" against the station. The servants' equipment will be permanently supercharged, and the Ark given extra time to prepare. //This will send an announcement to the station, meaning that they will be warned very early in advance about the impending attack. /obj/structure/destructible/clockwork/heralds_beacon @@ -58,7 +60,7 @@ . += "There are [time_remaining] second[time_remaining != 1 ? "s" : ""] remaining to vote." . += "There are [voters.len]/[votes_needed] votes to activate the beacon!" -/obj/structure/destructible/clockwork/heralds_beacon/attack_hand(mob/living/user) +/obj/structure/destructible/clockwork/heralds_beacon/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -108,5 +110,4 @@ to_chat(H, "The beacon's power warps your body into a clockwork form! You are now immune to many hazards, and your body is more robust against damage!") H.set_species(/datum/species/golem/clockwork/no_scrap) var/obj/structure/destructible/clockwork/massive/celestial_gateway/G = GLOB.ark_of_the_clockwork_justiciar - G.grace_period = FALSE //no grace period if we've declared war G.recalls_remaining++ diff --git a/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm b/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm index 5fbaf9fd57..40cadb53a2 100644 --- a/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm +++ b/code/modules/antagonists/clockcult/clock_structures/mania_motor.dm @@ -30,7 +30,7 @@ toggle() return TRUE -/obj/structure/destructible/clockwork/powered/mania_motor/attack_hand(mob/living/user) +/obj/structure/destructible/clockwork/powered/mania_motor/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm b/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm new file mode 100644 index 0000000000..73488d736a --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_structures/prolonging_prism.dm @@ -0,0 +1,134 @@ +//Prolonging Prism: A prism that consumes power to delay the shuttle +/obj/structure/destructible/clockwork/powered/prolonging_prism + name = "prolonging prism" + desc = "A dark onyx prism, held in midair by spiraling tendrils of stone." + clockwork_desc = "A powerful prism that will delay the arrival of an emergency shuttle." + icon_state = "prolonging_prism_inactive" + active_icon = "prolonging_prism" + inactive_icon = "prolonging_prism_inactive" + unanchored_icon = "prolonging_prism_unwrenched" + construction_value = 20 + max_integrity = 125 + break_message = "The prism falls to the ground with a heavy thud!" + debris = list(/obj/item/clockwork/alloy_shards/small = 3, \ + /obj/item/clockwork/alloy_shards/medium = 1, \ + /obj/item/clockwork/alloy_shards/large = 1, \ + /obj/item/clockwork/component/vanguard_cogwheel/onyx_prism = 1) + var/static/power_refund = 250 + var/static/delay_cost = 2000 //Updated power values for new-newclock. Easier to activate and sustain, you are quite literally pointing the entire station towards you as opposed to blood-delay after all. + var/static/delay_cost_increase = 1000 + var/static/delay_remaining = 0 + +/obj/structure/destructible/clockwork/powered/prolonging_prism/examine(mob/user) + . = ..() + if(is_servant_of_ratvar(user) || isobserver(user)) + if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) + . += "An emergency shuttle has arrived and this prism is no longer useful; attempt to activate it to gain a partial refund of components used." + else + var/efficiency = get_efficiency_mod(TRUE) + . += "It requires at least [DisplayPower(get_delay_cost())] of power to attempt to delay the arrival of an emergency shuttle by [2 * efficiency] minutes." + . += "This cost increases by [DisplayPower(delay_cost_increase)] for every previous activation." + +/obj/structure/destructible/clockwork/powered/prolonging_prism/forced_disable(bad_effects) + if(active) + if(bad_effects) + try_use_power(MIN_CLOCKCULT_POWER*4) + visible_message("[src] emits an airy chuckling sound and falls dark!") + toggle() + return TRUE + +/obj/structure/destructible/clockwork/powered/prolonging_prism/on_attack_hand(mob/living/user) + if(user.canUseTopic(src, !issilicon(user), NO_DEXTERY) && is_servant_of_ratvar(user)) + if(SSshuttle.emergency.mode == SHUTTLE_DOCKED || SSshuttle.emergency.mode == SHUTTLE_IGNITING || SSshuttle.emergency.mode == SHUTTLE_STRANDED || SSshuttle.emergency.mode == SHUTTLE_ESCAPE) + to_chat(user, "You break [src] apart, refunding some of the power used.") + adjust_clockwork_power(power_refund) + take_damage(max_integrity) + return 0 + if(active) + return 0 + var/turf/T = get_turf(src) + if(!T || !is_station_level(T.z)) + to_chat(user, "[src] must be on the station to function!") + return 0 + if(SSshuttle.emergency.mode != SHUTTLE_CALL) + to_chat(user, "No emergency shuttles are attempting to arrive at the station!") + return 0 + if(!try_use_power(get_delay_cost())) + to_chat(user, "[src] needs more power to function!") + return 0 + delay_cost += delay_cost_increase + delay_remaining += PRISM_DELAY_DURATION + toggle(0, user) + +/obj/structure/destructible/clockwork/powered/prolonging_prism/process() + var/turf/own_turf = get_turf(src) + if(SSshuttle.emergency.mode != SHUTTLE_CALL || delay_remaining <= 0 || !own_turf || !is_station_level(own_turf.z)) + forced_disable(FALSE) + return + . = ..() + var/delay_amount = 40 + delay_remaining -= delay_amount + var/efficiency = get_efficiency_mod() + SSshuttle.emergency.setTimer(SSshuttle.emergency.timeLeft(1) + (delay_amount * efficiency)) + var/highest_y + var/highest_x + var/lowest_y + var/lowest_x + var/list/prism_turfs = list() + for(var/t in SSshuttle.emergency.ripple_area(SSshuttle.getDock("emergency_home"))) + prism_turfs[t] = TRUE + var/turf/T = t + if(!highest_y || T.y > highest_y) + highest_y = T.y + if(!highest_x || T.x > highest_x) + highest_x = T.x + if(!lowest_y || T.y < lowest_y) + lowest_y = T.y + if(!lowest_x || T.x < lowest_x) + lowest_x = T.x + var/mean_y = LERP(lowest_y, highest_y, 0.5) + var/mean_x = LERP(lowest_x, highest_x, 0.5) + if(prob(50)) + mean_y = CEILING(mean_y, 1) + else + mean_y = FLOOR(mean_y, 1) //Yes, I know round(mean_y) does the same, just left as FLOOR for consistancy sake + if(prob(50)) + mean_x = CEILING(mean_x, 1) + else + mean_x = FLOOR(mean_x, 1) + var/turf/semi_random_center_turf = locate(mean_x, mean_y, z) + for(var/t in getline(src, semi_random_center_turf)) + prism_turfs[t] = TRUE + var/placement_style = prob(50) + for(var/t in prism_turfs) + var/turf/T = t + if(placement_style) + if(ISODD(T.x + T.y)) + seven_random_hexes(T, efficiency) + else if(prob(50 * efficiency)) + new /obj/effect/temp_visual/ratvar/prolonging_prism(T) + else + if(ISEVEN(T.x + T.y)) + seven_random_hexes(T, efficiency) + else if(prob(50 * efficiency)) + new /obj/effect/temp_visual/ratvar/prolonging_prism(T) + CHECK_TICK //we may be going over a hell of a lot of turfs + +/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/get_delay_cost() + return FLOOR(delay_cost, MIN_CLOCKCULT_POWER) + +/obj/structure/destructible/clockwork/powered/prolonging_prism/proc/seven_random_hexes(turf/T, efficiency) + var/static/list/hex_states = list("prismhex1", "prismhex2", "prismhex3", "prismhex4", "prismhex5", "prismhex6", "prismhex7") + var/mutable_appearance/hex_combo + for(var/n in hex_states) //BUILD ME A HEXAGON + if(prob(50 * efficiency)) + if(!hex_combo) + hex_combo = mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER) + else + hex_combo.add_overlay(mutable_appearance('icons/effects/64x64.dmi', n, RIPPLE_LAYER)) + if(hex_combo) //YOU BUILT A HEXAGON + hex_combo.pixel_x = -16 + hex_combo.pixel_y = -16 + hex_combo.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + hex_combo.plane = GAME_PLANE + new /obj/effect/temp_visual/ratvar/prolonging_prism(T, hex_combo) diff --git a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm index c17885315f..73ae89a19b 100644 --- a/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm +++ b/code/modules/antagonists/clockcult/clock_structures/ratvar_the_clockwork_justicar.dm @@ -101,8 +101,8 @@ return clashing = TRUE GLOB.cult_narsie.clashing = TRUE - to_chat(world, "\"YOU.\"") - to_chat(world, "\"Ratvar?!\"") + to_chat(world, "\"[pick("YOU.", "BLOOD GOD!!", "FACE ME, COWARD!")]\"") + to_chat(world, "\"[pick("Ratvar?! How?!", "YOU. BANISHED ONCE. KILLED NOW.", "SCRAP HEAP!!")]\"") clash_of_the_titans(GLOB.cult_narsie) // >:( return TRUE @@ -137,15 +137,16 @@ base_victory_chance *= 2 //The clash has a higher chance of resolving each time both gods attack one another switch(winner) if("Ratvar") - send_to_playing_players("\"[pick("DIE.", "ROT.")]\"\n\ + send_to_playing_players("\"[pick("DIE.", "ROT FOR CENTURIES, AS I HAVE!.","PERISH, HEATHEN.", "DIE, MONSTER, YOU DON'T BELONG IN THIS WORLD.")]\"\n\ \"[pick("Nooooo...", "Not die. To y-", "Die. Ratv-", "Sas tyen re-")]\"") //Nar'Sie get out sound_to_playing_players('sound/magic/clockwork/anima_fragment_attack.ogg') - sound_to_playing_players('sound/magic/demon_dies.ogg', 50) + sound_to_playing_players('sound/magic/abomscream.ogg', 50) clashing = FALSE qdel(narsie) if("Nar'Sie") - send_to_playing_players("\"[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]\"") //Broken English - sound_to_playing_players('sound/magic/demon_attack1.ogg') - sound_to_playing_players('sound/magic/clockwork/anima_fragment_death.ogg', 62) + send_to_playing_players("\"[pick("Ha.", "Ra'sha fonn dest.", "You fool. To come here.")]\"\n\ + \"[pick("NO, YOUR SHADOWS SHALL NO-", "ZNL GUR FGERNZF BS GVZR PNEEL ZL RKVFG-", "MY LIGHT CANNO-")]\"") + sound_to_playing_players('sound/magic/demon_attack1.ogg', 50) + sound_to_playing_players('sound/machines/clockcult/ratvar_scream.ogg', 80) narsie.clashing = FALSE qdel(src) diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm index 12e4b62a65..55347685f4 100644 --- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm +++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/lever.dm @@ -6,7 +6,7 @@ max_integrity = 75 icon_state = "lever" -/obj/structure/destructible/clockwork/trap/trigger/lever/attack_hand(mob/living/user) +/obj/structure/destructible/clockwork/trap/trigger/lever/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm index f5ed91ac15..7a528786e2 100644 --- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm +++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/repeater.dm @@ -6,7 +6,7 @@ max_integrity = 15 //Fragile! icon_state = "repeater" -/obj/structure/destructible/clockwork/trap/trigger/repeater/attack_hand(mob/living/user) +/obj/structure/destructible/clockwork/trap/trigger/repeater/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm index 52ead9a1e7..68a890028e 100644 --- a/code/modules/antagonists/cult/blood_magic.dm +++ b/code/modules/antagonists/cult/blood_magic.dm @@ -801,7 +801,7 @@ var/turf/T = get_turf(user) qdel(src) var/datum/action/innate/cult/spear/S = new(user) - var/obj/item/twohanded/cult_spear/rite = new(T) + var/obj/item/cult_spear/rite = new(T) S.Grant(user, rite) rite.spear_act = S if(user.put_in_hands(rite)) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 8f0f9a658c..35151953a0 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -34,6 +34,8 @@ w_class = WEIGHT_CLASS_SMALL force = 15 throwforce = 25 + wound_bonus = -30 + bare_wound_bonus = 30 armour_penetration = 35 actions_types = list(/datum/action/item_action/cult_dagger) @@ -51,10 +53,12 @@ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' flags_1 = CONDUCT_1 - sharpness = IS_SHARP + sharpness = SHARP_EDGED w_class = WEIGHT_CLASS_BULKY - force = 30 + force = 30 // whoever balanced this got beat in the head by a bible too many times good lord throwforce = 10 + wound_bonus = -80 + bare_wound_bonus = 30 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended") @@ -100,7 +104,7 @@ user.apply_damage(30, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) user.dropItemToGround(src) -/obj/item/twohanded/required/cult_bastard +/obj/item/cult_bastard name = "bloody bastard sword" desc = "An enormous sword used by Nar'Sien cultists to rapidly harvest the souls of non-believers." w_class = WEIGHT_CLASS_HUGE @@ -110,7 +114,7 @@ armour_penetration = 45 throw_speed = 1 throw_range = 3 - sharpness = IS_SHARP + sharpness = SHARP_EDGED light_color = "#ff0000" attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved") icon_state = "cultbastard" @@ -127,31 +131,35 @@ var/spin_cooldown = 250 var/dash_toggled = TRUE -/obj/item/twohanded/required/cult_bastard/Initialize() +/obj/item/cult_bastard/Initialize() . = ..() set_light(4) jaunt = new(src) linked_action = new(src) - AddComponent(/datum/component/butchering, 50, 80) -/obj/item/twohanded/required/cult_bastard/examine(mob/user) +/obj/item/cult_bastard/ComponentInitialize() + . = ..() + AddComponent(/datum/component/butchering, 50, 80) + AddComponent(/datum/component/two_handed, require_twohands=TRUE) + +/obj/item/cult_bastard/examine(mob/user) . = ..() if(contents.len) . += "
    There are [contents.len] souls trapped within the sword's core." else . += "
    The sword appears to be quite lifeless." -/obj/item/twohanded/required/cult_bastard/can_be_pulled(user) +/obj/item/cult_bastard/can_be_pulled(user) return FALSE -/obj/item/twohanded/required/cult_bastard/attack_self(mob/user) +/obj/item/cult_bastard/attack_self(mob/user) dash_toggled = !dash_toggled if(dash_toggled) to_chat(loc, "You raise [src] and prepare to jaunt with it.") else to_chat(loc, "You lower [src] and prepare to swing it normally.") -/obj/item/twohanded/required/cult_bastard/pickup(mob/living/user) +/obj/item/cult_bastard/pickup(mob/living/user) . = ..() if(!iscultist(user)) if(!is_servant_of_ratvar(user)) @@ -171,13 +179,13 @@ linked_action.Grant(user, src) user.update_icons() -/obj/item/twohanded/required/cult_bastard/dropped(mob/user) +/obj/item/cult_bastard/dropped(mob/user) . = ..() linked_action.Remove(user) jaunt.Remove(user) user.update_icons() -/obj/item/twohanded/required/cult_bastard/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +/obj/item/cult_bastard/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(spinning && is_energy_reflectable_projectile(object) && (attack_type & ATTACK_TYPE_PROJECTILE)) playsound(src, pick('sound/weapons/effects/ric1.ogg', 'sound/weapons/effects/ric2.ogg', 'sound/weapons/effects/ric3.ogg', 'sound/weapons/effects/ric4.ogg', 'sound/weapons/effects/ric5.ogg'), 100, 1) return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL | BLOCK_REDIRECTED | BLOCK_SHOULD_REDIRECT @@ -192,7 +200,7 @@ return BLOCK_SUCCESS | BLOCK_PHYSICAL_EXTERNAL return BLOCK_NONE -/obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) +/obj/item/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) . = ..() if(dash_toggled && !proximity) jaunt.Teleport(user, target) @@ -235,7 +243,7 @@ button_icon_state = "sintouch" var/cooldown = 0 var/mob/living/carbon/human/holder - var/obj/item/twohanded/required/cult_bastard/sword + var/obj/item/cult_bastard/sword /datum/action/innate/cult/spin2win/Grant(mob/user, obj/bastard) . = ..() @@ -250,7 +258,7 @@ /datum/action/innate/cult/spin2win/Activate() cooldown = world.time + sword.spin_cooldown - holder.changeNext_move(50) + holder.DelayNextAction(50) holder.apply_status_effect(/datum/status_effect/sword_spin) sword.spinning = TRUE sword.block_chance = 100 @@ -687,7 +695,7 @@ to_chat(user, "\The [src] can only transport items!") -/obj/item/twohanded/cult_spear +/obj/item/cult_spear name = "blood halberd" desc = "A sickening spear composed entirely of crystallized blood." icon_state = "bloodspear0" @@ -695,30 +703,44 @@ righthand_file = 'icons/mob/inhands/weapons/polearms_righthand.dmi' slot_flags = 0 force = 17 - force_unwielded = 17 - force_wielded = 24 throwforce = 40 throw_speed = 2 armour_penetration = 30 block_chance = 30 attack_verb = list("attacked", "impaled", "stabbed", "torn", "gored") - sharpness = IS_SHARP + sharpness = SHARP_EDGED hitsound = 'sound/weapons/bladeslice.ogg' var/datum/action/innate/cult/spear/spear_act + var/wielded = FALSE // track wielded status on item -/obj/item/twohanded/cult_spear/Initialize() + +/obj/item/cult_spear/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) + +/obj/item/cult_spear/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 100, 90) + AddComponent(/datum/component/two_handed, force_unwielded=17, force_wielded=24, icon_wielded="bloodspear1") -/obj/item/twohanded/cult_spear/Destroy() +/// triggered on wield of two handed item +/obj/item/cult_spear/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/cult_spear/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/cult_spear/update_icon_state() + icon_state = "bloodspear0" + +/obj/item/cult_spear/Destroy() if(spear_act) qdel(spear_act) ..() -/obj/item/twohanded/cult_spear/update_icon_state() - icon_state = "bloodspear[wielded]" - -/obj/item/twohanded/cult_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) +/obj/item/cult_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) var/turf/T = get_turf(hit_atom) if(isliving(hit_atom)) var/mob/living/L = hit_atom @@ -741,7 +763,7 @@ else ..() -/obj/item/twohanded/cult_spear/proc/break_spear(turf/T) +/obj/item/cult_spear/proc/break_spear(turf/T) if(src) if(!T) T = get_turf(src) @@ -752,7 +774,7 @@ playsound(T, 'sound/effects/glassbr3.ogg', 100) qdel(src) -/obj/item/twohanded/cult_spear/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) +/obj/item/cult_spear/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) if(wielded) final_block_chance *= 2 if(prob(final_block_chance)) @@ -771,7 +793,7 @@ desc = "Call the blood spear back to your hand!" background_icon_state = "bg_demon" button_icon_state = "bloodspear" - var/obj/item/twohanded/cult_spear/spear + var/obj/item/cult_spear/spear var/cooldown = 0 /datum/action/innate/cult/spear/Grant(mob/user, obj/blood_spear) diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm index 6f340b9271..5803941f36 100644 --- a/code/modules/antagonists/cult/cult_structures.dm +++ b/code/modules/antagonists/cult/cult_structures.dm @@ -44,15 +44,16 @@ /obj/structure/destructible/cult/attack_animal(mob/living/simple_animal/M) if(istype(M, /mob/living/simple_animal/hostile/construct/builder)) if(obj_integrity < max_integrity) - M.changeNext_move(CLICK_CD_MELEE) + M.DelayNextAction(CLICK_CD_MELEE) obj_integrity = min(max_integrity, obj_integrity + 5) Beam(M, icon_state="sendbeam", time=4) M.visible_message("[M] repairs \the [src].", \ "You repair [src], leaving [p_they()] at [round(obj_integrity * 100 / max_integrity)]% stability.") + return TRUE else to_chat(M, "You cannot repair [src], as [p_theyre()] undamaged!") else - ..() + return ..() /obj/structure/destructible/cult/attackby(obj/I, mob/user, params) if(istype(I, /obj/item/melee/cultblade/dagger) && iscultist(user)) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index b0538d6521..3ea160c5cc 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -67,7 +67,7 @@ Runes can either be invoked by one's self or with many different cultists. Each to_chat(user, "You disrupt the magic of [src] with [I].") qdel(src) -/obj/effect/rune/attack_hand(mob/living/user) +/obj/effect/rune/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm index c12259778e..3b6dc68986 100644 --- a/code/modules/antagonists/devil/devil.dm +++ b/code/modules/antagonists/devil/devil.dm @@ -92,6 +92,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", //Don't delete upon mind destruction, otherwise soul re-selling will break. delete_on_mind_deletion = FALSE threat = 5 + show_to_ghosts = TRUE var/obligation var/ban var/bane diff --git a/code/modules/antagonists/devil/imp/imp.dm b/code/modules/antagonists/devil/imp/imp.dm index 7a6850bfa1..f7f55456f7 100644 --- a/code/modules/antagonists/devil/imp/imp.dm +++ b/code/modules/antagonists/devil/imp/imp.dm @@ -48,8 +48,9 @@ ..() boost = world.time + 30 -/mob/living/simple_animal/imp/Life() - ..() +/mob/living/simple_animal/imp/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(boost[H ? H.name : "Host"] cannot be infected.
    ") + confirm_initial_infection(A) else ..() +/mob/camera/disease/proc/confirm_initial_infection(mob/living/carbon/human/H) + set waitfor = FALSE + if(alert(src, "Select [H.name] as your initial host?", "Select Host", "Yes", "No") != "Yes") + return + if(!freemove) + return + if(QDELETED(H) || !force_infect(H)) + to_chat(src, "[H ? H.name : "Host"] cannot be infected.") + /mob/camera/disease/proc/adapt_cooldown() to_chat(src, "You have altered your genetic structure. You will be unable to adapt again for [DisplayTimeText(adaptation_cooldown)].") next_adaptation_time = world.time + adaptation_cooldown diff --git a/code/modules/antagonists/eldritch_cult/eldritch_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm new file mode 100644 index 0000000000..367710b110 --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_antag.dm @@ -0,0 +1,229 @@ +/datum/antagonist/heretic + name = "Heretic" + roundend_category = "Heretics" + antagpanel_category = "Heretic" + antag_moodlet = /datum/mood_event/heretics + job_rank = ROLE_HERETIC + antag_hud_type = ANTAG_HUD_HERETIC + antag_hud_name = "heretic" + var/give_equipment = TRUE + var/list/researched_knowledge = list() + var/total_sacrifices = 0 + var/ascended = FALSE + +/datum/antagonist/heretic/admin_add(datum/mind/new_owner,mob/admin) + give_equipment = TRUE + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].") + log_admin("[key_name(admin)] has heresized [key_name(new_owner)].") + +/datum/antagonist/heretic/greet() + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change + to_chat(owner, "You are the Heretic!
    \ + The old ones gave you these tasks to fulfill:") + owner.announce_objectives() + to_chat(owner, "The book whispers, the forbidden knowledge walks once again!
    \ + Your book allows you to research abilities, but be careful, you cannot undo what has been done.
    \ + You gain charges by either collecting influences or sacrificing people tracked by the living heart
    \ + You can find a basic guide at : https://tgstation13.org/wiki/Heresy_101
    ") + +/datum/antagonist/heretic/on_gain() + var/mob/living/current = owner.current + if(ishuman(current)) + forge_primary_objectives() + gain_knowledge(/datum/eldritch_knowledge/spell/basic) + gain_knowledge(/datum/eldritch_knowledge/living_heart) + gain_knowledge(/datum/eldritch_knowledge/codex_cicatrix) + gain_knowledge(/datum/eldritch_knowledge/eldritch_blade) + current.log_message("has been converted to the cult of the forgotten ones!", LOG_ATTACK, color="#960000") + GLOB.reality_smash_track.AddMind(owner) + START_PROCESSING(SSprocessing,src) + if(give_equipment) + equip_cultist() + owner.teach_crafting_recipe(/datum/crafting_recipe/heretic/codex) + return ..() + +/datum/antagonist/heretic/on_removal() + + for(var/X in researched_knowledge) + var/datum/eldritch_knowledge/EK = researched_knowledge[X] + EK.on_lose(owner.current) + + if(!silent) + to_chat(owner.current, "Your mind begins to flare as the otherwordly knowledge escapes your grasp!") + owner.current.log_message("has renounced the cult of the old ones!", LOG_ATTACK, color="#960000") + GLOB.reality_smash_track.RemoveMind(owner) + STOP_PROCESSING(SSprocessing,src) + + return ..() + + +/datum/antagonist/heretic/proc/equip_cultist() + var/mob/living/carbon/H = owner.current + if(!istype(H)) + return + . += ecult_give_item(/obj/item/forbidden_book, H) + . += ecult_give_item(/obj/item/living_heart, H) + +/datum/antagonist/heretic/proc/ecult_give_item(obj/item/item_path, mob/living/carbon/human/H) + var/list/slots = list( + "backpack" = SLOT_IN_BACKPACK, + "left pocket" = SLOT_L_STORE, + "right pocket" = SLOT_R_STORE + ) + + var/T = new item_path(H) + var/item_name = initial(item_path.name) + var/where = H.equip_in_one_of_slots(T, slots) + if(!where) + to_chat(H, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).") + return FALSE + else + to_chat(H, "You have a [item_name] in your [where].") + if(where == "backpack") + SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H) + return TRUE + +/datum/antagonist/heretic/process() + + for(var/X in researched_knowledge) + var/datum/eldritch_knowledge/EK = researched_knowledge[X] + EK.on_life(owner.current) + +/datum/antagonist/heretic/proc/forge_primary_objectives() + var/list/assasination = list() + var/list/protection = list() + for(var/i in 1 to 2) + var/pck = pick("assasinate","protect") + switch(pck) + if("assasinate") + var/datum/objective/assassinate/A = new + A.owner = owner + var/list/owners = A.get_owners() + A.find_target(owners,protection) + assasination += A.target + objectives += A + if("protect") + var/datum/objective/protect/P = new + P.owner = owner + var/list/owners = P.get_owners() + P.find_target(owners,assasination) + protection += P.target + objectives += P + + + var/datum/objective/sacrifice_ecult/SE = new + SE.owner = owner + SE.update_explanation_text() + objectives += SE + + var/datum/objective/escape/escape_objective = new + escape_objective.owner = owner + objectives += escape_objective + +/datum/antagonist/heretic/apply_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current = owner.current + if(mob_override) + current = mob_override + add_antag_hud(antag_hud_type, antag_hud_name, current) + handle_clown_mutation(current, mob_override ? null : "Knowledge described in the book allowed you to overcome your clownish nature, allowing you to use complex items effectively.") + current.faction |= "heretics" + +/datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override) + . = ..() + var/mob/living/current = owner.current + if(mob_override) + current = mob_override + remove_antag_hud(antag_hud_type, current) + handle_clown_mutation(current, removing = FALSE) + current.faction -= "heretics" + +/datum/antagonist/heretic/get_admin_commands() + . = ..() + .["Equip"] = CALLBACK(src,.proc/equip_cultist) + +/datum/antagonist/heretic/roundend_report() + var/list/parts = list() + + var/cultiewin = TRUE + + parts += printplayer(owner) + parts += "Sacrifices Made: [total_sacrifices]" + + if(length(objectives)) + var/count = 1 + for(var/o in objectives) + var/datum/objective/objective = o + if(objective.check_completion()) + parts += "Objective #[count]: [objective.explanation_text] Success!
    " + else + parts += "Objective #[count]: [objective.explanation_text] Fail." + cultiewin = FALSE + count++ + if(ascended) + parts += "HERETIC HAS ASCENDED!" + else + if(cultiewin) + parts += "The heretic was successful!" + else + parts += "The heretic has failed." + + parts += "Knowledge Researched: " + + var/list/knowledge_message = list() + var/list/knowledge = get_all_knowledge() + for(var/X in knowledge) + var/datum/eldritch_knowledge/EK = knowledge[X] + knowledge_message += "[EK.name]" + parts += knowledge_message.Join(", ") + + return parts.Join("
    ") +//////////////// +// Knowledge // +//////////////// + +/datum/antagonist/heretic/proc/gain_knowledge(datum/eldritch_knowledge/EK) + if(get_knowledge(EK)) + return FALSE + var/datum/eldritch_knowledge/initialized_knowledge = new EK + researched_knowledge[initialized_knowledge.type] = initialized_knowledge + initialized_knowledge.on_gain(owner.current) + return TRUE + +/datum/antagonist/heretic/proc/get_researchable_knowledge() + var/list/researchable_knowledge = list() + var/list/banned_knowledge = list() + for(var/X in researched_knowledge) + var/datum/eldritch_knowledge/EK = researched_knowledge[X] + researchable_knowledge |= EK.next_knowledge + banned_knowledge |= EK.banned_knowledge + banned_knowledge |= EK.type + researchable_knowledge -= banned_knowledge + return researchable_knowledge + +/datum/antagonist/heretic/proc/get_knowledge(wanted) + return researched_knowledge[wanted] + +/datum/antagonist/heretic/proc/get_all_knowledge() + return researched_knowledge + +//////////////// +// Objectives // +//////////////// + +/datum/objective/sacrifice_ecult + name = "sacrifice" + +/datum/objective/sacrifice_ecult/update_explanation_text() + . = ..() + target_amount = rand(2,4) + explanation_text = "Sacrifice at least [target_amount] people." + +/datum/objective/sacrifice_ecult/check_completion() + if(!owner) + return FALSE + var/datum/antagonist/heretic/cultie = owner.has_antag_datum(/datum/antagonist/heretic) + if(!cultie) + return FALSE + return cultie.total_sacrifices >= target_amount diff --git a/code/modules/antagonists/eldritch_cult/eldritch_book.dm b/code/modules/antagonists/eldritch_cult/eldritch_book.dm new file mode 100644 index 0000000000..839150d37d --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_book.dm @@ -0,0 +1,145 @@ +/obj/item/forbidden_book + name = "Codex Cicatrix" + desc = "Book describing the secrets of the veil." + icon = 'icons/obj/eldritch.dmi' + icon_state = "book" + item_state = "book" + w_class = WEIGHT_CLASS_SMALL + ///Last person that touched this + var/mob/living/last_user + ///how many charges do we have? + var/charge = 0 + ///Where we cannot create the rune? + var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava)) + +/obj/item/forbidden_book/Destroy() + last_user = null + . = ..() + + +/obj/item/forbidden_book/examine(mob/user) + . = ..() + if(!IS_HERETIC(user)) + return + . += "The Tome holds [charge] charges." + . += "Use it on the floor to create a transmutation rune, used to perform rituals." + . += "Hit an influence in the black part with it to gain a charge." + . += "Hit a transmutation rune to destroy it." + +/obj/item/forbidden_book/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(!proximity_flag || !IS_HERETIC(user)) + return + if(istype(target,/obj/effect/eldritch)) + remove_rune(target,user) + if(istype(target,/obj/effect/reality_smash)) + get_power_from_influence(target,user) + if(istype(target,/turf/open)) + draw_rune(target,user) + +///Gives you a charge and destroys a corresponding influence +/obj/item/forbidden_book/proc/get_power_from_influence(atom/target, mob/user) + var/obj/effect/reality_smash/RS = target + to_chat(target, "You start drawing power from influence...") + if(do_after(user,10 SECONDS,TRUE,RS)) + qdel(RS) + charge += 1 + +///Draws a rune on a selected turf +/obj/item/forbidden_book/proc/draw_rune(atom/target,mob/user) + + for(var/turf/T in range(1,target)) + if(is_type_in_typecache(T, blacklisted_turfs)) + to_chat(target, "The terrain doesn't support runes!") + return + var/A = get_turf(target) + to_chat(user, "You start drawing a rune...") + + if(do_after(user,30 SECONDS,FALSE, user)) + + new /obj/effect/eldritch/big(A) + +///Removes runes from the selected turf +/obj/item/forbidden_book/proc/remove_rune(atom/target,mob/user) + + to_chat(user, "You start removing a rune...") + if(do_after(user,2 SECONDS,FALSE, user)) + qdel(target) + +/obj/item/forbidden_book/ui_interact(mob/user, datum/tgui/ui = null) + if(!IS_HERETIC(user)) + return FALSE + last_user = user + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + icon_state = "book_open" + flick("book_opening", src) + ui = new(user, src, "ForbiddenLore", name) + ui.open() + +/obj/item/forbidden_book/ui_data(mob/user) + var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic) + var/list/to_know = list() + for(var/Y in cultie.get_researchable_knowledge()) + to_know += new Y + var/list/known = cultie.get_all_knowledge() + var/list/data = list() + var/list/lore = list() + + data["charges"] = charge + + for(var/X in to_know) + lore = list() + var/datum/eldritch_knowledge/EK = X + lore["type"] = EK.type + lore["name"] = EK.name + lore["cost"] = EK.cost + lore["disabled"] = EK.cost <= charge ? FALSE : TRUE + lore["path"] = EK.route + lore["state"] = "Research" + lore["flavour"] = EK.gain_text + lore["desc"] = EK.desc + data["to_know"] += list(lore) + + for(var/X in known) + lore = list() + var/datum/eldritch_knowledge/EK = known[X] + lore["name"] = EK.name + lore["cost"] = EK.cost + lore["disabled"] = TRUE + lore["path"] = EK.route + lore["state"] = "Researched" + lore["flavour"] = EK.gain_text + lore["desc"] = EK.desc + data["to_know"] += list(lore) + + if(!length(data["to_know"])) + data["to_know"] = null + + return data + +/obj/item/forbidden_book/ui_act(action, params) + . = ..() + if(.) + return + switch(action) + if("research") + var/datum/antagonist/heretic/cultie = last_user.mind.has_antag_datum(/datum/antagonist/heretic) + var/ekname = params["name"] + for(var/X in cultie.get_researchable_knowledge()) + var/datum/eldritch_knowledge/EK = X + if(initial(EK.name) != ekname) + continue + if(cultie.gain_knowledge(EK)) + charge -= text2num(params["cost"]) + return TRUE + + update_icon() // Not applicable to all objects. + +/obj/item/forbidden_book/ui_close(mob/user) + flick("book_closing",src) + icon_state = initial(icon_state) + return ..() + +/obj/item/forbidden_book/debug + charge = 100 diff --git a/code/modules/antagonists/eldritch_cult/eldritch_effects.dm b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm new file mode 100644 index 0000000000..899e588bda --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_effects.dm @@ -0,0 +1,289 @@ +/obj/effect/eldritch + name = "Generic rune" + desc = "Weird combination of shapes and symbols etched into the floor itself. The indentation is filled with thick black tar-like fluid." + anchored = TRUE + icon_state = "" + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF + layer = SIGIL_LAYER + ///Used mainly for summoning ritual to prevent spamming the rune to create millions of monsters. + var/is_in_use = FALSE + +/obj/effect/eldritch/attack_hand(mob/living/user) + . = ..() + if(.) + return + try_activate(user) + +/obj/effect/eldritch/proc/try_activate(mob/living/user) + if(!IS_HERETIC(user)) + return + if(!is_in_use) + INVOKE_ASYNC(src, .proc/activate , user) + +/obj/effect/eldritch/attacked_by(obj/item/I, mob/living/user) + . = ..() + if(istype(I,/obj/item/nullrod)) + qdel(src) + +/obj/effect/eldritch/proc/activate(mob/living/user) + is_in_use = TRUE + // Have fun trying to read this proc. + var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic) + var/list/knowledge = cultie.get_all_knowledge() + var/list/atoms_in_range = list() + + for(var/A in range(1, src)) + var/atom/atom_in_range = A + if(istype(atom_in_range,/area)) + continue + if(istype(atom_in_range,/turf)) // we dont want turfs + continue + if(istype(atom_in_range,/mob/living)) + var/mob/living/living_in_range = atom_in_range + if(living_in_range.stat != DEAD || living_in_range == user) // we only accept corpses, no living beings allowed. + continue + atoms_in_range += atom_in_range + for(var/X in knowledge) + var/datum/eldritch_knowledge/current_eldritch_knowledge = knowledge[X] + + //has to be done so that we can freely edit the local_required_atoms without fucking up the eldritch knowledge + var/list/local_required_atoms = list() + + if(!current_eldritch_knowledge.required_atoms || current_eldritch_knowledge.required_atoms.len == 0) + continue + + local_required_atoms += current_eldritch_knowledge.required_atoms + + var/list/selected_atoms = list() + + if(!current_eldritch_knowledge.recipe_snowflake_check(atoms_in_range,drop_location(),selected_atoms)) + continue + + for(var/LR in local_required_atoms) + var/list/local_required_atom_list = LR + + for(var/LAIR in atoms_in_range) + var/atom/local_atom_in_range = LAIR + if(is_type_in_list(local_atom_in_range,local_required_atom_list)) + selected_atoms |= local_atom_in_range + local_required_atoms -= list(local_required_atom_list) + + if(length(local_required_atoms) > 0) + continue + + flick("[icon_state]_active",src) + playsound(user, 'sound/magic/castsummon.ogg', 75, TRUE) + //we are doing this since some on_finished_recipe subtract the atoms from selected_atoms making them invisible permanently. + var/list/atoms_to_disappear = selected_atoms.Copy() + for(var/to_disappear in atoms_to_disappear) + var/atom/atom_to_disappear = to_disappear + //temporary so we dont have to deal with the bs of someone picking those up when they may be deleted + atom_to_disappear.invisibility = INVISIBILITY_ABSTRACT + if(current_eldritch_knowledge.on_finished_recipe(user,selected_atoms,loc)) + current_eldritch_knowledge.cleanup_atoms(selected_atoms) + is_in_use = FALSE + + for(var/to_appear in atoms_to_disappear) + var/atom/atom_to_appear = to_appear + //we need to reappear the item just in case the ritual didnt consume everything... or something. + atom_to_appear.invisibility = initial(atom_to_appear.invisibility) + + return + is_in_use = FALSE + to_chat(user,"Your ritual failed! You used either wrong components or are missing something important!") + +/obj/effect/eldritch/big + name = "transmutation circle" + icon = 'icons/effects/96x96.dmi' + icon_state = "eldritch_rune1" + pixel_x = -32 //So the big ol' 96x96 sprite shows up right + pixel_y = -32 + +/** + * #Reality smash tracker + * + * Stupid fucking list holder, DONT create new ones, it will break the game, this is automnatically created whenever eldritch cultists are created. + * + * Tracks relevant data, generates relevant data, useful tool + */ +/datum/reality_smash_tracker + ///list of tracked reality smashes + var/list/smashes = list() + ///List of mobs with ability to see the smashes + var/list/targets = list() + +/datum/reality_smash_tracker/Destroy(force, ...) + if(GLOB.reality_smash_track == src) + stack_trace("/datum/reality_smash_tracker was deleted. Heretics may no longer access any influences. Fix it or call coder support") + QDEL_LIST(smashes) + targets.Cut() + return ..() + +/** + * Automatically fixes the target and smash network + * + * Fixes any bugs that are caused by late Generate() or exchanging clients + */ +/datum/reality_smash_tracker/proc/ReworkNetwork() + listclearnulls(smashes) + for(var/mind in targets) + if(isnull(mind)) + stack_trace("A null somehow landed in a list of minds") + continue + for(var/X in smashes) + var/obj/effect/reality_smash/reality_smash = X + reality_smash.AddMind(mind) + +/** + * Generates a set amount of reality smashes based on the N value + * + * Automatically creates more reality smashes + */ +/datum/reality_smash_tracker/proc/_Generate() + var/targ_len = length(targets) + var/smash_len = length(smashes) + var/number = targ_len * 6 - smash_len + + for(var/i in 0 to number) + + var/turf/chosen_location = get_safe_random_station_turf() + //we also dont want them close to each other, at least 1 tile of seperation + var/obj/effect/reality_smash/what_if_i_have_one = locate() in range(1, chosen_location) + var/obj/effect/broken_illusion/what_if_i_had_one_but_got_used = locate() in range(1, chosen_location) + if(what_if_i_have_one || what_if_i_had_one_but_got_used) //we dont want to spawn + continue + var/obj/effect/reality_smash/RS = new/obj/effect/reality_smash(chosen_location) + smashes += RS + ReworkNetwork() + + +/** + * Adds a mind to the list of people that can see the reality smashes + * + * Use this whenever you want to add someone to the list + */ +/datum/reality_smash_tracker/proc/AddMind(var/datum/mind/M) + RegisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN,.proc/ReworkNetwork) + targets |= M + _Generate() + for(var/X in smashes) + var/obj/effect/reality_smash/reality_smash = X + reality_smash.AddMind(M) + + +/** + * Removes a mind from the list of people that can see the reality smashes + * + * Use this whenever you want to remove someone from the list + */ +/datum/reality_smash_tracker/proc/RemoveMind(var/datum/mind/M) + UnregisterSignal(M.current,COMSIG_MOB_CLIENT_LOGIN) + targets -= M + for(var/obj/effect/reality_smash/RS in smashes) + RS.RemoveMind(M) + +/obj/effect/broken_illusion + name = "pierced reality" + icon = 'icons/effects/eldritch.dmi' + icon_state = "pierced_illusion" + anchored = TRUE + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF + +/obj/effect/broken_illusion/attack_hand(mob/living/user) + if(!ishuman(user)) + return ..() + var/mob/living/carbon/human/human_user = user + if(IS_HERETIC(human_user)) + to_chat(human_user,"You know better than to tempt forces out of your control.") + else + var/obj/item/bodypart/arm = human_user.get_active_hand() + if(prob(25)) + to_chat(human_user,"An otherwordly presence tears your arm apart into atoms as you try to touch the hole in the very fabric of reality!") + arm.dismember() + qdel(arm) + else + to_chat(human_user,"You pull your hand away from the hole as eldritch energy flails out, trying to latch onto existence itself!") + +/obj/effect/broken_illusion/attack_tk(mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/human_user = user + if(IS_HERETIC(human_user)) + to_chat(human_user,"You know better than to tempt forces out of your control.") + else + //a very elaborate way to suicide + to_chat(human_user,"Eldritch energy lashes out, piercing your fragile mind, tearing it to pieces!") + human_user.ghostize() + var/obj/item/bodypart/head/head = locate() in human_user.bodyparts + if(head) + head.dismember() + qdel(head) + else + human_user.gib() + + var/datum/effect_system/reagents_explosion/explosion = new() + explosion.set_up(1, get_turf(human_user), 1, 0) + explosion.start() + +/obj/effect/broken_illusion/examine(mob/user) + if(!IS_HERETIC(user) && ishuman(user)) + var/mob/living/carbon/human/human_user = user + to_chat(human_user,"Your brain hurts when you look at this!") + human_user.adjustOrganLoss(ORGAN_SLOT_BRAIN,30) + . = ..() + +/obj/effect/reality_smash + name = "/improper reality smash" + icon = 'icons/effects/eldritch.dmi' + anchored = TRUE + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF + ///We cannot use icon_state since this is invisible, functions the same way but with custom behaviour. + var/image_state = "reality_smash" + ///Who can see us? + var/list/minds = list() + ///Tracked image + var/image/img + +/obj/effect/reality_smash/Initialize() + . = ..() + img = image(icon, src, image_state, OBJ_LAYER) + generate_name() + +/obj/effect/reality_smash/Destroy() + on_destroy() + return ..() + +///Custom effect that happens on destruction +/obj/effect/reality_smash/proc/on_destroy() + for(var/cm in minds) + var/datum/mind/cultie = cm + if(cultie.current?.client) + cultie.current.client.images -= img + //clear the list + minds -= cultie + GLOB.reality_smash_track.smashes -= src + img = null + new /obj/effect/broken_illusion(drop_location()) + +///Makes the mind able to see this effect +/obj/effect/reality_smash/proc/AddMind(var/datum/mind/cultie) + minds |= cultie + if(cultie.current.client) + cultie.current.client.images |= img + + + +///Makes the mind not able to see this effect +/obj/effect/reality_smash/proc/RemoveMind(var/datum/mind/cultie) + minds -= cultie + if(cultie.current.client) + cultie.current.client.images -= img + + + +///Generates random name +/obj/effect/reality_smash/proc/generate_name() + var/static/list/prefix = list("Omniscient","Thundering","Enlightening","Intrusive","Rejectful","Atomized","Subtle","Rising","Lowering","Fleeting","Towering","Blissful","Arrogant","Threatening","Peaceful","Aggressive") + var/static/list/postfix = list("Flaw","Presence","Crack","Heat","Cold","Memory","Reminder","Breeze","Grasp","Sight","Whisper","Flow","Touch","Veil","Thought","Imperfection","Blemish","Blush") + + name = pick(prefix) + " " + pick(postfix) diff --git a/code/modules/antagonists/eldritch_cult/eldritch_items.dm b/code/modules/antagonists/eldritch_cult/eldritch_items.dm new file mode 100644 index 0000000000..4dab6d789d --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_items.dm @@ -0,0 +1,142 @@ +/obj/item/living_heart + name = "living heart" + desc = "Link to the worlds beyond." + icon = 'icons/obj/eldritch.dmi' + icon_state = "living_heart" + w_class = WEIGHT_CLASS_SMALL + ///Target + var/mob/living/carbon/human/target + +/obj/item/living_heart/attack_self(mob/user) + . = ..() + if(!IS_HERETIC(user)) + return + if(!target) + to_chat(user,"No target could be found. Put the living heart on the rune and use the rune to recieve a target.") + return + var/dist = get_dist(user.loc,target.loc) + var/dir = get_dir(user.loc,target.loc) + + switch(dist) + if(0 to 15) + to_chat(user,"[target.real_name] is near you. They are to the [dir2text(dir)] of you!") + if(16 to 31) + to_chat(user,"[target.real_name] is somewhere in your vicinty. They are to the [dir2text(dir)] of you!") + if(32 to 127) + to_chat(user,"[target.real_name] is far away from you. They are to the [dir2text(dir)] of you!") + else + to_chat(user,"[target.real_name] is beyond our reach.") + + if(target.stat == DEAD) + to_chat(user,"[target.real_name] is dead. Bring them onto a transmutation rune!") + +/obj/item/melee/sickly_blade + name = "eldritch blade" + desc = "A sickly green crescent blade, decorated with an ornamental eye. You feel like you're being watched..." + icon = 'icons/obj/eldritch.dmi' + icon_state = "eldritch_blade" + item_state = "eldritch_blade" + lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' + righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' + inhand_x_dimension = 64 + inhand_y_dimension = 64 + flags_1 = CONDUCT_1 + sharpness = SHARP_EDGED + w_class = WEIGHT_CLASS_NORMAL + force = 17 + throwforce = 10 + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb = list("attacked", "slashed", "stabbed", "sliced", "tore", "lacerated", "ripped", "diced", "rended") + +/obj/item/melee/sickly_blade/attack(mob/living/M, mob/living/user) + if(!IS_HERETIC(user)) + to_chat(user,"You feel a pulse of some alien intellect lash out at your mind!") + var/mob/living/carbon/human/human_user = user + human_user.AdjustParalyzed(5 SECONDS) + return FALSE + return ..() + +/obj/item/melee/sickly_blade/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + var/datum/antagonist/heretic/cultie = user.mind.has_antag_datum(/datum/antagonist/heretic) + if(!cultie || !proximity_flag) + return + var/list/knowledge = cultie.get_all_knowledge() + for(var/X in knowledge) + var/datum/eldritch_knowledge/eldritch_knowledge_datum = knowledge[X] + eldritch_knowledge_datum.on_eldritch_blade(target,user,proximity_flag,click_parameters) + +/obj/item/melee/sickly_blade/rust + name = "rusted blade" + desc = "This crescent blade is decrepit, wasting to dust. Yet still it bites, catching flesh with jagged, rotten teeth." + icon_state = "rust_blade" + item_state = "rust_blade" + embedding = list("pain_mult" = 4, "embed_chance" = 75, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE) + throwforce = 17 + +/obj/item/melee/sickly_blade/ash + name = "ashen blade" + desc = "Molten and unwrought, a hunk of metal warped to cinders and slag. Unmade, it aspires to be more than it is, and shears soot-filled wounds with a blunt edge." + icon_state = "ash_blade" + item_state = "ash_blade" + force = 20 + +/obj/item/melee/sickly_blade/flesh + name = "flesh blade" + desc = "A crescent blade born from a fleshwarped creature. Keenly aware, it seeks to spread to others the excruciations it has endured from dead origins." + icon_state = "flesh_blade" + item_state = "flesh_blade" + wound_bonus = 5 + bare_wound_bonus = 15 + +/obj/item/clothing/neck/eldritch_amulet + name = "warm eldritch medallion" + desc = "A strange medallion. Peering through the crystalline surface, the world around you melts away. You see your own beating heart, and the pulse of a thousand others." + icon = 'icons/obj/eldritch.dmi' + icon_state = "eye_medalion" + w_class = WEIGHT_CLASS_SMALL + ///What trait do we want to add upon equipiing + var/trait = TRAIT_THERMAL_VISION + +/obj/item/clothing/neck/eldritch_amulet/equipped(mob/user, slot) + . = ..() + if(ishuman(user) && user.mind && slot == SLOT_NECK && IS_HERETIC(user)) + ADD_TRAIT(user, trait, CLOTHING_TRAIT) + user.update_sight() + +/obj/item/clothing/neck/eldritch_amulet/dropped(mob/user) + . = ..() + REMOVE_TRAIT(user, trait, CLOTHING_TRAIT) + user.update_sight() + +/obj/item/clothing/neck/eldritch_amulet/piercing + name = "piercing eldritch medallion" + desc = "A strange medallion. Peering through the crystalline surface, the light refracts into new and terrifying spectrums of color. You see yourself, reflected off cascading mirrors, warped into improbable shapes." + trait = TRAIT_XRAY_VISION + +/obj/item/clothing/head/hooded/cult_hoodie/eldritch + name = "ominous hood" + icon_state = "eldritch" + desc = "A torn, dust-caked hood. Strange eyes line the inside." + flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR + flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH + flash_protect = 2 + +/obj/item/clothing/suit/hooded/cultrobes/eldritch + name = "ominous armor" + desc = "A ragged, dusty set of robes. Strange eyes line the inside." + icon_state = "eldritch_armor" + item_state = "eldritch_armor" + flags_inv = HIDESHOES|HIDEJUMPSUIT + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS + allowed = list(/obj/item/melee/sickly_blade, /obj/item/forbidden_book) + hoodtype = /obj/item/clothing/head/hooded/cult_hoodie/eldritch + // slightly better than normal cult robes + armor = list("melee" = 50, "bullet" = 50, "laser" = 50,"energy" = 50, "bomb" = 35, "bio" = 20, "rad" = 0, "fire" = 20, "acid" = 20) + +/obj/item/reagent_containers/glass/beaker/eldritch + name = "flask of eldritch essence" + desc = "Toxic to the close minded. Healing to those with knowledge of the beyond." + icon = 'icons/obj/eldritch.dmi' + icon_state = "eldrich_flask" + list_reagents = list(/datum/reagent/eldritch = 50) diff --git a/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm new file mode 100644 index 0000000000..065844bedf --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_knowledge.dm @@ -0,0 +1,303 @@ + +/** + * #Eldritch Knwoledge + * + * Datum that makes eldritch cultist interesting. + * + * Eldritch knowledge aren't instantiated anywhere roundstart, and are initalized and destroyed as the round goes on. + */ +/datum/eldritch_knowledge + ///Name of the knowledge + var/name = "Basic knowledge" + ///Description of the knowledge + var/desc = "Basic knowledge of forbidden arts." + ///What shows up + var/gain_text = "" + ///Cost of knowledge in souls + var/cost = 0 + ///Next knowledge in the research tree + var/list/next_knowledge = list() + ///What knowledge is incompatible with this. This will simply make it impossible to research knowledges that are in banned_knowledge once this gets researched. + var/list/banned_knowledge = list() + ///Used with rituals, how many items this needs + var/list/required_atoms = list() + ///What do we get out of this + var/list/result_atoms = list() + ///What path is this on defaults to "Side" + var/route = PATH_SIDE + +/datum/eldritch_knowledge/New() + . = ..() + var/list/temp_list + for(var/X in required_atoms) + var/atom/A = X + temp_list += list(typesof(A)) + required_atoms = temp_list + +/** + * What happens when this is assigned to an antag datum + * + * This proc is called whenever a new eldritch knowledge is added to an antag datum + */ +/datum/eldritch_knowledge/proc/on_gain(mob/user) + to_chat(user, "[gain_text]") + return +/** + * What happens when you loose this + * + * This proc is called whenever antagonist looses his antag datum, put cleanup code in here + */ +/datum/eldritch_knowledge/proc/on_lose(mob/user) + return +/** + * What happens every tick + * + * This proc is called on SSprocess in eldritch cultist antag datum. SSprocess happens roughly every second + */ +/datum/eldritch_knowledge/proc/on_life(mob/user) + return + +/** + * Special check for recipes + * + * If you are adding a more complex summoning or something that requires a special check that parses through all the atoms in an area override this. + */ +/datum/eldritch_knowledge/proc/recipe_snowflake_check(list/atoms,loc) + return TRUE + +/** + * What happens once the recipe is succesfully finished + * + * By default this proc creates atoms from result_atoms list. Override this is you want something else to happen. + */ +/datum/eldritch_knowledge/proc/on_finished_recipe(mob/living/user,list/atoms,loc) + if(result_atoms.len == 0) + return FALSE + + for(var/A in result_atoms) + new A(loc) + + return TRUE + +/** + * Used atom cleanup + * + * Overide this proc if you dont want ALL ATOMS to be destroyed. useful in many situations. + */ +/datum/eldritch_knowledge/proc/cleanup_atoms(list/atoms) + for(var/X in atoms) + var/atom/A = X + if(!isliving(A)) + atoms -= A + qdel(A) + return + +/** + * Mansus grasp act + * + * Gives addtional effects to mansus grasp spell + */ +/datum/eldritch_knowledge/proc/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) + return FALSE + + +/** + * Sickly blade act + * + * Gives addtional effects to sickly blade weapon + */ +/datum/eldritch_knowledge/proc/on_eldritch_blade(target,user,proximity_flag,click_parameters) + return + +////////////// +///Subtypes/// +////////////// + +/datum/eldritch_knowledge/spell + var/obj/effect/proc_holder/spell/spell_to_add + +/datum/eldritch_knowledge/spell/on_gain(mob/user) + var/obj/effect/proc_holder/S = new spell_to_add + user.mind.AddSpell(S) + return ..() + +/datum/eldritch_knowledge/spell/on_lose(mob/user) + user.mind.RemoveSpell(spell_to_add) + return ..() + +/datum/eldritch_knowledge/curse + var/timer = 5 MINUTES + var/list/fingerprints = list() + +/datum/eldritch_knowledge/curse/recipe_snowflake_check(list/atoms, loc) + fingerprints = list() + for(var/X in atoms) + var/atom/A = X + fingerprints |= A.fingerprints + listclearnulls(fingerprints) + if(fingerprints.len == 0) + return FALSE + return TRUE + +/datum/eldritch_knowledge/curse/on_finished_recipe(mob/living/user,list/atoms,loc) + + var/list/compiled_list = list() + + for(var/H in GLOB.human_list) + var/mob/living/carbon/human/human_to_check = H + if(fingerprints[md5(human_to_check.dna.uni_identity)]) + compiled_list |= human_to_check.real_name + compiled_list[human_to_check.real_name] = human_to_check + + if(compiled_list.len == 0) + to_chat(user, "The items don't posses required fingerprints.") + return FALSE + + var/chosen_mob = input("Select the person you wish to curse","Your target") as null|anything in sortList(compiled_list, /proc/cmp_mob_realname_dsc) + if(!chosen_mob) + return FALSE + curse(compiled_list[chosen_mob]) + addtimer(CALLBACK(src, .proc/uncurse, compiled_list[chosen_mob]),timer) + return TRUE + +/datum/eldritch_knowledge/curse/proc/curse(mob/living/chosen_mob) + return + +/datum/eldritch_knowledge/curse/proc/uncurse(mob/living/chosen_mob) + return + +/datum/eldritch_knowledge/summon + //Mob to summon + var/mob/living/mob_to_summon + + +/datum/eldritch_knowledge/summon/on_finished_recipe(mob/living/user,list/atoms,loc) + //we need to spawn the mob first so that we can use it in pollCandidatesForMob, we will move it from nullspace down the code + var/mob/living/summoned = new mob_to_summon(loc) + message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]") + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [summoned.name]", ROLE_HERETIC, null, FALSE, 100, summoned) + if(!LAZYLEN(candidates)) + to_chat(user,"No ghost could be found...") + qdel(summoned) + return FALSE + var/mob/dead/observer/C = pick(candidates) + log_game("[key_name_admin(C)] has taken control of ([key_name_admin(summoned)]), their master is [user.real_name]") + summoned.ghostize(FALSE) + summoned.key = C.key + summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster) + var/datum/antagonist/heretic_monster/heretic_monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster) + var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) + heretic_monster.set_owner(master) + return TRUE + +//Ascension knowledge +/datum/eldritch_knowledge/final + var/finished = FALSE + +/datum/eldritch_knowledge/final/recipe_snowflake_check(list/atoms, loc,selected_atoms) + if(finished) + return FALSE + var/counter = 0 + for(var/mob/living/carbon/human/H in atoms) + selected_atoms |= H + counter++ + if(counter == 3) + return TRUE + return FALSE + +/datum/eldritch_knowledge/final/on_finished_recipe( mob/living/user, list/atoms, loc) + finished = TRUE + return TRUE + +/datum/eldritch_knowledge/final/cleanup_atoms(list/atoms) + . = ..() + for(var/mob/living/carbon/human/H in atoms) + atoms -= H + H.gib() + + +/////////////// +///Base lore/// +/////////////// + +/datum/eldritch_knowledge/spell/basic + name = "Break of Dawn" + desc = "Starts your journey in the mansus. Allows you to select a target using a living heart on a transmutation rune." + gain_text = "Gates of Mansus open up to your mind." + next_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh) + cost = 0 + spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/mansus_grasp + required_atoms = list(/obj/item/living_heart) + route = "Start" + +/datum/eldritch_knowledge/spell/basic/recipe_snowflake_check(list/atoms, loc) + . = ..() + for(var/obj/item/living_heart/LH in atoms) + if(!LH.target) + return TRUE + if(LH.target in atoms) + return TRUE + return FALSE + +/datum/eldritch_knowledge/spell/basic/on_finished_recipe(mob/living/user, list/atoms, loc) + . = TRUE + var/mob/living/carbon/carbon_user = user + for(var/obj/item/living_heart/LH in atoms) + + if(LH.target && LH.target.stat == DEAD) + to_chat(carbon_user,"Your patrons accepts your offer...") + var/mob/living/carbon/human/H = LH.target + H.become_husk() + LH.target = null + var/datum/antagonist/heretic/EC = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic) + + EC.total_sacrifices++ + for(var/X in carbon_user.get_all_gear()) + if(!istype(X,/obj/item/forbidden_book)) + continue + var/obj/item/forbidden_book/FB = X + FB.charge++ + FB.charge++ + break + + if(!LH.target) + var/datum/objective/A = new + A.owner = user.mind + var/datum/mind/targeted = A.find_target()//easy way, i dont feel like copy pasting that entire block of code + LH.target = targeted.current + qdel(A) + if(LH.target) + to_chat(user,"Your new target has been selected, go and sacrifice [LH.target.real_name]!") + + else + to_chat(user,"target could not be found for living heart.") + +/datum/eldritch_knowledge/spell/basic/cleanup_atoms(list/atoms) + return + +/datum/eldritch_knowledge/living_heart + name = "Living Heart" + desc = "Allows you to create additional living hearts, using a heart, a pool of blood and a poppy. Living hearts when used on a transmutation rune will grant you a person to hunt and sacrifice on the rune. Every sacrifice gives you an additional charge in the book." + gain_text = "Disconnected, yet it still beats." + cost = 0 + required_atoms = list(/obj/item/organ/heart,/obj/effect/decal/cleanable/blood,/obj/item/reagent_containers/food/snacks/grown/poppy) + result_atoms = list(/obj/item/living_heart) + route = "Start" + +/datum/eldritch_knowledge/codex_cicatrix + name = "Codex Cicatrix" + desc = "Allows you to create a spare Codex Cicatrix if you have lost one, using a bible, human skin, a pen and a pair of eyes." + gain_text = "Their hands are at your throat, yet you see them not." + cost = 0 + required_atoms = list(/obj/item/organ/eyes,/obj/item/stack/sheet/animalhide/human,/obj/item/storage/book/bible,/obj/item/pen) + result_atoms = list(/obj/item/forbidden_book) + route = "Start" + +/datum/eldritch_knowledge/eldritch_blade + name = "Eldritch Blade" + desc = "Allows you to create a sickly, eldritch blade by transmuting a glass shard and a metal rod atop a transmutation rune." + gain_text = "The first step starts with sacrifice." + cost = 0 + required_atoms = list(/obj/item/shard,/obj/item/stack/rods) + result_atoms = list(/obj/item/melee/sickly_blade) + route = "Start" diff --git a/code/modules/antagonists/eldritch_cult/eldritch_magic.dm b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm new file mode 100644 index 0000000000..d84a997e28 --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_magic.dm @@ -0,0 +1,668 @@ +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash + name = "Ashen Passage" + desc = "Low range spell allowing you to pass through a few walls." + school = "transmutation" + invocation = "DULK'ES PRE'ZIMAS" + invocation_type = "whisper" + charge_max = 150 + range = -1 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "ash_shift" + action_background_icon_state = "bg_ecult" + jaunt_in_time = 13 + jaunt_duration = 10 + jaunt_in_type = /obj/effect/temp_visual/dir_setting/ash_shift + jaunt_out_type = /obj/effect/temp_visual/dir_setting/ash_shift/out + +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long + jaunt_duration = 50 + +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/play_sound() + return + +/obj/effect/temp_visual/dir_setting/ash_shift + name = "ash_shift" + icon = 'icons/mob/mob.dmi' + icon_state = "ash_shift2" + duration = 13 + +/obj/effect/temp_visual/dir_setting/ash_shift/out + icon_state = "ash_shift" + +/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp + name = "Mansus Grasp" + desc = "Touch spell that allows you to channel the power of the Old Gods through you." + hand_path = /obj/item/melee/touch_attack/mansus_fist + school = "evocation" + charge_max = 150 + clothes_req = FALSE + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "mansus_grasp" + action_background_icon_state = "bg_ecult" + +/obj/item/melee/touch_attack/mansus_fist + name = "Mansus Grasp" + desc = "A sinister looking aura that distorts the flow of reality around it. Causes knockdown, major stamina damage aswell as some Brute. It gains additional beneficial effects with certain knowledges you can research." + icon_state = "disintegrate" + item_state = "disintegrate" + catchphrase = "T'IESA SIE'KTI VISATA" + +/obj/item/melee/touch_attack/mansus_fist/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + + if(!proximity_flag || target == user) + return + playsound(user, 'sound/items/welder.ogg', 75, TRUE) + if(ishuman(target)) + var/mob/living/carbon/human/tar = target + if(tar.anti_magic_check()) + tar.visible_message("Spell bounces off of [target]!","The spell bounces off of you!") + return ..() + var/datum/mind/M = user.mind + var/datum/antagonist/heretic/cultie = M.has_antag_datum(/datum/antagonist/heretic) + + var/use_charge = FALSE + if(iscarbon(target)) + use_charge = TRUE + var/mob/living/carbon/C = target + C.adjustBruteLoss(15) + C.DefaultCombatKnockdown(50, override_stamdmg = 0) + C.adjustStaminaLoss(60) + var/list/knowledge = cultie.get_all_knowledge() + + for(var/X in knowledge) + var/datum/eldritch_knowledge/EK = knowledge[X] + if(EK.on_mansus_grasp(target, user, proximity_flag, click_parameters)) + use_charge = TRUE + if(use_charge) + return ..() + +/obj/effect/proc_holder/spell/aoe_turf/rust_conversion + name = "Aggressive Spread" + desc = "Spreads rust onto nearby turfs." + school = "transmutation" + charge_max = 300 //twice as long as mansus grasp + clothes_req = FALSE + invocation = "PLI'STI MINO DOMI'KA" + invocation_type = "whisper" + range = 3 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "corrode" + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/cast(list/targets, mob/user = usr) + playsound(user, 'sound/items/welder.ogg', 75, TRUE) + for(var/turf/T in targets) + ///What we want is the 3 tiles around the user and the tile under him to be rusted, so min(dist,1)-1 causes us to get 0 for these tiles, rest of the tiles are based on chance + var/chance = 100 - (max(get_dist(T,user),1)-1)*100/(range+1) + if(!prob(chance)) + continue + T.rust_heretic_act() + +/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small + name = "Rust Conversion" + desc = "Spreads rust onto nearby turfs." + range = 2 + +/obj/effect/proc_holder/spell/targeted/touch/blood_siphon + name = "Blood Siphon" + desc = "Touch spell that heals you while damaging the enemy, has a chance to transfer wounds between you and your enemy." + hand_path = /obj/item/melee/touch_attack/blood_siphon + school = "evocation" + charge_max = 150 + clothes_req = FALSE + invocation_type = "none" + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "blood_siphon" + action_background_icon_state = "bg_ecult" + +/obj/item/melee/touch_attack/blood_siphon + name = "Blood Siphon" + desc = "A sinister looking aura that distorts the flow of reality around it." + icon_state = "disintegrate" + item_state = "disintegrate" + catchphrase = "SUN'AI'KINI'MAS" + +/obj/item/melee/touch_attack/blood_siphon/afterattack(atom/target, mob/user, proximity_flag, proximity) + if(!proximity_flag) + return + playsound(user, 'sound/effects/curseattack.ogg', 75, TRUE) + if(ishuman(target)) + var/mob/living/carbon/human/tar = target + if(tar.anti_magic_check()) + tar.visible_message("Spell bounces off of [target]!","The spell bounces off of you!") + return ..() + var/mob/living/carbon/C2 = user + if(isliving(target)) + var/mob/living/L = target + L.adjustBruteLoss(20) + C2.adjustBruteLoss(-20) + if(iscarbon(target)) + var/mob/living/carbon/C1 = target + for(var/obj/item/bodypart/bodypart in C2.bodyparts) + for(var/i in bodypart.wounds) + var/datum/wound/iter_wound = i + if(prob(50)) + continue + var/obj/item/bodypart/target_bodypart = locate(bodypart.type) in C1.bodyparts + if(!target_bodypart) + continue + iter_wound.remove_wound() + iter_wound.apply_wound(target_bodypart) + + C1.blood_volume -= 20 + if(C2.blood_volume < BLOOD_VOLUME_MAXIMUM) //we dont want to explode after all + C2.blood_volume += 20 + return ..() + +/obj/effect/proc_holder/spell/aimed/rust_wave + name = "Patron's Reach" + desc = "Channels energy into your gauntlet - firing it results in a wave of rust being created in it's wake." + projectile_type = /obj/item/projectile/magic/spell/rust_wave + charge_max = 350 + clothes_req = FALSE + action_icon = 'icons/mob/actions/actions_ecult.dmi' + base_icon_state = "rust_wave" + action_icon_state = "rust_wave" + action_background_icon_state = "bg_ecult" + sound = 'sound/effects/curse5.ogg' + active_msg = "You extend your hand out, preparing to send out a wave of rust." + deactive_msg = "You extinguish that energy, for now..." + invocation = "RUD'ZI VAR'ZTAS" + invocation_type = "whisper" + +/obj/item/projectile/magic/spell/rust_wave + name = "rust bolt" + icon_state = "eldritch_projectile" + alpha = 180 + damage = 30 + damage_type = TOX + nodamage = 0 + hitsound = 'sound/effects/curseattack.ogg' + range = 15 + +/obj/item/projectile/magic/spell/rust_wave/Moved(atom/OldLoc, Dir) + . = ..() + playsound(src, 'sound/items/welder.ogg', 75, TRUE) + var/list/turflist = list() + var/turf/T1 + turflist += get_turf(src) + T1 = get_step(src,turn(dir,90)) + turflist += T1 + turflist += get_step(T1,turn(dir,90)) + T1 = get_step(src,turn(dir,-90)) + turflist += T1 + turflist += get_step(T1,turn(dir,-90)) + for(var/X in turflist) + if(!X || prob(25)) + continue + var/turf/T = X + T.rust_heretic_act() + +/obj/effect/proc_holder/spell/aimed/rust_wave/short + name = "Small Patron's Reach" + projectile_type = /obj/item/projectile/magic/spell/rust_wave/short + +/obj/item/projectile/magic/spell/rust_wave/short + range = 7 + +/obj/effect/proc_holder/spell/pointed/cleave + name = "Cleave" + desc = "Causes severe bleeding on a target and people around them" + school = "transmutation" + charge_max = 350 + clothes_req = FALSE + invocation = "PLES'TI VI'RIBUS" + invocation_type = "whisper" + range = 9 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "cleave" + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/pointed/cleave/cast(list/targets, mob/user) + if(!targets.len) + to_chat(user, "No target found in range!") + return FALSE + if(!can_target(targets[1], user)) + return FALSE + + for(var/mob/living/carbon/human/C in range(1,targets[1])) + targets |= C + + + for(var/X in targets) + var/mob/living/carbon/human/target = X + if(target == user) + continue + if(target.anti_magic_check()) + to_chat(user, "The spell had no effect!") + target.visible_message("[target]'s veins flash with fire, but their magic protection repulses the blaze!", \ + "Your veins flash with fire, but your magic protection repels the blaze!") + continue + + target.visible_message("[target]'s veins are shredded from within as an unholy blaze erupts from their blood!", \ + "Your veins burst from within and unholy flame erupts from your blood!") + var/obj/item/bodypart/bodypart = pick(target.bodyparts) + var/datum/wound/slash/critical/crit_wound = new + crit_wound.apply_wound(bodypart) + target.adjustFireLoss(20) + new /obj/effect/temp_visual/cleave(target.drop_location()) + +/obj/effect/proc_holder/spell/pointed/cleave/can_target(atom/target, mob/user, silent) + . = ..() + if(!.) + return FALSE + if(!istype(target,/mob/living/carbon/human)) + if(!silent) + to_chat(user, "You are unable to cleave [target]!") + return FALSE + return TRUE + +/obj/effect/proc_holder/spell/pointed/cleave/long + charge_max = 650 + +/obj/effect/proc_holder/spell/pointed/touch/mad_touch + name = "Touch of Madness" + desc = "Touch spell that drains your enemies sanity." + school = "transmutation" + charge_max = 150 + clothes_req = FALSE + invocation_type = "none" + range = 2 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "mad_touch" + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/pointed/touch/mad_touch/can_target(atom/target, mob/user, silent) + . = ..() + if(!.) + return FALSE + if(!istype(target,/mob/living/carbon/human)) + if(!silent) + to_chat(user, "You are unable to touch [target]!") + return FALSE + return TRUE + +/obj/effect/proc_holder/spell/pointed/touch/mad_touch/cast(list/targets, mob/user) + . = ..() + for(var/mob/living/carbon/target in targets) + if(ishuman(targets)) + var/mob/living/carbon/human/tar = target + if(tar.anti_magic_check()) + tar.visible_message("Spell bounces off of [target]!","The spell bounces off of you!") + return + if(target.mind && !target.mind.has_antag_datum(/datum/antagonist/heretic)) + to_chat(user,"[target.name] has been cursed!") + SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "gates_of_mansus", /datum/mood_event/gates_of_mansus) + +/obj/effect/proc_holder/spell/pointed/ash_final + name = "Nightwatcher's Rite" + desc = "Powerful spell that releases 5 streams of fire away from you." + school = "transmutation" + invocation = "IGNIS'INTI" + invocation_type = "whisper" + charge_max = 300 + range = 15 + clothes_req = FALSE + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "flames" + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/pointed/ash_final/cast(list/targets, mob/user) + for(var/X in targets) + var/T + T = line_target(-25, range, X, user) + INVOKE_ASYNC(src, .proc/fire_line, user,T) + T = line_target(10, range, X, user) + INVOKE_ASYNC(src, .proc/fire_line, user,T) + T = line_target(0, range, X, user) + INVOKE_ASYNC(src, .proc/fire_line, user,T) + T = line_target(-10, range, X, user) + INVOKE_ASYNC(src, .proc/fire_line, user,T) + T = line_target(25, range, X, user) + INVOKE_ASYNC(src, .proc/fire_line, user,T) + return ..() + +/obj/effect/proc_holder/spell/pointed/ash_final/proc/line_target(offset, range, atom/at , atom/user) + if(!at) + return + var/angle = ATAN2(at.x - user.x, at.y - user.y) + offset + var/turf/T = get_turf(user) + for(var/i in 1 to range) + var/turf/check = locate(user.x + cos(angle) * i, user.y + sin(angle) * i, user.z) + if(!check) + break + T = check + return (getline(user, T) - get_turf(user)) + +/obj/effect/proc_holder/spell/pointed/ash_final/proc/fire_line(atom/source, list/turfs) + var/list/hit_list = list() + for(var/turf/T in turfs) + if(istype(T, /turf/closed)) + break + + for(var/mob/living/L in T.contents) + if(L.anti_magic_check()) + L.visible_message("Spell bounces off of [L]!","The spell bounces off of you!") + continue + if(L in hit_list || L == source) + continue + hit_list += L + L.adjustFireLoss(20) + to_chat(L, "You're hit by [source]'s fire breath!") + + new /obj/effect/hotspot(T) + T.hotspot_expose(700,50,1) + // deals damage to mechs + for(var/obj/mecha/M in T.contents) + if(M in hit_list) + continue + hit_list += M + M.take_damage(45, BURN, "melee", 1) + sleep(1.5) + +/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch + invocation_type = "none" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + sound = 'sound/magic/enter_blood.ogg' + possible_shapes = list(/mob/living/simple_animal/mouse,\ + /mob/living/simple_animal/pet/dog/corgi,\ + /mob/living/simple_animal/hostile/carp,\ + /mob/living/simple_animal/bot/secbot, \ + /mob/living/simple_animal/pet/fox,\ + /mob/living/simple_animal/pet/cat ) + +/obj/effect/proc_holder/spell/targeted/emplosion/eldritch + name = "Energetic Pulse" + invocation_type = "none" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + range = -1 + include_user = TRUE + charge_max = 300 + emp_heavy = 6 + emp_light = 10 + sound = 'sound/effects/lingscreech.ogg' + +/obj/effect/proc_holder/spell/aoe_turf/fire_cascade + name = "Fire Cascade" + desc = "creates hot turfs around you." + school = "transmutation" + charge_max = 300 //twice as long as mansus grasp + clothes_req = FALSE + invocation = "IGNIS'SAVARIN" + invocation_type = "whisper" + range = 4 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "fire_ring" + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/cast(list/targets, mob/user = usr) + INVOKE_ASYNC(src, .proc/fire_cascade, user,range) + +/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/proc/fire_cascade(atom/centre,max_range) + playsound(get_turf(centre), 'sound/items/welder.ogg', 75, TRUE) + var/_range = 1 + for(var/i = 0, i <= max_range,i++) + for(var/turf/T in spiral_range_turfs(_range,centre)) + new /obj/effect/hotspot(T) + T.hotspot_expose(700,50,1) + for(var/mob/living/livies in T.contents - centre) + livies.adjustFireLoss(10) + _range++ + sleep(3) + +/obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big + range = 6 + +/obj/effect/proc_holder/spell/targeted/telepathy/eldritch + invocation = "" + invocation_type = "whisper" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/targeted/fire_sworn + name = "Oath of Fire" + desc = "For a minute you will passively create a ring of fire around you." + invocation = "IGNIS'AISTRA'LISTRE" + invocation_type = "whisper" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + range = -1 + include_user = TRUE + charge_max = 700 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "fire_ring" + ///how long it lasts + var/duration = 1 MINUTES + ///who casted it right now + var/mob/current_user + ///Determines if you get the fire ring effect + var/has_fire_ring = FALSE + +/obj/effect/proc_holder/spell/targeted/fire_sworn/cast(list/targets, mob/user) + . = ..() + current_user = user + has_fire_ring = TRUE + addtimer(CALLBACK(src, .proc/remove, user), duration, TIMER_OVERRIDE|TIMER_UNIQUE) + +/obj/effect/proc_holder/spell/targeted/fire_sworn/proc/remove() + has_fire_ring = FALSE + +/obj/effect/proc_holder/spell/targeted/fire_sworn/process() + . = ..() + if(!has_fire_ring) + return + for(var/turf/T in range(1,current_user)) + new /obj/effect/hotspot(T) + T.hotspot_expose(700,50,1) + for(var/mob/living/livies in T.contents - current_user) + livies.adjustFireLoss(5) + + +/obj/effect/proc_holder/spell/targeted/worm_contract + name = "Force Contract" + desc = "Forces all the worm parts to collapse onto a single turf" + invocation_type = "none" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + range = -1 + include_user = TRUE + charge_max = 300 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "worm_contract" + +/obj/effect/proc_holder/spell/targeted/worm_contract/cast(list/targets, mob/user) + . = ..() + if(!istype(user,/mob/living/simple_animal/hostile/eldritch/armsy)) + to_chat(user, "You try to contract your muscles but nothing happens...") + var/mob/living/simple_animal/hostile/eldritch/armsy/armsy = user + armsy.contract_next_chain_into_single_tile() + +/obj/effect/temp_visual/cleave + icon = 'icons/effects/eldritch.dmi' + icon_state = "cleave" + duration = 6 + +/obj/effect/temp_visual/eldritch_smoke + icon = 'icons/effects/eldritch.dmi' + icon_state = "smoke" + duration = 10 + +/obj/effect/proc_holder/spell/targeted/fiery_rebirth + name = "Nightwatcher's Rebirth" + desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off." + invocation = "PETHRO'MINO'IGNI" + invocation_type = "whisper" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + range = -1 + include_user = TRUE + charge_max = 600 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "smoke" + +/obj/effect/proc_holder/spell/targeted/fiery_rebirth/cast(list/targets, mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/human_user = user + for(var/mob/living/carbon/target in view(7,user)) + if(target.stat == DEAD || !target.on_fire) + continue + //This is essentially a death mark, use this to finish your opponent quicker. + if(target.InCritical()) + target.death() + target.adjustFireLoss(20) + new /obj/effect/temp_visual/eldritch_smoke(target.drop_location()) + human_user.ExtinguishMob() + human_user.adjustBruteLoss(-10, FALSE) + human_user.adjustFireLoss(-10, FALSE) + human_user.adjustStaminaLoss(-10, FALSE) + human_user.adjustToxLoss(-10, FALSE) + human_user.adjustOxyLoss(-10) + +/obj/effect/proc_holder/spell/pointed/manse_link + name = "Mansus Link" + desc = "Piercing through reality, connecting minds. This spell allows you to add people to a mansus net, allowing them to communicate with eachother" + school = "transmutation" + charge_max = 300 + clothes_req = FALSE + invocation = "SUSEI' METO MIN'TIS" + invocation_type = "whisper" + range = 10 + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "mansus_link" + action_background_icon_state = "bg_ecult" + +/obj/effect/proc_holder/spell/pointed/manse_link/can_target(atom/target, mob/user, silent) + if(!isliving(target)) + return FALSE + return TRUE + +/obj/effect/proc_holder/spell/pointed/manse_link/cast(list/targets, mob/user) + var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator = user + + var/mob/living/target = targets[1] + + to_chat(originator, "You begin linking [target]'s mind to yours...") + to_chat(target, "You feel your mind being pulled... connected... intertwined with the very fabric of reality...") + if(!do_after(originator, 6 SECONDS, target)) + return + if(!originator.link_mob(target)) + to_chat(originator, "You can't seem to link [target]'s mind...") + to_chat(target, "The foreign presence leaves your mind.") + return + to_chat(originator, "You connect [target]'s mind to your mansus link!") + + +/datum/action/innate/mansus_speech + name = "Mansus Link" + desc = "Send a psychic message to everyone connected to your mansus link." + button_icon_state = "link_speech" + icon_icon = 'icons/mob/actions/actions_slime.dmi' + background_icon_state = "bg_ecult" + var/mob/living/simple_animal/hostile/eldritch/raw_prophet/originator + +/datum/action/innate/mansus_speech/New(_originator) + . = ..() + originator = _originator + +/datum/action/innate/mansus_speech/Activate() + var/mob/living/living_owner = owner + if(!originator?.linked_mobs[living_owner]) + CRASH("Uh oh the mansus link got somehow activated without it being linked to a raw prophet or the mob not being in a list of mobs that should be able to do it.") + + var/message = sanitize(input("Message:", "Telepathy from the Manse") as text|null) + + if(QDELETED(living_owner)) + return + + if(!originator?.linked_mobs[living_owner]) + to_chat(living_owner, "The link seems to have been severed...") + Remove(living_owner) + return + if(message) + var/msg = "\[Mansus Link\] [living_owner]: [message]" + log_directed_talk(living_owner, originator, msg, LOG_SAY, "Mansus Link") + to_chat(originator.linked_mobs, msg) + + for(var/dead_mob in GLOB.dead_mob_list) + var/link = FOLLOW_LINK(dead_mob, living_owner) + to_chat(dead_mob, "[link] [msg]") + +/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch + range = 10 + invocation = "AK'LIS" + action_background_icon_state = "bg_ecult" + +/obj/effect/temp_visual/dir_setting/entropic + icon = 'icons/effects/160x160.dmi' + icon_state = "entropic_plume" + duration = 3 SECONDS + +/obj/effect/temp_visual/dir_setting/entropic/setDir(dir) + . = ..() + switch(dir) + if(NORTH) + pixel_x = -64 + if(SOUTH) + pixel_x = -64 + pixel_y = -128 + if(EAST) + pixel_y = -64 + if(WEST) + pixel_y = -64 + pixel_x = -128 + +/obj/effect/temp_visual/glowing_rune + icon = 'icons/effects/eldritch.dmi' + icon_state = "small_rune_1" + duration = 1 MINUTES + layer = LOW_SIGIL_LAYER + +/obj/effect/temp_visual/glowing_rune/Initialize() + . = ..() + pixel_y = rand(-6,6) + pixel_x = rand(-6,6) + icon_state = "small_rune_[rand(12)]" + update_icon() + +/obj/effect/proc_holder/spell/cone/staggered/entropic_plume + name = "Entropic Plume" + desc = "Spews forth a disorienting plume that causes enemies to strike each other, briefly blinds them(increasing with range) and poisons them(decreasing with range). Also spreads rust in the path of the plume." + school = "illusion" + invocation = "RU'KAS NU'DYTI" + invocation_type = "whisper" + clothes_req = FALSE + action_background_icon_state = "bg_ecult" + action_icon = 'icons/mob/actions/actions_ecult.dmi' + action_icon_state = "entropic_plume" + charge_max = 300 + cone_levels = 5 + respect_density = TRUE + +/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/cast(list/targets,mob/user = usr) + . = ..() + new /obj/effect/temp_visual/dir_setting/entropic(get_step(user,user.dir), user.dir) + +/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_turf_cone_effect(turf/target_turf, level) + . = ..() + target_turf.rust_heretic_act() + +/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/do_mob_cone_effect(mob/living/victim, level) + . = ..() + if(victim.anti_magic_check() || IS_HERETIC(victim) || victim.mind?.has_antag_datum(/datum/antagonist/heretic_monster)) + return + victim.apply_status_effect(STATUS_EFFECT_AMOK) + victim.apply_status_effect(STATUS_EFFECT_CLOUDSTRUCK, (level*10)) + if(iscarbon(victim)) + var/mob/living/carbon/carbon_victim = victim + carbon_victim.reagents.add_reagent(/datum/reagent/eldritch, min(1, 6-level)) + +/obj/effect/proc_holder/spell/cone/staggered/entropic_plume/calculate_cone_shape(current_level) + if(current_level == cone_levels) + return 5 + else if(current_level == cone_levels-1) + return 3 + else + return 2 diff --git a/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm new file mode 100644 index 0000000000..529128fc0a --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/eldritch_monster_antag.dm @@ -0,0 +1,43 @@ +///Tracking reasons +/datum/antagonist/heretic_monster + name = "Eldritch Horror" + roundend_category = "Heretics" + antagpanel_category = "Heretic Beast" + antag_moodlet = /datum/mood_event/heretics + job_rank = ROLE_HERETIC + antag_hud_type = ANTAG_HUD_HERETIC + antag_hud_name = "heretic_beast" + var/datum/antagonist/master + +/datum/antagonist/heretic_monster/admin_add(datum/mind/new_owner,mob/admin) + new_owner.add_antag_datum(src) + message_admins("[key_name_admin(admin)] has heresized [key_name_admin(new_owner)].") + log_admin("[key_name(admin)] has heresized [key_name(new_owner)].") + +/datum/antagonist/heretic_monster/greet() + owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ecult_op.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change + to_chat(owner, "You became an Eldritch Horror!") + +/datum/antagonist/heretic_monster/on_removal() + if(owner) + to_chat(owner, "Your master is no longer [master.owner.current.real_name]") + owner = null + return ..() + +/datum/antagonist/heretic_monster/proc/set_owner(datum/antagonist/_master) + master = _master + var/datum/objective/master_obj = new + master_obj.owner = src + master_obj.explanation_text = "Assist your master in any way you can!" + objectives += master_obj + owner.announce_objectives() + to_chat(owner, "Your master is [master.owner.current.real_name]") + return + +/datum/antagonist/heretic_monster/apply_innate_effects(mob/living/mob_override) + . = ..() + add_antag_hud(antag_hud_type, antag_hud_name, owner.current) + +/datum/antagonist/heretic_monster/remove_innate_effects(mob/living/mob_override) + . = ..() + remove_antag_hud(antag_hud_type, owner.current) diff --git a/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm new file mode 100644 index 0000000000..8efd9837a9 --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/knowledge/ash_lore.dm @@ -0,0 +1,183 @@ +/datum/eldritch_knowledge/base_ash + name = "Nightwatcher's Secret" + desc = "Inducts you into the Path of Ash. Allows you to transmute a match with an eldritch blade into an ashen blade." + gain_text = "The City guard knows their watch. If you ask them at night they may tell you about the ashy lantern." + banned_knowledge = list(/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/final/flesh_final) + next_knowledge = list(/datum/eldritch_knowledge/ashen_grasp) + required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/match) + result_atoms = list(/obj/item/melee/sickly_blade/ash) + cost = 1 + route = PATH_ASH + +/datum/eldritch_knowledge/spell/ashen_shift + name = "Ashen Shift" + gain_text = "Ash is all the same, how can one man master it all?" + desc = "A short range jaunt that will enable you to escape from danger." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash + next_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/essence,/datum/eldritch_knowledge/ashen_eyes) + route = PATH_ASH + +/datum/eldritch_knowledge/ashen_grasp + name = "Grasp of Ash" + gain_text = "Gates have opened, minds have flooded, yet I remain." + desc = "Empowers your mansus grasp to knock enemies down and throw them away." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift) + route = PATH_ASH + +/datum/eldritch_knowledge/ashen_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(!iscarbon(target)) + return + + var/mob/living/carbon/C = target + var/datum/status_effect/eldritch/E = C.has_status_effect(/datum/status_effect/eldritch/rust) || C.has_status_effect(/datum/status_effect/eldritch/ash) || C.has_status_effect(/datum/status_effect/eldritch/flesh) + if(E) + . = TRUE + E.on_effect() + for(var/X in user.mind.spell_list) + if(!istype(X,/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp)) + continue + var/obj/effect/proc_holder/spell/targeted/touch/mansus_grasp/MG = X + MG.charge_counter = min(round(MG.charge_counter + MG.charge_max * 0.75),MG.charge_max) // refunds 75% of charge. + var/atom/throw_target = get_edge_target_turf(C, user.dir) + if(!C.anchored) + . = TRUE + C.throw_at(throw_target, rand(4,8), 14, user) + return + +/datum/eldritch_knowledge/ashen_eyes + name = "Ashen Eyes" + gain_text = "Piercing eyes may guide me through the mundane." + desc = "Allows you to craft thermal vision amulet by transmutating eyes with a glass shard." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/spell/ashen_shift,/datum/eldritch_knowledge/flesh_ghoul) + required_atoms = list(/obj/item/organ/eyes,/obj/item/shard) + result_atoms = list(/obj/item/clothing/neck/eldritch_amulet) + +/datum/eldritch_knowledge/ash_mark + name = "Mark of Ash" + gain_text = "Spread the famine." + desc = "Your sickly blade now applies ash mark on hit. Use your mansus grasp to proc the mark. Mark of Ash causes stamina damage, and fire loss, and spreads to a nearby carbon. Damage decreases with how many times the mark has spread." + cost = 2 + next_knowledge = list(/datum/eldritch_knowledge/curse/blindness) + banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/flesh_mark) + route = PATH_ASH + +/datum/eldritch_knowledge/ash_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters) + . = ..() + if(isliving(target)) + var/mob/living/living_target = target + living_target.apply_status_effect(/datum/status_effect/eldritch/ash,5) + +/datum/eldritch_knowledge/curse/blindness + name = "Curse of Blindness" + gain_text = "The blind man walks through the world, unnoticed by the masses." + desc = "Curse someone with 2 minutes of complete blindness by sacrificing a pair of eyes, a screwdriver and a pool of blood, with an object that the victim has touched with their bare hands." + cost = 1 + required_atoms = list(/obj/item/organ/eyes,/obj/item/screwdriver,/obj/effect/decal/cleanable/blood) + next_knowledge = list(/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/curse/paralysis) + timer = 2 MINUTES + route = PATH_ASH + +/datum/eldritch_knowledge/curse/blindness/curse(mob/living/chosen_mob) + . = ..() + chosen_mob.become_blind(MAGIC_TRAIT) + +/datum/eldritch_knowledge/curse/blindness/uncurse(mob/living/chosen_mob) + . = ..() + chosen_mob.cure_blind(MAGIC_TRAIT) + +/datum/eldritch_knowledge/spell/flame_birth + name = "Fiery Rebirth" + gain_text = "Nightwatcher was a man of principles, and yet he arose from the chaos he vowed to protect from." + desc = "Drains nearby alive people that are engulfed in flames. It heals 10 of each damage type per person. If a person is in critical condition it finishes them off." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/targeted/fiery_rebirth + next_knowledge = list(/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/final/ash_final) + route = PATH_ASH + +/datum/eldritch_knowledge/ash_blade_upgrade + name = "Blazing Steel" + gain_text = "May the sun burn the heretics." + desc = "Your blade of choice will now add firestacks." + cost = 2 + next_knowledge = list(/datum/eldritch_knowledge/spell/flame_birth) + banned_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade) + route = PATH_ASH + +/datum/eldritch_knowledge/ash_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters) + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/C = target + C.adjust_fire_stacks(1) + C.IgniteMob() + +/datum/eldritch_knowledge/curse/corrosion + name = "Curse of Corrosion" + gain_text = "Cursed land, cursed man, cursed mind." + desc = "Curse someone for 2 minutes of vomiting and major organ damage. Using a wirecutter, a spill of blood, a heart, left arm and a right arm, and an item that the victim touched with their bare hands." + cost = 1 + required_atoms = list(/obj/item/wirecutters,/obj/effect/decal/cleanable/blood,/obj/item/organ/heart,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm) + next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/spell/area_conversion) + timer = 2 MINUTES + +/datum/eldritch_knowledge/curse/corrosion/curse(mob/living/chosen_mob) + . = ..() + chosen_mob.apply_status_effect(/datum/status_effect/corrosion_curse) + +/datum/eldritch_knowledge/curse/corrosion/uncurse(mob/living/chosen_mob) + . = ..() + chosen_mob.remove_status_effect(/datum/status_effect/corrosion_curse) + +/datum/eldritch_knowledge/curse/paralysis + name = "Curse of Paralysis" + gain_text = "Corrupt their flesh, make them bleed." + desc = "Curse someone for 5 minutes of inability to walk. Using a knife, pool of blood, left leg, right leg, a hatchet and an item that the victim touched with their bare hands. " + cost = 1 + required_atoms = list(/obj/item/kitchen/knife,/obj/effect/decal/cleanable/blood,/obj/item/bodypart/l_leg,/obj/item/bodypart/r_leg,/obj/item/hatchet) + next_knowledge = list(/datum/eldritch_knowledge/curse/blindness,/datum/eldritch_knowledge/summon/raw_prophet) + timer = 5 MINUTES + +/datum/eldritch_knowledge/curse/paralysis/curse(mob/living/chosen_mob) + . = ..() + ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT) + ADD_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT) + chosen_mob.update_mobility() + +/datum/eldritch_knowledge/curse/paralysis/uncurse(mob/living/chosen_mob) + . = ..() + REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_L_LEG,MAGIC_TRAIT) + REMOVE_TRAIT(chosen_mob,TRAIT_PARALYSIS_R_LEG,MAGIC_TRAIT) + chosen_mob.update_mobility() + +/datum/eldritch_knowledge/spell/cleave + name = "Blood Cleave" + gain_text = "At first I was unfamiliar with these instruments of war, but the priest told me how to use them." + desc = "Grants a spell that will inflict wounds and bleeding upon the target, as well as in a short radius around them." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/pointed/cleave + next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume,/datum/eldritch_knowledge/spell/flame_birth) + +/datum/eldritch_knowledge/final/ash_final + name = "Ashlord's Rite" + gain_text = "The forgotten lords have spoken! The Lord of Ash has come! Fear the flame!" + desc = "Bring three corpses onto a transmutation rune, after ascending you will become immune to fire, space, temperature and other environmental hazards. You will develop resistance to all other damages. You will be granted two spells, one which can bring forth a cascade of massive fire, and another which will surround your body in precious flames for a minute." + required_atoms = list(/mob/living/carbon/human) + cost = 5 + route = PATH_ASH + var/list/trait_list = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_RADIMMUNE,TRAIT_GENELESS,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_BOMBIMMUNE) + +/datum/eldritch_knowledge/final/ash_final/on_finished_recipe(mob/living/user, list/atoms, loc) + priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the blaze, for Ashbringer [user.real_name] has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg') + user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/fire_cascade/big) + user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/fire_sworn) + var/mob/living/carbon/human/H = user + H.physiology.brute_mod *= 0.5 + H.physiology.burn_mod *= 0.5 + var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic) + ascension.ascended = TRUE + for(var/X in trait_list) + ADD_TRAIT(user,X,MAGIC_TRAIT) + return ..() diff --git a/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm new file mode 100644 index 0000000000..9684e1fa0c --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/knowledge/flesh_lore.dm @@ -0,0 +1,252 @@ +/datum/eldritch_knowledge/base_flesh + name = "Principle of Hunger" + desc = "Inducts you into the Path of Flesh. Allows you to transmute a pool of blood with your eldritch blade into a Blade of Flesh." + gain_text = "Hundred's of us starved, but I.. I found the strength in my greed." + banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_rust,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/rust_final) + next_knowledge = list(/datum/eldritch_knowledge/flesh_grasp) + required_atoms = list(/obj/item/melee/sickly_blade,/obj/effect/decal/cleanable/blood) + result_atoms = list(/obj/item/melee/sickly_blade/flesh) + cost = 1 + route = PATH_FLESH + +/datum/eldritch_knowledge/flesh_ghoul + name = "Imperfect Ritual" + desc = "Allows you to resurrect the dead as voiceless dead by sacrificing them on the transmutation rune with a poppy. Voiceless dead are mute and have 50 HP. You can only have 2 at a time." + gain_text = "I found notes... notes of a ritual, scraps, unfinished, and yet... I still did it." + cost = 1 + required_atoms = list(/mob/living/carbon/human,/obj/item/reagent_containers/food/snacks/grown/poppy) + next_knowledge = list(/datum/eldritch_knowledge/flesh_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/ashen_eyes) + route = PATH_FLESH + var/max_amt = 2 + var/current_amt = 0 + var/list/ghouls = list() + +/datum/eldritch_knowledge/flesh_ghoul/on_finished_recipe(mob/living/user,list/atoms,loc) + var/mob/living/carbon/human/humie = locate() in atoms + if(QDELETED(humie) || humie.stat != DEAD) + return + + if(length(ghouls) >= max_amt) + return + + if(HAS_TRAIT(humie,TRAIT_HUSK)) + return + + humie.grab_ghost() + + if(!humie.mind || !humie.client) + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [humie.real_name], a voiceless dead.", ROLE_HERETIC, null, ROLE_HERETIC, 50,humie) + if(!LAZYLEN(candidates)) + return + var/mob/dead/observer/C = pick(candidates) + message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(humie)]) to replace an AFK player.") + humie.ghostize(0) + humie.key = C.key + + ADD_TRAIT(humie,TRAIT_MUTE,MAGIC_TRAIT) + log_game("[key_name_admin(humie)] has become a voiceless dead, their master is [user.real_name]") + humie.revive(full_heal = TRUE, admin_revive = TRUE) + humie.setMaxHealth(75) + humie.health = 75 // Voiceless dead are much tougher than ghouls + humie.become_husk() + humie.faction |= "heretics" + + var/datum/antagonist/heretic_monster/heretic_monster = humie.mind.add_antag_datum(/datum/antagonist/heretic_monster) + var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) + heretic_monster.set_owner(master) + atoms -= humie + RegisterSignal(humie,COMSIG_MOB_DEATH,.proc/remove_ghoul) + ghouls += humie + +/datum/eldritch_knowledge/flesh_ghoul/proc/remove_ghoul(datum/source) + var/mob/living/carbon/human/humie = source + ghouls -= humie + humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster) + UnregisterSignal(source,COMSIG_MOB_DEATH) + +/datum/eldritch_knowledge/flesh_grasp + name = "Grasp of Flesh" + gain_text = "'My newfound desire, it drove me to do great things,' The Priest said." + desc = "Empowers your Mansus Grasp to be able to create a single ghoul out of a dead player. You cannot raise the same person twice. Ghouls have only 50 HP and look like husks." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/flesh_ghoul) + var/ghoul_amt = 6 + var/list/spooky_scaries + route = PATH_FLESH + +/datum/eldritch_knowledge/flesh_grasp/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(!ishuman(target) || target == user) + return + var/mob/living/carbon/human/human_target = target + var/datum/status_effect/eldritch/eldritch_effect = human_target.has_status_effect(/datum/status_effect/eldritch/rust) || human_target.has_status_effect(/datum/status_effect/eldritch/ash) || human_target.has_status_effect(/datum/status_effect/eldritch/flesh) + if(eldritch_effect) + . = TRUE + eldritch_effect.on_effect() + if(iscarbon(target)) + var/mob/living/carbon/carbon_target = target + var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts) + var/datum/wound/slash/severe/crit_wound = new + crit_wound.apply_wound(bodypart) + + if(QDELETED(human_target) || human_target.stat != DEAD) + return + + human_target.grab_ghost() + + if(!human_target.mind || !human_target.client) + to_chat(user, "There is no soul connected to this body...") + return + + if(HAS_TRAIT(human_target, TRAIT_HUSK)) + to_chat(user, "You cannot revive a dead ghoul!") + return + + if(LAZYLEN(spooky_scaries) >= ghoul_amt) + to_chat(user, "Your patron cannot support more ghouls on this plane!") + return + + LAZYADD(spooky_scaries, human_target) + log_game("[key_name_admin(human_target)] has become a ghoul, their master is [user.real_name]") + //we change it to true only after we know they passed all the checks + . = TRUE + RegisterSignal(human_target,COMSIG_MOB_DEATH,.proc/remove_ghoul) + human_target.revive(full_heal = TRUE, admin_revive = TRUE) + human_target.setMaxHealth(40) + human_target.health = 40 + human_target.become_husk() + human_target.faction |= "heretics" + var/datum/antagonist/heretic_monster/heretic_monster = human_target.mind.add_antag_datum(/datum/antagonist/heretic_monster) + var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) + heretic_monster.set_owner(master) + return + + +/datum/eldritch_knowledge/flesh_grasp/proc/remove_ghoul(datum/source) + var/mob/living/carbon/human/humie = source + spooky_scaries -= humie + humie.mind.remove_antag_datum(/datum/antagonist/heretic_monster) + UnregisterSignal(source, COMSIG_MOB_DEATH) + +/datum/eldritch_knowledge/flesh_mark + name = "Mark of Flesh" + gain_text = "I saw them, the marked ones. The screams... the silence." + desc = "Your sickly blade now applies a mark of flesh to those cut by it. Once marked, using your Mansus Grasp upon them will cause additional bleeding from the target." + cost = 2 + next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet) + banned_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/ash_mark) + route = PATH_FLESH + +/datum/eldritch_knowledge/flesh_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters) + . = ..() + if(isliving(target)) + var/mob/living/living_target = target + living_target.apply_status_effect(/datum/status_effect/eldritch/flesh) + +/datum/eldritch_knowledge/flesh_blade_upgrade + name = "Bleeding Steel" + gain_text = "It rained blood, that's when I understood the gravekeeper's advice." + desc = "Your blade will now cause additional bleeding to those hit by it." + cost = 2 + next_knowledge = list(/datum/eldritch_knowledge/summon/stalker) + banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/rust_blade_upgrade) + route = PATH_FLESH + +/datum/eldritch_knowledge/flesh_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters) + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/carbon_target = target + var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts) + var/datum/wound/slash/severe/crit_wound = new + crit_wound.apply_wound(bodypart) + +/datum/eldritch_knowledge/summon/raw_prophet + name = "Raw Ritual" + gain_text = "The uncanny man walks alone in the valley, I was able to call his aid." + desc = "You can now summon a Raw Prophet using eyes, a left arm, right arm and a pool of blood using a transmutation circle. Raw prophets have increased seeing range, and can see through walls. They can jaunt long distances, though they are fragile." + cost = 1 + required_atoms = list(/obj/item/organ/eyes,/obj/item/bodypart/l_arm,/obj/item/bodypart/r_arm,/obj/effect/decal/cleanable/blood) + mob_to_summon = /mob/living/simple_animal/hostile/eldritch/raw_prophet + next_knowledge = list(/datum/eldritch_knowledge/flesh_blade_upgrade,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/curse/paralysis) + route = PATH_FLESH + +/datum/eldritch_knowledge/summon/stalker + name = "Lonely Ritual" + gain_text = "I was able to combine my greed and desires to summon an eldritch beast I have not seen before." + desc = "You can now summon a Stalker using a knife, a flower, a pen and a piece of paper using a transmutation circle. Stalkers possess the ability to shapeshift into various forms while assuming the vigor and powers of that form." + cost = 1 + required_atoms = list(/obj/item/kitchen/knife,/obj/item/reagent_containers/food/snacks/grown/poppy,/obj/item/pen,/obj/item/paper) + mob_to_summon = /mob/living/simple_animal/hostile/eldritch/stalker + next_knowledge = list(/datum/eldritch_knowledge/summon/ashy,/datum/eldritch_knowledge/summon/rusty,/datum/eldritch_knowledge/final/flesh_final) + route = PATH_FLESH + +/datum/eldritch_knowledge/summon/ashy + name = "Ashen Ritual" + gain_text = "I combined principle of hunger with desire of destruction. The eyeful lords have noticed me." + desc = "You can now summon an Ashen One by transmuting a pile of ash, a head and a book using a transmutation circle. They possess the ability to jaunt short distances and create a cascade of flames." + cost = 1 + required_atoms = list(/obj/effect/decal/cleanable/ash,/obj/item/bodypart/head,/obj/item/book) + mob_to_summon = /mob/living/simple_animal/hostile/eldritch/ash_spirit + next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/flame_birth) + +/datum/eldritch_knowledge/summon/rusty + name = "Rusted Ritual" + gain_text = "I combined principle of hunger with desire of corruption. The rusted hills call my name." + desc = "You can now summon a Rust Walker transmuting a vomit pool, a head, and a book using a transmutation circle. Rust Walkers possess the ability to spread rust and can fire bolts of rust to further corrode the area." + cost = 1 + required_atoms = list(/obj/effect/decal/cleanable/vomit,/obj/item/bodypart/head,/obj/item/book) + mob_to_summon = /mob/living/simple_animal/hostile/eldritch/rust_spirit + next_knowledge = list(/datum/eldritch_knowledge/summon/stalker,/datum/eldritch_knowledge/spell/entropic_plume) + +/datum/eldritch_knowledge/spell/blood_siphon + name = "Blood Siphon" + gain_text = "Our blood is all the same after all, the owl told me." + desc = "You are granted a spell that drains some of the targets health, and returns it to you. It also has a chance to transfer any wounds you possess onto the target." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/targeted/touch/blood_siphon + next_knowledge = list(/datum/eldritch_knowledge/summon/raw_prophet,/datum/eldritch_knowledge/spell/area_conversion) + +/datum/eldritch_knowledge/final/flesh_final + name = "Priest's Final Hymn" + gain_text = "Man of this world. Hear me! For the time of the lord of arms has come!" + desc = "Bring three corpses to a transmutation rune to either ascend as The Lord of the Night or summon a single Terror of the Night, however you cannot ascend more than once." + required_atoms = list(/mob/living/carbon/human) + cost = 5 + route = PATH_FLESH + +/datum/eldritch_knowledge/final/flesh_final/on_finished_recipe(mob/living/user, list/atoms, loc) + var/alert_ = alert(user,"Do you want to ascend as the lord of the night or just summon a terror of the night?","...","Yes","No") + user.SetImmobilized(10 HOURS) // no way someone will stand 10 hours in a spot, just so he can move while the alert is still showing. + switch(alert_) + if("No") + var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy(loc) + message_admins("[summoned.name] is being summoned by [user.real_name] in [loc]") + var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [summoned.real_name]", ROLE_HERETIC, null, ROLE_HERETIC, 100,summoned) + user.SetImmobilized(0) + if(LAZYLEN(candidates) == 0) + to_chat(user,"No ghost could be found...") + qdel(summoned) + return FALSE + var/mob/dead/observer/ghost_candidate = pick(candidates) + priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for vassal of arms has ascended! Terror of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg') + log_game("[key_name_admin(ghost_candidate)] has taken control of ([key_name_admin(summoned)]).") + summoned.ghostize(FALSE) + summoned.key = ghost_candidate.key + summoned.mind.add_antag_datum(/datum/antagonist/heretic_monster) + var/datum/antagonist/heretic_monster/monster = summoned.mind.has_antag_datum(/datum/antagonist/heretic_monster) + var/datum/antagonist/heretic/master = user.mind.has_antag_datum(/datum/antagonist/heretic) + monster.set_owner(master) + master.ascended = TRUE + if("Yes") + var/mob/living/summoned = new /mob/living/simple_animal/hostile/eldritch/armsy/prime(loc,TRUE,10) + summoned.ghostize(0) + user.SetImmobilized(0) + priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the dark, for king of arms has ascended! Lord of the night has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg') + log_game("[user.real_name] ascended as [summoned.real_name]") + var/mob/living/carbon/carbon_user = user + var/datum/antagonist/heretic/ascension = carbon_user.mind.has_antag_datum(/datum/antagonist/heretic) + ascension.ascended = TRUE + carbon_user.mind.transfer_to(summoned, TRUE) + carbon_user.gib() + + return ..() diff --git a/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm new file mode 100644 index 0000000000..74b3753b69 --- /dev/null +++ b/code/modules/antagonists/eldritch_cult/knowledge/rust_lore.dm @@ -0,0 +1,209 @@ +/datum/eldritch_knowledge/base_rust + name = "Blacksmith's Tale" + desc = "Inducts you into the Path of Rust. Allows you to transmute an eldritch blade with any trash item into a Blade of Rust." + gain_text = "'Let me tell you a story,' The Blacksmith said as he gazed into his rusty blade." + banned_knowledge = list(/datum/eldritch_knowledge/base_ash,/datum/eldritch_knowledge/base_flesh,/datum/eldritch_knowledge/final/ash_final,/datum/eldritch_knowledge/final/flesh_final) + next_knowledge = list(/datum/eldritch_knowledge/rust_fist) + required_atoms = list(/obj/item/melee/sickly_blade,/obj/item/trash) + result_atoms = list(/obj/item/melee/sickly_blade/rust) + cost = 1 + route = PATH_RUST + +/datum/eldritch_knowledge/rust_fist + name = "Grasp of Rust" + desc = "Empowers your Mansus Grasp to deal 500 damage to non-living matter and rust any structure it touches. Destroys already rusted structures." + gain_text = "Rust grows on the ceiling of the mansus." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/rust_regen) + var/rust_force = 500 + var/static/list/blacklisted_turfs = typecacheof(list(/turf/closed,/turf/open/space,/turf/open/lava,/turf/open/chasm,/turf/open/floor/plating/rust)) + route = PATH_RUST + +/datum/eldritch_knowledge/rust_fist/on_mansus_grasp(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(ishuman(target)) + var/mob/living/carbon/human/H = target + var/datum/status_effect/eldritch/E = H.has_status_effect(/datum/status_effect/eldritch/rust) || H.has_status_effect(/datum/status_effect/eldritch/ash) || H.has_status_effect(/datum/status_effect/eldritch/flesh) + if(E) + E.on_effect() + H.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_EARS,ORGAN_SLOT_EYES,ORGAN_SLOT_LIVER,ORGAN_SLOT_LUNGS,ORGAN_SLOT_STOMACH,ORGAN_SLOT_HEART),25) + target.rust_heretic_act() + target.emp_act(EMP_HEAVY) + return TRUE + +/datum/eldritch_knowledge/spell/area_conversion + name = "Aggressive Spread" + desc = "Spreads rust to nearby turfs. Destroys already rusted walls." + gain_text = "All wise men know not to touch the bound king." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/aoe_turf/rust_conversion + next_knowledge = list(/datum/eldritch_knowledge/rust_blade_upgrade,/datum/eldritch_knowledge/curse/corrosion,/datum/eldritch_knowledge/spell/blood_siphon,/datum/eldritch_knowledge/spell/rust_wave) + route = PATH_RUST + +/datum/eldritch_knowledge/spell/rust_wave + name = "Patron's Reach" + desc = "You can now send a bolt of rust that corrupts the immediate area, and poisons the first target hit." + gain_text = "Messengers of hope fear the rustbringer." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/aimed/rust_wave + route = PATH_RUST + +/datum/eldritch_knowledge/rust_regen + name = "Leeching Walk" + desc = "Passively heals you when you are on rusted tiles." + gain_text = "'The strength was unparalleled, unnatural.' The Blacksmith was smiling." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/rust_mark,/datum/eldritch_knowledge/armor,/datum/eldritch_knowledge/essence) + route = PATH_RUST + +/datum/eldritch_knowledge/rust_regen/on_life(mob/user) + . = ..() + var/turf/user_loc_turf = get_turf(user) + if(!istype(user_loc_turf, /turf/open/floor/plating/rust) || !isliving(user)) + return + var/mob/living/living_user = user + living_user.adjustBruteLoss(-3, FALSE) + living_user.adjustFireLoss(-3, FALSE) + living_user.adjustToxLoss(-3, FALSE) + living_user.adjustOxyLoss(-1, FALSE) + living_user.adjustStaminaLoss(-6) + +/datum/eldritch_knowledge/rust_mark + name = "Mark of Rust" + desc = "Your eldritch blade now applies a rust mark. Rust marks have a chance to deal between 0 to 200 damage to 75% of enemies items. To activate the mark use your Mansus Grasp on it." + gain_text = "Lords of the depths help those in dire need at a cost." + cost = 2 + next_knowledge = list(/datum/eldritch_knowledge/spell/area_conversion) + banned_knowledge = list(/datum/eldritch_knowledge/ash_mark,/datum/eldritch_knowledge/flesh_mark) + route = PATH_RUST + +/datum/eldritch_knowledge/rust_mark/on_eldritch_blade(target,user,proximity_flag,click_parameters) + . = ..() + if(isliving(target)) + var/mob/living/living_target = target + living_target.apply_status_effect(/datum/status_effect/eldritch/rust) + +/datum/eldritch_knowledge/rust_blade_upgrade + name = "Toxic Steel" + gain_text = "Let the blade guide you through the flesh." + desc = "Your blade of choice will now add toxin to enemies bloodstream." + cost = 2 + next_knowledge = list(/datum/eldritch_knowledge/spell/entropic_plume) + banned_knowledge = list(/datum/eldritch_knowledge/ash_blade_upgrade,/datum/eldritch_knowledge/flesh_blade_upgrade) + route = PATH_RUST + +/datum/eldritch_knowledge/rust_blade_upgrade/on_eldritch_blade(target,user,proximity_flag,click_parameters) + . = ..() + if(iscarbon(target)) + var/mob/living/carbon/carbon_target = target + carbon_target.reagents.add_reagent(/datum/reagent/eldritch, 5) + +/datum/eldritch_knowledge/spell/entropic_plume + name = "Entropic Plume" + desc = "You can now send a befuddling plume that blinds, poisons and makes enemies strike each other, while also converting the immediate area into rust." + gain_text = "Messengers of hope fear the rustbringer." + cost = 1 + spell_to_add = /obj/effect/proc_holder/spell/cone/staggered/entropic_plume + next_knowledge = list(/datum/eldritch_knowledge/final/rust_final,/datum/eldritch_knowledge/spell/cleave,/datum/eldritch_knowledge/summon/rusty) + route = PATH_RUST + +/datum/eldritch_knowledge/armor + name = "Armorer's Ritual" + desc = "You can now create eldritch armor using a built table and a gas mask on top of a transmutation rune." + gain_text = "For I am the heir to the throne of doom." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/flesh_ghoul) + required_atoms = list(/obj/structure/table,/obj/item/clothing/mask/gas) + result_atoms = list(/obj/item/clothing/suit/hooded/cultrobes/eldritch) + +/datum/eldritch_knowledge/essence + name = "Priest's Ritual" + desc = "You can now transmute a tank of water into a bottle of eldritch fluid." + gain_text = "This is an old recipe, i got it from an owl." + cost = 1 + next_knowledge = list(/datum/eldritch_knowledge/rust_regen,/datum/eldritch_knowledge/spell/ashen_shift) + required_atoms = list(/obj/structure/reagent_dispensers/watertank) + result_atoms = list(/obj/item/reagent_containers/glass/beaker/eldritch) + +/datum/eldritch_knowledge/final/rust_final + name = "Rustbringer's Oath" + desc = "Bring three corpses onto a transmutation rune. After you finish the ritual, rust will now automatically spread from the rune. Your healing on rust is also tripled, while you become more resilient overall." + gain_text = "Champion of rust. Corruptor of steel. Fear the dark for Rustbringer has come!" + cost = 5 + required_atoms = list(/mob/living/carbon/human) + route = PATH_RUST + +/datum/eldritch_knowledge/final/rust_final/on_finished_recipe(mob/living/user, list/atoms, loc) + var/mob/living/carbon/human/H = user + H.physiology.brute_mod *= 0.5 + H.physiology.burn_mod *= 0.5 + priority_announce("$^@&#*$^@(#&$(@&#^$&#^@# Fear the decay, for Rustbringer [user.real_name] has come! $^@&#*$^@(#&$(@&#^$&#^@#","#$^@&#*$^@(#&$(@&#^$&#^@#", 'sound/announcer/classic/spanomalies.ogg') + new /datum/rust_spread(loc) + var/datum/antagonist/heretic/ascension = H.mind.has_antag_datum(/datum/antagonist/heretic) + ascension.ascended = TRUE + return ..() + + +/datum/eldritch_knowledge/final/rust_final/on_life(mob/user) + . = ..() + if(!finished) + return + var/mob/living/carbon/human/human_user = user + human_user.adjustBruteLoss(-6, FALSE) + human_user.adjustFireLoss(-6, FALSE) + human_user.adjustToxLoss(-6, FALSE) + human_user.adjustOxyLoss(-6, FALSE) + human_user.adjustStaminaLoss(-20) + + +/** + * #Rust spread datum + * + * Simple datum that automatically spreads rust around it + * + * Simple implementation of automatically growing entity + */ +/datum/rust_spread + var/list/edge_turfs = list() + var/list/turfs = list() + var/static/list/blacklisted_turfs = typecacheof(list(/turf/open/indestructible,/turf/closed/indestructible,/turf/open/space,/turf/open/lava,/turf/open/chasm)) + var/spread_per_tick = 6 + + +/datum/rust_spread/New(loc) + . = ..() + var/turf/turf_loc = get_turf(loc) + turf_loc.rust_heretic_act() + turfs += turf_loc + START_PROCESSING(SSprocessing,src) + + +/datum/rust_spread/Destroy(force, ...) + STOP_PROCESSING(SSprocessing,src) + return ..() + +/datum/rust_spread/process() + compile_turfs() + var/turf/T + for(var/i in 0 to spread_per_tick) + T = pick(edge_turfs) + T.rust_heretic_act() + turfs += get_turf(T) + +/** + * Compile turfs + * + * Recreates all edge_turfs as well as normal turfs. + */ +/datum/rust_spread/proc/compile_turfs() + edge_turfs = list() + for(var/X in turfs) + if(!istype(X,/turf/closed/wall/rust) && !istype(X,/turf/closed/wall/r_wall/rust) && !istype(X,/turf/open/floor/plating/rust)) + turfs -=X + continue + for(var/turf/T in range(1,X)) + if(T in turfs) + continue + if(is_type_in_typecache(T,blacklisted_turfs)) + continue + edge_turfs += T diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm index 1d773627c7..295616d052 100644 --- a/code/modules/antagonists/ert/ert.dm +++ b/code/modules/antagonists/ert/ert.dm @@ -12,6 +12,7 @@ var/list/name_source threat = -5 show_in_antagpanel = FALSE + show_to_ghosts = TRUE antag_moodlet = /datum/mood_event/focused /datum/antagonist/ert/on_gain() diff --git a/code/modules/antagonists/monkey/monkey.dm b/code/modules/antagonists/monkey/monkey.dm index ebb39c814e..971532958f 100644 --- a/code/modules/antagonists/monkey/monkey.dm +++ b/code/modules/antagonists/monkey/monkey.dm @@ -9,6 +9,7 @@ roundend_category = "monkeys" antagpanel_category = "Monkey" threat = 3 + show_to_ghosts = TRUE var/datum/team/monkey/monkey_team var/monkey_only = TRUE diff --git a/code/modules/antagonists/nightmare/nightmare.dm b/code/modules/antagonists/nightmare/nightmare.dm index 837b6e4216..f5b10de5c2 100644 --- a/code/modules/antagonists/nightmare/nightmare.dm +++ b/code/modules/antagonists/nightmare/nightmare.dm @@ -3,3 +3,4 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE threat = 5 + show_to_ghosts = TRUE diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm index 2615822dd8..414f7dd6b0 100644 --- a/code/modules/antagonists/ninja/ninja.dm +++ b/code/modules/antagonists/ninja/ninja.dm @@ -3,6 +3,7 @@ antagpanel_category = "Ninja" job_rank = ROLE_NINJA show_name_in_check_antagonists = TRUE + show_to_ghosts = TRUE antag_moodlet = /datum/mood_event/focused threat = 8 var/helping_station = FALSE diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm index a11ecaa3df..a18906b70b 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm @@ -8,13 +8,12 @@ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF var/timer_set = 90 - var/default_timer_set = 90 var/minimum_timer_set = 90 var/maximum_timer_set = 3600 - ui_style = "nanotrasen" var/numeric_input = "" var/ui_mode = NUKEUI_AWAIT_DISK + var/timing = FALSE var/exploding = FALSE var/exploded = FALSE @@ -31,7 +30,6 @@ var/interior = "" var/proper_bomb = TRUE //Please var/obj/effect/countdown/nuclearbomb/countdown - var/nuclear_cooldown //used to stop global spam. /obj/machinery/nuclearbomb/Initialize() . = ..() @@ -74,15 +72,16 @@ /obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station) var/datum/game_mode/nuclear/NM = SSticker.mode switch(off_station) - if(FALSE) + if(0) if(istype(NM) && !NM.nuke_team.syndies_escaped()) return CINEMATIC_ANNIHILATION else return CINEMATIC_NUKE_WIN - if(NUKE_MISS_STATION) + if(1) return CINEMATIC_NUKE_MISS - else + if(2) return CINEMATIC_NUKE_FAR + return CINEMATIC_NUKE_FAR /obj/machinery/nuclearbomb/proc/disk_check(obj/item/disk/nuclear/D) if(D.fake) @@ -191,7 +190,7 @@ icon_state = "nuclearbomb_exploding" /obj/machinery/nuclearbomb/update_overlays() - . = ..() + . += ..() update_icon_interior() update_icon_lights() @@ -233,7 +232,7 @@ explode() else var/volume = (get_time_left() <= 20 ? 30 : 5) - playsound(loc, 'sound/items/timer.ogg', volume, 0) + playsound(loc, 'sound/items/timer.ogg', volume, FALSE) /obj/machinery/nuclearbomb/proc/update_ui_mode() if(exploded) @@ -258,18 +257,18 @@ ui_mode = NUKEUI_AWAIT_TIMER - -/obj/machinery/nuclearbomb/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) +/obj/machinery/nuclearbomb/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "nuclear_bomb", name, 350, 442, master_ui, state) - ui.set_style(ui_style) + ui = new(user, src, "NuclearBomb", name) ui.open() /obj/machinery/nuclearbomb/ui_data(mob/user) var/list/data = list() data["disk_present"] = auth + var/hidden_code = (ui_mode == NUKEUI_AWAIT_CODE && numeric_input != "ERROR") + var/current_code = "" if(hidden_code) while(length(current_code) < length(numeric_input)) @@ -386,14 +385,13 @@ if("anchor") if(auth && yes_code) playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - set_anchor(usr) + set_anchor() else playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) - -/obj/machinery/nuclearbomb/proc/set_anchor(mob/user) - if((istype(get_area(src), /area/space) || isinspace()) && !anchored) - to_chat(user, "This is not a suitable platform for anchoring [src]!") +/obj/machinery/nuclearbomb/proc/set_anchor() + if(isinspace() && !anchored) + to_chat(usr, "There is nothing to anchor to!") else anchored = !anchored @@ -414,9 +412,6 @@ if(safety) to_chat(usr, "The safety is still on.") return - if(!timing && nuclear_cooldown > world.time) - to_chat(usr, "[src]'s timer protocols are currently on cooldown, please stand by.") - return timing = !timing if(timing) previous_level = NUM2SECLEVEL(GLOB.security_level) @@ -425,12 +420,6 @@ S.switch_mode_to(TRACK_INFILTRATOR) countdown.start() set_security_level("delta") - nuclear_cooldown = world.time + 15 SECONDS - - if(GLOB.war_declared) - var/area/A = get_area(src) - priority_announce("Alert: Unexpected increase in radiation levels near [A.name] ([src.x],[src.y],[src.z]). Please send an authorized radiation specialist to investigate.", "Sensory Nuclear Indexer Telemetry Calculation Helper") - else detonation_timer = null set_security_level(previous_level) @@ -481,12 +470,19 @@ var/off_station = FALSE var/turf/bomb_location = get_turf(src) - if(!bomb_location || !is_station_level(bomb_location.z)) - off_station = NUKE_MISS_STATION + var/area/A = get_area(bomb_location) + + if(bomb_location && is_station_level(bomb_location.z)) + if(istype(A, /area/space)) + off_station = NUKE_NEAR_MISS + if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE))) + off_station = NUKE_NEAR_MISS else if(bomb_location.onSyndieBase()) off_station = NUKE_SYNDICATE_BASE + else + off_station = NUKE_MISS_STATION - if(!off_station) + if(off_station < 2) //can only launch when nuke is on syndie base or space SSshuttle.registerHostileEnvironment(src) SSshuttle.lockdown = TRUE @@ -500,13 +496,13 @@ INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel, z) /obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station) - if(!off_station) + if(off_station < 2) return CINEMATIC_SELFDESTRUCT else return CINEMATIC_SELFDESTRUCT_MISS /obj/machinery/nuclearbomb/beer - name = "Nanotrasen-brand nuclear fission explosive" + name = "\improper Nanotrasen-brand nuclear fission explosive" desc = "One of the more successful achievements of the Nanotrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devastatingly effective. Signs explain that though this particular device has been decommissioned, every Nanotrasen station is equipped with an equivalent one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back." proper_bomb = FALSE var/obj/structure/reagent_dispensers/beerkeg/keg @@ -519,9 +515,9 @@ /obj/machinery/nuclearbomb/beer/examine(mob/user) . = ..() if(keg.reagents.total_volume) - . += "It has [keg.reagents.total_volume] unit\s left." + to_chat(user, "It has [keg.reagents.total_volume] unit\s left.") else - . += "It's empty." + to_chat(user, "It's empty.") /obj/machinery/nuclearbomb/beer/attackby(obj/item/W, mob/user, params) if(W.is_refillable()) @@ -533,6 +529,8 @@ return ..() /obj/machinery/nuclearbomb/beer/actually_explode() + //Unblock roundend, we're not actually exploding. + SSticker.roundend_check_paused = FALSE var/turf/bomb_location = get_turf(src) if(!bomb_location) disarm() @@ -581,7 +579,7 @@ This is here to make the tiles around the station mininuke change when it's armed. */ -/obj/machinery/nuclearbomb/selfdestruct/set_anchor(mob/user) +/obj/machinery/nuclearbomb/selfdestruct/set_anchor() return /obj/machinery/nuclearbomb/selfdestruct/set_active() @@ -639,18 +637,19 @@ This is here to make the tiles around the station mininuke change when it's arme if(newturf && lastlocation == newturf) if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.0001)) var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control - if(istype(loneop)) + if(istype(loneop) && loneop.occurrences < loneop.max_occurrences) loneop.weight += 1 - if(loneop.weight % 5 == 0) + if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1) //players count now message_admins("[src] is stationary in [ADMIN_VERBOSEJMP(newturf)]. The weight of Lone Operative is now [loneop.weight].") log_game("[src] is stationary for too long in [loc_name(newturf)], and has increased the weight of the Lone Operative event to [loneop.weight].") + else lastlocation = newturf last_disk_move = world.time var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control - if(istype(loneop) && prob(loneop.weight)) + if(istype(loneop) && loneop.occurrences < loneop.max_occurrences && prob(loneop.weight)) loneop.weight = max(loneop.weight - 1, 0) - if(loneop.weight % 5 == 0) + if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1) message_admins("[src] is on the move (currently in [ADMIN_VERBOSEJMP(newturf)]). The weight of Lone Operative is now [loneop.weight].") log_game("[src] being on the move has reduced the weight of the Lone Operative event to [loneop.weight].") @@ -659,9 +658,19 @@ This is here to make the tiles around the station mininuke change when it's arme if(!fake) return - if(isobserver(user) || HAS_TRAIT(user, TRAIT_DISK_VERIFIER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER))) + if(isobserver(user) || HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER)) . += "The serial numbers on [src] are incorrect." +/* + * You can't accidentally eat the nuke disk, bro + */ + /* +/obj/item/disk/nuclear/on_accidental_consumption(mob/living/carbon/M, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE) + M.visible_message("[M] looks like [M.p_theyve()] just bitten into something important.", \ + "Wait, is this the nuke disk?") + + return discover_after +*/ /obj/item/disk/nuclear/attackby(obj/item/I, mob/living/user, params) if(istype(I, /obj/item/claymore/highlander) && !fake) var/obj/item/claymore/highlander/H = I @@ -684,7 +693,7 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/suicide_act(mob/user) user.visible_message("[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!") - playsound(src, 'sound/machines/alarm.ogg', 50, -1, 1) + playsound(src, 'sound/machines/alarm.ogg', 50, -1, TRUE) for(var/i in 1 to 100) addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i) addtimer(CALLBACK(src, .proc/manual_suicide, user), 101) @@ -692,7 +701,7 @@ This is here to make the tiles around the station mininuke change when it's arme /obj/item/disk/nuclear/proc/manual_suicide(mob/living/user) user.remove_atom_colour(ADMIN_COLOUR_PRIORITY) - user.visible_message("[user] was destroyed by the nuclear blast!") + user.visible_message("[user] is destroyed by the nuclear blast!") user.adjustOxyLoss(200) user.death(0) diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index 454cde6d72..652b19a8e7 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -6,6 +6,7 @@ antag_moodlet = /datum/mood_event/focused threat = 10 skill_modifiers = list(/datum/skill_modifier/job/level/wiring) + show_to_ghosts = TRUE 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/official/official.dm b/code/modules/antagonists/official/official.dm index 1d340253c4..1ec64cb2b6 100644 --- a/code/modules/antagonists/official/official.dm +++ b/code/modules/antagonists/official/official.dm @@ -4,6 +4,7 @@ show_in_antagpanel = FALSE var/datum/objective/mission var/datum/team/ert/ert_team + show_to_ghosts = TRUE /datum/antagonist/official/greet() to_chat(owner, "You are a CentCom Official.") diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm index 01f3c6068e..e6d350064d 100644 --- a/code/modules/antagonists/pirate/pirate.dm +++ b/code/modules/antagonists/pirate/pirate.dm @@ -4,6 +4,7 @@ roundend_category = "space pirates" antagpanel_category = "Pirate" threat = 5 + show_to_ghosts = TRUE var/datum/team/pirate/crew /datum/antagonist/pirate/greet() diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index e06e8691b3..848fe124be 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -28,6 +28,7 @@ throwforce = 0 blood_volume = 0 has_field_of_vision = FALSE //we are a spoopy ghost + rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE @@ -107,11 +108,12 @@ mind.add_antag_datum(/datum/antagonist/revenant) //Life, Stat, Hud Updates, and Say -/mob/living/simple_animal/revenant/Life() +/mob/living/simple_animal/revenant/Life(seconds, times_fired) + . = ..() if(stasis) return if(revealed && essence <= 0) - death() + INVOKE_ASYNC(src, .proc/death) if(unreveal_time && world.time >= unreveal_time) unreveal_time = 0 revealed = FALSE @@ -120,14 +122,13 @@ to_chat(src, "You are once more concealed.") if(unstun_time && world.time >= unstun_time) unstun_time = 0 - notransform = FALSE + mob_transforming = FALSE to_chat(src, "You can move again!") if(essence_regenerating && !inhibited && essence < essence_regen_cap) //While inhibited, essence will not regenerate essence = min(essence_regen_cap, essence+essence_regen_amount) update_action_buttons_icon() //because we update something required by our spells in life, we need to update our buttons update_spooky_icon() update_health_hud() - ..() /mob/living/simple_animal/revenant/Stat() ..() @@ -218,7 +219,7 @@ return 0 stasis = TRUE to_chat(src, "NO! No... it's too late, you can feel your essence [pick("breaking apart", "drifting away")]...") - notransform = TRUE + mob_transforming = TRUE revealed = TRUE invisibility = 0 playsound(src, 'sound/effects/screech.ogg', 100, 1) @@ -260,7 +261,7 @@ return if(time <= 0) return - notransform = TRUE + mob_transforming = TRUE if(!unstun_time) to_chat(src, "You cannot move!") unstun_time = world.time + time @@ -271,7 +272,7 @@ /mob/living/simple_animal/revenant/proc/update_spooky_icon() if(revealed) - if(notransform) + if(mob_transforming) if(draining) icon_state = icon_drain else @@ -320,7 +321,7 @@ /mob/living/simple_animal/revenant/proc/death_reset() revealed = FALSE unreveal_time = 0 - notransform = 0 + mob_transforming = 0 unstun_time = 0 inhibited = FALSE draining = FALSE diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm index 2d84ed7c22..7a2f661fd9 100644 --- a/code/modules/antagonists/revenant/revenant_abilities.dm +++ b/code/modules/antagonists/revenant/revenant_abilities.dm @@ -17,6 +17,7 @@ //Harvest; activated ly clicking the target, will try to drain their essence. /mob/living/simple_animal/revenant/proc/Harvest(mob/living/carbon/human/target) + set waitfor = FALSE if(!castcheck(0)) return if(draining) diff --git a/code/modules/antagonists/revenant/revenant_antag.dm b/code/modules/antagonists/revenant/revenant_antag.dm index 46c1176533..c93291797a 100644 --- a/code/modules/antagonists/revenant/revenant_antag.dm +++ b/code/modules/antagonists/revenant/revenant_antag.dm @@ -3,6 +3,7 @@ show_in_antagpanel = FALSE show_name_in_check_antagonists = TRUE threat = 5 + show_to_ghosts = TRUE /datum/antagonist/revenant/greet() owner.announce_objectives() diff --git a/code/modules/antagonists/santa/santa.dm b/code/modules/antagonists/santa/santa.dm index f58a21ba42..ff7dae98f6 100644 --- a/code/modules/antagonists/santa/santa.dm +++ b/code/modules/antagonists/santa/santa.dm @@ -1,6 +1,8 @@ /datum/antagonist/santa name = "Santa" show_in_antagpanel = FALSE + show_name_in_check_antagonists = TRUE + show_to_ghosts = TRUE /datum/antagonist/santa/on_gain() . = ..() diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 6b063559dc..d1db363b04 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -16,6 +16,7 @@ icon_state = "daemon" icon_living = "daemon" mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + mob_size = MOB_SIZE_LARGE speed = 1 a_intent = INTENT_HARM stop_automated_movement = 1 @@ -34,8 +35,11 @@ healable = 0 environment_smash = ENVIRONMENT_SMASH_STRUCTURES obj_damage = 50 - melee_damage_lower = 30 - melee_damage_upper = 30 + melee_damage_lower = 22.5 // reduced from 30 to 22.5 with wounds since they get big buffs to slicing wounds + melee_damage_upper = 22.5 + wound_bonus = -10 + bare_wound_bonus = 0 + sharpness = SHARP_EDGED see_in_dark = 8 blood_volume = 0 //No bleeding on getting shot, for skeddadles lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE @@ -43,13 +47,25 @@ var/playstyle_string = "You are a slaughter demon, a terrible creature from another realm. You have a single desire: To kill. \ You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and disappearing from the station at will. \ Pulling a dead or unconscious mob while you enter a pool will pull them in with you, allowing you to feast and regain your health. \ - You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. " + You move quickly upon leaving a pool of blood, but the material world will soon sap your strength and leave you sluggish. \ + You gain strength the more attacks you land on live humanoids, though this resets when you return to the blood zone. You can also \ + launch a devastating slam attack with ctrl+shift+click, capable of smashing bones in one strike." loot = list(/obj/effect/decal/cleanable/blood, \ /obj/effect/decal/cleanable/blood/innards, \ /obj/item/organ/heart/demon) del_on_death = 1 deathmessage = "screams in anger as it collapses into a puddle of viscera!" + // How long it takes for the alt-click slam attack to come off cooldown + var/slam_cooldown_time = 45 SECONDS + // The actual instance var for the cooldown + var/slam_cooldown = 0 + // How many times we have hit humanoid targets since we last bloodcrawled, scaling wounding power + var/current_hitstreak = 0 + // How much both our wound_bonus and bare_wound_bonus go up per hitstreak hit + var/wound_bonus_per_hit = 5 + // How much our wound_bonus hitstreak bonus caps at (peak demonry) + var/wound_bonus_hitstreak_max = 12 /mob/living/simple_animal/slaughter/Initialize() ..() @@ -58,6 +74,33 @@ if(istype(loc, /obj/effect/dummy/phased_mob/slaughter)) bloodspell.phased = TRUE +/mob/living/simple_animal/slaughter/CtrlShiftClickOn(atom/A) + if(!isliving(A)) + return ..() + if(slam_cooldown + slam_cooldown_time > world.time) + to_chat(src, "Your slam ability is still on cooldown!") + return + + face_atom(A) + var/mob/living/victim = A + victim.take_bodypart_damage(brute=20, wound_bonus=wound_bonus) // don't worry, there's more punishment when they hit something + visible_message("[src] slams into [victim] with monstrous strength!", "You slam into [victim] with monstrous strength!", ignored_mobs=victim) + to_chat(victim, "[src] slams into you with monstrous strength, sending you flying like a ragdoll!") + var/turf/yeet_target = get_edge_target_turf(victim, dir) + victim.throw_at(yeet_target, 10, 5, src) + slam_cooldown = world.time + log_combat(src, victim, "slaughter slammed") + +/mob/living/simple_animal/slaughter/UnarmedAttack(atom/A, proximity) + if(iscarbon(A)) + var/mob/living/carbon/target = A + if(target.stat != DEAD && target.mind && current_hitstreak < wound_bonus_hitstreak_max) + current_hitstreak++ + wound_bonus += wound_bonus_per_hit + bare_wound_bonus += wound_bonus_per_hit + + return ..() + /obj/effect/decal/cleanable/blood/innards icon = 'icons/obj/surgery.dmi' name = "pile of viscera" diff --git a/code/modules/antagonists/slaughter/slaughter_antag.dm b/code/modules/antagonists/slaughter/slaughter_antag.dm index 04f7167fa5..d6d504ef8e 100644 --- a/code/modules/antagonists/slaughter/slaughter_antag.dm +++ b/code/modules/antagonists/slaughter/slaughter_antag.dm @@ -6,6 +6,7 @@ threat = 10 job_rank = ROLE_ALIEN show_in_antagpanel = FALSE + show_to_ghosts = TRUE /datum/antagonist/slaughter/on_gain() forge_objectives() @@ -14,6 +15,7 @@ /datum/antagonist/slaughter/greet() . = ..() owner.announce_objectives() + to_chat(owner, "You have a powerful alt-attack that slams people backwards that you can activate by shift+ctrl+clicking your target!") /datum/antagonist/slaughter/proc/forge_objectives() if(summoner) diff --git a/code/modules/antagonists/survivalist/survivalist.dm b/code/modules/antagonists/survivalist/survivalist.dm index 04ad53f65b..296369fe3b 100644 --- a/code/modules/antagonists/survivalist/survivalist.dm +++ b/code/modules/antagonists/survivalist/survivalist.dm @@ -23,6 +23,18 @@ /datum/antagonist/survivalist/guns greet_message = "Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, and don't let anyone take them!" +/datum/antagonist/survivalist/guns/forge_objectives() + var/datum/objective/steal_five_of_type/summon_guns/guns = new + guns.owner = owner + objectives += guns + ..() + /datum/antagonist/survivalist/magic name = "Amateur Magician" greet_message = "This magic stuff is... so powerful. You want more. More! They want your power. They can't have it! Don't let them have it!" + +/datum/antagonist/survivalist/magic/forge_objectives() + var/datum/objective/steal_five_of_type/summon_magic/magic = new + magic.owner = owner + objectives += magic + ..() diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm index d0e36394ab..305c4fadb7 100644 --- a/code/modules/antagonists/swarmer/swarmer.dm +++ b/code/modules/antagonists/swarmer/swarmer.dm @@ -36,7 +36,7 @@ if(A) notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE) -/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user) +/obj/effect/mob_spawn/swarmer/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -70,7 +70,6 @@ icon_living = "swarmer" icon_dead = "swarmer_unactivated" icon_gib = null - threat = 0.5 wander = 0 harm_intent_damage = 5 minbodytemp = 0 @@ -158,10 +157,11 @@ face_atom(A) if(!isturf(loc)) return - if(next_move > world.time) + if(!CheckActionCooldown()) return if(!A.Adjacent(src)) return + DelayNextAction() A.swarmer_act(src) /atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) @@ -399,13 +399,13 @@ return FALSE /obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) - . = ..() var/turf/here = get_turf(src) for(var/A in here.contents) var/obj/structure/cable/C = A if(istype(C)) to_chat(S, "Disrupting the power grid would bring no benefit to us. Aborting.") return FALSE + return ..() /obj/item/deactivated_swarmer/IntegrateAmount() return 50 @@ -486,7 +486,7 @@ var/obj/O = target if(O.resistance_flags & INDESTRUCTIBLE) return FALSE - for(var/mob/living/L in GetAllContents()) + for(var/mob/living/L in target.GetAllContents()) if(!ispAI(L) && !isbrain(L)) to_chat(src, "An organism has been detected inside this object. Aborting.") return FALSE @@ -497,7 +497,7 @@ if(resource_gain) resources += resource_gain do_attack_animation(target) - changeNext_move(CLICK_CD_MELEE) + DelayNextAction(CLICK_CD_MELEE) var/obj/effect/temp_visual/swarmer/integrate/I = new /obj/effect/temp_visual/swarmer/integrate(get_turf(target)) I.pixel_x = target.pixel_x I.pixel_y = target.pixel_y @@ -517,10 +517,9 @@ /mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(atom/movable/target) new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target)) do_attack_animation(target) - changeNext_move(CLICK_CD_MELEE) + DelayNextAction(CLICK_CD_MELEE) target.ex_act(EXPLODE_LIGHT) - /mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(mob/living/target) if(target == src) return diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm index 19144d67c9..ff012e556a 100644 --- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm +++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm @@ -167,10 +167,10 @@ return if(last_man_standing) if(syndicate) - to_chat(owner.current," All the loyalist agents are dead, and no more is required of you. Die a glorious death, agent. ") + to_chat(owner.current,"All the suspected agents are dead, and no more is required of you. Die a glorious death, agent.") + replace_escape_objective(owner) else - to_chat(owner.current," All the other agents are dead, and you're the last loose end. Stage a Syndicate terrorist attack to cover up for today's events. You no longer have any limits on collateral damage.") - replace_escape_objective(owner) + to_chat(owner.current,"All the other agents are dead. You have done us all a great service and shall be honorably exiled upon returning to base.") /datum/antagonist/traitor/internal_affairs/proc/iaa_process() if(owner&&owner.current&&owner.current.stat!=DEAD) @@ -193,7 +193,7 @@ if(syndicate) fail_msg += " You no longer have permission to die. " else - fail_msg += " The truth could still slip out!
    Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated." + fail_msg += " The truth could still slip out! Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to great shame." reinstate_escape_objective(owner) last_man_standing = FALSE to_chat(owner.current, fail_msg) @@ -226,18 +226,20 @@ add_objective(escape_objective) /datum/antagonist/traitor/internal_affairs/proc/greet_iaa() - var/crime = pick("distribution of contraband" , "unauthorized erotic action on duty", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence") + var/crime = pick("distribution of contraband" , "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence") to_chat(owner.current, "You are the [special_role].") if(syndicate) - to_chat(owner.current, "Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.") - to_chat(owner.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.") - to_chat(owner.current, " You have been provided with a standard uplink to accomplish your task. ") - to_chat(owner.current, "By no means reveal that you, or any other NT employees, are undercover agents.") + to_chat(owner.current, "GREAT LEADER IS DEAD. NANOTRASEN MUST FALL.") + to_chat(owner.current, "Your have infiltrated this vessel to cause chaos and assassinate targets known to have conspired against the Syndicate.") + to_chat(owner.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.") + to_chat(owner.current, "You have been provided with a standard uplink to accomplish your task. ") + to_chat(owner.current, "By no means reveal that you are a Syndicate agent. By no means reveal that your targets are being hunted.") else - to_chat(owner.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.") - to_chat(owner.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.") - to_chat(owner.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.") + to_chat(owner.current, "CAUTION: Your legal status as a citizen of NanoTrasen will be permanently revoked upon completion of your first contract.") + to_chat(owner.current, "Your target has been suspected of [crime], and must be removed from this plane.") + to_chat(owner.current, "While you have a license to kill, you are to eliminate your targets with no collateral or unrelated deaths.") + to_chat(owner.current, "For the sake of plausable deniability, you have been equipped with captured Syndicate equipment via uplink.") to_chat(owner.current, "By no means reveal that you, or any other NT employees, are undercover agents.") to_chat(owner.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.") diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm index 6616eea006..8e9a54a69a 100644 --- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm +++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm @@ -257,6 +257,8 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list( return if (active) return //prevent the AI from activating an already active doomsday + if (owner_AI.shunted) + return //prevent AI from activating doomsday while shunted. active = TRUE set_us_up_the_bomb(owner) diff --git a/code/modules/antagonists/traitor/equipment/contractor.dm b/code/modules/antagonists/traitor/equipment/contractor.dm index 6c5d5766e4..94a3059b5f 100644 --- a/code/modules/antagonists/traitor/equipment/contractor.dm +++ b/code/modules/antagonists/traitor/equipment/contractor.dm @@ -1,4 +1,4 @@ -// Support unit gets it's own very basic antag datum for admin logging. +/// Support unit gets it's own very basic antag datum for admin logging. /datum/antagonist/traitor/contractor_support name = "Contractor Support Unit" antag_moodlet = /datum/mood_event/focused @@ -8,11 +8,13 @@ should_equip = FALSE /// Don't give them an uplink. var/datum/team/contractor_team/contractor_team -/datum/team/contractor_team // Team for storing both the contractor and their support unit - only really for the HUD and admin logging. +/// Team for storing both the contractor and their support unit - only really for the HUD and admin logging. +/datum/team/contractor_team show_roundend_report = FALSE /datum/antagonist/traitor/contractor_support/forge_traitor_objectives() var/datum/objective/generic_objective = new + generic_objective.name = "Follow Contractor's Orders" generic_objective.explanation_text = "Follow your orders. Assist agents in this mission area." generic_objective.completed = TRUE @@ -25,7 +27,9 @@ var/static/list/contractor_items = typecacheof(/datum/contractor_item/, TRUE) var/datum/syndicate_contract/current_contract var/list/datum/syndicate_contract/assigned_contracts = list() + var/list/assigned_targets = list() // used as a blacklist to make sure we're not assigning targets already assigned + var/contracts_completed = 0 var/contract_TC_payed_out = 0 // Keeping track for roundend reporting var/contract_TC_to_redeem = 0 // Used internally and roundend reporting - what TC we have available to cashout. @@ -34,7 +38,8 @@ var/datum/contractor_item/contractor_item = new path hub_items.Add(contractor_item) -/datum/contractor_hub/proc/create_contracts(datum/mind/owner) // 6 initial contracts +/datum/contractor_hub/proc/create_contracts(datum/mind/owner) + // 6 initial contracts var/list/to_generate = list( CONTRACT_PAYOUT_LARGE, CONTRACT_PAYOUT_MEDIUM, @@ -44,61 +49,74 @@ CONTRACT_PAYOUT_SMALL ) - var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount + //What the fuck + if(length(to_generate) > length(GLOB.data_core.locked)) + to_generate.Cut(1, length(GLOB.data_core.locked)) + // We don't want the sum of all the payouts to be under this amount + var/lowest_TC_threshold = 30 + var/total = 0 var/lowest_paying_sum = 0 var/datum/syndicate_contract/lowest_paying_contract - to_generate = shuffle(to_generate) // Randomise order, so we don't have contracts always in payout order. - var/start_index = 1 // Support contract generation happening multiple times - if(assigned_contracts.len != 0) + // Randomise order, so we don't have contracts always in payout order. + to_generate = shuffle(to_generate) + // Support contract generation happening multiple times + var/start_index = 1 + if (assigned_contracts.len != 0) start_index = assigned_contracts.len + 1 - for(var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying. + // Generate contracts, and find the lowest paying. + for (var/i = 1; i <= to_generate.len; i++) var/datum/syndicate_contract/contract_to_add = new(owner, assigned_targets, to_generate[i]) var/contract_payout_total = contract_to_add.contract.payout + contract_to_add.contract.payout_bonus assigned_targets.Add(contract_to_add.contract.target) - if(!lowest_paying_contract || (contract_payout_total < lowest_paying_sum)) + if (!lowest_paying_contract || (contract_payout_total < lowest_paying_sum)) lowest_paying_sum = contract_payout_total lowest_paying_contract = contract_to_add total += contract_payout_total contract_to_add.id = start_index assigned_contracts.Add(contract_to_add) start_index++ - if(total < lowest_TC_threshold) // If the threshold for TC payouts isn't reached, boost the lowest paying contract + + // If the threshold for TC payouts isn't reached, boost the lowest paying contract + if (total < lowest_TC_threshold) lowest_paying_contract.contract.payout_bonus += (lowest_TC_threshold - total) /datum/contractor_item var/name // Name of item var/desc // description of item var/item // item path, no item path means the purchase needs it's own handle_purchase() - var/item_icon = "fa-broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/ + var/item_icon = "broadcast-tower" // fontawesome icon to use inside the hub - https://fontawesome.com/icons/ var/limited = -1 // Any number above 0 for how many times it can be bought in a round for a single traitor. -1 is unlimited. var/cost // Cost of the item in contract rep. /datum/contractor_item/contract_reroll name = "Contract Reroll" desc = "Request a reroll of your current contract list. Will generate a new target, payment, and dropoff for the contracts you currently have available." - item_icon = "fa-dice" + item_icon = "dice" limited = 2 cost = 0 /datum/contractor_item/contract_reroll/handle_purchase(var/datum/contractor_hub/hub) . = ..() if (.) - var/list/new_target_list = list() // We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets. + /// We're not regenerating already completed/aborted/extracting contracts, but we don't want to repeat their targets. + var/list/new_target_list = list() for(var/datum/syndicate_contract/contract_check in hub.assigned_contracts) if (contract_check.status != CONTRACT_STATUS_ACTIVE && contract_check.status != CONTRACT_STATUS_INACTIVE) if (contract_check.contract.target) new_target_list.Add(contract_check.contract.target) continue - for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts) // Reroll contracts without duplicates + /// Reroll contracts without duplicates + for(var/datum/syndicate_contract/rerolling_contract in hub.assigned_contracts) if (rerolling_contract.status != CONTRACT_STATUS_ACTIVE && rerolling_contract.status != CONTRACT_STATUS_INACTIVE) continue rerolling_contract.generate(new_target_list) new_target_list.Add(rerolling_contract.contract.target) - hub.assigned_targets = new_target_list // Set our target list with the new set we've generated. + /// Set our target list with the new set we've generated. + hub.assigned_targets = new_target_list /datum/contractor_item/contractor_pinpointer name = "Contractor Pinpointer" desc = "A pinpointer that finds targets even without active suit sensors. Due to taking advantage of an exploit within the system, it can't pinpoint to the same accuracy as the traditional models. Becomes permanently locked to the user that first activates it." @@ -125,20 +143,25 @@ /datum/contractor_item/contractor_partner/handle_purchase(var/datum/contractor_hub/hub, mob/living/user) . = ..() + if (.) to_chat(user, "The uplink vibrates quietly, connecting to nearby agents...") - var/list/mob/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT) + + var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the Contractor Support Unit for [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_CONTRACTOR_SUPPORT) + if(LAZYLEN(candidates)) var/mob/dead/observer/C = pick(candidates) spawn_contractor_partner(user, C.key) else to_chat(user, "No available agents at this time, please try again later.") - limited += 1 // refund and add the limit back. + // refund and add the limit back. + limited += 1 hub.contract_rep += cost hub.purchased_items -= src /datum/outfit/contractor_partner name = "Contractor Support Unit" + uniform = /obj/item/clothing/under/chameleon suit = /obj/item/clothing/suit/chameleon back = /obj/item/storage/backpack @@ -148,28 +171,35 @@ ears = /obj/item/radio/headset/chameleon id = /obj/item/card/id/syndicate r_hand = /obj/item/storage/toolbox/syndicate + backpack_contents = list(/obj/item/storage/box/survival, /obj/item/implanter/uplink, /obj/item/clothing/mask/chameleon, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/lighter) /datum/outfit/contractor_partner/post_equip(mob/living/carbon/human/H, visualsOnly) . = ..() - var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(SLOT_WEAR_MASK) - cig.light() // pre-light their cig for extra badass + var/obj/item/clothing/mask/cigarette/syndicate/cig = H.get_item_by_slot(ITEM_SLOT_MASK) + // pre-light their cig + cig.light() /datum/contractor_item/contractor_partner/proc/spawn_contractor_partner(mob/living/user, key) var/mob/living/carbon/human/partner = new() var/datum/outfit/contractor_partner/partner_outfit = new() + partner_outfit.equip(partner) + var/obj/structure/closet/supplypod/arrival_pod = new() + arrival_pod.style = STYLE_SYNDICATE arrival_pod.explosionSize = list(0,0,0,1) arrival_pod.bluespace = TRUE var/turf/free_location = find_obstruction_free_location(2, user) - if (!free_location) // We really want to send them - if we can't find a nice location just land it on top of them. + // We really want to send them - if we can't find a nice location just land it on top of them. + if (!free_location) free_location = get_turf(user) partner.forceMove(arrival_pod) partner.ckey = key - partner_mind = partner.mind // We give a reference to the mind that'll be the support unit + /// We give a reference to the mind that'll be the support unit + partner_mind = partner.mind partner_mind.make_Contractor_Support() to_chat(partner_mind.current, "\n[user.real_name] is your superior. Follow any, and all orders given by them. You're here to support their mission only.") to_chat(partner_mind.current, "Should they perish, or be otherwise unavailable, you're to assist other active agents in this mission area to the best of your ability.\n\n") @@ -186,7 +216,7 @@ . = ..() if (.) power_fail(35, 50) - priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff") + priority_announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure", "poweroff.ogg") // Subtract cost, and spawn if it's an item. /datum/contractor_item/proc/handle_purchase(var/datum/contractor_hub/hub, mob/living/user) @@ -199,6 +229,7 @@ else if (limited == 0) return FALSE hub.purchased_items.Add(src) + user.playsound_local(user, 'sound/machines/uplinkpurchase.ogg', 100) if (item && ispath(item)) var/atom/item_to_create = new item(get_turf(user)) diff --git a/code/modules/antagonists/traitor/syndicate_contract.dm b/code/modules/antagonists/traitor/syndicate_contract.dm index 70ff59eee0..0f67616a32 100644 --- a/code/modules/antagonists/traitor/syndicate_contract.dm +++ b/code/modules/antagonists/traitor/syndicate_contract.dm @@ -4,47 +4,70 @@ var/datum/objective/contract/contract = new() var/target_rank var/ransom = 0 - var/payout_type = null + var/payout_type + var/wanted_message + var/list/victim_belongings = list() /datum/syndicate_contract/New(contract_owner, blacklist, type=CONTRACT_PAYOUT_SMALL) contract.owner = contract_owner payout_type = type + generate(blacklist) /datum/syndicate_contract/proc/generate(blacklist) contract.find_target(null, blacklist) - var/datum/data/record/record = find_record("name", contract.target.name, GLOB.data_core.general) - if(record) + + var/datum/data/record/record + if (contract.target) + record = find_record("name", contract.target.name, GLOB.data_core.general) + + if (record) target_rank = record.fields["rank"] else target_rank = "Unknown" + if (payout_type == CONTRACT_PAYOUT_LARGE) contract.payout_bonus = rand(9,13) - else if(payout_type == CONTRACT_PAYOUT_MEDIUM) + else if (payout_type == CONTRACT_PAYOUT_MEDIUM) contract.payout_bonus = rand(6,8) else contract.payout_bonus = rand(2,4) + contract.payout = rand(0, 2) contract.generate_dropoff() + ransom = 100 * rand(18, 45) + var/base = pick_list(WANTED_FILE, "basemessage") + var/verb_string = pick_list(WANTED_FILE, "verb") + var/noun = pick_list_weighted(WANTED_FILE, "noun") + var/location = pick_list_weighted(WANTED_FILE, "location") + wanted_message = "[base] [verb_string] [noun] [location]." + /datum/syndicate_contract/proc/handle_extraction(var/mob/living/user) if (contract.target && contract.dropoff_check(user, contract.target.current)) + var/turf/free_location = find_obstruction_free_location(3, user, contract.dropoff) - if(free_location) // We've got a valid location, launch. + + if (free_location) + // We've got a valid location, launch. launch_extraction_pod(free_location) return TRUE + return FALSE // Launch the pod to collect our victim. /datum/syndicate_contract/proc/launch_extraction_pod(turf/empty_pod_turf) var/obj/structure/closet/supplypod/extractionpod/empty_pod = new() + RegisterSignal(empty_pod, COMSIG_ATOM_ENTERED, .proc/enter_check) + empty_pod.stay_after_drop = TRUE empty_pod.reversing = TRUE empty_pod.explosionSize = list(0,0,0,1) empty_pod.leavingSound = 'sound/effects/podwoosh.ogg' + new /obj/effect/abstract/DPtarget(empty_pod_turf, empty_pod) /datum/syndicate_contract/proc/enter_check(datum/source, sent_mob) @@ -52,37 +75,55 @@ if(isliving(sent_mob)) var/mob/living/M = sent_mob var/datum/antagonist/traitor/traitor_data = contract.owner.has_antag_datum(/datum/antagonist/traitor) + if(M == contract.target.current) traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout + traitor_data.contractor_hub.contracts_completed += 1 + if(M.stat != DEAD) traitor_data.contractor_hub.contract_TC_to_redeem += contract.payout_bonus + status = CONTRACT_STATUS_COMPLETE + if(traitor_data.contractor_hub.current_contract == src) traitor_data.contractor_hub.current_contract = null + traitor_data.contractor_hub.contract_rep += 2 else status = CONTRACT_STATUS_ABORTED // Sending a target that wasn't even yours is as good as just aborting it + if(traitor_data.contractor_hub.current_contract == src) traitor_data.contractor_hub.current_contract = null + if(iscarbon(M)) for(var/obj/item/W in M) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(W == H.w_uniform || W == H.shoes) - continue //So all they're left with are shoes and uniform. + if(W == H.w_uniform) + continue //So all they're left with are shoes and uniform. + if(W == H.shoes) + continue + + M.transferItemToLoc(W) victim_belongings.Add(W) + var/obj/structure/closet/supplypod/extractionpod/pod = source - pod.send_up(pod) // Handle the pod returning + + // Handle the pod returning + pod.send_up(pod) + if(ishuman(M)) - var/mob/living/carbon/human/target = M // After we remove items, at least give them what they need to live. + 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/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") + 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) @@ -128,13 +169,18 @@ M.Dizzy(15) M.confused += 20 -/datum/syndicate_contract/proc/returnVictim(var/mob/living/M) // We're returning the victim +// We're returning the victim +/datum/syndicate_contract/proc/returnVictim(var/mob/living/M) var/list/possible_drop_loc = list() + for(var/turf/possible_drop in contract.dropoff.contents) - if(!is_blocked_turf(possible_drop)) - possible_drop_loc.Add(possible_drop) + if(!isspaceturf(possible_drop) && !isclosedturf(possible_drop)) + if(!is_blocked_turf(possible_drop)) + possible_drop_loc.Add(possible_drop) + if(possible_drop_loc.len > 0) var/pod_rand_loc = rand(1, possible_drop_loc.len) + var/obj/structure/closet/supplypod/return_pod = new() return_pod.bluespace = TRUE return_pod.explosionSize = list(0,0,0,0) @@ -144,8 +190,10 @@ for(var/obj/item/W in M) if(ishuman(M)) var/mob/living/carbon/human/H = M - if(W == H.w_uniform || W == H.shoes) + if(W == H.w_uniform) continue //So all they're left with are shoes and uniform. + if(W == H.shoes) + continue M.dropItemToGround(W) for(var/obj/item/W in victim_belongings) W.forceMove(return_pod) diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index ff3d95598d..d8a8e9a1be 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -234,7 +234,7 @@ H.equip_to_slot_or_del(new /obj/item/clothing/shoes/roman(H), SLOT_SHOES) H.put_in_hands(new /obj/item/shield/riot/roman(H), TRUE) H.put_in_hands(new /obj/item/claymore(H), TRUE) - H.equip_to_slot_or_del(new /obj/item/twohanded/spear(H), SLOT_BACK) + H.equip_to_slot_or_del(new /obj/item/spear(H), SLOT_BACK) /obj/item/voodoo @@ -259,7 +259,7 @@ to_chat(target, "You suddenly feel very hot") target.adjust_bodytemperature(50) GiveHint(target) - else if(is_pointed(I)) + else if(I.get_sharpness() == SHARP_POINTY) to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_selected)]!") target.DefaultCombatKnockdown(40) GiveHint(target) @@ -369,7 +369,7 @@ var/mob/living/carbon/last_user /obj/item/warpwhistle/proc/interrupted(mob/living/carbon/user) - if(!user || QDELETED(src) || user.notransform) + if(!user || QDELETED(src) || user.mob_transforming) on_cooldown = FALSE return TRUE return FALSE diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm index a9bc64a932..1e98b2f753 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook.dm @@ -161,12 +161,12 @@ /datum/spellbook_entry/blind name = "Blind" - spell_type = /obj/effect/proc_holder/spell/targeted/trigger/blind + spell_type = /obj/effect/proc_holder/spell/pointed/trigger/blind cost = 1 /datum/spellbook_entry/mindswap name = "Mindswap" - spell_type = /obj/effect/proc_holder/spell/targeted/mind_transfer + spell_type = /obj/effect/proc_holder/spell/pointed/mind_transfer category = "Mobility" /datum/spellbook_entry/forcewall @@ -246,7 +246,7 @@ /datum/spellbook_entry/barnyard name = "Barnyard Curse" - spell_type = /obj/effect/proc_holder/spell/targeted/barnyardcurse + spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse /datum/spellbook_entry/charge name = "Charge" @@ -294,6 +294,11 @@ dat += "[surplus] left.
    " return dat +/datum/spellbook_entry/item/timestop_katana + name = "Temporal Katana" + desc = "An oddly-weighted katana, reinforced to allow parrying, with a temporal anomaly magically shoved into it. Successful ripostes prove devastating to those unprepared." + item_path = /obj/item/katana/timestop + /datum/spellbook_entry/item/staffchange name = "Staff of Change" desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself." @@ -430,12 +435,12 @@ /datum/spellbook_entry/item/mjolnir name = "Mjolnir" desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power." - item_path = /obj/item/twohanded/mjollnir + item_path = /obj/item/mjollnir /datum/spellbook_entry/item/singularity_hammer name = "Singularity Hammer" desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everything nearby to the point of impact." - item_path = /obj/item/twohanded/singularityhammer + item_path = /obj/item/singularityhammer /datum/spellbook_entry/item/battlemage name = "Battlemage Armour" @@ -503,6 +508,7 @@ name = "Summon Guns" desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long!" dynamic_requirement = 60 + limit = 1 /datum/spellbook_entry/summon/guns/IsAvailible() if(!SSticker.mode) // In case spellbook is placed on map @@ -521,6 +527,7 @@ name = "Summon Magic" desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time." dynamic_requirement = 60 + limit = 1 /datum/spellbook_entry/summon/magic/IsAvailible() if(!SSticker.mode) // In case spellbook is placed on map @@ -560,6 +567,27 @@ . += "You cast it [times] times.
    " return . +/datum/spellbook_entry/summon/curse_of_madness + name = "Curse of Madness" + desc = "Curses the station, warping the minds of everyone inside, causing lasting traumas. Warning: this spell can affect you if not cast from a safe distance." + cost = 4 + +/datum/spellbook_entry/summon/curse_of_madness/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) + SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name) + active = TRUE + var/message = stripped_input(user, "Whisper a secret truth to drive your victims to madness.", "Whispers of Madness") + if(!message) + return FALSE + curse_of_madness(user, message) + to_chat(user, "You have cast the curse of insanity!") + playsound(user, 'sound/magic/mandswap.ogg', 50, 1) + return TRUE + +/datum/spellbook_entry/summon/curse_of_madness/IsAvailible() + if(!SSticker.mode) // In case spellbook is placed on map + return FALSE + return (!CONFIG_GET(flag/no_summon_traumas) && ..()) + /obj/item/spellbook name = "spell book" desc = "An unearthly tome that glows with power." diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm index 70adafd3fb..42954c3542 100644 --- a/code/modules/antagonists/wizard/wizard.dm +++ b/code/modules/antagonists/wizard/wizard.dm @@ -13,6 +13,7 @@ var/move_to_lair = TRUE var/outfit_type = /datum/outfit/wizard var/wiz_age = WIZARD_AGE_MIN /* Wizards by nature cannot be too young. */ + show_to_ghosts = TRUE /datum/antagonist/wizard/on_gain() register() @@ -176,7 +177,7 @@ to_chat(owner, "Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.") if(APPRENTICE_ROBELESS) owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null)) - owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null)) + owner.AddSpell(new /obj/effect/proc_holder/spell/pointed/mind_transfer(null)) to_chat(owner, "Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.") if(APPRENTICE_MARTIAL) owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist(null)) diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm index 7c4c5351df..f10506a0d9 100644 --- a/code/modules/antagonists/xeno/xeno.dm +++ b/code/modules/antagonists/xeno/xeno.dm @@ -12,9 +12,22 @@ name = "Xenomorph" job_rank = ROLE_ALIEN show_in_antagpanel = FALSE + show_to_ghosts = TRUE var/datum/team/xeno/xeno_team threat = 3 +/datum/antagonist/xeno/threat() + . = 1 + if(isalienhunter(owner)) + . = 2 + else if(isaliensentinel(owner)) + . = 4 + else if(isalienroyal(owner)) + if(isalienqueen(owner)) + . = 8 + else + . = 6 + /datum/antagonist/xeno/create_team(datum/team/xeno/new_team) if(!new_team) for(var/datum/antagonist/xeno/X in GLOB.antagonists) diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm index fb254a2dcc..8f88076af9 100644 --- a/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -1,7 +1,7 @@ /obj/item/organ/genital color = "#fcccb3" w_class = WEIGHT_CLASS_SMALL - organ_flags = ORGAN_NO_DISMEMBERMENT + organ_flags = ORGAN_NO_DISMEMBERMENT|ORGAN_EDIBLE var/shape var/sensitivity = 1 // wow if this were ever used that'd be cool but it's not but i'm keeping it for my unshit code var/genital_flags //see citadel_defines.dm @@ -232,23 +232,6 @@ /obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H) return - -//procs to handle sprite overlays being applied to humans - -/mob/living/carbon/human/equip_to_slot(obj/item/I, slot) - . = ..() - if(!. && I && slot && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage, hands or cuffs. - update_genitals() - -/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE) - var/no_update = FALSE - if(!I || I == l_store || I == r_store || I == s_store || I == handcuffed || I == legcuffed || get_held_index_of_item(I)) //stops storages, cuffs and held items from triggering it. - no_update = TRUE - . = ..() - if(!. || no_update) - return - update_genitals() - /mob/living/carbon/human/proc/update_genitals() if(QDELETED(src)) return diff --git a/code/modules/arousal/organs/womb.dm b/code/modules/arousal/organs/womb.dm index 386f407a26..e89d4329aa 100644 --- a/code/modules/arousal/organs/womb.dm +++ b/code/modules/arousal/organs/womb.dm @@ -6,5 +6,5 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_WOMB genital_flags = GENITAL_INTERNAL|GENITAL_FUID_PRODUCTION - fluid_id = /datum/reagent/consumable/femcum + fluid_id = /datum/reagent/consumable/semen/femcum linked_organ_slot = ORGAN_SLOT_VAGINA diff --git a/code/modules/arousal/toys/dildos.dm b/code/modules/arousal/toys/dildos.dm index 5cb6d47118..3f6fa9bb45 100644 --- a/code/modules/arousal/toys/dildos.dm +++ b/code/modules/arousal/toys/dildos.dm @@ -122,6 +122,7 @@ obj/item/dildo/flared/huge name = "literal horse cock" desc = "THIS THING IS HUGE!" dildo_size = 4 + force = 10 obj/item/dildo/custom name = "customizable dildo" diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index a40a4c1a42..1c814fa193 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -53,8 +53,8 @@ return if(I.use_tool(src, user, 0, volume=40)) status = TRUE - GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]" - message_admins("[ADMIN_LOOKUPFLW(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]") + GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.return_temperature()-T0C]" + message_admins("[ADMIN_LOOKUPFLW(user)] welded a single tank bomb. Temp: [bombtank.air_contents.return_temperature()-T0C]") to_chat(user, "A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.") add_fingerprint(user) return TRUE @@ -62,6 +62,7 @@ /obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I) bombtank.analyzer_act(user, I) + return TRUE /obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly bombassembly.attack_self(user, TRUE) @@ -90,7 +91,7 @@ if(bombassembly) bombassembly.on_found(finder) -/obj/item/onetankbomb/attack_hand() //also for mousetraps +/obj/item/onetankbomb/on_attack_hand() //also for mousetraps . = ..() if(.) return @@ -145,8 +146,7 @@ return /obj/item/tank/proc/ignite() //This happens when a bomb is told to explode - var/fuel_moles = air_contents.gases[/datum/gas/plasma] + air_contents.gases[/datum/gas/oxygen]/6 - GAS_GARBAGE_COLLECT(air_contents.gases) + var/fuel_moles = air_contents.get_moles(/datum/gas/plasma) + air_contents.get_moles(/datum/gas/oxygen)/6 var/datum/gas_mixture/bomb_mixture = air_contents.copy() var/strength = 1 @@ -156,7 +156,7 @@ qdel(master) qdel(src) - if(bomb_mixture.temperature > (T0C + 400)) + if(bomb_mixture.return_temperature() > (T0C + 400)) strength = (fuel_moles/15) if(strength >=1) @@ -169,7 +169,7 @@ ground_zero.assume_air(bomb_mixture) ground_zero.hotspot_expose(1000, 125) - else if(bomb_mixture.temperature > (T0C + 250)) + else if(bomb_mixture.return_temperature() > (T0C + 250)) strength = (fuel_moles/20) if(strength >=1) @@ -180,7 +180,7 @@ ground_zero.assume_air(bomb_mixture) ground_zero.hotspot_expose(1000, 125) - else if(bomb_mixture.temperature > (T0C + 100)) + else if(bomb_mixture.return_temperature() > (T0C + 100)) strength = (fuel_moles/25) if (strength >=1) diff --git a/code/modules/assembly/health.dm b/code/modules/assembly/health.dm index cddc4fb08f..0af6c85fb6 100644 --- a/code/modules/assembly/health.dm +++ b/code/modules/assembly/health.dm @@ -4,7 +4,6 @@ icon_state = "health" custom_materials = list(/datum/material/iron=800, /datum/material/glass=200) attachable = TRUE - secured = FALSE var/scanning = FALSE var/health_scan @@ -12,7 +11,8 @@ /obj/item/assembly/health/examine(mob/user) . = ..() - . += "Use a multitool to swap between \"detect death\" mode and \"detect critical state\" mode." + . += "Use it in hand to turn it off/on and Alt-click to swap between \"detect death\" mode and \"detect critical state\" mode." + . += "[src.scanning ? "The sensor is on and you can see [health_scan] displayed on the screen" : "The sensor is off"]." /obj/item/assembly/health/activate() if(!..()) @@ -30,14 +30,13 @@ update_icon() return secured -/obj/item/assembly/health/multitool_act(mob/living/user, obj/item/I) +/obj/item/assembly/health/AltClick(mob/living/user) if(alarm_health == HEALTH_THRESHOLD_CRIT) alarm_health = HEALTH_THRESHOLD_DEAD to_chat(user, "You toggle [src] to \"detect death\" mode.") else alarm_health = HEALTH_THRESHOLD_CRIT to_chat(user, "You toggle [src] to \"detect critical state\" mode.") - return TRUE /obj/item/assembly/health/process() if(!scanning || !secured) @@ -46,7 +45,6 @@ var/atom/A = src if(connected && connected.holder) A = connected.holder - for(A, A && !ismob(A), A=A.loc); // like get_turf(), but for mobs. var/mob/living/M = A @@ -71,36 +69,7 @@ STOP_PROCESSING(SSobj, src) return -/obj/item/assembly/health/ui_interact(mob/user as mob)//TODO: Change this to the wires thingy +/obj/item/assembly/health/attack_self(mob/user) . = ..() - if(!secured) - user.show_message("The [name] is unsecured!") - return FALSE - var/dat = "Health Sensor" - dat += "
    [scanning?"On":"Off"]" - if(scanning && health_scan) - dat += "
    Health: [health_scan]" - user << browse(dat, "window=hscan") - onclose(user, "hscan") - -/obj/item/assembly/health/Topic(href, href_list) - ..() - if(!ismob(usr)) - return - - var/mob/user = usr - - if(!user.canUseTopic(src)) - usr << browse(null, "window=hscan") - onclose(usr, "hscan") - return - - if(href_list["scanning"]) - toggle_scan() - - if(href_list["close"]) - usr << browse(null, "window=hscan") - return - - attack_self(user) - return + to_chat(user, "You toggle [src] [src.scanning ? "off" : "on"].") + toggle_scan() diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index c960a7f039..bf56449a0c 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -87,7 +87,7 @@ if(a_right) a_right.dropped(user) -/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess +/obj/item/assembly_holder/on_attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess . = ..() if(.) return diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 33c6d46045..899eb12511 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -4,7 +4,6 @@ icon_state = "infrared" custom_materials = list(/datum/material/iron=1000, /datum/material/glass=500) is_position_sensitive = TRUE - var/on = FALSE var/visible = FALSE var/maxlength = 8 @@ -38,7 +37,7 @@ /obj/item/assembly/infra/activate() if(!..()) - return FALSE//Cooldown check + return FALSE //Cooldown check on = !on refreshBeam() update_icon() @@ -69,7 +68,7 @@ holder.update_icon() return -/obj/item/assembly/infra/dropped(mob/user) +/obj/item/assembly/infra/dropped() . = ..() if(holder) holder_movement() //sync the dir of the device as well if it's contained in a TTV or an assembly holder @@ -124,7 +123,7 @@ return refreshBeam() -/obj/item/assembly/infra/attack_hand() +/obj/item/assembly/infra/on_attack_hand() . = ..() refreshBeam() @@ -133,7 +132,7 @@ . = ..() setDir(t) -/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) +/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE) . = ..() olddir = dir @@ -176,55 +175,55 @@ return return refreshBeam() -/obj/item/assembly/infra/ui_interact(mob/user)//TODO: change this this to the wire control panel - . = ..() - if(is_secured(user)) - user.set_machine(src) - var/dat = "Infrared Laser" - dat += "
    Status: [on ? "On" : "Off"]" - dat += "
    Visibility: [visible ? "Visible" : "Invisible"]" - dat += "

    Refresh" - dat += "

    Close" - user << browse(dat, "window=infra") - onclose(user, "infra") - return - -/obj/item/assembly/infra/Topic(href, href_list) - ..() - if(usr.incapacitated() || !in_range(loc, usr)) - usr << browse(null, "window=infra") - onclose(usr, "infra") - return - if(href_list["state"]) - on = !(on) - update_icon() - refreshBeam() - if(href_list["visible"]) - visible = !(visible) - update_icon() - refreshBeam() - if(href_list["close"]) - usr << browse(null, "window=infra") - return - if(usr) - attack_self(usr) - /obj/item/assembly/infra/setDir() . = ..() refreshBeam() +/obj/item/assembly/infra/ui_status(mob/user) + if(is_secured(user)) + return ..() + return UI_CLOSE + +/obj/item/assembly/infra/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "InfraredEmitter", name) + ui.open() + +/obj/item/assembly/infra/ui_data(mob/user) + var/list/data = list() + data["on"] = on + data["visible"] = visible + return data + +/obj/item/assembly/infra/ui_act(action, params) + if(..()) + return + + switch(action) + if("power") + on = !on + . = TRUE + if("visibility") + visible = !visible + . = TRUE + + update_icon() + refreshBeam() + /***************************IBeam*********************************/ /obj/effect/beam/i_beam name = "infrared beam" icon = 'icons/obj/projectiles.dmi' icon_state = "ibeam" - var/obj/item/assembly/infra/master anchored = TRUE density = FALSE pass_flags = PASSTABLE|PASSGLASS|PASSGRILLE|LETPASSTHROW + var/obj/item/assembly/infra/master /obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj) + . = ..() if(istype(AM, /obj/effect/beam)) return if (isitem(AM)) diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 90d4662c15..2c005b971d 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -84,8 +84,7 @@ playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/assembly/mousetrap/attack_hand(mob/living/carbon/human/user) +/obj/item/assembly/mousetrap/on_attack_hand(mob/living/carbon/human/user) if(armed) if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50)) var/which_hand = BODY_ZONE_PRECISE_L_HAND diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm index f1a4ce47cc..60de1b3e87 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -4,7 +4,6 @@ icon_state = "prox" custom_materials = list(/datum/material/iron=800, /datum/material/glass=200) attachable = TRUE - var/scanning = FALSE var/timing = FALSE var/time = 10 @@ -26,7 +25,7 @@ /obj/item/assembly/prox_sensor/activate() if(!..()) - return FALSE//Cooldown check + return FALSE //Cooldown check if(!scanning) timing = !timing else @@ -41,7 +40,6 @@ else proximity_monitor.SetHost(src,src) - /obj/item/assembly/prox_sensor/toggle_secure() secured = !secured if(!secured) @@ -56,8 +54,6 @@ update_icon() return secured - - /obj/item/assembly/prox_sensor/HasProximity(atom/movable/AM as mob|obj) if (istype(AM, /obj/effect/beam)) return @@ -75,7 +71,6 @@ next_activate = world.time + 30 return TRUE - /obj/item/assembly/prox_sensor/process() if(!timing) return @@ -111,50 +106,46 @@ holder.update_icon() return -/obj/item/assembly/prox_sensor/ui_interact(mob/user)//TODO: Change this to the wires thingy - . = ..() +/obj/item/assembly/prox_sensor/ui_status(mob/user) if(is_secured(user)) - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = "Proximity Sensor" - if(!scanning) - dat += "
    [(timing ? "Arming" : "Not Arming")] [minute]:[second]" - dat += "
    - - + +" - dat += "
    Armed":"1'>Unarmed (Movement sensor active when armed!)"]" - dat += "
    Detection range: - [sensitivity] +" - dat += "

    Refresh" - dat += "

    Close" - user << browse(dat, "window=prox") - onclose(user, "prox") + return ..() + return UI_CLOSE + +/obj/item/assembly/prox_sensor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ProximitySensor", name) + ui.open() + +/obj/item/assembly/prox_sensor/ui_data(mob/user) + var/list/data = list() + data["seconds"] = round(time % 60) + data["minutes"] = round((time - data["seconds"]) / 60) + data["timing"] = timing + data["scanning"] = scanning + data["sensitivity"] = sensitivity + return data + +/obj/item/assembly/prox_sensor/ui_act(action, params) + if(..()) return - -/obj/item/assembly/prox_sensor/Topic(href, href_list) - ..() - if(usr.incapacitated() || !in_range(loc, usr)) - usr << browse(null, "window=prox") - onclose(usr, "prox") - return - - if(href_list["sense"]) - sensitivity_change(((href_list["sense"] == "up") ? 1 : -1)) - - if(href_list["scanning"]) - toggle_scan(text2num(href_list["scanning"])) - - if(href_list["time"]) - timing = text2num(href_list["time"]) - update_icon() - - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 600) - - if(href_list["close"]) - usr << browse(null, "window=prox") - return - - if(usr) - attack_self(usr) - + switch(action) + if("scanning") + toggle_scan(!scanning) + . = TRUE + if("sense") + var/value = text2num(params["range"]) + if(value) + sensitivity_change(value) + . = TRUE + if("time") + timing = !timing + update_icon() + . = TRUE + if("input") + var/value = text2num(params["adjust"]) + if(value) + value = round(time + value) + time = clamp(value, 0, 600) + . = TRUE diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index e70b6e5c74..e586f97a28 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -12,28 +12,42 @@ var/code = DEFAULT_SIGNALER_CODE var/frequency = FREQ_SIGNALER var/datum/radio_frequency/radio_connection - var/suicider = null + ///Holds the mind that commited suicide. + var/datum/mind/suicider + ///Holds a reference string to the mob, decides how much of a gamer you are. + var/suicide_mob var/hearing_range = 1 /obj/item/assembly/signaler/suicide_act(mob/living/carbon/user) user.visible_message("[user] eats \the [src]! If it is signaled, [user.p_they()] will die!") playsound(src, 'sound/items/eatfood.ogg', 50, TRUE) - user.transferItemToLoc(src, user, TRUE) - suicider = user + moveToNullspace() + suicider = user.mind + suicide_mob = REF(user) return MANUAL_SUICIDE -/obj/item/assembly/signaler/proc/manual_suicide(mob/living/carbon/user) - user.visible_message("[user]'s \the [src] receives a signal, killing [user.p_them()] instantly!") +/obj/item/assembly/signaler/proc/manual_suicide(datum/mind/suicidee) + var/mob/living/user = suicidee.current + if(!istype(user)) + return + if(suicide_mob == REF(user)) + user.visible_message("[user]'s [src] receives a signal, killing [user.p_them()] instantly!") + else + user.visible_message("[user]'s [src] receives a signal and [user.p_they()] die[user.p_s()] like a gamer!") user.adjustOxyLoss(200)//it sends an electrical pulse to their heart, killing them. or something. user.death(0) + //user.set_suicide(TRUE) + user.suicide_log() + playsound(user, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE) + qdel(src) /obj/item/assembly/signaler/Initialize() . = ..() set_frequency(frequency) - /obj/item/assembly/signaler/Destroy() SSradio.remove_object(src,frequency) + suicider = null . = ..() /obj/item/assembly/signaler/activate() @@ -47,14 +61,15 @@ holder.update_icon() return -/obj/item/assembly/signaler/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) - if(!is_secured(user)) - return - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/assembly/signaler/ui_status(mob/user) + if(is_secured(user)) + return ..() + return UI_CLOSE + +/obj/item/assembly/signaler/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - var/ui_width = 280 - var/ui_height = 132 - ui = new(user, src, ui_key, "signaler", name, ui_width, ui_height, master_ui, state) + ui = new(user, src, "Signaler", name) ui.open() /obj/item/assembly/signaler/ui_data(mob/user) @@ -63,12 +78,12 @@ data["code"] = code data["minFrequency"] = MIN_FREE_FREQ data["maxFrequency"] = MAX_FREE_FREQ - return data /obj/item/assembly/signaler/ui_act(action, params) if(..()) return + switch(action) if("signal") INVOKE_ASYNC(src, .proc/signal) @@ -112,9 +127,6 @@ if(usr) GLOB.lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") - - return - /obj/item/assembly/signaler/receive_signal(datum/signal/signal) . = FALSE if(!signal) @@ -125,6 +137,7 @@ return if(suicider) manual_suicide(suicider) + return pulse(TRUE) audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range) for(var/CHM in get_hearers_in_view(hearing_range, src)) @@ -133,7 +146,6 @@ LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE) return TRUE - /obj/item/assembly/signaler/proc/set_frequency(new_frequency) SSradio.remove_object(src, frequency) frequency = new_frequency @@ -162,73 +174,12 @@ return return ..(signal) -// Embedded signaller used in anomalies. -/obj/item/assembly/signaler/anomaly - name = "anomaly core" - desc = "The neutralized core of an anomaly. It'd probably be valuable for research." - icon_state = "anomaly core" - item_state = "electronic" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - resistance_flags = FIRE_PROOF - var/anomaly_type = /obj/effect/anomaly - -/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal) - if(!signal) - return FALSE - if(signal.data["code"] != code) - return FALSE - if(suicider) - manual_suicide(suicider) - for(var/obj/effect/anomaly/A in get_turf(src)) - A.anomalyNeutralize() - return TRUE - -/obj/item/assembly/signaler/anomaly/manual_suicide(mob/living/carbon/user) - user.visible_message("[user]'s [src] is reacting to the radio signal, warping [user.p_their()] body!") - user.suiciding = TRUE - user.suicide_log() - user.gib() - -/obj/item/assembly/signaler/anomaly/attackby(obj/item/I, mob/user, params) - if(I.tool_behaviour == TOOL_ANALYZER) - to_chat(user, "Analyzing... [src]'s stabilized field is fluctuating along frequency [format_frequency(frequency)], code [code].") - ..() - -//Anomaly cores -/obj/item/assembly/signaler/anomaly/pyro - name = "\improper pyroclastic anomaly core" - desc = "The neutralized core of a pyroclastic anomaly. It feels warm to the touch. It'd probably be valuable for research." - icon_state = "pyro core" - anomaly_type = /obj/effect/anomaly/pyro - -/obj/item/assembly/signaler/anomaly/grav - name = "\improper gravitational anomaly core" - desc = "The neutralized core of a gravitational anomaly. It feels much heavier than it looks. It'd probably be valuable for research." - icon_state = "grav core" - anomaly_type = /obj/effect/anomaly/grav - -/obj/item/assembly/signaler/anomaly/flux - name = "\improper flux anomaly core" - desc = "The neutralized core of a flux anomaly. Touching it makes your skin tingle. It'd probably be valuable for research." - icon_state = "flux core" - anomaly_type = /obj/effect/anomaly/flux - -/obj/item/assembly/signaler/anomaly/bluespace - name = "\improper bluespace anomaly core" - desc = "The neutralized core of a bluespace anomaly. It keeps phasing in and out of view. It'd probably be valuable for research." - icon_state = "anomaly core" - anomaly_type = /obj/effect/anomaly/bluespace - -/obj/item/assembly/signaler/anomaly/vortex - name = "\improper vortex anomaly core" - desc = "The neutralized core of a vortex anomaly. It won't sit still, as if some invisible force is acting on it. It'd probably be valuable for research." - icon_state = "vortex core" - anomaly_type = /obj/effect/anomaly/bhole +/obj/item/assembly/signaler/anomaly/attack_self() + return /obj/item/assembly/signaler/cyborg /obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params) return /obj/item/assembly/signaler/cyborg/screwdriver_act(mob/living/user, obj/item/I) - return \ No newline at end of file + return diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index bbcddbdb93..e06bb22b0b 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -41,7 +41,6 @@ update_icon() return TRUE - /obj/item/assembly/timer/toggle_secure() secured = !secured if(secured) @@ -52,7 +51,6 @@ update_icon() return secured - /obj/item/assembly/timer/proc/timer_end() if(!secured || next_activate > world.time) return FALSE @@ -66,7 +64,6 @@ timing = TRUE update_icon() - /obj/item/assembly/timer/process() if(!timing) return @@ -76,7 +73,6 @@ timer_end() time = saved_time - /obj/item/assembly/timer/update_icon() cut_overlays() attached_overlays = list() @@ -86,50 +82,43 @@ if(holder) holder.update_icon() - -/obj/item/assembly/timer/ui_interact(mob/user)//TODO: Have this use the wires - . = ..() +/obj/item/assembly/timer/ui_status(mob/user) if(is_secured(user)) - var/second = time % 60 - var/minute = (time - second) / 60 - var/dat = "Timing Unit" - dat += "
    [(timing ? "Timing" : "Not Timing")] [minute]:[second]" - dat += "
    - - + +" - dat += "

    Stop repeating" : "1'>Set to repeat")]" - dat += "

    Refresh" - dat += "

    Close" - var/datum/browser/popup = new(user, "timer", name) - popup.set_content(dat) - popup.open() + return ..() + return UI_CLOSE +/obj/item/assembly/timer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Timer", name) + ui.open() -/obj/item/assembly/timer/Topic(href, href_list) - ..() - if(!usr.canUseTopic(src, BE_CLOSE)) - usr << browse(null, "window=timer") - onclose(usr, "timer") +/obj/item/assembly/timer/ui_data(mob/user) + var/list/data = list() + data["seconds"] = round(time % 60) + data["minutes"] = round((time - data["seconds"]) / 60) + data["timing"] = timing + data["loop"] = loop + return data + +/obj/item/assembly/timer/ui_act(action, params) + if(..()) return - if(href_list["time"]) - timing = text2num(href_list["time"]) - if(timing && istype(holder, /obj/item/transfer_valve)) - var/timer_message = "[ADMIN_LOOKUPFLW(usr)] activated [src] attachment on [holder]." - message_admins(timer_message) - GLOB.bombers += timer_message - log_game("[key_name(usr)] activated [src] attachment on [holder]") - update_icon() - if(href_list["repeat"]) - loop = text2num(href_list["repeat"]) - - if(href_list["tp"]) - var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 1), 600) - saved_time = time - - if(href_list["close"]) - usr << browse(null, "window=timer") - return - - if(usr) - attack_self(usr) + switch(action) + if("time") + timing = !timing + if(timing && istype(holder, /obj/item/transfer_valve)) + log_game(usr, "activated a", src, "attachment on [holder]") + update_icon() + . = TRUE + if("repeat") + loop = !loop + . = TRUE + if("input") + var/value = text2num(params["adjust"]) + if(value) + value = round(time + value) + time = clamp(value, 1, 600) + saved_time = time + . = TRUE diff --git a/code/modules/asset_cache/asset_cache.dm b/code/modules/asset_cache/asset_cache.dm new file mode 100644 index 0000000000..53a30d4299 --- /dev/null +++ b/code/modules/asset_cache/asset_cache.dm @@ -0,0 +1,110 @@ +/* +Asset cache quick users guide: + +Make a datum in asset_list_items.dm with your assets for your thing. +Checkout asset_list.dm for the helper subclasses +The simple subclass will most like be of use for most cases. +Then call get_asset_datum() with the type of the datum you created and store the return +Then call .send(client) on that stored return value. + +Note: If your code uses output() with assets you will need to call asset_flush on the client and wait for it to return before calling output(). You only need do this if .send(client) returned TRUE +*/ + +//When sending mutiple assets, how many before we give the client a quaint little sending resources message +#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8 + +//This proc sends the asset to the client, but only if it needs it. +//This proc blocks(sleeps) unless verify is set to false +/proc/send_asset(client/client, asset_name) + return send_asset_list(client, list(asset_name)) + +/// Sends a list of assets to a client +/// This proc will no longer block, use client.asset_flush() if you to need know when the client has all assets (such as for output()). (This is not required for browse() calls as they use the same message queue as asset sends) +/// client - a client or mob +/// asset_list - A list of asset filenames to be sent to the client. +/// Returns TRUE if any assets were sent. +/proc/send_asset_list(client/client, list/asset_list) + if(!istype(client)) + if(ismob(client)) + var/mob/M = client + if(M.client) + client = M.client + else + return + else + return + + var/list/unreceived = list() + + for (var/asset_name in asset_list) + var/datum/asset_cache_item/asset = SSassets.cache[asset_name] + if (!asset) + continue + var/asset_file = asset.resource + if (!asset_file) + continue + + var/asset_md5 = asset.md5 + if (client.sent_assets[asset_name] == asset_md5) + continue + unreceived[asset_name] = asset_md5 + + if (unreceived.len) + if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT) + to_chat(client, "Sending Resources...") + + for(var/asset in unreceived) + var/datum/asset_cache_item/ACI + if ((ACI = SSassets.cache[asset])) + log_asset("Sending asset [asset] to client [client]") + client << browse_rsc(ACI.resource, asset) + + client.sent_assets |= unreceived + addtimer(CALLBACK(client, /client/proc/asset_cache_update_json), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) + return TRUE + return FALSE + +//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start. +//The proc calls procs that sleep for long times. +/proc/getFilesSlow(client/client, list/files, register_asset = TRUE, filerate = 3) + var/startingfilerate = filerate + for(var/file in files) + if (!client) + break + if (register_asset) + register_asset(file, files[file]) + + if (send_asset(client, file)) + if (!(--filerate)) + filerate = startingfilerate + client.asset_flush() + stoplag(0) //queuing calls like this too quickly can cause issues in some client versions + +//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up. +//icons and virtual assets get copied to the dyn rsc before use +/proc/register_asset(asset_name, asset) + var/datum/asset_cache_item/ACI = new(asset_name, asset) + + //this is technically never something that was supported and i want metrics on how often it happens if at all. + if (SSassets.cache[asset_name]) + var/datum/asset_cache_item/OACI = SSassets.cache[asset_name] + if (OACI.md5 != ACI.md5) + stack_trace("ERROR: new asset added to the asset cache with the same name as another asset: [asset_name] existing asset md5: [OACI.md5] new asset md5:[ACI.md5]") + else + var/list/stacktrace = gib_stack_trace() + log_asset("WARNING: dupe asset added to the asset cache: [asset_name] existing asset md5: [OACI.md5] new asset md5:[ACI.md5]\n[stacktrace.Join("\n")]") + SSassets.cache[asset_name] = ACI + return ACI + +/// Returns the url of the asset, currently this is just its name, here to allow further work cdn'ing assets. +/// Can be given an asset as well, this is just a work around for buggy edge cases where two assets may have the same name, doesn't matter now, but it will when the cdn comes. +/proc/get_asset_url(asset_name, asset = null) + var/datum/asset_cache_item/ACI = SSassets.cache[asset_name] + return ACI?.url + +//Generated names do not include file extention. +//Used mainly for code that deals with assets in a generic way +//The same asset will always lead to the same asset name +/proc/generate_asset_name(file) + return "asset.[md5(fcopy_rsc(file))]" + diff --git a/code/modules/asset_cache/asset_cache_client.dm b/code/modules/asset_cache/asset_cache_client.dm new file mode 100644 index 0000000000..0f51520f13 --- /dev/null +++ b/code/modules/asset_cache/asset_cache_client.dm @@ -0,0 +1,51 @@ + +/// Process asset cache client topic calls for "asset_cache_confirm_arrival=[INT]" +/client/proc/asset_cache_confirm_arrival(job_id) + var/asset_cache_job = round(text2num(job_id)) + //because we skip the limiter, we have to make sure this is a valid arrival and not somebody tricking us into letting them append to a list without limit. + if (asset_cache_job > 0 && asset_cache_job <= last_asset_job && !(completed_asset_jobs["[asset_cache_job]"])) + completed_asset_jobs["[asset_cache_job]"] = TRUE + last_completed_asset_job = max(last_completed_asset_job, asset_cache_job) + else + return asset_cache_job || TRUE + + +/// Process asset cache client topic calls for "asset_cache_preload_data=[HTML+JSON_STRING] +/client/proc/asset_cache_preload_data(data) + /*var/jsonend = findtextEx(data, "{{{ENDJSONDATA}}}") + if (!jsonend) + CRASH("invalid asset_cache_preload_data, no jsonendmarker")*/ + //var/json = html_decode(copytext(data, 1, jsonend)) + var/json = data + var/list/preloaded_assets = json_decode(json) + + for (var/preloaded_asset in preloaded_assets) + if (copytext(preloaded_asset, findlasttext(preloaded_asset, ".")+1) in list("js", "jsm", "htm", "html")) + preloaded_assets -= preloaded_asset + continue + sent_assets |= preloaded_assets + + +/// Updates the client side stored html/json combo file used to keep track of what assets the client has between restarts/reconnects. +/client/proc/asset_cache_update_json(verify = FALSE, list/new_assets = list()) + if (world.time - connection_time < 10 SECONDS) //don't override the existing data file on a new connection + return + if (!islist(new_assets)) + new_assets = list("[new_assets]" = md5(SSassets.cache[new_assets])) + + src << browse(json_encode(new_assets|sent_assets), "file=asset_data.json&display=0") + +/// Blocks until all currently sending browser assets have been sent. +/// Due to byond limitations, this proc will sleep for 1 client round trip even if the client has no pending asset sends. +/// This proc will return an untrue value if it had to return before confirming the send, such as timeout or the client going away. +/client/proc/asset_flush(timeout = 50) + var/job = ++last_asset_job + var/t = 0 + var/timeout_time = timeout + src << browse({""}, "window=asset_cache_browser&file=asset_cache_send_verify.htm") + + while(!completed_asset_jobs["[job]"] && t < timeout_time) // Reception is handled in Topic() + stoplag(1) // Lock up the caller until this is received. + t++ + if (t < timeout_time) + return TRUE diff --git a/code/modules/asset_cache/asset_cache_item.dm b/code/modules/asset_cache/asset_cache_item.dm new file mode 100644 index 0000000000..e74293c65e --- /dev/null +++ b/code/modules/asset_cache/asset_cache_item.dm @@ -0,0 +1,23 @@ +/** + * # asset_cache_item + * + * An internal datum containing info on items in the asset cache. Mainly used to cache md5 info for speed. +**/ +/datum/asset_cache_item + var/name + var/url + var/md5 + var/resource + +/datum/asset_cache_item/New(name, file) + if (!isfile(file)) + file = fcopy_rsc(file) + md5 = md5(file) + if (!md5) + md5 = md5(fcopy_rsc(file)) + if (!md5) + CRASH("invalid asset sent to asset cache") + debug_world_log("asset cache unexpected success of second fcopy_rsc") + src.name = name + url = name + resource = file diff --git a/code/modules/asset_cache/asset_list.dm b/code/modules/asset_cache/asset_list.dm new file mode 100644 index 0000000000..4ce9dcf6fc --- /dev/null +++ b/code/modules/asset_cache/asset_list.dm @@ -0,0 +1,256 @@ + +//These datums are used to populate the asset cache, the proc "register()" does this. +//Place any asset datums you create in asset_list_items.dm + +//all of our asset datums, used for referring to these later +GLOBAL_LIST_EMPTY(asset_datums) + +//get an assetdatum or make a new one +/proc/get_asset_datum(type) + return GLOB.asset_datums[type] || new type() + +/datum/asset + var/_abstract = /datum/asset + +/datum/asset/New() + GLOB.asset_datums[type] = src + register() + +/datum/asset/proc/get_url_mappings() + return list() + +/datum/asset/proc/register() + return + +/datum/asset/proc/send(client) + return + + +//If you don't need anything complicated. +/datum/asset/simple + _abstract = /datum/asset/simple + var/assets = list() + +/datum/asset/simple/register() + for(var/asset_name in assets) + assets[asset_name] = register_asset(asset_name, assets[asset_name]) + +/datum/asset/simple/send(client) + . = send_asset_list(client, assets) + +/datum/asset/simple/get_url_mappings() + . = list() + for (var/asset_name in assets) + var/datum/asset_cache_item/ACI = assets[asset_name] + if (!ACI) + continue + .[asset_name] = ACI.url + + +// For registering or sending multiple others at once +/datum/asset/group + _abstract = /datum/asset/group + var/list/children + +/datum/asset/group/register() + for(var/type in children) + get_asset_datum(type) + +/datum/asset/group/send(client/C) + for(var/type in children) + var/datum/asset/A = get_asset_datum(type) + . = A.send(C) || . + +/datum/asset/group/get_url_mappings() + . = list() + for(var/type in children) + var/datum/asset/A = get_asset_datum(type) + . += A.get_url_mappings() + +// spritesheet implementation - coalesces various icons into a single .png file +// and uses CSS to select icons out of that file - saves on transferring some +// 1400-odd individual PNG files +#define SPR_SIZE 1 +#define SPR_IDX 2 +#define SPRSZ_COUNT 1 +#define SPRSZ_ICON 2 +#define SPRSZ_STRIPPED 3 + +/datum/asset/spritesheet + _abstract = /datum/asset/spritesheet + var/name + var/list/sizes = list() // "32x32" -> list(10, icon/normal, icon/stripped) + var/list/sprites = list() // "foo_bar" -> list("32x32", 5) + +/datum/asset/spritesheet/register() + if (!name) + CRASH("spritesheet [type] cannot register without a name") + ensure_stripped() + for(var/size_id in sizes) + var/size = sizes[size_id] + register_asset("[name]_[size_id].png", size[SPRSZ_STRIPPED]) + var/res_name = "spritesheet_[name].css" + var/fname = "data/spritesheets/[res_name]" + fdel(fname) + text2file(generate_css(), fname) + register_asset(res_name, fcopy_rsc(fname)) + fdel(fname) + +/datum/asset/spritesheet/send(client/C) + if (!name) + return + var/all = list("spritesheet_[name].css") + for(var/size_id in sizes) + all += "[name]_[size_id].png" + . = send_asset_list(C, all) + +/datum/asset/spritesheet/get_url_mappings() + if (!name) + return + . = list("spritesheet_[name].css" = get_asset_url("spritesheet_[name].css")) + for(var/size_id in sizes) + .["[name]_[size_id].png"] = get_asset_url("[name]_[size_id].png") + + + +/datum/asset/spritesheet/proc/ensure_stripped(sizes_to_strip = sizes) + for(var/size_id in sizes_to_strip) + var/size = sizes[size_id] + if (size[SPRSZ_STRIPPED]) + continue + + // save flattened version + var/fname = "data/spritesheets/[name]_[size_id].png" + fcopy(size[SPRSZ_ICON], fname) + var/error = rustg_dmi_strip_metadata(fname) + if(length(error)) + stack_trace("Failed to strip [name]_[size_id].png: [error]") + size[SPRSZ_STRIPPED] = icon(fname) + fdel(fname) + +/datum/asset/spritesheet/proc/generate_css() + var/list/out = list() + + for (var/size_id in sizes) + var/size = sizes[size_id] + var/icon/tiny = size[SPRSZ_ICON] + out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[get_asset_url("[name]_[size_id].png")]') no-repeat;}" + + for (var/sprite_id in sprites) + var/sprite = sprites[sprite_id] + var/size_id = sprite[SPR_SIZE] + var/idx = sprite[SPR_IDX] + var/size = sizes[size_id] + + var/icon/tiny = size[SPRSZ_ICON] + var/icon/big = size[SPRSZ_STRIPPED] + var/per_line = big.Width() / tiny.Width() + var/x = (idx % per_line) * tiny.Width() + var/y = round(idx / per_line) * tiny.Height() + + out += ".[name][size_id].[sprite_id]{background-position:-[x]px -[y]px;}" + + return out.Join("\n") + +/datum/asset/spritesheet/proc/Insert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) + I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) + if (!I || !length(icon_states(I))) // that direction or state doesn't exist + return + var/size_id = "[I.Width()]x[I.Height()]" + var/size = sizes[size_id] + + if (sprites[sprite_name]) + CRASH("duplicate sprite \"[sprite_name]\" in sheet [name] ([type])") + + if (size) + var/position = size[SPRSZ_COUNT]++ + var/icon/sheet = size[SPRSZ_ICON] + size[SPRSZ_STRIPPED] = null + sheet.Insert(I, icon_state=sprite_name) + sprites[sprite_name] = list(size_id, position) + else + sizes[size_id] = size = list(1, I, null) + sprites[sprite_name] = list(size_id, 0) + +/datum/asset/spritesheet/proc/InsertAll(prefix, icon/I, list/directions) + if (length(prefix)) + prefix = "[prefix]-" + + if (!directions) + directions = list(SOUTH) + + for (var/icon_state_name in icon_states(I)) + for (var/direction in directions) + var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : "" + Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction) + +/datum/asset/spritesheet/proc/css_tag() + return {""} + +/datum/asset/spritesheet/proc/css_filename() + return get_asset_url("spritesheet_[name].css") + +/datum/asset/spritesheet/proc/icon_tag(sprite_name) + var/sprite = sprites[sprite_name] + if (!sprite) + return null + var/size_id = sprite[SPR_SIZE] + return {""} + +/datum/asset/spritesheet/proc/icon_class_name(sprite_name) + var/sprite = sprites[sprite_name] + if (!sprite) + return null + var/size_id = sprite[SPR_SIZE] + return {"[name][size_id] [sprite_name]"} + +#undef SPR_SIZE +#undef SPR_IDX +#undef SPRSZ_COUNT +#undef SPRSZ_ICON +#undef SPRSZ_STRIPPED + + +/datum/asset/spritesheet/simple + _abstract = /datum/asset/spritesheet/simple + var/list/assets + +/datum/asset/spritesheet/simple/register() + for (var/key in assets) + Insert(key, assets[key]) + ..() + +//Generates assets based on iconstates of a single icon +/datum/asset/simple/icon_states + _abstract = /datum/asset/simple/icon_states + var/icon + var/list/directions = list(SOUTH) + var/frame = 1 + var/movement_states = FALSE + + var/prefix = "default" //asset_name = "[prefix].[icon_state_name].png" + var/generic_icon_names = FALSE //generate icon filenames using generate_asset_name() instead the above format + +/datum/asset/simple/icon_states/register(_icon = icon) + for(var/icon_state_name in icon_states(_icon)) + for(var/direction in directions) + var/asset = icon(_icon, icon_state_name, direction, frame, movement_states) + if (!asset) + continue + asset = fcopy_rsc(asset) //dedupe + var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]." : "" + var/asset_name = sanitize_filename("[prefix].[prefix2][icon_state_name].png") + if (generic_icon_names) + asset_name = "[generate_asset_name(asset)].png" + + register_asset(asset_name, asset) + +/datum/asset/simple/icon_states/multiple_icons + _abstract = /datum/asset/simple/icon_states/multiple_icons + var/list/icons + +/datum/asset/simple/icon_states/multiple_icons/register() + for(var/i in icons) + ..(i) + + diff --git a/code/modules/client/asset_cache.dm b/code/modules/asset_cache/asset_list_items.dm similarity index 50% rename from code/modules/client/asset_cache.dm rename to code/modules/asset_cache/asset_list_items.dm index de7cd1696f..18e3281e4b 100644 --- a/code/modules/client/asset_cache.dm +++ b/code/modules/asset_cache/asset_list_items.dm @@ -1,409 +1,9 @@ -/* -Asset cache quick users guide: - -Make a datum at the bottom of this file with your assets for your thing. -The simple subsystem will most like be of use for most cases. -Then call get_asset_datum() with the type of the datum you created and store the return -Then call .send(client) on that stored return value. - -You can set verify to TRUE if you want send() to sleep until the client has the assets. -*/ - - -// Amount of time(ds) MAX to send per asset, if this get exceeded we cancel the sleeping. -// This is doubled for the first asset, then added per asset after -#define ASSET_CACHE_SEND_TIMEOUT 7 - -//When sending mutiple assets, how many before we give the client a quaint little sending resources message -#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8 - -//When passively preloading assets, how many to send at once? Too high creates noticable lag where as too low can flood the client's cache with "verify" files -#define ASSET_CACHE_PRELOAD_CONCURRENT 3 - -/client - var/list/cache = list() // List of all assets sent to this client by the asset cache. - var/list/completed_asset_jobs = list() // List of all completed jobs, awaiting acknowledgement. - var/list/sending = list() - var/last_asset_job = 0 // Last job done. - -//This proc sends the asset to the client, but only if it needs it. -//This proc blocks(sleeps) unless verify is set to false -/proc/send_asset(client/client, asset_name, verify = TRUE) - if(!istype(client)) - if(ismob(client)) - var/mob/M = client - if(M.client) - client = M.client - - else - return 0 - - else - return 0 - - if(client.cache.Find(asset_name) || client.sending.Find(asset_name)) - return 0 - - client << browse_rsc(SSassets.cache[asset_name], asset_name) - if(!verify) - client.cache += asset_name - return 1 - - client.sending |= asset_name - var/job = ++client.last_asset_job - - client << browse({" - - "}, "window=asset_cache_browser") - - var/t = 0 - var/timeout_time = (ASSET_CACHE_SEND_TIMEOUT * client.sending.len) + ASSET_CACHE_SEND_TIMEOUT - while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic() - stoplag(1) // Lock up the caller until this is received. - t++ - - if(client) - client.sending -= asset_name - client.cache |= asset_name - client.completed_asset_jobs -= job - - return 1 - -//This proc blocks(sleeps) unless verify is set to false -/proc/send_asset_list(client/client, list/asset_list, verify = TRUE) - if(!istype(client)) - if(ismob(client)) - var/mob/M = client - if(M.client) - client = M.client - - else - return 0 - - else - return 0 - - var/list/unreceived = asset_list - (client.cache + client.sending) - if(!unreceived || !unreceived.len) - return 0 - if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT) - to_chat(client, "Sending Resources...") - for(var/asset in unreceived) - if (asset in SSassets.cache) - client << browse_rsc(SSassets.cache[asset], asset) - - if(!verify) // Can't access the asset cache browser, rip. - client.cache += unreceived - return 1 - - client.sending |= unreceived - var/job = ++client.last_asset_job - - client << browse({" - - "}, "window=asset_cache_browser") - - var/t = 0 - var/timeout_time = ASSET_CACHE_SEND_TIMEOUT * client.sending.len - while(client && !client.completed_asset_jobs.Find(job) && t < timeout_time) // Reception is handled in Topic() - stoplag(1) // Lock up the caller until this is received. - t++ - - if(client) - client.sending -= unreceived - client.cache |= unreceived - client.completed_asset_jobs -= job - - return 1 - -//This proc will download the files without clogging up the browse() queue, used for passively sending files on connection start. -//The proc calls procs that sleep for long times. -/proc/getFilesSlow(client/client, list/files, register_asset = TRUE) - var/concurrent_tracker = 1 - for(var/file in files) - if (!client) - break - if (register_asset) - register_asset(file, files[file]) - if (concurrent_tracker >= ASSET_CACHE_PRELOAD_CONCURRENT) - concurrent_tracker = 1 - send_asset(client, file) - else - concurrent_tracker++ - send_asset(client, file, verify=FALSE) - - stoplag(0) //queuing calls like this too quickly can cause issues in some client versions - -//This proc "registers" an asset, it adds it to the cache for further use, you cannot touch it from this point on or you'll fuck things up. -//if it's an icon or something be careful, you'll have to copy it before further use. -/proc/register_asset(asset_name, asset) - SSassets.cache[asset_name] = asset - -//Generated names do not include file extention. -//Used mainly for code that deals with assets in a generic way -//The same asset will always lead to the same asset name -/proc/generate_asset_name(file) - return "asset.[md5(fcopy_rsc(file))]" - - -//These datums are used to populate the asset cache, the proc "register()" does this. - -//all of our asset datums, used for referring to these later -GLOBAL_LIST_EMPTY(asset_datums) - -//get an assetdatum or make a new one -/proc/get_asset_datum(type) - return GLOB.asset_datums[type] || new type() - -/datum/asset - var/_abstract = /datum/asset - -/datum/asset/New() - GLOB.asset_datums[type] = src - register() - -/datum/asset/proc/register() - return - -/datum/asset/proc/send(client) - return - - -//If you don't need anything complicated. -/datum/asset/simple - _abstract = /datum/asset/simple - var/assets = list() - var/verify = FALSE - -/datum/asset/simple/register() - for(var/asset_name in assets) - register_asset(asset_name, assets[asset_name]) - -/datum/asset/simple/send(client) - send_asset_list(client,assets,verify) - - -// For registering or sending multiple others at once -/datum/asset/group - _abstract = /datum/asset/group - var/list/children - -/datum/asset/group/register() - for(var/type in children) - get_asset_datum(type) - -/datum/asset/group/send(client/C) - for(var/type in children) - var/datum/asset/A = get_asset_datum(type) - A.send(C) - - -// spritesheet implementation - coalesces various icons into a single .png file -// and uses CSS to select icons out of that file - saves on transferring some -// 1400-odd individual PNG files -#define SPR_SIZE 1 -#define SPR_IDX 2 -#define SPRSZ_COUNT 1 -#define SPRSZ_ICON 2 -#define SPRSZ_STRIPPED 3 - -/datum/asset/spritesheet - _abstract = /datum/asset/spritesheet - var/name - var/list/sizes = list() // "32x32" -> list(10, icon/normal, icon/stripped) - var/list/sprites = list() // "foo_bar" -> list("32x32", 5) - var/verify = FALSE - -/datum/asset/spritesheet/register() - if (!name) - CRASH("spritesheet [type] cannot register without a name") - ensure_stripped() - - var/res_name = "spritesheet_[name].css" - var/fname = "data/spritesheets/[res_name]" - fdel(fname) - text2file(generate_css(), fname) - register_asset(res_name, fcopy_rsc(fname)) - fdel(fname) - - for(var/size_id in sizes) - var/size = sizes[size_id] - register_asset("[name]_[size_id].png", size[SPRSZ_STRIPPED]) - -/datum/asset/spritesheet/send(client/C) - if (!name) - return - var/all = list("spritesheet_[name].css") - for(var/size_id in sizes) - all += "[name]_[size_id].png" - send_asset_list(C, all, verify) - -/datum/asset/spritesheet/proc/ensure_stripped(sizes_to_strip = sizes) - for(var/size_id in sizes_to_strip) - var/size = sizes[size_id] - if (size[SPRSZ_STRIPPED]) - continue - - // save flattened version - var/fname = "data/spritesheets/[name]_[size_id].png" - fcopy(size[SPRSZ_ICON], fname) - var/error = rustg_dmi_strip_metadata(fname) - if(length(error)) - stack_trace("Failed to strip [name]_[size_id].png: [error]") - size[SPRSZ_STRIPPED] = icon(fname) - fdel(fname) - -/datum/asset/spritesheet/proc/generate_css() - var/list/out = list() - - for (var/size_id in sizes) - var/size = sizes[size_id] - var/icon/tiny = size[SPRSZ_ICON] - out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[name]_[size_id].png') no-repeat;}" - - for (var/sprite_id in sprites) - var/sprite = sprites[sprite_id] - var/size_id = sprite[SPR_SIZE] - var/idx = sprite[SPR_IDX] - var/size = sizes[size_id] - - var/icon/tiny = size[SPRSZ_ICON] - var/icon/big = size[SPRSZ_STRIPPED] - var/per_line = big.Width() / tiny.Width() - var/x = (idx % per_line) * tiny.Width() - var/y = round(idx / per_line) * tiny.Height() - - out += ".[name][size_id].[sprite_id]{background-position:-[x]px -[y]px;}" - - return out.Join("\n") - -/datum/asset/spritesheet/proc/Insert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE) - I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving) - if (!I || !length(icon_states(I))) // that direction or state doesn't exist - return - var/size_id = "[I.Width()]x[I.Height()]" - var/size = sizes[size_id] - - if (sprites[sprite_name]) - CRASH("duplicate sprite \"[sprite_name]\" in sheet [name] ([type])") - - if (size) - var/position = size[SPRSZ_COUNT]++ - var/icon/sheet = size[SPRSZ_ICON] - size[SPRSZ_STRIPPED] = null - sheet.Insert(I, icon_state=sprite_name) - sprites[sprite_name] = list(size_id, position) - else - sizes[size_id] = size = list(1, I, null) - sprites[sprite_name] = list(size_id, 0) - -/datum/asset/spritesheet/proc/InsertAll(prefix, icon/I, list/directions) - if (length(prefix)) - prefix = "[prefix]-" - - if (!directions) - directions = list(SOUTH) - - for (var/icon_state_name in icon_states(I)) - for (var/direction in directions) - var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : "" - Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction) - -/datum/asset/spritesheet/proc/css_tag() - return {""} - -/datum/asset/spritesheet/proc/icon_tag(sprite_name) - var/sprite = sprites[sprite_name] - if (!sprite) - return null - var/size_id = sprite[SPR_SIZE] - return {""} - -/datum/asset/spritesheet/proc/icon_class_name(sprite_name) - var/sprite = sprites[sprite_name] - if (!sprite) - return null - var/size_id = sprite[SPR_SIZE] - return {"[name][size_id] [sprite_name]"} - -#undef SPR_SIZE -#undef SPR_IDX -#undef SPRSZ_COUNT -#undef SPRSZ_ICON -#undef SPRSZ_STRIPPED - - -/datum/asset/spritesheet/simple - _abstract = /datum/asset/spritesheet/simple - var/list/assets - -/datum/asset/spritesheet/simple/register() - for (var/key in assets) - Insert(key, assets[key]) - ..() - -//Generates assets based on iconstates of a single icon -/datum/asset/simple/icon_states - _abstract = /datum/asset/simple/icon_states - var/icon - var/list/directions = list(SOUTH) - var/frame = 1 - var/movement_states = FALSE - - var/prefix = "default" //asset_name = "[prefix].[icon_state_name].png" - var/generic_icon_names = FALSE //generate icon filenames using generate_asset_name() instead the above format - - verify = FALSE - -/datum/asset/simple/icon_states/register(_icon = icon) - for(var/icon_state_name in icon_states(_icon)) - for(var/direction in directions) - var/asset = icon(_icon, icon_state_name, direction, frame, movement_states) - if (!asset) - continue - asset = fcopy_rsc(asset) //dedupe - var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]." : "" - var/asset_name = sanitize_filename("[prefix].[prefix2][icon_state_name].png") - if (generic_icon_names) - asset_name = "[generate_asset_name(asset)].png" - - register_asset(asset_name, asset) - -/datum/asset/simple/icon_states/multiple_icons - _abstract = /datum/asset/simple/icon_states/multiple_icons - var/list/icons - -/datum/asset/simple/icon_states/multiple_icons/register() - for(var/i in icons) - ..(i) - - //DEFINITIONS FOR ASSET DATUMS START HERE. /datum/asset/simple/tgui assets = list( - // tgui - "tgui.css" = 'tgui/assets/tgui.css', - "tgui.js" = 'tgui/assets/tgui.js', - // tgui-next - "tgui-main.html" = 'tgui-next/packages/tgui/public/tgui-main.html', - "tgui-fallback.html" = 'tgui-next/packages/tgui/public/tgui-fallback.html', - "tgui.bundle.js" = 'tgui-next/packages/tgui/public/tgui.bundle.js', - "tgui.bundle.css" = 'tgui-next/packages/tgui/public/tgui.bundle.css', - "shim-html5shiv.js" = 'tgui-next/packages/tgui/public/shim-html5shiv.js', - "shim-ie8.js" = 'tgui-next/packages/tgui/public/shim-ie8.js', - "shim-dom4.js" = 'tgui-next/packages/tgui/public/shim-dom4.js', - "shim-css-om.js" = 'tgui-next/packages/tgui/public/shim-css-om.js', - ) - -/datum/asset/group/tgui - children = list( - /datum/asset/simple/tgui, - /datum/asset/simple/fontawesome + "tgui.bundle.js" = 'tgui/packages/tgui/public/tgui.bundle.js', + "tgui.bundle.css" = 'tgui/packages/tgui/public/tgui.bundle.css', ) /datum/asset/simple/headers @@ -433,7 +33,15 @@ GLOBAL_LIST_EMPTY(asset_datums) "smmon_3.gif" = 'icons/program_icons/smmon_3.gif', "smmon_4.gif" = 'icons/program_icons/smmon_4.gif', "smmon_5.gif" = 'icons/program_icons/smmon_5.gif', - "smmon_6.gif" = 'icons/program_icons/smmon_6.gif' + "smmon_6.gif" = 'icons/program_icons/smmon_6.gif', + "borg_mon.gif" = 'icons/program_icons/borg_mon.gif' + ) + +/datum/asset/simple/radar_assets + assets = list( + "ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png', + "ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png', + "ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png' ) /datum/asset/spritesheet/simple/pda @@ -464,6 +72,7 @@ GLOBAL_LIST_EMPTY(asset_datums) "refresh" = 'icons/pda_icons/pda_refresh.png', "scanner" = 'icons/pda_icons/pda_scanner.png', "signaler" = 'icons/pda_icons/pda_signaler.png', + // "skills" = 'icons/pda_icons/pda_skills.png', "status" = 'icons/pda_icons/pda_status.png', "dronephone" = 'icons/pda_icons/pda_dronephone.png', "emoji" = 'icons/pda_icons/pda_emoji.png' @@ -483,52 +92,12 @@ GLOBAL_LIST_EMPTY(asset_datums) "stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png', "stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png', "stamp-law" = 'icons/stamp_icons/large_stamp-law.png' + // "stamp-chap" = 'icons/stamp_icons/large_stamp-chap.png' + // "stamp-mime" = 'icons/stamp_icons/large_stamp-mime.png', + // "stamp-centcom" = 'icons/stamp_icons/large_stamp-centcom.png', + // "stamp-syndicate" = 'icons/stamp_icons/large_stamp-syndicate.png' ) -/datum/asset/spritesheet/simple/minesweeper - name = "minesweeper" - assets = list( - "1" = 'icons/UI_Icons/minesweeper_tiles/one.png', - "2" = 'icons/UI_Icons/minesweeper_tiles/two.png', - "3" = 'icons/UI_Icons/minesweeper_tiles/three.png', - "4" = 'icons/UI_Icons/minesweeper_tiles/four.png', - "5" = 'icons/UI_Icons/minesweeper_tiles/five.png', - "6" = 'icons/UI_Icons/minesweeper_tiles/six.png', - "7" = 'icons/UI_Icons/minesweeper_tiles/seven.png', - "8" = 'icons/UI_Icons/minesweeper_tiles/eight.png', - "empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png', - "flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png', - "hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png', - "mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png', - "minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png' - ) - -/datum/asset/spritesheet/simple/pills - name = "pills" - assets = list( - "pill1" = 'icons/UI_Icons/Pills/pill1.png', - "pill2" = 'icons/UI_Icons/Pills/pill2.png', - "pill3" = 'icons/UI_Icons/Pills/pill3.png', - "pill4" = 'icons/UI_Icons/Pills/pill4.png', - "pill5" = 'icons/UI_Icons/Pills/pill5.png', - "pill6" = 'icons/UI_Icons/Pills/pill6.png', - "pill7" = 'icons/UI_Icons/Pills/pill7.png', - "pill8" = 'icons/UI_Icons/Pills/pill8.png', - "pill9" = 'icons/UI_Icons/Pills/pill9.png', - "pill10" = 'icons/UI_Icons/Pills/pill10.png', - "pill11" = 'icons/UI_Icons/Pills/pill11.png', - "pill12" = 'icons/UI_Icons/Pills/pill12.png', - "pill13" = 'icons/UI_Icons/Pills/pill13.png', - "pill14" = 'icons/UI_Icons/Pills/pill14.png', - "pill15" = 'icons/UI_Icons/Pills/pill15.png', - "pill16" = 'icons/UI_Icons/Pills/pill16.png', - "pill17" = 'icons/UI_Icons/Pills/pill17.png', - "pill18" = 'icons/UI_Icons/Pills/pill18.png', - "pill19" = 'icons/UI_Icons/Pills/pill19.png', - "pill20" = 'icons/UI_Icons/Pills/pill20.png', - "pill21" = 'icons/UI_Icons/Pills/pill21.png', - "pill22" = 'icons/UI_Icons/Pills/pill22.png', - ) /datum/asset/simple/IRV assets = list( @@ -573,13 +142,11 @@ GLOBAL_LIST_EMPTY(asset_datums) ) /datum/asset/simple/jquery - verify = FALSE assets = list( "jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js', ) /datum/asset/simple/goonchat - verify = FALSE assets = list( "json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js', "browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js', @@ -589,7 +156,6 @@ GLOBAL_LIST_EMPTY(asset_datums) ) /datum/asset/simple/fontawesome - verify = FALSE assets = list( "fa-regular-400.eot" = 'html/font-awesome/webfonts/fa-regular-400.eot', "fa-regular-400.woff" = 'html/font-awesome/webfonts/fa-regular-400.woff', @@ -604,6 +170,7 @@ GLOBAL_LIST_EMPTY(asset_datums) /datum/asset/spritesheet/goonchat/register() InsertAll("emoji", 'icons/emoji.dmi') + InsertAll("emoji", 'icons/emoji_32.dmi') // pre-loading all lanugage icons also helps to avoid meta InsertAll("language", 'icons/misc/language.dmi') @@ -630,6 +197,62 @@ GLOBAL_LIST_EMPTY(asset_datums) "none_button.png" = 'html/none_button.png', ) +/datum/asset/simple/arcade + assets = list( + "boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif', + "boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif', + "boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif', + "boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif', + "boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif', + "boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif', + ) + +/datum/asset/spritesheet/simple/minesweeper + name = "minesweeper" + assets = list( + "1" = 'icons/UI_Icons/minesweeper_tiles/one.png', + "2" = 'icons/UI_Icons/minesweeper_tiles/two.png', + "3" = 'icons/UI_Icons/minesweeper_tiles/three.png', + "4" = 'icons/UI_Icons/minesweeper_tiles/four.png', + "5" = 'icons/UI_Icons/minesweeper_tiles/five.png', + "6" = 'icons/UI_Icons/minesweeper_tiles/six.png', + "7" = 'icons/UI_Icons/minesweeper_tiles/seven.png', + "8" = 'icons/UI_Icons/minesweeper_tiles/eight.png', + "empty" = 'icons/UI_Icons/minesweeper_tiles/empty.png', + "flag" = 'icons/UI_Icons/minesweeper_tiles/flag.png', + "hidden" = 'icons/UI_Icons/minesweeper_tiles/hidden.png', + "mine" = 'icons/UI_Icons/minesweeper_tiles/mine.png', + "minehit" = 'icons/UI_Icons/minesweeper_tiles/minehit.png' + ) + + +/datum/asset/spritesheet/simple/pills + name ="pills" + assets = list( + "pill1" = 'icons/UI_Icons/Pills/pill1.png', + "pill2" = 'icons/UI_Icons/Pills/pill2.png', + "pill3" = 'icons/UI_Icons/Pills/pill3.png', + "pill4" = 'icons/UI_Icons/Pills/pill4.png', + "pill5" = 'icons/UI_Icons/Pills/pill5.png', + "pill6" = 'icons/UI_Icons/Pills/pill6.png', + "pill7" = 'icons/UI_Icons/Pills/pill7.png', + "pill8" = 'icons/UI_Icons/Pills/pill8.png', + "pill9" = 'icons/UI_Icons/Pills/pill9.png', + "pill10" = 'icons/UI_Icons/Pills/pill10.png', + "pill11" = 'icons/UI_Icons/Pills/pill11.png', + "pill12" = 'icons/UI_Icons/Pills/pill12.png', + "pill13" = 'icons/UI_Icons/Pills/pill13.png', + "pill14" = 'icons/UI_Icons/Pills/pill14.png', + "pill15" = 'icons/UI_Icons/Pills/pill15.png', + "pill16" = 'icons/UI_Icons/Pills/pill16.png', + "pill17" = 'icons/UI_Icons/Pills/pill17.png', + "pill18" = 'icons/UI_Icons/Pills/pill18.png', + "pill19" = 'icons/UI_Icons/Pills/pill19.png', + "pill20" = 'icons/UI_Icons/Pills/pill20.png', + "pill21" = 'icons/UI_Icons/Pills/pill21.png', + "pill22" = 'icons/UI_Icons/Pills/pill22.png', + ) + //this exists purely to avoid meta by pre-loading all language icons. /datum/asset/language/register() for(var/path in typesof(/datum/language)) @@ -641,7 +264,7 @@ GLOBAL_LIST_EMPTY(asset_datums) name = "pipes" /datum/asset/spritesheet/pipes/register() - for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi')) + for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi', 'icons/obj/plumbing/fluid_ducts.dmi')) InsertAll("", each, GLOB.alldirs) ..() @@ -708,9 +331,9 @@ GLOBAL_LIST_EMPTY(asset_datums) name = "vending" /datum/asset/spritesheet/vending/register() - for(var/k in GLOB.vending_products) + for (var/k in GLOB.vending_products) var/atom/item = k - if(!ispath(item, /atom)) + if (!ispath(item, /atom)) continue var/icon_file = initial(item.icon) @@ -721,12 +344,12 @@ GLOBAL_LIST_EMPTY(asset_datums) if(icon_state in icon_states_list) I = icon(icon_file, icon_state, SOUTH) var/c = initial(item.color) - if(!isnull(c) && c != "#FFFFFF") + if (!isnull(c) && c != "#FFFFFF") I.Blend(c, ICON_MULTIPLY) else var/icon_states_string - for(var/an_icon_state in icon_states_list) - if(!icon_states_string) + for (var/an_icon_state in icon_states_list) + if (!icon_states_string) icon_states_string = "[json_encode(an_icon_state)](\ref[an_icon_state])" else icon_states_string += ", [json_encode(an_icon_state)](\ref[an_icon_state])" @@ -745,7 +368,31 @@ GLOBAL_LIST_EMPTY(asset_datums) "dna_extra.gif" = 'html/dna_extra.gif' ) +/datum/asset/simple/orbit + assets = list( + "ghost.png" = 'html/ghost.png' + ) + /datum/asset/simple/vv assets = list( "view_variables.css" = 'html/admin/view_variables.css' ) + +/datum/asset/spritesheet/sheetmaterials + name = "sheetmaterials" + +/datum/asset/spritesheet/sheetmaterials/register() + InsertAll("", 'icons/obj/stack_objects.dmi') + + // Special case to handle Bluespace Crystals + Insert("polycrystal", 'icons/obj/telescience.dmi', "polycrystal") + ..() + + +/datum/asset/spritesheet/mafia + name = "mafia" + +/datum/asset/spritesheet/mafia/register() + InsertAll("", 'icons/obj/mafia.dmi') + ..() + diff --git a/code/modules/asset_cache/validate_assets.html b/code/modules/asset_cache/validate_assets.html new file mode 100644 index 0000000000..b27a266c00 --- /dev/null +++ b/code/modules/asset_cache/validate_assets.html @@ -0,0 +1,29 @@ + + + + + + + + + + \ No newline at end of file diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm index 06d73867f8..81e103fba2 100644 --- a/code/modules/atmospherics/environmental/LINDA_fire.dm +++ b/code/modules/atmospherics/environmental/LINDA_fire.dm @@ -9,46 +9,31 @@ return -/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh = FALSE, holo = FALSE) - var/datum/gas_mixture/air_contents = return_air() - if(!air_contents) - return 0 +/turf/open/hotspot_expose(exposed_temperature, exposed_volume, soh) + if(!air) + return - var/oxy = air_contents.gases[/datum/gas/oxygen] - var/tox = air_contents.gases[/datum/gas/plasma] - var/trit = air_contents.gases[/datum/gas/tritium] + var/oxy = air.get_moles(/datum/gas/oxygen) + if (oxy < 0.5) + return + var/tox = air.get_moles(/datum/gas/plasma) + var/trit = air.get_moles(/datum/gas/tritium) if(active_hotspot) if(soh) - if((tox > 0.5 || trit > 0.5) && oxy > 0.5) - if(active_hotspot.temperature < exposed_temperature*50) - active_hotspot.temperature = exposed_temperature*50 + if(tox > 0.5 || trit > 0.5) + if(active_hotspot.temperature < exposed_temperature) + active_hotspot.temperature = exposed_temperature if(active_hotspot.volume < exposed_volume) active_hotspot.volume = exposed_volume - return 1 - - var/igniting = 0 + return if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && (tox > 0.5 || trit > 0.5)) - igniting = 1 - if(igniting) - if(oxy < 0.5) - return 0 - - active_hotspot = new /obj/effect/hotspot(src, holo) - active_hotspot.temperature = exposed_temperature*50 - active_hotspot.volume = exposed_volume*25 + active_hotspot = new /obj/effect/hotspot(src, exposed_volume*25, exposed_temperature) active_hotspot.just_spawned = (current_cycle < SSair.times_fired) //remove just_spawned protection if no longer processing this cell SSair.add_to_active(src, 0) - else - var/datum/gas_mixture/heating = air_contents.remove_ratio(exposed_volume/air_contents.volume) - heating.temperature = exposed_temperature - heating.react() - assume_air(heating) - air_update_turf() - return igniting //This is the icon for fire on turfs, also helps for nurturing small fires until they are full tile /obj/effect/hotspot @@ -67,11 +52,13 @@ var/bypassing = FALSE var/visual_update_tick = 0 -/obj/effect/hotspot/Initialize(mapload, holo = FALSE) +/obj/effect/hotspot/Initialize(mapload, starting_volume, starting_temperature) . = ..() - if(holo) - flags_1 |= HOLOGRAM_1 SSair.hotspots += src + if(!isnull(starting_volume)) + volume = starting_volume + if(!isnull(starting_temperature)) + temperature = starting_temperature perform_exposure() setDir(pick(GLOB.cardinals)) air_update_turf() @@ -83,22 +70,19 @@ location.active_hotspot = src - if(volume > CELL_VOLUME*0.95) - bypassing = TRUE - else - bypassing = FALSE + bypassing = !just_spawned && (volume > CELL_VOLUME*0.95) if(bypassing) - if(!just_spawned) - volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE - temperature = location.air.temperature + volume = location.air.reaction_results["fire"]*FIRE_GROWTH_RATE + temperature = location.air.return_temperature() else - var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.volume) - affected.temperature = temperature - affected.react(src) - temperature = affected.temperature - volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE - location.assume_air(affected) + var/datum/gas_mixture/affected = location.air.remove_ratio(volume/location.air.return_volume()) + if(affected) //in case volume is 0 + affected.set_temperature(temperature) + affected.react(src) + temperature = affected.return_temperature() + volume = affected.reaction_results["fire"]*FIRE_GROWTH_RATE + location.assume_air(affected) for(var/A in location) var/atom/AT = A @@ -164,7 +148,7 @@ color = list(LERP(0.3, 1, 1-greyscale_fire) * heat_r,0.3 * heat_g * greyscale_fire,0.3 * heat_b * greyscale_fire, 0.59 * heat_r * greyscale_fire,LERP(0.59, 1, 1-greyscale_fire) * heat_g,0.59 * heat_b * greyscale_fire, 0.11 * heat_r * greyscale_fire,0.11 * heat_g * greyscale_fire,LERP(0.11, 1, 1-greyscale_fire) * heat_b, 0,0,0) alpha = heat_a -#define INSUFFICIENT(path) (location.air.gases[path] < 0.5) +#define INSUFFICIENT(path) (location.air.get_moles(path) < 0.5) /obj/effect/hotspot/process() if(just_spawned) just_spawned = FALSE @@ -175,8 +159,7 @@ qdel(src) return - if(location.excited_group) - location.excited_group.reset_cooldowns() + location.eg_reset_cooldowns() if((temperature < FIRE_MINIMUM_TEMPERATURE_TO_EXIST) || (volume <= 1)) qdel(src) @@ -186,7 +169,8 @@ return //Not enough to burn - if((location.air.gases[/datum/gas/plasma] < 0.5 && location.air.gases[/datum/gas/tritium] < 0.5) || location.air.gases[/datum/gas/oxygen] < 0.5) + // god damn it previous coder you made the INSUFFICIENT macro for a fucking reason why didn't you use it here smh + if((INSUFFICIENT(/datum/gas/plasma) && INSUFFICIENT(/datum/gas/tritium)) || INSUFFICIENT(/datum/gas/oxygen)) qdel(src) return @@ -194,16 +178,15 @@ if(bypassing) icon_state = "3" - if(!(flags_1 & HOLOGRAM_1)) - location.burn_tile() + location.burn_tile() //Possible spread due to radiated heat - if(location.air.temperature > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD) - var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE + if(location.air.return_temperature() > FIRE_MINIMUM_TEMPERATURE_TO_SPREAD) + var/radiated_temperature = location.air.return_temperature()*FIRE_SPREAD_RADIOSITY_SCALE for(var/t in location.atmos_adjacent_turfs) var/turf/open/T = t if(!T.active_hotspot) - T.hotspot_expose(radiated_temperature, CELL_VOLUME/4, flags_1 & HOLOGRAM_1) + T.hotspot_expose(radiated_temperature, CELL_VOLUME/4) else if(volume > CELL_VOLUME*0.4) @@ -227,14 +210,13 @@ var/turf/open/T = loc if(istype(T) && T.active_hotspot == src) T.active_hotspot = null - if(!(flags_1 & HOLOGRAM_1)) - DestroyTurf() + DestroyTurf() return ..() /obj/effect/hotspot/proc/DestroyTurf() if(isturf(loc)) var/turf/T = loc - if(T.to_be_destroyed) + if(T.to_be_destroyed && !T.changing_turf) var/chance_of_deletion if (T.heat_capacity) //beware of division by zero chance_of_deletion = T.max_fire_temperature_sustained / T.heat_capacity * 8 //there is no problem with prob(23456), min() was redundant --rastaf0 diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm index 760e4e22da..4f057ca9be 100644 --- a/code/modules/atmospherics/environmental/LINDA_system.dm +++ b/code/modules/atmospherics/environmental/LINDA_system.dm @@ -18,7 +18,7 @@ /turf/open/CanAtmosPass(turf/T, vertical = FALSE) var/dir = vertical? get_dir_multiz(src, T) : get_dir(src, T) - var/opp = dir_inverse_multiz(dir) + var/opp = REVERSE_DIR(dir) var/R = FALSE if(vertical && !(zAirOut(dir, T) && T.zAirIn(dir, src))) R = TRUE @@ -44,25 +44,32 @@ return FALSE /turf/proc/ImmediateCalculateAdjacentTurfs() - var/canpass = CANATMOSPASS(src, src) + var/canpass = CANATMOSPASS(src, src) var/canvpass = CANVERTICALATMOSPASS(src, src) for(var/direction in GLOB.cardinals_multiz) var/turf/T = get_step_multiz(src, direction) + var/opp_dir = REVERSE_DIR(direction) if(!isopenturf(T)) continue if(!(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) ) LAZYINITLIST(atmos_adjacent_turfs) LAZYINITLIST(T.atmos_adjacent_turfs) - atmos_adjacent_turfs[T] = TRUE - T.atmos_adjacent_turfs[src] = TRUE + atmos_adjacent_turfs[T] = direction + T.atmos_adjacent_turfs[src] = opp_dir + T.__update_extools_adjacent_turfs() else if (atmos_adjacent_turfs) atmos_adjacent_turfs -= T if (T.atmos_adjacent_turfs) T.atmos_adjacent_turfs -= src + T.__update_extools_adjacent_turfs() UNSETEMPTY(T.atmos_adjacent_turfs) UNSETEMPTY(atmos_adjacent_turfs) src.atmos_adjacent_turfs = atmos_adjacent_turfs + __update_extools_adjacent_turfs() + +/turf/proc/__update_extools_adjacent_turfs() + //returns a list of adjacent turfs that can share air with this one. //alldir includes adjacent diagonal tiles that can share @@ -111,9 +118,9 @@ SSair.add_to_active(src,command) /atom/movable/proc/move_update_air(turf/T) - if(isturf(T)) - T.air_update_turf(1) - air_update_turf(1) + if(isturf(T)) + T.air_update_turf(1) + air_update_turf(1) /atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires var/turf/open/T = get_turf(src) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 081f0b1d28..2b43319904 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -8,6 +8,7 @@ var/list/atmos_adjacent_turfs //bitfield of dirs in which we are superconducitng var/atmos_supeconductivity = NONE + var/is_openturf = FALSE // used by extools shizz. //used to determine whether we should archive var/archived_cycle = 0 @@ -23,21 +24,21 @@ //used for spacewind var/pressure_difference = 0 var/pressure_direction = 0 + var/turf/pressure_specific_target - var/datum/excited_group/excited_group - var/excited = FALSE var/datum/gas_mixture/turf/air var/obj/effect/hotspot/active_hotspot - var/atmos_cooldown = 0 var/planetary_atmos = FALSE //air will revert to initial_gas_mix over time var/list/atmos_overlay_types //gas IDs of current active gas overlays + is_openturf = TRUE /turf/open/Initialize() if(!blocks_air) air = new air.copy_from_turf(src) + update_air_ref() . = ..() /turf/open/Destroy() @@ -48,6 +49,8 @@ SSair.add_to_active(T) return ..() +/turf/proc/update_air_ref() + /////////////////GAS MIXTURE PROCS/////////////////// /turf/open/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air @@ -89,15 +92,37 @@ temperature_archived = temperature /turf/open/archive() - ARCHIVE(air) + air.archive() archived_cycle = SSair.times_fired temperature_archived = temperature +/turf/open/proc/eg_reset_cooldowns() +/turf/open/proc/eg_garbage_collect() +/turf/open/proc/get_excited() +/turf/open/proc/set_excited() + /////////////////////////GAS OVERLAYS////////////////////////////// + /turf/open/proc/update_visuals() - var/list/new_overlay_types = tile_graphic() + var/list/atmos_overlay_types = src.atmos_overlay_types // Cache for free performance + var/list/new_overlay_types = list() + var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays() + + if(!air) // 2019-05-14: was not able to get this path to fire in testing. Consider removing/looking at callers -Naksu + if (atmos_overlay_types) + for(var/overlay in atmos_overlay_types) + vis_contents -= overlay + src.atmos_overlay_types = null + return + + for(var/id in air.get_gases()) + if (nonoverlaying_gases[id]) + continue + var/gas_overlay = GLOB.meta_gas_overlays[id] + if(gas_overlay && air.get_moles(id) > GLOB.meta_gas_visibility[META_GAS_MOLES_VISIBLE]) + new_overlay_types += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(air.get_moles(id) / MOLES_GAS_VISIBLE_STEP, 1))] if (atmos_overlay_types) for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added @@ -112,19 +137,18 @@ UNSETEMPTY(new_overlay_types) src.atmos_overlay_types = new_overlay_types -/turf/open/proc/tile_graphic() - var/static/list/nonoverlaying_gases = typecache_of_gases_with_no_overlays() - if(!air) - return - . = new /list - var/list/gases = air.gases - for(var/id in gases) - if (nonoverlaying_gases[id]) - continue - var/gas = gases[id] - var/gas_overlay = GLOB.meta_gas_overlays[id] - if(gas_overlay && gas > GLOB.meta_gas_visibility[id]) - . += gas_overlay[min(FACTOR_GAS_VISIBLE_MAX, CEILING(gas / MOLES_GAS_VISIBLE_STEP, 1))] +/turf/open/proc/set_visuals(list/new_overlay_types) + if (atmos_overlay_types) + for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added + vis_contents -= overlay + + if (length(new_overlay_types)) + if (atmos_overlay_types) + vis_contents += new_overlay_types - atmos_overlay_types //don't add overlays that already exist + else + vis_contents += new_overlay_types + UNSETEMPTY(new_overlay_types) + src.atmos_overlay_types = new_overlay_types /proc/typecache_of_gases_with_no_overlays() . = list() @@ -135,8 +159,8 @@ /////////////////////////////SIMULATION/////////////////////////////////// -#define LAST_SHARE_CHECK \ - var/last_share = our_air.last_share;\ +/*#define LAST_SHARE_CHECK \ + var/last_share = our_air.get_last_share();\ if(last_share > MINIMUM_AIR_TO_SUSPEND){\ our_excited_group.reset_cooldowns();\ cached_atmos_cooldown = 0;\ @@ -144,127 +168,62 @@ our_excited_group.dismantle_cooldown = 0;\ cached_atmos_cooldown = 0;\ } - +*/ /turf/proc/process_cell(fire_count) SSair.remove_from_active(src) -/turf/open/process_cell(fire_count) - if(archived_cycle < fire_count) //archive self if not already done - archive() - - current_cycle = fire_count - - //cache for sanic speed - var/list/adjacent_turfs = atmos_adjacent_turfs - var/datum/excited_group/our_excited_group = excited_group - var/adjacent_turfs_length = LAZYLEN(adjacent_turfs) - var/cached_atmos_cooldown = atmos_cooldown + 1 - - var/planet_atmos = planetary_atmos - if (planet_atmos) - adjacent_turfs_length++ - - var/datum/gas_mixture/our_air = air - - for(var/t in adjacent_turfs) - var/turf/open/enemy_tile = t - - if(fire_count <= enemy_tile.current_cycle) +/turf/open/proc/equalize_pressure_in_zone(cyclenum) +/turf/open/proc/consider_firelocks(turf/T2) + var/reconsider_adj = FALSE + for(var/obj/machinery/door/firedoor/FD in T2) + if((FD.flags_1 & ON_BORDER_1) && get_dir(T2, src) != FD.dir) continue - enemy_tile.archive() + FD.emergency_pressure_stop() + reconsider_adj = TRUE + for(var/obj/machinery/door/firedoor/FD in src) + if((FD.flags_1 & ON_BORDER_1) && get_dir(src, T2) != FD.dir) + continue + FD.emergency_pressure_stop() + reconsider_adj = TRUE + if(reconsider_adj) + T2.ImmediateCalculateAdjacentTurfs() // We want those firelocks closed yesterday. - /******************* GROUP HANDLING START *****************************************************************/ +/turf/proc/handle_decompression_floor_rip() +/turf/open/floor/handle_decompression_floor_rip(sum) + if(sum > 20 && prob(clamp(sum / 10, 0, 30))) + remove_tile() - var/should_share_air = FALSE - var/datum/gas_mixture/enemy_air = enemy_tile.air - - //cache for sanic speed - var/datum/excited_group/enemy_excited_group = enemy_tile.excited_group - - if(our_excited_group && enemy_excited_group) - if(our_excited_group != enemy_excited_group) - //combine groups (this also handles updating the excited_group var of all involved turfs) - our_excited_group.merge_groups(enemy_excited_group) - our_excited_group = excited_group //update our cache - should_share_air = TRUE - - else if(our_air.compare(enemy_air)) - if(!enemy_tile.excited) - SSair.add_to_active(enemy_tile) - var/datum/excited_group/EG = our_excited_group || enemy_excited_group || new - if(!our_excited_group) - EG.add_turf(src) - if(!enemy_excited_group) - EG.add_turf(enemy_tile) - our_excited_group = excited_group - should_share_air = TRUE - - //air sharing - if(should_share_air) - var/difference = our_air.share(enemy_air, adjacent_turfs_length) - if(difference) - if(difference > 0) - consider_pressure_difference(enemy_tile, difference) - else - enemy_tile.consider_pressure_difference(src, -difference) - LAST_SHARE_CHECK - - - /******************* GROUP HANDLING FINISH *********************************************************************/ - - if (planet_atmos) //share our air with the "atmosphere" "above" the turf - var/datum/gas_mixture/G = new - G.copy_from_turf(src) - ARCHIVE(G) - if(our_air.compare(G)) - if(!our_excited_group) - var/datum/excited_group/EG = new - EG.add_turf(src) - our_excited_group = excited_group - our_air.share(G, adjacent_turfs_length) - LAST_SHARE_CHECK - - SSair.add_to_react_queue(src) - - if((!our_excited_group && !(our_air.temperature > MINIMUM_TEMPERATURE_START_SUPERCONDUCTION && consider_superconductivity(starting = TRUE))) \ - || (cached_atmos_cooldown > (EXCITED_GROUP_DISMANTLE_CYCLES * 2))) - SSair.remove_from_active(src) - - atmos_cooldown = cached_atmos_cooldown - -/turf/open/space/process_cell(fire_count) //dumb hack to prevent space pollution - . = ..() - var/datum/gas_mixture/immutable/I = space_gas - I.after_process_cell() - -/turf/proc/process_cell_reaction() - SSair.remove_from_react_queue(src) - -/turf/open/process_cell_reaction() - air.react(src) - update_visuals() - SSair.remove_from_react_queue(src) - return +/turf/open/process_cell(fire_count) //////////////////////////SPACEWIND///////////////////////////// /turf/open/proc/consider_pressure_difference(turf/T, difference) - SSair.high_pressure_delta |= src if(difference > pressure_difference) pressure_direction = get_dir(src, T) pressure_difference = difference + SSair.high_pressure_delta[src] = TRUE /turf/open/proc/high_pressure_movements() - var/atom/movable/M - for(var/thing in src) - M = thing - if (!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired) - M.experience_pressure_difference(pressure_difference, pressure_direction) + var/diff = pressure_difference + if(locate(/obj/structure/rack) in src) + diff *= 0.1 + else if(locate(/obj/structure/table) in src) + diff *= 0.2 + for(var/obj/M in src) + if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired) + M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target) + for(var/mob/M in src) + if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired) + M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target) + /* + if(pressure_difference > 100) + new /obj/effect/temp_visual/dir_setting/space_wind(src, pressure_direction, clamp(round(sqrt(pressure_difference) * 2), 10, 255)) + */ /atom/movable/var/pressure_resistance = 10 /atom/movable/var/last_high_pressure_movement_air_cycle = 0 -/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0) +/atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target) var/const/PROBABILITY_OFFSET = 25 var/const/PROBABILITY_BASE_PRECENT = 75 var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5) @@ -275,93 +234,8 @@ move_prob += pressure_resistance_prob_delta if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO)))) step(src, direction) - last_high_pressure_movement_air_cycle = SSair.times_fired - -///////////////////////////EXCITED GROUPS///////////////////////////// - -/datum/excited_group - var/list/turf_list = list() - var/breakdown_cooldown = 0 - var/dismantle_cooldown = 0 - -/datum/excited_group/New() - SSair.excited_groups += src - -/datum/excited_group/proc/add_turf(turf/open/T) - turf_list += T - T.excited_group = src - reset_cooldowns() - -/datum/excited_group/proc/merge_groups(datum/excited_group/E) - if(turf_list.len > E.turf_list.len) - SSair.excited_groups -= E - for(var/t in E.turf_list) - var/turf/open/T = t - T.excited_group = src - turf_list += T - reset_cooldowns() - else - SSair.excited_groups -= src - for(var/t in turf_list) - var/turf/open/T = t - T.excited_group = E - E.turf_list += T - E.reset_cooldowns() - -/datum/excited_group/proc/reset_cooldowns() - breakdown_cooldown = 0 - dismantle_cooldown = 0 - -//argument is so world start can clear out any turf differences quickly. -/datum/excited_group/proc/self_breakdown(space_is_all_consuming = FALSE) - var/datum/gas_mixture/A = new - - //make local for sanic speed - var/list/A_gases = A.gases - var/list/turf_list = src.turf_list - var/turflen = turf_list.len - var/space_in_group = FALSE - - for(var/t in turf_list) - var/turf/open/T = t - if (space_is_all_consuming && !space_in_group && istype(T.air, /datum/gas_mixture/immutable/space)) - space_in_group = TRUE - qdel(A) - A = new /datum/gas_mixture/immutable/space() - A_gases = A.gases //update the cache - break - A.merge(T.air) - - for(var/id in A_gases) - A_gases[id] /= turflen - - for(var/t in turf_list) - var/turf/open/T = t - T.air.copy_from(A) - T.atmos_cooldown = 0 - T.update_visuals() - - breakdown_cooldown = 0 - -/datum/excited_group/proc/dismantle() - for(var/t in turf_list) - var/turf/open/T = t - T.excited = FALSE - T.excited_group = null - SSair.active_turfs -= T - garbage_collect() - -/datum/excited_group/proc/garbage_collect() - for(var/t in turf_list) - var/turf/open/T = t - T.excited_group = null - turf_list.Cut() - SSair.excited_groups -= src ////////////////////////SUPERCONDUCTIVITY///////////////////////////// -/atom/movable/proc/blocksTemperature() - return FALSE - /turf/proc/conductivity_directions() if(archived_cycle < SSair.times_fired) archive() @@ -376,9 +250,6 @@ . |= direction /turf/proc/neighbor_conduct_with_src(turf/open/other) - for (var/atom/movable/G in src) - if (G.blocksTemperature()) - return if(!other.blocks_air) //Open but neighbor is solid other.temperature_share_open_to_solid(src) else //Both tiles are solid @@ -389,9 +260,7 @@ if(blocks_air) ..() return - for (var/atom/movable/G in src) - if (G.blocksTemperature()) - return + if(!other.blocks_air) //Both tiles are open var/turf/open/T = other T.air.temperature_share(air, WINDOW_HEAT_TRANSFER_COEFFICIENT) @@ -410,8 +279,10 @@ if(!neighbor.thermal_conductivity) continue + if(neighbor.archived_cycle < SSair.times_fired) neighbor.archive() + neighbor.neighbor_conduct_with_src(src) neighbor.consider_superconductivity() @@ -430,17 +301,18 @@ //Conduct with air on my tile if I have it if(!blocks_air) temperature = air.temperature_share(null, thermal_conductivity, temperature, heat_capacity) - ..((blocks_air ? temperature : air.temperature)) + ..((blocks_air ? temperature : air.return_temperature())) /turf/proc/consider_superconductivity() if(!thermal_conductivity) return FALSE - SSair.active_super_conductivity |= src + SSair.active_super_conductivity[src] = TRUE + return TRUE /turf/open/consider_superconductivity(starting) - if(air.temperature < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) + if(air.return_temperature() < (starting?MINIMUM_TEMPERATURE_START_SUPERCONDUCTION:MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION)) return FALSE if(air.heat_capacity() < M_CELL_WITH_RATIO) // Was: MOLES_CELLSTANDARD*0.1*0.05 Since there are no variables here we can make this a constant. return FALSE diff --git a/code/modules/atmospherics/gasmixtures/gas_mixture.dm b/code/modules/atmospherics/gasmixtures/gas_mixture.dm index 58e826b36d..e86b249be6 100644 --- a/code/modules/atmospherics/gasmixtures/gas_mixture.dm +++ b/code/modules/atmospherics/gasmixtures/gas_mixture.dm @@ -16,90 +16,154 @@ GLOBAL_LIST_INIT(meta_gas_dangers, meta_gas_danger_list()) 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 - var/last_share = 0 - var/list/reaction_results = list() + /// Never ever set this variable, hooked into vv_get_var for view variables viewing. + var/gas_list_view_only + var/initial_volume = CELL_VOLUME //liters + var/list/reaction_results var/list/analyzer_results //used for analyzer feedback - not initialized until its used - var/gc_share = FALSE // Whether to call garbage_collect() on the sharer during shares, used for immutable mixtures + var/_extools_pointer_gasmixture = 0 // Contains the memory address of the shared_ptr object for this gas mixture in c++ land. Don't. Touch. This. Var. /datum/gas_mixture/New(volume) if (!isnull(volume)) - src.volume = volume + initial_volume = volume + ATMOS_EXTOOLS_CHECK + __gasmixture_register() + reaction_results = new - //PV = nRT +/datum/gas_mixture/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, _extools_pointer_gasmixture)) + return FALSE // please no. segfaults bad. + if(var_name == NAMEOF(src, gas_list_view_only)) + return FALSE + return ..() -/datum/gas_mixture/proc/heat_capacity() +/datum/gas_mixture/vv_get_var(var_name) + . = ..() + if(var_name == NAMEOF(src, gas_list_view_only)) + var/list/dummy = get_gases() + for(var/gas in dummy) + dummy[gas] = get_moles(gas) + dummy["TEMP"] = return_temperature() + dummy["PRESSURE"] = return_pressure() + dummy["HEAT CAPACITY"] = heat_capacity() + dummy["TOTAL MOLES"] = total_moles() + dummy["VOLUME"] = return_volume() + dummy["THERMAL ENERGY"] = thermal_energy() + return debug_variable("gases (READ ONLY)", dummy, 0, src) -/datum/gas_mixture/proc/archived_heat_capacity() +/datum/gas_mixture/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION("", "---") + VV_DROPDOWN_OPTION(VV_HK_PARSE_GASSTRING, "Parse Gas String") + VV_DROPDOWN_OPTION(VV_HK_EMPTY, "Empty") + VV_DROPDOWN_OPTION(VV_HK_SET_MOLES, "Set Moles") + VV_DROPDOWN_OPTION(VV_HK_SET_TEMPERATURE, "Set Temperature") + VV_DROPDOWN_OPTION(VV_HK_SET_VOLUME, "Set Volume") -/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 - for(var/id in cached_gases) - . += cached_gases[id] * cached_gasheats[id] +/datum/gas_mixture/vv_do_topic(list/href_list) + . = ..() if(!.) - . += HEAT_CAPACITY_VACUUM //we want vacuums in turfs to have the same heat capacity as space + return + if(href_list[VV_HK_PARSE_GASSTRING]) + var/gasstring = input(usr, "Input Gas String (WARNING: Advanced. Don't use this unless you know how these work.", "Gas String Parse") as text|null + if(!istext(gasstring)) + return + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set to gas string [gasstring].") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set to gas string [gasstring].") + parse_gas_string(gasstring) + if(href_list[VV_HK_EMPTY]) + log_admin("[key_name(usr)] emptied gas mixture [REF(src)].") + message_admins("[key_name(usr)] emptied gas mixture [REF(src)].") + clear() + if(href_list[VV_HK_SET_MOLES]) + var/list/gases = get_gases() + for(var/gas in gases) + gases[gas] = get_moles(gas) + var/gastype = input(usr, "What kind of gas?", "Set Gas") as null|anything in subtypesof(/datum/gas) + if(!ispath(gastype, /datum/gas)) + return + var/amount = input(usr, "Input amount", "Set Gas", gases[gastype] || 0) as num|null + if(!isnum(amount)) + return + amount = max(0, amount) + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Set gas type [gastype] to [amount] moles.") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Set gas type [gastype] to [amount] moles.") + set_moles(gastype, amount) + if(href_list[VV_HK_SET_TEMPERATURE]) + var/temp = input(usr, "Set the temperature of this mixture to?", "Set Temperature", return_temperature()) as num|null + if(!isnum(temp)) + return + temp = max(2.7, temp) + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Changed temperature to [temp].") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Changed temperature to [temp].") + set_temperature(temp) + if(href_list[VV_HK_SET_VOLUME]) + var/volume = input(usr, "Set the volume of this mixture to?", "Set Volume", return_volume()) as num|null + if(!isnum(volume)) + return + volume = max(0, volume) + log_admin("[key_name(usr)] modified gas mixture [REF(src)]: Changed volume to [volume].") + message_admins("[key_name(usr)] modified gas mixture [REF(src)]: Changed volume to [volume].") + set_volume(volume) -/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/Del() + __gasmixture_unregister() + . = ..()*/ + +/datum/gas_mixture/proc/__gasmixture_unregister() +/datum/gas_mixture/proc/__gasmixture_register() + +/proc/gas_types() + var/list/L = subtypesof(/datum/gas) + for(var/gt in L) + var/datum/gas/G = gt + L[gt] = initial(G.specific_heat) + return L + +/datum/gas_mixture/proc/heat_capacity() //joules per kelvin /datum/gas_mixture/proc/total_moles() - var/cached_gases = gases - TOTAL_MOLES(cached_gases, .) /datum/gas_mixture/proc/return_pressure() //kilopascals - if(volume > 0) // to prevent division by zero - var/cached_gases = gases - TOTAL_MOLES(cached_gases, .) - . *= R_IDEAL_GAS_EQUATION * temperature / volume - return - return 0 /datum/gas_mixture/proc/return_temperature() //kelvins - return temperature + +/datum/gas_mixture/proc/set_min_heat_capacity(n) +/datum/gas_mixture/proc/set_temperature(new_temp) +/datum/gas_mixture/proc/set_volume(new_volume) +/datum/gas_mixture/proc/get_moles(gas_type) +/datum/gas_mixture/proc/set_moles(gas_type, moles) +/datum/gas_mixture/proc/scrub_into(datum/gas_mixture/target, list/gases) +/datum/gas_mixture/proc/mark_immutable() +/datum/gas_mixture/proc/get_gases() +/datum/gas_mixture/proc/multiply(factor) +/datum/gas_mixture/proc/get_last_share() +/datum/gas_mixture/proc/clear() + +/datum/gas_mixture/proc/adjust_moles(gas_type, amt = 0) + set_moles(gas_type, get_moles(gas_type) + amt) /datum/gas_mixture/proc/return_volume() //liters - return max(0, volume) /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. + //Merges all air from giver into self. giver is untouched. //Returns: 1 if we are mutable, 0 otherwise /datum/gas_mixture/proc/remove(amount) - //Proportionally removes amount of gas from the gas_mixture + //Removes amount of gas from the gas_mixture //Returns: gas_mixture with the gases removed +/datum/gas_mixture/proc/transfer_to(datum/gas_mixture/target, amount) + //Transfers amount of gas to target. Equivalent to target.merge(remove(amount)) but faster. + //Removes amount of gas from the gas_mixture + /datum/gas_mixture/proc/remove_ratio(ratio) //Proportionally removes amount of gas from the gas_mixture //Returns: gas_mixture with the gases removed @@ -136,245 +200,63 @@ 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) - return 0 - - //heat transfer - if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/self_heat_capacity = heat_capacity() - var/giver_heat_capacity = giver.heat_capacity() - var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity - if(combined_heat_capacity) - temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity - - var/list/cached_gases = gases //accessing datum vars is slower than proc vars - var/list/giver_gases = giver.gases - //gas transfer - for(var/giver_id in giver_gases) - cached_gases[giver_id] += giver_gases[giver_id] - - return 1 - +/datum/gas_mixture/proc/__remove() /datum/gas_mixture/remove(amount) - var/sum - var/list/cached_gases = gases - TOTAL_MOLES(cached_gases, sum) - amount = min(amount, sum) //Can not take more air than tile has! - if(amount <= 0) - return null var/datum/gas_mixture/removed = new type - var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars - - removed.temperature = temperature - for(var/id in cached_gases) - removed_gases[id] = QUANTIZE((cached_gases[id] / sum) * amount) - cached_gases[id] -= removed_gases[id] - GAS_GARBAGE_COLLECT(gases) + __remove(removed, amount) return removed +/datum/gas_mixture/proc/__remove_ratio() /datum/gas_mixture/remove_ratio(ratio) - if(ratio <= 0) - return null - ratio = min(ratio, 1) - - var/list/cached_gases = gases var/datum/gas_mixture/removed = new type - var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars - - removed.temperature = temperature - for(var/id in cached_gases) - removed_gases[id] = QUANTIZE(cached_gases[id] * ratio) - cached_gases[id] -= removed_gases[id] - - GAS_GARBAGE_COLLECT(gases) + __remove_ratio(removed, ratio) return removed /datum/gas_mixture/copy() - var/list/cached_gases = gases var/datum/gas_mixture/copy = new type - var/list/copy_gases = copy.gases - - copy.temperature = temperature - for(var/id in cached_gases) - copy_gases[id] = cached_gases[id] + copy.copy_from(src) return copy - -/datum/gas_mixture/copy_from(datum/gas_mixture/sample) - var/list/cached_gases = gases //accessing datum vars is slower than proc vars - var/list/sample_gases = sample.gases - - temperature = sample.temperature - for(var/id in sample_gases) - cached_gases[id] = sample_gases[id] - - //remove all gases not in the sample - cached_gases &= sample_gases - - return 1 - /datum/gas_mixture/copy_from_turf(turf/model) parse_gas_string(model.initial_gas_mix) //acounts for changes in temperature var/turf/model_parent = model.parent_type if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature)) - temperature = model.temperature + set_temperature(model.temperature) return 1 /datum/gas_mixture/parse_gas_string(gas_string) - var/list/gases = src.gases var/list/gas = params2list(gas_string) if(gas["TEMP"]) - temperature = text2num(gas["TEMP"]) + set_temperature(text2num(gas["TEMP"])) gas -= "TEMP" - gases.Cut() + clear() for(var/id in gas) var/path = id if(!ispath(path)) path = gas_id2path(path) //a lot of these strings can't have embedded expressions (especially for mappers), so support for IDs needs to stick around - gases[path] = text2num(gas[id]) + set_moles(path, text2num(gas[id])) archive() return 1 -/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4) - - var/list/cached_gases = gases - var/list/sharer_gases = sharer.gases - - var/temperature_delta = temperature_archived - sharer.temperature_archived - var/abs_temperature_delta = abs(temperature_delta) - - var/old_self_heat_capacity = 0 - var/old_sharer_heat_capacity = 0 - if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - old_self_heat_capacity = heat_capacity() - old_sharer_heat_capacity = sharer.heat_capacity() - - var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer - var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us - - var/moved_moles = 0 - var/abs_moved_moles = 0 - - //we're gonna define these vars outside of this for loop because as it turns out, var declaration is pricy - var/delta - var/gas_heat_capacity - //and also cache this shit rq because that results in sanic speed for reasons byond explanation - var/list/cached_gasheats = GLOB.meta_gas_specific_heats - //GAS TRANSFER - for(var/id in cached_gases | sharer_gases) // transfer gases - - 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] - if(delta > 0) - heat_capacity_self_to_sharer += gas_heat_capacity - else - heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative. - - cached_gases[id] -= delta - sharer_gases[id] += delta - moved_moles += delta - abs_moved_moles += abs(delta) - - last_share = abs_moved_moles - - //THERMAL ENERGY TRANSFER - if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) - var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer - var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self - - //transfer of thermal energy (via changed heat capacity) between self and sharer - if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) - temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity - - if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) - sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity - //thermal energy of the system (self and sharer) is unchanged - - if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY) - if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity - temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT) - - if (initial(sharer.gc_share)) - GAS_GARBAGE_COLLECT(sharer.gases) - if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) - var/our_moles - TOTAL_MOLES(cached_gases,our_moles) - var/their_moles - TOTAL_MOLES(sharer_gases,their_moles) - return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume - -/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity) - //transfer of thermal energy (via conduction) between self and sharer - if(sharer) - 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 = 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* \ - (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) - - temperature = max(temperature - heat/self_heat_capacity, TCMB) - sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB) - if(sharer) - sharer.temperature = sharer_temperature - return sharer_temperature - //thermal energy of the system (self and sharer) is unchanged - -/datum/gas_mixture/compare(datum/gas_mixture/sample) - var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars - var/list/cached_gases = gases - - for(var/id in cached_gases | sample_gases) // compare gases from either mixture - var/gas_moles = cached_gases[id] - var/sample_moles = sample_gases[id] - var/delta = abs(gas_moles - sample_moles) - if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \ - delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE) - return id - - var/our_moles - TOTAL_MOLES(cached_gases, our_moles) - if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE) - var/temp = temperature - var/sample_temp = sample.temperature - - var/temperature_delta = abs(temp - sample_temp) - if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) - return "temp" - - return "" - /datum/gas_mixture/react(datum/holder) . = NO_REACTION - var/list/cached_gases = gases - if(!length(cached_gases)) + if(!total_moles()) return var/list/reactions = list() for(var/datum/gas_reaction/G in SSair.gas_reactions) - if(cached_gases[G.major_gas]) + if(get_moles(G.major_gas)) reactions += G if(!length(reactions)) return reaction_results = new - var/temp = temperature - var/ener = THERMAL_ENERGY(src) + var/temp = return_temperature() + var/ener = thermal_energy() reaction_loop: for(var/r in reactions) @@ -388,14 +270,13 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) for(var/id in min_reqs) if (id == "TEMP" || id == "ENER") continue - if(cached_gases[id] < min_reqs[id]) + if(get_moles(id) < min_reqs[id]) continue reaction_loop //at this point, all minimum requirements for the reaction are satisfied. /* currently no reactions have maximum requirements, so we can leave the checks commented out for a slight performance boost PLEASE DO NOT REMOVE THIS CODE. the commenting is here only for a performance increase. enabling these checks should be as easy as possible and the fact that they are disabled should be as clear as possible - var/list/max_reqs = reaction.max_requirements if((max_reqs["TEMP"] && temp > max_reqs["TEMP"]) \ || (max_reqs["ENER"] && ener > max_reqs["ENER"])) @@ -410,8 +291,6 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) . |= reaction.react(src, holder) if (. & STOP_REACTIONS) break - if(.) - GAS_GARBAGE_COLLECT(gases) //Takes the amount of the gas you want to PP as an argument //So I don't have to do some hacky switches/defines/magic strings @@ -420,16 +299,50 @@ GLOBAL_LIST_INIT(meta_gas_fusions, meta_gas_fusion_list()) //O2_PP = get_partial_pressure(gas_mixture.oxygen) /datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure) - return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME + return (gas_pressure * R_IDEAL_GAS_EQUATION * return_temperature()) / BREATH_VOLUME //inverse /datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure) - return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature) + return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * return_temperature()) //Mathematical proofs: /* get_breath_partial_pressure(gas_pp) --> gas_pp/total_moles()*breath_pp = pp get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles() - 10/20*5 = 2.5 10 = 2.5/5*20 */ + +/datum/gas_mixture/turf + +/* +/mob/verb/profile_atmos() + /world{loop_checks = 0;} + var/datum/gas_mixture/A = new + var/datum/gas_mixture/B = new + A.parse_gas_string("o2=200;n2=800;TEMP=50") + B.parse_gas_string("co2=500;plasma=500;TEMP=5000") + var/pa + var/pb + pa = world.tick_usage + for(var/I in 1 to 100000) + B.transfer_to(A, 1) + A.transfer_to(B, 1) + pb = world.tick_usage + var/total_time = (pb-pa) * world.tick_lag + to_chat(src, "Total time (gas transfer): [total_time]ms") + to_chat(src, "Operations per second: [100000 / (total_time/1000)]") + pa = world.tick_usage + for(var/I in 1 to 100000) + B.total_moles(); + pb = world.tick_usage + total_time = (pb-pa) * world.tick_lag + to_chat(src, "Total time (total_moles): [total_time]ms") + to_chat(src, "Operations per second: [100000 / (total_time/1000)]") + pa = world.tick_usage + for(var/I in 1 to 100000) + new /datum/gas_mixture + pb = world.tick_usage + total_time = (pb-pa) * world.tick_lag + to_chat(src, "Total time (new gas mixture): [total_time]ms") + to_chat(src, "Operations per second: [100000 / (total_time/1000)]") +*/ diff --git a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm index 5527ba3fef..eefad7c970 100644 --- a/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm +++ b/code/modules/atmospherics/gasmixtures/immutable_mixtures.dm @@ -2,73 +2,29 @@ //it can be changed, but any changes will ultimately be undone before they can have any effect /datum/gas_mixture/immutable - var/initial_temperature - gc_share = TRUE + var/initial_temperature = 0 /datum/gas_mixture/immutable/New() ..() - temperature = initial_temperature - temperature_archived = initial_temperature - gases.Cut() + set_temperature(initial_temperature) + populate() + mark_immutable() -/datum/gas_mixture/immutable/merge() - return 0 //we're immutable. +/datum/gas_mixture/immutable/proc/populate() + return -/datum/gas_mixture/immutable/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4) - . = ..(sharer, 0) - temperature = initial_temperature - temperature_archived = initial_temperature - gases.Cut() - -/datum/gas_mixture/immutable/react() - return 0 //we're immutable. - -/datum/gas_mixture/immutable/copy() - return new type //we're immutable, so we can just return a new instance. - -/datum/gas_mixture/immutable/copy_from() - return 0 //we're immutable. - -/datum/gas_mixture/immutable/copy_from_turf() - return 0 //we're immutable. - -/datum/gas_mixture/immutable/parse_gas_string() - return 0 //we're immutable. - -/datum/gas_mixture/immutable/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity) - . = ..() - temperature = initial_temperature - -/datum/gas_mixture/immutable/proc/after_process_cell() - temperature = initial_temperature - temperature_archived = initial_temperature - gases.Cut() //used by space tiles /datum/gas_mixture/immutable/space initial_temperature = TCMB -/datum/gas_mixture/immutable/space/heat_capacity() - return HEAT_CAPACITY_VACUUM - -/datum/gas_mixture/immutable/space/remove() - return copy() //we're always empty, so we can just return a copy. - -/datum/gas_mixture/immutable/space/remove_ratio() - return copy() //we're always empty, so we can just return a copy. - +/datum/gas_mixture/immutable/space/populate() + set_min_heat_capacity(HEAT_CAPACITY_VACUUM) //used by cloners /datum/gas_mixture/immutable/cloner initial_temperature = T20C -/datum/gas_mixture/immutable/cloner/New() +/datum/gas_mixture/immutable/cloner/populate() ..() - gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD - -/datum/gas_mixture/immutable/cloner/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4) - . = ..(sharer, 0) - gases[/datum/gas/nitrogen] = MOLES_O2STANDARD + MOLES_N2STANDARD - -/datum/gas_mixture/immutable/cloner/heat_capacity() - return (MOLES_O2STANDARD + MOLES_N2STANDARD)*20 //specific heat of nitrogen is 20 + set_moles(/datum/gas/nitrogen, MOLES_O2STANDARD + MOLES_N2STANDARD) diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm index 59ef15b4cf..c0f66be7de 100644 --- a/code/modules/atmospherics/gasmixtures/reactions.dm +++ b/code/modules/atmospherics/gasmixtures/reactions.dm @@ -63,11 +63,11 @@ /datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder) var/turf/open/location = isturf(holder) ? holder : null . = NO_REACTION - if (air.temperature <= WATER_VAPOR_FREEZE) + if (air.return_temperature() <= WATER_VAPOR_FREEZE) if(location && location.freon_gas_act()) . = REACTING else if(location && location.water_vapor_gas_act()) - air.gases[/datum/gas/water_vapor] -= MOLES_GAS_VISIBLE + air.adjust_moles(/datum/gas/water_vapor,-MOLES_GAS_VISIBLE) . = REACTING //tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic @@ -86,38 +86,37 @@ /datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder) var/energy_released = 0 var/old_heat_capacity = air.heat_capacity() - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/temperature = air.temperature + var/temperature = air.return_temperature() var/list/cached_results = air.reaction_results cached_results["fire"] = 0 var/turf/open/location = isturf(holder) ? holder : null var/burned_fuel = 0 - if(cached_gases[/datum/gas/oxygen] < cached_gases[/datum/gas/tritium]) - burned_fuel = cached_gases[/datum/gas/oxygen]/TRITIUM_BURN_OXY_FACTOR - cached_gases[/datum/gas/tritium] -= burned_fuel + if(air.get_moles(/datum/gas/oxygen) < air.get_moles(/datum/gas/tritium)) + burned_fuel = air.get_moles(/datum/gas/oxygen)/TRITIUM_BURN_OXY_FACTOR + air.adjust_moles(/datum/gas/tritium, -burned_fuel) else - burned_fuel = cached_gases[/datum/gas/tritium]*TRITIUM_BURN_TRIT_FACTOR - cached_gases[/datum/gas/tritium] -= cached_gases[/datum/gas/tritium]/TRITIUM_BURN_TRIT_FACTOR - cached_gases[/datum/gas/oxygen] -= cached_gases[/datum/gas/tritium] + burned_fuel = air.get_moles(/datum/gas/tritium)*TRITIUM_BURN_TRIT_FACTOR + air.adjust_moles(/datum/gas/tritium, -air.get_moles(/datum/gas/tritium)/TRITIUM_BURN_TRIT_FACTOR) + air.adjust_moles(/datum/gas/oxygen,-air.get_moles(/datum/gas/tritium)) if(burned_fuel) energy_released += (FIRE_HYDROGEN_ENERGY_RELEASED * burned_fuel) if(location && prob(10) && burned_fuel > TRITIUM_MINIMUM_RADIATION_ENERGY) //woah there let's not crash the server radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR) - cached_gases[/datum/gas/water_vapor] += burned_fuel/TRITIUM_BURN_OXY_FACTOR + air.adjust_moles(/datum/gas/water_vapor, burned_fuel/TRITIUM_BURN_OXY_FACTOR) cached_results["fire"] += burned_fuel if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity + air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity) //let the floor know a fire is happening if(istype(location)) - temperature = air.temperature + temperature = air.return_temperature() if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) location.hotspot_expose(temperature, CELL_VOLUME) for(var/I in location) @@ -143,8 +142,7 @@ /datum/gas_reaction/plasmafire/react(datum/gas_mixture/air, datum/holder) var/energy_released = 0 var/old_heat_capacity = air.heat_capacity() - var/list/cached_gases = air.gases //this speeds things up because accessing datum vars is slow - var/temperature = air.temperature + var/temperature = air.return_temperature() var/list/cached_results = air.reaction_results cached_results["fire"] = 0 var/turf/open/location = isturf(holder) ? holder : null @@ -163,21 +161,21 @@ temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE) if(temperature_scale > 0) oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale - if(cached_gases[/datum/gas/oxygen] / cached_gases[/datum/gas/plasma] > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium. + if(air.get_moles(/datum/gas/oxygen) / air.get_moles(/datum/gas/plasma) > SUPER_SATURATION_THRESHOLD) //supersaturation. Form Tritium. super_saturation = TRUE - if(cached_gases[/datum/gas/oxygen] > cached_gases[/datum/gas/plasma]*PLASMA_OXYGEN_FULLBURN) - plasma_burn_rate = (cached_gases[/datum/gas/plasma]*temperature_scale)/PLASMA_BURN_RATE_DELTA + if(air.get_moles(/datum/gas/oxygen) > air.get_moles(/datum/gas/plasma)*PLASMA_OXYGEN_FULLBURN) + plasma_burn_rate = (air.get_moles(/datum/gas/plasma)*temperature_scale)/PLASMA_BURN_RATE_DELTA else - plasma_burn_rate = (temperature_scale*(cached_gases[/datum/gas/oxygen]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA + plasma_burn_rate = (temperature_scale*(air.get_moles(/datum/gas/oxygen)/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY) - plasma_burn_rate = min(plasma_burn_rate,cached_gases[/datum/gas/plasma],cached_gases[/datum/gas/oxygen]/oxygen_burn_rate) //Ensures matter is conserved properly - cached_gases[/datum/gas/plasma] = QUANTIZE(cached_gases[/datum/gas/plasma] - plasma_burn_rate) - cached_gases[/datum/gas/oxygen] = QUANTIZE(cached_gases[/datum/gas/oxygen] - (plasma_burn_rate * oxygen_burn_rate)) + plasma_burn_rate = min(plasma_burn_rate,air.get_moles(/datum/gas/plasma),air.get_moles(/datum/gas/oxygen)/oxygen_burn_rate) //Ensures matter is conserved properly + air.set_moles(/datum/gas/plasma, QUANTIZE(air.get_moles(/datum/gas/plasma) - plasma_burn_rate)) + air.set_moles(/datum/gas/oxygen, QUANTIZE(air.get_moles(/datum/gas/oxygen) - (plasma_burn_rate * oxygen_burn_rate))) if (super_saturation) - cached_gases[/datum/gas/tritium] += plasma_burn_rate + air.adjust_moles(/datum/gas/tritium, plasma_burn_rate) else - cached_gases[/datum/gas/carbon_dioxide] += plasma_burn_rate + air.adjust_moles(/datum/gas/carbon_dioxide, plasma_burn_rate) energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate) @@ -186,11 +184,11 @@ if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = (temperature*old_heat_capacity + energy_released)/new_heat_capacity + air.set_temperature((temperature*old_heat_capacity + energy_released)/new_heat_capacity) //let the floor know a fire is happening if(istype(location)) - temperature = air.temperature + temperature = air.return_temperature() if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST) location.hotspot_expose(temperature, CELL_VOLUME) for(var/I in location) @@ -218,7 +216,6 @@ /datum/gas/carbon_dioxide = FUSION_MOLE_THRESHOLD) /datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases var/turf/open/location if (istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet. var/datum/pipeline/fusion_pipenet = holder @@ -230,14 +227,14 @@ var/list/cached_scan_results = air.analyzer_results var/old_heat_capacity = air.heat_capacity() var/reaction_energy = 0 //Reaction energy can be negative or positive, for both exothermic and endothermic reactions. - var/initial_plasma = cached_gases[/datum/gas/plasma] - var/initial_carbon = cached_gases[/datum/gas/carbon_dioxide] - var/scale_factor = (air.volume)/(PI) //We scale it down by volume/Pi because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions. - var/toroidal_size = (2*PI)+TORADIANS(arctan((air.volume-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus + var/initial_plasma = air.get_moles(/datum/gas/plasma) + var/initial_carbon = air.get_moles(/datum/gas/carbon_dioxide) + var/scale_factor = (air.return_volume())/(PI) //We scale it down by volume/Pi because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions. + var/toroidal_size = (2*PI)+TORADIANS(arctan((air.return_volume()-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus var/gas_power = 0 var/list/gas_fusion_powers = GLOB.meta_gas_fusions - for (var/gas_id in cached_gases) - gas_power += (gas_fusion_powers[gas_id]*cached_gases[gas_id]) + for (var/gas_id in air.get_gases()) + gas_power += (gas_fusion_powers[gas_id]*air.get_moles(gas_id)) var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is cached_scan_results[id] = instability//used for analyzer feedback @@ -249,9 +246,9 @@ carbon = MODULUS(carbon - plasma, toroidal_size) - cached_gases[/datum/gas/plasma] = plasma*scale_factor + FUSION_MOLE_THRESHOLD //Scales the gases back up - cached_gases[/datum/gas/carbon_dioxide] = carbon*scale_factor + FUSION_MOLE_THRESHOLD - var/delta_plasma = initial_plasma - cached_gases[/datum/gas/plasma] + air.set_moles(/datum/gas/plasma, plasma*scale_factor + FUSION_MOLE_THRESHOLD) //Scales the gases back up + air.set_moles(/datum/gas/carbon_dioxide , carbon*scale_factor + FUSION_MOLE_THRESHOLD) + var/delta_plasma = initial_plasma - air.get_moles(/datum/gas/plasma) reaction_energy += delta_plasma*PLASMA_BINDING_ENERGY //Energy is gained or lost corresponding to the creation or destruction of mass. if(instability < FUSION_INSTABILITY_ENDOTHERMALITY) @@ -260,17 +257,17 @@ reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5 if(air.thermal_energy() + reaction_energy < 0) //No using energy that doesn't exist. - cached_gases[/datum/gas/plasma] = initial_plasma - cached_gases[/datum/gas/carbon_dioxide] = initial_carbon + air.set_moles(/datum/gas/plasma,initial_plasma) + air.set_moles(/datum/gas/carbon_dioxide, initial_carbon) return NO_REACTION - cached_gases[/datum/gas/tritium] -= FUSION_TRITIUM_MOLES_USED + air.adjust_moles(/datum/gas/tritium, -FUSION_TRITIUM_MOLES_USED) //The decay of the tritium and the reaction's energy produces waste gases, different ones depending on whether the reaction is endo or exothermic if(reaction_energy > 0) - cached_gases[/datum/gas/oxygen] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT) - cached_gases[/datum/gas/nitrous_oxide] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT) + air.adjust_moles(/datum/gas/oxygen, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)) + air.adjust_moles(/datum/gas/nitrous_oxide, FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)) else - cached_gases[/datum/gas/bz] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT) - cached_gases[/datum/gas/nitryl] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT) + air.adjust_moles(/datum/gas/bz, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)) + air.adjust_moles(/datum/gas/nitryl, FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)) if(reaction_energy) if(location) @@ -282,7 +279,7 @@ var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = clamp(((air.temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY) + air.set_temperature(clamp(((air.return_temperature()*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY)) return REACTING /datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst. @@ -299,22 +296,21 @@ ) /datum/gas_reaction/nitrylformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/temperature = air.temperature + var/temperature = air.return_temperature() var/old_heat_capacity = air.heat_capacity() - var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),cached_gases[/datum/gas/oxygen],cached_gases[/datum/gas/nitrogen]) + var/heat_efficency = min(temperature/(FIRE_MINIMUM_TEMPERATURE_TO_EXIST*100),air.get_moles(/datum/gas/oxygen),air.get_moles(/datum/gas/nitrogen)) var/energy_used = heat_efficency*NITRYL_FORMATION_ENERGY - if ((cached_gases[/datum/gas/oxygen] - heat_efficency < 0 )|| (cached_gases[/datum/gas/nitrogen] - heat_efficency < 0)) //Shouldn't produce gas from nothing. + if ((air.get_moles(/datum/gas/oxygen) - heat_efficency < 0 )|| (air.get_moles(/datum/gas/nitrogen) - heat_efficency < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - cached_gases[/datum/gas/oxygen] -= heat_efficency - cached_gases[/datum/gas/nitrogen] -= heat_efficency - cached_gases[/datum/gas/nitryl] += heat_efficency*2 + air.adjust_moles(/datum/gas/oxygen, heat_efficency) + air.adjust_moles(/datum/gas/nitrogen, heat_efficency) + air.adjust_moles(/datum/gas/nitryl, heat_efficency*2) if(energy_used > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB) + air.set_temperature(max(((temperature*old_heat_capacity - energy_used)/new_heat_capacity),TCMB)) return REACTING /datum/gas_reaction/bzformation //Formation of BZ by combining plasma and tritium at low pressures. Exothermic. @@ -330,27 +326,26 @@ /datum/gas_reaction/bzformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/temperature = air.temperature + var/temperature = air.return_temperature() var/pressure = air.return_pressure() var/old_heat_capacity = air.heat_capacity() - var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma]/cached_gases[/datum/gas/nitrous_oxide],1))),cached_gases[/datum/gas/nitrous_oxide],cached_gases[/datum/gas/plasma]/2) + var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(air.get_moles(/datum/gas/plasma)/air.get_moles(/datum/gas/nitrous_oxide),1))),air.get_moles(/datum/gas/nitrous_oxide),air.get_moles(/datum/gas/plasma)/2) var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED - if ((cached_gases[/datum/gas/nitrous_oxide] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma] - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing. + if ((air.get_moles(/datum/gas/nitrous_oxide) - reaction_efficency < 0 )|| (air.get_moles(/datum/gas/plasma) - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing. return NO_REACTION - cached_gases[/datum/gas/bz] += reaction_efficency - if(reaction_efficency == cached_gases[/datum/gas/nitrous_oxide]) - cached_gases[/datum/gas/bz] -= min(pressure,1) - cached_gases[/datum/gas/oxygen] += min(pressure,1) - cached_gases[/datum/gas/nitrous_oxide] -= reaction_efficency - cached_gases[/datum/gas/plasma] -= 2*reaction_efficency + air.adjust_moles(/datum/gas/bz, reaction_efficency) + if(reaction_efficency == air.get_moles(/datum/gas/nitrous_oxide)) + air.adjust_moles(/datum/gas/bz, -min(pressure,1)) + air.adjust_moles(/datum/gas/oxygen, min(pressure,1)) + air.adjust_moles(/datum/gas/nitrous_oxide, -reaction_efficency) + air.adjust_moles(/datum/gas/plasma, -2*reaction_efficency) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((reaction_efficency**2)*BZ_RESEARCH_SCALE),BZ_RESEARCH_MAX_AMOUNT) if(energy_released > 0) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB) + air.set_temperature(max(((temperature*old_heat_capacity + energy_released)/new_heat_capacity),TCMB)) return REACTING /datum/gas_reaction/stimformation //Stimulum formation follows a strange pattern of how effective it will be at a given temperature, having some multiple peaks and some large dropoffs. Exo and endo thermic. @@ -367,24 +362,22 @@ "TEMP" = STIMULUM_HEAT_SCALE/2) /datum/gas_reaction/stimformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases - var/old_heat_capacity = air.heat_capacity() - var/heat_scale = min(air.temperature/STIMULUM_HEAT_SCALE,cached_gases[/datum/gas/tritium],cached_gases[/datum/gas/plasma],cached_gases[/datum/gas/nitryl]) + var/heat_scale = min(air.return_temperature()/STIMULUM_HEAT_SCALE,air.get_moles(/datum/gas/tritium),air.get_moles(/datum/gas/plasma),air.get_moles(/datum/gas/nitryl)) var/stim_energy_change = heat_scale + STIMULUM_FIRST_RISE*(heat_scale**2) - STIMULUM_FIRST_DROP*(heat_scale**3) + STIMULUM_SECOND_RISE*(heat_scale**4) - STIMULUM_ABSOLUTE_DROP*(heat_scale**5) - if ((cached_gases[/datum/gas/tritium] - heat_scale < 0 )|| (cached_gases[/datum/gas/plasma] - heat_scale < 0) || (cached_gases[/datum/gas/nitryl] - heat_scale < 0)) //Shouldn't produce gas from nothing. + if ((air.get_moles(/datum/gas/tritium) - heat_scale < 0 )|| (air.get_moles(/datum/gas/plasma) - heat_scale < 0) || (air.get_moles(/datum/gas/nitryl) - heat_scale < 0)) //Shouldn't produce gas from nothing. return NO_REACTION - cached_gases[/datum/gas/stimulum]+= heat_scale/10 - cached_gases[/datum/gas/tritium] -= heat_scale - cached_gases[/datum/gas/plasma] -= heat_scale - cached_gases[/datum/gas/nitryl] -= heat_scale + air.adjust_moles(/datum/gas/stimulum, heat_scale/10) + air.adjust_moles(/datum/gas/tritium, -heat_scale) + air.adjust_moles(/datum/gas/plasma, -heat_scale) + air.adjust_moles(/datum/gas/nitryl, -heat_scale) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, STIMULUM_RESEARCH_AMOUNT*max(stim_energy_change,0)) if(stim_energy_change) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = max(((air.temperature*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB) + air.set_temperature(max(((air.return_temperature()*old_heat_capacity + stim_energy_change)/new_heat_capacity),TCMB)) return REACTING /datum/gas_reaction/nobliumformation //Hyper-Noblium formation is extrememly endothermic, but requires high temperatures to start. Due to its high mass, hyper-nobelium uses large amounts of nitrogen and tritium. BZ can be used as a catalyst to make it less endothermic. @@ -399,22 +392,21 @@ "TEMP" = 5000000) /datum/gas_reaction/nobliumformation/react(datum/gas_mixture/air) - var/list/cached_gases = air.gases var/old_heat_capacity = air.heat_capacity() - var/nob_formed = min((cached_gases[/datum/gas/nitrogen]+cached_gases[/datum/gas/tritium])/100,cached_gases[/datum/gas/tritium]/10,cached_gases[/datum/gas/nitrogen]/20) - var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(cached_gases[/datum/gas/bz],1))) - if ((cached_gases[/datum/gas/tritium] - 10*nob_formed < 0) || (cached_gases[/datum/gas/nitrogen] - 20*nob_formed < 0)) + var/nob_formed = min((air.get_moles(/datum/gas/nitrogen)+air.get_moles(/datum/gas/tritium))/100,air.get_moles(/datum/gas/tritium)/10,air.get_moles(/datum/gas/nitrogen)/20) + var/energy_taken = nob_formed*(NOBLIUM_FORMATION_ENERGY/(max(air.get_moles(/datum/gas/bz),1))) + if ((air.get_moles(/datum/gas/tritium) - 10*nob_formed < 0) || (air.get_moles(/datum/gas/nitrogen) - 20*nob_formed < 0)) return NO_REACTION - cached_gases[/datum/gas/tritium] -= 10*nob_formed - cached_gases[/datum/gas/nitrogen] -= 20*nob_formed - cached_gases[/datum/gas/hypernoblium]+= nob_formed + air.adjust_moles(/datum/gas/tritium, -10*nob_formed) + air.adjust_moles(/datum/gas/nitrogen, -20*nob_formed) + air.adjust_moles(/datum/gas/hypernoblium,nob_formed) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, nob_formed*NOBLIUM_RESEARCH_AMOUNT) if (nob_formed) var/new_heat_capacity = air.heat_capacity() if(new_heat_capacity > MINIMUM_HEAT_CAPACITY) - air.temperature = max(((air.temperature*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB) + air.set_temperature(max(((air.return_temperature()*old_heat_capacity - energy_taken)/new_heat_capacity),TCMB)) /datum/gas_reaction/miaster //dry heat sterilization: clears out pathogens in the air @@ -429,16 +421,15 @@ ) /datum/gas_reaction/miaster/react(datum/gas_mixture/air, datum/holder) - var/list/cached_gases = air.gases // As the name says it, it needs to be dry - if(cached_gases[/datum/gas/water_vapor] && cached_gases[/datum/gas/water_vapor]/air.total_moles() > 0.1) + if(air.get_moles(/datum/gas/water_vapor) && air.get_moles(/datum/gas/water_vapor)/air.total_moles() > 0.1) return //Replace miasma with oxygen - var/cleaned_air = min(cached_gases[/datum/gas/miasma], 20 + (air.temperature - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20) - cached_gases[/datum/gas/miasma] -= cleaned_air - cached_gases[/datum/gas/oxygen] += cleaned_air + var/cleaned_air = min(air.get_moles(/datum/gas/miasma), 20 + (air.return_temperature() - FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 70) / 20) + air.adjust_moles(/datum/gas/miasma, -cleaned_air) + air.adjust_moles(/datum/gas/oxygen, cleaned_air) //Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable - air.temperature += cleaned_air * 0.002 + air.set_temperature(air.return_temperature() + cleaned_air * 0.002) SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists diff --git a/code/modules/atmospherics/gasmixtures/zextools_broke.dm b/code/modules/atmospherics/gasmixtures/zextools_broke.dm new file mode 100644 index 0000000000..eef6933edb --- /dev/null +++ b/code/modules/atmospherics/gasmixtures/zextools_broke.dm @@ -0,0 +1,304 @@ +#ifdef EXTOOLS_BROKE + +/datum/gas_mixture + var/list/gases = list() + var/temperature = 0 //kelvins + var/tmp/temperature_archived = 0 + var/volume = CELL_VOLUME //liters + var/last_share = 0 + +/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/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 + 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 + +//prefer this to gas_mixture/total_moles in performance critical areas +#define TOTAL_MOLES(cached_gases, out_var)\ + out_var = 0;\ + for(var/total_moles_id in cached_gases){\ + out_var += cached_gases[total_moles_id];\ + } + +#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity()) + +/datum/gas_mixture/total_moles() + var/cached_gases = gases + TOTAL_MOLES(cached_gases, .) + +/datum/gas_mixture/return_pressure() //kilopascals + if(volume > 0) // to prevent division by zero + var/cached_gases = gases + TOTAL_MOLES(cached_gases, .) + . *= R_IDEAL_GAS_EQUATION * temperature / volume + return + return 0 + +/datum/gas_mixture/return_temperature() //kelvins + return temperature + +/datum/gas_mixture/set_min_heat_capacity(n) + return +/datum/gas_mixture/set_temperature(new_temp) + temperature = new_temp +/datum/gas_mixture/set_volume(new_volume) + volume = new_volume +/datum/gas_mixture/get_moles(gas_type) + return gases[gas_type] +/datum/gas_mixture/set_moles(gas_type, moles) + gases[gas_type] = moles +/datum/gas_mixture/scrub_into(datum/gas_mixture/target, list/gases) + if(isnull(target)) + return FALSE + + var/list/removed_gases = target.gases + + //Filter it + var/datum/gas_mixture/filtered_out = new + var/list/filtered_gases = filtered_out.gases + filtered_out.temperature = removed.temperature + for(var/gas in filter_types & removed_gases) + filtered_gases[gas] = removed_gases[gas] + removed_gases[gas] = 0 + merge(filtered_out) +/datum/gas_mixture/mark_immutable() + return +/datum/gas_mixture/get_gases() + return gases +/datum/gas_mixture/multiply(factor) + for(var/id in gases) + gases[id] *= factor +/datum/gas_mixture/get_last_share() + return last_share +/datum/gas_mixture/clear() + gases.Cut() + +/datum/gas_mixture/return_volume() + return volume // wow! + +/datum/gas_mixture/thermal_energy() + return THERMAL_ENERGY(src) + +/datum/gas_mixture/archive() + temperature_archived = temperature + gas_archive = gases.Copy() + return 1 + +/datum/gas_mixture/merge(datum/gas_mixture/giver) + if(!giver) + return 0 + + //heat transfer + if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/self_heat_capacity = heat_capacity() + var/giver_heat_capacity = giver.heat_capacity() + var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity + if(combined_heat_capacity) + temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity + + var/list/cached_gases = gases //accessing datum vars is slower than proc vars + var/list/giver_gases = giver.gases + //gas transfer + for(var/giver_id in giver_gases) + cached_gases[giver_id] += giver_gases[giver_id] + + return 1 + +/datum/gas_mixture/remove(amount) + var/sum + var/list/cached_gases = gases + TOTAL_MOLES(cached_gases, sum) + amount = min(amount, sum) //Can not take more air than tile has! + if(amount <= 0) + return null + var/datum/gas_mixture/removed = new type + var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars + + removed.temperature = temperature + for(var/id in cached_gases) + removed_gases[id] = QUANTIZE((cached_gases[id] / sum) * amount) + cached_gases[id] -= removed_gases[id] + GAS_GARBAGE_COLLECT(gases) + + return removed + +/datum/gas_mixture/remove_ratio(ratio) + if(ratio <= 0) + return null + ratio = min(ratio, 1) + + var/list/cached_gases = gases + var/datum/gas_mixture/removed = new type + var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars + + removed.temperature = temperature + for(var/id in cached_gases) + removed_gases[id] = QUANTIZE(cached_gases[id] * ratio) + cached_gases[id] -= removed_gases[id] + + GAS_GARBAGE_COLLECT(gases) + + return removed + +/datum/gas_mixture/copy() + var/list/cached_gases = gases + var/datum/gas_mixture/copy = new type + var/list/copy_gases = copy.gases + + copy.temperature = temperature + for(var/id in cached_gases) + copy_gases[id] = cached_gases[id] + + return copy + + +/datum/gas_mixture/copy_from(datum/gas_mixture/sample) + var/list/cached_gases = gases //accessing datum vars is slower than proc vars + var/list/sample_gases = sample.gases + + temperature = sample.temperature + for(var/id in sample_gases) + cached_gases[id] = sample_gases[id] + + //remove all gases not in the sample + cached_gases &= sample_gases + + return 1 + +/datum/gas_mixture/copy_from_turf(turf/model) + parse_gas_string(model.initial_gas_mix) + + //acounts for changes in temperature + var/turf/model_parent = model.parent_type + if(model.temperature != initial(model.temperature) || model.temperature != initial(model_parent.temperature)) + temperature = model.temperature + + return 1 + +/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4) + + var/list/cached_gases = gases + var/list/sharer_gases = sharer.gases + + var/temperature_delta = temperature_archived - sharer.temperature_archived + var/abs_temperature_delta = abs(temperature_delta) + + var/old_self_heat_capacity = 0 + var/old_sharer_heat_capacity = 0 + if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + old_self_heat_capacity = heat_capacity() + old_sharer_heat_capacity = sharer.heat_capacity() + + var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer + var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us + + var/moved_moles = 0 + var/abs_moved_moles = 0 + + //we're gonna define these vars outside of this for loop because as it turns out, var declaration is pricy + var/delta + var/gas_heat_capacity + //and also cache this shit rq because that results in sanic speed for reasons byond explanation + var/list/cached_gasheats = GLOB.meta_gas_specific_heats + //GAS TRANSFER + for(var/id in cached_gases | sharer_gases) // transfer gases + + 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] + if(delta > 0) + heat_capacity_self_to_sharer += gas_heat_capacity + else + heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative. + + cached_gases[id] -= delta + sharer_gases[id] += delta + moved_moles += delta + abs_moved_moles += abs(delta) + + last_share = abs_moved_moles + + //THERMAL ENERGY TRANSFER + if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER) + var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer + var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self + + //transfer of thermal energy (via changed heat capacity) between self and sharer + if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY) + temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity + + if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) + sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity + //thermal energy of the system (self and sharer) is unchanged + + if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY) + if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.1) // <10% change in sharer heat capacity + temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT) + + if (initial(sharer.gc_share)) + GAS_GARBAGE_COLLECT(sharer.gases) + if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE) + var/our_moles + TOTAL_MOLES(cached_gases,our_moles) + var/their_moles + TOTAL_MOLES(sharer_gases,their_moles) + return (temperature_archived*(our_moles + moved_moles) - sharer.temperature_archived*(their_moles - moved_moles)) * R_IDEAL_GAS_EQUATION / volume + +/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient, sharer_temperature, sharer_heat_capacity) + //transfer of thermal energy (via conduction) between self and sharer + if(sharer) + 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 = 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* \ + (self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity)) + + temperature = max(temperature - heat/self_heat_capacity, TCMB) + sharer_temperature = max(sharer_temperature + heat/sharer_heat_capacity, TCMB) + if(sharer) + sharer.temperature = sharer_temperature + return sharer_temperature + //thermal energy of the system (self and sharer) is unchanged + +/datum/gas_mixture/compare(datum/gas_mixture/sample) + var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars + var/list/cached_gases = gases + + for(var/id in cached_gases | sample_gases) // compare gases from either mixture + var/gas_moles = cached_gases[id] + var/sample_moles = sample_gases[id] + var/delta = abs(gas_moles - sample_moles) + if(delta > MINIMUM_MOLES_DELTA_TO_MOVE && \ + delta > gas_moles * MINIMUM_AIR_RATIO_TO_MOVE) + return id + + var/our_moles + TOTAL_MOLES(cached_gases, our_moles) + if(our_moles > MINIMUM_MOLES_DELTA_TO_MOVE) + var/temp = temperature + var/sample_temp = sample.temperature + + var/temperature_delta = abs(temp - sample_temp) + if(temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) + return "temp" + + return "" + +/datum/gas_mixture/transfer_to(datum/gas_mixture/target, amount) + return merge(target.remove(amount)) + +#endif diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm index b47f45b42d..8316b29a24 100644 --- a/code/modules/atmospherics/machinery/airalarm.dm +++ b/code/modules/atmospherics/machinery/airalarm.dm @@ -237,11 +237,10 @@ return ..() return UI_CLOSE -/obj/machinery/airalarm/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/airalarm/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state) + ui = new(user, src, "AirAlarm", name) ui.open() /obj/machinery/airalarm/ui_data(mob/user) @@ -269,7 +268,7 @@ "unit" = "kPa", "danger_level" = cur_tlv.get_danger_level(pressure) )) - var/temperature = environment.temperature + var/temperature = environment.return_temperature() cur_tlv = TLV["temperature"] data["environment_data"] += list(list( "name" = "Temperature", @@ -278,16 +277,16 @@ "danger_level" = cur_tlv.get_danger_level(temperature) )) var/total_moles = environment.total_moles() - var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume - for(var/gas_id in environment.gases) + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.return_temperature() / environment.return_volume() + for(var/gas_id in environment.get_gases()) if(!(gas_id in TLV)) // We're not interested in this gas, it seems. continue cur_tlv = TLV[gas_id] data["environment_data"] += list(list( "name" = GLOB.meta_gas_names[gas_id], - "value" = environment.gases[gas_id] / total_moles * 100, + "value" = environment.get_moles(gas_id) / total_moles * 100, "unit" = "%", - "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure) + "danger_level" = cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure) )) if(!locked || hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE)) @@ -684,24 +683,21 @@ var/datum/tlv/cur_tlv var/datum/gas_mixture/environment = location.return_air() - var/list/env_gases = environment.gases - var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume + var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.return_temperature() / environment.return_volume() cur_tlv = TLV["pressure"] var/environment_pressure = environment.return_pressure() var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure) cur_tlv = TLV["temperature"] - var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature) + var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.return_temperature()) var/gas_dangerlevel = 0 - for(var/gas_id in env_gases) + for(var/gas_id in environment.get_gases()) if(!(gas_id in TLV)) // We're not interested in this gas, it seems. continue cur_tlv = TLV[gas_id] - gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(env_gases[gas_id] * partial_pressure)) - - GAS_GARBAGE_COLLECT(environment.gases) + gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(environment.get_moles(gas_id) * partial_pressure)) var/old_danger_level = danger_level danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel) diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm index 6b685d4bc1..39a99148c2 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm @@ -52,10 +52,10 @@ return null //Calculate necessary moles to transfer using PV = nRT - if(air2.temperature>0) + if(air2.return_temperature()>0) var/pressure_delta = (input_starting_pressure - output_starting_pressure)/2 - var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta*air1.return_volume()/(air2.return_temperature() * R_IDEAL_GAS_EQUATION) last_pressure_delta = pressure_delta diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm index 2dc0afac26..d1bb58b99a 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm @@ -66,8 +66,8 @@ pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min)) if(pressure_delta > 0) - if(air1.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + if(air1.return_temperature() > 0) + var/transfer_moles = pressure_delta*environment.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air1.remove(transfer_moles) //Removed can be null if there is no atmosphere in air1 @@ -81,20 +81,17 @@ parent1.update = 1 else //external -> output - var/pressure_delta = 10000 + if(environment.return_pressure() > 0) + var/our_multiplier = air2.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION) + var/moles_delta = 10000 * our_multiplier + if(pressure_checks&EXT_BOUND) + moles_delta = min(moles_delta, (environment_pressure - output_pressure_max) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)) + if(pressure_checks&INPUT_MIN) + moles_delta = min(moles_delta, (input_pressure_min - air2.return_pressure()) * our_multiplier) - if(pressure_checks&EXT_BOUND) - pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) - if(pressure_checks&INPUT_MIN) - pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure())) - - if(pressure_delta > 0) - if(environment.temperature > 0) - var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION) - - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - //removed can be null if there is no air in the location - if(!removed) + if(moles_delta > 0) + var/datum/gas_mixture/removed = loc.remove_air(moles_delta) + if (isnull(removed)) // in space return air2.merge(removed) @@ -182,8 +179,8 @@ ..() var/datum/gas_mixture/air1 = airs[1] var/datum/gas_mixture/air2 = airs[2] - air1.volume = 1000 - air2.volume = 1000 + air1.set_volume(1000) + air2.set_volume(1000) // Mapping diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm index 051dc965ad..00a085c31b 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm @@ -26,6 +26,18 @@ Passive gate is similar to the regular pump except: construction_type = /obj/item/pipe/directional pipe_state = "passivegate" +/obj/machinery/atmospherics/components/binary/passive_gate/CtrlClick(mob/user) + if(can_interact(user)) + on = !on + update_icon() + return ..() + +/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user) + if(can_interact(user)) + target_pressure = MAX_OUTPUT_PRESSURE + update_icon() + return ..() + /obj/machinery/atmospherics/components/binary/passive_gate/Destroy() SSradio.remove_object(src,frequency) return ..() @@ -53,11 +65,11 @@ Passive gate is similar to the regular pump except: return //Calculate necessary moles to transfer using PV = nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) + if((air1.total_moles() > 0) && (air1.return_temperature()>0)) var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2) //Can not have a pressure delta that would cause output_pressure > input_pressure - var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta*air2.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = air1.remove(transfer_moles) @@ -87,11 +99,10 @@ Passive gate is similar to the regular pump except: )) radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) -/obj/machinery/atmospherics/components/binary/passive_gate/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state) + ui = new(user, src, "AtmosPump", name) ui.open() /obj/machinery/atmospherics/components/binary/passive_gate/ui_data() @@ -172,4 +183,4 @@ Passive gate is similar to the regular pump except: /obj/machinery/atmospherics/components/binary/passive_gate/layer3 piping_layer = 3 - icon_state = "passgate_map-3" \ No newline at end of file + icon_state = "passgate_map-3" diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm index 0e41f78e20..eb00e432b7 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm @@ -77,9 +77,9 @@ return //Calculate necessary moles to transfer using PV=nRT - if((air1.total_moles() > 0) && (air1.temperature>0)) + if((air1.total_moles() > 0) && (air1.return_temperature()>0)) var/pressure_delta = target_pressure - output_starting_pressure - var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta*air2.return_volume()/(air1.return_temperature() * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = air1.remove(transfer_moles) @@ -107,11 +107,10 @@ )) radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) -/obj/machinery/atmospherics/components/binary/pump/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state) + ui = new(user, src, "AtmosPump", name) ui.open() /obj/machinery/atmospherics/components/binary/pump/ui_data() @@ -212,4 +211,4 @@ /obj/machinery/atmospherics/components/binary/pump/on/layer3 piping_layer = 3 - icon_state= "pump_on_map-3" \ No newline at end of file + icon_state= "pump_on_map-3" diff --git a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm index 7bdd22cbd1..d0b663e4ad 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/relief_valve.dm @@ -60,15 +60,14 @@ else if(!opened && our_pressure >= open_pressure) open() -/obj/machinery/atmospherics/components/binary/relief_valve/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/binary/relief_valve/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_relief", name, 335, 115, master_ui, state) + ui = new(user, src, "AtmosRelief", name) ui.open() /obj/machinery/atmospherics/components/binary/relief_valve/ui_data() - var/data = list() + var/list/data = list() data["open_pressure"] = round(open_pressure) data["close_pressure"] = round(close_pressure) data["max_pressure"] = round(50*ONE_ATMOSPHERE) @@ -79,11 +78,11 @@ return switch(action) if("open_pressure") - var/pressure = params["open_pressure"] + var/pressure = params["pressure"] if(pressure == "max") pressure = 50*ONE_ATMOSPHERE . = TRUE - else if(pressure == "input") + else if(pressure == "input") // The manual expirience. pressure = input("New output pressure ([close_pressure]-[50*ONE_ATMOSPHERE] kPa):", name, open_pressure) as num|null if(!isnull(pressure) && !..()) . = TRUE @@ -94,7 +93,7 @@ open_pressure = clamp(pressure, close_pressure, 50*ONE_ATMOSPHERE) investigate_log("open pressure was set to [open_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS) if("close_pressure") - var/pressure = params["close_pressure"] + var/pressure = params["pressure"] if(pressure == "max") pressure = open_pressure . = TRUE diff --git a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm index 1005f72afe..1b049322a1 100644 --- a/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm +++ b/code/modules/atmospherics/machinery/components/binary_devices/volume_pump.dm @@ -65,7 +65,7 @@ if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000)) return - var/transfer_ratio = transfer_rate/air1.volume + var/transfer_ratio = transfer_rate/air1.return_volume() var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio) @@ -92,11 +92,10 @@ )) radio_connection.post_signal(src, signal) -/obj/machinery/atmospherics/components/binary/volume_pump/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/binary/volume_pump/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_pump", name, 310, 115, master_ui, state) + ui = new(user, src, "AtmosPump", name) ui.open() /obj/machinery/atmospherics/components/binary/volume_pump/ui_data() @@ -153,7 +152,7 @@ if("set_transfer_rate" in signal.data) var/datum/gas_mixture/air1 = airs[1] - transfer_rate = clamp(text2num(signal.data["set_transfer_rate"]),0,air1.volume) + transfer_rate = clamp(text2num(signal.data["set_transfer_rate"]),0,air1.return_volume()) if(on != old_on) investigate_log("was turned [on ? "on" : "off"] by a remote signal", INVESTIGATE_ATMOS) @@ -200,4 +199,4 @@ /obj/machinery/atmospherics/components/binary/volume_pump/on/layer3 piping_layer = 3 - icon_state = "volpump_map-3" \ No newline at end of file + icon_state = "volpump_map-3" diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index 33fd160b1a..a8d9586fc4 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -15,8 +15,7 @@ ..() for(var/i in 1 to device_type) - var/datum/gas_mixture/A = new - A.volume = 200 + var/datum/gas_mixture/A = new(200) airs[i] = A // Iconnery @@ -117,7 +116,7 @@ var/times_lost = 0 for(var/i in 1 to device_type) var/datum/gas_mixture/air = airs[i] - lost += pressures*environment.volume/(air.temperature * R_IDEAL_GAS_EQUATION) + lost += pressures*environment.return_volume()/(air.return_temperature() * R_IDEAL_GAS_EQUATION) times_lost++ var/shared_loss = lost/times_lost @@ -171,3 +170,4 @@ /obj/machinery/atmospherics/components/analyzer_act(mob/living/user, obj/item/I) atmosanalyzer_scan(airs, user, src) + return TRUE \ No newline at end of file diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm index 78258dd10a..ffab6a885c 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm @@ -94,7 +94,7 @@ //Calculate necessary moles to transfer using PV=nRT - var/transfer_ratio = transfer_rate/air1.volume + var/transfer_ratio = transfer_rate/air1.return_volume() //Actually transfer the gas @@ -111,14 +111,13 @@ else filtering = FALSE - if(filtering && removed.gases[filter_type]) + if(filtering && removed.get_moles(filter_type)) var/datum/gas_mixture/filtered_out = new - filtered_out.temperature = removed.temperature - filtered_out.gases[filter_type] = removed.gases[filter_type] + filtered_out.set_temperature(removed.return_temperature()) + filtered_out.set_moles(filter_type, removed.get_moles(filter_type)) - removed.gases[filter_type] = 0 - GAS_GARBAGE_COLLECT(removed.gases) + removed.set_moles(filter_type, 0) var/datum/gas_mixture/target = (air2.return_pressure() < 9000 ? air2 : air1) target.merge(filtered_out) @@ -134,11 +133,10 @@ set_frequency(frequency) return ..() -/obj/machinery/atmospherics/components/trinary/filter/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/trinary/filter/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_filter", name, 475, 185, master_ui, state) + ui = new(user, src, "AtmosFilter", name) ui.open() /obj/machinery/atmospherics/components/trinary/filter/ui_data() @@ -280,4 +278,4 @@ critical_machine = TRUE /obj/machinery/atmospherics/components/trinary/filter/flipped/critical - critical_machine = TRUE \ No newline at end of file + critical_machine = TRUE diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm index dcf0d09bee..7dac6d540e 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/mixer.dm @@ -14,9 +14,6 @@ construction_type = /obj/item/pipe/trinary/flippable pipe_state = "mixer" - ui_x = 370 - ui_y = 165 - //node 3 is the outlet, nodes 1 & 2 are intakes /obj/machinery/atmospherics/components/trinary/mixer/CtrlClick(mob/user) @@ -57,7 +54,7 @@ /obj/machinery/atmospherics/components/trinary/mixer/New() ..() var/datum/gas_mixture/air3 = airs[3] - air3.volume = 300 + air3.set_volume(300) airs[3] = air3 /obj/machinery/atmospherics/components/trinary/mixer/process_atmos() @@ -81,26 +78,26 @@ return //Calculate necessary moles to transfer using PV=nRT - var/general_transfer = (target_pressure - output_starting_pressure) * air3.volume / R_IDEAL_GAS_EQUATION + var/general_transfer = (target_pressure - output_starting_pressure) * air3.return_volume() / R_IDEAL_GAS_EQUATION - var/transfer_moles1 = air1.temperature ? node1_concentration * general_transfer / air1.temperature : 0 - var/transfer_moles2 = air2.temperature ? node2_concentration * general_transfer / air2.temperature : 0 + var/transfer_moles1 = air1.return_temperature() ? node1_concentration * general_transfer / air1.return_temperature() : 0 + var/transfer_moles2 = air2.return_temperature() ? node2_concentration * general_transfer / air2.return_temperature() : 0 var/air1_moles = air1.total_moles() var/air2_moles = air2.total_moles() if(!node2_concentration) - if(air1.temperature <= 0) + if(air1.return_temperature() <= 0) return transfer_moles1 = min(transfer_moles1, air1_moles) transfer_moles2 = 0 else if(!node1_concentration) - if(air2.temperature <= 0) + if(air2.return_temperature() <= 0) return transfer_moles2 = min(transfer_moles2, air2_moles) transfer_moles1 = 0 else - if(air1.temperature <= 0 || air2.temperature <= 0) + if(air1.return_temperature() <= 0 || air2.return_temperature() <= 0) return if((transfer_moles2 <= 0) || (transfer_moles1 <= 0)) return @@ -127,11 +124,10 @@ var/datum/pipeline/parent3 = parents[3] parent3.update = TRUE -/obj/machinery/atmospherics/components/trinary/mixer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_mixer", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "AtmosMixer", name) ui.open() /obj/machinery/atmospherics/components/trinary/mixer/ui_data() @@ -248,4 +244,4 @@ /obj/machinery/atmospherics/components/trinary/mixer/airmix/flipped/inverse node1_concentration = O2STANDARD - node2_concentration = N2STANDARD \ No newline at end of file + node2_concentration = N2STANDARD diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 4f26a2f772..c08eaf2e8a 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -33,6 +33,8 @@ var/escape_in_progress = FALSE var/message_cooldown var/breakout_time = 300 + ///Cryo will continue to treat people with 0 damage but existing wounds, but will sound off when damage healing is done in case doctors want to directly treat the wounds instead + var/treating_wounds = FALSE fair_market_price = 10 payment_department = ACCOUNT_MED @@ -174,19 +176,31 @@ return if(mob_occupant.health >= mob_occupant.getMaxHealth()) // Don't bother with fully healed people. - on = FALSE - update_icon() - playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors. - var/msg = "Patient fully restored." - if(autoeject) // Eject if configured. - msg += " Auto ejecting patient now." - open_machine() - radio.talk_into(src, msg, radio_channel) - return + if(iscarbon(mob_occupant)) + var/mob/living/carbon/C = mob_occupant + if(C.all_wounds) + if(!treating_wounds) // if we have wounds and haven't already alerted the doctors we're only dealing with the wounds, let them know + treating_wounds = TRUE + playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors. + var/msg = "Patient vitals fully recovered, continuing automated wound treatment." + radio.talk_into(src, msg, radio_channel) + else // otherwise if we were only treating wounds and now we don't have any, turn off treating_wounds so we can boot 'em out + treating_wounds = FALSE + + if(!treating_wounds) + on = FALSE + update_icon() + playsound(src, 'sound/machines/cryo_warning.ogg', volume) // Bug the doctors. + var/msg = "Patient fully restored." + if(autoeject) // Eject if configured. + msg += " Auto ejecting patient now." + open_machine() + radio.talk_into(src, msg, radio_channel) + return var/datum/gas_mixture/air1 = airs[1] - if(air1.gases.len) + if(air1.total_moles()) if(mob_occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic. // temperature factor goes from 1 to about 2.5 var/amount = max(1, (4 * log(T0C - mob_occupant.bodytemperature)) - 20) * knockout_factor * base_knockout @@ -196,8 +210,7 @@ if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic. beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents. beaker.reagents.reaction(occupant, VAPOR) - air1.gases[/datum/gas/oxygen] -= max(0,air1.gases[/datum/gas/oxygen] - 2 / efficiency) //Let's use gas for this - GAS_GARBAGE_COLLECT(air1.gases) + air1.adjust_moles(/datum/gas/oxygen, -max(0,air1.get_moles(/datum/gas/oxygen) - 2 / efficiency)) //Let's use gas for this if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker). reagent_transfer = 0 @@ -211,7 +224,7 @@ var/datum/gas_mixture/air1 = airs[1] - if(!nodes[1] || !airs[1] || !air1.gases.len || air1.gases[/datum/gas/oxygen] < 5) // Turn off if the machine won't work. + if(!nodes[1] || !airs[1] || air1.get_moles(/datum/gas/oxygen) < 5) // Turn off if the machine won't work. on = FALSE update_icon() return @@ -219,22 +232,21 @@ if(occupant) var/mob/living/mob_occupant = occupant var/cold_protection = 0 - var/temperature_delta = air1.temperature - mob_occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant. + var/temperature_delta = air1.return_temperature() - mob_occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant. if(ishuman(occupant)) var/mob/living/carbon/human/H = occupant - cold_protection = H.get_thermal_protection(air1.temperature, TRUE) + cold_protection = H.get_thermal_protection(air1.return_temperature(), TRUE) if(abs(temperature_delta) > 1) var/air_heat_capacity = air1.heat_capacity() var/heat = ((1 - cold_protection) * 0.1 + conduction_coefficient) * temperature_delta * (air_heat_capacity * heat_capacity / (air_heat_capacity + heat_capacity)) - air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB) + air1.set_temperature(max(air1.return_temperature() - heat / air_heat_capacity, TCMB)) mob_occupant.adjust_bodytemperature(heat / heat_capacity, TCMB) - air1.gases[/datum/gas/oxygen] = max(0,air1.gases[/datum/gas/oxygen] - 0.5 / efficiency) // Magically consume gas? Why not, we run on cryo magic. - GAS_GARBAGE_COLLECT(air1.gases) + air1.set_temperature(max(air1.return_temperature() - 0.5 / efficiency)) // Magically consume gas? Why not, we run on cryo magic. /obj/machinery/atmospherics/components/unary/cryo_cell/power_change() ..() @@ -264,8 +276,6 @@ return occupant /obj/machinery/atmospherics/components/unary/cryo_cell/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 glass of [src]!", \ "You struggle inside [src], kicking the release with your foot... (this will take about [DisplayTimeText(breakout_time)].)", \ "You hear a thump from [src].") @@ -322,11 +332,13 @@ return return ..() -/obj/machinery/atmospherics/components/unary/cryo_cell/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) +/obj/machinery/atmospherics/components/unary/cryo_cell/ui_state(mob/user) + return GLOB.notcontained_state + +/obj/machinery/atmospherics/components/unary/cryo_cell/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "cryo", name, 400, 550, master_ui, state) + ui = new(user, src, "Cryo", name) ui.open() /obj/machinery/atmospherics/components/unary/cryo_cell/ui_data() @@ -369,7 +381,7 @@ data["occupant"]["temperaturestatus"] = "bad" var/datum/gas_mixture/air1 = airs[1] - data["cellTemperature"] = round(air1.temperature, 1) + data["cellTemperature"] = round(air1.return_temperature(), 1) data["isBeakerLoaded"] = beaker ? TRUE : FALSE var/beakerContents = list() @@ -439,7 +451,7 @@ var/datum/gas_mixture/G = airs[1] if(G.total_moles() > 10) - return G.temperature + return G.return_temperature() return ..() /obj/machinery/atmospherics/components/unary/cryo_cell/default_change_direction_wrench(mob/user, obj/item/wrench/W) diff --git a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm index a856ea1f3f..c0dfc5633e 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/heat_exchanger.dm @@ -59,18 +59,18 @@ var/other_air_heat_capacity = partner_air_contents.heat_capacity() var/combined_heat_capacity = other_air_heat_capacity + air_heat_capacity - var/old_temperature = air_contents.temperature - var/other_old_temperature = partner_air_contents.temperature + var/old_temperature = air_contents.return_temperature() + var/other_old_temperature = partner_air_contents.return_temperature() if(combined_heat_capacity > 0) - var/combined_energy = partner_air_contents.temperature*other_air_heat_capacity + air_heat_capacity*air_contents.temperature + var/combined_energy = partner_air_contents.return_temperature()*other_air_heat_capacity + air_heat_capacity*air_contents.return_temperature() var/new_temperature = combined_energy/combined_heat_capacity - air_contents.temperature = new_temperature - partner_air_contents.temperature = new_temperature + air_contents.set_temperature(new_temperature) + partner_air_contents.set_temperature(new_temperature) - if(abs(old_temperature-air_contents.temperature) > 1) + if(abs(old_temperature-air_contents.return_temperature()) > 1) update_parents() - if(abs(other_old_temperature-partner_air_contents.temperature) > 1) + if(abs(other_old_temperature-partner_air_contents.return_temperature()) > 1) partner.update_parents() diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm index 05720583f9..a07f131d62 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm @@ -20,6 +20,18 @@ pipe_state = "injector" +/obj/machinery/atmospherics/components/unary/outlet_injector/CtrlClick(mob/user) + if(can_interact(user)) + on = !on + update_icon() + return ..() + +/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user) + if(can_interact(user)) + volume_rate = MAX_TRANSFER_RATE + update_icon() + return ..() + /obj/machinery/atmospherics/components/unary/outlet_injector/Destroy() SSradio.remove_object(src,frequency) return ..() @@ -52,8 +64,8 @@ var/datum/gas_mixture/air_contents = airs[1] - if(air_contents.temperature > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + if(air_contents.return_temperature() > 0) + var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -71,8 +83,8 @@ injecting = 1 - if(air_contents.temperature > 0) - var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + if(air_contents.return_temperature() > 0) + var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) loc.assume_air(removed) update_parents() @@ -117,30 +129,24 @@ on = !on if("inject" in signal.data) - spawn inject() + INVOKE_ASYNC(src, .proc/inject) return if("set_volume_rate" in signal.data) var/number = text2num(signal.data["set_volume_rate"]) var/datum/gas_mixture/air_contents = airs[1] - volume_rate = clamp(number, 0, air_contents.volume) + volume_rate = clamp(number, 0, air_contents.return_volume()) - if("status" in signal.data) - spawn(2) - broadcast_status() - return //do not update_icon + addtimer(CALLBACK(src, .proc/broadcast_status), 2) - spawn(2) - broadcast_status() - - update_icon() + if(!("status" in signal.data)) //do not update_icon + update_icon() -/obj/machinery/atmospherics/components/unary/outlet_injector/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/unary/outlet_injector/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_pump", name, 310, 115, master_ui, state) + ui = new(user, src, "AtmosPump", name) ui.open() /obj/machinery/atmospherics/components/unary/outlet_injector/ui_data() @@ -241,4 +247,4 @@ id = ATMOS_GAS_MONITOR_INPUT_INCINERATOR /obj/machinery/atmospherics/components/unary/outlet_injector/atmos/toxins_mixing_input name = "toxins mixing input injector" - id = ATMOS_GAS_MONITOR_INPUT_TOXINS_LAB \ No newline at end of file + id = ATMOS_GAS_MONITOR_INPUT_TOXINS_LAB diff --git a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm index a113484d20..3f5bb818ce 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/passive_vent.dm @@ -30,14 +30,14 @@ if(pressure_delta > 0.5) if(external_pressure < internal_pressure) - var/air_temperature = (external.temperature > 0) ? external.temperature : internal.temperature - var/transfer_moles = (pressure_delta * external.volume) / (air_temperature * R_IDEAL_GAS_EQUATION) + var/air_temperature = (external.return_temperature() > 0) ? external.return_temperature() : internal.return_temperature() + var/transfer_moles = (pressure_delta * external.return_volume()) / (air_temperature * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = internal.remove(transfer_moles) external.merge(removed) else - var/air_temperature = (internal.temperature > 0) ? internal.temperature : external.temperature - var/transfer_moles = (pressure_delta * internal.volume) / (air_temperature * R_IDEAL_GAS_EQUATION) - transfer_moles = min(transfer_moles, external.total_moles() * internal.volume / external.volume) + var/air_temperature = (internal.return_temperature() > 0) ? internal.return_temperature() : external.return_temperature() + var/transfer_moles = (pressure_delta * internal.return_volume()) / (air_temperature * R_IDEAL_GAS_EQUATION) + transfer_moles = min(transfer_moles, external.total_moles() * internal.return_volume() / external.return_volume()) var/datum/gas_mixture/removed = external.remove(transfer_moles) if(isnull(removed)) return diff --git a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm index 81ca14a828..6188c919ac 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/portables_connector.dm @@ -16,7 +16,7 @@ ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.volume = 0 + air_contents.set_volume(0) /obj/machinery/atmospherics/components/unary/portables_connector/Destroy() if(connected_device) @@ -64,4 +64,4 @@ /obj/machinery/atmospherics/components/unary/portables_connector/visible/layer3 piping_layer = 3 - icon_state = "connector_map-3" \ No newline at end of file + icon_state = "connector_map-3" diff --git a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm index 1d8b875528..f0d0d1d856 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/relief_valve.dm @@ -49,10 +49,10 @@ else if(!opened && our_pressure >= open_pressure) opened = TRUE update_icon_nopipes() - if(opened && air_contents.temperature > 0) + if(opened && air_contents.return_temperature() > 0) var/datum/gas_mixture/environment = loc.return_air() var/pressure_delta = our_pressure - environment.return_pressure() - var/transfer_moles = pressure_delta*200/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + var/transfer_moles = pressure_delta*200/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) if(transfer_moles > 0) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -61,15 +61,14 @@ update_parents() -/obj/machinery/atmospherics/components/unary/relief_valve/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/unary/relief_valve/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "atmos_relief", name, 335, 115, master_ui, state) + ui = new(user, src, "AtmosRelief", name) ui.open() /obj/machinery/atmospherics/components/unary/relief_valve/ui_data() - var/data = list() + var/list/data = list() data["open_pressure"] = round(open_pressure) data["close_pressure"] = round(close_pressure) data["max_pressure"] = round(50*ONE_ATMOSPHERE) @@ -80,7 +79,7 @@ return switch(action) if("open_pressure") - var/pressure = params["open_pressure"] + var/pressure = params["pressure"] if(pressure == "max") pressure = 50*ONE_ATMOSPHERE . = TRUE @@ -95,7 +94,7 @@ open_pressure = clamp(pressure, close_pressure, 50*ONE_ATMOSPHERE) investigate_log("open pressure was set to [open_pressure] kPa by [key_name(usr)]", INVESTIGATE_ATMOS) if("close_pressure") - var/pressure = params["close_pressure"] + var/pressure = params["pressure"] if(pressure == "max") pressure = open_pressure . = TRUE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/tank.dm b/code/modules/atmospherics/machinery/components/unary_devices/tank.dm index 79ff24e8b7..2f3372462d 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/tank.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/tank.dm @@ -1,4 +1,4 @@ -#define AIR_CONTENTS ((25*ONE_ATMOSPHERE)*(air_contents.volume)/(R_IDEAL_GAS_EQUATION*air_contents.temperature)) +#define AIR_CONTENTS ((25*ONE_ATMOSPHERE)*(air_contents.return_volume())/(R_IDEAL_GAS_EQUATION*air_contents.return_temperature())) /obj/machinery/atmospherics/components/unary/tank icon = 'icons/obj/atmospherics/pipes/pressure_tank.dmi' icon_state = "generic" @@ -15,10 +15,10 @@ /obj/machinery/atmospherics/components/unary/tank/New() ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.volume = volume - air_contents.temperature = T20C + air_contents.set_volume(volume) + air_contents.set_temperature(T20C) if(gas_type) - air_contents.gases[gas_type] = AIR_CONTENTS + air_contents.set_moles(AIR_CONTENTS) name = "[name] ([GLOB.meta_gas_names[gas_type]])" /obj/machinery/atmospherics/components/unary/tank/air @@ -28,8 +28,8 @@ /obj/machinery/atmospherics/components/unary/tank/air/New() ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.gases[/datum/gas/oxygen] = AIR_CONTENTS * 0.2 - air_contents.gases[/datum/gas/nitrogen] = AIR_CONTENTS * 0.8 + air_contents.set_moles(/datum/gas/oxygen, AIR_CONTENTS * 0.2) + air_contents.set_moles(/datum/gas/nitrogen, AIR_CONTENTS * 0.8) /obj/machinery/atmospherics/components/unary/tank/carbon_dioxide gas_type = /datum/gas/carbon_dioxide diff --git a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm index 7af3e57bc7..8456c0b346 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/thermomachine.dm @@ -11,8 +11,6 @@ layer = OBJ_LAYER plane = GAME_PLANE circuit = /obj/item/circuitboard/machine/thermomachine - ui_x = 300 - ui_y = 230 pipe_flags = PIPING_ONE_PER_TURF @@ -74,13 +72,13 @@ var/air_heat_capacity = air_contents.heat_capacity() var/combined_heat_capacity = heat_capacity + air_heat_capacity - var/old_temperature = air_contents.temperature + var/old_temperature = air_contents.return_temperature() if(combined_heat_capacity > 0) - var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.temperature - air_contents.temperature = combined_energy/combined_heat_capacity + var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.return_temperature() + air_contents.set_temperature(combined_energy/combined_heat_capacity) - var/temperature_delta= abs(old_temperature - air_contents.temperature) + var/temperature_delta= abs(old_temperature - air_contents.return_temperature()) if(temperature_delta > 1) active_power_usage = (heat_capacity * temperature_delta) / 10 + idle_power_usage update_parents() @@ -125,11 +123,10 @@ return ..() return UI_CLOSE -/obj/machinery/atmospherics/components/unary/thermomachine/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/atmospherics/components/unary/thermomachine/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "thermomachine", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "ThermoMachine", name) ui.open() /obj/machinery/atmospherics/components/unary/thermomachine/ui_data(mob/user) @@ -142,7 +139,7 @@ data["initial"] = initial(target_temperature) var/datum/gas_mixture/air1 = airs[1] - data["temperature"] = air1.temperature + data["temperature"] = air1.return_temperature() data["pressure"] = air1.return_pressure() return data diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index 9788bcb4ee..1a86898f1f 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -104,8 +104,8 @@ pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound)) if(pressure_delta > 0) - if(air_contents.temperature > 0) - var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION) + if(air_contents.return_temperature() > 0) + var/transfer_moles = pressure_delta*environment.return_volume()/(air_contents.return_temperature() * R_IDEAL_GAS_EQUATION) var/datum/gas_mixture/removed = air_contents.remove(transfer_moles) @@ -113,21 +113,21 @@ air_update_turf() else // external -> internal - var/pressure_delta = 10000 - if(pressure_checks&EXT_BOUND) - pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound)) - if(pressure_checks&INT_BOUND) - pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure())) + if(environment.return_pressure() > 0) + var/our_multiplier = air_contents.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION) + var/moles_delta = 10000 * our_multiplier + if(pressure_checks&EXT_BOUND) + moles_delta = min(moles_delta, (environment_pressure - external_pressure_bound) * environment.return_volume() / (environment.return_temperature() * R_IDEAL_GAS_EQUATION)) + if(pressure_checks&INT_BOUND) + moles_delta = min(moles_delta, (internal_pressure_bound - air_contents.return_pressure()) * our_multiplier) - if(pressure_delta > 0 && environment.temperature > 0) - var/transfer_moles = pressure_delta * air_contents.volume / (environment.temperature * R_IDEAL_GAS_EQUATION) + if(moles_delta > 0) + var/datum/gas_mixture/removed = loc.remove_air(moles_delta) + if (isnull(removed)) // in space + return - var/datum/gas_mixture/removed = loc.remove_air(transfer_moles) - if (isnull(removed)) // in space - return - - air_contents.merge(removed) - air_update_turf() + air_contents.merge(removed) + air_update_turf() update_parents() //Radio remote control @@ -295,7 +295,7 @@ /obj/machinery/atmospherics/components/unary/vent_pump/high_volume/New() ..() var/datum/gas_mixture/air_contents = airs[1] - air_contents.volume = 1000 + air_contents.set_volume(1000) // mapping diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 10eac9c717..025c9734ca 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -149,43 +149,29 @@ return FALSE var/datum/gas_mixture/environment = tile.return_air() var/datum/gas_mixture/air_contents = airs[1] - var/list/env_gases = environment.gases if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE) return FALSE if(scrubbing & SCRUBBING) - if(length(env_gases & filter_types)) - var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles() + var/transfer_moles = min(1, volume_rate/environment.return_volume())*environment.total_moles() - //Take a gas sample - var/datum/gas_mixture/removed = tile.remove_air(transfer_moles) + //Take a gas sample + var/datum/gas_mixture/removed = tile.remove_air(transfer_moles) - //Nothing left to remove from the tile - if(isnull(removed)) - return FALSE + //Nothing left to remove from the tile + if(isnull(removed)) + return FALSE - var/list/removed_gases = removed.gases + removed.scrub_into(air_contents, filter_types) - //Filter it - var/datum/gas_mixture/filtered_out = new - var/list/filtered_gases = filtered_out.gases - filtered_out.temperature = removed.temperature - - for(var/gas in filter_types & removed_gases) - filtered_gases[gas] = removed_gases[gas] - removed_gases[gas] = 0 - - GAS_GARBAGE_COLLECT(removed.gases) - - //Remix the resulting gases - air_contents.merge(filtered_out) - tile.assume_air(removed) - tile.air_update_turf() + //Remix the resulting gases + tile.assume_air(removed) + tile.air_update_turf() else //Just siphoning all air - var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume) + var/transfer_moles = environment.total_moles()*(volume_rate/environment.return_volume()) var/datum/gas_mixture/removed = tile.remove_air(transfer_moles) diff --git a/code/modules/atmospherics/machinery/datum_pipeline.dm b/code/modules/atmospherics/machinery/datum_pipeline.dm index 565bbb7b3c..098df67321 100644 --- a/code/modules/atmospherics/machinery/datum_pipeline.dm +++ b/code/modules/atmospherics/machinery/datum_pipeline.dm @@ -15,7 +15,7 @@ /datum/pipeline/Destroy() SSair.networks -= src - if(air && air.volume) + if(air && air.return_volume()) temporarily_store_air() for(var/obj/machinery/atmospherics/pipe/P in members) P.parent = null @@ -76,7 +76,7 @@ possible_expansions -= borderline - air.volume = volume + air.set_volume(volume) /datum/pipeline/proc/addMachineryMember(obj/machinery/atmospherics/components/C) other_atmosmch |= C @@ -99,7 +99,7 @@ merge(E) if(!members.Find(P)) members += P - air.volume += P.volume + air.set_volume(air.return_volume() + P.volume) else A.setPipenet(src, N) addMachineryMember(A) @@ -107,7 +107,7 @@ /datum/pipeline/proc/merge(datum/pipeline/E) if(E == src) return - air.volume += E.air.volume + air.set_volume(air.return_volume() + E.air.return_volume()) members.Add(E.members) for(var/obj/machinery/atmospherics/pipe/S in E.members) S.parent = src @@ -139,18 +139,16 @@ for(var/obj/machinery/atmospherics/pipe/member in members) member.air_temporary = new - member.air_temporary.volume = member.volume + member.air_temporary.set_volume(member.volume) member.air_temporary.copy_from(air) - var/member_gases = member.air_temporary.gases - for(var/id in member_gases) - member_gases[id] *= member.volume/air.volume + member.air_temporary.multiply(member.volume/air.return_volume()) - member.air_temporary.temperature = air.temperature + member.air_temporary.set_temperature(air.return_temperature()) /datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity) var/total_heat_capacity = air.heat_capacity() - var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) + var/partial_heat_capacity = total_heat_capacity*(share_volume/air.return_volume()) var/target_temperature var/target_heat_capacity @@ -163,19 +161,19 @@ if(modeled_location.blocks_air) if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.temperature - target_temperature + var/delta_temperature = air.return_temperature() - target_temperature var/heat = thermal_conductivity*delta_temperature* \ (partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity)) - air.temperature -= heat/total_heat_capacity + air.set_temperature(air.return_temperature() - heat/total_heat_capacity) modeled_location.TakeTemperature(heat/target_heat_capacity) else var/delta_temperature = 0 var/sharer_heat_capacity = 0 - delta_temperature = (air.temperature - target_temperature) + delta_temperature = (air.return_temperature() - target_temperature) sharer_heat_capacity = target_heat_capacity var/self_temperature_delta = 0 @@ -190,18 +188,18 @@ else return 1 - air.temperature += self_temperature_delta + air.set_temperature(air.return_temperature() + self_temperature_delta) modeled_location.TakeTemperature(sharer_temperature_delta) else if((target.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.temperature - target.temperature + var/delta_temperature = air.return_temperature() - target.return_temperature() var/heat = thermal_conductivity*delta_temperature* \ (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) - air.temperature -= heat/total_heat_capacity + air.set_temperature(air.return_temperature() - heat/total_heat_capacity) update = TRUE /datum/pipeline/proc/return_air() @@ -242,20 +240,18 @@ for(var/i in GL) var/datum/gas_mixture/G = i - total_gas_mixture.volume += G.volume + total_gas_mixture.set_volume(total_gas_mixture.return_volume() + G.return_volume()) total_gas_mixture.merge(G) - total_thermal_energy += THERMAL_ENERGY(G) + total_thermal_energy += G.thermal_energy() total_heat_capacity += G.heat_capacity() - total_gas_mixture.temperature = total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0 + total_gas_mixture.set_temperature(total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0) - if(total_gas_mixture.volume > 0) + if(total_gas_mixture.return_volume() > 0) //Update individual gas_mixtures by volume ratio for(var/i in GL) var/datum/gas_mixture/G = i G.copy_from(total_gas_mixture) - var/list/G_gases = G.gases - for(var/id in G_gases) - G_gases[id] *= G.volume/total_gas_mixture.volume + G.multiply(G.return_volume()/total_gas_mixture.return_volume()) diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index fab70cc168..c17c93ab95 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -103,7 +103,7 @@ if (target) var/datum/gas_mixture/environment = target.return_air() if(environment) - . = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)] K ([round(environment.temperature-T0C,0.01)]°C)." + . = "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.return_temperature(),0.01)] K ([round(environment.return_temperature()-T0C,0.01)]°C)." else . = "The sensor error light is blinking." else diff --git a/code/modules/atmospherics/machinery/other/miner.dm b/code/modules/atmospherics/machinery/other/miner.dm index c90d388a1d..1842211fd2 100644 --- a/code/modules/atmospherics/machinery/other/miner.dm +++ b/code/modules/atmospherics/machinery/other/miner.dm @@ -131,8 +131,8 @@ if(!isopenturf(O)) return FALSE var/datum/gas_mixture/merger = new - merger.gases[spawn_id] = (spawn_mol) - merger.temperature = spawn_temp + merger.set_moles(spawn_id, spawn_mol) + merger.set_temperature(spawn_temp) O.assume_air(merger) O.air_update_turf(TRUE) diff --git a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm index 4da053d3c8..7c170f8afc 100644 --- a/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/heat_exchange/he_pipes.dm @@ -28,14 +28,14 @@ if(islava(T)) environment_temperature = 5000 else if(T.blocks_air) - environment_temperature = T.temperature + environment_temperature = T.return_temperature() else var/turf/open/OT = T environment_temperature = OT.GetTemperature() else - environment_temperature = T.temperature + environment_temperature = T.return_temperature() - if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference) + if(abs(environment_temperature-pipe_air.return_temperature()) > minimum_temperature_difference) parent.temperature_interact(T, volume, thermal_conductivity) @@ -44,11 +44,11 @@ var/hc = pipe_air.heat_capacity() var/mob/living/heat_source = buckled_mobs[1] //Best guess-estimate of the total bodytemperature of all the mobs, since they share the same environment it's ~ok~ to guess like this - var/avg_temp = (pipe_air.temperature * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0)) + var/avg_temp = (pipe_air.return_temperature() * hc + (heat_source.bodytemperature * buckled_mobs.len) * 3500) / (hc + (buckled_mobs ? buckled_mobs.len * 3500 : 0)) for(var/m in buckled_mobs) var/mob/living/L = m L.bodytemperature = avg_temp - pipe_air.temperature = avg_temp + pipe_air.set_temperature(avg_temp) /obj/machinery/atmospherics/pipe/heat_exchanging/process() if(!parent) @@ -57,9 +57,9 @@ var/datum/gas_mixture/pipe_air = return_air() //Heat causes pipe to glow - if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //glow starts at 500K - if(abs(pipe_air.temperature - icon_temperature) > 10) - icon_temperature = pipe_air.temperature + if(pipe_air.return_temperature() && (icon_temperature > 500 || pipe_air.return_temperature() > 500)) //glow starts at 500K + if(abs(pipe_air.return_temperature() - icon_temperature) > 10) + icon_temperature = pipe_air.return_temperature() var/h_r = heat2colour_r(icon_temperature) var/h_g = heat2colour_g(icon_temperature) @@ -76,7 +76,7 @@ //burn any mobs buckled based on temperature if(has_buckled_mobs()) var/heat_limit = 1000 - if(pipe_air.temperature > heat_limit + 1) + if(pipe_air.return_temperature() > heat_limit + 1) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - buckled_mob.apply_damage(4 * log(pipe_air.temperature - heat_limit), BURN, BODY_ZONE_CHEST) + buckled_mob.apply_damage(4 * log(pipe_air.return_temperature() - heat_limit), BURN, BODY_ZONE_CHEST) diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 4a6170c251..23fd2292ff 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -64,6 +64,7 @@ /obj/machinery/atmospherics/pipe/analyzer_act(mob/living/user, obj/item/I) atmosanalyzer_scan(parent.air, user, src) + return TRUE /obj/machinery/atmospherics/pipe/returnPipenet() return parent diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index 03463ff0f7..c66aabd57f 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -34,6 +34,7 @@ var/restricted = FALSE req_access = list() + var/update = 0 var/static/list/label2types = list( "n2" = /obj/machinery/portable_atmospherics/canister/nitrogen, "o2" = /obj/machinery/portable_atmospherics/canister/oxygen, @@ -159,11 +160,11 @@ /obj/machinery/portable_atmospherics/canister/proto name = "prototype canister" + /obj/machinery/portable_atmospherics/canister/proto/default name = "prototype canister" desc = "The best way to fix an atmospheric emergency... or the best way to introduce one." icon_state = "proto" - icon_state = "proto" volume = 5000 max_integrity = 300 temperature_resistance = 2000 + T0C @@ -171,6 +172,7 @@ can_min_release_pressure = (ONE_ATMOSPHERE / 30) prototype = TRUE + /obj/machinery/portable_atmospherics/canister/proto/default/oxygen name = "prototype canister" desc = "A prototype canister for a prototype bike, what could go wrong?" @@ -192,6 +194,7 @@ update_icon() + /obj/machinery/portable_atmospherics/canister/Destroy() qdel(pump) pump = null @@ -200,14 +203,14 @@ /obj/machinery/portable_atmospherics/canister/proc/create_gas() if(gas_type) if(starter_temp) - air_contents.temperature = starter_temp - air_contents.gases[gas_type] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) + air_contents.set_temperature(starter_temp) + air_contents.set_moles(gas_type,(maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) if(starter_temp) - air_contents.temperature = starter_temp + air_contents.set_temperature(starter_temp) /obj/machinery/portable_atmospherics/canister/air/create_gas() - air_contents.gases[/datum/gas/oxygen] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) - air_contents.gases[/datum/gas/nitrogen] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature) + air_contents.set_moles(/datum/gas/oxygen, (O2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) + air_contents.set_moles(/datum/gas/nitrogen, (N2STANDARD * maximum_pressure * filled) * air_contents.return_volume() / (R_IDEAL_GAS_EQUATION * air_contents.return_temperature())) /obj/machinery/portable_atmospherics/canister/update_icon_state() if(stat & BROKEN) @@ -215,7 +218,6 @@ /obj/machinery/portable_atmospherics/canister/update_overlays() . = ..() - if(holding) . += "can-open" if(connected_port) @@ -245,7 +247,8 @@ new /obj/item/stack/sheet/metal (loc, 5) qdel(src) -/obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I) +obj/machinery/portable_atmospherics/canister/welder_act(mob/living/user, obj/item/I) + ..() if(user.a_intent == INTENT_HARM) return FALSE @@ -263,6 +266,7 @@ /obj/machinery/portable_atmospherics/canister/obj_break(damage_flag) if((stat & BROKEN) || (flags_1 & NODECONSTRUCT_1)) return + stat |= BROKEN canister_break() /obj/machinery/portable_atmospherics/canister/proc/canister_break() @@ -272,10 +276,9 @@ T.assume_air(expelled_gas) air_update_turf() - stat |= BROKEN + obj_break() density = FALSE - playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3) - update_icon() + playsound(src.loc, 'sound/effects/spray.ogg', 10, TRUE, -3) investigate_log("was destroyed.", INVESTIGATE_ATMOS) if(holding) @@ -314,11 +317,13 @@ air_update_turf() // Update the environment if needed. update_icon() -/obj/machinery/portable_atmospherics/canister/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) +/obj/machinery/portable_atmospherics/canister/ui_state(mob/user) + return GLOB.physical_state + +/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "canister", name, 420, 405, master_ui, state) + ui = new(user, src, "Canister", name) ui.open() /obj/machinery/portable_atmospherics/canister/ui_data() @@ -353,7 +358,7 @@ return switch(action) if("relabel") - var/label = input("New canister label:", name) as null|anything in label2types + var/label = input("New canister label:", name) as null|anything in sortList(label2types) if(label && !..()) var/newtype = label2types[label] if(newtype) @@ -396,8 +401,8 @@ logmsg = "Valve was opened by [key_name(usr)], starting a transfer into \the [holding || "air"].
    " if(!holding) var/list/danger = list() - for(var/id in air_contents.gases) - var/gas = air_contents.gases[id] + for(var/id in air_contents.get_gases()) + var/gas = air_contents.get_moles(id) if(!GLOB.meta_gas_dangers[id]) continue if(gas > (GLOB.meta_gas_visibility[id] || MOLES_GAS_VISIBLE)) //if moles_visible is undefined, default to default visibility diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 952db8315a..fa57e683c4 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -18,9 +18,8 @@ ..() SSair.atmos_machinery += src - air_contents = new - air_contents.volume = volume - air_contents.temperature = T20C + air_contents = new(volume) + air_contents.set_temperature(T20C) return 1 @@ -146,6 +145,7 @@ /obj/machinery/portable_atmospherics/analyzer_act(mob/living/user, obj/item/I) atmosanalyzer_scan(air_contents, user, src) + return TRUE /obj/machinery/portable_atmospherics/attacked_by(obj/item/I, mob/user, attackchain_flags = NONE, damage_multiplier = 1) if(I.force < 10 && !(stat & BROKEN)) diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm index 377e9285e3..bdde8f0f22 100644 --- a/code/modules/atmospherics/machinery/portable/pump.dm +++ b/code/modules/atmospherics/machinery/portable/pump.dm @@ -32,7 +32,6 @@ /obj/machinery/portable_atmospherics/pump/update_icon_state() icon_state = "psiphon:[on]" - /obj/machinery/portable_atmospherics/pump/update_overlays() . = ..() if(holding) @@ -79,14 +78,13 @@ on = FALSE update_icon() else if(on && holding && direction == PUMP_OUT) - investigate_log("[key_name(user)] started a transfer into [holding].
    ", INVESTIGATE_ATMOS) + investigate_log("[key_name(user)] started a transfer into [holding].", INVESTIGATE_ATMOS) -/obj/machinery/portable_atmospherics/pump/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) +/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "portable_pump", name, 300, 315, master_ui, state) + ui = new(user, src, "PortablePump", name) ui.open() /obj/machinery/portable_atmospherics/pump/ui_data() @@ -115,20 +113,20 @@ if("power") on = !on if(on && !holding) - var/plasma = air_contents.gases[/datum/gas/plasma] - var/n2o = air_contents.gases[/datum/gas/nitrous_oxide] + var/plasma = air_contents.get_moles(/datum/gas/plasma) + var/n2o = air_contents.get_moles(/datum/gas/nitrous_oxide) if(n2o || plasma) message_admins("[ADMIN_LOOKUPFLW(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [ADMIN_VERBOSEJMP(src)]") log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [AREACOORD(src)]") else if(on && direction == PUMP_OUT) - investigate_log("[key_name(usr)] started a transfer into [holding].
    ", INVESTIGATE_ATMOS) + investigate_log("[key_name(usr)] started a transfer into [holding].", INVESTIGATE_ATMOS) . = TRUE if("direction") if(direction == PUMP_OUT) direction = PUMP_IN else if(on && holding) - investigate_log("[key_name(usr)] started a transfer into [holding].
    ", INVESTIGATE_ATMOS) + investigate_log("[key_name(usr)] started a transfer into [holding].", INVESTIGATE_ATMOS) direction = PUMP_OUT . = TRUE if("pressure") @@ -142,10 +140,6 @@ else if(pressure == "max") pressure = PUMP_MAX_PRESSURE . = TRUE - else if(pressure == "input") - pressure = input("New release pressure ([PUMP_MIN_PRESSURE]-[PUMP_MAX_PRESSURE] kPa):", name, pump.target_pressure) as num|null - if(!isnull(pressure) && !..()) - . = TRUE else if(text2num(pressure) != null) pressure = text2num(pressure) . = TRUE @@ -154,7 +148,6 @@ investigate_log("was set to [pump.target_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS) if("eject") if(holding) - holding.forceMove(drop_location()) - holding = null + replace_tank(usr, FALSE) . = TRUE update_icon() diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm index 3dfce7c1bf..7976ba641a 100644 --- a/code/modules/atmospherics/machinery/portable/scrubber.dm +++ b/code/modules/atmospherics/machinery/portable/scrubber.dm @@ -2,6 +2,8 @@ name = "portable air scrubber" icon_state = "pscrubber:0" density = TRUE + ui_x = 320 + ui_y = 350 var/on = FALSE var/volume_rate = 1000 @@ -40,20 +42,13 @@ scrub(T.return_air()) /obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture) - var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles() + var/transfer_moles = min(1, volume_rate / mixture.return_volume()) * mixture.total_moles() var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter. - var/datum/gas_mixture/filtered = new if(!filtering) return - filtered.temperature = filtering.temperature - for(var/gas in filtering.gases & scrubbing) - filtered.gases[gas] = filtering.gases[gas] // Shuffle the "bad" gasses to the filtered mixture. - filtering.gases[gas] = 0 - GAS_GARBAGE_COLLECT(filtering.gases) - - air_contents.merge(filtered) // Store filtered out gasses. + filtering.scrub_into(air_contents,scrubbing) mixture.merge(filtering) // Returned the cleaned gas. if(!holding) air_update_turf() @@ -67,11 +62,10 @@ on = !on update_icon() -/obj/machinery/portable_atmospherics/scrubber/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) +/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "portable_scrubber", name, 320, 335, master_ui, state) + ui = new(user, src, "PortableScrubber", name) ui.open() /obj/machinery/portable_atmospherics/scrubber/ui_data() diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm index f841ae20ca..3426208fae 100644 --- a/code/modules/awaymissions/capture_the_flag.dm +++ b/code/modules/awaymissions/capture_the_flag.dm @@ -7,7 +7,7 @@ #define AMMO_DROP_LIFETIME 300 #define CTF_REQUIRED_PLAYERS 4 -/obj/item/twohanded/ctf +/obj/item/ctf name = "banner" icon = 'icons/obj/items_and_weapons.dmi' icon_state = "banner" @@ -16,6 +16,7 @@ righthand_file = 'icons/mob/inhands/equipment/banners_righthand.dmi' desc = "A banner with Nanotrasen's logo on it." slowdown = 2 + item_flags = SLOWS_WHILE_IN_HAND throw_speed = 0 throw_range = 1 force = 200 @@ -28,16 +29,20 @@ var/obj/effect/ctf/flag_reset/reset var/reset_path = /obj/effect/ctf/flag_reset -/obj/item/twohanded/ctf/Destroy() +/obj/item/ctf/Destroy() QDEL_NULL(reset) return ..() -/obj/item/twohanded/ctf/Initialize() +/obj/item/ctf/Initialize() . = ..() if(!reset) reset = new reset_path(get_turf(src)) -/obj/item/twohanded/ctf/process() +/obj/item/ctf/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed) + +/obj/item/ctf/process() if(is_ctf_target(loc)) //don't reset from someone's hands. return PROCESS_KILL if(world.time > reset_cooldown) @@ -48,8 +53,7 @@ to_chat(M, "\The [src] has been returned to base!") STOP_PROCESSING(SSobj, src) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/twohanded/ctf/attack_hand(mob/living/user) +/obj/item/ctf/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(!is_ctf_target(user) && !anyonecanpickup) to_chat(user, "Non players shouldn't be moving the flag!") return @@ -73,7 +77,7 @@ STOP_PROCESSING(SSobj, src) ..() -/obj/item/twohanded/ctf/dropped(mob/user) +/obj/item/ctf/dropped(mob/user) ..() user.anchored = FALSE user.status_flags |= CANPUSH @@ -86,7 +90,7 @@ anchored = TRUE -/obj/item/twohanded/ctf/red +/obj/item/ctf/red name = "red flag" icon_state = "banner-red" item_state = "banner-red" @@ -95,7 +99,7 @@ reset_path = /obj/effect/ctf/flag_reset/red -/obj/item/twohanded/ctf/blue +/obj/item/ctf/blue name = "blue flag" icon_state = "banner-blue" item_state = "banner-blue" @@ -276,8 +280,8 @@ attack_ghost(ghost) /obj/machinery/capture_the_flag/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/twohanded/ctf)) - var/obj/item/twohanded/ctf/flag = I + if(istype(I, /obj/item/ctf)) + var/obj/item/ctf/flag = I if(flag.team != src.team) user.transferItemToLoc(flag, get_turf(flag.reset), TRUE) points++ @@ -294,7 +298,7 @@ if(istype(mob_area, /area/ctf)) to_chat(M, "[team] team wins!") to_chat(M, "Teams have been cleared. Click on the machines to vote to begin another round.") - for(var/obj/item/twohanded/ctf/W in M) + for(var/obj/item/ctf/W in M) M.dropItemToGround(W) M.dust() for(var/obj/machinery/control_point/control in GLOB.machines) @@ -335,7 +339,7 @@ var/list/ctf_object_typecache = typecacheof(list( /obj/machinery, /obj/effect/ctf, - /obj/item/twohanded/ctf + /obj/item/ctf )) for(var/atm in A) if (isturf(A) || ismob(A) || isarea(A)) @@ -674,10 +678,7 @@ /obj/machinery/control_point/attackby(mob/user, params) capture(user) -/obj/machinery/control_point/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/control_point/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) capture(user) /obj/machinery/control_point/proc/capture(mob/user) diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index c11267a5f3..e68c45a84c 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -594,8 +594,7 @@ assignedrole = "Space Bar Patron" job_description = "Space Bar Patron" -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/mob_spawn/human/alive/space_bar_patron/attack_hand(mob/user) +/obj/effect/mob_spawn/human/alive/space_bar_patron/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/despawn = alert("Return to cryosleep? (Warning, Your mob will be deleted!)",,"Yes","No") if(despawn == "No" || !loc || !Adjacent(user)) return @@ -661,5 +660,5 @@ /datum/outfit/lavaknight/captain name ="Cydonian Knight Captain" - l_pocket = /obj/item/twohanded/dualsaber/hypereutactic + l_pocket = /obj/item/dualsaber/hypereutactic id = /obj/item/card/id/knight/captain diff --git a/code/modules/awaymissions/gateway.dm b/code/modules/awaymissions/gateway.dm index 4f155d4174..8476090f75 100644 --- a/code/modules/awaymissions/gateway.dm +++ b/code/modules/awaymissions/gateway.dm @@ -1,246 +1,328 @@ +/// Station home gateway GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation) +/// List of possible gateway destinations. +GLOBAL_LIST_EMPTY(gateway_destinations) + +/** + * Corresponds to single entry in gateway control. + * + * Will NOT be added automatically to GLOB.gateway_destinations list. + */ +/datum/gateway_destination + var/name = "Unknown Destination" + var/wait = 0 /// How long after roundstart this destination becomes active + var/enabled = TRUE /// If disabled, the destination won't be availible + var/hidden = FALSE /// Will not show on gateway controls at all. + +/* Can a gateway link to this destination right now. */ +/datum/gateway_destination/proc/is_availible() + return enabled && (world.time - SSticker.round_start_time >= wait) + +/* Returns user-friendly description why you can't connect to this destination, displayed in UI */ +/datum/gateway_destination/proc/get_availible_reason() + . = "Unreachable" + if(world.time - SSticker.round_start_time < wait) + . = "Connection desynchronized. Recalibration in progress." + +/* Check if the movable is allowed to arrive at this destination (exile implants mostly) */ +/datum/gateway_destination/proc/incoming_pass_check(atom/movable/AM) + return TRUE + +/* Get the actual turf we'll arrive at */ +/datum/gateway_destination/proc/get_target_turf() + CRASH("get target turf not implemented for this destination type") + +/* Called after moving the movable to target turf */ +/datum/gateway_destination/proc/post_transfer(atom/movable/AM) + if (ismob(AM)) + var/mob/M = AM + if (M.client) + M.client.move_delay = max(world.time + 5, M.client.move_delay) + +/* Called when gateway activates with this destination. */ +/datum/gateway_destination/proc/activate(obj/machinery/gateway/activated) + return + +/* Called when gateway targeting this destination deactivates. */ +/datum/gateway_destination/proc/deactivate(obj/machinery/gateway/deactivated) + return + +/* Returns data used by gateway controller ui */ +/datum/gateway_destination/proc/get_ui_data() + . = list() + .["ref"] = REF(src) + .["name"] = name + .["availible"] = is_availible() + .["reason"] = get_availible_reason() + if(wait) + .["timeout"] = max(1 - (wait - (world.time - SSticker.round_start_time)) / wait, 0) + +/* Destination is another gateway */ +/datum/gateway_destination/gateway + /// The gateway this destination points at + var/obj/machinery/gateway/target_gateway + +/* We set the target gateway target to activator gateway */ +/datum/gateway_destination/gateway/activate(obj/machinery/gateway/activated) + if(!target_gateway.target) + target_gateway.activate(activated) + +/* We turn off the target gateway if it's linked with us */ +/datum/gateway_destination/gateway/deactivate(obj/machinery/gateway/deactivated) + if(target_gateway.target == deactivated.destination) + target_gateway.deactivate() + +/datum/gateway_destination/gateway/is_availible() + return ..() && target_gateway.calibrated && !target_gateway.target && target_gateway.powered() + +/datum/gateway_destination/gateway/get_availible_reason() + . = ..() + if(!target_gateway.calibrated) + . = "Exit gateway malfunction. Manual recalibration required." + if(target_gateway.target) + . = "Exit gateway in use." + if(!target_gateway.powered()) + . = "Exit gateway unpowered." + +/datum/gateway_destination/gateway/get_target_turf() + return get_step(target_gateway.portal,SOUTH) + +/datum/gateway_destination/gateway/post_transfer(atom/movable/AM) + . = ..() + addtimer(CALLBACK(AM,/atom/movable.proc/setDir,SOUTH),0) + +/* Special home destination, so we can check exile implants */ +/datum/gateway_destination/gateway/home + +/datum/gateway_destination/gateway/home/incoming_pass_check(atom/movable/AM) + if(isliving(AM)) + if(check_exile_implant(AM)) + return FALSE + else + for(var/mob/living/L in AM.contents) + if(check_exile_implant(L)) + target_gateway.say("Rejecting [AM]: Exile implant detected in contained lifeform.") + return FALSE + if(AM.has_buckled_mobs()) + for(var/mob/living/L in AM.buckled_mobs) + if(check_exile_implant(L)) + target_gateway.say("Rejecting [AM]: Exile implant detected in close proximity lifeform.") + return FALSE + return TRUE + +/datum/gateway_destination/gateway/home/proc/check_exile_implant(mob/living/L) + for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant + to_chat(L, "The station gate has detected your exile implant and is blocking your entry.") + return TRUE + return FALSE + + +/* Destination is one ore more turfs - created by landmarks */ +/datum/gateway_destination/point + var/list/target_turfs = list() + /// Used by away landmarks + var/id + +/datum/gateway_destination/point/get_target_turf() + return pick(target_turfs) + +/* Dense invisible object starting the teleportation. Created by gateways on activation. */ +/obj/effect/gateway_portal_bumper + var/obj/machinery/gateway/gateway + density = TRUE + invisibility = INVISIBILITY_ABSTRACT + +/obj/effect/gateway_portal_bumper/Bumped(atom/movable/AM) + if(get_dir(src,AM) == SOUTH) + gateway.Transfer(AM) + +/obj/effect/gateway_portal_bumper/Destroy(force) + . = ..() + gateway = null /obj/machinery/gateway name = "gateway" desc = "A mysterious gateway built by unknown hands, it allows for faster than light travel to far-flung locations." icon = 'icons/obj/machines/gateway.dmi' icon_state = "off" - density = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - var/active = 0 - var/checkparts = TRUE - var/list/obj/effect/landmark/randomspawns = list() + + // 3x2 offset by one row + pixel_x = -32 + pixel_y = -32 + bound_height = 64 + bound_width = 96 + bound_x = -32 + bound_y = 0 + density = TRUE + + use_power = IDLE_POWER_USE + idle_power_usage = 100 + active_power_usage = 5000 + var/calibrated = TRUE - var/list/linked = list() - var/can_link = FALSE //Is this the centerpiece? + /// Type of instanced gateway destination, needs to be subtype of /datum/gateway_destination/gateway + var/destination_type = /datum/gateway_destination/gateway + /// Name of the generated destination + var/destination_name = "Unknown Gateway" + /// This is our own destination, pointing at this gateway + var/datum/gateway_destination/gateway/destination + /// This is current active destination + var/datum/gateway_destination/target + /// bumper object, the thing that starts actual teleport + var/obj/effect/gateway_portal_bumper/portal /obj/machinery/gateway/Initialize() - randomspawns = GLOB.awaydestinations + generate_destination() update_icon() - if(!istype(src, /obj/machinery/gateway/centerstation) && !istype(src, /obj/machinery/gateway/centeraway)) - switch(dir) - if(SOUTH,SOUTHEAST,SOUTHWEST) - density = FALSE return ..() -/obj/machinery/gateway/proc/toggleoff() - for(var/obj/machinery/gateway/G in linked) - G.active = 0 - G.update_icon() - active = 0 +/obj/machinery/gateway/proc/generate_destination() + destination = new destination_type + destination.name = destination_name + destination.target_gateway = src + GLOB.gateway_destinations += destination + +/obj/machinery/gateway/proc/deactivate() + var/datum/gateway_destination/dest = target + target = null + dest.deactivate(src) + QDEL_NULL(portal) + if(use_power == ACTIVE_POWER_USE) + use_power = IDLE_POWER_USE update_icon() -/obj/machinery/gateway/proc/detect() - if(!can_link) - return FALSE - linked = list() //clear the list - var/turf/T = loc - var/ready = FALSE - - for(var/i in GLOB.alldirs) - T = get_step(loc, i) - var/obj/machinery/gateway/G = locate(/obj/machinery/gateway) in T - if(G) - linked.Add(G) - continue - - //this is only done if we fail to find a part - ready = FALSE - toggleoff() - break - - if((linked.len == 8) || !checkparts) - ready = TRUE - return ready +/obj/machinery/gateway/process() + if((stat & (NOPOWER)) && use_power) + if(target) + deactivate() + return /obj/machinery/gateway/update_icon_state() - icon_state = active ? "on" : "off" + if(target) + icon_state = "on" + else + icon_state = "off" -/obj/machinery/gateway/attack_hand(mob/user) - . = ..() - if(.) - return - if(!detect()) - return - if(!active) - toggleon(user) - return - toggleoff() - -/obj/machinery/gateway/proc/toggleon(mob/user) - return FALSE - -/obj/machinery/gateway/safe_throw_at() +/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE) return +/obj/machinery/gateway/proc/generate_bumper() + portal = new(get_turf(src)) + portal.gateway = src + +/obj/machinery/gateway/proc/activate(datum/gateway_destination/D) + if(!powered() || target) + return + target = D + target.activate(destination) + generate_bumper() + if(use_power == IDLE_POWER_USE) + use_power = ACTIVE_POWER_USE + update_icon() + +/obj/machinery/gateway/proc/Transfer(atom/movable/AM) + if(!target || !target.incoming_pass_check(AM)) + return + AM.forceMove(target.get_target_turf()) + target.post_transfer(AM) + +/* Station's primary gateway */ +/obj/machinery/gateway/centerstation + destination_type = /datum/gateway_destination/gateway/home + destination_name = "Home Gateway" + /obj/machinery/gateway/centerstation/Initialize() . = ..() if(!GLOB.the_gateway) GLOB.the_gateway = src - update_icon() - wait = world.time + CONFIG_GET(number/gateway_delay) //+ thirty minutes default - awaygate = locate(/obj/machinery/gateway/centeraway) /obj/machinery/gateway/centerstation/Destroy() if(GLOB.the_gateway == src) GLOB.the_gateway = null return ..() -//this is da important part wot makes things go -/obj/machinery/gateway/centerstation - density = TRUE - icon_state = "offcenter" - use_power = IDLE_POWER_USE - - //warping vars - var/wait = 0 //this just grabs world.time at world start - var/obj/machinery/gateway/centeraway/awaygate = null - can_link = TRUE - -/obj/machinery/gateway/centerstation/update_icon_state() - icon_state = active ? "oncenter" : "offcenter" - -/obj/machinery/gateway/centerstation/process() - if((stat & (NOPOWER)) && use_power) - if(active) - toggleoff() - return - - if(active) - use_power(5000) - -/obj/machinery/gateway/centerstation/toggleon(mob/user) - if(!detect()) - return - if(!powered()) - return - if(!awaygate) - to_chat(user, "Error: No destination found.") - return - if(world.time < wait) - to_chat(user, "Error: Warpspace triangulation in progress. Estimated time to completion: [DisplayTimeText(wait - world.time)].") - return - - for(var/obj/machinery/gateway/G in linked) - G.active = 1 - G.update_icon() - active = 1 - update_icon() - -//okay, here's the good teleporting stuff -/obj/machinery/gateway/centerstation/Bumped(atom/movable/AM) - if(!active) - return - if(!detect()) - return - if(!awaygate || QDELETED(awaygate)) - return - - if(awaygate.calibrated) - AM.forceMove(get_step(awaygate.loc, SOUTH)) - AM.setDir(SOUTH) - if (ismob(AM)) - var/mob/M = AM - if (M.client) - M.client.move_delay = max(world.time + 5, M.client.move_delay) - return +/obj/machinery/gateway/multitool_act(mob/living/user, obj/item/I) + if(calibrated) + to_chat(user, "The gate is already calibrated, there is no work for you to do here.") else - var/obj/effect/landmark/dest = pick(randomspawns) - if(dest) - AM.forceMove(get_turf(dest)) - AM.setDir(SOUTH) - use_power(5000) - return - -/obj/machinery/gateway/centeraway/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/multitool)) - if(calibrated) - to_chat(user, "\black The gate is already calibrated, there is no work for you to do here.") - return - else - to_chat(user, "Recalibration successful!: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.") - calibrated = TRUE - return - -/////////////////////////////////////Away//////////////////////// - - -/obj/machinery/gateway/centeraway - density = TRUE - icon_state = "offcenter" - use_power = NO_POWER_USE - var/obj/machinery/gateway/centerstation/stationgate = null - can_link = TRUE - - -/obj/machinery/gateway/centeraway/Initialize() - . = ..() - update_icon() - stationgate = locate(/obj/machinery/gateway/centerstation) - - -/obj/machinery/gateway/centeraway/update_icon_state() - icon_state = active ? "oncenter" : "offcenter" - -/obj/machinery/gateway/centeraway/toggleon(mob/user) - if(!detect()) - return - if(!stationgate) - to_chat(user, "Error: No destination found.") - return - - for(var/obj/machinery/gateway/G in linked) - G.active = 1 - G.update_icon() - active = 1 - update_icon() - -/obj/machinery/gateway/centeraway/proc/check_exile_implant(mob/living/L) - for(var/obj/item/implant/exile/E in L.implants)//Checking that there is an exile implant - to_chat(L, "\black The station gate has detected your exile implant and is blocking your entry.") - return TRUE - return FALSE - -/obj/machinery/gateway/centeraway/Bumped(atom/movable/AM) - if(!detect()) - return - if(!active) - return - if(!stationgate || QDELETED(stationgate)) - return - if(isliving(AM)) - if(check_exile_implant(AM)) - return - else - for(var/mob/living/L in AM.contents) - if(check_exile_implant(L)) - say("Rejecting [AM]: Exile implant detected in contained lifeform.") - return - if(AM.has_buckled_mobs()) - for(var/mob/living/L in AM.buckled_mobs) - if(check_exile_implant(L)) - say("Rejecting [AM]: Exile implant detected in close proximity lifeform.") - return - AM.forceMove(get_step(stationgate.loc, SOUTH)) - AM.setDir(SOUTH) - if (ismob(AM)) - var/mob/M = AM - if (M.client) - M.client.move_delay = max(world.time + 5, M.client.move_delay) - - -/obj/machinery/gateway/centeraway/admin - desc = "A mysterious gateway built by unknown hands, this one seems more compact." - -/obj/machinery/gateway/centeraway/admin/Initialize() - . = ..() - if(stationgate && !stationgate.awaygate) - stationgate.awaygate = src - -/obj/machinery/gateway/centeraway/admin/detect() + to_chat(user, "Recalibration successful!: \black This gate's systems have been fine tuned. Travel to this gate will now be on target.") + calibrated = TRUE return TRUE +/* Doesn't need control console or power, always links to home when interacting. */ +/obj/machinery/gateway/away + density = TRUE + use_power = NO_POWER_USE + +/obj/machinery/gateway/away/interact(mob/user, special_state) + . = ..() + if(!target) + if(!GLOB.the_gateway) + to_chat(user,"Home gateway is not responding!") + if(GLOB.the_gateway.target) + to_chat(user,"Home gateway already in use!") + return + activate(GLOB.the_gateway.destination) + else + deactivate() + +/* Gateway control computer */ +/obj/machinery/computer/gateway_control + name = "Gateway Control" + desc = "Human friendly interface to the mysterious gate next to it." + var/obj/machinery/gateway/G + +/obj/machinery/computer/gateway_control/Initialize(mapload, obj/item/circuitboard/C) + . = ..() + try_to_linkup() + +/obj/machinery/computer/gateway_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Gateway", name) + ui.open() + +/obj/machinery/computer/gateway_control/ui_data(mob/user) + . = ..() + .["gateway_present"] = G + .["gateway_status"] = G ? G.powered() : FALSE + .["current_target"] = G?.target?.get_ui_data() + var/list/destinations = list() + if(G) + for(var/datum/gateway_destination/D in GLOB.gateway_destinations) + if(D == G.destination) + continue + destinations += list(D.get_ui_data()) + .["destinations"] = destinations + +/obj/machinery/computer/gateway_control/ui_act(action, list/params) + . = ..() + if(.) + return + switch(action) + if("linkup") + try_to_linkup() + return TRUE + if("activate") + var/datum/gateway_destination/D = locate(params["destination"]) in GLOB.gateway_destinations + try_to_connect(D) + return TRUE + if("deactivate") + if(G && G.target) + G.deactivate() + return TRUE + +/obj/machinery/computer/gateway_control/proc/try_to_linkup() + G = locate(/obj/machinery/gateway) in view(7,get_turf(src)) + +/obj/machinery/computer/gateway_control/proc/try_to_connect(datum/gateway_destination/D) + if(!D || !G) + return + if(!D.is_availible() || G.target) + return + G.activate(D) /obj/item/paper/fluff/gateway - info = "Congratulations,

    Your station has been selected to carry out the Gateway Project.

    The equipment will be shipped to you at the start of the next quarter.
    You are to prepare a secure location to house the equipment as outlined in the attached documents.

    --Nanotrasen Blue Space Research" + info = "Congratulations,

    Your station has been selected to carry out the Gateway Project.

    The equipment will be shipped to you at the start of the next quarter.
    You are to prepare a secure location to house the equipment as outlined in the attached documents.

    --Nanotrasen Bluespace Research" name = "Confidential Correspondence, Pg 1" diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm index f714a86f22..129e6d7a2b 100644 --- a/code/modules/awaymissions/mission_code/Academy.dm +++ b/code/modules/awaymissions/mission_code/Academy.dm @@ -189,6 +189,8 @@ if(!ishuman(user) || !user.mind || (user.mind in SSticker.mode.wizards)) to_chat(user, "You feel the magic of the dice is restricted to ordinary humans! You should leave it alone.") user.dropItemToGround(src) + return + return ..() /obj/item/dice/d20/fate/proc/effect(var/mob/living/carbon/human/user,roll) diff --git a/code/modules/awaymissions/mission_code/Cabin.dm b/code/modules/awaymissions/mission_code/Cabin.dm index a13fecd11c..1b099a22db 100644 --- a/code/modules/awaymissions/mission_code/Cabin.dm +++ b/code/modules/awaymissions/mission_code/Cabin.dm @@ -1,20 +1,39 @@ /*Cabin areas*/ -/area/awaymission/snowforest - name = "Snow Forest" - icon_state = "away" - requires_power = FALSE - dynamic_lighting = DYNAMIC_LIGHTING_ENABLED - /area/awaymission/cabin name = "Cabin" icon_state = "away2" requires_power = TRUE dynamic_lighting = DYNAMIC_LIGHTING_ENABLED -/area/awaymission/snowforest/lumbermill +/area/awaymission/cabin/snowforest + name = "Snow Forest" + icon_state = "away" + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + +/area/awaymission/cabin/snowforest/sovietsurface + name = "Snow Forest" + icon_state = "awaycontent29" + requires_power = FALSE + +/area/awaymission/cabin/lumbermill name = "Lumbermill" icon_state = "away3" + requires_power = FALSE + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + +/area/awaymission/cabin/caves/sovietcave + name = "Soviet Bunker" + icon_state = "awaycontent4" + +/area/awaymission/cabin/caves + name = "North Snowdin Caves" + icon_state = "awaycontent15" + dynamic_lighting = DYNAMIC_LIGHTING_FORCED + +/area/awaymission/cabin/caves/mountain + name = "North Snowdin Mountains" + icon_state = "awaycontent24" /obj/structure/firepit name = "firepit" @@ -92,7 +111,7 @@ egg_type = null speak = list() -/*Cabin's forest*/ +/*Cabin's forest. Removed in the new cabin map since it was buggy and I prefer manual placement.*/ /datum/mapGenerator/snowy modules = list(/datum/mapGeneratorModule/bottomlayer/snow, \ /datum/mapGeneratorModule/snow/pineTrees, \ @@ -136,4 +155,4 @@ endTurfX = 159 endTurfY = 157 startTurfX = 37 - startTurfY = 35 + startTurfY = 35 \ No newline at end of file diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index fc797d227c..c7e2609436 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -475,43 +475,26 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonlite name = "dungeon lite" - loot = list(/obj/item/melee/classic_baton = 11, - /obj/item/melee/classic_baton/telescopic = 12, - /obj/item/book/granter/spell/smoke = 10, + loot = list(/obj/item/book/granter/spell/smoke = 10, /obj/item/book/granter/spell/blind = 10, /obj/item/storage/firstaid/regular = 45, /obj/item/storage/firstaid/toxin = 35, /obj/item/storage/firstaid/brute = 27, /obj/item/storage/firstaid/fire = 27, /obj/item/storage/toolbox/syndicate = 12, - /obj/item/grenade/plastic/c4 = 7, /obj/item/grenade/clusterbuster/smoke = 15, /obj/item/clothing/under/chameleon = 13, - /obj/item/clothing/shoes/chameleon/noslip = 10, /obj/item/borg/upgrade/ddrill = 3) /obj/effect/spawner/lootdrop/snowdin/dungeonmid name = "dungeon mid" - loot = list(/obj/item/defibrillator/compact = 6, - /obj/item/storage/firstaid/tactical = 35, - /obj/item/shield/energy = 6, - /obj/item/shield/riot/tele = 12, - /obj/item/dnainjector/lasereyesmut = 7, - /obj/item/gun/magic/wand/fireball/inert = 3, + loot = list(/obj/item/shield/riot = 12, /obj/item/pneumatic_cannon = 15, - /obj/item/melee/transforming/energy/sword = 7, - /obj/item/book/granter/spell/knock = 15, - /obj/item/book/granter/spell/summonitem = 20, - /obj/item/book/granter/spell/forcewall = 17, /obj/item/storage/backpack/holding = 12, - /obj/item/grenade/spawnergrenade/manhacks = 6, - /obj/item/grenade/spawnergrenade/spesscarp = 7, - /obj/item/grenade/clusterbuster/inferno = 3, /obj/item/stack/sheet/mineral/diamond{amount = 15} = 10, /obj/item/stack/sheet/mineral/uranium{amount = 15} = 10, /obj/item/stack/sheet/mineral/plasma{amount = 15} = 10, /obj/item/stack/sheet/mineral/gold{amount = 15} = 10, - /obj/item/book/granter/spell/barnyard = 4, /obj/item/pickaxe/drill/diamonddrill = 6, /obj/item/borg/upgrade/vtec = 7, /obj/item/borg/upgrade/disablercooler = 7) @@ -519,21 +502,12 @@ /obj/effect/spawner/lootdrop/snowdin/dungeonheavy name = "dungeon heavy" - loot = list(/obj/item/twohanded/singularityhammer = 25, - /obj/item/twohanded/mjollnir = 10, - /obj/item/twohanded/fireaxe = 25, + loot = list(/obj/item/fireaxe = 25, /obj/item/organ/brain/alien = 17, - /obj/item/twohanded/dualsaber = 15, - /obj/item/organ/heart/demon = 7, - /obj/item/gun/ballistic/automatic/c20r/unrestricted = 16, - /obj/item/gun/magic/wand/resurrection/inert = 15, - /obj/item/gun/magic/wand/resurrection = 10, - /obj/item/uplink/old = 2, - /obj/item/book/granter/spell/charge = 12, - /obj/item/grenade/clusterbuster/spawner_manhacks = 15, - /obj/item/book/granter/spell/fireball = 10, + /obj/item/organ/heart/cursed = 7, + /obj/item/book/granter/spell/forcewall = 17, + /obj/item/gun/magic/wand/fireball/inert = 3, /obj/item/pickaxe/drill/jackhammer = 30, - /obj/item/borg/upgrade/syndicate = 13, /obj/item/borg/upgrade/selfrepair = 17) /obj/effect/spawner/lootdrop/snowdin/dungeonmisc @@ -544,7 +518,7 @@ loot = list(/obj/item/stack/sheet/mineral/snow{amount = 25} = 10, /obj/item/toy/snowball = 15, /obj/item/shovel = 10, - /obj/item/twohanded/spear = 8, + /obj/item/spear = 8, ) //special items//-- diff --git a/code/modules/awaymissions/mission_code/spacebattle.dm b/code/modules/awaymissions/mission_code/spacebattle.dm deleted file mode 100644 index a477a223b2..0000000000 --- a/code/modules/awaymissions/mission_code/spacebattle.dm +++ /dev/null @@ -1,51 +0,0 @@ -//Spacebattle Areas - -/area/awaymission/spacebattle - name = "Space Battle" - icon_state = "awaycontent1" - requires_power = FALSE - -/area/awaymission/spacebattle/cruiser - name = "Nanotrasen Cruiser" - icon_state = "awaycontent2" - -/area/awaymission/spacebattle/syndicate1 - name = "Syndicate Assault Ship 1" - icon_state = "awaycontent3" - -/area/awaymission/spacebattle/syndicate2 - name = "Syndicate Assault Ship 2" - icon_state = "awaycontent4" - -/area/awaymission/spacebattle/syndicate3 - name = "Syndicate Assault Ship 3" - icon_state = "awaycontent5" - -/area/awaymission/spacebattle/syndicate4 - name = "Syndicate War Sphere 1" - icon_state = "awaycontent6" - -/area/awaymission/spacebattle/syndicate5 - name = "Syndicate War Sphere 2" - icon_state = "awaycontent7" - -/area/awaymission/spacebattle/syndicate6 - name = "Syndicate War Sphere 3" - icon_state = "awaycontent8" - -/area/awaymission/spacebattle/syndicate7 - name = "Syndicate Fighter" - icon_state = "awaycontent9" - -/area/awaymission/spacebattle/secret - name = "Hidden Chamber" - icon_state = "awaycontent10" - -/mob/living/simple_animal/hostile/syndicate/ranged/spacebattle - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier, - /obj/item/gun/ballistic/automatic/c20r, - /obj/item/shield/energy) - -/mob/living/simple_animal/hostile/syndicate/melee/spacebattle - deathmessage = "falls limp as they release their grip from the energy weapons, activating their self-destruct function!" - loot = list(/obj/effect/mob_spawn/human/corpse/syndicatesoldier) diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index 6c8d8287d8..1e2e1fe43c 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -15,24 +15,28 @@ INIT_ANNOUNCE("Loaded [name] in [(REALTIMEOFDAY - start_time)/10]s!") GLOB.random_zlevels_generated[name] = TRUE -/proc/reset_gateway_spawns(reset = FALSE) - for(var/obj/machinery/gateway/G in world) - if(reset) - G.randomspawns = GLOB.awaydestinations - else - G.randomspawns.Add(GLOB.awaydestinations) - /obj/effect/landmark/awaystart name = "away mission spawn" desc = "Randomly picked away mission spawn points." + var/id + var/delay = TRUE // If the generated destination should be delayed by configured gateway delay -/obj/effect/landmark/awaystart/New() - GLOB.awaydestinations += src - ..() +/obj/effect/landmark/awaystart/Initialize() + . = ..() + var/datum/gateway_destination/point/current + for(var/datum/gateway_destination/point/D in GLOB.gateway_destinations) + if(D.id == id) + current = D + if(!current) + current = new + current.id = id + if(delay) + current.wait = CONFIG_GET(number/gateway_delay) + GLOB.gateway_destinations += current + current.target_turfs += get_turf(src) -/obj/effect/landmark/awaystart/Destroy() - GLOB.awaydestinations -= src - return ..() +/obj/effect/landmark/awaystart/nodelay + delay = FALSE /proc/generateMapList(filename) . = list() diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm index 4af28d78cc..744c01a257 100644 --- a/code/modules/cargo/bounties/assistant.dm +++ b/code/modules/cargo/bounties/assistant.dm @@ -31,7 +31,7 @@ description = "CentCom's security forces are going through budget cuts. You will be paid if you ship a set of spears." reward = 1000 required_count = 5 - wanted_types = list(/obj/item/twohanded/spear) + wanted_types = list(/obj/item/spear) /datum/bounty/item/assistant/toolbox name = "Toolboxes" @@ -134,7 +134,7 @@ description = "Central Command is looking to commission a new BirdBoat-class station. You've been ordered to supply the potted plants." reward = 2000 required_count = 8 - wanted_types = list(/obj/item/twohanded/required/kirbyplants) + wanted_types = list(/obj/item/kirbyplants) // /datum/bounty/item/assistant/earmuffs // name = "Earmuffs" @@ -160,7 +160,7 @@ name = "Chainsaw" description = "The chef at CentCom is having trouble butchering her animals. She requests one chainsaw, please." reward = 2500 - wanted_types = list(/obj/item/twohanded/required/chainsaw) + wanted_types = list(/obj/item/chainsaw) /datum/bounty/item/assistant/ied name = "IED" diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm index 99e6aa2bdc..b84fd2ca2c 100644 --- a/code/modules/cargo/bounties/engineering.dm +++ b/code/modules/cargo/bounties/engineering.dm @@ -10,9 +10,7 @@ if(!..()) return FALSE var/obj/item/tank/T = O - if(!T.air_contents.gases[gas_type]) - return FALSE - return T.air_contents.gases[gas_type] >= moles_required + return T.air_contents.get_moles(gas_type) >= moles_required //datum/bounty/item/engineering/gas/nitryl_tank // name = "Full Tank of Nitryl" diff --git a/code/modules/cargo/bounties/mining.dm b/code/modules/cargo/bounties/mining.dm index 1f3266af62..cd8d5707d8 100644 --- a/code/modules/cargo/bounties/mining.dm +++ b/code/modules/cargo/bounties/mining.dm @@ -22,7 +22,7 @@ name = "Bone Axe" description = "Station 12 has had their fire axes stolen by marauding clowns. Ship them a bone axe as a replacement." reward = 3500 - wanted_types = list(/obj/item/twohanded/fireaxe/boneaxe) + wanted_types = list(/obj/item/fireaxe/boneaxe) /datum/bounty/item/mining/bone_armor name = "Bone Armor" diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm index a4632f7ed0..ffa608f8fd 100644 --- a/code/modules/cargo/bounties/science.dm +++ b/code/modules/cargo/bounties/science.dm @@ -119,7 +119,7 @@ /datum/bounty/item/science/noneactive_reactivearmor name = "Reactive Armor Shells" - description = "Do to the breakthroughs in anomalies, we can not keep up in making reactive armor shells, can you send us a few?" + description = "Due to the breakthroughs in anomalies, we can not keep up in making reactive armor shells, can you send us a few?" reward = 2000 required_count = 5 wanted_types = list(/obj/item/reactive_armour_shell, /obj/item/clothing/suit/armor/reactive) @@ -138,14 +138,14 @@ /datum/bounty/item/science/anomaly_neutralizer name = "Anomaly Neutralizers" - description = "An idea for a long time was to use an unstable Supermatter Shard to help create the breeding grounds for an unstable part of space to harvest any anomalies we want. It worked a little too well and now were out of anomaly neutralizers please send us a baker's dozen." + description = "An idea for a long time was to use an unstable Supermatter Shard to help create the breeding grounds for an unstable part of space to harvest any anomalies we want. It worked a little too well and now we're out of anomaly neutralizers, please send us a baker's dozen." reward = 2500 required_count = 13 wanted_types = list(/obj/item/anomaly_neutralizer) /datum/bounty/item/science/integrated_circuit_printer name = "Integrated Circuit Printer" - description = "due to a paperwork error, a newly made integrated circuit manufacturer line is missing three of its printers needed to operate. Until the paper work is corrected we are outsourcing this problem, so please send us three integrated circuit printers." + description = "Due to a paperwork error, a newly made integrated circuit manufacturer line is missing three of its printers needed to operate. Until the paper work is corrected we are outsourcing this problem, so please send us three integrated circuit printers." reward = 2000 required_count = 3 wanted_types = list(/obj/item/integrated_circuit_printer) @@ -159,7 +159,7 @@ /datum/bounty/item/science/nanite_trash name = "Nanite Based Gear" - description = "CC wants to make nanite based gear available to a new wing of devolvement but lacks the hand held tools to get it full up and running. Please send us any you have." + description = "CC wants to make nanite based gear available to a new wing of development but lacks the hand held tools to get it fully up and running. Please send us any you have." reward = 2500 required_count = 20 //Its just metal wanted_types = list( /obj/item/nanite_remote, /obj/item/nanite_remote/comm, /obj/item/nanite_scanner) diff --git a/code/modules/cargo/bounty_console.dm b/code/modules/cargo/bounty_console.dm index f499c38090..8a29715016 100644 --- a/code/modules/cargo/bounty_console.dm +++ b/code/modules/cargo/bounty_console.dm @@ -1,18 +1,18 @@ #define PRINTER_TIMEOUT 10 - - /obj/machinery/computer/bounty - name = "Nanotrasen bounty console" + name = "\improper Nanotrasen bounty console" desc = "Used to check and claim bounties offered by Nanotrasen" icon_screen = "bounty" circuit = /obj/item/circuitboard/computer/bounty light_color = "#E2853D"//orange var/printer_ready = 0 //cooldown var + var/static/datum/bank_account/cargocash /obj/machinery/computer/bounty/Initialize() . = ..() printer_ready = world.time + PRINTER_TIMEOUT + cargocash = SSeconomy.get_dep_account(ACCOUNT_CAR) /obj/machinery/computer/bounty/proc/print_paper() new /obj/item/paper/bounty_printout(loc) @@ -23,70 +23,43 @@ /obj/item/paper/bounty_printout/Initialize() . = ..() info = "

    Nanotrasen Cargo Bounties


    " + update_icon() + for(var/datum/bounty/B in GLOB.bounties_list) if(B.claimed) continue info += {"

    [B.name]

    -
    • Reward: [B.reward_string()]
    • -
    • Completed: [B.completion_string()]
    "} - -/obj/machinery/computer/bounty/ui_interact(mob/user) - . = ..() +
    • Reward: [B.reward_string()]
    • +
    • Completed: [B.completion_string()]
    "} +/obj/machinery/computer/bounty/ui_interact(mob/user, datum/tgui/ui) 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: [D.account_balance]

    - - "}) - for(var/datum/bounty/B in GLOB.bounties_list) - if(B.claimed) - dat += "" - else if(B.can_claim()) - dat += "" - else - dat += "" - if(B.high_priority) - dat += {" - - "} - else - dat += {" - - "} - dat += "" - if(B.claimed) - dat += "" - else if(B.can_claim()) - dat += "" - else - dat += "" - dat += "" - dat += "
    NameDescriptionRewardCompletionStatus
    [B.name]High Priority: [B.description][B.reward_string()][B.name][B.description][B.reward_string()][B.completion_string()]ClaimedClaimUnclaimed
    " - dat = dat.Join() - var/datum/browser/popup = new(user, "bounties", "Nanotrasen Bounties", 700, 600) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state)) - popup.open() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CargoBountyConsole", name) + ui.open() -/obj/machinery/computer/bounty/Topic(href, href_list) +/obj/machinery/computer/bounty/ui_data(mob/user) + var/list/data = list() + var/list/bountyinfo = list() + for(var/datum/bounty/B in GLOB.bounties_list) + bountyinfo += list(list("name" = B.name, "description" = B.description, "reward_string" = B.reward_string(), "completion_string" = B.completion_string() , "claimed" = B.claimed, "can_claim" = B.can_claim(), "priority" = B.high_priority, "bounty_ref" = REF(B))) + data["stored_cash"] = cargocash.account_balance + data["bountydata"] = bountyinfo + return data + +/obj/machinery/computer/bounty/ui_act(action,params) if(..()) return - - switch(href_list["choice"]) + switch(action) + if("ClaimBounty") + var/datum/bounty/cashmoney = locate(params["bounty"]) in GLOB.bounties_list + if(cashmoney) + cashmoney.claim() + return TRUE if("Print") if(printer_ready < world.time) printer_ready = world.time + PRINTER_TIMEOUT print_paper() - - if("Claim") - var/datum/bounty/B = locate(href_list["d_rec"]) - if(B in GLOB.bounties_list) - B.claim() - - if(href_list["refresh"]) - playsound(src, "terminal_type", 25, 0) - - updateUsrDialog() + return diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm index 3418f78dbd..b7eac1e591 100644 --- a/code/modules/cargo/centcom_podlauncher.dm +++ b/code/modules/cargo/centcom_podlauncher.dm @@ -11,7 +11,7 @@ /client/proc/centcom_podlauncher() //Creates a verb for admins to open up the ui set name = "Config/Launch Supplypod" - set desc = "Configure and launch a Centcom supplypod full of whatever your heart desires!" + set desc = "Configure and launch a CentCom supplypod full of whatever your heart desires!" set category = "Admin" var/datum/centcom_podlauncher/plaunch = new(usr)//create the datum plaunch.ui_interact(usr)//datum has a tgui component, here we open the window @@ -23,7 +23,10 @@ var/turf/oldTurf //Keeps track of where the user was at if they use the "teleport to centcom" button, so they can go back var/client/holder //client of whoever is using this datum var/area/bay //What bay we're using to launch shit from. + var/turf/dropoff_turf //If we're reversing, where the reverse pods go + var/picking_dropoff_turf var/launchClone = FALSE //If true, then we don't actually launch the thing in the bay. Instead we call duplicateObject() and send the result + var/launchRandomItem = FALSE //If true, lauches a single random item instead of everything on a turf. var/launchChoice = 1 //Determines if we launch all at once (0) , in order (1), or at random(2) var/explosionChoice = 0 //Determines if there is no explosion (0), custom explosion (1), or just do a maxcap (2) var/damageChoice = 0 //Determines if we do no damage (0), custom amnt of damage (1), or gib + 5000dmg (2) @@ -50,20 +53,25 @@ temp_pod = new(locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas) //Create a new temp_pod in the podStorage area on centcom (so users are free to look at it and change other variables if needed) orderedArea = createOrderedArea(bay) //Order all the turfs in the selected bay (top left to bottom right) to a single list. Used for the "ordered" mode (launchChoice = 1) -/datum/centcom_podlauncher/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, \ -force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state)//ui_interact is called when the client verb is called. +/datum/centcom_podlauncher/ui_state(mob/user) + return GLOB.admin_state - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/centcom_podlauncher/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "centcom_podlauncher", "Config/Launch Supplypod", 700, 700, master_ui, state) + ui = new(user, src, "CentcomPodLauncher") ui.open() /datum/centcom_podlauncher/ui_data(mob/user) //Sends info about the pod to the UI. var/list/data = list() //*****NOTE*****: Many of these comments are similarly described in supplypod.dm. If you change them here, please consider doing so in the supplypod code as well! - var/B = (istype(bay, /area/centcom/supplypod/loading/one)) ? 1 : (istype(bay, /area/centcom/supplypod/loading/two)) ? 2 : (istype(bay, /area/centcom/supplypod/loading/three)) ? 3 : (istype(bay, /area/centcom/supplypod/loading/four)) ? 4 : 0 //top ten THICCEST FUCKING TERNARY CONDITIONALS OF 2036 - data["bay"] = B //Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map. + var/B = (istype(bay, /area/centcom/supplypod/loading/one)) ? 1 : (istype(bay, /area/centcom/supplypod/loading/two)) ? 2 : (istype(bay, /area/centcom/supplypod/loading/three)) ? 3 : (istype(bay, /area/centcom/supplypod/loading/four)) ? 4 : 0 //(istype(bay, /area/centcom/supplypod/loading/ert)) ? 5 : 0 //top ten THICCEST FUCKING TERNARY CONDITIONALS OF 2036 + data["bay"] = bay //Holds the current bay the user is launching objects from. Bays are specific rooms on the centcom map. + data["bayNumber"] = B //Holds the bay as a number. Useful for comparisons in centcom_podlauncher.ract data["oldArea"] = (oldTurf ? get_area(oldTurf) : null) //Holds the name of the area that the user was in before using the teleportCentcom action + data["picking_dropoff_turf"] = picking_dropoff_turf //If we're picking or have picked a dropoff turf. Only works when pod is in reverse mode + data["dropoff_turf"] = dropoff_turf //The turf that reverse pods will drop their newly acquired cargo off at data["launchClone"] = launchClone //Do we launch the actual items in the bay or just launch clones of them? + data["launchRandomItem"] = launchRandomItem //Do we launch a single random item instead of everything on the turf? data["launchChoice"] = launchChoice //Launch turfs all at once (0), ordered (1), or randomly(1) data["explosionChoice"] = explosionChoice //An explosion that occurs when landing. Can be no explosion (0), custom explosion (1), or maxcap (2) data["damageChoice"] = damageChoice //Damage that occurs to any mob under the pod when it lands. Can be no damage (0), custom damage (1), or gib+5000dmg (2) @@ -72,11 +80,12 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm data["openingDelay"] = temp_pod.openingDelay //How long the pod takes to open after landing data["departureDelay"] = temp_pod.departureDelay //How long the pod takes to leave after opening (if bluespace=true, it deletes. if reversing=true, it flies back to centcom) data["styleChoice"] = temp_pod.style //Style is a variable that keeps track of what the pod is supposed to look like. It acts as an index to the POD_STYLES list in cargo.dm defines to get the proper icon/name/desc for the pod. + data["effectShrapnel"] = FALSE //temp_pod.effectShrapnel //If true, creates a cloud of shrapnel of a decided type and magnitude on landing data["effectStun"] = temp_pod.effectStun //If true, stuns anyone under the pod when it launches until it lands, forcing them to get hit by the pod. Devilish! data["effectLimb"] = temp_pod.effectLimb //If true, pops off a limb (if applicable) from anyone caught under the pod when it lands data["effectOrgans"] = temp_pod.effectOrgans //If true, yeets the organs out of any bodies caught under the pod when it lands data["effectBluespace"] = temp_pod.bluespace //If true, the pod deletes (in a shower of sparks) after landing - data["effectStealth"] = temp_pod.effectStealth //If true, a target icon isnt displayed on the turf where the pod will land + data["effectStealth"] = temp_pod.effectStealth //If true, a target icon isn't displayed on the turf where the pod will land data["effectQuiet"] = temp_pod.effectQuiet //The female sniper. If true, the pod makes no noise (including related explosions, opening sounds, etc) data["effectMissile"] = temp_pod.effectMissile //If true, the pod deletes the second it lands. If you give it an explosion, it will act like a missile exploding as it hits the ground data["effectCircle"] = temp_pod.effectCircle //If true, allows the pod to come in at any angle. Bit of a weird feature but whatever its here @@ -115,20 +124,41 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm bay = locate(/area/centcom/supplypod/loading/four) in GLOB.sortedAreas refreshBay() . = TRUE + if("bay5") + to_chat(usr, "LetterN is lazy and didin't bother porting this new cc area!") + return + // bay = locate(/area/centcom/supplypod/loading/ert) in GLOB.sortedAreas + // refreshBay() + // . = TRUE + if("pickDropoffTurf") //Enters a mode that lets you pick the dropoff location for reverse pods + if (picking_dropoff_turf) + picking_dropoff_turf = FALSE + updateCursor(FALSE, FALSE) //Update the cursor of the user to a cool looking target icon + return + if (launcherActivated) + launcherActivated = FALSE //We don't want to have launch mode enabled while we're picking a turf + picking_dropoff_turf = TRUE + updateCursor(FALSE, TRUE) //Update the cursor of the user to a cool looking target icon + . = TRUE + if("clearDropoffTurf") + picking_dropoff_turf = FALSE + dropoff_turf = null + updateCursor(FALSE, FALSE) + . = TRUE if("teleportCentcom") //Teleports the user to the centcom supply loading facility. var/mob/M = holder.mob //We teleport whatever mob the client is attached to at the point of clicking oldTurf = get_turf(M) //Used for the "teleportBack" action - var/area/A = locate(/area/centcom/supplypod/loading) in GLOB.sortedAreas + var/area/A = locate(bay) in GLOB.sortedAreas var/list/turfs = list() for(var/turf/T in A) turfs.Add(T) //Fill a list with turfs in the area - var/turf/T = safepick(turfs) //Only teleport if the list isn't empty - if(!T) //If the list is empty, error and cancel + if (!length(turfs)) //If the list is empty, error and cancel to_chat(M, "Nowhere to jump to!") - return + return //Only teleport if the list isn't empty + var/turf/T = pick(turfs) M.forceMove(T) //Perform the actual teleport - log_admin("[key_name(usr)] jumped to [AREACOORD(A)]") - message_admins("[key_name_admin(usr)] jumped to [AREACOORD(A)]") + log_admin("[key_name(usr)] jumped to [AREACOORD(T)]") + message_admins("[key_name_admin(usr)] jumped to [AREACOORD(T)]") . = TRUE if("teleportBack") //After teleporting to centcom, this button allows the user to teleport to the last spot they were at. var/mob/M = holder.mob @@ -144,6 +174,9 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if("launchClone") //Toggles the launchClone var. See variable declarations above for what this specifically means launchClone = !launchClone . = TRUE + if("launchRandomItem") //Pick random turfs from the supplypod bay at centcom to launch + launchRandomItem = !launchRandomItem + . = TRUE if("launchOrdered") //Launch turfs (from the orderedArea list) one at a time in order, from the supplypod bay at centcom if (launchChoice == 1) //launchChoice 1 represents ordered. If we push "ordered" and it already is, then we go to default value launchChoice = 0 @@ -152,7 +185,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm launchChoice = 1 updateSelector() . = TRUE - if("launchRandom") //Pick random turfs from the supplypod bay at centcom to launch + if("launchRandomTurf") //Pick random turfs from the supplypod bay at centcom to launch if (launchChoice == 2) launchChoice = 0 updateSelector() @@ -170,11 +203,11 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm var/list/expNames = list("Devastation", "Heavy Damage", "Light Damage", "Flame") //Explosions have a range of different types of damage var/list/boomInput = list() for (var/i=1 to expNames.len) //Gather input from the user for the value of each type of damage - boomInput.Add(input("[expNames[i]] Range", "Enter the [expNames[i]] range of the explosion. WARNING: This ignores the bomb cap!", 0) as null|num) + boomInput.Add(input("Enter the [expNames[i]] range of the explosion. WARNING: This ignores the bomb cap!", "[expNames[i]] Range", 0) as null|num) if (isnull(boomInput[i])) return if (!isnum(boomInput[i])) //If the user doesn't input a number, set that specific explosion value to zero - alert(usr, "That wasnt a number! Value set to default (zero) instead.") + alert(usr, "That wasn't a number! Value set to default (zero) instead.") boomInput = 0 explosionChoice = 1 temp_pod.explosionSize = boomInput @@ -192,11 +225,11 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm damageChoice = 0 temp_pod.damage = 0 return - var/damageInput = input("How much damage to deal", "Enter the amount of brute damage dealt by getting hit", 0) as null|num + var/damageInput = input("Enter the amount of brute damage dealt by getting hit","How much damage to deal", 0) as null|num if (isnull(damageInput)) return if (!isnum(damageInput)) //Sanitize the input for damage to deal.s - alert(usr, "That wasnt a number! Value set to default (zero) instead.") + alert(usr, "That wasn't a number! Value set to default (zero) instead.") damageInput = 0 damageChoice = 1 temp_pod.damage = damageInput @@ -226,13 +259,32 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm temp_pod.desc = descInput temp_pod.adminNamed = TRUE //This variable is checked in the supplypod/setStyle() proc . = TRUE + /* + if("effectShrapnel") //Creates a cloud of shrapnel on landing + if (temp_pod.effectShrapnel == TRUE) //If already doing custom damage, set back to default (no shrapnel) + temp_pod.effectShrapnel = FALSE + return + var/shrapnelInput = input("Please enter the type of pellet cloud you'd like to create on landing (Can be any projectile!)", "Projectile Typepath", 0) in sortList(subtypesof(/obj/item/projectile), /proc/cmp_typepaths_asc) + if (isnull(shrapnelInput)) + return + var/shrapnelMagnitude = input("Enter the magnitude of the pellet cloud. This is usually a value around 1-5. Please note that Ryll-Ryll has asked me to tell you that if you go too crazy with the projectiles you might crash the server. So uh, be gentle!", "Shrapnel Magnitude", 0) as null|num + if (isnull(shrapnelMagnitude)) + return + if (!isnum(shrapnelMagnitude)) + alert(usr, "That wasn't a number! Value set to 3 instead.") + shrapnelMagnitude = 3 + temp_pod.shrapnel_type = shrapnelInput + temp_pod.shrapnel_magnitude = shrapnelMagnitude + temp_pod.effectShrapnel = TRUE + . = TRUE + */ if("effectStun") //Toggle: Any mob under the pod is stunned (cant move) until the pod lands, hitting them! temp_pod.effectStun = !temp_pod.effectStun . = TRUE if("effectLimb") //Toggle: Anyone carbon mob under the pod loses a limb when it lands temp_pod.effectLimb = !temp_pod.effectLimb . = TRUE - if("effectOrgans") //Toggle: Any carbon mob under the pod loses every limb and organ + if("effectOrgans") //Toggle: Anyone carbon mob under the pod loses a limb when it lands temp_pod.effectOrgans = !temp_pod.effectOrgans . = TRUE if("effectBluespace") //Toggle: Deletes the pod after landing @@ -253,7 +305,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if("effectBurst") //Toggle: Launch 5 pods (with a very slight delay between) in a 3x3 area centered around the target effectBurst = !effectBurst . = TRUE - if("effectAnnounce") //Toggle: Sends a ghost announcement. + if("effectAnnounce") //Toggle: Launch 5 pods (with a very slight delay between) in a 3x3 area centered around the target effectAnnounce = !effectAnnounce . = TRUE if("effectReverse") //Toggle: Don't send any items. Instead, after landing, close (taking any objects inside) and go back to the centcom bay it came from @@ -272,15 +324,15 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm . = TRUE ////////////////////////////TIMER DELAYS////////////////// - if("fallDuration") //Change the falling animation duration - if (temp_pod.fallDuration != initial(temp_pod.fallDuration)) //If the fall duration has already been changed when we push the "change value" button, then set it to default + if("fallDuration") //Change the time it takes the pod to land, after firing + if (temp_pod.fallDuration != initial(temp_pod.fallDuration)) //If the landing delay has already been changed when we push the "change value" button, then set it to default temp_pod.fallDuration = initial(temp_pod.fallDuration) return - var/timeInput = input("Enter the duration of the pod's falling animation, in seconds", "Delay Time", initial(temp_pod.fallDuration) * 0.1) as null|num + var/timeInput = input("Enter the duration of the pod's falling animation, in seconds", "Delay Time", initial(temp_pod.fallDuration) * 0.1) as null|num if (isnull(timeInput)) return if (!isnum(timeInput)) //Sanitize input, if it doesnt check out, error and set to default - alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.fallDuration)*0.1]) instead.") + alert(usr, "That wasn't a number! Value set to default ([initial(temp_pod.fallDuration)*0.1]) instead.") timeInput = initial(temp_pod.fallDuration) temp_pod.fallDuration = 10 * timeInput . = TRUE @@ -292,7 +344,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (isnull(timeInput)) return if (!isnum(timeInput)) //Sanitize input, if it doesnt check out, error and set to default - alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.landingDelay)*0.1]) instead.") + alert(usr, "That wasn't a number! Value set to default ([initial(temp_pod.landingDelay)*0.1]) instead.") timeInput = initial(temp_pod.landingDelay) temp_pod.landingDelay = 10 * timeInput . = TRUE @@ -304,7 +356,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (isnull(timeInput)) return if (!isnum(timeInput)) //Sanitize input - alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.openingDelay)*0.1]) instead.") + alert(usr, "That wasn't a number! Value set to default ([initial(temp_pod.openingDelay)*0.1]) instead.") timeInput = initial(temp_pod.openingDelay) temp_pod.openingDelay = 10 * timeInput . = TRUE @@ -316,13 +368,13 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (isnull(timeInput)) return if (!isnum(timeInput)) - alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.departureDelay)*0.1]) instead.") + alert(usr, "That wasn't a number! Value set to default ([initial(temp_pod.departureDelay)*0.1]) instead.") timeInput = initial(temp_pod.departureDelay) temp_pod.departureDelay = 10 * timeInput . = TRUE ////////////////////////////ADMIN SOUNDS////////////////// - if("fallingSound") //Admin sound from a local file that plays when the pod falls + if("fallSound") //Admin sound from a local file that plays when the pod lands if ((temp_pod.fallingSound) != initial(temp_pod.fallingSound)) temp_pod.fallingSound = initial(temp_pod.fallingSound) temp_pod.fallingSoundLength = initial(temp_pod.fallingSoundLength) @@ -334,7 +386,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (isnull(timeInput)) return if (!isnum(timeInput)) - alert(usr, "That wasnt a number! Value set to default ([initial(temp_pod.fallingSoundLength)*0.1]) instead.") + alert(usr, "That wasn't a number! Value set to default ([initial(temp_pod.fallingSoundLength)*0.1]) instead.") temp_pod.fallingSound = soundInput temp_pod.fallingSoundLength = 10 * timeInput . = TRUE @@ -369,7 +421,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (temp_pod.soundVolume != initial(temp_pod.soundVolume)) temp_pod.soundVolume = initial(temp_pod.soundVolume) return - var/soundInput = input(holder, "Please pick a volume. Default is between 1 and 100 with 80 being average, but pick whatever. I'm a notification, not a cop. If you still cant hear your sound, consider turning on the Quiet effect. It will silence all pod sounds except for the custom admin ones set by the previous three buttons.", "Pick Admin Sound Volume") as null|num + var/soundInput = input(holder, "Please pick a volume. Default is between 1 and 100 with 50 being average, but pick whatever. I'm a notification, not a cop. If you still cant hear your sound, consider turning on the Quiet effect. It will silence all pod sounds except for the custom admin ones set by the previous three buttons.", "Pick Admin Sound Volume") as null|num if (isnull(soundInput)) return temp_pod.soundVolume = soundInput @@ -421,26 +473,36 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm . = TRUE if("giveLauncher") //Enters the "Launch Mode". When the launcher is activated, temp_pod is cloned, and the result it filled and launched anywhere the user clicks (unless specificTarget is true) launcherActivated = !launcherActivated - updateCursor(launcherActivated) //Update the cursor of the user to a cool looking target icon + updateCursor(launcherActivated, FALSE) //Update the cursor of the user to a cool looking target icon + . = TRUE + if("clearBay") //Delete all mobs and objs in the selected bay + if(alert(usr, "This will delete all objs and mobs in [bay]. Are you sure?", "Confirmation", "Delete that shit", "No") == "Delete that shit") + clearBay() + refreshBay() . = TRUE /datum/centcom_podlauncher/ui_close() //Uses the destroy() proc. When the user closes the UI, we clean up the temp_pod and supplypod_selector variables. qdel(src) -/datum/centcom_podlauncher/proc/updateCursor(var/launching) //Update the moues of the user - if (holder) //Check to see if we have a client - if (launching) //If the launching param is true, we give the user new mouse icons. - holder.mouse_up_icon = 'icons/effects/supplypod_target.dmi' //Icon for when mouse is released - holder.mouse_down_icon = 'icons/effects/supplypod_down_target.dmi' //Icon for when mouse is pressed - holder.mouse_pointer_icon = holder.mouse_up_icon //Icon for idle mouse (same as icon for when released) - holder.click_intercept = src //Create a click_intercept so we know where the user is clicking - else - var/mob/M = holder.mob - holder.mouse_up_icon = null - holder.mouse_down_icon = null - holder.click_intercept = null - if (M) - M.update_mouse_pointer() //set the moues icons to null, then call update_moues_pointer() which resets them to the correct values based on what the mob is doing (in a mech, holding a spell, etc)() +/datum/centcom_podlauncher/proc/updateCursor(var/launching, var/turf_picking) //Update the mouse of the user + if (!holder) //Can't update the mouse icon if the client doesnt exist! + return + if (launching || turf_picking) //If the launching param is true, we give the user new mouse icons. + if(launching) + holder.mouse_up_icon = 'icons/effects/mouse_pointers/supplypod_target.dmi' //Icon for when mouse is released + holder.mouse_down_icon = 'icons/effects/mouse_pointers/supplypod_down_target.dmi' //Icon for when mouse is pressed + if(turf_picking) + holder.mouse_up_icon = 'icons/effects/mouse_pointers/supplypod_pickturf.dmi' //Icon for when mouse is released + holder.mouse_down_icon = 'icons/effects/mouse_pointers/supplypod_pickturf_down.dmi' //Icon for when mouse is pressed + holder.mouse_pointer_icon = holder.mouse_up_icon //Icon for idle mouse (same as icon for when released) + holder.click_intercept = src //Create a click_intercept so we know where the user is clicking + else + var/mob/M = holder.mob + holder.mouse_up_icon = null + holder.mouse_down_icon = null + holder.click_intercept = null + if (M) + M.update_mouse_pointer() //set the moues icons to null, then call update_moues_pointer() which resets them to the correct values based on what the mob is doing (in a mech, holding a spell, etc)() /datum/centcom_podlauncher/proc/InterceptClickOn(user,params,atom/target) //Click Intercept so we know where to send pods where the user clicks var/list/pa = params2list(params) @@ -461,7 +523,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm else return //if target is null and we don't have a specific target, cancel if (effectAnnounce) - deadchat_broadcast("A special package is being launched at the station!", turf_target = target) + deadchat_broadcast("A special package is being launched at the station!", turf_target = target) //, message_type=DEADCHAT_ANNOUNCEMENT) var/list/bouttaDie = list() for (var/mob/living/M in target) bouttaDie.Add(M) @@ -479,6 +541,15 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm else launch(target) //If we couldn't locate an adjacent turf, just launch at the normal target sleep(rand()*2) //looks cooler than them all appearing at once. Gives the impression of burst fire. + else if (picking_dropoff_turf) + //Clicking on UI elements shouldn't pick a dropoff turf + if(istype(target,/obj/screen)) + return FALSE + + . = TRUE + if(left_click) //When we left click: + dropoff_turf = get_turf(target) + to_chat(user, " You've selected [dropoff_turf] at [COORD(dropoff_turf)] as your dropoff location.") /datum/centcom_podlauncher/proc/refreshBay() //Called whenever the bay is switched, as well as wheneber a pod is launched orderedArea = createOrderedArea(bay) //Create an ordered list full of turfs form the bay @@ -489,7 +560,7 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm to_chat(holder.mob, "No /area/centcom/supplypod/loading/one (or /two or /three or /four) in the world! You can make one yourself (then refresh) for now, but yell at a mapper to fix this, today!") CRASH("No /area/centcom/supplypod/loading/one (or /two or /three or /four) has been mapped into the centcom z-level!") orderedArea = list() - if (!isemptylist(A.contents)) //Go through the area passed into the proc, and figure out the top left and bottom right corners by calculating max and min values + if (length(A.contents)) //Go through the area passed into the proc, and figure out the top left and bottom right corners by calculating max and min values var/startX = A.contents[1].x //Create the four values (we do it off a.contents[1] so they have some sort of arbitrary initial value. They should be overwritten in a few moments) var/endX = A.contents[1].x var/startY = A.contents[1].y @@ -512,12 +583,12 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm numTurfs = 0 //Counts the number of turfs that can be launched (remember, supplypods either launch all at once or one turf-worth of items at a time) acceptableTurfs = list() for (var/turf/T in orderedArea) //Go through the orderedArea list - if (typecache_filter_list_reverse(T.contents, ignored_atoms).len != 0) //if there is something in this turf that isnt in the blacklist, we consider this turf "acceptable" and add it to the acceptableTurfs list + if (typecache_filter_list_reverse(T.contents, ignored_atoms).len != 0) //if there is something in this turf that isn't in the blacklist, we consider this turf "acceptable" and add it to the acceptableTurfs list acceptableTurfs.Add(T) //Because orderedArea was an ordered linear list, acceptableTurfs will be as well. numTurfs ++ launchList = list() //Anything in launchList will go into the supplypod when it is launched - if (!isemptylist(acceptableTurfs) && !temp_pod.reversing && !temp_pod.effectMissile) //We dont fill the supplypod if acceptableTurfs is empty, if the pod is going in reverse (effectReverse=true), or if the pod is acitng like a missile (effectMissile=true) + if (length(acceptableTurfs) && !temp_pod.reversing && !temp_pod.effectMissile) //We dont fill the supplypod if acceptableTurfs is empty, if the pod is going in reverse (effectReverse=true), or if the pod is acitng like a missile (effectMissile=true) switch(launchChoice) if(0) //If we are launching all the turfs at once for (var/turf/T in acceptableTurfs) @@ -536,22 +607,36 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm if (isnull(A)) return var/obj/structure/closet/supplypod/centcompod/toLaunch = DuplicateObject(temp_pod) //Duplicate the temp_pod (which we have been varediting or configuring with the UI) and store the result - toLaunch.bay = bay //Bay is currently a nonstatic expression, so it cant go into toLaunch using DuplicateObject - toLaunch.update_icon()//we update_icon() here so that the door doesnt "flicker on" right after it lands - if (launchClone) //We arent launching the actual items from the bay, rather we are creating clones and launching those - for (var/atom/movable/O in launchList) - DuplicateObject(O).forceMove(toLaunch) //Duplicate each atom/movable in launchList and forceMove them into the supplypod - new /obj/effect/abstract/DPtarget(A, toLaunch) //Create the DPTarget, which will eventually forceMove the temp_pod to it's location + /* + if(dropoff_turf) + toLaunch.reverse_dropoff_turf = dropoff_turf else - for (var/atom/movable/O in launchList) //If we aren't cloning the objects, just go through the launchList + toLaunch.reverse_dropoff_turf = bay //Bay is currently a nonstatic expression, so it cant go into toLaunch using DuplicateObject + */ + toLaunch.update_icon()//we update_icon() here so that the door doesnt "flicker on" right after it lands + // var/shippingLane = GLOB.areas_by_type[/area/centcom/supplypod/fly_me_to_the_moon] + // toLaunch.forceMove(shippingLane) The shipping lane is temporarily closed due to ratvarian blockades + if (launchClone) //We arent launching the actual items from the bay, rather we are creating clones and launching those + if(launchRandomItem) + var/atom/movable/O = pick_n_take(launchList) + DuplicateObject(O).forceMove(toLaunch) //Duplicate a single atom/movable from launchList and forceMove it into the supplypod + else + for (var/atom/movable/O in launchList) + DuplicateObject(O).forceMove(toLaunch) //Duplicate each atom/movable in launchList and forceMove them into the supplypod + else + if(launchRandomItem) + var/atom/movable/O = pick_n_take(launchList) O.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod - new /obj/effect/abstract/DPtarget(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location + else + for (var/atom/movable/O in launchList) //If we aren't cloning the objects, just go through the launchList + O.forceMove(toLaunch) //and forceMove any atom/moveable into the supplypod + new /obj/effect/abstract/DPtarget(A, toLaunch) //Then, create the DPTarget effect, which will eventually forceMove the temp_pod to it's location if (launchClone) launchCounter++ //We only need to increment launchCounter if we are cloning objects. //If we aren't cloning objects, taking and removing the first item each time from the acceptableTurfs list will inherently iterate through the list in order /datum/centcom_podlauncher/proc/updateSelector() //Ensures that the selector effect will showcase the next item if needed - if (launchChoice == 1 && !isemptylist(acceptableTurfs) && !temp_pod.reversing && !temp_pod.effectMissile) //We only show the selector if we are taking items from the bay + if (launchChoice == 1 && length(acceptableTurfs) && !temp_pod.reversing && !temp_pod.effectMissile) //We only show the selector if we are taking items from the bay var/index = launchCounter + 1 //launchCounter acts as an index to the ordered acceptableTurfs list, so adding one will show the next item in the list if (index > acceptableTurfs.len) //out of bounds check index = 1 @@ -559,8 +644,14 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm else selector.moveToNullspace() //Otherwise, we move the selector to nullspace until it is needed again +/datum/centcom_podlauncher/proc/clearBay() //Clear all objs and mobs from the selected bay + for (var/obj/O in bay.GetAllContents()) + qdel(O) + for (var/mob/M in bay.GetAllContents()) + qdel(M) + /datum/centcom_podlauncher/Destroy() //The Destroy() proc. This is called by ui_close proc, or whenever the user leaves the game - updateCursor(FALSE) //Make sure our moues cursor resets to default. False means we are not in launch mode + updateCursor(FALSE, FALSE) //Make sure our moues cursor resets to default. False means we are not in launch mode qdel(temp_pod) //Delete the temp_pod qdel(selector) //Delete the selector effect . = ..() @@ -581,8 +672,8 @@ force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.adm for (var/X in temp_pod.explosionSize) explosionString += "[X]|" - var/msg = "launched [podString][whomString].[delayString][damageString][explosionString]]" - message_admins("[key_name_admin(usr)] [msg] in [AREACOORD(specificTarget)].") - if (!isemptylist(whoDyin)) + var/msg = "launched [podString] towards [whomString] [delayString][damageString][explosionString]" + message_admins("[key_name_admin(usr)] [msg] in [ADMIN_VERBOSEJMP(specificTarget)].") + if (length(whoDyin)) for (var/mob/living/M in whoDyin) admin_ticket_log(M, "[key_name_admin(usr)] [msg]") diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm index 6968a5ccd8..f5a8d21278 100644 --- a/code/modules/cargo/console.dm +++ b/code/modules/cargo/console.dm @@ -3,9 +3,6 @@ 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 var/requestonly = FALSE var/contraband = FALSE @@ -18,6 +15,7 @@ var/obj/item/radio/headset/radio /// var that tracks message cooldown var/message_cooldown + var/list/loaded_coupons light_color = "#E2853D"//orange @@ -26,7 +24,6 @@ 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() @@ -65,15 +62,12 @@ 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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/cargo/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "cargo", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "Cargo", name) ui.open() /obj/machinery/computer/cargo/ui_data() @@ -119,7 +113,6 @@ 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]) @@ -134,6 +127,8 @@ "cost" = P.cost, "id" = pack, "desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name. + "goody" = P.goody, + "private_goody" = P.goody == PACK_GOODY_PRIVATE, "access" = P.access, "can_private_buy" = P.can_private_buy )) @@ -142,9 +137,6 @@ /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()) @@ -176,6 +168,8 @@ else SSshuttle.shuttle_loan.loan_shuttle() say("The supply shuttle has been loaned to CentCom.") + investigate_log("[key_name(usr)] accepted a shuttle loan event.", INVESTIGATE_CARGO) + log_game("[key_name(usr)] accepted a shuttle loan event.") . = TRUE if("add") var/id = text2path(params["id"]) @@ -197,13 +191,15 @@ 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(self_paid && ishuman(usr)) + var/mob/living/carbon/human/H = usr + var/obj/item/card/id/id_card = H.get_idcard(TRUE) if(!istype(id_card)) say("No ID card detected.") return + if(istype(id_card, /obj/item/card/id/departmental_budget)) + say("The [src] rejects [id_card].") + return account = id_card.registered_account if(!istype(account)) say("Invalid bank account.") @@ -215,8 +211,22 @@ if(isnull(reason) || ..()) return + if(pack.goody == PACK_GOODY_PRIVATE && !self_paid) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE) + say("ERROR: Private small crates may only be purchased by private accounts.") + return + + var/obj/item/coupon/applied_coupon + for(var/i in loaded_coupons) + var/obj/item/coupon/coupon_check = i + if(pack.type == coupon_check.discounted_pack) + say("Coupon found! [round(coupon_check.discount_pct_off * 100)]% off applied!") + coupon_check.moveToNullspace() + applied_coupon = coupon_check + break + var/turf/T = get_turf(src) - var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account) + var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account, applied_coupon) SO.generateRequisition(T) if(requestonly && !self_paid) SSshuttle.requestlist += SO @@ -224,11 +234,17 @@ SSshuttle.shoppinglist += SO if(self_paid) say("Order processed. The price will be charged to [account.account_holder]'s bank account on delivery.") + if(requestonly && message_cooldown < world.time) + radio.talk_into(src, "A new order has been requested.", RADIO_CHANNEL_SUPPLY) + message_cooldown = world.time + 30 SECONDS . = TRUE if("remove") var/id = text2num(params["id"]) for(var/datum/supply_order/SO in SSshuttle.shoppinglist) if(SO.id == id) + if(SO.applied_coupon) + say("Coupon refunded.") + SO.applied_coupon.forceMove(get_turf(src)) SSshuttle.shoppinglist -= SO . = TRUE break diff --git a/code/modules/cargo/coupon.dm b/code/modules/cargo/coupon.dm new file mode 100644 index 0000000000..1c1f2a36e1 --- /dev/null +++ b/code/modules/cargo/coupon.dm @@ -0,0 +1,52 @@ + +#define COUPON_OMEN "omen" + +/obj/item/coupon + name = "coupon" + desc = "It doesn't matter if you didn't want it before, what matters now is that you've got a coupon for it!" + icon_state = "data_1" + icon = 'icons/obj/card.dmi' + item_flags = NOBLUDGEON + w_class = WEIGHT_CLASS_TINY + attack_speed = CLICK_CD_RAPID + var/datum/supply_pack/discounted_pack + var/discount_pct_off = 0.05 + var/obj/machinery/computer/cargo/inserted_console + +/// Choose what our prize is :D +/obj/item/coupon/proc/generate() + discounted_pack = pick(subtypesof(/datum/supply_pack/goody)) + var/list/chances = list("0.10" = 4, "0.15" = 8, "0.20" = 10, "0.25" = 8, "0.50" = 4, COUPON_OMEN = 1) + discount_pct_off = pickweight(chances) + if(discount_pct_off == COUPON_OMEN) + name = "coupon - fuck you" + desc = "The small text reads, 'You will be slaughtered'... That doesn't sound right, does it?" + if(ismob(loc)) + var/mob/M = loc + to_chat(M, "The coupon reads 'fuck you' in large, bold text... is- is that a prize, or?") + M.AddComponent(/datum/component/omen, TRUE, src) + else + discount_pct_off = text2num(discount_pct_off) + name = "coupon - [round(discount_pct_off * 100)]% off [initial(discounted_pack.name)]" + +/obj/item/coupon/attack_obj(obj/O, mob/living/user) + if(!istype(O, /obj/machinery/computer/cargo)) + return ..() + if(discount_pct_off == COUPON_OMEN) + to_chat(user, "\The [O] validates the coupon as authentic, but refuses to accept it...") + O.say("Coupon fulfillment already in progress...") + user.DelayNextAction() + return + + inserted_console = O + LAZYADD(inserted_console.loaded_coupons, src) + inserted_console.say("Coupon for [initial(discounted_pack.name)] applied!") + forceMove(inserted_console) + +/obj/item/coupon/Destroy() + if(inserted_console) + LAZYREMOVE(inserted_console.loaded_coupons, src) + inserted_console = null + . = ..() + +#undef COUPON_OMEN diff --git a/code/modules/cargo/exports/gear.dm b/code/modules/cargo/exports/gear.dm index 646e1c6e47..678948128f 100644 --- a/code/modules/cargo/exports/gear.dm +++ b/code/modules/cargo/exports/gear.dm @@ -310,7 +310,7 @@ /datum/export/gear/combatgloves cost = 80 unit_name = "combat gloves" - export_types = list(/obj/item/clothing/gloves/tackler/combat, /obj/item/clothing/gloves/tackler/dolphin, /obj/item/clothing/gloves/fingerless/pugilist/rapid, /obj/item/clothing/gloves/krav_maga) + export_types = list(/obj/item/clothing/gloves/tackler/combat, /obj/item/clothing/gloves/tackler/dolphin, /obj/item/clothing/gloves/krav_maga) include_subtypes = TRUE /datum/export/gear/bonegloves diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm index 2b93a25a61..2943130a19 100644 --- a/code/modules/cargo/exports/large_objects.dm +++ b/code/modules/cargo/exports/large_objects.dm @@ -169,15 +169,13 @@ /datum/export/large/gas_canister/get_cost(obj/O) var/obj/machinery/portable_atmospherics/canister/C = O var/worth = 10 - var/gases = C.air_contents.gases - - worth += gases[/datum/gas/bz]*3 - worth += gases[/datum/gas/stimulum]*25 - worth += gases[/datum/gas/hypernoblium]*1000 - worth += gases[/datum/gas/miasma]*2 - worth += gases[/datum/gas/tritium]*7 - worth += gases[/datum/gas/pluoxium]*6 - worth += gases[/datum/gas/nitryl]*30 + worth += C.air_contents.get_moles(/datum/gas/bz)*3 + worth += C.air_contents.get_moles(/datum/gas/stimulum)*25 + worth += C.air_contents.get_moles(/datum/gas/hypernoblium)*1000 + worth += C.air_contents.get_moles(/datum/gas/miasma)*2 + worth += C.air_contents.get_moles(/datum/gas/tritium)*7 + worth += C.air_contents.get_moles(/datum/gas/pluoxium)*6 + worth += C.air_contents.get_moles(/datum/gas/nitryl)*30 return worth @@ -303,7 +301,7 @@ export_types = list(/obj/mecha/combat/durand) /datum/export/large/mech/phazon - cost = 35000 //Little over half do to needing a core + cost = 35000 //Little over half due to needing a core unit_name = "working phazon" export_types = list(/obj/mecha/combat/phazon) diff --git a/code/modules/cargo/exports/organs_robotics.dm b/code/modules/cargo/exports/organs_robotics.dm index a6c5ee93ca..b65cf28949 100644 --- a/code/modules/cargo/exports/organs_robotics.dm +++ b/code/modules/cargo/exports/organs_robotics.dm @@ -2,11 +2,11 @@ /datum/export/robotics include_subtypes = FALSE - k_elasticity = 1/50 + k_elasticity = 1/200 /datum/export/implant include_subtypes = FALSE - k_elasticity = 1/50 + k_elasticity = 1/200 /datum/export/organs include_subtypes = TRUE @@ -34,8 +34,8 @@ export_types = list(/obj/item/organ/cyberimp/brain/anti_stun) /datum/export/implant/breathtube - cost = 150 - k_elasticity = 300/20 //Large before depleating + cost = 175 + k_elasticity = 1/350 //Large before depleating unit_name = "breath implant" export_types = list(/obj/item/organ/cyberimp/mouth/breathing_tube) @@ -71,35 +71,35 @@ export_types = list(/obj/item/organ/cyberimp/arm/gun/laser, /obj/item/organ/cyberimp/arm/gun/taser, /obj/item/organ/cyberimp/arm/esword, /obj/item/organ/cyberimp/arm/medibeam, /obj/item/organ/cyberimp/arm/combat, /obj/item/organ/cyberimp/arm/flash, /obj/item/organ/cyberimp/arm/baton) include_subtypes = TRUE -/datum/export/orgains/heart +/datum/export/organs/heart cost = 250 unit_name = "heart" export_types = list(/obj/item/organ/heart) exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic) -/datum/export/orgains/tongue +/datum/export/organs/tongue cost = 75 unit_name = "tongue" export_types = list(/obj/item/organ/tongue) -/datum/export/orgains/eyes +/datum/export/organs/eyes cost = 50 //So many things take your eyes out anyways unit_name = "eyes" export_types = list(/obj/item/organ/eyes) exclude_types = list(/obj/item/organ/eyes/robotic) -/datum/export/orgains/stomach +/datum/export/organs/stomach cost = 50 //can be replaced unit_name = "stomach" export_types = list(/obj/item/organ/stomach) -/datum/export/orgains/lungs +/datum/export/organs/lungs cost = 150 unit_name = "lungs" export_types = list(/obj/item/organ/lungs) exclude_types = list(/obj/item/organ/lungs/cybernetic, /obj/item/organ/lungs/cybernetic/upgraded) -/datum/export/orgains/liver +/datum/export/organs/liver cost = 175 unit_name = "liver" export_types = list(/obj/item/organ/liver) @@ -116,35 +116,35 @@ unit_name = "upgraded cybernetic organ" export_types = list(/obj/item/organ/lungs/cybernetic/upgraded, /obj/item/organ/liver/cybernetic/upgraded) -/datum/export/organs/tail //Shhh +/datum/export/organs/tail // yeah have fun pulling this off someone without catching a bwoink cost = 500 - unit_name = "error shipment failer" + unit_name = "organic tail" export_types = list(/obj/item/organ/tail) -/datum/export/orgains/vocal_cords +/datum/export/organs/vocal_cords cost = 500 unit_name = "vocal cords" export_types = list(/obj/item/organ/vocal_cords) //These are gotten via different races -/datum/export/robotics/lims - cost = 30 - unit_name = "robotic lim replacement" +/datum/export/robotics/limbs + cost = 60 + unit_name = "robotic limb replacement" export_types = list(/obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/l_leg/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot) /datum/export/robotics/surpluse - cost = 40 - unit_name = "robotic lim replacement" + cost = 50 + unit_name = "robotic limb replacement" export_types = list(/obj/item/bodypart/l_arm/robot/surplus, /obj/item/bodypart/r_arm/robot/surplus, /obj/item/bodypart/l_leg/robot/surplus, /obj/item/bodypart/r_leg/robot/surplus) /datum/export/robotics/surplus_upgraded - cost = 50 - unit_name = "upgraded robotic lim replacement" + cost = 80 + unit_name = "upgraded robotic limb replacement" export_types = list(/obj/item/bodypart/l_arm/robot/surplus_upgraded, /obj/item/bodypart/r_arm/robot/surplus_upgraded, /obj/item/bodypart/l_leg/robot/surplus_upgraded, /obj/item/bodypart/r_leg/robot/surplus_upgraded) /datum/export/robotics/surgery_gear_basic - cost = 10 + cost = 50 unit_name = "surgery tool" - export_types = list(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/surgical_drapes) + export_types = list(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/bonesetter, /obj/item/surgical_drapes) /datum/export/robotics/mech_weapon_laser cost = 300 //Sadly just metal and glass diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm index da3c0cf31d..3e52780d44 100644 --- a/code/modules/cargo/exports/parts.dm +++ b/code/modules/cargo/exports/parts.dm @@ -102,6 +102,7 @@ export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged) //Glass working stuff +// i'd just like to say how i despise the previous coder's fetish for their funny glasswork /datum/export/glasswork_dish cost = 300 diff --git a/code/modules/cargo/exports/sheets.dm b/code/modules/cargo/exports/sheets.dm index 120bfbe5e4..b0676fbde2 100644 --- a/code/modules/cargo/exports/sheets.dm +++ b/code/modules/cargo/exports/sheets.dm @@ -138,11 +138,11 @@ message = "of bones" export_types = list(/obj/item/stack/sheet/bone) -/datum/export/stack/bronze +/datum/export/stack/sheet/bronze unit_name = "tiles" cost = 5 message = "of brozne" - export_types = list(/obj/item/stack/tile/bronze) + export_types = list(/obj/item/stack/sheet/bronze) /datum/export/stack/brass unit_name = "tiles" @@ -155,3 +155,10 @@ cost = 30 message = "of paperframes" export_types = list(/obj/item/stack/sheet/paperframes) + +/datum/export/stack/telecrystal + unit_name = "raw" + cost = 1000 + message = "telecrystals" + export_types = list(/obj/item/stack/telecrystal) + diff --git a/code/modules/cargo/exports/tools.dm b/code/modules/cargo/exports/tools.dm index a889f0ed13..6769dfec40 100644 --- a/code/modules/cargo/exports/tools.dm +++ b/code/modules/cargo/exports/tools.dm @@ -1,5 +1,5 @@ /datum/export/tool - k_elasticity = 1/500 //Tool selling almost allways fine a target + k_elasticity = 1/500 //Tool selling almost always find a target /datum/export/tool/toolbox cost = 6 diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm index 2342603bde..dc2703c146 100644 --- a/code/modules/cargo/exports/weapons.dm +++ b/code/modules/cargo/exports/weapons.dm @@ -5,7 +5,7 @@ /datum/export/weapon/makeshift_shield cost = 30 - unit_name = "unknown shield" + unit_name = "nonstandard shield" export_types = list(/obj/item/shield/riot, /obj/item/shield/riot/roman, /obj/item/shield/riot/buckler, /obj/item/shield/makeshift) /datum/export/weapon/riot_shield @@ -37,7 +37,7 @@ /datum/export/weapon/taser cost = 200 - unit_name = "advanced taser" + unit_name = "hybrid taser" export_types = list(/obj/item/gun/energy/e_gun/advtaser) /datum/export/weapon/laser @@ -104,12 +104,12 @@ /datum/export/weapon/aeg cost = 200 //Endless power - unit_name = "advance engery gun" + unit_name = "advanced energy gun" export_types = list(/obj/item/gun/energy/e_gun/nuclear) /datum/export/weapon/deconer cost = 600 - unit_name = "deconer" + unit_name = "decloner" export_types = list(/obj/item/gun/energy/decloner) /datum/export/weapon/ntsniper @@ -123,9 +123,8 @@ export_types = list(/obj/item/gun/syringe/rapidsyringe) /datum/export/weapon/temp_gun - cost = 175 //Its just smaller + cost = 175 unit_name = "small temperature gun" - k_elasticity = 1/30 //Its just a smaller temperature gun, easy to mass make export_types = list(/obj/item/gun/energy/temperature) /datum/export/weapon/flowergun @@ -139,8 +138,7 @@ export_types = list(/obj/item/gun/energy/xray) /datum/export/weapon/ioncarbine - cost = 200 - k_elasticity = 1/30 //Its just a smaller temperature gun, easy to mass make + cost = 200 unit_name = "ion carbine" export_types = list(/obj/item/gun/energy/ionrifle/carbine) @@ -194,7 +192,7 @@ export_types = list(/obj/item/firing_pin/test_range) /datum/export/weapon/techslug - cost = 25 + cost = 30 k_elasticity = 0 unit_name = "advanced shotgun shell" export_types = list(/obj/item/ammo_casing/shotgun/dragonsbreath, /obj/item/ammo_casing/shotgun/meteorslug, /obj/item/ammo_casing/shotgun/pulseslug, /obj/item/ammo_casing/shotgun/frag12, /obj/item/ammo_casing/shotgun/ion, /obj/item/ammo_casing/shotgun/laserslug) @@ -215,7 +213,7 @@ /datum/export/weapon/bow_teaching cost = 500 - unit_name = "stone tablets" + unit_name = "bowyery tablet" export_types = list(/obj/item/book/granter/crafting_recipe/bone_bow) /datum/export/weapon/quiver @@ -230,48 +228,48 @@ /datum/export/weapon/pistol cost = 120 - unit_name = "illegal firearm" + unit_name = "nonstandard sidearm" export_types = list(/obj/item/gun/ballistic/automatic/pistol) /datum/export/weapon/revolver cost = 200 - unit_name = "large handgun" + unit_name = "large-caliber revolver" export_types = list(/obj/item/gun/ballistic/revolver) exclude_types = list(/obj/item/gun/ballistic/revolver/russian, /obj/item/gun/ballistic/revolver/doublebarrel) /datum/export/weapon/rocketlauncher cost = 1000 - unit_name = "rocketlauncher" + unit_name = "PML-9 rocket-propelled grenade launcher" export_types = list(/obj/item/gun/ballistic/rocketlauncher) /datum/export/weapon/antitank cost = 300 - unit_name = "hand cannon" + unit_name = "anti-tank pistol" export_types = list(/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate) /datum/export/weapon/clownstuff cost = 500 - unit_name = "clown war tech" - export_types = list(/obj/item/pneumatic_cannon/pie/selfcharge, /obj/item/shield/energy/bananium, /obj/item/melee/transforming/energy/sword/bananium, ) + unit_name = "clown combat equipment" + export_types = list(/obj/item/pneumatic_cannon/pie/selfcharge, /obj/item/shield/energy/bananium, /obj/item/melee/transforming/energy/sword/bananium) /datum/export/weapon/bulldog cost = 400 - unit_name = "drum loaded shotgun" + unit_name = "drum-fed compact combat shotgun" export_types = list(/obj/item/gun/ballistic/automatic/shotgun/bulldog) /datum/export/weapon/smg cost = 350 - unit_name = "automatic c-20r" + unit_name = "C-20r sub-machine gun" export_types = list(/obj/item/gun/ballistic/automatic/c20r) /datum/export/weapon/duelsaber - cost = 360 //Get it? - unit_name = "energy saber" - export_types = list(/obj/item/twohanded/dualsaber) + cost = 360 + unit_name = "double-bladed energy saber" + export_types = list(/obj/item/dualsaber) /datum/export/weapon/esword cost = 130 - unit_name = "energy sword" + unit_name = "energy saber" export_types = list(/obj/item/melee/transforming/energy/sword/cx/traitor, /obj/item/melee/transforming/energy/sword/saber) /datum/export/weapon/rapier @@ -286,32 +284,32 @@ /datum/export/weapon/gloves cost = 90 - unit_name = "star struck gloves" + unit_name = "anomalous armwraps" export_types = list(/obj/item/clothing/gloves/fingerless/pugilist/rapid) /datum/export/weapon/l6 cost = 500 - unit_name = "law 6 saw" + unit_name = "Aussec Armory L6 SAW" export_types = list(/obj/item/gun/ballistic/automatic/l6_saw) /datum/export/weapon/m90 cost = 400 - unit_name = "assault class weapon" + unit_name = "M90-gl carbine" export_types = list(/obj/item/gun/ballistic/automatic/m90) /datum/export/weapon/powerglove cost = 100 - unit_name = "hydraulic glove" + unit_name = "pneumatic gauntlet" export_types = list(/obj/item/melee/powerfist) /datum/export/weapon/sniper cost = 750 - unit_name = ".50 sniper" + unit_name = "anti-materiel rifle" export_types = list(/obj/item/gun/ballistic/automatic/sniper_rifle/syndicate) /datum/export/weapon/ebow cost = 600 - unit_name = "mini crossbow" + unit_name = "compact energy crossbow" export_types = list(/obj/item/gun/energy/kinetic_accelerator/crossbow) /datum/export/weapon/m10mm @@ -333,12 +331,12 @@ /datum/export/weapon/smg_mag cost = 45 - unit_name = "smg magazine" + unit_name = "SMG/carbine magazine" export_types = list(/obj/item/ammo_box/magazine/smgm45, /obj/item/ammo_box/magazine/m556) /datum/export/weapon/l6sawammo cost = 60 - unit_name = "law 6 saw ammo box" + unit_name = "L6 SAW ammo box" export_types = list(/obj/item/ammo_box/magazine/mm195x129) include_subtypes = TRUE @@ -355,13 +353,13 @@ /datum/export/weapon/fletcher_ammo cost = 60 - unit_name = "illegal ammo magazines" + unit_name = "flechette launcher magazine" export_types = list(/obj/item/ammo_box/magazine/flechette) include_subtypes = TRUE /datum/export/weapon/dj_a_pizzabomb cost = -6000 - unit_name = "Repair Costs" + unit_name = "undeclared ordinance and subsequent repair costs" export_types = list(/obj/item/pizzabox/bomb, /obj/item/sbeacondrop/bomb) /datum/export/weapon/real_toolbox @@ -371,12 +369,12 @@ /datum/export/weapon/melee cost = 50 - unit_name = "unlisted weapon" + unit_name = "any other melee weapon" export_types = list(/obj/item/melee) include_subtypes = TRUE /datum/export/weapon/gun cost = 50 - unit_name = "unlisted weapon" + unit_name = "any other weapon" export_types = list(/obj/item/gun) include_subtypes = TRUE diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm index 9fe427c45a..4ca97a13a5 100644 --- a/code/modules/cargo/expressconsole.dm +++ b/code/modules/cargo/expressconsole.dm @@ -1,5 +1,5 @@ #define MAX_EMAG_ROCKETS 8 -#define BEACON_COST 5000 +#define BEACON_COST 500 #define SP_LINKED 1 #define SP_READY 2 #define SP_LAUNCH 3 @@ -15,6 +15,7 @@ circuit = /obj/item/circuitboard/computer/cargo/express blockade_warning = "Bluespace instability detected. Delivery impossible." req_access = list(ACCESS_QM) + var/message var/printed_beacons = 0 //number of beacons printed. Used to determine beacon names. var/list/meme_pack_data @@ -40,7 +41,7 @@ to_chat(user, "You [locked ? "lock" : "unlock"] the interface.") return else if(istype(W, /obj/item/disk/cargo/bluespace_pod)) - podType = /obj/structure/closet/supplypod/bluespacepod + podType = /obj/structure/closet/supplypod/bluespacepod //doesnt effect circuit board, making reversal possible to_chat(user, "You insert the disk into [src], allowing for advanced supply delivery vehicles.") qdel(W) return TRUE @@ -50,22 +51,20 @@ sb.link_console(src, user) return TRUE else - to_chat(user, "[src] is already linked to [sb].") + to_chat(user, "[src] is already linked to [sb].") ..() /obj/machinery/computer/cargo/express/emag_act(mob/living/user) - . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT) if(obj_flags & EMAGGED) return - user.visible_message("[user] swipes a suspicious card through [src]!", - "You change the routing protocols, allowing the Supply Pod to land anywhere on the station.") + if(user) + user.visible_message("[user] swipes a suspicious card through [src]!", + "You change the routing protocols, allowing the Supply Pod to land anywhere on the station.") obj_flags |= EMAGGED // This also sets this on the circuit board var/obj/item/circuitboard/computer/cargo/board = circuit board.obj_flags |= EMAGGED packin_up() - req_access = list() - return TRUE /obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry meme_pack_data = list() // sorry for what? @@ -87,10 +86,10 @@ "desc" = P.desc || P.name // If there is a description, use it. Otherwise use the pack's name. )) -/obj/machinery/computer/cargo/express/ui_interact(mob/living/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state. - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/cargo/express/ui_interact(mob/living/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "cargo_express", name, 600, 700, master_ui, state) + ui = new(user, src, "CargoExpress", name) ui.open() /obj/machinery/computer/cargo/express/ui_data(mob/user) @@ -129,9 +128,6 @@ 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 @@ -151,6 +147,7 @@ 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"]) var/datum/supply_pack/pack = SSshuttle.supply_packs[id] @@ -193,7 +190,6 @@ LZ = pick(empty_turfs) 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() @@ -207,7 +203,7 @@ CHECK_TICK if(empty_turfs && empty_turfs.len) 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) var/LZ = pick(empty_turfs) diff --git a/code/modules/cargo/order.dm b/code/modules/cargo/order.dm index 3d1caf6ba6..4fa6a4eade 100644 --- a/code/modules/cargo/order.dm +++ b/code/modules/cargo/order.dm @@ -27,10 +27,12 @@ var/orderer_rank var/orderer_ckey var/reason + var/discounted_pct var/datum/supply_pack/pack var/datum/bank_account/paying_account + var/obj/item/coupon/applied_coupon -/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason, paying_account) +/datum/supply_order/New(datum/supply_pack/pack, orderer, orderer_rank, orderer_ckey, reason, paying_account, coupon) id = SSshuttle.ordernum++ src.pack = pack src.orderer = orderer @@ -38,6 +40,7 @@ src.orderer_ckey = orderer_ckey src.reason = reason src.paying_account = paying_account + src.applied_coupon = coupon /datum/supply_order/proc/generateRequisition(turf/T) var/obj/item/paper/P = new(T) @@ -57,58 +60,64 @@ P.update_icon() return P -/datum/supply_order/proc/generateManifest(obj/structure/closet/crate/C) - var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(C, id, pack.cost) +/datum/supply_order/proc/generateManifest(obj/container, owner, packname) //generates-the-manifests. + var/obj/item/paper/fluff/jobs/cargo/manifest/P = new(container, id, 0) var/station_name = (P.errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name() - P.name = "shipping manifest - #[id] ([pack.name])" + P.name = "shipping manifest - [packname?"#[id] ([pack.name])":"(Grouped Item Crate)"]" 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]" + if(id && !(id == "Cargo")) + P.info += "Direct purchase from [owner]
    " + P.name += " - Purchased by [owner]" P.info += "Order #[id]
    " P.info += "Destination: [station_name]
    " - P.info += "Item: [pack.name]
    " + if(packname) + P.info += "Item: [packname]
    " P.info += "Contents:
    " P.info += "
      " - for(var/atom/movable/AM in C.contents - P - C.lockerelectronics) + var/list/ignore_this = list(P) + if(istype(container, /obj/structure/closet)) + var/obj/structure/closet/C = container + ignore_this += C.lockerelectronics + for(var/atom/movable/AM in container.contents - ignore_this) if((P.errors & MANIFEST_ERROR_CONTENTS) && prob(50)) continue P.info += "
    • [AM.name]
    • " P.info += "
    " P.info += "

    Stamp below to confirm receipt of goods:

    " + if(P.errors & MANIFEST_ERROR_ITEM) + var/static/list/blacklisted_error = typecacheof(list( + /obj/structure/closet/crate/secure, + /obj/structure/closet/crate/large, + /obj/structure/closet/secure_closet/goodies + )) + if(blacklisted_error[container.type]) + P.errors &= ~MANIFEST_ERROR_ITEM + else + var/lost = max(round(container.contents.len / 10), 1) + while(--lost >= 0) + qdel(pick(container.contents)) + P.update_icon() - P.forceMove(C) - C.manifest = P - C.update_icon() + P.forceMove(container) + + if(istype(container, /obj/structure/closet/crate)) + var/obj/structure/closet/crate/C = container + C.manifest = P + C.update_icon() return P /datum/supply_order/proc/generate(atom/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) - if(istype(C, /obj/structure/closet/crate/secure) || istype(C, /obj/structure/closet/crate/large)) - M.errors &= ~MANIFEST_ERROR_ITEM - else - var/lost = max(round(C.contents.len / 10), 1) - while(--lost >= 0) - qdel(pick(C.contents)) + generateManifest(C, paying_account, pack) return C -//Paperwork for NT -/obj/item/folder/paperwork - name = "Incomplete Paperwork" - desc = "These should've been filled out four months ago! Unfinished grant papers issued by Nanotrasen's finance department. Complete this page for additional funding." - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "docs_generic" - -/obj/item/folder/paperwork_correct - name = "Finished Paperwork" - desc = "A neat stack of filled-out forms, in triplicate and signed. Is there anything more satisfying? Make sure they get stamped." - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "docs_verified" +/datum/supply_order/proc/generateCombo(var/miscbox, var/misc_own, var/misc_contents) + for (var/I in misc_contents) + new I(miscbox) + generateManifest(miscbox, misc_own, "") + return diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm index f82e16ad5c..7ec3a775a5 100644 --- a/code/modules/cargo/packs.dm +++ b/code/modules/cargo/packs.dm @@ -15,6 +15,7 @@ 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/goody = PACK_GOODY_NONE //Small items can be grouped into a single crate.They also come in a closet/lockbox instead of a full crate, so the 700 min doesn't apply var/can_private_buy = TRUE //Can it be purchased privately by each crewmember? /datum/supply_pack/proc/generate(atom/A, datum/bank_account/paying_account) diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm index 3a3357cc42..9f8bb2f25f 100644 --- a/code/modules/cargo/packs/armory.dm +++ b/code/modules/cargo/packs/armory.dm @@ -37,15 +37,6 @@ contains = list(/obj/item/storage/box/chemimp) crate_name = "chemical implant crate" -/datum/supply_pack/security/armory/combatknives - name = "Combat Knives Crate" - desc = "Contains three sharpened combat knives. Each knife guaranteed to fit snugly inside any Nanotrasen-standard boot. Requires Armory access to open." - cost = 3200 - contains = list(/obj/item/kitchen/knife/combat, - /obj/item/kitchen/knife/combat, - /obj/item/kitchen/knife/combat) - crate_name = "combat knife crate" - /datum/supply_pack/security/armory/ballistic name = "Combat Shotguns Crate" desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, with three Shotgun Bandoliers, as well as seven buchshot and 12g shotgun slugs. Requires Armory access to open." @@ -167,11 +158,10 @@ /datum/supply_pack/security/armory/russian name = "Russian Surplus Crate" - desc = "Hello Comrade, we have the most modern russian military equipment the black market can offer, for the right price of course. Sadly we couldnt remove the lock so it requires Armory access to open." + desc = "Hello Comrade, we have the most modern Russian military equipment the black market can offer, for the right price of course. Sadly we couldn't remove the lock so it requires Armory access to open." cost = 7500 contraband = TRUE contains = list(/obj/item/reagent_containers/food/snacks/rationpack, - /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 +171,10 @@ /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/automatic/surplus) + /obj/effect/spawner/bundle/crate/mosin, + /obj/item/storage/toolbox/ammo, + /obj/effect/spawner/bundle/crate/surplusrifle, + /obj/item/storage/toolbox/ammo/surplus) crate_name = "surplus military crate" /datum/supply_pack/security/armory/russian/fill(obj/structure/closet/crate/C) @@ -232,3 +225,10 @@ /obj/item/ammo_box/magazine/wt550m9/wtrubber, /obj/item/ammo_box/magazine/wt550m9/wtrubber) crate_name = "auto rifle ammo crate" + +/datum/supply_pack/security/armory/hell_single + name = "Hellgun Single-Pack" + crate_name = "hellgun crate" + desc = "Contains one hellgun, an old pattern of laser gun infamous for its ability to horribly disfigure targets with burns. Technically violates the Space Geneva Convention when used on humanoids." + cost = 1500 + contains = list(/obj/item/gun/energy/laser/hellgun) diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm index c181d6fb74..08f9a927c6 100644 --- a/code/modules/cargo/packs/costumes_toys.dm +++ b/code/modules/cargo/packs/costumes_toys.dm @@ -301,3 +301,36 @@ /obj/item/clothing/head/wizard/fake) crate_name = "wizard costume crate" crate_type = /obj/structure/closet/crate/wooden + +/datum/supply_pack/costumes_toys/wedding + name = "Wedding Crate" + desc = "Tie the knot IN SPACE! Hold your own extravagant wedding with this crate of suits and bridal gowns. Complete with champagne, cake, and the luxurious cost you would expect for an event to remember." + cost = 10000 // weddings are absurdly expensive and so is this crate + contains = list(/obj/item/clothing/under/suit/black_really, //we don't actually need suits since you can vend them but the crate should feel "complete" + /obj/item/clothing/under/suit/black_really, + /obj/item/clothing/under/suit/charcoal, + /obj/item/clothing/under/suit/charcoal, + /obj/item/clothing/under/suit/navy, + /obj/item/clothing/under/suit/navy, + /obj/item/clothing/under/suit/burgundy, + /obj/item/clothing/under/suit/burgundy, // A pair of each "fancy suit" color for variety + /obj/item/clothing/under/suit/white, + /obj/item/clothing/under/suit/white, // white is a weird color for a groom but some people are weird + /obj/item/clothing/under/suit/polychromic, + /obj/item/clothing/under/suit/polychromic, // in case you can't be satisfied with the most fitting choices, of course. + /obj/item/clothing/under/dress/wedding, + /obj/item/clothing/under/dress/wedding, // this is what you actually bought the crate for. You can't get these anywhere else. + /obj/item/clothing/under/dress/wedding/orange, + /obj/item/clothing/under/dress/wedding/orange, + /obj/item/clothing/under/dress/wedding/purple, + /obj/item/clothing/under/dress/wedding/purple, + /obj/item/clothing/under/dress/wedding/blue, + /obj/item/clothing/under/dress/wedding/blue, + /obj/item/clothing/under/dress/wedding/red, + /obj/item/clothing/under/dress/wedding/red, // two of each + /obj/item/reagent_containers/food/drinks/bottle/champagne, //appropriate booze for a wedding + /obj/item/reagent_containers/food/snacks/store/cake/vanilla_cake, // we don't have a full wedding cake but this will do + /obj/item/storage/fancy/ringbox/silver, + /obj/item/storage/fancy/ringbox/silver) //diamond rings cost the same price as this crate via cargo so we're not giving you two for free. Wedding rings are traditionally less valuable anyway. + crate_name = "wedding crate" + diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm index 22258d19a7..9af18e13f6 100644 --- a/code/modules/cargo/packs/engineering.dm +++ b/code/modules/cargo/packs/engineering.dm @@ -90,16 +90,6 @@ crate_name = "industrial rcd" crate_type = /obj/structure/closet/crate/secure/engineering -/datum/supply_pack/engineering/powergamermitts - name = "Insulated Gloves Crate" - desc = "The backbone of modern society. Barely ever ordered for actual engineering. Contains three insulated gloves." - cost = 2300 //Made of pure-grade bullshittinium - contains = list(/obj/item/clothing/gloves/color/yellow, - /obj/item/clothing/gloves/color/yellow, - /obj/item/clothing/gloves/color/yellow) - crate_name = "insulated gloves crate" - crate_type = /obj/structure/closet/crate/engineering/electrical - /datum/supply_pack/engineering/inducers name = "NT-75 Electromagnetic Power Inducers Crate" desc = "No rechargers? No problem, with the NT-75 EPI, you can recharge any standard cell-based equipment anytime, anywhere. Contains two Inducers." @@ -162,6 +152,7 @@ /obj/item/storage/toolbox/mechanical) cost = 1200 crate_name = "toolbox crate" + special = TRUE //Department resupply shuttle loan event. /datum/supply_pack/engineering/bsa name = "Bluespace Artillery Parts" diff --git a/code/modules/cargo/packs/goodies.dm b/code/modules/cargo/packs/goodies.dm new file mode 100644 index 0000000000..5d07e85bac --- /dev/null +++ b/code/modules/cargo/packs/goodies.dm @@ -0,0 +1,83 @@ + +/datum/supply_pack/goody + access = NONE + group = "Goodies" + goody = PACK_GOODY_PRIVATE + +/datum/supply_pack/goody/combatknives_single + name = "Combat Knife Single-Pack" + desc = "Contains one sharpened combat knive. Guaranteed to fit snugly inside any Nanotrasen-standard boot." + cost = 800 + contains = list(/obj/item/kitchen/knife/combat) + +/datum/supply_pack/goody/sologamermitts + name = "Insulated Gloves Single-Pack" + desc = "The backbone of modern society. Barely ever ordered for actual engineering." + cost = 800 + contains = list(/obj/item/clothing/gloves/color/yellow) + +/datum/supply_pack/goody/firstaidbruises_single + name = "Bruise Treatment Kit Single-Pack" + desc = "A single brute first-aid kit, perfect for recovering from being crushed in an airlock. Did you know people get crushed in airlocks all the time? Interesting..." + cost = 330 + contains = list(/obj/item/storage/firstaid/brute) + +/datum/supply_pack/goody/firstaidburns_single + name = "Burn Treatment Kit Single-Pack" + desc = "A single burn first-aid kit. The advertisement displays a winking atmospheric technician giving a thumbs up, saying \"Mistakes happen!\"" + cost = 330 + contains = list(/obj/item/storage/firstaid/fire) + +/datum/supply_pack/goody/firstaid_single + name = "First Aid Kit Single-Pack" + desc = "A single first-aid kit, fit for healing most types of bodily harm." + cost = 250 + contains = list(/obj/item/storage/firstaid/regular) + +/datum/supply_pack/goody/firstaidoxygen_single + name = "Oxygen Deprivation Kit Single-Pack" + desc = "A single oxygen deprivation first-aid kit, marketed heavily to those with crippling fears of asphyxiation." + cost = 330 + contains = list(/obj/item/storage/firstaid/o2) + +/datum/supply_pack/goody/firstaidtoxins_single + name = "Toxin Treatment Kit Single-Pack" + desc = "A single first aid kit focused on healing damage dealt by heavy toxins." + cost = 330 + contains = list(/obj/item/storage/firstaid/toxin) + +/datum/supply_pack/goody/toolbox // mostly just to water down coupon probability + name = "Mechanical Toolbox" + desc = "A fully stocked mechanical toolbox, for when you're too lazy to just print them out." + cost = 300 + contains = list(/obj/item/storage/toolbox/mechanical) + +/datum/supply_pack/goody/electrical_toolbox // mostly just to water down coupon probability + name = "Mechanical Toolbox" + desc = "A fully stocked electrical toolbox, for when you're too lazy to just print them out." + cost = 300 + contains = list(/obj/item/storage/toolbox/electrical) + +/datum/supply_pack/goody/valentine + name = "Valentine Card" + desc = "Make an impression on that special someone! Comes with one valentine card and a free candy heart!" + cost = 150 + contains = list(/obj/item/valentine, /obj/item/reagent_containers/food/snacks/candyheart) + +/datum/supply_pack/goody/beeplush + name = "Bee Plushie" + desc = "The most important thing you could possibly spend your hard-earned money on." + cost = 1500 + contains = list(/obj/item/toy/plush/beeplushie) + +/datum/supply_pack/goody/beach_ball + name = "Beach Ball" + desc = "The simple beach ball is one of Nanotrasen's most popular products. 'Why do we make beach balls? Because we can! (TM)' - Nanotrasen" + cost = 200 + contains = list(/obj/item/toy/beach_ball) + +/datum/supply_pack/goody/medipen_twopak + name = "Medipen Two-Pak" + desc = "Contains one standard epinephrine medipen and one standard emergency first-aid kit medipen. For when you want to prepare for the worst." + cost = 500 + contains = list(/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/hypospray/medipen/ekit) diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm index 771f7ce222..0cf12fbc5d 100644 --- a/code/modules/cargo/packs/materials.dm +++ b/code/modules/cargo/packs/materials.dm @@ -14,53 +14,60 @@ ////////////////////////////////////////////////////////////////////////////// /datum/supply_pack/materials/cardboard50 + goody = PACK_GOODY_PUBLIC name = "50 Cardboard Sheets" desc = "Create a bunch of boxes." - cost = 1000 + cost = 300 //thrice their export value contains = list(/obj/item/stack/sheet/cardboard/fifty) - crate_name = "cardboard sheets crate" /datum/supply_pack/materials/glass50 + goody = PACK_GOODY_PUBLIC name = "50 Glass Sheets" desc = "Let some nice light in with fifty glass sheets!" - cost = 850 + cost = 300 //double their export value contains = list(/obj/item/stack/sheet/glass/fifty) - crate_name = "glass sheets crate" /datum/supply_pack/materials/metal50 + goody = PACK_GOODY_PUBLIC name = "50 Metal Sheets" desc = "Any construction project begins with a good stack of fifty metal sheets!" - cost = 850 + cost = 300 //double their export value contains = list(/obj/item/stack/sheet/metal/fifty) - crate_name = "metal sheets crate" /datum/supply_pack/materials/plasteel20 + goody = PACK_GOODY_PUBLIC name = "20 Plasteel Sheets" desc = "Reinforce the station's integrity with twenty plasteel sheets!" - cost = 4700 + cost = 4000 contains = list(/obj/item/stack/sheet/plasteel/twenty) - crate_name = "plasteel sheets crate" - -/datum/supply_pack/materials/plasteel50 - name = "50 Plasteel Sheets" - desc = "For when you REALLY have to reinforce something." - cost = 9050 - contains = list(/obj/item/stack/sheet/plasteel/fifty) - crate_name = "plasteel sheets crate" /datum/supply_pack/materials/plastic50 + goody = PACK_GOODY_PUBLIC name = "50 Plastic Sheets" desc = "Build a limitless amount of toys with fifty plastic sheets!" - cost = 950 - contains = list(/obj/item/stack/sheet/plastic/fifty) - crate_name = "plastic sheets crate" + cost = 200 // double their export + contains = list(/obj/item/stack/sheet/plastic/twenty) /datum/supply_pack/materials/sandstone30 + goody = PACK_GOODY_PUBLIC name = "30 Sandstone Blocks" desc = "Neither sandy nor stoney, these thirty blocks will still get the job done." - cost = 800 + cost = 150 // five times their export contains = list(/obj/item/stack/sheet/mineral/sandstone/thirty) - crate_name = "sandstone blocks crate" + +/datum/supply_pack/materials/wood50 + goody = PACK_GOODY_PUBLIC + name = "50 Wood Planks" + desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!" + cost = 400 // 6-7 planks shy from having equal import/export prices + contains = list(/obj/item/stack/sheet/mineral/wood/twenty) + +/datum/supply_pack/materials/rcdammo + goody = PACK_GOODY_PUBLIC + name = "Large RCD ammo Single-Pack" + desc = "A single large compressed RCD matter pack, to help with any holes or projects people might be working on." + cost = 600 + contains = list(/obj/item/rcd_ammo/large) /datum/supply_pack/materials/rawlumber name = "50 Towercap Logs" @@ -74,35 +81,6 @@ for(var/i in 1 to 49) new /obj/item/grown/log(.) -/datum/supply_pack/materials/wood50 - name = "50 Wood Planks" - desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!" - cost = 1450 - contains = list(/obj/item/stack/sheet/mineral/wood/fifty) - crate_name = "wood planks crate" - -/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." - cost = 3750 - contains = list(/obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo, - /obj/item/rcd_ammo) - crate_name = "rcd ammo" - ////////////////////////////////////////////////////////////////////////////// ///////////////////////////// Canisters ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index ab188f235b..6a4165f840 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -114,7 +114,9 @@ /obj/item/storage/box/medsprays, /obj/item/storage/box/syringes, /obj/item/storage/box/bodybags, - /obj/item/storage/pill_bottle/stimulant) + /obj/item/storage/pill_bottle/stimulant, + /obj/item/stack/medical/bone_gel, + /obj/item/stack/medical/bone_gel) crate_name = "medical supplies crate" /datum/supply_pack/medical/adv_surgery_tools @@ -141,34 +143,6 @@ ///////////////////////////// Medical Kits /////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -/datum/supply_pack/medical/firstaidbruises - name = "Bruise Treatment Kit Crate" - desc = "Contains three first aid kits focused on healing bruises and broken bones." - cost = 1000 - contains = list(/obj/item/storage/firstaid/brute, - /obj/item/storage/firstaid/brute, - /obj/item/storage/firstaid/brute) - crate_name = "brute treatment kit crate" - -/datum/supply_pack/medical/firstaidburns - name = "Burn Treatment Kit Crate" - desc = "Contains three first aid kits focused on healing severe burns." - cost = 1000 - contains = list(/obj/item/storage/firstaid/fire, - /obj/item/storage/firstaid/fire, - /obj/item/storage/firstaid/fire) - crate_name = "burn treatment kit crate" - -/datum/supply_pack/medical/firstaid - name = "First Aid Kit Crate" - desc = "Contains four first aid kits for healing most types of wounds." - cost = 1000 - contains = list(/obj/item/storage/firstaid/regular, - /obj/item/storage/firstaid/regular, - /obj/item/storage/firstaid/regular, - /obj/item/storage/firstaid/regular) - crate_name = "first aid kit crate" - /datum/supply_pack/medical/sprays name = "Medical Sprays" desc = "Contains two cans of Styptic Spray, Silver Sulfadiazine Spray, Synthflesh Spray and Sterilizer Compound Spray." @@ -183,35 +157,6 @@ /obj/item/reagent_containers/medspray/sterilizine) crate_name = "medical supplies crate" -/datum/supply_pack/medical/firstaidmixed - name = "Mixed Medical Kits" - desc = "Contains one of each medical kits for dealing with a variety of injured crewmembers." - cost = 1250 - contains = list(/obj/item/storage/firstaid/toxin, - /obj/item/storage/firstaid/o2, - /obj/item/storage/firstaid/brute, - /obj/item/storage/firstaid/fire, - /obj/item/storage/firstaid/regular) - crate_name = "medical supplies crate" - -/datum/supply_pack/medical/firstaidoxygen - name = "Oxygen Deprivation Kit Crate" - desc = "Contains three first aid kits focused on helping oxygen deprivation victims." - cost = 1000 - contains = list(/obj/item/storage/firstaid/o2, - /obj/item/storage/firstaid/o2, - /obj/item/storage/firstaid/o2) - crate_name = "oxygen deprivation kit crate" - -/datum/supply_pack/medical/firstaidtoxins - name = "Toxin Treatment Kit Crate" - desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins." - cost = 1000 - contains = list(/obj/item/storage/firstaid/toxin, - /obj/item/storage/firstaid/toxin, - /obj/item/storage/firstaid/toxin) - crate_name = "toxin treatment kit crate" - /datum/supply_pack/medical/advrad name = "Radiation Treatment Crate Deluxe" desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pills, as well as a radiation treatment deluxe pill bottle!" @@ -273,3 +218,18 @@ /obj/item/storage/box/beakers) crate_name = "virus containment unit crate" crate_type = /obj/structure/closet/crate/secure/plasma + +/datum/supply_pack/medical/medipen_variety + name = "Medipen Variety-Pak" + desc = "Contains eight different medipens in three different varieties, to assist in quickly treating seriously injured patients." + cost = 2000 + contains = list(/obj/item/reagent_containers/hypospray/medipen/, + /obj/item/reagent_containers/hypospray/medipen/, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/blood_loss, + /obj/item/reagent_containers/hypospray/medipen/blood_loss, + /obj/item/reagent_containers/hypospray/medipen/blood_loss) + + crate_name = "medipen crate" diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm index 7df9d851a4..c6728831eb 100644 --- a/code/modules/cargo/packs/misc.dm +++ b/code/modules/cargo/packs/misc.dm @@ -194,9 +194,9 @@ /datum/supply_pack/misc/dirtymags name = "Dirty Magazines" - desc = "Get your mind out of the gutter operative, you have work to do. Three items per order. Possible Results: .357 Speedloaders, Kitchen Gun Mags, Stetchkin Mags." + desc = "Get your mind out of the gutter operative, you have work to do. Three items per order. Possible Results: .357 Speedloaders, Kitchen Gun patented magazines, or Stetchkin magazines." hidden = TRUE - cost = 12000 + cost = 4000 var/num_contained = 3 contains = list(/obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/pistolm9mm, @@ -294,11 +294,11 @@ name = "Potted Plants Crate" desc = "Spruce up the station with these lovely plants! Contains a random assortment of five potted plants from Nanotrasen's potted plant research division. Warranty void if thrown." cost = 730 - contains = list(/obj/item/twohanded/required/kirbyplants/random, - /obj/item/twohanded/required/kirbyplants/random, - /obj/item/twohanded/required/kirbyplants/random, - /obj/item/twohanded/required/kirbyplants/random, - /obj/item/twohanded/required/kirbyplants/random) + contains = list(/obj/item/kirbyplants/random, + /obj/item/kirbyplants/random, + /obj/item/kirbyplants/random, + /obj/item/kirbyplants/random, + /obj/item/kirbyplants/random) crate_name = "potted plants crate" crate_type = /obj/structure/closet/crate/hydroponics @@ -333,45 +333,58 @@ //////////////////////////// Misc + Decor //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -/datum/supply_pack/misc/carpet_exotic - name = "Exotic Carpet Crate" - desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns." - cost = 7000 - contains = list(/obj/item/stack/tile/carpet/blue/fifty, - /obj/item/stack/tile/carpet/blue/fifty, - /obj/item/stack/tile/carpet/cyan/fifty, - /obj/item/stack/tile/carpet/cyan/fifty, - /obj/item/stack/tile/carpet/green/fifty, - /obj/item/stack/tile/carpet/green/fifty, - /obj/item/stack/tile/carpet/orange/fifty, - /obj/item/stack/tile/carpet/orange/fifty, - /obj/item/stack/tile/carpet/purple/fifty, - /obj/item/stack/tile/carpet/purple/fifty, - /obj/item/stack/tile/carpet/red/fifty, - /obj/item/stack/tile/carpet/red/fifty, - /obj/item/stack/tile/carpet/royalblue/fifty, - /obj/item/stack/tile/carpet/royalblue/fifty, - /obj/item/stack/tile/carpet/royalblack/fifty, - /obj/item/stack/tile/carpet/royalblack/fifty, - /obj/item/stack/tile/carpet/blackred/fifty, - /obj/item/stack/tile/carpet/blackred/fifty, - /obj/item/stack/tile/carpet/monochrome/fifty, - /obj/item/stack/tile/carpet/monochrome/fifty) - crate_name = "exotic carpet crate" - /datum/supply_pack/misc/carpet - name = "Premium Carpet Crate" - desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains some classic carpet, along with black, red, and monochrome varients." - cost = 1350 - contains = list(/obj/item/stack/tile/carpet/fifty, - /obj/item/stack/tile/carpet/fifty, - /obj/item/stack/tile/carpet/black/fifty, - /obj/item/stack/tile/carpet/black/fifty, - /obj/item/stack/tile/carpet/blackred/fifty, - /obj/item/stack/tile/carpet/blackred/fifty, - /obj/item/stack/tile/carpet/monochrome/fifty, - /obj/item/stack/tile/carpet/monochrome/fifty) - crate_name = "premium carpet crate" + goody = PACK_GOODY_PUBLIC + name = "Classic Carpet Single-Pack" + desc = "Plasteel floor tiles getting on your nerves? This 50 units stack of extra soft carpet will tie any room together." + cost = 200 + contains = list(/obj/item/stack/tile/carpet/fifty) + +/datum/supply_pack/misc/carpet/black + name = "Black Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/black/fifty) + +/datum/supply_pack/misc/carpet/premium + name = "Monochrome Carpet Single-Pack" + desc = "Exotic carpets for all your decorating needs. This 30 units stack of extra soft carpet will tie any room together." + cost = 250 + contains = list(/obj/item/stack/tile/carpet/monochrome/thirty) + +/datum/supply_pack/misc/carpet/premium/blackred + name = "Black-Red Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/blackred/thirty) + +/datum/supply_pack/misc/carpet/premium/royalblack + name = "Royal Black Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/royalblack/thirty) + +/datum/supply_pack/misc/carpet/premium/royalblue + name = "Royal Blue Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/royalblue/thirty) + +/datum/supply_pack/misc/carpet/premium/red + name = "Red Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/red/thirty) + +/datum/supply_pack/misc/carpet/premium/purple + name = "Purple Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/purple/thirty) + +/datum/supply_pack/misc/carpet/premium/orange + name = "Orange Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/orange/thirty) + +/datum/supply_pack/misc/carpet/premium/green + name = "Green Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/green/thirty) + +/datum/supply_pack/misc/carpet/premium/cyan + name = "Cyan Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/cyan/thirty) + +/datum/supply_pack/misc/carpet/premium/blue + name = "Blue Carpet Single-Pack" + contains = list(/obj/item/stack/tile/carpet/blue/thirty) /datum/supply_pack/misc/noslipfloor name = "High-traction Floor Tiles" @@ -402,21 +415,10 @@ /obj/item/restraints/handcuffs/fake/kinky, /obj/item/clothing/head/kitty/genuine, // Why its illegal /obj/item/clothing/head/kitty/genuine, - /obj/item/storage/pill_bottle/penis_enlargement, - /obj/structure/reagent_dispensers/keg/aphro) + /obj/item/storage/pill_bottle/penis_enlargement) crate_name = "lewd kit" crate_type = /obj/structure/closet/crate -/datum/supply_pack/misc/lewdkeg - name = "Lewd Deluxe Keg" - desc = "That other stuff not getting you ready? Well I have a Chemslut making tons of the good stuff." - cost = 7500 //It can be a weapon - contraband = TRUE - contains = list(/obj/structure/reagent_dispensers/keg/aphro/strong) - crate_name = "deluxe keg" - crate_type = /obj/structure/closet/crate - - ///Special supply crate that generates random syndicate gear up to a determined TC value /datum/supply_pack/misc/syndicate @@ -453,4 +455,4 @@ if(crate_value < I.cost) continue crate_value -= I.cost - new I.item(C) \ No newline at end of file + new I.item(C) diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm index 249faae33d..0f01dfd5d9 100644 --- a/code/modules/cargo/packs/organic.dm +++ b/code/modules/cargo/packs/organic.dm @@ -361,6 +361,7 @@ /obj/item/seeds/reishi, /obj/item/seeds/banana, /obj/item/seeds/eggplant/eggy, + /obj/item/seeds/poppy/lily/trumpet, /obj/item/seeds/random, /obj/item/seeds/random) crate_name = "exotic seeds crate" diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm index 738eb03fbf..cf9cc5e0d1 100644 --- a/code/modules/cargo/packs/security.dm +++ b/code/modules/cargo/packs/security.dm @@ -100,7 +100,7 @@ crate_name = "surplus russian clothing" crate_type = /obj/structure/closet/crate/internals -/datum/supply_pack/security/russianmosin +/datum/supply_pack/security/russian_partisan 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 @@ -112,12 +112,17 @@ /obj/item/clothing/suit/armor/bulletproof, /obj/item/clothing/head/helmet/alt, /obj/item/clothing/gloves/tackler/combat/insulated, - /obj/item/clothing/mask/gas, - /obj/item/ammo_box/magazine/m10mm/rifle, - /obj/item/gun/ballistic/automatic/surplus) + /obj/item/clothing/mask/gas) crate_name = "surplus russian gear" crate_type = /obj/structure/closet/crate/internals +/datum/supply_pack/security/russian_partisan/fill(obj/structure/closet/crate/C) + ..() + if(prob(20)) + new /obj/effect/spawner/bundle/crate/mosin(C) + else + new /obj/effect/spawner/bundle/crate/surplusrifle(C) + /datum/supply_pack/security/sechardsuit name = "Sec Hardsuit" desc = "One Sec Hardsuit with a small air tank and mask." diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 0402dc683f..ae48fddfb4 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -19,6 +19,8 @@ ///Next tick to reset the total message counter var/total_count_reset = 0 var/ircreplyamount = 0 + /// last time they tried to do an autobunker auth + var/autobunker_last_try = 0 ///////// //OTHER// @@ -28,6 +30,9 @@ var/move_delay = 0 var/area = null + /// Last time we Click()ed. No clicking twice in one tick! + var/last_click = 0 + /////////////// //SOUND STUFF// /////////////// @@ -117,6 +122,8 @@ /// Messages currently seen by this client var/list/seen_messages + ///A lazy list of atoms we've examined in the last EXAMINE_MORE_TIME (default 1.5) seconds, so that we will call [atom/proc/examine_more()] instead of [atom/proc/examine()] on them when examining + var/list/recent_examines ///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 @@ -134,5 +141,13 @@ var/parallax_layers_max = 3 var/parallax_animate_timer + // List of all asset filenames sent to this client by the asset cache, along with their assoicated md5s + var/list/sent_assets = list() + /// List of all completed blocking send jobs awaiting acknowledgement by send_asset + var/list/completed_asset_jobs = list() + /// Last asset send job id. + var/last_asset_job = 0 + var/last_completed_asset_job = 0 + //world.time of when the crew manifest can be accessed var/crew_manifest_delay diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index d575a53afa..e7aa447840 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -20,9 +20,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( When somebody clicks a link in game, this Topic is called first. It does the stuff in this proc and then is redirected to the Topic() proc for the src=[0xWhatever] (if specified in the link). ie locate(hsrc).Topic() - Such links can be spoofed. - Because of this certain things MUST be considered whenever adding a Topic() for something: - Can it be fed harmful values which could cause runtimes? - Is the Topic call an admin-only thing? @@ -37,29 +35,13 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( return // asset_cache + var/asset_cache_job if(href_list["asset_cache_confirm_arrival"]) - var/job = text2num(href_list["asset_cache_confirm_arrival"]) - //because we skip the limiter, we have to make sure this is a valid arrival and not somebody tricking us - // into letting append to a list without limit. - if (job && job <= last_asset_job && !(job in completed_asset_jobs)) - completed_asset_jobs += job + asset_cache_job = asset_cache_confirm_arrival(href_list["asset_cache_confirm_arrival"]) + if(!asset_cache_job) return - else if (job in completed_asset_jobs) //byond bug ID:2256651 - to_chat(src, "An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)") - src << browse("...", "window=asset_cache_browser") - // Keypress passthrough - if(href_list["__keydown"]) - var/keycode = browser_keycode_to_byond(href_list["__keydown"]) - if(keycode) - keyDown(keycode) - return - if(href_list["__keyup"]) - var/keycode = browser_keycode_to_byond(href_list["__keyup"]) - if(keycode) - keyUp(keycode) - return - + // Rate limiting var/mtl = CONFIG_GET(number/minute_topic_limit) if (!holder && mtl) var/minute = round(world.time, 600) @@ -75,7 +57,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( topiclimiter[ADMINSWARNED_AT] = minute msg += " Administrators have been informed." log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute") - message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute") + message_admins("[ADMIN_LOOKUPFLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute") to_chat(src, "[msg]") return @@ -96,6 +78,31 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( if(!(href_list["_src_"] == "chat" && href_list["proc"] == "ping" && LAZYLEN(href_list) == 2)) log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]") + //byond bug ID:2256651 + if (asset_cache_job && (asset_cache_job in completed_asset_jobs)) + to_chat(src, "An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)") + src << browse("...", "window=asset_cache_browser") + return + if (href_list["asset_cache_preload_data"]) + asset_cache_preload_data(href_list["asset_cache_preload_data"]) + return + + // Keypress passthrough + if(href_list["__keydown"]) + var/keycode = browser_keycode_to_byond(href_list["__keydown"]) + if(keycode) + keyDown(keycode) + return + if(href_list["__keyup"]) + var/keycode = browser_keycode_to_byond(href_list["__keyup"]) + if(keycode) + keyUp(keycode) + return + + // Tgui Topic middleware + if(!tgui_Topic(href_list)) + return + // Admin PM if(href_list["priv_msg"]) cmd_admin_pm(href_list["priv_msg"],null) @@ -265,9 +272,7 @@ 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) + addtimer(CALLBACK(src, .proc/ensure_keys_set), 0) //prevents possible race conditions prefs.last_ip = address //these are gonna be used for banning prefs.last_id = computer_id //these are gonna be used for banning @@ -461,11 +466,21 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) Master.UpdateTickRate() +/client/proc/ensure_keys_set() + if(SSinput.initialized) + set_macros() + update_movement_keys(prefs) + ////////////// //DISCONNECT// ////////////// /client/Del() + if(!gc_destroyed) + Destroy() + return ..() + +/client/Destroy() if(credits) QDEL_LIST(credits) log_access("Logout: [key_name(src)]") @@ -499,9 +514,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) movingmob.client_mobs_in_contents -= mob UNSETEMPTY(movingmob.client_mobs_in_contents) Master.UpdateTickRate() - return ..() - -/client/Destroy() + . = ..() return QDEL_HINT_HARDDEL_NOW /client/proc/set_client_age_from_db(connectiontopic) @@ -766,6 +779,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) ip_intel = res.intel /client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE) + if(last_click > world.time - world.tick_lag) + return + last_click = world.time var/ab = FALSE var/list/L = params2list(params) if (object && object == middragatom && L["left"]) @@ -858,8 +874,14 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) 'html/browser/playeroptions.css', ) spawn (10) //removing this spawn causes all clients to not get verbs. + + //load info on what assets the client has + src << browse('code/modules/asset_cache/validate_assets.html', "window=asset_cache_browser") + //Precache the client with all other assets slowly, so as to not block other browse() calls getFilesSlow(src, SSassets.preload, register_asset = FALSE) + addtimer(CALLBACK(GLOBAL_PROC, /proc/getFilesSlow, src, SSassets.preload, FALSE), 5 SECONDS) + #if (PRELOAD_RSC == 0) for (var/name in GLOB.vox_sounds) var/file = GLOB.vox_sounds[name] @@ -879,13 +901,13 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) /client/vv_edit_var(var_name, var_value) switch (var_name) - if ("holder") + if (NAMEOF(src, holder)) return FALSE - if ("ckey") + if (NAMEOF(src, ckey)) return FALSE - if ("key") + if (NAMEOF(src, key)) return FALSE - if("view") + if(NAMEOF(src, view)) change_view(var_value) return TRUE . = ..() @@ -971,3 +993,6 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) screen -= S qdel(S) char_render_holders = null + +/client/proc/can_have_part(part_name) + return prefs.pref_species.mutant_bodyparts[part_name] || (part_name in GLOB.unlocked_mutant_parts) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 347a77059a..2fe674e59e 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -40,7 +40,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) //If it's 0, that's good, if it's anything but 0, the owner of this prefs file's antag choices were, //autocorrected this round, not that you'd need to check that. - var/UI_style = null var/buttons_locked = FALSE var/hotkeys = FALSE @@ -83,24 +82,24 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/gender = MALE //gender of character (well duh) var/age = 30 //age of character var/underwear = "Nude" //underwear type - var/undie_color = "FFF" + var/undie_color = "FFFFFF" var/undershirt = "Nude" //undershirt type - var/shirt_color = "FFF" + var/shirt_color = "FFFFFF" var/socks = "Nude" //socks type - var/socks_color = "FFF" + var/socks_color = "FFFFFF" var/backbag = DBACKPACK //backpack type var/jumpsuit_style = PREF_SUIT //suit/skirt var/hair_style = "Bald" //Hair type - var/hair_color = "000" //Hair color + var/hair_color = "000000" //Hair color var/facial_hair_style = "Shaved" //Face hair type - var/facial_hair_color = "000" //Facial hair color + var/facial_hair_color = "000000" //Facial hair color var/skin_tone = "caucasian1" //Skin color var/use_custom_skin_tone = FALSE - var/eye_color = "000" //Eye color + var/eye_color = "000000" //Eye color var/datum/species/pref_species = new /datum/species/human() //Mutant race - var/list/features = list("mcolor" = "FFF", - "mcolor2" = "FFF", - "mcolor3" = "FFF", + var/list/features = list("mcolor" = "FFFFFF", + "mcolor2" = "FFFFFF", + "mcolor3" = "FFFFFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", @@ -131,23 +130,23 @@ GLOBAL_LIST_EMPTY(preferences_datums) "cock_shape" = DEF_COCK_SHAPE, "cock_length" = COCK_SIZE_DEF, "cock_diameter_ratio" = COCK_DIAMETER_RATIO_DEF, - "cock_color" = "fff", + "cock_color" = "ffffff", "cock_taur" = FALSE, "has_balls" = FALSE, - "balls_color" = "fff", + "balls_color" = "ffffff", "balls_shape" = DEF_BALLS_SHAPE, "balls_size" = BALLS_SIZE_DEF, "balls_cum_rate" = CUM_RATE, "balls_cum_mult" = CUM_RATE_MULT, "balls_efficiency" = CUM_EFFICIENCY, "has_breasts" = FALSE, - "breasts_color" = "fff", + "breasts_color" = "ffffff", "breasts_size" = BREASTS_SIZE_DEF, "breasts_shape" = DEF_BREASTS_SHAPE, "breasts_producing" = FALSE, "has_vag" = FALSE, "vag_shape" = DEF_VAGINA_SHAPE, - "vag_color" = "fff", + "vag_color" = "ffffff", "has_womb" = FALSE, "balls_visibility" = GEN_VISIBLE_NO_UNDIES, "breasts_visibility"= GEN_VISIBLE_NO_UNDIES, @@ -162,6 +161,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) "body_model" = MALE, "body_size" = RESIZE_DEFAULT_SIZE ) + var/custom_speech_verb = "default" //if your say_mod is to be something other than your races + var/custom_tongue = "default" //if your tongue is to be something other than your races + + /// Security record note section + var/security_records + /// Medical record note section + var/medical_records var/list/custom_names = list() var/preferred_ai_core_display = "Blue" @@ -223,7 +229,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/gear_points = 10 var/list/gear_categories var/list/chosen_gear = list() - var/gear_tab + var/gear_category + var/gear_subcategory var/screenshake = 100 var/damagescreenshake = 2 @@ -232,6 +239,15 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/autostand = TRUE var/auto_ooc = FALSE + /// If we have persistent scars enabled + var/persistent_scars = TRUE + /// We have 5 slots for persistent scars, if enabled we pick a random one to load (empty by default) and scars at the end of the shift if we survived as our original person + var/list/scars_list = list("1" = "", "2" = "", "3" = "", "4" = "", "5" = "") + /// Which of the 5 persistent scar slots we randomly roll to load for this round, if enabled. Actually rolled in [/datum/preferences/proc/load_character(slot)] + var/scars_index = 1 + + var/chosen_limb_id //body sprite selected to load for the users limbs, null means default, is sanitized when loaded + /datum/preferences/New(client/C) parent = C @@ -338,6 +354,24 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Custom job preferences:
    " dat += "Preferred AI Core Display: [preferred_ai_core_display]
    " dat += "Preferred Security Department: [prefered_security_department]
    " + dat += "
    Records

    " + dat += "
    Security Records
    " + if(length_char(security_records) <= 40) + if(!length(security_records)) + dat += "\[...\]" + else + dat += "[security_records]" + else + dat += "[TextPreview(security_records)]...
    " + + dat += "
    Medical Records
    " + if(length_char(medical_records) <= 40) + if(!length(medical_records)) + dat += "\[...\]
    " + else + dat += "[medical_records]" + else + dat += "[TextPreview(medical_records)]...
    " dat += "" //Character Appearance @@ -440,6 +474,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) else if(use_skintones || mutant_colors) dat += "" + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

    Speech preferences

    " + dat += "Custom Speech Verb:
    " + dat += "
    [custom_speech_verb]
    " + dat += "Custom Tongue:
    " + dat += "[custom_tongue]
    " + if(HAIR in pref_species.species_traits) dat += APPEARANCE_CATEGORY_COLUMN @@ -468,310 +509,25 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "" mutant_category = 0 - if(pref_species.mutant_bodyparts["tail_lizard"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Tail

    " - - dat += "[features["tail_lizard"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - if(pref_species.mutant_bodyparts["mam_tail"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Tail

    " - - dat += "[features["mam_tail"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["tail_human"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Tail

    " - - dat += "[features["tail_human"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - if(pref_species.mutant_bodyparts["meat_type"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Meat Type

    " - - dat += "[features["meat_type"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["snout"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Snout

    " - - dat += "[features["snout"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["horns"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Horns

    " - - dat += "[features["horns"]]" - dat += "    Change
    " - - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - if(pref_species.mutant_bodyparts["frills"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Frills

    " - - dat += "[features["frills"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - if(pref_species.mutant_bodyparts["spines"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Spines

    " - - dat += "[features["spines"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - if(pref_species.mutant_bodyparts["body_markings"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Body Markings

    " - - dat += "[features["body_markings"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["mam_body_markings"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Species Markings

    " - - dat += "[features["mam_body_markings"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - - if(pref_species.mutant_bodyparts["mam_ears"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Ears

    " - - dat += "[features["mam_ears"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - if(pref_species.mutant_bodyparts["ears"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Ears

    " - - dat += "[features["ears"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - if(pref_species.mutant_bodyparts["mam_snouts"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Snout

    " - - dat += "[features["mam_snouts"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["legs"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Legs

    " - - dat += "[features["legs"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["deco_wings"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Decorative wings

    " - - dat += "[features["deco_wings"]]" - dat += "    Change
    " - - if(pref_species.mutant_bodyparts["insect_wings"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Insect wings

    " - - dat += "[features["insect_wings"]]" - dat += "    Change
    " - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["insect_fluff"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Insect Fluff

    " - - dat += "[features["insect_fluff"]]" - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["taur"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Tauric Body

    " - - dat += "[features["taur"]]" - - if(pref_species.mutant_bodyparts["insect_markings"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Insect markings

    " - - dat += "[features["insect_markings"]]
    " - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["wings"] && GLOB.r_wings_list.len >1) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Wings

    " - - dat += "[features["wings"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["xenohead"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Caste Head

    " - - dat += "[features["xenohead"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["xenotail"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Tail

    " - - dat += "[features["xenotail"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["xenodorsal"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Dorsal Spines

    " - - dat += "[features["xenodorsal"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["ipc_screen"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Screen

    " - - dat += "[features["ipc_screen"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 - if(pref_species.mutant_bodyparts["ipc_antenna"]) - if(!mutant_category) - dat += APPEARANCE_CATEGORY_COLUMN - - dat += "

    Antenna

    " - - dat += "[features["ipc_antenna"]]" - - mutant_category++ - if(mutant_category >= MAX_MUTANT_ROWS) - dat += "" - mutant_category = 0 + for(var/mutant_part in GLOB.all_mutant_parts) + if(parent.can_have_part(mutant_part)) + if(!mutant_category) + dat += APPEARANCE_CATEGORY_COLUMN + dat += "

    [GLOB.all_mutant_parts[mutant_part]]

    " + dat += "[features[mutant_part]]" + var/color_type = GLOB.colored_mutant_parts[mutant_part] //if it can be coloured, show the appropriate button + if(color_type) + dat += "    Change
    " + mutant_category++ + if(mutant_category >= MAX_MUTANT_ROWS) + dat += "" + mutant_category = 0 + + if(length(pref_species.allowed_limb_ids)) + if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids)) + chosen_limb_id = pref_species.id + dat += "

    Body sprite

    " + dat += "[chosen_limb_id]" if(mutant_category) dat += "" @@ -793,6 +549,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Socks Color:     Change
    " dat += "Backpack:[backbag]" dat += "Jumpsuit:
    [jumpsuit_style]
    " + if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) + dat += "
    Temporal Scarring:
    [(persistent_scars) ? "Enabled" : "Disabled"]" + dat += "Clear scar slots" dat += "Uplink Location:[uplink_spawn_loc]" dat += "" @@ -814,7 +573,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/tauric_shape = FALSE if(features["cock_taur"]) var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[features["cock_shape"]] - if(P.taur_icon && pref_species.mutant_bodyparts["taur"]) + if(P.taur_icon && parent.can_have_part("taur")) var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] if(T.taur_mode & P.accepted_taurs) tauric_shape = TRUE @@ -1017,58 +776,83 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "
    " if(3) - if(!gear_tab) - gear_tab = GLOB.loadout_items[1] dat += "" dat += "" dat += "" dat += "" + dat += "" + + dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - dat += "" - for(var/j in GLOB.loadout_items[gear_tab]) - var/datum/gear/gear = GLOB.loadout_items[gear_tab][j] - var/donoritem = gear.donoritem - if(donoritem && !gear.donator_ckey_check(user.ckey)) - continue - var/class_link = "" - if(gear.type in chosen_gear) - class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=0'" - else if(gear_points <= 0) - class_link = "style='white-space:normal;' class='linkOff'" - else if(donoritem) - class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=1'" - else - class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=1'" - dat += "" - dat += "" - dat += "
    [gear_points] loadout points remaining. \[Clear Loadout\]
    You can only choose one item per category, unless it's an item that spawns in your backpack or hands.
    " - var/firstcat = TRUE - for(var/i in GLOB.loadout_items) - if(firstcat) - firstcat = FALSE + + if(!length(GLOB.loadout_items)) + dat += "
    ERROR: No loadout categories - something is horribly wrong!" + else + if(!GLOB.loadout_categories[gear_category]) + gear_category = GLOB.loadout_categories[1] + var/firstcat = TRUE + for(var/category in GLOB.loadout_categories) + if(firstcat) + firstcat = FALSE + else + dat += " |" + if(category == gear_category) + dat += " [category] " + else + dat += " [category] " + + dat += "

    " + + if(!length(GLOB.loadout_categories[gear_category])) + dat += "No subcategories detected. Something is horribly wrong!" else - dat += " |" - if(i == gear_tab) - dat += " [i] " - else - dat += " [i] " - dat += "

    [gear_tab]

    NameCostRestrictionsDescription
    [j][gear.cost]" - if(islist(gear.restricted_roles)) - if(gear.restricted_roles.len) - if(gear.restricted_desc) - dat += "" - dat += gear.restricted_desc - dat += "" + var/list/subcategories = GLOB.loadout_categories[gear_category] + if(!subcategories.Find(gear_subcategory)) + gear_subcategory = subcategories[1] + + var/firstsubcat = TRUE + for(var/subcategory in subcategories) + if(firstsubcat) + firstsubcat = FALSE else - dat += "" - dat += gear.restricted_roles.Join(";") - dat += "" - dat += "[gear.description]
    " + dat += " |" + if(gear_subcategory == subcategory) + dat += " [subcategory] " + else + dat += " [subcategory] " + dat += "" + + dat += "Name" + dat += "Cost" + dat += "Restrictions" + dat += "Description" + for(var/name in GLOB.loadout_items[gear_category][gear_subcategory]) + var/datum/gear/gear = GLOB.loadout_items[gear_category][gear_subcategory][name] + var/donoritem = gear.donoritem + if(donoritem && !gear.donator_ckey_check(user.ckey)) + continue + var/class_link = "" + if(gear.type in chosen_gear) + class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=0'" + else if(gear_points <= 0) + class_link = "style='white-space:normal;' class='linkOff'" + else if(donoritem) + class_link = "style='white-space:normal;background:#ebc42e;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" + else + class_link = "style='white-space:normal;' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(name)];toggle_gear=1'" + dat += "[name]" + dat += "[gear.cost]" + if(islist(gear.restricted_roles)) + if(gear.restricted_roles.len) + if(gear.restricted_desc) + dat += "" + dat += gear.restricted_desc + dat += "" + else + dat += "" + dat += gear.restricted_roles.Join(";") + dat += "" + dat += "[gear.description]" + dat += "" if(4) // Content preferences dat += "
    " dat += "

    Fetish content prefs

    " @@ -1086,8 +870,8 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Breast Enlargement: [(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]
    " dat += "Penis Enlargement: [(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]
    " dat += "Hypno: [(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]
    " - dat += "Aphrodisiacs: [(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]
    " dat += "Ass Slapping: [(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]
    " + dat += "Automatic Wagging: [(cit_toggles & NO_AUTO_WAG) ? "Disabled" : "Enabled"]
    " dat += "
    " dat += "
    " if(5) // Custom keybindings @@ -1637,6 +1421,16 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_age) age = max(min( round(text2num(new_age)), AGE_MAX),AGE_MIN) + if("security_records") + var/rec = stripped_multiline_input(usr, "Set your security record note section. This should be IC!", "Security Records", html_decode(security_records), MAX_FLAVOR_LEN, TRUE) + if(!isnull(rec)) + security_records = rec + + if("medical_records") + var/rec = stripped_multiline_input(usr, "Set your medical record note section. This should be IC!", "Security Records", html_decode(medical_records), MAX_FLAVOR_LEN, TRUE) + if(!isnull(rec)) + medical_records = rec + if("flavor_text") var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(features["flavor_text"]), MAX_FLAVOR_LEN, TRUE) if(!isnull(msg)) @@ -1655,7 +1449,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("hair") var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null if(new_hair) - hair_color = sanitize_hexcolor(new_hair) + hair_color = sanitize_hexcolor(new_hair, 6) if("hair_style") var/new_hair_style @@ -1672,7 +1466,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("facial") var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference","#"+facial_hair_color) as color|null if(new_facial) - facial_hair_color = sanitize_hexcolor(new_facial) + facial_hair_color = sanitize_hexcolor(new_facial, 6) if("facial_hair_style") var/new_facial_hair_style @@ -1697,7 +1491,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("undie_color") var/n_undie_color = input(user, "Choose your underwear's color.", "Character Preference", "#[undie_color]") as color|null if(n_undie_color) - undie_color = sanitize_hexcolor(n_undie_color) + undie_color = sanitize_hexcolor(n_undie_color, 6) if("undershirt") var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_list @@ -1707,7 +1501,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("shirt_color") var/n_shirt_color = input(user, "Choose your undershirt's color.", "Character Preference", "#[shirt_color]") as color|null if(n_shirt_color) - shirt_color = sanitize_hexcolor(n_shirt_color) + shirt_color = sanitize_hexcolor(n_shirt_color, 6) if("socks") var/new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list @@ -1717,12 +1511,12 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("socks_color") var/n_socks_color = input(user, "Choose your socks' color.", "Character Preference", "#[socks_color]") as color|null if(n_socks_color) - socks_color = sanitize_hexcolor(n_socks_color) + socks_color = sanitize_hexcolor(n_socks_color, 6) if("eyes") var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null if(new_eyes) - eye_color = sanitize_hexcolor(new_eyes) + eye_color = sanitize_hexcolor(new_eyes, 6) if("species") var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_race_names @@ -1731,14 +1525,14 @@ GLOBAL_LIST_EMPTY(preferences_datums) pref_species = new newtype() //let's ensure that no weird shit happens on species swapping. custom_species = null - if(!pref_species.mutant_bodyparts["body_markings"]) + if(!parent.can_have_part("body_markings")) features["body_markings"] = "None" - if(!pref_species.mutant_bodyparts["mam_body_markings"]) + if(!parent.can_have_part("mam_body_markings")) features["mam_body_markings"] = "None" - if(pref_species.mutant_bodyparts["mam_body_markings"]) + if(parent.can_have_part("mam_body_markings")) if(features["mam_body_markings"] == "None") features["mam_body_markings"] = "Plain" - if(pref_species.mutant_bodyparts["tail_lizard"]) + if(parent.can_have_part("tail_lizard")) features["tail_lizard"] = "Smooth" if(pref_species.id == "felinid") features["mam_tail"] = "Cat" @@ -1746,11 +1540,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) //Now that we changed our species, we must verify that the mutant colour is still allowed. var/temp_hsv = RGBtoHSV(features["mcolor"]) - if(features["mcolor"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])) + if(features["mcolor"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])) features["mcolor"] = pref_species.default_color - if(features["mcolor2"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])) + if(features["mcolor2"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])) features["mcolor2"] = pref_species.default_color - if(features["mcolor3"] == "#000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])) + if(features["mcolor3"] == "#000000" || (!(MUTCOLORS_PARTSONLY in pref_species.species_traits) && ReadHSV(temp_hsv)[3] < ReadHSV("#202020")[3])) features["mcolor3"] = pref_species.default_color if("custom_species") @@ -1767,7 +1561,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_mutantcolor == "#000000") features["mcolor"] = pref_species.default_color else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin - features["mcolor"] = sanitize_hexcolor(new_mutantcolor) + features["mcolor"] = sanitize_hexcolor(new_mutantcolor, 6) else to_chat(user, "Invalid color. Your color is not bright enough.") @@ -1778,7 +1572,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_mutantcolor == "#000000") features["mcolor2"] = pref_species.default_color else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin - features["mcolor2"] = sanitize_hexcolor(new_mutantcolor) + features["mcolor2"] = sanitize_hexcolor(new_mutantcolor, 6) else to_chat(user, "Invalid color. Your color is not bright enough.") @@ -1789,7 +1583,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_mutantcolor == "#000000") features["mcolor3"] = pref_species.default_color else if((MUTCOLORS_PARTSONLY in pref_species.species_traits) || ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) // mutantcolors must be bright, but only if they affect the skin - features["mcolor3"] = sanitize_hexcolor(new_mutantcolor) + features["mcolor3"] = sanitize_hexcolor(new_mutantcolor, 6) else to_chat(user, "Invalid color. Your color is not bright enough.") @@ -1850,7 +1644,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("mam_tail") var/list/snowflake_tails_list = list() for(var/path in GLOB.mam_tails_list) - var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[path] + var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id)) @@ -1866,7 +1660,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) features["tail_human"] = "None" features["tail_lizard"] = "None" - if("meats") + if("meat_type") var/new_meat new_meat = input(user, "Choose your character's meat type:", "Character Preference") as null|anything in GLOB.meat_types if(new_meat) @@ -1875,7 +1669,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("snout") var/list/snowflake_snouts_list = list() for(var/path in GLOB.snouts_list) - var/datum/sprite_accessory/mam_snouts/instance = GLOB.snouts_list[path] + var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.snouts_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id)) @@ -1892,7 +1686,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("mam_snouts") var/list/snowflake_mam_snouts_list = list() for(var/path in GLOB.mam_snouts_list) - var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[path] + var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id)) @@ -1917,7 +1711,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if (new_horn_color == "#000000") features["horns_color"] = "85615A" else - features["horns_color"] = sanitize_hexcolor(new_horn_color) + features["horns_color"] = sanitize_hexcolor(new_horn_color, 6) if("wings") var/new_wings @@ -1931,7 +1725,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if (new_wing_color == "#000000") features["wings_color"] = "#FFFFFF" else - features["wings_color"] = sanitize_hexcolor(new_wing_color) + features["wings_color"] = sanitize_hexcolor(new_wing_color, 6) if("frills") var/new_frills @@ -1971,7 +1765,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_deco_wings) features["deco_wings"] = new_deco_wings - if("insect_fluffs") + if("insect_fluff") var/new_insect_fluff new_insect_fluff = input(user, "Choose your character's wings:", "Character Preference") as null|anything in GLOB.insect_fluffs_list if(new_insect_fluff) @@ -2041,7 +1835,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("mam_ears") var/list/snowflake_ears_list = list() for(var/path in GLOB.mam_ears_list) - var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[path] + var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if(!show_mismatched_markings && S.recommended_species && !S.recommended_species.Find(pref_species.id)) @@ -2105,7 +1899,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_cockcolor == "#000000") features["cock_color"] = pref_species.default_color else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) - features["cock_color"] = sanitize_hexcolor(new_cockcolor) + features["cock_color"] = sanitize_hexcolor(new_cockcolor, 6) else to_chat(user,"Invalid color. Your color is not bright enough.") @@ -2119,7 +1913,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("cock_shape") var/new_shape var/list/hockeys = list() - if(pref_species.mutant_bodyparts["taur"]) + if(parent.can_have_part("taur")) var/datum/sprite_accessory/taur/T = GLOB.taur_list[features["taur"]] for(var/A in GLOB.cock_shapes_list) var/datum/sprite_accessory/penis/P = GLOB.cock_shapes_list[A] @@ -2145,7 +1939,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_ballscolor == "#000000") features["balls_color"] = pref_species.default_color else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) - features["balls_color"] = sanitize_hexcolor(new_ballscolor) + features["balls_color"] = sanitize_hexcolor(new_ballscolor, 6) else to_chat(user,"Invalid color. Your color is not bright enough.") @@ -2172,7 +1966,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_breasts_color == "#000000") features["breasts_color"] = pref_species.default_color else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) - features["breasts_color"] = sanitize_hexcolor(new_breasts_color) + features["breasts_color"] = sanitize_hexcolor(new_breasts_color, 6) else to_chat(user,"Invalid color. Your color is not bright enough.") @@ -2194,7 +1988,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(new_vagcolor == "#000000") features["vag_color"] = pref_species.default_color else if(ReadHSV(temp_hsv)[3] >= ReadHSV("#202020")[3]) - features["vag_color"] = sanitize_hexcolor(new_vagcolor) + features["vag_color"] = sanitize_hexcolor(new_vagcolor, 6) else to_chat(user,"Invalid color. Your color is not bright enough.") @@ -2306,24 +2100,36 @@ GLOBAL_LIST_EMPTY(preferences_datums) else features["body_model"] = chosengender gender = chosengender - facial_hair_style = random_facial_hair_style(gender) - hair_style = random_hair_style(gender) if("body_size") var/min = CONFIG_GET(number/body_size_min) var/max = CONFIG_GET(number/body_size_max) var/danger = CONFIG_GET(number/threshold_body_size_slowdown) - var/new_body_size = input(user, "Choose your desired sprite size:\n([min*100]%-[max*100]%), Warning: May make your character look distorted[danger > min ? ", and an exponential slowdown will occur for those smaller than [danger*100]%!" : "!"]", "Character Preference", features["body_size"]*100) as num|null + var/new_body_size = input(user, "Choose your desired sprite size: ([min*100]%-[max*100]%)\nWarning: This may make your character look distorted[danger > min ? "! Additionally, a proportional movement speed penalty will be applied to characters smaller than [danger*100]%." : "!"]", "Character Preference", features["body_size"]*100) as num|null if (new_body_size) new_body_size = clamp(new_body_size * 0.01, min, max) var/dorfy - if(danger > new_body_size) - dorfy = alert(user, "The chosen size appears to be smaller than the threshold of [danger*100]%, which will lead to an added exponential slowdown. Are you sure about that?", "Dwarfism Alert", "Yes", "Move it to the threshold", "No") - if(!dorfy || dorfy == "Move it above the threshold") + if((new_body_size + 0.01) < danger) // Adding 0.01 as a dumb fix to prevent the warning message from appearing when exactly at threshold... Not sure why that happens in the first place. + dorfy = alert(user, "You have chosen a size below the slowdown threshold of [danger*100]%. For balancing purposes, the further you go below this percentage, the slower your character will be. Do you wish to keep this size?", "Speed Penalty Alert", "Yes", "Move it to the threshold", "No") + if(dorfy == "Move it to the threshold") new_body_size = danger + if(!dorfy) //Aborts if this var is somehow empty + return if(dorfy != "No") features["body_size"] = new_body_size + if("tongue") + var/selected_custom_tongue = input(user, "Choose your desired tongue (none means your species tongue)", "Character Preference") as null|anything in GLOB.roundstart_tongues + if(selected_custom_tongue) + custom_tongue = selected_custom_tongue + if("speech_verb") + var/selected_custom_speech_verb = input(user, "Choose your desired speech verb (none means your species speech verb)", "Character Preference") as null|anything in GLOB.speech_verbs + if(selected_custom_speech_verb) + custom_speech_verb = selected_custom_speech_verb + if("bodysprite") + var/selected_body_sprite = input(user, "Choose your desired body sprite", "Character Preference") as null|anything in pref_species.allowed_limb_ids + if(selected_body_sprite) + chosen_limb_id = selected_body_sprite //this gets sanitized before loading else switch(href_list["preference"]) //CITADEL PREFERENCES EDIT - I can't figure out how to modularize these, so they have to go here. :c -Pooj @@ -2494,6 +2300,17 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("hear_midis") toggles ^= SOUND_MIDI + if("persistent_scars") + persistent_scars = !persistent_scars + + if("clear_scars") + to_chat(user, "All scar slots cleared. Please save character to confirm.") + scars_list["1"] = "" + scars_list["2"] = "" + scars_list["3"] = "" + scars_list["4"] = "" + scars_list["5"] = "" + if("lobby_music") toggles ^= SOUND_LOBBY if((toggles & SOUND_LOBBY) && user.client && isnewplayer(user)) @@ -2572,6 +2389,9 @@ GLOBAL_LIST_EMPTY(preferences_datums) if("bimbo") cit_toggles ^= BIMBOFICATION + if("auto_wag") + cit_toggles ^= NO_AUTO_WAG + //END CITADEL EDIT if("ambientocclusion") @@ -2615,11 +2435,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) gear_points = CONFIG_GET(number/initial_gear_points) save_preferences() if(href_list["select_category"]) - for(var/i in GLOB.loadout_items) - if(i == href_list["select_category"]) - gear_tab = i + gear_category = html_decode(href_list["select_category"]) + gear_subcategory = GLOB.loadout_categories[gear_category][1] + if(href_list["select_subcategory"]) + gear_subcategory = html_decode(href_list["select_subcategory"]) if(href_list["toggle_gear_path"]) - var/datum/gear/G = GLOB.loadout_items[gear_tab][html_decode(href_list["toggle_gear_path"])] + var/name = html_decode(href_list["toggle_gear_path"]) + var/datum/gear/G = GLOB.loadout_items[gear_category][gear_subcategory][name] if(!G) return var/toggle = text2num(href_list["toggle_gear"]) @@ -2699,14 +2521,16 @@ GLOBAL_LIST_EMPTY(preferences_datums) character.dna.features = features.Copy() character.set_species(chosen_species, icon_update = FALSE, pref_load = TRUE) + if(chosen_limb_id && (chosen_limb_id in character.dna.species.allowed_limb_ids)) + character.dna.species.mutant_bodyparts["limbs_id"] = chosen_limb_id character.dna.real_name = character.real_name character.dna.nameless = character.nameless character.dna.custom_species = character.custom_species - if(pref_species.mutant_bodyparts["meat_type"]) + if((parent && parent.can_have_part("meat_type")) || pref_species.mutant_bodyparts["meat_type"]) character.type_of_meat = GLOB.meat_types[features["meat_type"]] - if(character.dna.species.mutant_bodyparts["legs"] && (character.dna.features["legs"] == "Digitigrade" || character.dna.features["legs"] == "Avian")) + if(((parent && parent.can_have_part("legs")) || pref_species.mutant_bodyparts["legs"]) && (character.dna.features["legs"] == "Digitigrade" || character.dna.features["legs"] == "Avian")) pref_species.species_traits |= DIGITIGRADE else pref_species.species_traits -= DIGITIGRADE @@ -2720,6 +2544,20 @@ GLOBAL_LIST_EMPTY(preferences_datums) character.dna.update_body_size(old_size) + //speech stuff + if(custom_tongue != "default") + var/new_tongue = GLOB.roundstart_tongues[custom_tongue] + if(new_tongue) + character.dna.species.mutanttongue = new_tongue //this means we get our tongue when we clone + var/obj/item/organ/tongue/T = character.getorganslot(ORGAN_SLOT_TONGUE) + if(T) + qdel(T) + var/obj/item/organ/tongue/new_custom_tongue = new new_tongue + new_custom_tongue.Insert(character) + if(custom_speech_verb != "default") + character.dna.species.say_mod = custom_speech_verb + + SEND_SIGNAL(character, COMSIG_HUMAN_PREFS_COPIED_TO, src, icon_updates, roundstart_checks) //let's be sure the character updates @@ -2785,17 +2623,17 @@ GLOBAL_LIST_EMPTY(preferences_datums) 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) + var/occupied_slots = L[initial(G.category)] ? L[initial(G.category)] + 1 : 1 + LAZYSET(L, initial(G.category), occupied_slots) switch(slot) if(SLOT_IN_BACKPACK) - if(L[slot_to_string(SLOT_IN_BACKPACK)] < BACKPACK_SLOT_AMT) + if(L[LOADOUT_CATEGORY_BACKPACK] < BACKPACK_SLOT_AMT) return TRUE if(SLOT_HANDS) - if(L[slot_to_string(SLOT_HANDS)] < HANDS_SLOT_AMT) + if(L[LOADOUT_CATEGORY_HANDS] < HANDS_SLOT_AMT) return TRUE else - if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT) + if(L[slot] < DEFAULT_SLOT_AMT) return TRUE #undef DEFAULT_SLOT_AMT diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index 1ec3fc6404..55a594cf21 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 33 +#define SAVEFILE_VERSION_MAX 35 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -194,12 +194,16 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(current_version < 31) S["wing_color"] >> features["wings_color"] S["horn_color"] >> features["horns_color"] - + if(current_version < 33) features["flavor_text"] = html_encode(features["flavor_text"]) features["silicon_flavor_text"] = html_encode(features["silicon_flavor_text"]) features["ooc_notes"] = html_encode(features["ooc_notes"]) + if(current_version < 35) + if(S["species"] == "lizard") + features["mam_snouts"] = features["snout"] + /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) return @@ -225,6 +229,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(needs_update == -2) //fatal, can't load any data return 0 + . = TRUE + //general preferences S["ooccolor"] >> ooccolor S["lastchangelog"] >> lastchangelog @@ -440,6 +446,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(needs_update == -2) //fatal, can't load any data return 0 + . = TRUE + //Species var/species_id S["species"] >> species_id @@ -453,6 +461,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(newtype) pref_species = new newtype + + scars_index = rand(1,5) + //Character S["real_name"] >> real_name S["nameless"] >> nameless @@ -479,6 +490,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["backbag"] >> backbag S["jumpsuit_style"] >> jumpsuit_style S["uplink_loc"] >> uplink_spawn_loc + S["custom_speech_verb"] >> custom_speech_verb + S["custom_tongue"] >> custom_tongue S["feature_mcolor"] >> features["mcolor"] S["feature_lizard_tail"] >> features["tail_lizard"] S["feature_lizard_snout"] >> features["snout"] @@ -495,6 +508,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["feature_insect_markings"] >> features["insect_markings"] S["feature_horns_color"] >> features["horns_color"] S["feature_wings_color"] >> features["wings_color"] + S["persistent_scars"] >> persistent_scars + S["scars1"] >> scars_list["1"] + S["scars2"] >> scars_list["2"] + S["scars3"] >> scars_list["3"] + S["scars4"] >> scars_list["4"] + S["scars5"] >> scars_list["5"] + S["chosen_limb_id"] >> chosen_limb_id //Custom names @@ -513,6 +533,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car //Quirks S["all_quirks"] >> all_quirks + //Records + S["security_records"] >> security_records + S["medical_records"] >> medical_records + //Citadel code S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"] S["feature_mcolor2"] >> features["mcolor2"] @@ -617,14 +641,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list) underwear = sanitize_inlist(underwear, GLOB.underwear_list) undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list) - undie_color = sanitize_hexcolor(undie_color, 3, FALSE, initial(undie_color)) - shirt_color = sanitize_hexcolor(shirt_color, 3, FALSE, initial(shirt_color)) + undie_color = sanitize_hexcolor(undie_color, 6, FALSE, initial(undie_color)) + shirt_color = sanitize_hexcolor(shirt_color, 6, FALSE, initial(shirt_color)) socks = sanitize_inlist(socks, GLOB.socks_list) - socks_color = sanitize_hexcolor(socks_color, 3, FALSE, initial(socks_color)) + socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color)) age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age)) - hair_color = sanitize_hexcolor(hair_color, 3, 0) - facial_hair_color = sanitize_hexcolor(facial_hair_color, 3, 0) - eye_color = sanitize_hexcolor(eye_color, 3, 0) + hair_color = sanitize_hexcolor(hair_color, 6, FALSE) + facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE) + eye_color = sanitize_hexcolor(eye_color, 6, FALSE) var/static/allow_custom_skintones if(isnull(allow_custom_skintones)) @@ -635,12 +659,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car else skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones - GLOB.nonstandard_skin_tones, initial(skin_tone)) - features["horns_color"] = sanitize_hexcolor(features["horns_color"], 3, FALSE, "85615a") - features["wings_color"] = sanitize_hexcolor(features["wings_color"], 3, FALSE, "FFFFFF") + features["horns_color"] = sanitize_hexcolor(features["horns_color"], 6, FALSE, "85615a") + features["wings_color"] = sanitize_hexcolor(features["wings_color"], 6, FALSE, "FFFFFF") backbag = sanitize_inlist(backbag, GLOB.backbaglist, initial(backbag)) jumpsuit_style = sanitize_inlist(jumpsuit_style, GLOB.jumpsuitlist, initial(jumpsuit_style)) uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc)) - features["mcolor"] = sanitize_hexcolor(features["mcolor"], 3, 0) + features["mcolor"] = sanitize_hexcolor(features["mcolor"], 6, FALSE) features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard) features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human) features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list) @@ -684,20 +708,32 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car features["cock_shape"] = sanitize_inlist(features["cock_shape"], GLOB.cock_shapes_list, DEF_COCK_SHAPE) features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE) features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE) - features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 3, FALSE, "FFF") - features["cock_color"] = sanitize_hexcolor(features["cock_color"], 3, FALSE, "FFF") - features["balls_color"] = sanitize_hexcolor(features["balls_color"], 3, FALSE, "FFF") - features["vag_color"] = sanitize_hexcolor(features["vag_color"], 3, FALSE, "FFF") + features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 6, FALSE, "FFFFFF") + features["cock_color"] = sanitize_hexcolor(features["cock_color"], 6, FALSE, "FFFFFF") + features["balls_color"] = sanitize_hexcolor(features["balls_color"], 6, FALSE, "FFFFFF") + features["vag_color"] = sanitize_hexcolor(features["vag_color"], 6, FALSE, "FFFFFF") features["breasts_visibility"] = sanitize_inlist(features["breasts_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES) features["cock_visibility"] = sanitize_inlist(features["cock_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES) features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES) features["vag_visibility"] = sanitize_inlist(features["vag_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES) + custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default") + custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default") + + security_records = copytext(security_records, 1, MAX_FLAVOR_LEN) + medical_records = copytext(medical_records, 1, MAX_FLAVOR_LEN) features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN) features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN) features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN) + persistent_scars = sanitize_integer(persistent_scars) + scars_list["1"] = sanitize_text(scars_list["1"]) + scars_list["2"] = sanitize_text(scars_list["2"]) + scars_list["3"] = sanitize_text(scars_list["3"]) + scars_list["4"] = sanitize_text(scars_list["4"]) + scars_list["5"] = sanitize_text(scars_list["5"]) + joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole)) //Validate job prefs for(var/j in job_preferences) @@ -756,6 +792,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["jumpsuit_style"] , jumpsuit_style) WRITE_FILE(S["uplink_loc"] , uplink_spawn_loc) WRITE_FILE(S["species"] , pref_species.id) + WRITE_FILE(S["custom_speech_verb"] , custom_speech_verb) + WRITE_FILE(S["custom_tongue"] , custom_tongue) + + // records + WRITE_FILE(S["security_records"] , security_records) + WRITE_FILE(S["medical_records"] , medical_records) + WRITE_FILE(S["feature_mcolor"] , features["mcolor"]) WRITE_FILE(S["feature_lizard_tail"] , features["tail_lizard"]) WRITE_FILE(S["feature_human_tail"] , features["tail_human"]) @@ -802,6 +845,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_ooc_notes"], features["ooc_notes"]) + WRITE_FILE(S["chosen_limb_id"], chosen_limb_id) + //Custom names for(var/custom_name_id in GLOB.preferences_custom_names) var/savefile_slot_name = custom_name_id + "_name" //TODO remove this @@ -822,6 +867,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) + WRITE_FILE(S["persistent_scars"] , persistent_scars) + WRITE_FILE(S["scars1"] , scars_list["1"]) + WRITE_FILE(S["scars2"] , scars_list["2"]) + WRITE_FILE(S["scars3"] , scars_list["3"]) + WRITE_FILE(S["scars4"] , scars_list["4"]) + WRITE_FILE(S["scars5"] , scars_list["5"]) + //gear loadout if(chosen_gear.len) var/text_to_save = chosen_gear.Join("|") diff --git a/code/modules/client/verbs/autobunker.dm b/code/modules/client/verbs/autobunker.dm new file mode 100644 index 0000000000..03200c5f0b --- /dev/null +++ b/code/modules/client/verbs/autobunker.dm @@ -0,0 +1,37 @@ +/client/verb/bunker_auto_authorize() + set name = "Auto Authorize Panic Bunker" + set desc = "Authorizes your account in the panic bunker of any servers connected to this function." + set category = "OOC" + + if(autobunker_last_try + 5 SECONDS > world.time) + to_chat(src, "Function on cooldown, try again in 5 seconds.") + return + autobunker_last_try = world.time + + world.send_cross_server_bunker_overrides(key, src) + +/world/proc/send_cross_server_bunker_overrides(key, client/C) + var/comms_key = CONFIG_GET(string/comms_key) + if(!comms_key) + return + var/list/message = list() + message["ckey"] = key + message["source"] = "[CONFIG_GET(string/cross_comms_name)]" + message["key"] = comms_key + message["auto_bunker_override"] = TRUE + var/list/servers = CONFIG_GET(keyed_list/cross_server_bunker_override) + if(!length(servers)) + to_chat(C, "AUTOBUNKER: No servers are configured to receive from this one.") + return + log_admin("[key] ([key_name(C)]) has initiated an autobunker authentication with linked servers.") + for(var/name in servers) + var/returned = world.Export("[servers[name]]?[list2params(message)]") + switch(returned) + if("Bad Key") + to_chat(C, "AUTOBuNKER: [name] failed to authenticate with this server.") + if("Function Disabled") + to_chat(C, "AUTOBUNKER: [name] has autobunker receive disabled.") + if("Success") + to_chat(C, "AUTOBUNKER: Successfully authenticated with [name]. Panic bunker bypass granted to [key]..") + else + to_chat(C, "AUTOBUNKER: Unknown error ([name]).") diff --git a/code/modules/client/verbs/minimap.dm b/code/modules/client/verbs/minimap.dm index 3d213dc210..3cdb1d57a8 100644 --- a/code/modules/client/verbs/minimap.dm +++ b/code/modules/client/verbs/minimap.dm @@ -6,5 +6,7 @@ if(!CONFIG_GET(flag/minimaps_enabled)) to_chat(usr, "Minimap generation is not enabled in the server's configuration.") return - + if(!SSminimaps.station_minimap) + to_chat(usr, "Minimap generation is in progress, please wait!") + return SSminimaps.station_minimap.show(src) diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index a28061db10..2fbe738acb 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -4,7 +4,7 @@ max_integrity = 200 integrity_failure = 0.4 block_priority = BLOCK_PRIORITY_CLOTHING - var/damaged_clothes = 0 //similar to machine's BROKEN stat and structure's broken var + var/damaged_clothes = CLOTHING_PRISTINE //similar to machine's BROKEN stat and structure's broken var var/flash_protect = 0 //What level of bright light protection item has. 1 = Flashers, Flashes, & Flashbangs | 2 = Welding | -1 = OH GOD WELDING BURNT OUT MY RETINAS var/tint = 0 //Sets the item's level of visual impairment tint, normally set to the same as flash_protect var/up = 0 //but separated to allow items to protect but not impair vision, like space helmets @@ -28,6 +28,9 @@ var/clothing_flags = NONE + // What items can be consumed to repair this clothing (must by an /obj/item/stack) + var/repairable_by = /obj/item/stack/sheet/cloth + //Var modification - PLEASE be careful with this I know who you are and where you live var/list/user_vars_to_edit //VARNAME = VARVALUE eg: "name" = "butts" var/list/user_vars_remembered //Auto built by the above + dropped() + equipped() @@ -45,7 +48,20 @@ var/list/species_restricted = null //Basically syntax is species_restricted = list("Species Name","Species Name") //Add a "exclude" string to do the opposite, making it only only species listed that can't wear it. - //You append this to clothing objects. + //You append this to clothing objects + + + + // How much clothing damage has been dealt to each of the limbs of the clothing, assuming it covers more than one limb + var/list/damage_by_parts + // How much integrity is in a specific limb before that limb is disabled (for use in [/obj/item/clothing/proc/take_damage_zone], and only if we cover multiple zones.) Set to 0 to disable shredding. + var/limb_integrity = 0 + // How many zones (body parts, not precise) we have disabled so far, for naming purposes + var/zones_disabled + ///These are armor values that protect the wearer, taken from the clothing's armor datum. List updates on examine because it's currently only used to print armor ratings to chat in Topic(). + var/list/armor_list = list() + ///These are armor values that protect the clothing, taken from its armor datum. List updates on examine because it's currently only used to print armor ratings to chat in Topic(). + var/list/durability_list = list() /obj/item/clothing/Initialize() . = ..() @@ -73,7 +89,7 @@ tastes = list("dust" = 1, "lint" = 1) /obj/item/clothing/attack(mob/M, mob/user, def_zone) - if(user.a_intent != INTENT_HARM && ismoth(M)) + if(user.a_intent != INTENT_HARM && isinsect(M)) var/obj/item/reagent_containers/food/snacks/clothing/clothing_as_food = new clothing_as_food.name = name if(clothing_as_food.attack(M, user, def_zone)) @@ -83,15 +99,104 @@ return ..() /obj/item/clothing/attackby(obj/item/W, mob/user, params) - if(damaged_clothes && istype(W, /obj/item/stack/sheet/cloth)) - var/obj/item/stack/sheet/cloth/C = W - C.use(1) - update_clothes_damaged_state(FALSE) - obj_integrity = max_integrity - to_chat(user, "You fix the damage on [src] with [C].") + if(damaged_clothes && istype(W, repairable_by)) + var/obj/item/stack/S = W + switch(damaged_clothes) + if(CLOTHING_DAMAGED) + S.use(1) + repair(user, params) + if(CLOTHING_SHREDDED) + if(S.amount < 3) + to_chat(user, "You require 3 [S.name] to repair [src].") + return + to_chat(user, "You begin fixing the damage to [src] with [S]...") + if(do_after(user, 6 SECONDS, TRUE, src)) + if(S.use(3)) + repair(user, params) return 1 return ..() +// Set the clothing's integrity back to 100%, remove all damage to bodyparts, and generally fix it up +/obj/item/clothing/proc/repair(mob/user, params) + update_clothes_damaged_state(CLOTHING_PRISTINE) + obj_integrity = max_integrity + name = initial(name) // remove "tattered" or "shredded" if there's a prefix + body_parts_covered = initial(body_parts_covered) + slot_flags = initial(slot_flags) + damage_by_parts = null + if(user) + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) + to_chat(user, "You fix the damage on [src].") + +/** + * take_damage_zone() is used for dealing damage to specific bodyparts on a worn piece of clothing, meant to be called from [/obj/item/bodypart/proc/check_woundings_mods()] + * + * This proc only matters when a bodypart that this clothing is covering is harmed by a direct attack (being on fire or in space need not apply), and only if this clothing covers + * more than one bodypart to begin with. No point in tracking damage by zone for a hat, and I'm not cruel enough to let you fully break them in a few shots. + * Also if limb_integrity is 0, then this clothing doesn't have bodypart damage enabled so skip it. + * + * Arguments: + * * def_zone: The bodypart zone in question + * * damage_amount: Incoming damage + * * damage_type: BRUTE or BURN + * * armour_penetration: If the attack had armour_penetration + */ +/obj/item/clothing/proc/take_damage_zone(def_zone, damage_amount, damage_type, armour_penetration) + if(!def_zone || !limb_integrity || (initial(body_parts_covered) in GLOB.bitflags)) // the second check sees if we only cover one bodypart anyway and don't need to bother with this + return + var/list/covered_limbs = body_parts_covered2organ_names(body_parts_covered) // what do we actually cover? + if(!(def_zone in covered_limbs)) + return + + var/damage_dealt = take_damage(damage_amount * 0.1, damage_type, armour_penetration, FALSE) * 10 // only deal 10% of the damage to the general integrity damage, then multiply it by 10 so we know how much to deal to limb + LAZYINITLIST(damage_by_parts) + damage_by_parts[def_zone] += damage_dealt + if(damage_by_parts[def_zone] > limb_integrity) + disable_zone(def_zone, damage_type) + +/** + * disable_zone() is used to disable a given bodypart's protection on our clothing item, mainly from [/obj/item/clothing/proc/take_damage_zone()] + * + * This proc disables all protection on the specified bodypart for this piece of clothing: it'll be as if it doesn't cover it at all anymore (because it won't!) + * If every possible bodypart has been disabled on the clothing, we put it out of commission entirely and mark it as shredded, whereby it will have to be repaired in + * order to equip it again. Also note we only consider it damaged if there's more than one bodypart disabled. + * + * Arguments: + * * def_zone: The bodypart zone we're disabling + * * damage_type: Only really relevant for the verb for describing the breaking, and maybe obj_destruction() + */ +/obj/item/clothing/proc/disable_zone(def_zone, damage_type) + var/list/covered_limbs = body_parts_covered2organ_names(body_parts_covered) + if(!(def_zone in covered_limbs)) + return + + var/zone_name = parse_zone(def_zone) + var/break_verb = ((damage_type == BRUTE) ? "torn" : "burned") + + if(iscarbon(loc)) + var/mob/living/carbon/C = loc + C.visible_message("The [zone_name] on [C]'s [src.name] is [break_verb] away!", "The [zone_name] on your [src.name] is [break_verb] away!", vision_distance = COMBAT_MESSAGE_RANGE) + RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/bristle) + + zones_disabled++ + for(var/i in zone2body_parts_covered(def_zone)) + body_parts_covered &= ~i + + if(body_parts_covered == NONE) // if there are no more parts to break then the whole thing is kaput + obj_destruction((damage_type == BRUTE ? "melee" : "laser")) // melee/laser is good enough since this only procs from direct attacks anyway and not from fire/bombs + return + + damaged_clothes = CLOTHING_DAMAGED + switch(zones_disabled) + if(1) + name = "damaged [initial(name)]" + if(2) + name = "mangy [initial(name)]" + if(3 to INFINITY) // take better care of your shit, dude + name = "tattered [initial(name)]" + + update_clothes_damaged_state(CLOTHING_DAMAGED) + /obj/item/clothing/Destroy() user_vars_remembered = null //Oh god somebody put REFERENCES in here? not to worry, we'll clean it up return ..() @@ -100,6 +205,7 @@ ..() if(!istype(user)) return + UnregisterSignal(user, COMSIG_MOVABLE_MOVED) if(LAZYLEN(user_vars_remembered)) for(var/variable in user_vars_remembered) if(variable in user.vars) @@ -112,7 +218,9 @@ if (!istype(user)) return if(slot_flags & slotdefine2slotbit(slot)) //Was equipped to a valid slot for this item? - if (LAZYLEN(user_vars_to_edit)) + if(iscarbon(user) && LAZYLEN(zones_disabled)) + RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/bristle) + if(LAZYLEN(user_vars_to_edit)) for(var/variable in user_vars_to_edit) if(variable in user.vars) LAZYSET(user_vars_remembered, variable, user.vars[variable]) @@ -120,8 +228,19 @@ /obj/item/clothing/examine(mob/user) . = ..() - if(damaged_clothes) - . += "It looks damaged!" + if(damaged_clothes == CLOTHING_SHREDDED) + . += "It is completely shredded and requires mending before it can be worn again!" + return + for(var/zone in damage_by_parts) + var/pct_damage_part = damage_by_parts[zone] / limb_integrity * 100 + var/zone_name = parse_zone(zone) + switch(pct_damage_part) + if(100 to INFINITY) + . += "The [zone_name] is useless and requires mending!" + if(60 to 99) + . += "The [zone_name] is heavily shredded!" + if(30 to 59) + . += "The [zone_name] is partially shredded." var/datum/component/storage/pockets = GetComponent(/datum/component/storage) if(pockets) var/list/how_cool_are_your_threads = list("") @@ -138,18 +257,104 @@ how_cool_are_your_threads += "" . += how_cool_are_your_threads.Join() + if(LAZYLEN(armor_list)) + armor_list.Cut() + if(armor.bio) + armor_list += list("TOXIN" = armor.bio) + if(armor.bomb) + armor_list += list("EXPLOSIVE" = armor.bomb) + if(armor.bullet) + armor_list += list("BULLET" = armor.bullet) + if(armor.energy) + armor_list += list("ENERGY" = armor.energy) + if(armor.laser) + armor_list += list("LASER" = armor.laser) + if(armor.magic) + armor_list += list("MAGIC" = armor.magic) + if(armor.melee) + armor_list += list("MELEE" = armor.melee) + if(armor.rad) + armor_list += list("RADIATION" = armor.rad) + + if(LAZYLEN(durability_list)) + durability_list.Cut() + if(armor.fire) + durability_list += list("FIRE" = armor.fire) + if(armor.acid) + durability_list += list("ACID" = armor.acid) + + if(LAZYLEN(armor_list) || LAZYLEN(durability_list)) + . += "It has a tag listing its protection classes." + +/obj/item/clothing/Topic(href, href_list) + . = ..() + + if(href_list["list_armor"]) + var/list/readout = list("PROTECTION CLASSES (I-X)") + if(LAZYLEN(armor_list)) + readout += "\nARMOR" + for(var/dam_type in armor_list) + var/armor_amount = armor_list[dam_type] + readout += "\n[dam_type] [armor_to_protection_class(armor_amount)]" //e.g. BOMB IV + if(LAZYLEN(durability_list)) + readout += "\nDURABILITY" + for(var/dam_type in durability_list) + var/durability_amount = durability_list[dam_type] + readout += "\n[dam_type] [armor_to_protection_class(durability_amount)]" //e.g. FIRE II + readout += "" + + to_chat(usr, "[readout.Join()]") + +/** + * Rounds armor_value to nearest 10, divides it by 10 and then expresses it in roman numerals up to 10 + * + * Rounds armor_value to nearest 10, divides it by 10 + * and then expresses it in roman numerals up to 10 + * Arguments: + * * armor_value - Number we're converting + */ +/obj/item/clothing/proc/armor_to_protection_class(armor_value) + armor_value = round(armor_value,10) / 10 + switch (armor_value) + if (1) + . = "I" + if (2) + . = "II" + if (3) + . = "III" + if (4) + . = "IV" + if (5) + . = "V" + if (6) + . = "VI" + if (7) + . = "VII" + if (8) + . = "VIII" + if (9) + . = "IX" + if (10 to INFINITY) + . = "X" + return . + /obj/item/clothing/obj_break(damage_flag) - if(!damaged_clothes) - update_clothes_damaged_state(TRUE) + damaged_clothes = CLOTHING_DAMAGED + update_clothes_damaged_state() if(ismob(loc)) //It's not important enough to warrant a message if nobody's wearing it var/mob/M = loc to_chat(M, "Your [name] starts to fall apart!") -/obj/item/clothing/proc/update_clothes_damaged_state(damaging = TRUE) - var/index = "[REF(initial(icon))]-[initial(icon_state)]" - var/static/list/damaged_clothes_icons = list() - if(damaging) - damaged_clothes = 1 +//This mostly exists so subtypes can call appriopriate update icon calls on the wearer. +/obj/item/clothing/proc/update_clothes_damaged_state(damaged_state = CLOTHING_DAMAGED) + damaged_clothes = damaged_state + update_icon() + +/obj/item/clothing/update_overlays() + . = ..() + if(damaged_clothes) + var/index = "[REF(initial(icon))]-[initial(icon_state)]" + var/static/list/damaged_clothes_icons = list() var/icon/damaged_clothes_icon = damaged_clothes_icons[index] if(!damaged_clothes_icon) damaged_clothes_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply damaged effect to the initial icon_state for each object @@ -157,11 +362,7 @@ damaged_clothes_icon.Blend(icon('icons/effects/item_damage.dmi', "itemdamaged"), ICON_MULTIPLY) //adds damage effect and the remaining white areas become transparant damaged_clothes_icon = fcopy_rsc(damaged_clothes_icon) damaged_clothes_icons[index] = damaged_clothes_icon - add_overlay(damaged_clothes_icon, 1) - else - damaged_clothes = 0 - cut_overlay(damaged_clothes_icons[index], TRUE) - + . += damaged_clothes_icon /* SEE_SELF // can see self, no matter what @@ -222,16 +423,25 @@ BLIND // can't see anything /obj/item/clothing/obj_destruction(damage_flag) - if(damage_flag == "bomb" || damage_flag == "melee") + if(damage_flag == "bomb") var/turf/T = get_turf(src) spawn(1) //so the shred survives potential turf change from the explosion. var/obj/effect/decal/cleanable/shreds/Shreds = new(T) Shreds.desc = "The sad remains of what used to be [name]." deconstruct(FALSE) + else if(!(damage_flag in list("acid", "fire"))) + damaged_clothes = CLOTHING_SHREDDED + body_parts_covered = NONE + name = "shredded [initial(name)]" + slot_flags = NONE + update_clothes_damaged_state() + if(ismob(loc)) + var/mob/M = loc + M.visible_message("[M]'s [src.name] falls off, completely shredded!", "Your [src.name] falls off, completely shredded!", vision_distance = COMBAT_MESSAGE_RANGE) + M.dropItemToGround(src) else ..() - //Species-restricted clothing check. - Thanks Oraclestation, BS13, /vg/station etc. /obj/item/clothing/mob_can_equip(mob/M, slot, disable_warning = TRUE) @@ -265,3 +475,12 @@ BLIND // can't see anything return FALSE return TRUE + + + +/// If we're a clothing with at least 1 shredded/disabled zone, give the wearer a periodic heads up letting them know their clothes are damaged +/obj/item/clothing/proc/bristle(mob/living/L) + if(!istype(L)) + return + if(prob(0.2)) + to_chat(L, "The damaged threads on your [src.name] chafe!") diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 01effea6f2..3f6d21bcd2 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -96,7 +96,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/clothing/glasses/meson/eyepatch name = "eyepatch mesons" @@ -149,6 +149,30 @@ icon_state = "eyepatch" item_state = "eyepatch" +/obj/item/clothing/glasses/eyepatch/syndicate + name = "cybernetic eyepatch" + desc = "An eyepatch used to enhance one's aim with guns." + icon_state = "syndicatepatch" + item_state = "syndicatepatch" + resistance_flags = ACID_PROOF + +/obj/item/clothing/glasses/eyepatch/syndicate/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot == SLOT_GLASSES) + user.visible_message("Circuitry from the eyepatch links itself to your brain as you put on the eyepatch.") + if(HAS_TRAIT(user, TRAIT_POOR_AIM)) + user.visible_message("You hear a fizzing noise from the circuit. That can't be good.") + ADD_TRAIT(user, TRAIT_INSANE_AIM, "SYNDICATE_EYEPATCH_AIM") + ADD_TRAIT(src, TRAIT_NODROP, "SYNDICATE_EYEPATCH_NODROP") + +/obj/item/clothing/glasses/eyepatch/syndicate/dropped(mob/living/carbon/human/user) + . = ..() + REMOVE_TRAIT(user, TRAIT_INSANE_AIM, "SYNDICATE_EYEPATCH_AIM") + var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES) + if(eyes) + eyes.applyOrganDamage(30) + user.visible_message("Your eye stings as the circuitry is removed from your eye!") + /obj/item/clothing/glasses/monocle name = "monocle" desc = "Such a dapper eyepiece!" @@ -180,7 +204,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED vision_correction = 1 glass_colour_type = /datum/client_colour/glass_colour/lightgreen @@ -237,7 +261,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/clothing/glasses/sunglasses/garb/supergarb name = "black giga gar glasses" @@ -257,7 +281,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED glass_colour_type = /datum/client_colour/glass_colour/orange /obj/item/clothing/glasses/sunglasses/gar/supergar diff --git a/code/modules/clothing/glasses/disablerglasses.dm b/code/modules/clothing/glasses/disablerglasses.dm index a46e4c8339..51fb1cec87 100644 --- a/code/modules/clothing/glasses/disablerglasses.dm +++ b/code/modules/clothing/glasses/disablerglasses.dm @@ -4,7 +4,9 @@ var/beamtype = /obj/item/projectile/beam/disabler //change for adminbus /obj/item/clothing/glasses/hud/security/sunglasses/disablers/ranged_attack(mob/living/carbon/human/user,atom/A, params) - user.changeNext_move(CLICK_CD_RANGE) + if(!user.CheckActionCooldown(CLICK_CD_RANGE)) + return + user.last_action = world.time var/obj/item/projectile/beam/disabler/LE = new beamtype( loc ) playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) LE.firer = src @@ -12,4 +14,4 @@ LE.preparePixelProjectile(A, src, params) LE.fire() return TRUE - //shamelessly copied \ No newline at end of file + //shamelessly copied diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index 2a64445776..d7e7ae3669 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -97,14 +97,14 @@ if(get_dist(user, place) >= range*8) //Rads are easier to see than wires under the floor continue var/strength = round(rad_places[i] / 1000, 0.1) - var/image/pic = new(loc = place) + var/image/pic = image(loc = place) var/mutable_appearance/MA = new() - MA.alpha = 180 - MA.maptext = "[strength]k" - MA.color = "#64C864" - MA.layer = FLY_LAYER + MA.maptext = "[strength]k" + MA.color = "#04e604" + MA.layer = RAD_TEXT_LAYER + MA.plane = GAME_PLANE pic.appearance = MA - flick_overlay(pic, list(user.client), 8) + flick_overlay(pic, list(user.client), 10) /obj/item/clothing/glasses/meson/engine/proc/show_shuttle() var/mob/living/carbon/human/user = loc diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index c745cd74f0..9ca98b0bca 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -70,7 +70,7 @@ flash_protect = -2 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE glass_colour_type = /datum/client_colour/glass_colour/green - + /obj/item/clothing/glasses/hud/health/night/syndicate name = "combat night vision health scanner HUD" desc = "An advanced shielded medical heads-up display that allows soldiers to approximate how much lead poisoning their allies have suffered in complete darkness." @@ -221,7 +221,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/clothing/glasses/hud/security/sunglasses/gars/supergars name = "giga HUD gar glasses" diff --git a/code/modules/clothing/gloves/_gloves.dm b/code/modules/clothing/gloves/_gloves.dm index ddf5e4b584..a206b9adc7 100644 --- a/code/modules/clothing/gloves/_gloves.dm +++ b/code/modules/clothing/gloves/_gloves.dm @@ -34,7 +34,7 @@ if(blood_DNA) . += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", color = blood_DNA_to_color()) -/obj/item/clothing/gloves/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/gloves/update_clothes_damaged_state() ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 1b5cd6c7d2..56d6e7d38f 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -23,14 +23,15 @@ 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) + var/success = C.equip_to_slot_if_possible(new /obj/item/clothing/gloves/color/yellow/sprayon, ITEM_SLOT_GLOVES, TRUE, TRUE, clothing_check = 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!") + user.visible_message("The rubber fails to stick to [C]'s hands!", + "The rubber fails to stick to [C]'s [(SLOT_GLOVES in C.check_obscured_slots()) ? "unexposed" : ""] hands!") qdel(src) diff --git a/code/modules/clothing/gloves/miscellaneous.dm b/code/modules/clothing/gloves/miscellaneous.dm index a8017631bd..b5d92fb780 100644 --- a/code/modules/clothing/gloves/miscellaneous.dm +++ b/code/modules/clothing/gloves/miscellaneous.dm @@ -45,8 +45,8 @@ REMOVE_TRAIT(user, secondary_trait, GLOVE_TRAIT) if(ishuman(user)) var/mob/living/carbon/human/H = user - H.dna.species.punchdamagehigh = initial(H.dna.species.punchdamagehigh) - H.dna.species.punchdamagelow = initial(H.dna.species.punchdamagelow) + H.dna.species.punchdamagehigh -= enhancement + H.dna.species.punchdamagelow -= enhancement return ..() /obj/item/clothing/gloves/fingerless/pugilist/chaplain @@ -105,11 +105,11 @@ return var/mob/living/M = loc - M.changeNext_move(CLICK_CD_RAPID) + M.SetNextAction(CLICK_CD_RAPID) if(warcry) M.say("[warcry]", ignore_spam = TRUE, forced = TRUE) - return FALSE + return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION /obj/item/clothing/gloves/fingerless/pugilist/rapid/AltClick(mob/user) var/input = stripped_input(user,"What do you want your battlecry to be? Max length of 6 characters.", ,"", 7) @@ -135,9 +135,9 @@ if(target.stat != CONSCIOUS) //Can't hug people who are dying/dead return FALSE else - M.changeNext_move(CLICK_CD_RAPID) + M.SetNextAction(CLICK_CD_RAPID) - return FALSE + return NO_AUTO_CLICKDELAY_HANDLING | ATTACK_IGNORE_ACTION /obj/item/clothing/gloves/botanic_leather name = "botanist's leather gloves" @@ -196,3 +196,19 @@ transfer_prints = FALSE strip_mod = 5 strip_silence = TRUE + +/obj/item/clothing/gloves/evening + name = "evening gloves" + desc = "Thin, pretty gloves intended for use in regal feminine attire. A tag on the hem claims they were 'maid' in Space China, these were probably intended for use in some maid fetish." + icon_state = "evening" + item_state = "evening" + transfer_prints = TRUE + cold_protection = HANDS + min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT + strip_mod = 0.9 + +/obj/item/clothing/gloves/evening/black + name = "midnight gloves" + desc = "Thin, pretty gloves intended for use in sexy feminine attire. A tag on the hem claims they pair great with black stockings." + icon_state = "eveningblack" + item_state = "eveningblack" diff --git a/code/modules/clothing/gloves/ring.dm b/code/modules/clothing/gloves/ring.dm index 8354f13bd2..daca843c45 100644 --- a/code/modules/clothing/gloves/ring.dm +++ b/code/modules/clothing/gloves/ring.dm @@ -21,7 +21,7 @@ desc = "An expensive ring, studded with a diamond. Cultures have used these rings in courtship for a millenia." icon_state = "ringdiamond" item_state = "dring" - + /obj/item/clothing/gloves/ring/diamond/attack_self(mob/user) user.visible_message("\The [user] gets down on one knee, presenting \the [src].","You get down on one knee, presenting \the [src].") @@ -30,3 +30,12 @@ desc = "A tiny silver ring, sized to wrap around a finger." icon_state = "ringsilver" item_state = "sring" + +/obj/item/clothing/gloves/ring/custom + name = "ring" + desc = "A ring." + gender = NEUTER + w_class = WEIGHT_CLASS_TINY + obj_flags = UNIQUE_RENAME + icon_state = "ringsilver" + item_state = "sring" diff --git a/code/modules/clothing/gloves/tacklers.dm b/code/modules/clothing/gloves/tacklers.dm index 11b2afa968..f4b4140a1a 100644 --- a/code/modules/clothing/gloves/tacklers.dm +++ b/code/modules/clothing/gloves/tacklers.dm @@ -72,6 +72,25 @@ siemens_coefficient = 0 permeability_coefficient = 0.05 +/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator + name = "insidious guerrilla gloves" + desc = "Specialized combat gloves for carrying people around. Transfers tactical kidnapping and tackling knowledge to the user via the use of nanochips." + icon_state = "infiltrator" + item_state = "infiltrator" + siemens_coefficient = 0 + permeability_coefficient = 0.05 + resistance_flags = FIRE_PROOF | ACID_PROOF + var/carrytrait = TRAIT_QUICKER_CARRY + +/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator/equipped(mob/user, slot) + . = ..() + if(slot == SLOT_GLOVES) + ADD_TRAIT(user, carrytrait, GLOVE_TRAIT) + +/obj/item/clothing/gloves/tackler/combat/insulated/infiltrator/dropped(mob/user) + . = ..() + REMOVE_TRAIT(user, carrytrait, GLOVE_TRAIT) + /obj/item/clothing/gloves/tackler/rocket name = "rocket gloves" desc = "The ultimate in high risk, high reward, perfect for when you need to stop a criminal from fifty feet away or die trying. Banned in most Spinward gridiron football and rugby leagues." diff --git a/code/modules/clothing/head/_head.dm b/code/modules/clothing/head/_head.dm index 475e7a4e51..dc07d5e050 100644 --- a/code/modules/clothing/head/_head.dm +++ b/code/modules/clothing/head/_head.dm @@ -8,6 +8,7 @@ var/blockTracking = 0 //For AI tracking var/can_toggle = null dynamic_hair_suffix = "+generic" + var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot /obj/item/clothing/head/Initialize() . = ..() @@ -56,7 +57,7 @@ if(blood_DNA) . += mutable_appearance('icons/effects/blood.dmi', "helmetblood", color = blood_DNA_to_color()) -/obj/item/clothing/head/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/head/update_clothes_damaged_state() ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/head/collectable.dm b/code/modules/clothing/head/collectable.dm index 314142d0cc..20cb7cc824 100644 --- a/code/modules/clothing/head/collectable.dm +++ b/code/modules/clothing/head/collectable.dm @@ -27,7 +27,9 @@ icon_state = "chef" item_state = "chef" dynamic_hair_suffix = "" + dog_fashion = /datum/dog_fashion/head/chef + beepsky_fashion = /datum/beepsky_fashion/chef /obj/item/clothing/head/collectable/paper name = "collectable paper hat" @@ -42,6 +44,8 @@ icon_state = "tophat" item_state = "that" + beepsky_fashion = /datum/beepsky_fashion/tophat + /obj/item/clothing/head/collectable/captain name = "collectable captain's hat" desc = "A collectable hat that'll make you look just like a real comdom!" @@ -49,6 +53,7 @@ item_state = "caphat" dog_fashion = /datum/dog_fashion/head/captain + beepsky_fashion = /datum/beepsky_fashion/captain /obj/item/clothing/head/collectable/police name = "collectable police officer's hat" @@ -91,6 +96,7 @@ item_state = "pirate" dog_fashion = /datum/dog_fashion/head/pirate + beepsky_fashion = /datum/beepsky_fashion/pirate /obj/item/clothing/head/collectable/kitty name = "collectable kitty ears" @@ -100,6 +106,7 @@ dynamic_hair_suffix = "" dog_fashion = /datum/dog_fashion/head/kitty + beepsky_fashion = /datum/beepsky_fashion/cat /obj/item/clothing/head/collectable/rabbitears name = "collectable rabbit ears" @@ -116,6 +123,7 @@ icon_state = "wizard" dog_fashion = /datum/dog_fashion/head/blue_wizard + beepsky_fashion = /datum/beepsky_fashion/wizard /obj/item/clothing/head/collectable/hardhat name = "collectable hard hat" diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index 80d0b7c8a8..12a4a43ca7 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -15,6 +15,7 @@ dynamic_hair_suffix = "+generic" dog_fashion = /datum/dog_fashion/head + beepsky_fashion = /datum/beepsky_fashion/engineer /obj/item/clothing/head/hardhat/ComponentInitialize() diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 8f852356b7..662318fb82 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -244,7 +244,7 @@ icon_state = "knight_greyscale" item_state = "knight_greyscale" armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40) - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS //Can change color and add prefix + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix /obj/item/clothing/head/helmet/skull name = "skull helmet" diff --git a/code/modules/clothing/head/jobs.dm b/code/modules/clothing/head/jobs.dm index 638a0c2f23..5af694ea1b 100644 --- a/code/modules/clothing/head/jobs.dm +++ b/code/modules/clothing/head/jobs.dm @@ -13,7 +13,9 @@ strip_delay = 10 equip_delay_other = 10 dynamic_hair_suffix = "" + dog_fashion = /datum/dog_fashion/head/chef + beepsky_fashion = /datum/beepsky_fashion/chef /obj/item/clothing/head/chefhat/suicide_act(mob/user) user.visible_message("[user] is donning [src]! It looks like [user.p_theyre()] trying to become a chef.") @@ -33,7 +35,9 @@ flags_inv = 0 armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) strip_delay = 60 + dog_fashion = /datum/dog_fashion/head/captain + beepsky_fashion = /datum/beepsky_fashion/captain //Captain: This is no longer space-worthy /obj/item/clothing/head/caphat/parade diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 201c9e0bea..124ece8fdc 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -20,9 +20,11 @@ desc = "It's an amish looking hat." icon_state = "tophat" item_state = "that" - dog_fashion = /datum/dog_fashion/head throwforce = 1 + dog_fashion = /datum/dog_fashion/head + beepsky_fashion = /datum/beepsky_fashion/tophat + /obj/item/clothing/head/canada name = "striped red tophat" desc = "It smells like fresh donut holes. / Il sent comme des trous de beignets frais." @@ -126,7 +128,9 @@ desc = "Yarr." icon_state = "pirate" item_state = "pirate" + dog_fashion = /datum/dog_fashion/head/pirate + beepsky_fashion = /datum/beepsky_fashion/pirate /obj/item/clothing/head/pirate/captain name = "pirate captain hat" @@ -189,6 +193,8 @@ desc = "A really cool hat if you're a mobster. A really lame hat if you're not." pocket_storage_component_path = /datum/component/storage/concrete/pockets/small + beepsky_fashion = /datum/beepsky_fashion/fedora + /obj/item/clothing/head/fedora/suicide_act(mob/user) if(user.gender == FEMALE) return 0 @@ -205,7 +211,9 @@ item_state = "sombrero" desc = "You can practically taste the fiesta." flags_inv = HIDEHAIR + dog_fashion = /datum/dog_fashion/head/sombrero + beepsky_fashion = /datum/beepsky_fashion/sombrero /obj/item/clothing/head/sombrero/green name = "green sombrero" @@ -213,6 +221,7 @@ item_state = "greensombrero" desc = "As elegant as a dancing cactus." flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS + dog_fashion = null /obj/item/clothing/head/sombrero/shamebrero @@ -220,6 +229,7 @@ icon_state = "shamebrero" item_state = "shamebrero" desc = "Once it's on, it never comes off." + dog_fashion = null /obj/item/clothing/head/sombrero/shamebrero/Initialize() @@ -248,7 +258,9 @@ item_state = "that" cold_protection = HEAD min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT + dog_fashion = /datum/dog_fashion/head/santa + beepsky_fashion = /datum/beepsky_fashion/santa /obj/item/clothing/head/jester name = "jester hat" @@ -286,6 +298,8 @@ resistance_flags = FIRE_PROOF dynamic_hair_suffix = "" + beepsky_fashion = /datum/beepsky_fashion/king + /obj/item/clothing/head/crown/fancy name = "magnificent crown" desc = "A crown worn by only the highest emperors of the land space." @@ -391,7 +405,9 @@ name = "cowboy hat" desc = "A standard brown cowboy hat, yeehaw." icon_state = "cowboyhat" - item_state= "cowboyhat" + item_state = "cowboyhat" + + beepsky_fashion = /datum/beepsky_fashion/cowboy /obj/item/clothing/head/cowboyhat/black name = "black cowboy hat" @@ -437,3 +453,32 @@ item_state = "hunter" armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 15, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) resistance_flags = FIRE_PROOF | ACID_PROOF + +/obj/item/clothing/head/kepi + name = "kepi" + desc = "A white cap with visor. Oui oui, mon capitane!" + icon_state = "kepi" + +/obj/item/clothing/head/kepi/old + icon_state = "kepi_old" + desc = "A flat, white circular cap with a visor, that demands some honor from it's wearer." + +/obj/item/clothing/head/maid + name = "maid headband" + desc = "Maid in China." + icon_state = "maid" + item_state = "maid" + dynamic_hair_suffix = "" + +/obj/item/clothing/head/widered + name = "Wide red hat" + desc = "It is both wide, and red. Stylish!" + icon_state = "widehat_red" + item_state = "widehat_red" + +/obj/item/clothing/head/kabuto + name = "Kabuto helmet" + desc = "A traditional kabuto helmet." + icon_state = "kabuto" + item_state = "kabuto" + flags_inv = HIDEHAIR|HIDEEARS diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 5582947732..3774ce575f 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -50,6 +50,8 @@ flags_cover = HEADCOVERSEYES heat = 1000 + beepsky_fashion = /datum/beepsky_fashion/cake + /obj/item/clothing/head/hardhat/cakehat/process() var/turf/location = src.loc if(ishuman(location)) @@ -131,6 +133,7 @@ dynamic_hair_suffix = "" dog_fashion = /datum/dog_fashion/head/kitty + beepsky_fashion = /datum/beepsky_fashion/cat /obj/item/clothing/head/kitty/equipped(mob/living/carbon/human/user, slot) if(ishuman(user) && slot == SLOT_HEAD) @@ -238,7 +241,7 @@ item_state = "foilhat" armor = list("melee" = 0, "bullet" = 0, "laser" = -5,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = -5, "fire" = 0, "acid" = 0) equip_delay_other = 140 - var/datum/brain_trauma/mild/phobia/paranoia + var/datum/brain_trauma/mild/phobia/conspiracies/paranoia var/warped = FALSE clothing_flags = IGNORE_HAT_TOSS @@ -255,7 +258,8 @@ return if(paranoia) QDEL_NULL(paranoia) - paranoia = new("conspiracies") + paranoia = new() + paranoia.clonable = FALSE user.gain_trauma(paranoia, TRAUMA_RESILIENCE_MAGIC) to_chat(user, "As you don the foiled hat, an entire world of conspiracy theories and seemingly insane ideas suddenly rush into your mind. What you once thought unbelievable suddenly seems.. undeniable. Everything is connected and nothing happens just by accident. You know too much and now they're out to get you. ") @@ -286,7 +290,7 @@ if(!target.IsUnconscious()) to_chat(target, "Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare.") -/obj/item/clothing/head/foilhat/attack_hand(mob/user) +/obj/item/clothing/head/foilhat/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!warped && iscarbon(user)) var/mob/living/carbon/C = user if(src == C.head) diff --git a/code/modules/clothing/masks/_masks.dm b/code/modules/clothing/masks/_masks.dm index 7df38661e5..94f7ee179a 100644 --- a/code/modules/clothing/masks/_masks.dm +++ b/code/modules/clothing/masks/_masks.dm @@ -8,6 +8,7 @@ var/modifies_speech = FALSE var/mask_adjusted = 0 var/adjusted_flags = null + var/datum/beepsky_fashion/beepsky_fashion //the associated datum for applying this to a secbot /obj/item/clothing/mask/attack_self(mob/user) if(CHECK_BITFIELD(clothing_flags, VOICEBOX_TOGGLABLE)) @@ -37,7 +38,7 @@ if(blood_DNA) . += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color()) -/obj/item/clothing/mask/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/mask/update_clothes_damaged_state() ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm index f11c89d00c..6701b53c10 100644 --- a/code/modules/clothing/masks/boxing.dm +++ b/code/modules/clothing/masks/boxing.dm @@ -12,6 +12,10 @@ /obj/item/clothing/mask/balaclava/attack_self(mob/user) adjustmask(user) +/obj/item/clothing/mask/balaclava/breath + name = "breathaclava" + clothing_flags = ALLOWINTERNALS + /obj/item/clothing/mask/infiltrator name = "insidious balaclava" desc = "An incredibly suspicious balaclava made with Syndicate nanofibers to absorb impacts slightly while obfuscating the voice and face using a garbled vocoder." diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 6a836cad7b..51a526d089 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -219,7 +219,7 @@ lock = TRUE return -/obj/item/clothing/neck/petcollar/locked/attack_hand(mob/user) +/obj/item/clothing/neck/petcollar/locked/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user && user.get_item_by_slot(SLOT_NECK) && lock != FALSE) to_chat(user, "The collar is locked! You'll need unlock the collar before you can take it off!") return diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm index d692f9c3fb..afe74de6a0 100644 --- a/code/modules/clothing/outfits/standard.dm +++ b/code/modules/clothing/outfits/standard.dm @@ -123,7 +123,7 @@ l_pocket = /obj/item/reagent_containers/food/snacks/grown/banana r_pocket = /obj/item/bikehorn id = /obj/item/card/id - r_hand = /obj/item/twohanded/fireaxe + r_hand = /obj/item/fireaxe /datum/outfit/tunnel_clown/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) if(visualsOnly) @@ -148,7 +148,7 @@ suit = /obj/item/clothing/suit/apron l_pocket = /obj/item/kitchen/knife r_pocket = /obj/item/scalpel - r_hand = /obj/item/twohanded/fireaxe + r_hand = /obj/item/fireaxe /datum/outfit/psycho/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) for(var/obj/item/carried_item in H.get_equipped_items(TRUE)) diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 802dd7265e..49256b490d 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -18,6 +18,16 @@ mutantrace_variation = STYLE_DIGITIGRADE var/last_bloodtype = "" //used to track the last bloodtype to have graced these shoes; makes for better performing footprint shenanigans var/last_blood_DNA = "" //same as last one + var/last_blood_color = "" + + ///Whether these shoes have laces that can be tied/untied + var/can_be_tied = TRUE + ///Are we currently tied? Can either be SHOES_UNTIED, SHOES_TIED, or SHOES_KNOTTED + var/tied = SHOES_TIED + ///How long it takes to lace/unlace these shoes + var/lace_time = 5 SECONDS + ///any alerts we have active + var/obj/screen/alert/our_alert /obj/item/clothing/shoes/ComponentInitialize() . = ..() @@ -42,12 +52,22 @@ playsound(user, 'sound/weapons/genhit2.ogg', 50, 1) return(BRUTELOSS) +/obj/item/clothing/shoes/examine(mob/user) + . = ..() + + if(!ishuman(loc)) + return ..() + if(tied == SHOES_UNTIED) + . += "The shoelaces are untied." + else if(tied == SHOES_KNOTTED) + . += "The shoelaces are all knotted together." /obj/item/clothing/shoes/transfer_blood_dna(list/blood_dna, diseases) ..() if(blood_dna.len) last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works last_blood_DNA = blood_dna[blood_dna.len] + last_blood_color = blood_dna["color"] /obj/item/clothing/shoes/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) . = ..() @@ -72,6 +92,9 @@ worn_y_dimension -= (offset * 2) user.update_inv_shoes() equipped_before_drop = TRUE + if(can_be_tied && tied == SHOES_UNTIED) + our_alert = user.throw_alert("shoealert", /obj/screen/alert/shoes/untied) + RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE) /obj/item/clothing/shoes/proc/restore_offsets(mob/user) equipped_before_drop = FALSE @@ -79,11 +102,13 @@ worn_y_dimension = world.icon_size /obj/item/clothing/shoes/dropped(mob/user) + if(our_alert && (our_alert.mob_viewer == user)) + user.clear_alert("shoealert") if(offset && equipped_before_drop) restore_offsets(user) . = ..() -/obj/item/clothing/shoes/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/shoes/update_clothes_damaged_state() ..() if(ismob(loc)) var/mob/M = loc @@ -99,3 +124,165 @@ /obj/item/proc/negates_gravity() return FALSE + +/** + * adjust_laces adjusts whether our shoes (assuming they can_be_tied) and tied, untied, or knotted + * + * In addition to setting the state, it will deal with getting rid of alerts if they exist, as well as registering and unregistering the stepping signals + * + * Arguments: + * * + * * state: SHOES_UNTIED, SHOES_TIED, or SHOES_KNOTTED, depending on what you want them to become + * * user: used to check to see if we're the ones unknotting our own laces + */ +/obj/item/clothing/shoes/proc/adjust_laces(state, mob/user) + if(!can_be_tied) + return + + var/mob/living/carbon/human/our_guy + if(ishuman(loc)) + our_guy = loc + + tied = state + if(tied == SHOES_TIED) + if(our_guy) + our_guy.clear_alert("shoealert") + UnregisterSignal(src, COMSIG_SHOES_STEP_ACTION) + else + if(tied == SHOES_UNTIED && our_guy && user == our_guy) + our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/untied) // if we're the ones unknotting our own laces, of course we know they're untied + RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_trip, override=TRUE) + +/** + * handle_tying deals with all the actual tying/untying/knotting, inferring your intent from who you are in relation to the state of the laces + * + * If you're the wearer, you want them to move towards tied-ness (knotted -> untied -> tied). If you're not, you're pranking them, so you're moving towards knotted-ness (tied -> untied -> knotted) + * + * Arguments: + * * + * * user: who is the person interacting with the shoes? + */ +/obj/item/clothing/shoes/proc/handle_tying(mob/user) + ///our_guy here is the wearer, if one exists (and he must exist, or we don't care) + var/mob/living/carbon/human/our_guy = loc + if(!istype(our_guy)) + return + + if(!in_range(user, our_guy)) + to_chat(user, "You aren't close enough to interact with [src]'s laces!") + return + + if(user == loc && tied != SHOES_TIED) // if they're our own shoes, go tie-wards + if(INTERACTING_WITH(user, our_guy)) + to_chat(user, "You're already interacting with [src]!") + return + user.visible_message("[user] begins [tied ? "unknotting" : "tying"] the laces of [user.p_their()] [src.name].", "You begin [tied ? "unknotting" : "tying"] the laces of your [src.name]...") + + if(do_after(user, lace_time, needhand=TRUE, target=our_guy, extra_checks=CALLBACK(src, .proc/still_shoed, our_guy))) + to_chat(user, "You [tied ? "unknot" : "tie"] the laces of your [src.name].") + if(tied == SHOES_UNTIED) + adjust_laces(SHOES_TIED, user) + else + adjust_laces(SHOES_UNTIED, user) + + else // if they're someone else's shoes, go knot-wards + var/mob/living/L = user + if(istype(L) && (L.mobility_flags & MOBILITY_STAND)) + to_chat(user, "You must be on the floor to interact with [src]!") + return + if(tied == SHOES_KNOTTED) + to_chat(user, "The laces on [loc]'s [src.name] are already a hopelessly tangled mess!") + return + if(INTERACTING_WITH(user, our_guy)) + to_chat(user, "You're already interacting with [src]!") + return + + var/mod_time = lace_time + to_chat(user, "You quietly set to work [tied ? "untying" : "knotting"] [loc]'s [src.name]...") + if(HAS_TRAIT(user, TRAIT_CLUMSY)) // based clowns trained their whole lives for this + mod_time *= 0.75 + + if(do_after(user, mod_time, needhand=TRUE, target=our_guy, extra_checks=CALLBACK(src, .proc/still_shoed, our_guy))) + to_chat(user, "You [tied ? "untie" : "knot"] the laces on [loc]'s [src.name].") + if(tied == SHOES_UNTIED) + adjust_laces(SHOES_KNOTTED, user) + else + adjust_laces(SHOES_UNTIED, user) + else // if one of us moved + user.visible_message("[our_guy] stamps on [user]'s hand, mid-shoelace [tied ? "knotting" : "untying"]!", "Ow! [our_guy] stamps on your hand!", list(our_guy)) + to_chat(our_guy, "You stamp on [user]'s hand! What the- [user.p_they()] [user.p_were()] [tied ? "knotting" : "untying"] your shoelaces!") + user.emote("scream") + if(istype(L)) + var/obj/item/bodypart/ouchie = L.get_bodypart(pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) + if(ouchie) + ouchie.receive_damage(brute = 10, stamina = 40) + L.Paralyze(10) + +///checking to make sure we're still on the person we're supposed to be, for lacing do_after's +/obj/item/clothing/shoes/proc/still_shoed(mob/living/carbon/our_guy) + return (loc == our_guy) + +///check_trip runs on each step to see if we fall over as a result of our lace status. Knotted laces are a guaranteed trip, while untied shoes are just a chance to stumble +/obj/item/clothing/shoes/proc/check_trip() + var/mob/living/carbon/human/our_guy = loc + if(!istype(our_guy)) // are they REALLY /our guy/? + return + + if(tied == SHOES_KNOTTED) + our_guy.Paralyze(5) + our_guy.Knockdown(10) + our_guy.visible_message("[our_guy] trips on [our_guy.p_their()] knotted shoelaces and falls! What a klutz!", "You trip on your knotted shoelaces and fall over!") + SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "trip", /datum/mood_event/tripped) // well we realized they're knotted now! + our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/knotted) + + else if(tied == SHOES_UNTIED) + var/wiser = TRUE // did we stumble and realize our laces are undone? + switch(rand(1, 1000)) + if(1) // .1% chance to trip and fall over (note these are per step while our laces are undone) + our_guy.Paralyze(5) + our_guy.Knockdown(10) + SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "trip", /datum/mood_event/tripped) // well we realized they're knotted now! + our_guy.visible_message("[our_guy] trips on [our_guy.p_their()] untied shoelaces and falls! What a klutz!", "You trip on your untied shoelaces and fall over!") + + if(2 to 5) // .4% chance to stumble and lurch forward + our_guy.throw_at(get_step(our_guy, our_guy.dir), 3, 2) + to_chat(our_guy, "You stumble on your untied shoelaces and lurch forward!") + + if(6 to 13) // .7% chance to stumble and fling what we're holding + var/have_anything = FALSE + for(var/obj/item/I in our_guy.held_items) + have_anything = TRUE + our_guy.accident(I) + to_chat(our_guy, "You trip on your shoelaces a bit[have_anything ? ", flinging what you were holding" : ""]!") + + if(14 to 25) // 1.3ish% chance to stumble and be a bit off balance (like being disarmed) + to_chat(our_guy, "You stumble a bit on your untied shoelaces!") + our_guy.ShoveOffBalance(SHOVE_OFFBALANCE_DURATION) + our_guy.Stagger(SHOVE_OFFBALANCE_DURATION) //yes, same. + if(26 to 1000) + wiser = FALSE + if(wiser) + SEND_SIGNAL(our_guy, COMSIG_ADD_MOOD_EVENT, "untied", /datum/mood_event/untied) // well we realized they're untied now! + our_alert = our_guy.throw_alert("shoealert", /obj/screen/alert/shoes/untied) + + +/obj/item/clothing/shoes/on_attack_hand(mob/living/user, act_intent, unarmed_attack_flags) + if(!istype(user)) + return ..() + if(loc == user && tied != SHOES_TIED && (user.mobility_flags & MOBILITY_USE)) + handle_tying(user) + return + return ..() + +/obj/item/clothing/shoes/attack_self(mob/user) + . = ..() + + if(INTERACTING_WITH(user, src)) + to_chat(user, "You're already interacting with [src]!") + return + + to_chat(user, "You begin [tied ? "untying" : "tying"] the laces on [src]...") + + if(do_after(user, lace_time, needhand=TRUE, target=src,extra_checks=CALLBACK(src, .proc/still_shoed, user))) + to_chat(user, "You [tied ? "untie" : "tie"] the laces on [src].") + adjust_laces(tied ? SHOES_TIED : SHOES_UNTIED, user) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index b68bef6329..b0d760ebd9 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -17,6 +17,7 @@ resistance_flags = NONE permeability_coefficient = 0.05 //Thick soles, and covers the ankle pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 12 SECONDS /obj/item/clothing/shoes/combat/sneakboots name = "insidious sneakboots" @@ -49,6 +50,7 @@ strip_delay = 50 equip_delay_other = 50 permeability_coefficient = 0.9 + can_be_tied = FALSE /obj/item/clothing/shoes/sandal/marisa desc = "A pair of magic black shoes." @@ -73,6 +75,7 @@ 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 = PRICE_ABOVE_EXPENSIVE + can_be_tied = FALSE /obj/item/clothing/shoes/galoshes/dry name = "absorbent galoshes" @@ -99,6 +102,7 @@ icon_state = "clown_shoes" slowdown = SHOES_SLOWDOWN+1 pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes/clown + lace_time = 20 SECONDS // how the hell do these laces even work?? /obj/item/clothing/shoes/clown_shoes/Initialize() . = ..() @@ -130,6 +134,7 @@ resistance_flags = NONE permeability_coefficient = 0.05 //Thick soles, and covers the ankle pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 12 SECONDS /obj/item/clothing/shoes/jackboots/fast slowdown = -1 @@ -144,6 +149,7 @@ heat_protection = FEET|LEGS max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/winterboots/ice_boots name = "ice hiking boots" @@ -177,6 +183,7 @@ strip_delay = 40 equip_delay_other = 40 pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/workboots/mining name = "mining boots" @@ -196,6 +203,7 @@ min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT heat_protection = FEET max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT + lace_time = 10 SECONDS /obj/item/clothing/shoes/cult/alt name = "cultist boots" @@ -226,12 +234,14 @@ strip_delay = 100 equip_delay_other = 100 permeability_coefficient = 0.9 + can_be_tied = FALSE /obj/item/clothing/shoes/griffin name = "griffon boots" desc = "A pair of costume boots fashioned after bird talons." icon_state = "griffinboots" pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS /obj/item/clothing/shoes/bhop name = "jump boots" @@ -284,6 +294,7 @@ desc = "A giant, clunky pair of shoes crudely made out of bronze. Why would anyone wear these?" icon = 'icons/obj/clothing/clockwork_garb.dmi' icon_state = "clockwork_treads" + lace_time = 8 SECONDS /obj/item/clothing/shoes/bronze/Initialize() . = ..() @@ -358,6 +369,7 @@ icon_state = "rus_shoes" item_state = "rus_shoes" pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes + lace_time = 8 SECONDS // kevin is into feet /obj/item/clothing/shoes/wraps @@ -365,6 +377,7 @@ desc = "Ankle coverings. These ones have a golden design." icon_state = "gildedcuffs" body_parts_covered = FALSE + can_be_tied = FALSE /obj/item/clothing/shoes/wraps/silver name = "silver leg wraps" @@ -385,6 +398,7 @@ name = "cowboy boots" desc = "A standard pair of brown cowboy boots." icon_state = "cowboyboots" + can_be_tied = FALSE /obj/item/clothing/shoes/cowboyboots/black name = "black cowboy boots" diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index 82dd3142ed..cba27845f1 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -7,7 +7,7 @@ clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS item_state = "spaceold" permeability_coefficient = 0.01 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70, "wound" = 5) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT dynamic_hair_suffix = "" dynamic_fhair_suffix = "" @@ -36,7 +36,7 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS allowed = list(/obj/item/flashlight, /obj/item/tank/internals) slowdown = 1 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70, "wound" = 5) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAUR cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 94ccdf94c6..3f77a2befc 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -4,7 +4,7 @@ icon_state = "chronohelmet" item_state = "chronohelmet" slowdown = 1 - armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 100, "wound" = 80) resistance_flags = FIRE_PROOF | ACID_PROOF var/obj/item/clothing/suit/space/chronos/suit = null @@ -19,7 +19,7 @@ icon_state = "chronosuit" item_state = "chronosuit" actions_types = list(/datum/action/item_action/toggle) - armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000) + armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000, "wound" = 80) resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE var/list/chronosafe_items = list(/obj/item/chrono_eraser, /obj/item/gun/energy/chrono_gun) @@ -80,11 +80,11 @@ if(to_turf) user.forceMove(to_turf) user.SetStun(0) - user.next_move = 1 + user.SetNextAction(0, considered_action = FALSE, immediate = FALSE) user.alpha = 255 user.update_atom_colour() user.animate_movement = FORWARD_STEPS - user.notransform = 0 + user.mob_transforming = 0 user.anchored = FALSE teleporting = 0 for(var/obj/item/I in user.held_items) @@ -124,8 +124,8 @@ for(var/obj/item/I in user.held_items) ADD_TRAIT(I, TRAIT_NODROP, CHRONOSUIT_TRAIT) user.animate_movement = NO_STEPS - user.changeNext_move(8 + phase_in_ds) - user.notransform = 1 + user.DelayNextAction(8 + phase_in_ds, considered_action = FALSE, immediate = FALSE) + user.mob_transforming = TRUE user.anchored = TRUE user.Stun(INFINITY) diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 695d25dbf4..12829ed0e7 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -5,7 +5,7 @@ icon_state = "hardsuit0-engineering" item_state = "eng_helm" max_integrity = 300 - armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75) + armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75, "wound" = 10) var/basestate = "hardsuit" var/brightness_on = 4 //luminosity when on var/on = FALSE @@ -94,7 +94,7 @@ icon_state = "hardsuit-engineering" item_state = "eng_hardsuit" max_integrity = 300 - armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75) + armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75, "wound" = 10) allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/t_scanner, /obj/item/construction/rcd, /obj/item/pipe_dispenser) siemens_coefficient = 0 var/obj/item/clothing/head/helmet/space/hardsuit/helmet @@ -107,11 +107,7 @@ /obj/item/clothing/suit/space/hardsuit/Initialize() if(jetpack && ispath(jetpack)) jetpack = new jetpack(src) - . = ..() - -/obj/item/clothing/suit/space/hardsuit/attack_self(mob/user) - user.changeNext_move(CLICK_CD_MELEE) - ..() + return ..() /obj/item/clothing/suit/space/hardsuit/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/tank/jetpack/suit)) @@ -167,7 +163,7 @@ desc = "A special helmet designed for work in a hazardous, low-pressure environment. Has radiation shielding." icon_state = "hardsuit0-engineering" item_state = "eng_helm" - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 100, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 100, "acid" = 75, "wound" = 10) hardsuit_type = "engineering" resistance_flags = FIRE_PROOF @@ -176,7 +172,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has radiation shielding." icon_state = "hardsuit-engineering" item_state = "eng_hardsuit" - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 100, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 100, "acid" = 75, "wound" = 10) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine resistance_flags = FIRE_PROOF mutantrace_variation = STYLE_DIGITIGRADE|STYLE_ALL_TAURIC @@ -188,7 +184,7 @@ icon_state = "hardsuit0-atmospherics" item_state = "atmo_helm" hardsuit_type = "atmospherics" - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 75, "wound" = 10) heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -197,7 +193,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has thermal shielding." icon_state = "hardsuit-atmospherics" item_state = "atmo_hardsuit" - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 25, "fire" = 100, "acid" = 75, "wound" = 10) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/atmos @@ -209,7 +205,7 @@ icon_state = "hardsuit0-white" item_state = "ce_helm" hardsuit_type = "white" - armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 90) + armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 90, "wound" = 10) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -218,7 +214,7 @@ name = "advanced hardsuit" desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish." item_state = "ce_hardsuit" - armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 95, "fire" = 100, "acid" = 90) + armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 90, "wound" = 10) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/elite @@ -234,7 +230,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF heat_protection = HEAD - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 75, "wound" = 15) brightness_on = 7 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) @@ -249,7 +245,7 @@ item_state = "mining_hardsuit" max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 75, "wound" = 15) allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -267,7 +263,7 @@ icon_state = "hardsuit1-syndi" item_state = "syndie_helm" hardsuit_type = "syndi" - armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90, "wound" = 25) on = FALSE var/obj/item/clothing/suit/space/hardsuit/syndi/linkedsuit = null actions_types = list(/datum/action/item_action/toggle_helmet_mode) @@ -345,7 +341,7 @@ item_state = "syndie_hardsuit" hardsuit_type = "syndi" w_class = WEIGHT_CLASS_NORMAL - armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90, "wound" = 25) allowed = list(/obj/item/gun, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi jetpack = /obj/item/tank/jetpack/suit @@ -358,7 +354,7 @@ alt_desc = "An elite version of the syndicate helmet, with improved armour and fireproofing. It is in combat mode. Property of Gorlex Marauders." icon_state = "hardsuit0-syndielite" hardsuit_type = "syndielite" - armor = list("melee" = 60, "bullet" = 60, "laser" = 50, "energy" = 25, "bomb" = 55, "bio" = 100, "rad" = 70, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 60, "laser" = 50, "energy" = 25, "bomb" = 55, "bio" = 100, "rad" = 70, "fire" = 100, "acid" = 100, "wound" = 25) heat_protection = HEAD max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -376,7 +372,7 @@ icon_state = "hardsuit0-syndielite" hardsuit_type = "syndielite" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite - armor = list("melee" = 60, "bullet" = 60, "laser" = 50, "energy" = 25, "bomb" = 55, "bio" = 100, "rad" = 70, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 60, "laser" = 50, "energy" = 25, "bomb" = 55, "bio" = 100, "rad" = 70, "fire" = 100, "acid" = 100, "wound" = 25) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -416,7 +412,7 @@ item_state = "wiz_helm" hardsuit_type = "wiz" resistance_flags = FIRE_PROOF | ACID_PROOF //No longer shall our kind be foiled by lone chemists with spray bottles! - armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 30) heat_protection = HEAD //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -431,7 +427,7 @@ item_state = "wiz_hardsuit" w_class = WEIGHT_CLASS_NORMAL resistance_flags = FIRE_PROOF | ACID_PROOF - armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 40, "laser" = 40, "energy" = 20, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 30) allowed = list(/obj/item/teleportation_scroll, /obj/item/tank/internals) heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS //Uncomment to enable firesuit protection max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT @@ -451,7 +447,7 @@ item_state = "medical_helm" hardsuit_type = "medical" flash_protect = 0 - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75, "wound" = 10) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS | SCAN_REAGENTS @@ -474,7 +470,7 @@ item_state = "medical_hardsuit" slowdown = 0.8 allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/firstaid, /obj/item/healthanalyzer, /obj/item/stack/medical) - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 75, "wound" = 10) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/medical mutantrace_variation = STYLE_DIGITIGRADE|STYLE_ALL_TAURIC @@ -486,7 +482,7 @@ hardsuit_type = "rd" resistance_flags = ACID_PROOF | FIRE_PROOF max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80, "wound" = 15) var/obj/machinery/doppler_array/integrated/bomb_radar clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS | SCAN_REAGENTS actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_research_scanner) @@ -516,7 +512,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT //Same as an emergency firesuit. Not ideal for extended exposure. allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/gun/energy/wormhole_projector, /obj/item/hand_tele, /obj/item/aicard) - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80, "wound" = 15) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/rd //Security hardsuit @@ -526,14 +522,14 @@ icon_state = "hardsuit0-sec" item_state = "sec_helm" hardsuit_type = "sec" - armor = list("melee" = 35, "bullet" = 15, "laser" = 30,"energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75) + armor = list("melee" = 35, "bullet" = 15, "laser" = 30,"energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75, "wound" = 20) /obj/item/clothing/suit/space/hardsuit/security icon_state = "hardsuit-sec" name = "security hardsuit" desc = "A special suit that protects against hazardous, low pressure environments. Has an additional layer of armor." item_state = "sec_hardsuit" - armor = list("melee" = 35, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75) + armor = list("melee" = 35, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 75, "acid" = 75, "wound" = 20) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security mutantrace_variation = STYLE_DIGITIGRADE|STYLE_ALL_TAURIC @@ -547,13 +543,13 @@ desc = "A special bulky helmet designed for work in a hazardous, low pressure environment. Has an additional layer of armor." icon_state = "hardsuit0-hos" hardsuit_type = "hos" - armor = list("melee" = 45, "bullet" = 25, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 95, "acid" = 95) + armor = list("melee" = 45, "bullet" = 25, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 95, "acid" = 95, "wound" = 25) /obj/item/clothing/suit/space/hardsuit/security/hos icon_state = "hardsuit-hos" name = "head of security's hardsuit" desc = "A special bulky suit that protects against hazardous, low pressure environments. Has an additional layer of armor." - armor = list("melee" = 45, "bullet" = 25, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 95, "acid" = 95) + armor = list("melee" = 45, "bullet" = 25, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 100, "rad" = 50, "fire" = 95, "acid" = 95, "wound" = 25) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos jetpack = /obj/item/tank/jetpack/suit @@ -563,7 +559,7 @@ icon_state = "capspace" item_state = "capspacehelmet" desc = "A tactical SWAT helmet MK.II boasting better protection and a horrible fashion sense." - armor = list("melee" = 40, "bullet" = 50, "laser" = 50, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 50, "laser" = 50, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 15) resistance_flags = FIRE_PROOF | ACID_PROOF flags_inv = HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR //we want to see the mask heat_protection = HEAD @@ -578,7 +574,7 @@ desc = "A MK.II SWAT suit with streamlined joints and armor made out of superior materials, insulated against intense heat. The most advanced tactical armor available Usually reserved for heavy hitter corporate security, this one has a regal finish in Nanotrasen company colors. Better not let the assistants get a hold of it." icon_state = "caparmor" item_state = "capspacesuit" - armor = list("melee" = 40, "bullet" = 50, "laser" = 50, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 50, "laser" = 50, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 15) resistance_flags = FIRE_PROOF | ACID_PROOF heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT //this needed to be added a long fucking time ago @@ -594,7 +590,7 @@ desc = "A special helmet designed for work in a hazardous, low-humor environment. Has radiation shielding." icon_state = "hardsuit0-clown" item_state = "hardsuit0-clown" - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 30) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 30, "wound" = 10) hardsuit_type = "clown" /obj/item/clothing/suit/space/hardsuit/clown @@ -602,7 +598,7 @@ desc = "A special suit that protects against hazardous, low humor environments. Has radiation shielding. Only a true clown can wear it." icon_state = "hardsuit-clown" item_state = "clown_hardsuit" - armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 30) + armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 30, "wound" = 10) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/clown mutantrace_variation = STYLE_DIGITIGRADE @@ -620,7 +616,7 @@ desc = "Early prototype RIG hardsuit helmet, designed to quickly shift over a user's head. Design constraints of the helmet mean it has no inbuilt cameras, thus it restricts the users visability." icon_state = "hardsuit0-ancient" item_state = "anc_helm" - armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75, "wound" = 10) hardsuit_type = "ancient" resistance_flags = FIRE_PROOF @@ -629,7 +625,7 @@ desc = "Prototype powered RIG hardsuit. Provides excellent protection from the elements of space while being comfortable to move around in, thanks to the powered locomotives. Remains very bulky however." icon_state = "hardsuit-ancient" item_state = "anc_hardsuit" - armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75) + armor = list("melee" = 30, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 75, "wound" = 10) slowdown = 3 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient resistance_flags = FIRE_PROOF @@ -642,7 +638,7 @@ 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) + armor = list("melee" = 20, "bullet" = 15, "laser" = 15, "energy" = 45, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 10) slowdown = 6 //Slow allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage, /obj/item/construction/rcd, /obj/item/pipe_dispenser) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ancient/mason @@ -655,7 +651,7 @@ desc = "The M.A.S.O.N RIG helmet is complimentary to the rest of the armor. It features a very large, high powered flood lamp and robust flash protection." icon_state = "hardsuit0-ancient" item_state = "anc_helm" - armor = list("melee" = 20, "bullet" = 15, "laser" = 15, "energy" = 45, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 20, "bullet" = 15, "laser" = 15, "energy" = 45, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 10) hardsuit_type = "ancient" brightness_on = 16 flash_protect = 5 //We will not be flash by bombs @@ -721,7 +717,7 @@ item_state = "rig0-soviet" hardsuit_type = "soviet" icon_state = "rig0-soviet" - armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75, "wound" = 15) mutantrace_variation = NONE /obj/item/clothing/suit/space/hardsuit/soviet @@ -730,7 +726,7 @@ item_state = "rig-soviet" icon_state = "rig-soviet" slowdown = 0.8 - armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75, "wound" = 15) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/soviet mutantrace_variation = NONE @@ -746,7 +742,7 @@ icon_state = "hardsuit-hos" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/security/hos allowed = null - armor = list("melee" = 30, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 30, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 15) resistance_flags = FIRE_PROOF | ACID_PROOF var/max_charges = 3 //How many charges total the shielding has var/current_charges //if null, will default to max_chargs @@ -775,7 +771,7 @@ item_state = "ert_medical" hardsuit_type = "ert_medical" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf - armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95, "wound" = 30) slowdown = 0 max_charges = 5 @@ -804,7 +800,7 @@ icon_state = "hardsuit0-ert_medical" item_state = "hardsuit0-ert_medical" hardsuit_type = "ert_medical" - armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95, "wound" = 30) /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red icon_state = "hardsuit0-ert_security" @@ -826,7 +822,7 @@ icon_state = "hardsuit1-syndi" item_state = "syndie_hardsuit" hardsuit_type = "syndi" - armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 30) allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi slowdown = 0 @@ -842,7 +838,7 @@ icon_state = "hardsuit1-syndi" item_state = "syndie_helm" hardsuit_type = "syndi" - armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 100, "acid" = 100, "wound" = 30) ///SWAT version /obj/item/clothing/suit/space/hardsuit/shielded/swat @@ -853,7 +849,7 @@ hardsuit_type = "syndi" max_charges = 4 recharge_delay = 15 - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/swat @@ -865,7 +861,7 @@ icon_state = "deathsquad" item_state = "deathsquad" hardsuit_type = "syndi" - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT actions_types = list() @@ -883,7 +879,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | LAVA_PROOF heat_protection = HEAD - armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100) + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100, "wound" = 30) brightness_on = 7 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) var/energy_color = "#35FFF0" @@ -927,7 +923,7 @@ item_state = "swat_suit" max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | LAVA_PROOF - armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100) + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100, "wound" = 30) allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/lavaknight heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 7df91352ca..5124c5d62e 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -22,7 +22,7 @@ Contains: desc = "An advanced tactical space helmet." icon_state = "deathsquad" item_state = "deathsquad" - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -37,7 +37,7 @@ Contains: icon_state = "deathsquad" item_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat) - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -51,7 +51,7 @@ Contains: icon_state = "heavy" item_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat) - armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100, "wound" = 25) strip_delay = 120 resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE @@ -63,7 +63,7 @@ Contains: dynamic_hair_suffix = "+generic" dynamic_fhair_suffix = "+generic" flags_inv = 0 - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -79,7 +79,7 @@ Contains: flags_inv = 0 w_class = WEIGHT_CLASS_NORMAL allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -140,7 +140,7 @@ Contains: desc = "A thick, space-proof tricorne from the royal Space Queen. It's lined with a layer of reflective kevlar." icon_state = "pirate" item_state = "pirate" - armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75) + armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75, "wound" = 30) flags_inv = HIDEHAIR strip_delay = 40 equip_delay_other = 20 @@ -163,7 +163,7 @@ Contains: flags_inv = 0 allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum) slowdown = 0 - armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75) + armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75, "wound" = 30) strip_delay = 40 equip_delay_other = 20 mutantrace_variation = STYLE_DIGITIGRADE @@ -175,7 +175,7 @@ Contains: icon_state = "hardsuit0-ert_commander" item_state = "hardsuit0-ert_commander" hardsuit_type = "ert_commander" - armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 30) strip_delay = 130 brightness_on = 7 resistance_flags = ACID_PROOF @@ -191,7 +191,7 @@ Contains: item_state = "ert_command" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 30) slowdown = 0 strip_delay = 130 resistance_flags = ACID_PROOF @@ -244,7 +244,7 @@ Contains: icon_state = "hardsuit0-ert_commander-alert" item_state = "hardsuit0-ert_commander-alert" hardsuit_type = "ert_commander-alert" - armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50) brightness_on = 8 resistance_flags = FIRE_PROOF | ACID_PROOF @@ -254,7 +254,7 @@ Contains: icon_state = "ert_command-alert" item_state = "ert_command-alert" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert - armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50) resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC @@ -303,7 +303,7 @@ Contains: icon_state = "space" item_state = "s_suit" desc = "A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies." - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65, "wound" = 10) /obj/item/clothing/head/helmet/space/eva name = "EVA helmet" @@ -311,7 +311,7 @@ Contains: item_state = "space" desc = "A lightweight space helmet with the basic ability to protect the wearer from the vacuum of space during emergencies." flash_protect = 0 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65, "wound" = 10) //Radiation /obj/item/clothing/head/helmet/space/rad @@ -319,7 +319,7 @@ Contains: desc = "A special helmet that protects against radiation and space. Not much else unfortunately." icon_state = "cespace_helmet" item_state = "nothing" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = FIRE_PROOF rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE actions_types = list() @@ -329,7 +329,7 @@ Contains: desc = "A special suit that protects against radiation and space. Not much else unfortunately." icon_state = "hardsuit-rad" item_state = "nothing" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = FIRE_PROOF rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE mutantrace_variation = NONE @@ -339,7 +339,7 @@ Contains: desc = "An advanced, space-proof helmet. It appears to be modeled after an old-world eagle." icon_state = "griffinhat" item_state = "griffinhat" - armor = list("melee" = 20, "bullet" = 40, "laser" = 30, "energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 20, "bullet" = 40, "laser" = 30, "energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 20) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = ACID_PROOF | FIRE_PROOF @@ -351,7 +351,7 @@ Contains: icon_state = "freedom" item_state = "freedom" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 20, "bullet" = 40, "laser" = 30,"energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 20, "bullet" = 40, "laser" = 30,"energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 20) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = ACID_PROOF | FIRE_PROOF @@ -364,7 +364,7 @@ Contains: desc = "Spaceworthy and it looks like a space carp's head, smells like one too." icon_state = "carp_helm" item_state = "syndicate" - armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75) //As whimpy as a space carp + armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75, "wound" = 5) //As whimpy as a space carp brightness_on = 0 //luminosity when on actions_types = list() mutantrace_variation = NONE @@ -380,7 +380,7 @@ Contains: icon_state = "carp_suit" item_state = "space_suit_syndicate" slowdown = 0 //Space carp magic, never stop believing - armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75) //As whimpy whimpy whoo + armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75, "wound" = 5) //As whimpy whimpy whoo allowed = list(/obj/item/tank/internals, /obj/item/gun/ballistic/automatic/speargun) //I'm giving you a hint here helmettype = /obj/item/clothing/head/helmet/space/hardsuit/carp mutantrace_variation = STYLE_DIGITIGRADE @@ -442,14 +442,14 @@ Contains: /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) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) slowdown = 0.8 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) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) charges = 12 /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker @@ -467,14 +467,14 @@ Contains: /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) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) slowdown = 0.8 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/beserker/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) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) charges = 6 /obj/item/clothing/head/helmet/space/fragile @@ -482,7 +482,7 @@ Contains: desc = "A bulky, air-tight helmet meant to protect the user during emergency situations. It doesn't look very durable." icon_state = "syndicate-helm-orange" item_state = "syndicate-helm-orange" - armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0) + armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0, "wound" = 5) strip_delay = 65 /obj/item/clothing/suit/space/fragile @@ -492,7 +492,7 @@ Contains: icon_state = "syndicate-orange" item_state = "syndicate-orange" slowdown = 2 - armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0) + armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0, "wound" = 5) strip_delay = 65 /obj/item/clothing/suit/space/fragile/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) @@ -525,7 +525,7 @@ Contains: icon_state = "hunter" item_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat) - armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wpound" = 25) strip_delay = 130 resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index f17eb91b74..5128f77433 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -5,7 +5,7 @@ name = "EVA plasma envirosuit" desc = "A special plasma containment suit designed to be space-worthy, as well as worn over other clothing. Like its smaller counterpart, it can automatically extinguish the wearer in a crisis, and holds twice as many charges." allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank) - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10) resistance_flags = FIRE_PROOF icon_state = "plasmaman_suit" item_state = "plasmaman_suit" @@ -40,7 +40,7 @@ icon_state = "plasmaman-helm" item_state = "plasmaman-helm" strip_delay = 80 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10) resistance_flags = FIRE_PROOF var/brightness_on = 4 //luminosity when the light is on var/on = FALSE @@ -77,7 +77,7 @@ desc = "A plasmaman containment helmet designed for security officers, protecting them from being flashed and burning alive, along-side other undesirables." icon_state = "security_envirohelm" item_state = "security_envirohelm" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 20) /obj/item/clothing/head/helmet/space/plasmaman/security/warden name = "warden's plasma envirosuit helmet" @@ -132,7 +132,7 @@ desc = "A sturdier plasmaman envirohelmet designed for research directors." icon_state = "rd_envirohelm" item_state = "rd_envirohelm" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10) /obj/item/clothing/head/helmet/space/plasmaman/robotics name = "robotics plasma envirosuit helmet" @@ -145,7 +145,7 @@ desc = "A space-worthy helmet specially designed for engineer plasmamen, the usual purple stripes being replaced by engineering's orange." icon_state = "engineer_envirohelm" item_state = "engineer_envirohelm" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 75, "wound" = 10) /obj/item/clothing/head/helmet/space/plasmaman/engineering/ce name = "chief engineer's plasma envirosuit helmet" @@ -194,7 +194,7 @@ desc = "A blue and gold envirohelm designed for the station's captain, nonetheless. Made of superior materials to protect them from the station hazards and more." icon_state = "captain_envirohelm" item_state = "captain_envirohelm" - armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 85) + armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 85, "wound" = 15) /obj/item/clothing/head/helmet/space/plasmaman/curator name = "curator's plasma envirosuit helmet" diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index 662e333f59..f55379da2f 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -4,7 +4,7 @@ icon_state = "syndicate" item_state = "syndicate" desc = "Has a tag on it: Totally not property of an enemy corporation, honest!" - armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85, "wound" = 20) /obj/item/clothing/suit/space/syndicate name = "red space suit" @@ -13,7 +13,7 @@ desc = "Has a tag on it: Totally not property of an enemy corporation, honest!" w_class = WEIGHT_CLASS_NORMAL allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85, "wound" = 20) mutantrace_variation = STYLE_DIGITIGRADE //Green syndicate space suit diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm index 8de49c63de..0d16f9bdfa 100644 --- a/code/modules/clothing/suits/_suits.dm +++ b/code/modules/clothing/suits/_suits.dm @@ -10,6 +10,7 @@ var/blood_overlay_type = "suit" var/togglename = null var/suittoggled = FALSE + limb_integrity = 0 // disabled for most exo-suits mutantrace_variation = STYLE_DIGITIGRADE /obj/item/clothing/suit/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE) @@ -28,7 +29,7 @@ if(A.above_suit) . += U.accessory_overlay -/obj/item/clothing/suit/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/suit/update_clothes_damaged_state() ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 557b4860c9..cf7dbc7462 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -8,7 +8,8 @@ equip_delay_other = 40 max_integrity = 250 resistance_flags = NONE - armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) + armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10) + /obj/item/clothing/suit/armor/Initialize() . = ..() @@ -57,7 +58,7 @@ icon_state = "hos" item_state = "greatcoat" body_parts_covered = CHEST|GROIN|ARMS|LEGS - armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90) + armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 10) cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS strip_delay = 80 @@ -123,7 +124,7 @@ icon_state = "capcarapace" item_state = "armor" body_parts_covered = CHEST|GROIN - armor = list("melee" = 50, "bullet" = 40, "laser" = 50, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 90) + armor = list("melee" = 50, "bullet" = 40, "laser" = 50, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 90, "wound" = 10) dog_fashion = null resistance_flags = FIRE_PROOF @@ -147,7 +148,7 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80) + armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 20) blocks_shove_knockdown = TRUE strip_delay = 80 equip_delay_other = 60 @@ -158,7 +159,7 @@ icon_state = "bonearmor" item_state = "bonearmor" blood_overlay_type = "armor" - armor = list("melee" = 35, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) + armor = list("melee" = 35, "bullet" = 25, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10) body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS /obj/item/clothing/suit/armor/bulletproof @@ -167,7 +168,7 @@ icon_state = "bulletproof" item_state = "armor" blood_overlay_type = "armor" - armor = list("melee" = 15, "bullet" = 60, "laser" = 10, "energy" = 10, "bomb" = 40, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) + armor = list("melee" = 15, "bullet" = 60, "laser" = 10, "energy" = 10, "bomb" = 40, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 20) strip_delay = 70 equip_delay_other = 50 mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -285,8 +286,8 @@ desc = "A classic suit of armour, able to be made from many different materials." icon_state = "knight_greyscale" item_state = "knight_greyscale" - armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40) - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS //Can change color and add prefix + armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40, "wound" = 15) + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix /obj/item/clothing/suit/armor/vest/durathread name = "makeshift vest" @@ -304,7 +305,7 @@ desc = "A bulletproof vest with forest camo. Good thing there's plenty of forests to hide in around here, right?" icon_state = "rus_armor" item_state = "rus_armor" - armor = list("melee" = 25, "bullet" = 30, "laser" = 0, "energy" = 15, "bomb" = 10, "bio" = 0, "rad" = 20, "fire" = 20, "acid" = 50) + armor = list("melee" = 25, "bullet" = 30, "laser" = 0, "energy" = 15, "bomb" = 10, "bio" = 0, "rad" = 20, "fire" = 20, "acid" = 50, "wound" = 10) /obj/item/clothing/suit/armor/vest/russian_coat name = "russian battle coat" @@ -315,4 +316,4 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - armor = list("melee" = 25, "bullet" = 20, "laser" = 20, "energy" = 10, "bomb" = 20, "bio" = 50, "rad" = 20, "fire" = -10, "acid" = 50) + armor = list("melee" = 25, "bullet" = 20, "laser" = 20, "energy" = 10, "bomb" = 20, "bio" = 50, "rad" = 20, "fire" = -10, "acid" = 50, "wound" = 10) diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm index 0a3923b28c..d5f65e4fa8 100644 --- a/code/modules/clothing/suits/cloaks.dm +++ b/code/modules/clothing/suits/cloaks.dm @@ -59,7 +59,7 @@ name = "goliath cloak" icon_state = "goliath_cloak" desc = "A staunch, practical cape made out of numerous monster materials, it is coveted amongst exiles & hermits." - allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/twohanded/spear, /obj/item/twohanded/bonespear, /obj/item/organ/regenerative_core/legion, /obj/item/kitchen/knife/combat/bone, /obj/item/kitchen/knife/combat/survival) + allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/pickaxe, /obj/item/spear, /obj/item/spear/bonespear, /obj/item/organ/regenerative_core/legion, /obj/item/kitchen/knife/combat/bone, /obj/item/kitchen/knife/combat/survival) armor = list("melee" = 35, "bullet" = 10, "laser" = 25, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 60, "acid" = 60) //a fair alternative to bone armor, requiring alternative materials and gaining a suit slot hoodtype = /obj/item/clothing/head/hooded/cloakhood/goliath body_parts_covered = CHEST|ARMS|LEGS @@ -75,7 +75,7 @@ name = "drake armour" 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) + 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/spear) 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 diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 8eaaee9ebc..d6853f52ca 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -402,6 +402,30 @@ min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON +/obj/item/clothing/suit/jacket/flannel + name = "black flannel jacket" + desc = "Comfy and supposedly flammable." + icon_state = "flannel" + item_state = "flannel" + +/obj/item/clothing/suit/jacket/flannel/red + name = "red flannel jacket" + desc = "Comfy and supposedly flammable." + icon_state = "flannel_red" + item_state = "flannel_red" + +/obj/item/clothing/suit/jacket/flannel/aqua + name = "aqua flannel jacket" + desc = "Comfy and supposedly flammable." + icon_state = "flannel_aqua" + item_state = "flannel_aqua" + +/obj/item/clothing/suit/jacket/flannel/brown + name = "brown flannel jacket" + desc = "Comfy and supposedly flammable." + icon_state = "flannel_brown" + item_state = "flannel_brown" + /obj/item/clothing/suit/jacket/leather name = "leather jacket" desc = "Pompadour not included." @@ -519,6 +543,7 @@ cold_protection = HEAD min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT flags_inv = HIDEHAIR|HIDEEARS + rad_flags = RAD_NO_CONTAMINATE /obj/item/clothing/suit/hooded/wintercoat/centcom name = "centcom winter coat" @@ -537,7 +562,7 @@ /obj/item/clothing/suit/hooded/wintercoat/captain name = "captain's winter coat" - desc = "A luxuriant winter coat, stuffed with the down of the endangered Uka bird and trimmed with genuine sable. The fabric is an indulgently soft micro-fiber, and the deep ultramarine color is only one that could be achieved with minute amounts of crystalline bluespace dust woven into the thread between the plectrums. Extremely lavish, and extremely durable. The tiny flakes of protective material make it nothing short of extremely light lamellar armor." + desc = "A luxurious winter coat, stuffed with the down of the endangered Uka bird and trimmed with genuine sable. The fabric is an indulgently soft micro-fiber, and the deep ultramarine color is only one that could be achieved with minute amounts of crystalline bluespace dust woven into the thread between the plectrums. Extremely lavish, and extremely durable. The tiny flakes of protective material make it nothing short of extremely light lamellar armor." icon_state = "coatcaptain" item_state = "coatcaptain" armor = list("melee" = 25, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50) @@ -565,7 +590,7 @@ /obj/item/clothing/suit/hooded/wintercoat/security name = "security winter coat" - desc = "A red, armor-padded winter coat. It glitters with a mild ablative coating and a robust air of authority. The zipper tab is a pair of jingly little handcuffs and got annoying after the first ten seconds." + desc = "A red, armor-padded winter coat. It glitters with a mild ablative coating and a robust air of authority. The zipper tab is a pair of jingly little handcuffs that get annoying after the first ten seconds." icon_state = "coatsecurity" item_state = "coatsecurity" armor = list("melee" = 25, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45) @@ -600,7 +625,7 @@ desc = "An arctic white winter coat with a small blue caduceus instead of a plastic zipper tab. Snazzy." icon_state = "coatmedical" item_state = "coatmedical" - 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) + allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /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/medical @@ -613,7 +638,7 @@ desc = "An arctic white winter coat with a small blue caduceus instead of a plastic zipper tab. The normal liner is replaced with an exceptionally thick, soft layer of fur." icon_state = "coatcmo" item_state = "coatcmo" - 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) + allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /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" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 0) hoodtype = /obj/item/clothing/head/hooded/winterhood/cmo @@ -626,7 +651,7 @@ desc = "A lab-grade winter coat made with acid resistant polymers. For the enterprising chemist who was exiled to a frozen wasteland on the go." icon_state = "coatchemistry" item_state = "coatchemistry" - 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) + allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /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" = 30, "rad" = 0, "fire" = 30, "acid" = 45) hoodtype = /obj/item/clothing/head/hooded/winterhood/chemistry @@ -639,7 +664,7 @@ desc = "A white winter coat with green markings. Warm, but wont fight off the common cold or any other disease. Might make people stand far away from you in the hallway. The zipper tab looks like an oversized bacteriophage." icon_state = "coatviro" item_state = "coatviro" - 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) + allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /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" = 30, "rad" = 0, "fire" = 0, "acid" = 0) hoodtype = /obj/item/clothing/head/hooded/winterhood/viro @@ -652,7 +677,7 @@ 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) + allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /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 @@ -760,6 +785,17 @@ desc = "A green winter coat hood." icon_state = "winterhood_hydro" +/obj/item/clothing/suit/hooded/wintercoat/bar + name = "bartender winter coat" + desc = "A fancy winter coat with a waistcoat and flamboyant bowtie stuck onto it. The zipper tab is actually the bowtie." + icon_state = "coatbar" + item_state = "coatbar" + hoodtype = /obj/item/clothing/head/hooded/winterhood/bar + +/obj/item/clothing/head/hooded/winterhood/bar + desc = "A fancy winter coat hood." + icon_state = "winterhood_bar" + /obj/item/clothing/suit/hooded/wintercoat/cosmic name = "cosmic winter coat" desc = "A starry winter coat that even glows softly." @@ -867,7 +903,7 @@ icon_state = "coatnarsie" item_state = "coatnarsie" armor = list("melee" = 30, "bullet" = 20, "laser" = 30,"energy" = 10, "bomb" = 30, "bio" = 10, "rad" = 10, "fire" = 30, "acid" = 30) - allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/restraints/legcuffs/bola/cult,/obj/item/melee/cultblade,/obj/item/melee/cultblade/dagger,/obj/item/reagent_containers/glass/beaker/unholywater,/obj/item/cult_shift,/obj/item/flashlight/flare/culttorch,/obj/item/twohanded/cult_spear) + allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/restraints/legcuffs/bola/cult,/obj/item/melee/cultblade,/obj/item/melee/cultblade/dagger,/obj/item/reagent_containers/glass/beaker/unholywater,/obj/item/cult_shift,/obj/item/flashlight/flare/culttorch,/obj/item/cult_spear) hoodtype = /obj/item/clothing/head/hooded/winterhood/narsie var/real = TRUE @@ -1022,3 +1058,9 @@ desc = "Reminds you of someone, but you just can't put your finger on it..." icon_state = "waldo_shirt" item_state = "waldo_shirt" + +/obj/item/clothing/suit/samurai + name = "Samurai outfit" + desc = "An outfit used by traditional japanese warriors." + icon_state = "samurai" + item_state = "samurai" diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index 639f2d3bfb..632d59187f 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -76,6 +76,7 @@ /obj/item/clothing/head/hooded var/obj/item/clothing/suit/hooded/suit + dynamic_hair_suffix = "" /obj/item/clothing/head/hooded/Destroy() suit = null @@ -164,7 +165,7 @@ RemoveHelmet() ..() -/obj/item/clothing/suit/space/hardsuit/proc/RemoveHelmet() +/obj/item/clothing/suit/space/hardsuit/proc/RemoveHelmet(message = TRUE) if(!helmet) return suittoggled = FALSE @@ -174,16 +175,18 @@ helmet.attack_self(H) H.transferItemToLoc(helmet, src, TRUE) H.update_inv_wear_suit() - to_chat(H, "The helmet on the hardsuit disengages.") + if(message) + to_chat(H, "The helmet on the hardsuit disengages.") playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1) else helmet.forceMove(src) + return TRUE /obj/item/clothing/suit/space/hardsuit/dropped(mob/user) ..() RemoveHelmet() -/obj/item/clothing/suit/space/hardsuit/proc/ToggleHelmet() +/obj/item/clothing/suit/space/hardsuit/proc/ToggleHelmet(message = TRUE) var/mob/living/carbon/human/H = loc if(!helmettype) return @@ -192,15 +195,19 @@ if(!suittoggled) if(ishuman(src.loc)) if(H.wear_suit != src) - to_chat(H, "You must be wearing [src] to engage the helmet!") + if(message) + to_chat(H, "You must be wearing [src] to engage the helmet!") return if(H.head) - to_chat(H, "You're already wearing something on your head!") + if(message) + to_chat(H, "You're already wearing something on your head!") return else if(H.equip_to_slot_if_possible(helmet,SLOT_HEAD,0,0,1)) - to_chat(H, "You engage the helmet on the hardsuit.") + if(message) + to_chat(H, "You engage the helmet on the hardsuit.") suittoggled = TRUE H.update_inv_wear_suit() playsound(src.loc, 'sound/mecha/mechmove03.ogg', 50, 1) + return TRUE else - RemoveHelmet() + return RemoveHelmet(message) diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index 047dc7b7a3..977e916f87 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -4,11 +4,12 @@ icon_state = "wizard" gas_transfer_coefficient = 0.01 // IT'S MAGICAL OKAY JEEZ +1 TO NOT DIE permeability_coefficient = 0.01 - armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100) + armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100, "wound" = 20) strip_delay = 50 equip_delay_other = 50 resistance_flags = FIRE_PROOF | ACID_PROOF dog_fashion = /datum/dog_fashion/head/blue_wizard + beepsky_fashion = /datum/beepsky_fashion/wizard var/magic_flags = SPELL_WIZARD_HAT /obj/item/clothing/head/wizard/ComponentInitialize() @@ -73,7 +74,7 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 body_parts_covered = CHEST|GROIN|ARMS|LEGS - armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100) + armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 100, "acid" = 100, "wound" = 20) allowed = list(/obj/item/teleportation_scroll) flags_inv = HIDEJUMPSUIT strip_delay = 50 diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index e0ecf24204..23cb2b1c15 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -5,8 +5,9 @@ permeability_coefficient = 0.9 block_priority = BLOCK_PRIORITY_UNIFORM slot_flags = ITEM_SLOT_ICLOTHING - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK + limb_integrity = 30 var/fitted = FEMALE_UNIFORM_FULL // For use in alternate clothing styles for women var/has_sensor = HAS_SENSORS // For the crew computer var/random_sensor = TRUE @@ -39,7 +40,7 @@ if(!attach_accessory(I, user)) return ..() -/obj/item/clothing/under/update_clothes_damaged_state(damaging = TRUE) +/obj/item/clothing/under/update_clothes_damaged_state() ..() if(ismob(loc)) var/mob/M = loc diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index cb173f3bde..ee7e4c48e1 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -369,3 +369,12 @@ icon_state = "plastics" armor = list("melee" = 0, "bullet" = 0, "laser" = 20, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = -40) flags_inv = HIDEACCESSORY + +//necklace +/obj/item/clothing/accessory/necklace + name = "necklace" + desc = "A necklace." + icon_state = "locket" + obj_flags = UNIQUE_RENAME + custom_materials = list(/datum/material/iron=100) + resistance_flags = FIRE_PROOF diff --git a/code/modules/clothing/under/costume.dm b/code/modules/clothing/under/costume.dm index 3e7bc755cb..18cd104ff8 100644 --- a/code/modules/clothing/under/costume.dm +++ b/code/modules/clothing/under/costume.dm @@ -329,3 +329,29 @@ desc = "cloud" icon_state = "cloud" can_adjust = FALSE + +/obj/item/clothing/under/costume/kimono + name = "Kimono" + desc = "A traditional piece of clothing from japan" + icon_state = "kimono" + item_state = "kimono" + +/obj/item/clothing/under/costume/kimono/black + name = "Black Kimono" + icon_state = "kimono_a" + item_state = "kimono_a" + +/obj/item/clothing/under/costume/kimono/kamishimo + name = "Kamishimo" + icon_state = "kamishimo" + item_state = "kamishimo" + +/obj/item/clothing/under/costume/kimono/fancy + name = "Fancy Kimono" + icon_state = "fancy_kimono" + item_state = "fancy_kimono" + +/obj/item/clothing/under/costume/kimono/sakura + name = "Sakura Kimono'" + icon_state = "sakura_kimono" + item_state = "sakura_kimono" diff --git a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm index 5928819b16..082d783bea 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm @@ -57,7 +57,7 @@ desc = "An expensive piece of plasmaman envirosuit fashion. guaranteed to keep you cool while the station goes down in fierceful fires." icon_state = "captain_envirosuit" item_state = "captain_envirosuit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 15) sensor_mode = SENSOR_COORDS random_sensor = FALSE diff --git a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm index 15eb189fa8..4850a605e7 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm @@ -3,7 +3,7 @@ desc = "An air-tight suit designed to be used by plasmamen exployed as engineers, the usual purple stripes being replaced by engineer's orange. It protects the user from fire and acid damage." icon_state = "engineer_envirosuit" item_state = "engineer_envirosuit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95, "wound" = 5) /obj/item/clothing/under/plasmaman/engineering/ce name = "chief engineer's plasma envirosuit" diff --git a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm index 03d089c10d..52f817dcce 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm @@ -21,7 +21,7 @@ desc = "A plasmaman envirosuit designed for the research director to aid them in their job of directing research into the right direction." icon_state = "rd_envirosuit" item_state = "rd_envirosuit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 5) /obj/item/clothing/under/plasmaman/robotics name = "robotics plasma envirosuit" diff --git a/code/modules/clothing/under/jobs/Plasmaman/security.dm b/code/modules/clothing/under/jobs/Plasmaman/security.dm index ddbda041f3..3330d72844 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/security.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/security.dm @@ -3,7 +3,7 @@ desc = "A plasmaman containment suit designed for security officers, offering a limited amount of extra protection." icon_state = "security_envirosuit" item_state = "security_envirosuit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 10) sensor_mode = SENSOR_COORDS random_sensor = FALSE diff --git a/code/modules/clothing/under/jobs/cargo.dm b/code/modules/clothing/under/jobs/cargo.dm index aa4db2fd30..8fbc343598 100644 --- a/code/modules/clothing/under/jobs/cargo.dm +++ b/code/modules/clothing/under/jobs/cargo.dm @@ -34,8 +34,9 @@ mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON /obj/item/clothing/under/rank/cargo/miner - desc = "It's a snappy jumpsuit with a sturdy set of overalls. It is very dirty." name = "shaft miner's jumpsuit" + desc = "It's a snappy jumpsuit with a sturdy set of overalls. It is very dirty." + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 0, "wound" = 10) icon_state = "miner" item_state = "miner" diff --git a/code/modules/clothing/under/jobs/civilian/civilian.dm b/code/modules/clothing/under/jobs/civilian/civilian.dm index 4eb6a18258..5dffc8f88d 100644 --- a/code/modules/clothing/under/jobs/civilian/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian/civilian.dm @@ -110,7 +110,7 @@ desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." name = "janitor's jumpsuit" icon_state = "janitor" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/civilian/janitor/skirt name = "janitor's jumpskirt" diff --git a/code/modules/clothing/under/jobs/command.dm b/code/modules/clothing/under/jobs/command.dm index a614e2fcb3..8272c36cf3 100644 --- a/code/modules/clothing/under/jobs/command.dm +++ b/code/modules/clothing/under/jobs/command.dm @@ -19,6 +19,7 @@ /obj/item/clothing/under/rank/captain/suit name = "captain's suit" desc = "A green suit and yellow necktie. Exemplifies authority." + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 15) icon_state = "green_suit" item_state = "dg_suit" can_adjust = FALSE @@ -46,4 +47,4 @@ icon_state = "lewdcap" item_state = "lewdcap" can_adjust = FALSE - mutantrace_variation = USE_TAUR_CLIP_MASK + mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 3eaaa42620..5693468b3b 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -4,7 +4,7 @@ name = "chief engineer's jumpsuit" icon_state = "chiefengineer" item_state = "gy_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40, "wound" = 5) resistance_flags = NONE /obj/item/clothing/under/rank/engineering/chief_engineer/skirt @@ -39,7 +39,7 @@ name = "engineer's jumpsuit" icon_state = "engine" item_state = "engi_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20, "wound" = 5) resistance_flags = NONE /obj/item/clothing/under/rank/engineering/engineer/hazard diff --git a/code/modules/clothing/under/jobs/medical.dm b/code/modules/clothing/under/jobs/medical.dm index f50e5161b6..c66b972624 100644 --- a/code/modules/clothing/under/jobs/medical.dm +++ b/code/modules/clothing/under/jobs/medical.dm @@ -4,7 +4,7 @@ icon_state = "cmo" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/chief_medical_officer/skirt name = "chief medical officer's jumpskirt" @@ -22,7 +22,7 @@ icon_state = "cmoturtle" item_state = "w_suit" alt_covers_chest = TRUE - mutantrace_variation = USE_TAUR_CLIP_MASK + mutantrace_variation = STYLE_DIGITIGRADE|USE_TAUR_CLIP_MASK /obj/item/clothing/under/rank/medical/geneticist desc = "It's made of a special fiber that gives special protection against biohazards. It has a genetics rank stripe on it." @@ -30,7 +30,7 @@ icon_state = "genetics" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/geneticist/skirt name = "geneticist's jumpskirt" @@ -48,7 +48,7 @@ icon_state = "virology" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/virologist/skirt name = "virologist's jumpskirt" @@ -66,7 +66,7 @@ icon_state = "chemistry" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65, "wound" = 5) /obj/item/clothing/under/rank/medical/chemist/skirt name = "chemist's jumpskirt" @@ -84,13 +84,11 @@ icon_state = "paramedic-dark" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) - can_adjust = FALSE + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/paramedic/light desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic." icon_state = "paramedic-light" - can_adjust = TRUE /obj/item/clothing/under/rank/medical/paramedic/skirt name = "paramedic jumpskirt" @@ -112,7 +110,7 @@ icon_state = "nursesuit" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) body_parts_covered = CHEST|GROIN|ARMS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -124,7 +122,7 @@ icon_state = "medical" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/doctor/blue name = "blue medical scrubs" diff --git a/code/modules/clothing/under/jobs/rnd.dm b/code/modules/clothing/under/jobs/rnd.dm index f7bd6d5e33..03eb910736 100644 --- a/code/modules/clothing/under/jobs/rnd.dm +++ b/code/modules/clothing/under/jobs/rnd.dm @@ -3,7 +3,7 @@ name = "research director's vest suit" icon_state = "director" item_state = "lb_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35, "wound" = 5) can_adjust = FALSE /obj/item/clothing/under/rank/rnd/research_director/skirt @@ -20,7 +20,7 @@ name = "research director's tan suit" icon_state = "rdwhimsy" item_state = "rdwhimsy" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) can_adjust = TRUE alt_covers_chest = TRUE @@ -39,7 +39,7 @@ name = "research director's turtleneck" icon_state = "rdturtle" item_state = "p_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) can_adjust = TRUE alt_covers_chest = TRUE @@ -59,7 +59,7 @@ icon_state = "toxins" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/rnd/scientist/skirt name = "scientist's jumpskirt" diff --git a/code/modules/clothing/under/jobs/security.dm b/code/modules/clothing/under/jobs/security.dm index 26fff7c8ed..7747d2e181 100644 --- a/code/modules/clothing/under/jobs/security.dm +++ b/code/modules/clothing/under/jobs/security.dm @@ -19,7 +19,7 @@ desc = "A tactical security jumpsuit for officers complete with Nanotrasen belt buckle." icon_state = "rsecurity" item_state = "r_suit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30, "wound" = 10) /obj/item/clothing/under/rank/security/officer/grey name = "grey security jumpsuit" @@ -67,7 +67,7 @@ desc = "A formal security suit for officers complete with Nanotrasen belt buckle." icon_state = "rwarden" item_state = "r_suit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30, "wound" = 10) /obj/item/clothing/under/rank/security/warden/grey name = "grey security suit" @@ -101,7 +101,7 @@ desc = "Someone who wears this means business." icon_state = "detective" item_state = "det" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30, "wound" = 10) /obj/item/clothing/under/rank/security/detective/skirt name = "detective's suitskirt" @@ -138,7 +138,7 @@ desc = "A security jumpsuit decorated for those few with the dedication to achieve the position of Head of Security." icon_state = "rhos" item_state = "r_suit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10) strip_delay = 60 /obj/item/clothing/under/rank/security/head_of_security/skirt diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 997f10a379..27fb0cc00d 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -66,7 +66,7 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 1000) //wound defense at 100 wont stop wounds cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -308,3 +308,21 @@ icon_state = "polyfemtankpantsu" poly_states = 2 poly_colors = list("#808080", "#FF3535") + +/obj/item/clothing/under/misc/black_dress + name = "little black dress" + desc = "A small black dress" + icon_state = "littleblackdress_s" + item_state = "littleblackdress_s" + +/obj/item/clothing/under/misc/pinktutu + name = "pink tutu" + desc = "A pink tutu" + icon_state = "pinktutu_s" + item_state = "pinktutu_s" + +/obj/item/clothing/under/misc/bathrobe + name = "bathrobe" + desc = "A blue bathrobe." + icon_state = "bathrobe" + item_state = "bathrobe" diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index 8a88e99d05..72af4e9572 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -4,7 +4,7 @@ icon_state = "syndicate" item_state = "bl_suit" has_sensor = NO_SENSORS - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) alt_covers_chest = TRUE /obj/item/clothing/under/syndicate/skirt @@ -13,7 +13,7 @@ icon_state = "syndicate_skirt" item_state = "bl_suit" has_sensor = NO_SENSORS - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) alt_covers_chest = TRUE fitted = FEMALE_UNIFORM_TOP mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -24,7 +24,7 @@ icon_state = "bloodred_pajamas" item_state = "bl_suit" dummy_thick = TRUE - armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40) + armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40, "wound" = 10) resistance_flags = FIRE_PROOF | ACID_PROOF can_adjust = FALSE @@ -33,21 +33,21 @@ desc = "Do operatives dream of nuclear sheep?" icon_state = "bloodred_pajamas" item_state = "bl_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) /obj/item/clothing/under/syndicate/tacticool name = "tacticool turtleneck" desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool" item_state = "bl_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) /obj/item/clothing/under/syndicate/tacticool/skirt name = "tacticool skirtleneck" desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool_skirt" item_state = "bl_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) fitted = FEMALE_UNIFORM_TOP mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -57,7 +57,7 @@ icon_state = "tactifool" item_state = "bl_suit" has_sensor = TRUE - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/syndicate/sniper name = "Tactical turtleneck suit" @@ -73,12 +73,15 @@ item_state = "g_suit" can_adjust = FALSE +/obj/item/clothing/under/syndicate/camo/cosmetic + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + /obj/item/clothing/under/syndicate/soviet name = "Ratnik 5 tracksuit" desc = "Badly translated labels tell you to clean this in Vodka. Great for squatting in." icon_state = "trackpants" can_adjust = FALSE - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = NONE /obj/item/clothing/under/syndicate/combat @@ -93,7 +96,7 @@ desc = "Military grade tracksuits for frontline squatting." icon_state = "rus_under" can_adjust = FALSE - armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = NONE mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -103,7 +106,7 @@ icon_state = "syndicatebaseball" item_state = "syndicatebaseball" has_sensor = NO_SENSORS - armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 10) alt_covers_chest = TRUE mutantrace_variation = USE_TAUR_CLIP_MASK diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm index 9b114829e1..70e85a9cfb 100644 --- a/code/modules/detectivework/scanner.dm +++ b/code/modules/detectivework/scanner.dm @@ -18,6 +18,7 @@ var/list/log = list() var/range = 8 var/view_check = TRUE + var/forensicPrintCount = 0 actions_types = list(/datum/action/item_action/displayDetectiveScanResults) /datum/action/item_action/displayDetectiveScanResults @@ -42,12 +43,15 @@ /obj/item/detective_scanner/proc/PrintReport() // Create our paper var/obj/item/paper/P = new(get_turf(src)) - P.name = "paper- 'Scanner Report'" - P.info = "
    Scanner Report


    " + + //This could be a global count like sec and med record printouts. See GLOB.data_core.medicalPrintCount AKA datacore.dm + var frNum = ++forensicPrintCount + + P.name = text("FR-[] 'Forensic Record'", frNum) + P.info = text("
    Forensic Record - (FR-[])


    ", frNum) P.info += jointext(log, "
    ") P.info += "
    Notes:
    " - P.info_links = P.info - P.updateinfolinks() + P.update_icon() if(ismob(loc)) var/mob/M = loc @@ -139,6 +143,8 @@ add_log("Blood:") found_something = TRUE for(var/B in blood) + if(B == "color") + continue add_log("Type: [blood[B]] DNA: [B]") //Fibers @@ -216,4 +222,4 @@ return to_chat(user, "Scanner Report") for(var/iterLog in log) - to_chat(user, iterLog) \ No newline at end of file + to_chat(user, iterLog) diff --git a/code/modules/emoji/emoji_parse.dm b/code/modules/emoji/emoji_parse.dm index 65e8063ce0..3fd83899c9 100644 --- a/code/modules/emoji/emoji_parse.dm +++ b/code/modules/emoji/emoji_parse.dm @@ -2,7 +2,8 @@ . = text if(!CONFIG_GET(flag/emojis)) return - var/static/list/emojis = icon_states(icon('icons/emoji.dmi')) + var/list/emojis = icon_states(icon('icons/emoji.dmi')) + emojis |= icon_states(icon('icons/emoji_32.dmi')) var/parsed = "" var/pos = 1 var/search = 0 @@ -15,10 +16,15 @@ search = findtext(text, ":", pos + length(text[pos])) if(search) emoji = lowertext(copytext(text, pos + length(text[pos]), search)) + var/isthisapath = (emoji[1] == "/") && text2path(emoji) var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat) var/tag = sheet.icon_tag("emoji-[emoji]") if(tag) - parsed += tag + parsed += "[tag]" //evil way of enforcing 16x16 + pos = search + length(text[pos]) + else if(ispath(isthisapath, /atom)) //path + var/atom/thisisanatom = isthisapath + parsed += "[icon2html(initial(thisisanatom.icon), world, initial(thisisanatom.icon_state))]" pos = search + length(text[pos]) else parsed += copytext(text, pos, search) @@ -34,7 +40,8 @@ . = text if(!CONFIG_GET(flag/emojis)) return - var/static/list/emojis = icon_states(icon('icons/emoji.dmi')) + var/list/emojis = icon_states(icon('icons/emoji.dmi')) + emojis |= icon_states(icon('icons/emoji_32.dmi')) var/final = "" //only tags are added to this var/pos = 1 var/search = 0 diff --git a/code/modules/events/_event.dm b/code/modules/events/_event.dm index a8ab470d5d..b88bef1c87 100644 --- a/code/modules/events/_event.dm +++ b/code/modules/events/_event.dm @@ -17,9 +17,9 @@ var/holidayID = "" //string which should be in the SSeventss.holidays list if you wish this event to be holiday-specific //anything with a (non-null) holidayID which does not match holiday, cannot run. - var/wizardevent = 0 - - var/alertadmins = 1 //should we let the admins know this event is firing + var/wizardevent = FALSE + var/random = FALSE //If the event has occured randomly, or if it was forced by an admin or in-game occurance + var/alert_observers = TRUE //should we let the ghosts and admins know this event is firing //should be disabled on events that fire a lot var/list/gamemode_blacklist = list() // Event won't happen in these gamemodes @@ -33,7 +33,7 @@ min_players = CEILING(min_players * CONFIG_GET(number/events_min_players_mul), 1) /datum/round_event_control/wizard - wizardevent = 1 + wizardevent = TRUE var/can_be_midround_wizard = TRUE // Checks if the event can be spawned. Used by event controller and "false alarm" event. @@ -67,7 +67,7 @@ return EVENT_CANT_RUN triggering = TRUE - if (alertadmins) + if (alert_observers) message_admins("Random Event triggering in 10 seconds: [name] (CANCEL)") sleep(100) var/gamemode = SSticker.mode.config_tag @@ -92,7 +92,7 @@ log_admin_private("[key_name(usr)] cancelled event [name].") SSblackbox.record_feedback("tally", "event_admin_cancelled", 1, typepath) -/datum/round_event_control/proc/runEvent(random) +/datum/round_event_control/proc/runEvent() var/datum/round_event/E = new typepath() E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1) E.control = src @@ -101,10 +101,9 @@ testing("[time2text(world.time, "hh:mm:ss")] [E.type]") if(random) - if(alertadmins) - deadchat_broadcast("[name] has just been randomly triggered!") //STOP ASSUMING IT'S BADMINS! log_game("Random Event triggering: [name] ([typepath])") - + if (alert_observers) + deadchat_broadcast("[name] has just been[random ? " randomly" : ""] triggered!") //STOP ASSUMING IT'S BADMINS! return E //Special admins setup @@ -140,6 +139,17 @@ /datum/round_event/proc/start() return +/** + * Called after something followable has been spawned by an event + * Provides ghosts a follow link to an atom if possible + * Only called once. + */ +/datum/round_event/proc/announce_to_ghosts(atom/atom_of_interest) + if(control.alert_observers) + if (atom_of_interest) + notify_ghosts("[control.name] has an object of interest: [atom_of_interest]!", source=atom_of_interest, action=NOTIFY_ORBIT, header="Something's Interesting!") + return + //Called when the tick is equal to the announceWhen variable. //Allows you to announce before starting or vice versa. //Only called once. diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm index 69e9a974eb..993577cb30 100644 --- a/code/modules/events/alien_infestation.dm +++ b/code/modules/events/alien_infestation.dm @@ -3,7 +3,7 @@ typepath = /datum/round_event/ghost_role/alien_infestation weight = 5 gamemode_blacklist = list("dynamic") - min_players = 10 + min_players = 25 max_occurrences = 1 /datum/round_event/ghost_role/alien_infestation diff --git a/code/modules/events/anomaly.dm b/code/modules/events/anomaly.dm index d8122eac75..394294db37 100644 --- a/code/modules/events/anomaly.dm +++ b/code/modules/events/anomaly.dm @@ -8,7 +8,7 @@ /datum/round_event/anomaly var/area/impact_area - var/obj/effect/anomaly/newAnomaly + var/obj/effect/anomaly/anomaly_path = /obj/effect/anomaly/flux announceWhen = 1 @@ -27,7 +27,7 @@ //Subtypes from the above that actually should explode. var/list/unsafe_area_subtypes = typecacheof(list(/area/engine/break_room)) - + allowed_areas = make_associative(GLOB.the_station_areas) - safe_area_types + unsafe_area_subtypes return safepick(typecache_filter_list(GLOB.sortedAreas,allowed_areas)) @@ -44,6 +44,9 @@ priority_announce("Localized energetic flux wave detected on long range scanners. Expected location of impact: [impact_area.name].", "Anomaly Alert") /datum/round_event/anomaly/start() - var/turf/T = safepick(get_area_turfs(impact_area)) + var/turf/T = pick(get_area_turfs(impact_area)) + var/newAnomaly if(T) - newAnomaly = new /obj/effect/anomaly/flux(T) \ No newline at end of file + newAnomaly = new anomaly_path(T) + if (newAnomaly) + announce_to_ghosts(newAnomaly) diff --git a/code/modules/events/anomaly_bluespace.dm b/code/modules/events/anomaly_bluespace.dm index a6a0effa2b..395b3b88a5 100644 --- a/code/modules/events/anomaly_bluespace.dm +++ b/code/modules/events/anomaly_bluespace.dm @@ -1,6 +1,7 @@ /datum/round_event_control/anomaly/anomaly_bluespace name = "Anomaly: Bluespace" typepath = /datum/round_event/anomaly/anomaly_bluespace + max_occurrences = 1 weight = 5 gamemode_blacklist = list("dynamic") @@ -8,15 +9,10 @@ /datum/round_event/anomaly/anomaly_bluespace startWhen = 3 announceWhen = 10 - + anomaly_path = /obj/effect/anomaly/bluespace /datum/round_event/anomaly/anomaly_bluespace/announce(fake) if(prob(90)) priority_announce("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") else print_command_report("Unstable bluespace anomaly detected on long range scanners. Expected location: [impact_area.name].", "Unstable bluespace anomaly") - -/datum/round_event/anomaly/anomaly_bluespace/start() - var/turf/T = safepick(get_area_turfs(impact_area)) - if(T) - newAnomaly = new /obj/effect/anomaly/bluespace(T) diff --git a/code/modules/events/anomaly_flux.dm b/code/modules/events/anomaly_flux.dm index f4c78c0ec4..a9a7ed50b9 100644 --- a/code/modules/events/anomaly_flux.dm +++ b/code/modules/events/anomaly_flux.dm @@ -10,14 +10,10 @@ /datum/round_event/anomaly/anomaly_flux startWhen = 10 announceWhen = 3 + anomaly_path = /obj/effect/anomaly/flux /datum/round_event/anomaly/anomaly_flux/announce(fake) if(prob(90)) priority_announce("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") else print_command_report("Localized hyper-energetic flux wave detected on long range scanners. Expected location: [impact_area.name].","Localized hyper-energetic flux wave") - -/datum/round_event/anomaly/anomaly_flux/start() - var/turf/T = safepick(get_area_turfs(impact_area)) - if(T) - newAnomaly = new /obj/effect/anomaly/flux(T) diff --git a/code/modules/events/anomaly_grav.dm b/code/modules/events/anomaly_grav.dm index 8500b44597..cabd7face8 100644 --- a/code/modules/events/anomaly_grav.dm +++ b/code/modules/events/anomaly_grav.dm @@ -1,6 +1,7 @@ /datum/round_event_control/anomaly/anomaly_grav name = "Anomaly: Gravitational" typepath = /datum/round_event/anomaly/anomaly_grav + max_occurrences = 5 weight = 20 gamemode_blacklist = list("dynamic") @@ -9,14 +10,10 @@ /datum/round_event/anomaly/anomaly_grav startWhen = 3 announceWhen = 20 + anomaly_path = /obj/effect/anomaly/grav /datum/round_event/anomaly/anomaly_grav/announce(fake) if(prob(90)) priority_announce("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") else print_command_report("Gravitational anomaly detected on long range scanners. Expected location: [impact_area.name].", "Gravitational anomaly") - -/datum/round_event/anomaly/anomaly_grav/start() - var/turf/T = safepick(get_area_turfs(impact_area)) - if(T) - newAnomaly = new /obj/effect/anomaly/grav(T) diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm index 9594727784..8c8fbd6d36 100644 --- a/code/modules/events/anomaly_pyro.dm +++ b/code/modules/events/anomaly_pyro.dm @@ -1,6 +1,7 @@ /datum/round_event_control/anomaly/anomaly_pyro name = "Anomaly: Pyroclastic" typepath = /datum/round_event/anomaly/anomaly_pyro + max_occurrences = 5 weight = 20 gamemode_blacklist = list("dynamic") @@ -8,14 +9,10 @@ /datum/round_event/anomaly/anomaly_pyro startWhen = 3 announceWhen = 10 + anomaly_path = /obj/effect/anomaly/pyro /datum/round_event/anomaly/anomaly_pyro/announce(fake) if(prob(90)) priority_announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert") else print_command_report("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Pyroclastic anomaly") - -/datum/round_event/anomaly/anomaly_pyro/start() - var/turf/T = safepick(get_area_turfs(impact_area)) - if(T) - newAnomaly = new /obj/effect/anomaly/pyro(T) diff --git a/code/modules/events/anomaly_vortex.dm b/code/modules/events/anomaly_vortex.dm index f6eaea40d5..96d084873d 100644 --- a/code/modules/events/anomaly_vortex.dm +++ b/code/modules/events/anomaly_vortex.dm @@ -10,14 +10,10 @@ /datum/round_event/anomaly/anomaly_vortex startWhen = 10 announceWhen = 3 + anomaly_path = /obj/effect/anomaly/bhole /datum/round_event/anomaly/anomaly_vortex/announce(fake) if(prob(90)) priority_announce("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name]", "Anomaly Alert") else print_command_report("Localized high-intensity vortex anomaly detected on long range scanners. Expected location: [impact_area.name].","Vortex anomaly") - -/datum/round_event/anomaly/anomaly_vortex/start() - var/turf/T = safepick(get_area_turfs(impact_area)) - if(T) - newAnomaly = new /obj/effect/anomaly/bhole(T) diff --git a/code/modules/events/brain_trauma.dm b/code/modules/events/brain_trauma.dm index 9e8c7e483e..3e8182a827 100644 --- a/code/modules/events/brain_trauma.dm +++ b/code/modules/events/brain_trauma.dm @@ -30,4 +30,4 @@ BRAIN_TRAUMA_SPECIAL = 10 )) - H.gain_trauma_type(trauma_type, resistance) \ No newline at end of file + H.gain_trauma_type(trauma_type, resistance) diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index e61af1368d..1c88e68377 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -27,7 +27,6 @@ "How do I vore people?", "ERP?", "Not epic bros...") - threat = 5 /datum/round_event/brand_intelligence/announce(fake) @@ -54,6 +53,7 @@ vendingMachines.Remove(originMachine) originMachine.shut_up = 0 originMachine.shoot_inventory = 1 + announce_to_ghosts(originMachine) /datum/round_event/brand_intelligence/tick() diff --git a/code/modules/events/camerafailure.dm b/code/modules/events/camerafailure.dm index e8556e9118..8d7ef3204c 100644 --- a/code/modules/events/camerafailure.dm +++ b/code/modules/events/camerafailure.dm @@ -3,7 +3,7 @@ typepath = /datum/round_event/camera_failure weight = 100 max_occurrences = 20 - alertadmins = 0 + alert_observers = FALSE /datum/round_event/camera_failure fakeable = FALSE diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm index e6cb043165..2c553fc8a7 100644 --- a/code/modules/events/carp_migration.dm +++ b/code/modules/events/carp_migration.dm @@ -10,6 +10,7 @@ /datum/round_event/carp_migration announceWhen = 3 startWhen = 50 + var/hasAnnounced = FALSE /datum/round_event/carp_migration/setup() startWhen = rand(40, 60) @@ -22,10 +23,16 @@ /datum/round_event/carp_migration/start() + var/mob/living/simple_animal/hostile/carp/fish for(var/obj/effect/landmark/carpspawn/C in GLOB.landmarks_list) if(prob(95)) - new /mob/living/simple_animal/hostile/carp(C.loc) + fish = new (C.loc) else - new /mob/living/simple_animal/hostile/carp/megacarp(C.loc) - + fish = new /mob/living/simple_animal/hostile/carp/megacarp(C.loc) + fishannounce(fish) //Prefer to announce the megacarps over the regular fishies + fishannounce(fish) +/datum/round_event/carp_migration/proc/fishannounce(atom/fish) + if (!hasAnnounced) + announce_to_ghosts(fish) //Only anounce the first fish + hasAnnounced = TRUE diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index 802736d5d4..860685c787 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -4,7 +4,7 @@ weight = 200 max_occurrences = 1000 earliest_start = 0 MINUTES - alertadmins = 0 + alert_observers = FALSE gamemode_blacklist = list("dynamic") /datum/round_event/space_dust diff --git a/code/modules/events/electrical_storm.dm b/code/modules/events/electrical_storm.dm index 6e6abb1cd4..5e5e318e3c 100644 --- a/code/modules/events/electrical_storm.dm +++ b/code/modules/events/electrical_storm.dm @@ -4,7 +4,7 @@ earliest_start = 10 MINUTES min_players = 5 weight = 40 - alertadmins = 0 + alert_observers = FALSE gamemode_blacklist = list("dynamic") /datum/round_event/electrical_storm diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm index e50d89a3a3..ae1d1320a5 100644 --- a/code/modules/events/ghost_role.dm +++ b/code/modules/events/ghost_role.dm @@ -37,7 +37,10 @@ signing up.") else if(status == SUCCESSFUL_SPAWN) message_admins("[role_name] spawned successfully.") - if(!spawned_mobs.len) + if(spawned_mobs.len) + for(var/mob/M in spawned_mobs) + announce_to_ghosts(M) + else message_admins("No mobs found in the `spawned_mobs` list, this is \ a bug.") else diff --git a/code/modules/events/heart_attack.dm b/code/modules/events/heart_attack.dm index a47a8b81b4..b3bc571a4a 100644 --- a/code/modules/events/heart_attack.dm +++ b/code/modules/events/heart_attack.dm @@ -20,4 +20,4 @@ var/mob/living/carbon/human/winner = pickweight(heart_attack_contestants) var/datum/disease/D = new /datum/disease/heart_failure() winner.ForceContractDisease(D, FALSE, TRUE) - notify_ghosts("[winner] is beginning to have a heart attack!", enter_link="(Click to orbit)", source=winner, action=NOTIFY_ORBIT) + announce_to_ghosts(winner) \ No newline at end of file diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index d4f51e995e..06318df4f5 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -35,12 +35,14 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 var/z = pick(SSmapping.levels_by_trait(ZTRAIT_STATION)) var/turf/startT = spaceDebrisStartLoc(startside, z) var/turf/endT = spaceDebrisFinishLoc(startside, z) - new /obj/effect/immovablerod(startT, endT, C.special_target) + var/atom/rod = new /obj/effect/immovablerod(startT, endT, C.special_target) + announce_to_ghosts(rod) /obj/effect/immovablerod name = "immovable rod" desc = "What the fuck is that?" icon = 'icons/obj/objects.dmi' + movement_type = FLOATING icon_state = "immrod" throwforce = 100 move_force = INFINITY @@ -61,10 +63,6 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 z_original = z destination = end special_target = aimed_at - if(notify) - notify_ghosts("\A [src] is inbound!", - enter_link="(Click to orbit)", - source=src, action=NOTIFY_ORBIT) GLOB.poi_list += src var/special_target_valid = FALSE @@ -146,7 +144,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 if(L && (L.density || prob(10))) L.ex_act(EXPLODE_HEAVY) -obj/effect/immovablerod/attack_hand(mob/living/user) +obj/effect/immovablerod/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(ishuman(user)) var/mob/living/carbon/human/U = user if(U.job in list("Research Director")) diff --git a/code/modules/events/pirates.dm b/code/modules/events/pirates.dm index b0b12f3944..9ab5e8d517 100644 --- a/code/modules/events/pirates.dm +++ b/code/modules/events/pirates.dm @@ -25,7 +25,7 @@ ship_name = pick(strings(PIRATE_NAMES_FILE, "ship_names")) /datum/round_event/pirates/announce(fake) - priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") // CITADEL EDIT metabreak + priority_announce("A business proposition has been downloaded and printed out at all communication consoles.", "Incoming Business Proposition", "commandreport") if(fake) return threat_message = new @@ -49,6 +49,7 @@ else priority_announce("Trying to cheat us? You'll regret this!",sender_override = ship_name) if(!shuttle_spawned) + priority_announce("You won't listen to reason? Then we'll take what's yours or die trying!",sender_override = ship_name) spawn_shuttle() /datum/round_event/pirates/start() @@ -80,10 +81,10 @@ var/mob/M = candidates[1] spawner.create(M.ckey) candidates -= M + announce_to_ghosts(M) else - notify_ghosts("Space pirates are waking up!", source = spawner, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE) - - priority_announce("A report has been downloaded and printed out at all communications consoles.", "Incoming Classified Message", "commandreport") //CITADEL EDIT also metabreak here too + announce_to_ghosts(spawner) + priority_announce("Unidentified ship detected near the station.") //Shuttle equipment @@ -94,14 +95,11 @@ icon_state = "dominator" density = TRUE var/active = FALSE - var/obj/item/gps/gps var/credits_stored = 0 var/siphon_per_tick = 5 /obj/machinery/shuttle_scrambler/Initialize(mapload) . = ..() - gps = new/obj/item/gps/internal/pirate(src) - gps.tracking = FALSE update_icon() /obj/machinery/shuttle_scrambler/process() @@ -111,6 +109,7 @@ if(D) var/siphoned = min(D.account_balance,siphon_per_tick) D.adjust_money(-siphoned) + credits_stored += siphoned interrupt_research() else return @@ -119,7 +118,7 @@ /obj/machinery/shuttle_scrambler/proc/toggle_on(mob/user) SSshuttle.registerTradeBlockade(src) - gps.tracking = TRUE + AddComponent(/datum/component/gps, "Nautical Signal") active = TRUE to_chat(user,"You toggle [src] [active ? "on":"off"].") to_chat(user,"The scrambling signal can be now tracked by GPS.") @@ -129,7 +128,7 @@ if(!active) if(alert(user, "Turning the scrambler on will make the shuttle trackable by GPS. Are you sure you want to do it?", "Scrambler", "Yes", "Cancel") == "Cancel") return - if(active || !user.canUseTopic(src)) + if(active || !user.canUseTopic(src, BE_CLOSE)) return toggle_on(user) update_icon() @@ -146,35 +145,31 @@ new /obj/effect/temp_visual/emp(get_turf(S)) /obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user) - new /obj/item/holochip(drop_location(), credits_stored) - to_chat(user,"You retrieve the siphoned credits!") - credits_stored = 0 + if(credits_stored) // Prevents spamming empty holochips + new /obj/item/holochip(drop_location(), credits_stored) + to_chat(user,"You retrieve the siphoned credits!") + credits_stored = 0 + else + to_chat(user,"There's nothing to withdraw.") /obj/machinery/shuttle_scrambler/proc/send_notification() priority_announce("Data theft signal detected, source registered on local gps units.") /obj/machinery/shuttle_scrambler/proc/toggle_off(mob/user) SSshuttle.clearTradeBlockade(src) - gps.tracking = FALSE active = FALSE STOP_PROCESSING(SSobj,src) -/obj/machinery/shuttle_scrambler/update_overlays() - . = ..() +/obj/machinery/shuttle_scrambler/update_icon_state() if(active) - var/mutable_appearance/M = mutable_appearance(icon, "dominator-overlay") - M.color = "#00FFFF" - . += M + icon_state = "dominator-blue" + else + icon_state = "dominator" /obj/machinery/shuttle_scrambler/Destroy() toggle_off() - QDEL_NULL(gps) return ..() -/obj/item/gps/internal/pirate - gpstag = "Nautical Signal" - desc = "You can hear shanties over the static." - /obj/machinery/computer/shuttle/pirate name = "pirate shuttle console" shuttleId = "pirateship" @@ -224,7 +219,8 @@ suit_type = /obj/item/clothing/suit/space helmet_type = /obj/item/clothing/head/helmet/space mask_type = /obj/item/clothing/mask/breath - storage_type = /obj/item/tank/jetpack/void + storage_type = /obj/item/tank/internals/oxygen + /obj/machinery/loot_locator name = "Booty Locator" @@ -279,8 +275,9 @@ /obj/machinery/computer/piratepad_control name = "cargo hold control terminal" - resistance_flags = INDESTRUCTIBLE - var/status_report = "Idle" + ui_x = 600 + ui_y = 230 + var/status_report = "Ready for delivery." var/obj/machinery/piratepad/pad var/warmup_time = 100 var/sending = FALSE @@ -297,7 +294,6 @@ if (istype(I) && istype(I.buffer,/obj/machinery/piratepad)) to_chat(user, "You link [src] with [I.buffer] in [I] buffer.") pad = I.buffer - updateDialog() return TRUE /obj/machinery/computer/piratepad_control/LateInitialize() @@ -310,29 +306,42 @@ else pad = locate() in range(4,src) -/obj/machinery/computer/piratepad_control/ui_interact(mob/user) - . = ..() - var/list/t = list() - t += "
    Cargo Hold Control
    " - t += "Current cargo value : [points]" - t += "
    " - if(!pad) - t += "
    No pad located.

    " - else - t += "
    [status_report]
    " - if(!sending) - t += "Recalculate ValueSend" - else - t += "Stop sending" +/obj/machinery/computer/piratepad_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "CargoHoldTerminal", name) + ui.open() - var/datum/browser/popup = new(user, "piratepad", name, 300, 500) - popup.set_content(t.Join()) - popup.open() +/obj/machinery/computer/piratepad_control/ui_data(mob/user) + var/list/data = list() + data["points"] = points + data["pad"] = pad ? TRUE : FALSE + data["sending"] = sending + data["status_report"] = status_report + return data + +/obj/machinery/computer/piratepad_control/ui_act(action, params) + if(..()) + return + if(!pad) + return + + switch(action) + if("recalc") + recalc() + . = TRUE + if("send") + start_sending() + . = TRUE + if("stop") + stop_sending() + . = TRUE /obj/machinery/computer/piratepad_control/proc/recalc() if(sending) return - status_report = "Predicted value:
    " + status_report = "Predicted value: " + var/value = 0 var/datum/export_report/ex = new for(var/atom/movable/AM in get_turf(pad)) if(AM == pad) @@ -340,7 +349,12 @@ export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, dry_run = TRUE, external_report = ex) for(var/datum/export/E in ex.total_amount) - status_report += E.total_printout(ex,notes = FALSE) + "
    " + status_report += E.total_printout(ex,notes = FALSE) + status_report += " " + value += ex.total_value[E] + + if(!value) + status_report += "0" /obj/machinery/computer/piratepad_control/proc/send() if(!sending) @@ -353,14 +367,15 @@ continue export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, delete_unsold = FALSE, external_report = ex) - status_report = "Sold:
    " + status_report = "Sold: " var/value = 0 for(var/datum/export/E in ex.total_amount) var/export_text = E.total_printout(ex,notes = FALSE) //Don't want nanotrasen messages, makes no sense here. if(!export_text) continue - status_report += export_text + "
    " + status_report += export_text + status_report += " " value += ex.total_value[E] if(!total_report) @@ -373,11 +388,12 @@ points += value + if(!value) + status_report += "Nothing" pad.visible_message("[pad] activates!") flick(pad.sending_state,pad) pad.icon_state = pad.idle_state sending = FALSE - updateDialog() /obj/machinery/computer/piratepad_control/proc/start_sending() if(sending) @@ -396,20 +412,6 @@ pad.icon_state = pad.idle_state deltimer(sending_timer) -/obj/machinery/computer/piratepad_control/Topic(href, href_list) - if(..()) - return - if(pad) - if(href_list["recalc"]) - recalc() - if(href_list["send"]) - start_sending() - if(href_list["stop"]) - stop_sending() - updateDialog() - else - updateDialog() - /datum/export/pirate export_category = EXPORT_PIRATE @@ -434,6 +436,8 @@ var/mob/living/carbon/human/H = AM if(H.stat != CONSCIOUS || !H.mind || !H.mind.assigned_role) //mint condition only return 0 + else if("pirate" in H.faction) //can't ransom your fellow pirates to CentCom! + return 0 else if(H.mind.assigned_role in GLOB.command_positions) return 3000 diff --git a/code/modules/events/processor_overload.dm b/code/modules/events/processor_overload.dm index cf6223bf0d..22e475a8ef 100644 --- a/code/modules/events/processor_overload.dm +++ b/code/modules/events/processor_overload.dm @@ -30,6 +30,7 @@ /datum/round_event/processor_overload/start() for(var/obj/machinery/telecomms/processor/P in GLOB.telecomms_list) if(prob(10)) + announce_to_ghosts(P) // Damage the surrounding area to indicate that it popped explosion(get_turf(P), 0, 0, 2) // Only a level 1 explosion actually damages the machine diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 85bcf4959d..7cf11848e8 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -171,10 +171,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - if(!GM.gases[/datum/gas/oxygen]) - return - GM.gases[/datum/gas/oxygen] = max(GM.gases[/datum/gas/oxygen] - severity * holder.energy, 0) - GAS_GARBAGE_COLLECT(GM.gases) + GM.set_moles(/datum/gas/oxygen, max(GM.get_moles(/datum/gas/oxygen) - severity * holder.energy, 0)) /datum/spacevine_mutation/nitro_eater name = "nitrogen consuming" @@ -186,10 +183,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - if(!GM.gases[/datum/gas/nitrogen]) - return - GM.gases[/datum/gas/nitrogen] = max(GM.gases[/datum/gas/nitrogen] - severity * holder.energy, 0) - GAS_GARBAGE_COLLECT(GM.gases) + GM.set_moles(/datum/gas/nitrogen, max(GM.get_moles(/datum/gas/nitrogen) - severity * holder.energy, 0)) /datum/spacevine_mutation/carbondioxide_eater name = "CO2 consuming" @@ -201,10 +195,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - if(!GM.gases[/datum/gas/carbon_dioxide]) - return - GM.gases[/datum/gas/carbon_dioxide] = max(GM.gases[/datum/gas/carbon_dioxide] - severity * holder.energy, 0) - GAS_GARBAGE_COLLECT(GM.gases) + GM.set_moles(/datum/gas/carbon_dioxide, max(GM.get_moles(/datum/gas/carbon_dioxide) - severity * holder.energy, 0)) /datum/spacevine_mutation/plasma_eater name = "toxins consuming" @@ -216,10 +207,7 @@ var/turf/open/floor/T = holder.loc if(istype(T)) var/datum/gas_mixture/GM = T.air - if(!GM.gases[/datum/gas/plasma]) - return - GM.gases[/datum/gas/plasma] = max(GM.gases[/datum/gas/plasma] - severity * holder.energy, 0) - GAS_GARBAGE_COLLECT(GM.gases) + GM.set_moles(/datum/gas/plasma, max(GM.get_moles(/datum/gas/plasma) - severity * holder.energy, 0)) /datum/spacevine_mutation/thorns name = "thorny" @@ -336,7 +324,7 @@ damage_dealt *= 4 if(I.damtype == BURN) damage_dealt *= 4 - + user.DelayNextAction() for(var/datum/spacevine_mutation/SM in mutations) damage_dealt = SM.on_hit(src, user, I, damage_dealt) //on_hit now takes override damage as arg and returns new value for other mutations to permutate further take_damage(damage_dealt, I.damtype, "melee", 1) @@ -357,8 +345,7 @@ for(var/datum/spacevine_mutation/SM in mutations) SM.on_cross(src, AM) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/spacevine/attack_hand(mob/user) +/obj/structure/spacevine/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) for(var/datum/spacevine_mutation/SM in mutations) SM.on_hit(src, user) user_unbuckle_mob(user, user) @@ -368,6 +355,7 @@ for(var/datum/spacevine_mutation/SM in mutations) SM.on_hit(src, user) user_unbuckle_mob(user,user) + return ..() /obj/structure/spacevine/attack_alien(mob/living/user) eat(user) @@ -383,7 +371,9 @@ /datum/spacevine_controller/New(turf/location, list/muts, potency, production, datum/round_event/event = null) vines = list() growth_queue = list() - spawn_spacevine_piece(location, null, muts) + var/obj/structure/spacevine/SV = spawn_spacevine_piece(location, null, muts) + if (event) + event.announce_to_ghosts(SV) START_PROCESSING(SSobj, src) vine_mutations_list = list() init_subtypes(/datum/spacevine_mutation/, vine_mutations_list) diff --git a/code/modules/events/spider_infestation.dm b/code/modules/events/spider_infestation.dm index 2cba5fc529..d1c327e0f7 100644 --- a/code/modules/events/spider_infestation.dm +++ b/code/modules/events/spider_infestation.dm @@ -35,6 +35,6 @@ var/spawn_type = /obj/structure/spider/spiderling if(prob(66)) spawn_type = /obj/structure/spider/spiderling/nurse - spawn_atom_to_turf(spawn_type, vent, 1, FALSE) + announce_to_ghosts(spawn_atom_to_turf(spawn_type, vent, 1, FALSE)) vents -= vent spawncount-- diff --git a/code/modules/events/stray_cargo.dm b/code/modules/events/stray_cargo.dm index 43c51fd5c8..031642c875 100644 --- a/code/modules/events/stray_cargo.dm +++ b/code/modules/events/stray_cargo.dm @@ -2,7 +2,7 @@ /datum/round_event_control/stray_cargo name = "Stray Cargo Pod" typepath = /datum/round_event/stray_cargo - weight = 20 + weight = 5 max_occurrences = 4 earliest_start = 10 MINUTES @@ -85,8 +85,8 @@ /datum/round_event_control/stray_cargo/syndicate name = "Stray Syndicate Cargo Pod" typepath = /datum/round_event/stray_cargo/syndicate - weight = 6 - max_occurrences = 1 + weight = 0 + max_occurrences = 0 earliest_start = 30 MINUTES /datum/round_event/stray_cargo/syndicate diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm new file mode 100644 index 0000000000..c7b982eda8 --- /dev/null +++ b/code/modules/events/travelling_trader.dm @@ -0,0 +1,331 @@ +/datum/round_event_control/travelling_trader + name = "Travelling Trader" + typepath = /datum/round_event/travelling_trader + weight = 8 + max_occurrences = 2 + earliest_start = 0 MINUTES + +/datum/round_event/travelling_trader + startWhen = 0 + endWhen = 900 //you effectively have 15 minutes to complete the traders request, before they disappear + var/mob/living/carbon/human/dummy/travelling_trader/trader + var/atom/spawn_location //where the trader appears + +/datum/round_event/travelling_trader/setup() + if(GLOB.generic_event_spawns) + spawn_location = pick(GLOB.generic_event_spawns) + else + message_admins("No event spawn landmarks exist on the map while placing a travelling trader, resorting to random station turf. (go yell at a mapper)") + spawn_location = get_random_station_turf() + +/datum/round_event/travelling_trader/start() + //spawn a type of trader + var/trader_type = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader)) + trader = new trader_type(get_turf(spawn_location)) + var/datum/effect_system/smoke_spread/smoke = new + smoke.set_up(1, spawn_location) + smoke.start() + trader.visible_message("[src] suddenly appears in a puff of smoke!") + +/datum/round_event/travelling_trader/announce(fake) + priority_announce("A mysterious figure has been detected on sensors at [get_area(spawn_location)]", "Mysterious Figure") + +/datum/round_event/travelling_trader/end() + if(trader) + trader.visible_message("The [src] has given up on waiting!") + qdel(trader) + +//the actual trader mob +/mob/living/carbon/human/dummy/travelling_trader //similar to a dummy because we want to be resource-efficient + var/trader_name = "Debug Travelling Trader" + status_flags = GODMODE //avoid scenarios of people trying to kill the trader + move_resist = MOVE_FORCE_VERY_STRONG //you can't bluespace bodybag them! + var/datum/outfit/trader_outfit + var/list/possible_wanted_items //weighted list of possible things to request + var/list/possible_rewards //weighted list of possible things to give in return for the requested item + var/atom/requested_item //the thing they chose from possible_wanted_items + var/last_speech //last time someone tried interacting with them using their hand + var/last_refusal //last time they vocally refused an item given to them + var/initial_speech = "It looks like the coders did a mishap!" //first thing they say when interacted with, like a description + var/speech_verb = "says" + var/request_speech = "Please bring me a requested_item you shall be greatly rewarded!" //second thing they say when interacted with + var/acceptance_speech = "This is exactly what I wanted! I shall be on my way now, thank you.!" + var/refusal_speech = "A given_item? I wanted a requested_item!" //what they say when refusing an item + var/active = TRUE + var/examine_text = list("You attempt to look directly at the being's face, but it's just a blur!") + move_resist = MOVE_FORCE_VERY_STRONG + mob_size = MOB_SIZE_LARGE + alpha = 200 + +/mob/living/carbon/human/dummy/travelling_trader/examine(mob/user) + SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, examine_text) + return examine_text + +/mob/living/carbon/human/dummy/travelling_trader/proc/setup_speech(var/input_speech, var/obj/item/given_item) + if(requested_item) + input_speech = replacetext(input_speech, "requested_item", initial(requested_item.name)) + if(given_item) + input_speech = replacetext(input_speech, "given_item", given_item.name) + return input_speech + +/mob/living/carbon/human/dummy/travelling_trader/on_attack_hand(mob/living/carbon/human/H) + if(active && last_speech + 3 < world.realtime) //can only talk once per 3 seconds, to avoid spam + last_speech = world.realtime + if(initial_speech) + visible_message("[src] [speech_verb] \"[setup_speech(initial_speech)]\"") + sleep(15) + if(active && request_speech) //they might not be active anymore because of the prior sleep! + visible_message("[src] [speech_verb] \"[setup_speech(request_speech)]\"") + +/mob/living/carbon/human/dummy/travelling_trader/attackby(obj/item/I, mob/user) + if(active) + if(check_item(I)) + active = FALSE + visible_message("[src] [speech_verb] \"[setup_speech(acceptance_speech, I)]\"") + qdel(I) + sleep(15) + give_reward(user) + qdel(src) + else + if(last_refusal + 3 < world.realtime) + last_refusal = world.realtime + visible_message("[src] [speech_verb] \"[setup_speech(refusal_speech, I)]\"") + +/mob/living/carbon/human/dummy/travelling_trader/proc/check_item(var/obj/item/supplied_item) //sometimes we might want to care about the properties of the item, etc + return istype(supplied_item, requested_item) + +/mob/living/carbon/human/dummy/travelling_trader/proc/give_reward() + var/reward = pickweight(possible_rewards) + new reward(get_turf(src)) + +/mob/living/carbon/human/dummy/travelling_trader/Initialize() + ..() + add_atom_colour("#570d6b", FIXED_COLOUR_PRIORITY) //make them purple (otherworldly!) + set_light(1, -0.7, "#AAD84B") + ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood + equipOutfit(trader_outfit, TRUE) + for(var/obj/item/item in src.get_equipped_items()) + ADD_TRAIT(item, TRAIT_NODROP, "trader_no_drop") //don't let people steal the travellers clothes! + item.resistance_flags |= INDESTRUCTIBLE //don't let people burn their clothes off, either. + if(!requested_item) //sometimes we already picked one + requested_item = pickweight(possible_wanted_items) + name = trader_name //gets changed in humans initialisation so we set it here + +/mob/living/carbon/human/dummy/travelling_trader/Destroy() + var/datum/effect_system/smoke_spread/smoke = new + smoke.set_up(1, loc) + smoke.start() + visible_message("[src] disappears in a puff of smoke, leaving something on the ground!") + ..() + +//travelling trader subtypes (the types that can actually spawn) +//so far there's: cook / botanist / bartender / animal hunter / artifact dealer / surgeon (6 types!) + +//cook +/mob/living/carbon/human/dummy/travelling_trader/cook + trader_name = "Otherworldly Chef" + trader_outfit = /datum/outfit/job/cook + initial_speech = "Mama-mia! I have came to this plane of existence, searching the greatest of foods!" + request_speech = "Can you fetch me the delicacy known as requested_item? I would pay you for your service!" + acceptance_speech = "Grazie! You have done me a service, my friend." + refusal_speech = "A given_item? Surely you must be joking!" + possible_rewards = list(/obj/item/paper/secretrecipe = 1, + /obj/item/pizzabox/infinite = 1, + /obj/item/kitchen/fork/throwing = 1, + /mob/living/simple_animal/cow/random = 1) + +/mob/living/carbon/human/dummy/travelling_trader/cook/Initialize() + //pick a random crafted food item as the requested item + var/datum/crafting_recipe/food_recipe = pick(subtypesof(/datum/crafting_recipe/food)) + var/result = initial(food_recipe.result) + if(ispath(result, /obj/item/reagent_containers/food)) //not all food recipes make food objects (like cak/butterbear) + requested_item = result + else + requested_item = /obj/item/reagent_containers/food/snacks/copypasta + ..() + +//botanist +/mob/living/carbon/human/dummy/travelling_trader/gardener + trader_name = "Otherworldly Gardener" + trader_outfit = /datum/outfit/job/botanist + initial_speech = "I have come across this realm in search of rare plants and believe this station may be able to help me.." + request_speech = "Are you able to bring me the plant known to you as: 'requested_item'? I could see that you get some reward for this task." + acceptance_speech = "Amazing! Ill finally be able to make that salad. Goodbye for now!" + refusal_speech = "A given_item? Did nobody ever teach you the basics of gardening?" + possible_rewards = list(/obj/item/seeds/cherry/bomb = 1, + /obj/item/storage/box/strange_seeds_5pack = 6, + /obj/item/clothing/suit/hooded/bee_costume = 2, + /obj/item/seeds/gatfruit = 1) //overall you have less chance of seeing them than a lifebringer just bringing the seeds to you directly + + +/mob/living/carbon/human/dummy/travelling_trader/gardener/Initialize() + requested_item = pick(subtypesof(/obj/item/reagent_containers/food/snacks/grown) - list(/obj/item/reagent_containers/food/snacks/grown/shell, + /obj/item/reagent_containers/food/snacks/grown/shell/gatfruit, + /obj/item/reagent_containers/food/snacks/grown/cherry_bomb)) + ..() + +//animal hunter +/mob/living/carbon/human/dummy/travelling_trader/animal_hunter + trader_name = "Otherworldly Animal Specialist" + trader_outfit = /datum/outfit/job/doctor + initial_speech = "Greetings, lifeform. I am here to locate a special creature aboard your station." + request_speech = "Find me the creature known as 'requested_item' and hand it to me, preferably in a suitable container." + refusal_speech = "Do you think me to be a fool, lifeform? I know a requested_item when I see one." + possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi = 4, + /mob/living/carbon/monkey = 1, + /mob/living/simple_animal/mouse = 2) + possible_rewards = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi = 1, //rewards are animals, friendly to only the person who handed the reward in! + /mob/living/simple_animal/cockroach = 1, + /mob/living/simple_animal/hostile/skeleton = 1, + /mob/living/simple_animal/hostile/stickman = 1, + /mob/living/simple_animal/hostile/stickman/dog = 1, + /mob/living/simple_animal/hostile/asteroid/fugu = 1, + /mob/living/simple_animal/hostile/bear = 1, + /mob/living/simple_animal/hostile/retaliate/clown/fleshclown = 1, + /mob/living/simple_animal/hostile/tree = 1, + /mob/living/simple_animal/hostile/mimic = 1, + /mob/living/simple_animal/hostile/shark = 1, + /mob/living/simple_animal/hostile/netherworld/blankbody = 1, + /mob/living/simple_animal/hostile/retaliate/goose = 1) + +mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() + acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection.")) + ..() + +/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied + for(var/atom/something in supplied_item.contents) + if(istype(something, requested_item)) + qdel(something) //typically things holding mobs release the mob when the container is deleted, so delete the mob first here + return TRUE + return FALSE + +/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(var/mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea + var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src)) + var/chosen_animal = pickweight(possible_rewards) + var/mob/living/new_animal = new chosen_animal(jar) + if(giver && giver.tag) + new_animal.faction += "\[[giver.tag]\]" + jar.add_occupant(new_animal) + jar.name = "WARNING: [new_animal]" + +//bartender +/mob/living/carbon/human/dummy/travelling_trader/bartender + trader_name = "Otherworldly Bartender" + trader_outfit = /datum/outfit/job/bartender + initial_speech = "Greetings, station inhabitor. I came to this dimension in the pursuit of a particular drink." + request_speech = "Bring me thirty units of the beverage known as 'requested_item'." + acceptance_speech = "This is truly the drink I have been seeking. Thank you." + refusal_speech = "Do not mess with me, simpleton, I do not wish for that which you are trying to give me." + possible_rewards = list(/obj/structure/reagent_dispensers/keg/neurotoxin = 1, //all kegs have 250u aside from neurotoxin/hearty punch which have 100u + /obj/structure/reagent_dispensers/keg/hearty_punch = 3, + /obj/structure/reagent_dispensers/keg/red_queen = 3, + /obj/structure/reagent_dispensers/keg/narsour = 3, + /obj/structure/reagent_dispensers/keg/quintuple_sec = 3) + +/mob/living/carbon/human/dummy/travelling_trader/bartender/Initialize() //pick a subtype of ethanol that isn't found in the default set of the booze dispensers reagents + requested_item = pick(subtypesof(/datum/reagent/consumable/ethanol) - list(/datum/reagent/consumable/ethanol/beer, + /datum/reagent/consumable/ethanol/kahlua, + /datum/reagent/consumable/ethanol/whiskey, + /datum/reagent/consumable/ethanol/wine, + /datum/reagent/consumable/ethanol/vodka, + /datum/reagent/consumable/ethanol/gin, + /datum/reagent/consumable/ethanol/rum, + /datum/reagent/consumable/ethanol/tequila, + /datum/reagent/consumable/ethanol/vermouth, + /datum/reagent/consumable/ethanol/cognac, + /datum/reagent/consumable/ethanol/ale, + /datum/reagent/consumable/ethanol/absinthe, + /datum/reagent/consumable/ethanol/hcider, + /datum/reagent/consumable/ethanol/creme_de_menthe, + /datum/reagent/consumable/ethanol/creme_de_cacao, + /datum/reagent/consumable/ethanol/creme_de_coconut, + /datum/reagent/consumable/ethanol/triple_sec, + /datum/reagent/consumable/ethanol/sake, + /datum/reagent/consumable/ethanol/applejack)) + ..() + +/mob/living/carbon/human/dummy/travelling_trader/bartender/check_item(var/obj/item/supplied_item) //you need to check its reagents + if(istype(supplied_item, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/supplied_container = supplied_item + if(supplied_container.reagents.has_reagent(requested_item, 30)) + return TRUE + return FALSE + +//artifact dealer +/mob/living/carbon/human/dummy/travelling_trader/artifact_dealer + trader_name = "Otherworldly Artifact Dealer" + trader_outfit = /datum/outfit/artifact_dealer //he's cool enough to get his own outfit + initial_speech = "I have come here due to sensing the existence of an object of great power and importance." + request_speech = "Give to me the great object known as: requested_item and I shall make it worth your while, traveller." + acceptance_speech = "This is truly an artifact worthy of my collection, thank you." + refusal_speech = "A given_item? Hah! Worthless." + possible_wanted_items = list(/obj/item/pen/fountain/captain = 1, //various rare things and high risk but not useful things (i.e. champion belt, bedsheet, pen) + /obj/item/storage/belt/champion = 1, + /obj/item/clothing/shoes/wheelys = 1, + /obj/item/relic = 1, + /obj/item/flashlight/lamp/bananalamp = 1, + /obj/item/storage/box/hug = 1, + /obj/item/clothing/gloves/color/yellow = 1, + /obj/item/instrument/saxophone = 1, + /obj/item/bedsheet/captain = 1, + /obj/item/slime_extract/green = 1, + /obj/item/chainsaw = 1, + /obj/item/clothing/head/crown = 1) + possible_rewards = list(/obj/item/storage/bag/money/c5000 = 5, + /obj/item/circuitboard/computer/arcade/amputation = 2, + /obj/item/stack/sticky_tape/infinite = 2, + /obj/item/clothing/suit/hooded/wintercoat/cosmic = 2) + +/mob/living/carbon/human/dummy/travelling_trader/artifact_dealer/Initialize() + possible_rewards += list(pick(subtypesof(/obj/item/clothing/head/collectable)) = 1) //this is slightly lower because it's absolutely useless + ..() + +/datum/outfit/artifact_dealer + name = "Artifact Dealer" + uniform = /obj/item/clothing/under/suit/black_really + shoes = /obj/item/clothing/shoes/combat + head = /obj/item/clothing/head/that + glasses = /obj/item/clothing/glasses/monocle + +//surgeon +/mob/living/carbon/human/dummy/travelling_trader/surgeon + trader_name = "Otherworldly Surgeon" + trader_outfit = /datum/outfit/otherworldly_surgeon + initial_speech = "Hello there, meatbag. You can provide me with something I want." + request_speech = "Find me the appendage you call 'requested_item'. I shall make sure it's worth your efforts." + acceptance_speech = "This shall do. Goodbye, meatbag." + refusal_speech = "That is not what I wish for. Give me a requested_item, or I shall take one by force." + possible_wanted_items = list(/obj/item/bodypart/l_arm = 4, + /obj/item/bodypart/r_arm = 4, + /obj/item/bodypart/l_leg = 4, + /obj/item/bodypart/r_leg = 4, + /obj/item/organ/tongue = 2, + /obj/item/organ/liver = 2, + /obj/item/organ/lungs = 2, + /obj/item/organ/heart = 2, + /obj/item/organ/eyes = 1, + /obj/item/organ/brain = 1, + /obj/item/bodypart/head = 1) + possible_rewards = list(/obj/item/organ/cyberimp/mouth/breathing_tube = 1, + /obj/item/organ/eyes/robotic/thermals = 1, + /obj/item/organ/cyberimp/arm/toolset = 1, + /obj/item/organ/cyberimp/arm/surgery = 1, + /obj/item/organ/cyberimp/arm/janitor = 1, + /obj/item/organ/cyberimp/arm/flash = 1, + /obj/item/organ/cyberimp/arm/shield = 1, + /obj/item/organ/cyberimp/eyes/hud/medical = 1, + /obj/item/organ/cyberimp/arm/baton = 1) + +/mob/living/carbon/human/dummy/travelling_trader/surgeon/give_reward() + var/chosen_implant = pickweight(possible_rewards) + var/new_implant = new chosen_implant + var/obj/item/autosurgeon/reward = new(get_turf(src)) + reward.insert_organ(new_implant) + +/datum/outfit/otherworldly_surgeon + name = "Otherworldly Surgeon" + uniform = /obj/item/clothing/under/pants/white + shoes = /obj/item/clothing/shoes/sneakers/white + gloves = /obj/item/clothing/gloves/color/latex + mask = /obj/item/clothing/mask/surgical + suit = /obj/item/clothing/suit/apron/surgical diff --git a/code/modules/events/vent_clog.dm b/code/modules/events/vent_clog.dm index 48fb688d70..dc672cec45 100644 --- a/code/modules/events/vent_clog.dm +++ b/code/modules/events/vent_clog.dm @@ -140,22 +140,6 @@ typepath = /datum/round_event/vent_clog/plasma_decon max_occurrences = 0 -/datum/round_event_control/vent_clog/female - name = "Clogged Vents; Girlcum" - typepath = /datum/round_event/vent_clog/female - max_occurrences = 0 - -/datum/round_event/vent_clog/female - reagentsAmount = 100 - -/datum/round_event_control/vent_clog/male - name = "Clogged Vents: Semen" - typepath = /datum/round_event/vent_clog/male - max_occurrences = 0 - -/datum/round_event/vent_clog/male - reagentsAmount = 100 - /datum/round_event/vent_clog/beer/announce() priority_announce("The scrubbers network is experiencing an unexpected surge of pressurized beer. Some ejection of contents may occur.", "Atmospherics alert") @@ -171,36 +155,6 @@ foam.start() CHECK_TICK -/datum/round_event/vent_clog/male/announce() - priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejaculation of contents may occur.", "Atmospherics alert") - -/datum/round_event/vent_clog/male/start() - for(var/obj/machinery/atmospherics/components/unary/vent in vents) - if(vent && vent.loc && !vent.welded) - var/datum/reagents/R = new/datum/reagents(1000) - R.my_atom = vent - R.add_reagent(/datum/reagent/consumable/semen, reagentsAmount) - - var/datum/effect_system/foam_spread/foam = new - foam.set_up(200, get_turf(vent), R) - foam.start() - CHECK_TICK - -/datum/round_event/vent_clog/female/announce() - priority_announce("The scrubbers network is experiencing a backpressure squirt. Some ejection of contents may occur.", "Atmospherics alert") - -/datum/round_event/vent_clog/female/start() - for(var/obj/machinery/atmospherics/components/unary/vent in vents) - if(vent && vent.loc && !vent.welded) - var/datum/reagents/R = new/datum/reagents(1000) - R.my_atom = vent - R.add_reagent(/datum/reagent/consumable/femcum, reagentsAmount) - - var/datum/effect_system/foam_spread/foam = new - foam.set_up(200, get_turf(vent), R) - foam.start() - CHECK_TICK - /datum/round_event/vent_clog/plasma_decon/announce() priority_announce("We are deploying an experimental plasma decontamination system. Please stand away from the vents and do not breathe the smoke that comes out.", "Central Command Update") diff --git a/code/modules/events/wisdomcow.dm b/code/modules/events/wisdomcow.dm index 4a50ccb306..553dd8f309 100644 --- a/code/modules/events/wisdomcow.dm +++ b/code/modules/events/wisdomcow.dm @@ -2,7 +2,7 @@ name = "Wisdom cow" typepath = /datum/round_event/wisdomcow max_occurrences = 1 - weight = 20 + weight = 10 /datum/round_event/wisdomcow/announce(fake) priority_announce("A wise cow has been spotted in the area. Be sure to ask for her advice.", "Nanotrasen Cow Ranching Agency") diff --git a/code/modules/events/wizard/madness.dm b/code/modules/events/wizard/madness.dm new file mode 100644 index 0000000000..ac86236623 --- /dev/null +++ b/code/modules/events/wizard/madness.dm @@ -0,0 +1,28 @@ +/datum/round_event_control/wizard/madness + name = "Curse of Madness" + weight = 1 + typepath = /datum/round_event/wizard/madness + earliest_start = 0 MINUTES + + var/forced_secret + +/datum/round_event_control/wizard/madness/admin_setup() + if(!check_rights(R_FUN)) + return + + var/suggested = pick(strings(REDPILL_FILE, "redpill_questions")) + + forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sortList(suggested)) as text|null) || suggested + +/datum/round_event/wizard/madness/start() + var/datum/round_event_control/wizard/madness/C = control + + var/horrifying_truth + + if(C.forced_secret) + horrifying_truth = C.forced_secret + C.forced_secret = null + else + horrifying_truth = pick(strings(REDPILL_FILE, "redpill_questions")) + + curse_of_madness(null, horrifying_truth) diff --git a/code/modules/events/wizard/magicarp.dm b/code/modules/events/wizard/magicarp.dm index 4d2e8e624c..57e2a2a051 100644 --- a/code/modules/events/wizard/magicarp.dm +++ b/code/modules/events/wizard/magicarp.dm @@ -30,7 +30,6 @@ icon_dead = "magicarp_dead" icon_gib = "magicarp_gib" ranged = 1 - threat = 4 retreat_distance = 2 minimum_distance = 0 //Between shots they can and will close in to nash projectiletype = /obj/item/projectile/magic @@ -52,7 +51,6 @@ color = "#00FFFF" maxHealth = 75 health = 75 - threat = 7 /mob/living/simple_animal/hostile/carp/ranged/chaos/Shoot() projectiletype = pick(allowed_projectile_types) diff --git a/code/modules/events/wizard/shuffle.dm b/code/modules/events/wizard/shuffle.dm index 3b5ea6b20a..18b8c8e21c 100644 --- a/code/modules/events/wizard/shuffle.dm +++ b/code/modules/events/wizard/shuffle.dm @@ -94,7 +94,7 @@ shuffle_inplace(mobs) - var/obj/effect/proc_holder/spell/targeted/mind_transfer/swapper = new /obj/effect/proc_holder/spell/targeted/mind_transfer + var/obj/effect/proc_holder/spell/pointed/mind_transfer/swapper = new /obj/effect/proc_holder/spell/pointed/mind_transfer while(mobs.len > 1) var/mob/living/carbon/human/H = pick(mobs) mobs -= H diff --git a/code/modules/flufftext/Dreaming.dm b/code/modules/flufftext/Dreaming.dm index 43c3337a4b..860d3898f2 100644 --- a/code/modules/flufftext/Dreaming.dm +++ b/code/modules/flufftext/Dreaming.dm @@ -1,7 +1,3 @@ -/mob/living/carbon/proc/handle_dreams() - if(prob(10) && !dreaming) - dream() - /mob/living/carbon/proc/dream() set waitfor = FALSE var/list/dream_fragments = list() diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 2e68c57abd..a3ee8c5228 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -23,7 +23,6 @@ gulp_size = max(round(reagents.total_volume / 5), 5) /obj/item/reagent_containers/food/drinks/attack(mob/living/M, mob/user, def_zone) - if(!reagents || !reagents.total_volume) to_chat(user, "[src] is empty!") return 0 @@ -37,9 +36,6 @@ if(M == user) user.visible_message("[user] swallows a gulp of [src].", "You swallow a gulp of [src].") - if(HAS_TRAIT(M, TRAIT_VORACIOUS)) - M.changeNext_move(CLICK_CD_MELEE * 0.5) //chug! chug! chug! - else M.visible_message("[user] attempts to feed the contents of [src] to [M].", "[user] attempts to feed the contents of [src] to [M].") if(!do_mob(user, M)) @@ -56,6 +52,10 @@ playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1) return 1 +/obj/item/reagent_containers/food/drinks/CheckAttackCooldown(mob/user, atom/target) + var/fast = HAS_TRAIT(user, TRAIT_VORACIOUS) && (user == target) + return user.CheckActionCooldown(fast? CLICK_CD_RANGE : CLICK_CD_MELEE) + /obj/item/reagent_containers/food/drinks/afterattack(obj/target, mob/user , proximity) . = ..() if(!proximity) @@ -299,6 +299,31 @@ desc = "An insult to Duke Purple is an insult to the Space Queen! Any proper gentleman will fight you, if you sully this tea." list_reagents = list(/datum/reagent/consumable/tea = 30) +/obj/item/reagent_containers/food/drinks/mug/tea/red + name = "Dutchess Red tea" + icon_state = "tea" + desc = "Duchess Red's personal blend of red tea leaves and hot water. Great addition to any meal." + list_reagents = list(/datum/reagent/consumable/tea/red = 30) + +/obj/item/reagent_containers/food/drinks/mug/tea/green + name = "Prince Green tea" + icon_state = "tea" + desc = "Prince Green's brew of tea. The blend may be different from time to time, but Prince Green swears by it!" + list_reagents = list(/datum/reagent/consumable/tea/green = 30) + +/obj/item/reagent_containers/food/drinks/mug/tea/forest + name = "Royal Forest tea" + icon_state = "tea" + desc = "Tea fit for anyone with a sweet tooth like Royal Forest." + list_reagents = list(/datum/reagent/consumable/tea/forest = 30) + +/obj/item/reagent_containers/food/drinks/mug/tea/mush + name = "Rebel Mush tea" + icon_state = "tea" + desc = "Rebel Mush, a hallucinogenic tea to help people find their inner self." + list_reagents = list(/datum/reagent/consumable/tea/mush = 30) + + /obj/item/reagent_containers/food/drinks/mug/coco name = "Dutch hot coco" desc = "Made in Space South America." diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index d87eb8fbc0..e31a9704df 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -87,7 +87,7 @@ hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("stabbed", "slashed", "attacked") var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken") - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/broken_bottle/Initialize() . = ..() diff --git a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm index 7361e50606..8e5069925f 100644 --- a/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm +++ b/code/modules/food_and_drinks/drinks/drinks/drinkingglass.dm @@ -94,7 +94,7 @@ list_reagents = list(/datum/reagent/consumable/nuka_cola = 50) /obj/item/reagent_containers/food/drinks/drinkingglass/filled/syndicatebomb - name = "Syndicat Bomb" + name = "Syndicate Bomb" list_reagents = list(/datum/reagent/consumable/ethanol/syndicatebomb = 50) /obj/item/reagent_containers/food/drinks/drinkingglass/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm index 203eb3eef6..f83a1222fd 100644 --- a/code/modules/food_and_drinks/food.dm +++ b/code/modules/food_and_drinks/food.dm @@ -6,7 +6,6 @@ /// get_random_food proc. //////////////////////////////////////////////////////////////////////////////// -#define STOP_SERVING_BREAKFAST (15 MINUTES) /obj/item/reagent_containers/food possible_transfer_amounts = list() @@ -51,5 +50,3 @@ if((foodtype & BREAKFAST) && world.time - SSticker.round_start_time < STOP_SERVING_BREAKFAST) SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "breakfast", /datum/mood_event/breakfast) last_check_time = world.time - -#undef STOP_SERVING_BREAKFAST diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index ccac1d4a77..4d5f4e2dd0 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -13,15 +13,31 @@ The nutriment reagent and bitesize variable replace the old heal_amt and amount bitesize of 2, then it'll take 3 bites to eat. Unlike the old system, the contained reagents are evenly spread among all the bites. No more contained reagents = no more bites. -Here is an example of the new formatting for anyone who wants to add more food items. +Food formatting and crafting examples. ``` -/obj/item/reagent_containers/food/snacks/xenoburger //Identification path for the object. - name = "Xenoburger" //Name that displays in the UI. - desc = "Smells caustic. Tastes like heresy." //Duh - icon_state = "xburger" //Refers to an icon in food.dmi - list_reagents = list(/datum/reagent/xenomicrobes = 10, - /datum/reagent/consumable/nutriment = 2) //What's inside the snack. - bitesize = 3 //This is the amount each bite consumes. +/obj/item/reagent_containers/food/snacks/saltedcornchips //Identification path for the object. + name = "salted corn chips" //Name that displays when hovered over. + desc = "Manufactured in a far away factory." //Description on examine. + icon_state = "saltychip" //Refers to an icon, usually in food.dmi + bitesize = 3 //How many reagents are consumed in each bite. + list_reagents = list(/datum/reagent/consumable/nutriment = 6, //What's inside the snack, but only if spawned. For example, from a chemical reaction, vendor, or slime core spawn. + /datum/reagent/consumable/nutriment/vitamin = 2) + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, //What's -added- to the food, in addition to the reagents contained inside the foods used to craft it. Basically, a reward for cooking. + /datum/reagent/consumable/nutriment/vitamin = 1) ^^For example. Egg+Egg = 2Egg + Bonus Reagents. + filling_color = "#F4A460" //What color it will use if put in a custom food. + tastes = list("salt" = 1, "oil" = 1) //Descriptive flavoring displayed when eaten. IE: "You taste a bit of salt and a bit of oil." + foodtype = GRAIN | JUNKFOOD //Tag for racial or custom food preferences. IE: Most Lizards cannot have GRAIN. + +Crafting Recipe (See files in code/modules/food_and_drinks/recipes/tablecraft/) + +/datum/crafting_recipe/food/nachos + name ="Salted Corn Chips" //Name that displays in the Crafting UI + reqs = list( //The list of ingredients to make the food. + /obj/item/reagent_containers/food/snacks/tortilla = 1, + /datum/reagent/consumable/sodiumchloride = 1 //As a note, reagents and non-food items don't get added to the food. If you + ) ^^want the reagents, make sure the food item has it listed under bonus_reagents. + result = /obj/item/reagent_containers/food/snacks/saltedcornchips //Resulting object. + subcategory = CAT_MISCFOOD //Subcategory the food falls under in the Food Tab of the crafting menu. ``` All foods are distributed among various categories. Use common sense. @@ -81,9 +97,12 @@ All foods are distributed among various categories. Use common sense. return -/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/living/user, def_zone) +/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) if(user.a_intent == INTENT_HARM) return ..() + INVOKE_ASYNC(src, .proc/attempt_forcefeed, M, user) + +/obj/item/reagent_containers/food/snacks/proc/attempt_forcefeed(mob/living/M, mob/living/user) if(!eatverb) eatverb = pick("bite","chew","nibble","gnaw","gobble","chomp") if(!reagents.total_volume) //Shouldn't be needed but it checks to see if it has anything left in it. @@ -113,8 +132,6 @@ All foods are distributed among various categories. Use common sense. else if(fullness > (600 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat user.visible_message("[user] cannot force any more of \the [src] to go down [user.p_their()] throat!", "You cannot force any more of \the [src] to go down your throat!") return 0 - if(HAS_TRAIT(M, TRAIT_VORACIOUS)) - M.changeNext_move(CLICK_CD_MELEE * 0.5) //nom nom nom else if(!isbrain(M)) //If you're feeding it to someone else. if(fullness <= (600 * (1 + M.overeatduration / 1000))) @@ -151,6 +168,10 @@ All foods are distributed among various categories. Use common sense. return 0 +/obj/item/reagent_containers/food/snacks/CheckAttackCooldown(mob/user, atom/target) + var/fast = HAS_TRAIT(user, TRAIT_VORACIOUS) && (user == target) + return user.CheckActionCooldown(fast? CLICK_CD_RANGE : CLICK_CD_MELEE) + /obj/item/reagent_containers/food/snacks/examine(mob/user) . = ..() if(food_quality >= 70) @@ -231,21 +252,9 @@ All foods are distributed among various categories. Use common sense. to_chat(user, "You cannot slice [src] here! You need a table or at least a tray.") return FALSE - var/slices_lost = 0 - if (accuracy >= IS_SHARP_ACCURATE) - user.visible_message( \ - "[user] slices [src].", \ - "You slice [src]." \ - ) - else - user.visible_message( \ - "[user] inaccurately slices [src] with [W]!", \ - "You inaccurately slice [src] with your [W]!" \ - ) - slices_lost = rand(1,min(1,round(slices_num/2))) - + user.visible_message("[user] slices [src].", "You slice [src].") var/reagents_per_slice = reagents.total_volume/slices_num - for(var/i=1 to (slices_num-slices_lost)) + for(var/i=1 to slices_num) var/obj/item/reagent_containers/food/snacks/slice = new slice_path (loc) initialize_slice(slice, reagents_per_slice) qdel(src) @@ -303,12 +312,12 @@ All foods are distributed among various categories. Use common sense. var/obj/item/result if(cooked_type) result = new cooked_type(T) - //if the result is food, set its food quality to the original food item's quality - if(isfood(result)) - var/obj/item/reagent_containers/food/food_output = result - food_output.adjust_food_quality(food_quality + M.quality_increase) if(istype(M)) initialize_cooked_food(result, M.efficiency) + //if the result is food, set its food quality to the original food item's quality + if(isfood(result)) + var/obj/item/reagent_containers/food/food_output = result + food_output.adjust_food_quality(food_quality + M.quality_increase) else initialize_cooked_food(result, 1) SSblackbox.record_feedback("tally", "food_made", 1, result.type) @@ -390,3 +399,13 @@ All foods are distributed among various categories. Use common sense. TB.MouseDrop(over) else return ..() + +// //////////////////////////////////////////////Frying//////////////////////////////////////// +/atom/proc/fry(cook_time = 30) //you can truly fry anything + //don't fry reagent containers that aren't food items, indestructable items, or items that are already fried + if(isitem(src)) + var/obj/item/fried_item = src + if(fried_item.resistance_flags & INDESTRUCTIBLE) + return + if(!GetComponent(/datum/component/fried) && (!reagents || isfood(src) || ismob(src))) + AddComponent(/datum/component/fried, frying_power = cook_time) diff --git a/code/modules/food_and_drinks/food/snacks/meat.dm b/code/modules/food_and_drinks/food/snacks/meat.dm index b8fa64a7bc..4d287fdb86 100644 --- a/code/modules/food_and_drinks/food/snacks/meat.dm +++ b/code/modules/food_and_drinks/food/snacks/meat.dm @@ -1,6 +1,7 @@ /obj/item/reagent_containers/food/snacks/meat var/subjectname = "" var/subjectjob = null + custom_materials = list(/datum/material/meat = MINERAL_MATERIAL_AMOUNT * 4) /obj/item/reagent_containers/food/snacks/meat/slab name = "meat" @@ -82,6 +83,7 @@ /obj/item/reagent_containers/food/snacks/meat/slab/chicken name = "chicken meat" desc = "A slab of raw chicken. Remember to wash your hands!" + icon_state = "chickenbreast" cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/chicken slice_path = /obj/item/reagent_containers/food/snacks/meat/rawcutlet/chicken tastes = list("chicken" = 1) @@ -160,6 +162,14 @@ tastes = list("brains" = 1, "meat" = 1) foodtype = RAW | MEAT | TOXIC +/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ethereal + icon_state = "etherealmeat" + desc = "So shiny you feel like ingesting it might make you shine too" + filling_color = "#97ee63" + list_reagents = list(/datum/reagent/consumable/liquidelectricity = 3) + tastes = list("pure electricity" = 2, "meat" = 1) + foodtype = RAW | MEAT | TOXIC + /obj/item/reagent_containers/food/snacks/carpmeat/aquatic name = "fillet" desc = "A fillet of one of the local water dwelling species." @@ -340,8 +350,14 @@ /obj/item/reagent_containers/food/snacks/meat/steak/chicken name = "chicken steak" //Can you have chicken steaks? Maybe this should be renamed once it gets new sprites. + icon_state = "chickenbreast_cooked" tastes = list("chicken" = 1) +/obj/item/reagent_containers/food/snacks/meat/steak/fish + name = "fish fillet" + icon_state = "grilled_carp_slice" + tastes = list("charred sushi" = 1) + /obj/item/reagent_containers/food/snacks/meat/steak/plain foodtype = MEAT @@ -360,6 +376,7 @@ /obj/item/reagent_containers/food/snacks/meat/steak/bear name = "bear steak" + icon_state = "bearcook" tastes = list("meat" = 1, "salmon" = 1) /obj/item/reagent_containers/food/snacks/meat/steak/xeno diff --git a/code/modules/food_and_drinks/food/snacks_bread.dm b/code/modules/food_and_drinks/food/snacks_bread.dm index f3d84f7169..0d7c715654 100644 --- a/code/modules/food_and_drinks/food/snacks_bread.dm +++ b/code/modules/food_and_drinks/food/snacks_bread.dm @@ -191,93 +191,6 @@ tastes = list("bread" = 1, "garlic" = 1, "butter" = 1) foodtype = GRAIN -/obj/item/reagent_containers/food/snacks/deepfryholder - name = "Deep Fried Foods Holder Obj" - desc = "If you can see this description the code for the deep fryer fucked up." - icon = 'icons/obj/food/food.dmi' - icon_state = "" - bitesize = 2 - var/fried_garbage = FALSE //did you really fry a fire extinguisher? - -GLOBAL_VAR_INIT(frying_hardmode, TRUE) -GLOBAL_VAR_INIT(frying_bad_chem_add_volume, TRUE) -GLOBAL_LIST_INIT(frying_bad_chems, list( -/datum/reagent/toxin/bad_food = 3, -/datum/reagent/drug/aranesp = 2, -/datum/reagent/toxin = 2, -/datum/reagent/lithium = 2, -/datum/reagent/mercury = 2, -)) - -/obj/item/reagent_containers/food/snacks/deepfryholder/Initialize(mapload, obj/item/fried) - . = ..() - name = fried.name //We'll determine the other stuff when it's actually removed - appearance = fried.appearance - layer = initial(layer) - plane = initial(plane) - lefthand_file = fried.lefthand_file - righthand_file = fried.righthand_file - item_state = fried.item_state - desc = fried.desc - w_class = fried.w_class - slowdown = fried.slowdown - equip_delay_self = fried.equip_delay_self - equip_delay_other = fried.equip_delay_other - strip_delay = fried.strip_delay - species_exception = fried.species_exception - item_flags = fried.item_flags - obj_flags = fried.obj_flags - - if(isfood(fried)) - fried.reagents.trans_to(src, fried.reagents.total_volume) - qdel(fried) - else - fried.forceMove(src) - trash = fried - fried_garbage = TRUE - -/obj/item/reagent_containers/food/snacks/deepfryholder/Destroy() - if(trash) - QDEL_NULL(trash) - . = ..() - -/obj/item/reagent_containers/food/snacks/deepfryholder/On_Consume(mob/living/eater) - if(fried_garbage && GLOB.frying_hardmode && GLOB.frying_bad_chems.len) - var/R = rand(1, GLOB.frying_bad_chems.len) - var/bad_chem = GLOB.frying_bad_chems[R] - var/bad_chem_amount = GLOB.frying_bad_chems[bad_chem] - eater.reagents.add_reagent(bad_chem, bad_chem_amount) - //All fried inedible items also get condensed cooking oil added, which induces minor vomiting and heart damage - eater.reagents.add_reagent(/datum/reagent/toxin/condensed_cooking_oil, 2) - if(trash) - QDEL_NULL(trash) - ..() - -/obj/item/reagent_containers/food/snacks/deepfryholder/proc/fry(cook_time = 30) - switch(cook_time) - if(0 to 15) - add_atom_colour(rgb(166,103,54), FIXED_COLOUR_PRIORITY) - name = "lightly-fried [name]" - desc = "[desc] It's been lightly fried in a deep fryer." - adjust_food_quality(food_quality - 5) - if(16 to 49) - add_atom_colour(rgb(103,63,24), FIXED_COLOUR_PRIORITY) - name = "fried [name]" - desc = "[desc] It's been fried, increasing its tastiness value by [rand(1, 75)]%." - adjust_food_quality(food_quality - 10) - if(50 to 59) - add_atom_colour(rgb(63,23,4), FIXED_COLOUR_PRIORITY) - name = "deep-fried [name]" - desc = "[desc] Deep-fried to perfection." - adjust_food_quality(food_quality) //we shouldn't punish perfection in the fried arts - if(60 to INFINITY) - add_atom_colour(rgb(33,19,9), FIXED_COLOUR_PRIORITY) - name = "the physical manifestation of the very concept of fried foods" - desc = "A heavily-fried...something. Who can tell anymore?" - adjust_food_quality(0) //good job, you're truly the best cook. - filling_color = color - foodtype |= FRIED - /obj/item/reagent_containers/food/snacks/butteredtoast name = "buttered toast" desc = "Butter lightly spread over a piece of toast." diff --git a/code/modules/food_and_drinks/food/snacks_cake.dm b/code/modules/food_and_drinks/food/snacks_cake.dm index f2253ee760..1117dbc3d3 100644 --- a/code/modules/food_and_drinks/food/snacks_cake.dm +++ b/code/modules/food_and_drinks/food/snacks_cake.dm @@ -312,7 +312,7 @@ obj/item/reagent_containers/food/snacks/store/cake/pound_cake name = "pound cake" desc = "A condensed cake made for filling people up quickly." icon_state = "pound_cake" - slices_num = 7 //Its ment to feed the party + slices_num = 7 //Its meant to feed the party slice_path = /obj/item/reagent_containers/food/snacks/cakeslice/pound_cake_slice bonus_reagents = list(/datum/reagent/consumable/nutriment = 60) tastes = list("cake" = 5, "sweetness" = 1, "batter" = 1) diff --git a/code/modules/food_and_drinks/food/snacks_frozen.dm b/code/modules/food_and_drinks/food/snacks_frozen.dm index b699477245..39c9c6c04f 100644 --- a/code/modules/food_and_drinks/food/snacks_frozen.dm +++ b/code/modules/food_and_drinks/food/snacks_frozen.dm @@ -91,7 +91,7 @@ icon = 'icons/obj/food/snowcones.dmi' icon_state = "flavorless_sc" trash = /obj/item/reagent_containers/food/drinks/sillycup //We dont eat paper cups - bonus_reagents = list(/datum/reagent/water = 10) //Base line will allways give water + bonus_reagents = list(/datum/reagent/water = 10) //Base line will always give water list_reagents = list(/datum/reagent/water = 1) // We dont get food for water/juices filling_color = "#FFFFFF" //Ice is white tastes = list("ice" = 1, "water" = 1) diff --git a/code/modules/food_and_drinks/food/snacks_meat.dm b/code/modules/food_and_drinks/food/snacks_meat.dm index c2a58b0821..05a0da2793 100644 --- a/code/modules/food_and_drinks/food/snacks_meat.dm +++ b/code/modules/food_and_drinks/food/snacks_meat.dm @@ -22,6 +22,7 @@ list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/toxin/carpotoxin = 2, /datum/reagent/consumable/nutriment/vitamin = 2) bitesize = 6 filling_color = "#FA8072" + cooked_type = /obj/item/reagent_containers/food/snacks/meat/steak/fish tastes = list("fish" = 1) foodtype = MEAT @@ -138,11 +139,22 @@ tastes = list("meat" = 1, "salmon" = 1) foodtype = MEAT | ALCOHOL +/obj/item/reagent_containers/food/snacks/rawmeatball + name = "raw meatball" + desc = "Raw mushy meat. Better cook this!" + icon_state = "rawmeatball" + cooked_type = /obj/item/reagent_containers/food/snacks/meatball + list_reagents = list(/datum/reagent/consumable/nutriment = 3) + filling_color = "#bd2020" + tastes = list("meat" = 1, "slime" = 1) + foodtype = MEAT | RAW + /obj/item/reagent_containers/food/snacks/meatball name = "meatball" desc = "MAMA MIA DAS A SPICY" icon_state = "meatball" list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 1) + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) filling_color = "#800000" tastes = list("meat" = 1) foodtype = MEAT @@ -173,6 +185,27 @@ tastes = list("meat" = 1, "smoke" = 1) foodtype = MEAT +/obj/item/reagent_containers/food/snacks/meatloaf + name = "meatloaf" + desc = "Meat! In a loaf!" + icon_state = "meatloaf" + filling_color = "#8f0f0f" + list_reagents = list(/datum/reagent/consumable/nutriment = 10) + bonus_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/ketchup = 5) + tastes = list("meat" = 1, "ketchup" = 1) + slices_num = 5 + slice_path = /obj/item/reagent_containers/food/snacks/meatloaf_slice + foodtype = MEAT + +/obj/item/reagent_containers/food/snacks/meatloaf_slice + name = "meatloaf slice" + filling_color = "#8f0f0f" + desc = "Meat! In chunky slices!" + icon_state = "meatloaf_slice" + list_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/ketchup = 1) + tastes = list("meat" = 1, "ketchup" = 1) + foodtype = MEAT + /obj/item/reagent_containers/food/snacks/kebab trash = /obj/item/stack/rods icon_state = "kebab" @@ -301,6 +334,16 @@ desc = "A 'chicken' nugget vaguely shaped like a [shape]." icon_state = "nugget_[shape]" +/obj/item/reagent_containers/food/snacks/sweet_and_sour + name = "sweet and sour chicken" + desc = "More sweet than sour, but delicious nonetheless." + icon_state = "sweet_and_sour" + filling_color = "#B22222" + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/consumable/soysauce = 2) + list_reagents = list(/datum/reagent/consumable/nutriment = 9, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/soysauce = 2) + tastes = list("\"chicken\"" = 1) + foodtype = MEAT | PINEAPPLE + /obj/item/reagent_containers/food/snacks/pigblanket name = "pig in a blanket" desc = "A tiny sausage wrapped in a flakey, buttery roll. Free this pig from its blanket prison by eating it." diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index bc80ffe621..e0697cecea 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -136,6 +136,17 @@ tastes = list("fries" = 3, "cheese" = 1) foodtype = VEGETABLES | GRAIN +/obj/item/reagent_containers/food/snacks/chilicheesefries + name = "chili cheese fries" + desc = "Fries smothered in cheese -and- chilli." + icon_state = "chilicheesefries" + trash = /obj/item/trash/plate + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2) + list_reagents = list(/datum/reagent/consumable/nutriment = 7, /datum/reagent/consumable/nutriment/vitamin = 1) + filling_color = "#FFD700" + tastes = list("fries" = 3, "cheese" = 1) + foodtype = VEGETABLES | GRAIN + /obj/item/reagent_containers/food/snacks/badrecipe name = "burned mess" desc = "Someone should be demoted from cook for this." @@ -537,6 +548,35 @@ tastes = list("butter" = 1) foodtype = DAIRY +/obj/item/reagent_containers/food/snacks/butter/margarine + name = "stick of margarine" + desc = "A stick of lightly salted vegetable oil." + icon_state = "marge" + list_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/cornoil = 2, /datum/reagent/consumable/sodiumchloride = 1) + filling_color = "#FFD700" + tastes = list("butter" = 1) + foodtype = JUNKFOOD + +/obj/item/reagent_containers/food/snacks/mashedpotato + name = "mashed potatoes" + desc = "A diced and smashed potato, served with sour cream." + icon_state = "mashedpotato" + list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/sodiumchloride = 1) + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) + filling_color = "#FFD700" + tastes = list("butter" = 1, "sour cream" = 1) + foodtype = GRAIN + +/obj/item/reagent_containers/food/snacks/butteredpotato + name = "buttered potatoes" + desc = "Mashed potatoes served with an ample serving of butter, and sour cream." + icon_state = "buttermash" + list_reagents = list(/datum/reagent/consumable/nutriment = 7, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/sodiumchloride = 2) + bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 1) + filling_color = "#FFD700" + tastes = list("potatoes" = 1, "sour cream" = 1, "butter" = 1) + foodtype = GRAIN | DAIRY + /obj/item/reagent_containers/food/snacks/onionrings name = "onion rings" desc = "Onion slices coated in batter." diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm index 03f4640718..81805f5529 100644 --- a/code/modules/food_and_drinks/food/snacks_pie.dm +++ b/code/modules/food_and_drinks/food/snacks_pie.dm @@ -113,6 +113,27 @@ tastes = list("pie" = 1, "meat" = 1) foodtype = GRAIN | MEAT +/obj/item/reagent_containers/food/snacks/pie/burek + name = "Burek" + icon = 'icons/obj/food/piecake.dmi' + icon_state = "burek" + desc = "If you know, you know." + slice_path = /obj/item/reagent_containers/food/snacks/pie/burekslice + slices_num = 4 + bonus_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/vitamin = 6) + list_reagents = list(/datum/reagent/consumable/nutriment= 20, /datum/reagent/consumable/nutriment/vitamin = 6) + bitesize = 12 + tastes = list("meat" = 1, "oil" = 1) + foodtype = GRAIN | MEAT + +/obj/item/reagent_containers/food/snacks/pie/burekslice + name = "Burek Slice" + icon = 'icons/obj/food/piecake.dmi' + icon_state = "burekslice" + desc = "A slice of Burek, watch out for oil stains!" + tastes = list("meat" = 1, "oil" = 1) + foodtype = GRAIN | MEAT + /obj/item/reagent_containers/food/snacks/pie/tofupie name = "tofu-pie" diff --git a/code/modules/food_and_drinks/food/snacks_pizza.dm b/code/modules/food_and_drinks/food/snacks_pizza.dm index ebc67a28c1..f30c182963 100644 --- a/code/modules/food_and_drinks/food/snacks_pizza.dm +++ b/code/modules/food_and_drinks/food/snacks_pizza.dm @@ -10,6 +10,17 @@ tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1) foodtype = GRAIN | DAIRY | VEGETABLES +/obj/item/reagent_containers/food/snacks/pizzaslice/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/kitchen/rollingpin)) + if(!isturf(loc)) + to_chat(user, "You need to put [src] on a surface to roll it out!") + return + new /obj/item/stack/sheet/pizza(loc) + to_chat(user, "You smoosh [src] into a cheesy sheet.") + qdel(src) + return + return ..() + /obj/item/reagent_containers/food/snacks/pizzaslice icon = 'icons/obj/food/pizzaspaghetti.dmi' list_reagents = list(/datum/reagent/consumable/nutriment = 5) diff --git a/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm b/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm index 9096429228..a606b9fe5a 100644 --- a/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm +++ b/code/modules/food_and_drinks/food/snacks_sandwichtoast.dm @@ -21,6 +21,17 @@ tastes = list("toast" = 1) foodtype = GRAIN +/obj/item/reagent_containers/food/snacks/baconlettucetomato + name = "blt sandwich" + desc = "The classic bacon, lettuce tomato sandwich." + icon = 'icons/obj/food/burgerbread.dmi' + icon_state = "blt" + trash = /obj/item/trash/plate + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 1) + list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 2) + tastes = list("bacon" = 1, "lettuce" = 1, "tomato" = 1, "mayo" = 1) + foodtype = GRAIN | MEAT | VEGETABLES + /obj/item/reagent_containers/food/snacks/grilledcheese name = "grilled cheese sandwich" desc = "Goes great with Tomato soup!" @@ -136,8 +147,19 @@ /obj/item/reagent_containers/food/snacks/tuna_sandwich name = "tuna sandwich" desc = "Both a salad and a sandwich in one." + icon = 'icons/obj/food/burgerbread.dmi' icon_state = "tunasandwich" - trash = /obj/item/trash/plate + list_reagents = list(/datum/reagent/consumable/nutriment = 12, /datum/reagent/consumable/nutriment/vitamin = 4) bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 3) tastes = list("tuna" = 4, "mayonnaise" = 2, "bread" = 2) foodtype = GRAIN | MEAT + +/obj/item/reagent_containers/food/snacks/meatballsub + name = "meatball sub" + desc = "At some point, you need to be the cheif sub." + icon = 'icons/obj/food/food.dmi' + icon_state = "meatballsub" + list_reagents = list(/datum/reagent/consumable/nutriment = 12, /datum/reagent/consumable/nutriment/vitamin = 4) + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 3) + tastes = list("meat" = 2, "toasted bread" = 1) + foodtype = GRAIN | MEAT diff --git a/code/modules/food_and_drinks/food/snacks_soup.dm b/code/modules/food_and_drinks/food/snacks_soup.dm index a6a251a84c..ffafcc6b1e 100644 --- a/code/modules/food_and_drinks/food/snacks_soup.dm +++ b/code/modules/food_and_drinks/food/snacks_soup.dm @@ -125,6 +125,15 @@ tastes = list("tomato" = 1, "mint" = 1) foodtype = VEGETABLES +/obj/item/reagent_containers/food/snacks/soup/bearchili + name = "bear chili" + desc = "Sensationally seasoned bear meat diced up with some peppers." + icon_state = "bearchili" + bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/capsaicin = 1) + list_reagents = list(/datum/reagent/consumable/nutriment = 10, /datum/reagent/medicine/morphine = 5, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/capsaicin = 5) + tastes = list("the outdoors" = 1, "hot peppers" = 1) + foodtype = VEGETABLES | MEAT + /obj/item/reagent_containers/food/snacks/soup/monkeysdelight name = "monkey's delight" desc = "A delicious soup with dumplings and hunks of monkey meat simmered to perfection, in a broth that tastes faintly of bananas." @@ -253,6 +262,16 @@ filling_color = "#CC2B52" foodtype = VEGETABLES | TOXIC +/obj/item/reagent_containers/food/snacks/soup/spiral_soup + name = "spiral soup" + desc = "The swirling of this soup is both frightening, and enticing." + icon_state = "spiral_soup" + list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/liquidelectricity = 5, /datum/reagent/cryptobiolin = 10, /datum/reagent/toxin/rotatium = 10) + bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/cryptobiolin = 15, /datum/reagent/toxin/rotatium = 15, /datum/reagent/consumable/liquidelectricity = 2) + tastes = list("the floor" = 1, "the ceiling" = 1, "regret" = 2) + filling_color = "#4476e2" + foodtype = GROSS | TOXIC | VEGETABLES + /obj/item/reagent_containers/food/snacks/soup/bungocurry name = "bungo curry" desc = "A spicy vegetable curry made with the humble bungo fruit, Exotic!" diff --git a/code/modules/food_and_drinks/food/snacks_vend.dm b/code/modules/food_and_drinks/food/snacks_vend.dm index 38f7ecf5b1..b4c7c89b74 100644 --- a/code/modules/food_and_drinks/food/snacks_vend.dm +++ b/code/modules/food_and_drinks/food/snacks_vend.dm @@ -91,3 +91,13 @@ tastes = list("sweetness" = 3, "cake" = 1) foodtype = GRAIN | FRUIT | VEGETABLES custom_price = PRICE_CHEAP + +/obj/item/reagent_containers/food/snacks/energybar + name = "High-power energy bars" + icon_state = "energybar" + desc = "An energy bar with a lot of punch, you probably shouldn't eat this if you're not an Ethereal." + trash = /obj/item/trash/energybar + list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/liquidelectricity = 3) + filling_color = "#97ee63" + tastes = list("pure electricity" = 3, "fitness" = 2) + foodtype = TOXIC diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index 0a3d172bb0..fecc9467a1 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -29,7 +29,7 @@ God bless America. use_power = IDLE_POWER_USE idle_power_usage = 5 layer = BELOW_OBJ_LAYER - var/obj/item/reagent_containers/food/snacks/deepfryholder/frying //What's being fried RIGHT NOW? + var/obj/item/frying //What's being fried RIGHT NOW? var/cook_time = 0 var/oil_use = 0.05 //How much cooking oil is used per tick var/fry_speed = 1 //How quickly we fry food @@ -91,25 +91,21 @@ God bless America. if(I.resistance_flags & INDESTRUCTIBLE) to_chat(user, "You don't feel it would be wise to fry [I]...") return - if(istype(I, /obj/item/reagent_containers/food/snacks/deepfryholder)) + if(I.GetComponent(/datum/component/fried)) to_chat(user, "Your cooking skills are not up to the legendary Doublefry technique.") return if(default_unfasten_wrench(user, I)) return else if(default_deconstruction_screwdriver(user, "fryer_off", "fryer_off" ,I)) //where's the open maint panel icon?! return + else if(I.reagents && !isfood(I)) + return else if(is_type_in_typecache(I, deepfry_blacklisted_items) || HAS_TRAIT(I, TRAIT_NODROP) || (I.item_flags & (ABSTRACT | DROPDEL))) return ..() else if(!frying && user.transferItemToLoc(I, src)) + frying = I to_chat(user, "You put [I] into [src].") - frying = new/obj/item/reagent_containers/food/snacks/deepfryholder(src, I) - //setup food quality for item depending on if it's edible or not - if(isfood(I)) - var/obj/item/reagent_containers/food/original_food = I - frying.adjust_food_quality(original_food.food_quality) //food quality remains unchanged until degree of frying is calculated - else - frying.adjust_food_quality(10) //inedible fried item has low quality icon_state = "fryer_on" fry_loop.start() @@ -134,7 +130,7 @@ God bless America. /obj/machinery/deepfryer/attack_ai(mob/user) return -/obj/machinery/deepfryer/attack_hand(mob/user) +/obj/machinery/deepfryer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(frying) if(frying.loc == src) to_chat(user, "You eject [frying] from [src].") @@ -150,6 +146,8 @@ God bless America. fry_loop.stop() return else if(user.pulling && user.a_intent == "grab" && iscarbon(user.pulling) && reagents.total_volume) + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return if(user.grab_state < GRAB_AGGRESSIVE) to_chat(user, "You need a better grip to do that!") return @@ -159,5 +157,5 @@ God bless America. C.apply_damage(min(30, reagents.total_volume), BURN, BODY_ZONE_HEAD) reagents.remove_any((reagents.total_volume/2)) C.DefaultCombatKnockdown(60) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction() return ..() diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index dcea93f06f..e4148d849a 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -63,10 +63,7 @@ /obj/machinery/gibber/relaymove(mob/living/user) go_out() -/obj/machinery/gibber/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/gibber/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(stat & (NOPOWER|BROKEN)) return if(operating) diff --git a/code/modules/food_and_drinks/kitchen_machinery/grill.dm b/code/modules/food_and_drinks/kitchen_machinery/grill.dm index 547ed244c0..09e1d7b1c6 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/grill.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/grill.dm @@ -107,7 +107,7 @@ /obj/machinery/grill/attack_ai(mob/user) return -/obj/machinery/grill/attack_hand(mob/user) +/obj/machinery/grill/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(grilled_item) to_chat(user, "You take out [grilled_item] from [src].") grilled_item.forceMove(drop_location()) diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 67a636eb9c..35fa40e15d 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -12,6 +12,7 @@ idle_power_usage = 5 active_power_usage = 100 circuit = /obj/item/circuitboard/machine/smartfridge + var/max_n_of_items = 1500 var/allow_ai_retrieve = FALSE var/list/initial_contents @@ -38,12 +39,10 @@ if(in_range(user, src) || isobserver(user)) . += "The status display reads: This unit can hold a maximum of [max_n_of_items] items." -/obj/machinery/smartfridge/power_change() - ..() - update_icon() - /obj/machinery/smartfridge/update_icon_state() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) if(!stat) + SSvis_overlays.add_vis_overlay(src, icon, "smartfridge-light-mask", EMISSIVE_LAYER, EMISSIVE_PLANE, dir, alpha) if(visible_contents) switch(contents.len) if(0) @@ -66,9 +65,6 @@ ********************/ /obj/machinery/smartfridge/attackby(obj/item/O, mob/user, params) - if(user.a_intent == INTENT_HARM) - return ..() - if(default_deconstruction_screwdriver(user, icon_state, icon_state, O)) cut_overlays() if(panel_open) @@ -87,46 +83,53 @@ updateUsrDialog() return - if(stat) - updateUsrDialog() - return FALSE + if(!stat) - if(contents.len >= max_n_of_items) - to_chat(user, "\The [src] is full!") - return FALSE - - if(accept_check(O)) - load(O) - user.visible_message("[user] has added \the [O] to \the [src].", "You add \the [O] to \the [src].") - updateUsrDialog() - if (visible_contents) - update_icon() - return TRUE - - if(istype(O, /obj/item/storage/bag)) - var/obj/item/storage/P = O - var/loaded = 0 - for(var/obj/G in P.contents) - if(contents.len >= max_n_of_items) - break - if(accept_check(G)) - load(G) - loaded++ - updateUsrDialog() - - if(loaded) - user.visible_message("[user] loads \the [src] with \the [O].", \ - "You [contents.len >= max_n_of_items ? "fill" : "load"] \the [src] with \the [O].") - if(O.contents.len > 0) - to_chat(user, "Some items are refused.") - return TRUE - else - to_chat(user, "There is nothing in [O] to put in [src]!") + if(contents.len >= max_n_of_items) + to_chat(user, "\The [src] is full!") return FALSE - to_chat(user, "\The [src] smartly refuses [O].") - updateUsrDialog() - return FALSE + if(accept_check(O)) + load(O) + user.visible_message("[user] adds \the [O] to \the [src].", "You add \the [O] to \the [src].") + updateUsrDialog() + if (visible_contents) + update_icon() + return TRUE + + if(istype(O, /obj/item/storage/bag)) + var/obj/item/storage/P = O + var/loaded = 0 + for(var/obj/G in P.contents) + if(contents.len >= max_n_of_items) + break + if(accept_check(G)) + load(G) + loaded++ + updateUsrDialog() + + if(loaded) + if(contents.len >= max_n_of_items) + user.visible_message("[user] loads \the [src] with \the [O].", \ + "You fill \the [src] with \the [O].") + else + user.visible_message("[user] loads \the [src] with \the [O].", \ + "You load \the [src] with \the [O].") + if(O.contents.len > 0) + to_chat(user, "Some items are refused.") + if (visible_contents) + update_icon() + return TRUE + else + to_chat(user, "There is nothing in [O] to put in [src]!") + return FALSE + + if(user.a_intent != INTENT_HARM) + to_chat(user, "\The [src] smartly refuses [O].") + updateUsrDialog() + return FALSE + else + return ..() @@ -151,16 +154,16 @@ return TRUE ///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge -/obj/machinery/smartfridge/proc/dispense(obj/item/O, var/mob/M) +/obj/machinery/smartfridge/proc/dispense(obj/item/O, mob/M) if(!M.put_in_hands(O)) O.forceMove(drop_location()) adjust_item_drop_location(O) -/obj/machinery/smartfridge/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/smartfridge/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "smartvend", name, 440, 550, master_ui, state) + ui = new(user, src, "SmartVend", name) ui.set_autoupdate(FALSE) ui.open() @@ -232,7 +235,7 @@ // ---------------------------- /obj/machinery/smartfridge/drying_rack name = "drying rack" - desc = "A wooden contraption, used to dry plant products, food and leather." + desc = "A wooden contraption, used to dry plant products, food and hide." icon = 'icons/obj/hydroponics/equipment.dmi' icon_state = "drying_rack" use_power = IDLE_POWER_USE @@ -277,6 +280,11 @@ return TRUE return FALSE +// /obj/machinery/smartfridge/drying_rack/powered() do we have this? no. +// if(!anchored) +// return FALSE +// return ..() + /obj/machinery/smartfridge/drying_rack/power_change() if(powered() && anchored) stat &= ~NOPOWER @@ -285,6 +293,10 @@ toggle_drying(TRUE) update_icon() + // . = ..() + // if(!powered()) + // toggle_drying(TRUE) + /obj/machinery/smartfridge/drying_rack/load() //For updating the filled overlay ..() update_icon() @@ -308,7 +320,7 @@ var/obj/item/reagent_containers/food/snacks/S = O if(S.dried_type) return TRUE - if(istype(O, /obj/item/stack/sheet/wetleather/)) + if(istype(O, /obj/item/stack/sheet/wetleather/)) //no wethide return TRUE return FALSE @@ -386,19 +398,19 @@ /obj/machinery/smartfridge/extract/preloaded initial_contents = list(/obj/item/slime_scanner = 2) -// ------------------------- You think you're better than Chem, huh? +// ------------------------- // Organ Surgery Smartfridge -// ------------------------- Just wait till Tamiorgans +// ------------------------- /obj/machinery/smartfridge/organ name = "smart organ storage" desc = "A refrigerated storage unit for organ storage." - max_n_of_items = 25 //vastly lower to prevent processing too long + max_n_of_items = 20 //vastly lower to prevent processing too long var/repair_rate = 0 /obj/machinery/smartfridge/organ/accept_check(obj/item/O) - if(istype(O, /obj/item/organ)) + if(isorgan(O) || isbodypart(O)) return TRUE - if(istype(O, /obj/item/reagent_containers/syringe)) + if(istype(O, /obj/item/reagent_containers/syringe)) //other medical things. return TRUE if(istype(O, /obj/item/reagent_containers/glass/bottle)) return TRUE @@ -410,7 +422,7 @@ . = ..() if(!.) //if the item loads, clear can_decompose return - if(istype(O, /obj/item/organ)) + if(isorgan(O)) var/obj/item/organ/organ = O organ.organ_flags |= ORGAN_FROZEN @@ -426,12 +438,13 @@ return O.applyOrganDamage(-repair_rate) -/obj/machinery/smartfridge/organ/Exited(obj/item/organ/AM, atom/newLoc) +/obj/machinery/smartfridge/organ/Exited(atom/movable/AM, atom/newLoc) . = ..() - if(istype(AM)) - AM.organ_flags &= ~ORGAN_FROZEN + if(isorgan(AM)) + var/obj/item/organ/O = AM + O.organ_flags &= ~ORGAN_FROZEN -/obj/machinery/smartfridge/organ/preloaded +/obj/machinery/smartfridge/organ/preloaded //cit specific?????? initial_contents = list( /obj/item/reagent_containers/medspray/synthtissue = 1, /obj/item/reagent_containers/medspray/sterilizine = 1) @@ -450,6 +463,15 @@ desc = "A refrigerated storage unit for medicine storage." /obj/machinery/smartfridge/chemistry/accept_check(obj/item/O) + var/static/list/chemfridge_typecache = typecacheof(list( + /obj/item/reagent_containers/syringe, + /obj/item/reagent_containers/glass/bottle, + /obj/item/reagent_containers/glass/beaker, + /obj/item/reagent_containers/spray, + // /obj/item/reagent_containers/medigel, + /obj/item/reagent_containers/chem_pack + )) + if(istype(O, /obj/item/storage/pill_bottle)) if(O.contents.len) for(var/obj/item/I in O) @@ -463,7 +485,7 @@ return TRUE if(!O.reagents || !O.reagents.reagent_list.len) // other empty containers not accepted return FALSE - if(istype(O, /obj/item/reagent_containers/syringe) || istype(O, /obj/item/reagent_containers/glass/bottle) || istype(O, /obj/item/reagent_containers/glass/beaker) || istype(O, /obj/item/reagent_containers/spray) || istype(O, /obj/item/reagent_containers/medspray)) + if(is_type_in_typecache(O, chemfridge_typecache)) return TRUE return FALSE @@ -487,6 +509,7 @@ /obj/item/reagent_containers/glass/bottle/cold = 1, /obj/item/reagent_containers/glass/bottle/flu_virion = 1, /obj/item/reagent_containers/glass/bottle/mutagen = 1, + /obj/item/reagent_containers/glass/bottle/sugar = 1, /obj/item/reagent_containers/glass/bottle/plasma = 1, /obj/item/reagent_containers/glass/bottle/synaptizine = 1, /obj/item/reagent_containers/glass/bottle/formaldehyde = 1) @@ -498,8 +521,8 @@ name = "disk compartmentalizer" desc = "A machine capable of storing a variety of disks. Denoted by most as the DSU (disk storage unit)." icon_state = "disktoaster" - visible_contents = FALSE pass_flags = PASSTABLE + visible_contents = FALSE /obj/machinery/smartfridge/disks/accept_check(obj/item/O) if(istype(O, /obj/item/disk/)) diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index 19ded25b08..a2603d07ab 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -106,8 +106,7 @@ START_PROCESSING(SSobj, src) update_icon() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/pizzabox/attack_hand(mob/user) +/obj/item/pizzabox/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.get_inactive_held_item() != src) return ..() if(open) diff --git a/code/modules/food_and_drinks/recipes/drinks_recipes.dm b/code/modules/food_and_drinks/recipes/drinks_recipes.dm index 8d8049194b..972f9a8cc3 100644 --- a/code/modules/food_and_drinks/recipes/drinks_recipes.dm +++ b/code/modules/food_and_drinks/recipes/drinks_recipes.dm @@ -18,12 +18,6 @@ results = list(/datum/reagent/consumable/ethanol/bilk = 2) required_reagents = list(/datum/reagent/consumable/milk = 1, /datum/reagent/consumable/ethanol/beer = 1) -/datum/chemical_reaction/icetea - name = "Iced Tea" - id = /datum/reagent/consumable/icetea - results = list(/datum/reagent/consumable/icetea = 4) - required_reagents = list(/datum/reagent/consumable/ice = 1, /datum/reagent/consumable/tea = 3) - /datum/chemical_reaction/icecoffee name = "Iced Coffee" id = /datum/reagent/consumable/icecoffee @@ -581,13 +575,6 @@ required_reagents = list(/datum/reagent/consumable/lemonjuice = 2, /datum/reagent/water = 2, /datum/reagent/consumable/sugar = 1, /datum/reagent/consumable/ice = 1) mix_message = "You're suddenly reminded of home." -/datum/chemical_reaction/arnold_palmer - name = "Arnold Palmer" - id = /datum/reagent/consumable/tea/arnold_palmer - results = list(/datum/reagent/consumable/tea/arnold_palmer = 2) - required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/consumable/lemonade = 1) - mix_message = "The smells of fresh green grass and sand traps waft through the air as the mixture turns a friendly yellow-orange." - /datum/chemical_reaction/chocolate_milk name = "chocolate milk" id = /datum/reagent/consumable/milk/chocolate_milk @@ -756,12 +743,6 @@ results = list(/datum/reagent/consumable/pinkmilk = 2) required_reagents = list(/datum/reagent/consumable/strawberryjuice = 1, /datum/reagent/consumable/milk = 1) -/datum/chemical_reaction/pinktea - name = "Strawberry Tea" - id = /datum/reagent/consumable/pinktea - results = list(/datum/reagent/consumable/pinktea = 5) - required_reagents = list(/datum/reagent/consumable/strawberryjuice = 1, /datum/reagent/consumable/tea/arnold_palmer = 1, /datum/reagent/consumable/sugar = 1) - /datum/chemical_reaction/blank_paper name = "Blank Paper" id = /datum/reagent/consumable/ethanol/blank_paper @@ -903,12 +884,6 @@ results = list(/datum/reagent/consumable/ethanol/mauna_loa = 5) required_reagents = list(/datum/reagent/consumable/capsaicin = 2, /datum/reagent/consumable/ethanol/kahlua = 1, /datum/reagent/consumable/ethanol/bahama_mama = 2) -/datum/chemical_reaction/catnip_tea - name = "Catnip Tea" - id = /datum/reagent/consumable/catnip_tea - results = list(/datum/reagent/consumable/catnip_tea = 3) - required_reagents = list(/datum/reagent/consumable/tea = 5, /datum/reagent/pax/catnip = 2) - /datum/chemical_reaction/commander_and_chief name = "Commander and Chief" id = /datum/reagent/consumable/ethanol/commander_and_chief @@ -916,79 +891,149 @@ required_reagents = list(/datum/reagent/consumable/ethanol/alliescocktail = 50, /datum/reagent/consumable/ethanol/champagne = 20, /datum/reagent/consumable/doctor_delight = 10, /datum/reagent/consumable/ethanol/quintuple_sec = 10, /datum/reagent/consumable/ethanol/screwdrivercocktail = 10) mix_message = "When your powers combine, I am Captain Pl-..." +////////////////////////////////////////// Tea Base Drinks ////////////////////////////////////// + +/datum/chemical_reaction/mush + name = "Mush Tea" + id = /datum/reagent/consumable/tea/mush + results = list(/datum/reagent/consumable/tea/mush = 3) + required_reagents = list(/datum/reagent/drug/mushroomhallucinogen = 3, /datum/reagent/consumable/tea = 3) + +/datum/chemical_reaction/foresttea1 + name = "Forest Tea" + id = /datum/reagent/consumable/tea/forest + results = list(/datum/reagent/consumable/tea/forest = 3) + required_reagents = list(/datum/reagent/consumable/buzz_fuzz= 3, /datum/reagent/consumable/tea = 3) + +/datum/chemical_reaction/foresttea2 + name = "Forest Tea" + id = /datum/reagent/consumable/tea/forest + results = list(/datum/reagent/consumable/tea/forest = 3) + required_reagents = list(/datum/reagent/consumable/honey = 1, /datum/reagent/consumable/tea = 3) + +/datum/chemical_reaction/redtea1 + name = "Red Tea" + id = /datum/reagent/consumable/tea/red + results = list(/datum/reagent/consumable/tea/red = 3) + required_reagents = list(/datum/reagent/colorful_reagent/crayonpowder/red = 1, /datum/reagent/consumable/tea = 3) + +/datum/chemical_reaction/greentea1 + name = "Green Tea" + id = /datum/reagent/consumable/tea/green + results = list(/datum/reagent/consumable/tea/green = 3) + required_reagents = list(/datum/reagent/colorful_reagent/crayonpowder/green = 1, /datum/reagent/consumable/tea = 3) + +/datum/chemical_reaction/redtea2 + name = "Red Tea" + id = /datum/reagent/consumable/tea/red + results = list(/datum/reagent/consumable/tea/red = 3) + required_reagents = list(/datum/reagent/toxin/teapowder/red = 1, /datum/reagent/water = 3) + +/datum/chemical_reaction/greentea2 + name = "Green Tea" + id = /datum/reagent/consumable/tea/green + results = list(/datum/reagent/consumable/tea/green = 3) + required_reagents = list(/datum/reagent/toxin/teapowder/green = 1, /datum/reagent/water = 3) + +/datum/chemical_reaction/arnold_palmer + name = "Arnold Palmer" + id = /datum/reagent/consumable/tea/arnold_palmer + results = list(/datum/reagent/consumable/tea/arnold_palmer = 2) + required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/consumable/lemonade = 1) + mix_message = "The smells of fresh green grass and sand traps waft through the air as the mixture turns a friendly yellow-orange." + +/datum/chemical_reaction/icetea + name = "Iced Tea" + id = /datum/reagent/consumable/icetea + results = list(/datum/reagent/consumable/icetea = 4) + required_reagents = list(/datum/reagent/consumable/ice = 1, /datum/reagent/consumable/tea = 3) + +/datum/chemical_reaction/pinktea + name = "Strawberry Tea" + id = /datum/reagent/consumable/pinktea + results = list(/datum/reagent/consumable/pinktea = 5) + required_reagents = list(/datum/reagent/consumable/strawberryjuice = 1, /datum/reagent/consumable/tea/arnold_palmer = 1, /datum/reagent/consumable/sugar = 1) + +/datum/chemical_reaction/catnip_tea + name = "Catnip Tea" + id = /datum/reagent/consumable/catnip_tea + results = list(/datum/reagent/consumable/catnip_tea = 3) + required_reagents = list(/datum/reagent/consumable/tea = 5, /datum/reagent/pax/catnip = 2) + + ////////////////////////////////////////// Race Base Drinks ////////////////////////////////////// /datum/chemical_reaction/coldscales name = "Cold Scales" - id = /datum/reagent/consumable/ethanol/coldscales - results = list(/datum/reagent/consumable/ethanol/coldscales = 3) + id = /datum/reagent/consumable/ethanol/species_drink/coldscales + results = list(/datum/reagent/consumable/ethanol/species_drink/coldscales = 3) required_reagents = list(/datum/reagent/consumable/tea = 1, /datum/reagent/toxin/slimejelly = 1, /datum/reagent/consumable/menthol = 1) /datum/chemical_reaction/oil_drum name = "Oil Drum" - id = /datum/reagent/consumable/ethanol/oil_drum - results = list(/datum/reagent/consumable/ethanol/oil_drum = 3) + id = /datum/reagent/consumable/ethanol/species_drink/oil_drum + results = list(/datum/reagent/consumable/ethanol/species_drink/oil_drum = 3) required_reagents = list(/datum/reagent/consumable/ethanol = 1, /datum/reagent/oil = 1, /datum/reagent/consumable/ethanol/champagne = 12) /datum/chemical_reaction/nord_king name = "Nord King" - id = /datum/reagent/consumable/ethanol/nord_king - results = list(/datum/reagent/consumable/ethanol/nord_king = 10) + id = /datum/reagent/consumable/ethanol/species_drink/nord_king + results = list(/datum/reagent/consumable/ethanol/species_drink/nord_king = 10) required_reagents = list(/datum/reagent/consumable/ethanol = 5, /datum/reagent/consumable/honey = 1, /datum/reagent/consumable/ethanol/red_mead = 10) /datum/chemical_reaction/velvet_kiss name = "Velvet Kiss" - id = /datum/reagent/consumable/ethanol/velvet_kiss - results = list(/datum/reagent/consumable/ethanol/velvet_kiss = 15) //Limited races use this + id = /datum/reagent/consumable/ethanol/species_drink/velvet_kiss + results = list(/datum/reagent/consumable/ethanol/species_drink/velvet_kiss = 15) //Limited races use this required_reagents = list(/datum/reagent/blood = 5, /datum/reagent/consumable/tea = 1, /datum/reagent/consumable/ethanol/wine = 10) /datum/chemical_reaction/abduction_fruit name = "Abduction Fruit" - id = /datum/reagent/consumable/ethanol/abduction_fruit - results = list(/datum/reagent/consumable/ethanol/abduction_fruit = 3) + id = /datum/reagent/consumable/ethanol/species_drink/abduction_fruit + results = list(/datum/reagent/consumable/ethanol/species_drink/abduction_fruit = 3) required_reagents = list(/datum/reagent/consumable/limejuice = 10, /datum/reagent/consumable/strawberryjuice = 5, /datum/reagent/consumable/watermelonjuice = 10) /datum/chemical_reaction/bug_zapper name = "Bug Zapper" - id = /datum/reagent/consumable/ethanol/bug_zapper - results = list(/datum/reagent/consumable/ethanol/bug_zapper = 20) //Harder to make + id = /datum/reagent/consumable/ethanol/species_drink/bug_zapper + results = list(/datum/reagent/consumable/ethanol/species_drink/bug_zapper = 20) //Harder to make required_reagents = list(/datum/reagent/consumable/lemonjuice = 10, /datum/reagent/teslium = 1, /datum/reagent/copper = 10) /datum/chemical_reaction/mush_crush name = "Mush Crush" - id = /datum/reagent/consumable/ethanol/mush_crush - results = list(/datum/reagent/consumable/ethanol/mush_crush = 10) + id = /datum/reagent/consumable/ethanol/species_drink/mush_crush + results = list(/datum/reagent/consumable/ethanol/species_drink/mush_crush = 10) required_reagents = list(/datum/reagent/iron = 5, /datum/reagent/ash = 5, /datum/reagent/toxin/coffeepowder = 10) /datum/chemical_reaction/darkbrew name = "Darkbrew" - id = /datum/reagent/consumable/ethanol/darkbrew - results = list(/datum/reagent/consumable/ethanol/darkbrew = 20)//Limited races use this + id = /datum/reagent/consumable/ethanol/species_drink/darkbrew + results = list(/datum/reagent/consumable/ethanol/species_drink/darkbrew = 20)//Limited races use this required_reagents = list(/datum/reagent/liquid_dark_matter = 5, /datum/reagent/toxin/bungotoxin = 5, /datum/reagent/toxin/coffeepowder = 10) /datum/chemical_reaction/hollow_bone name = "Hollow Bone" - id = /datum/reagent/consumable/ethanol/hollow_bone - results = list(/datum/reagent/consumable/ethanol/hollow_bone = 10) + id = /datum/reagent/consumable/ethanol/species_drink/hollow_bone + results = list(/datum/reagent/consumable/ethanol/species_drink/hollow_bone = 10) required_reagents = list(/datum/reagent/toxin/bonehurtingjuice = 5, /datum/reagent/consumable/milk = 10, /datum/reagent/consumable/coconutmilk = 10) /datum/chemical_reaction/frisky_kitty name = "Frisky Kitty" - id = /datum/reagent/consumable/ethanol/frisky_kitty - results = list(/datum/reagent/consumable/ethanol/frisky_kitty = 2) + id = /datum/reagent/consumable/ethanol/species_drink/frisky_kitty + results = list(/datum/reagent/consumable/ethanol/species_drink/frisky_kitty = 2) required_reagents = list(/datum/reagent/consumable/catnip_tea = 1, /datum/reagent/consumable/milk = 1) required_temp = 296 //Just above room temp (22.85'C) /datum/chemical_reaction/jell_wyrm name = "Jell Wyrm" - id = /datum/reagent/consumable/ethanol/jell_wyrm - results = list(/datum/reagent/consumable/ethanol/jell_wyrm = 2) + id = /datum/reagent/consumable/ethanol/species_drink/jell_wyrm + results = list(/datum/reagent/consumable/ethanol/species_drink/jell_wyrm = 2) required_reagents = list(/datum/reagent/toxin/slimejelly = 1, /datum/reagent/toxin/carpotoxin = 1, /datum/reagent/carbondioxide = 5) required_temp = 333 // (59.85'C) /datum/chemical_reaction/laval_spit name = "Laval Spit" - id = /datum/reagent/consumable/ethanol/laval_spit - results = list(/datum/reagent/consumable/ethanol/laval_spit = 20) //Limited use + id = /datum/reagent/consumable/ethanol/species_drink/laval_spit + results = list(/datum/reagent/consumable/ethanol/species_drink/laval_spit = 20) //Limited use required_reagents = list(/datum/reagent/iron = 5, /datum/reagent/consumable/ethanol/mauna_loa = 10, /datum/reagent/sulfur = 5) required_temp = 900 // (626.85'C) diff --git a/code/modules/food_and_drinks/recipes/food_mixtures.dm b/code/modules/food_and_drinks/recipes/food_mixtures.dm index ec96a4537c..541c972490 100644 --- a/code/modules/food_and_drinks/recipes/food_mixtures.dm +++ b/code/modules/food_and_drinks/recipes/food_mixtures.dm @@ -179,3 +179,14 @@ id = /datum/reagent/consumable/bbqsauce results = list(/datum/reagent/consumable/bbqsauce = 5) required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/tomatojuice = 1, /datum/reagent/medicine/salglu_solution = 3, /datum/reagent/consumable/blackpepper = 1) + +/datum/chemical_reaction/margarine + name = "Margarine" + id = "margarine" + required_reagents = list(/datum/reagent/consumable/cornoil = 5, /datum/reagent/consumable/soymilk = 5, /datum/reagent/consumable/sodiumchloride = 1) + mix_message = "The ingredients solidify into a stick of margarine." + +/datum/chemical_reaction/margarine/on_reaction(datum/reagents/holder, multiplier) + var/location = get_turf(holder.my_atom) + for(var/i = 1, i <= multiplier, i++) + new /obj/item/reagent_containers/food/snacks/butter/margarine(location) \ No newline at end of file diff --git a/code/modules/food_and_drinks/recipes/processor_recipes.dm b/code/modules/food_and_drinks/recipes/processor_recipes.dm index 1e3afd1cf5..f75cf6ef3a 100644 --- a/code/modules/food_and_drinks/recipes/processor_recipes.dm +++ b/code/modules/food_and_drinks/recipes/processor_recipes.dm @@ -6,7 +6,7 @@ /datum/food_processor_process/meat input = /obj/item/reagent_containers/food/snacks/meat/slab - output = /obj/item/reagent_containers/food/snacks/meatball + output = /obj/item/reagent_containers/food/snacks/rawmeatball /datum/food_processor_process/bacon input = /obj/item/reagent_containers/food/snacks/meat/rawcutlet diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm index e8640886c2..53c3682e2c 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_egg.dm @@ -22,6 +22,15 @@ result = /obj/item/reagent_containers/food/snacks/baconegg subcategory = CAT_EGG +/datum/crafting_recipe/food/wrap + name = "Egg Wrap" + reqs = list(/datum/reagent/consumable/soysauce = 10, + /obj/item/reagent_containers/food/snacks/friedegg = 1, + /obj/item/reagent_containers/food/snacks/grown/cabbage = 1, + ) + result = /obj/item/reagent_containers/food/snacks/eggwrap + subcategory = CAT_EGG + /datum/crafting_recipe/food/omelette name = "Omelette" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm index 60b363c168..17ea36a160 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_meat.dm @@ -84,6 +84,17 @@ result = /obj/item/reagent_containers/food/snacks/nugget subcategory = CAT_MEAT +/datum/crafting_recipe/food/sweet_and_sour + name = "Sweet and sour \"chicken\"" + reqs = list( + /obj/item/reagent_containers/food/snacks/nugget = 2, + /obj/item/reagent_containers/food/snacks/pineappleslice = 1, + /datum/reagent/consumable/soysauce = 2, + /datum/reagent/consumable/sodiumchloride = 1 + ) + result = /obj/item/reagent_containers/food/snacks/sweet_and_sour + subcategory = CAT_MEAT + /datum/crafting_recipe/food/corndog name = "Corndog meal" reqs = list( @@ -135,6 +146,16 @@ result = /obj/item/reagent_containers/food/snacks/sausage subcategory = CAT_MEAT +/datum/crafting_recipe/food/meatloaf + name = "Meatloaf" + reqs = list( + /obj/item/reagent_containers/food/snacks/meat/cutlet = 4, + /datum/reagent/consumable/eggyolk = 10, + /datum/reagent/consumable/ketchup = 5 + ) + result = /obj/item/reagent_containers/food/snacks/meatloaf + subcategory = CAT_MEAT + /datum/crafting_recipe/food/pigblanket name = "Pig in a Blanket" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm index 359fadfb70..affb76cca7 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_misc.dm @@ -14,15 +14,6 @@ result = /obj/item/reagent_containers/food/snacks/chawanmushi subcategory = CAT_MISCFOOD -/datum/crafting_recipe/food/wrap - name = "Egg Wrap" - reqs = list(/datum/reagent/consumable/soysauce = 10, - /obj/item/reagent_containers/food/snacks/friedegg = 1, - /obj/item/reagent_containers/food/snacks/grown/cabbage = 1, - ) - result = /obj/item/reagent_containers/food/snacks/eggwrap - subcategory = CAT_MISCFOOD - /datum/crafting_recipe/food/khachapuri name = "Khachapuri" reqs = list( @@ -93,6 +84,16 @@ result = /obj/item/reagent_containers/food/snacks/cheesyfries subcategory = CAT_MISCFOOD +/datum/crafting_recipe/food/chilicheesefries + name = "Chilli cheese fries" + reqs = list( + /obj/item/reagent_containers/food/snacks/fries = 1, + /obj/item/reagent_containers/food/snacks/cheesewedge = 1, + /obj/item/reagent_containers/food/snacks/grown/chili = 1 + ) + result = /obj/item/reagent_containers/food/snacks/chilicheesefries + subcategory = CAT_MISCFOOD + /datum/crafting_recipe/food/eggplantparm name ="Eggplant parmigiana" reqs = list( @@ -112,6 +113,25 @@ result = /obj/item/reagent_containers/food/snacks/loadedbakedpotato subcategory = CAT_MISCFOOD +/datum/crafting_recipe/food/mashedpotato + name = "Mashed potato" + reqs = list( + /obj/item/reagent_containers/food/snacks/grown/potato = 1, + /datum/reagent/consumable/cream = 5, + /datum/reagent/consumable/sodiumchloride = 1 + ) + result = /obj/item/reagent_containers/food/snacks/mashedpotato + subcategory = CAT_MISCFOOD + +/datum/crafting_recipe/food/butteredpotato + name = "Buttered mash" + reqs = list( + /obj/item/reagent_containers/food/snacks/mashedpotato = 1, + /obj/item/reagent_containers/food/snacks/butter = 1 + ) + result = /obj/item/reagent_containers/food/snacks/butteredpotato + subcategory = CAT_MISCFOOD + /datum/crafting_recipe/food/melonfruitbowl name ="Melon fruit bowl" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pies_sweets.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pies_sweets.dm index 52becf81df..289c698b9a 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pies_sweets.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pies_sweets.dm @@ -130,6 +130,18 @@ result = /obj/item/reagent_containers/food/snacks/pie/dulcedebatata subcategory = CAT_PIE +/datum/crafting_recipe/food/burek + name = "Burek" + reqs = list( + /datum/reagent/consumable/blackpepper = 3, + /datum/reagent/consumable/sodiumchloride = 3, + /obj/item/reagent_containers/food/snacks/pizzabread = 2, + /obj/item/reagent_containers/food/snacks/meat/cutlet/plain = 6, + /obj/item/reagent_containers/food/snacks/butter = 1, + ) + result = /obj/item/reagent_containers/food/snacks/pie/burek + subcategory = CAT_PIE + /datum/crafting_recipe/food/meatpie name = "Meat pie" reqs = list( @@ -302,4 +314,4 @@ /obj/item/reagent_containers/food/snacks/spiderling = 1 ) result = /obj/item/reagent_containers/food/snacks/spiderlollipop - subcategory = CAT_PIE \ No newline at end of file + subcategory = CAT_PIE diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm index d2ea1da50a..81c5b4dd92 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_sandwich.dm @@ -25,6 +25,17 @@ result = /obj/item/reagent_containers/food/snacks/grilledcheese subcategory = CAT_SANDWICH +/datum/crafting_recipe/food/baconlettucetomato + name = "BLT sandwich" + reqs = list( + /obj/item/reagent_containers/food/snacks/meat/bacon = 2, + /obj/item/reagent_containers/food/snacks/grown/cabbage = 1, + /obj/item/reagent_containers/food/snacks/grown/tomato = 1, + /datum/reagent/consumable/mayonnaise = 5 + ) + result = /obj/item/reagent_containers/food/snacks/baconlettucetomato + subcategory = CAT_SANDWICH + /datum/crafting_recipe/food/slimesandwich name = "Jelly sandwich" reqs = list( @@ -99,11 +110,20 @@ /obj/item/reagent_containers/food/snacks/breadslice/plain = 2, /obj/item/reagent_containers/food/snacks/tuna = 1, /obj/item/reagent_containers/food/snacks/grown/onion = 1, - /obj/item/reagent_containers/food/condiment/mayonnaise = 5 + /datum/reagent/consumable/mayonnaise = 5 ) result = /obj/item/reagent_containers/food/snacks/tuna_sandwich subcategory = CAT_SANDWICH +/datum/crafting_recipe/food/meatballsub + name = "Meatball sub" + reqs = list( + /obj/item/reagent_containers/food/snacks/meatball = 3, + /obj/item/reagent_containers/food/snacks/bun = 1 + ) + result = /obj/item/reagent_containers/food/snacks/meatballsub + subcategory = CAT_SANDWICH + /datum/crafting_recipe/food/hotdog name = "Hot dog" reqs = list( diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm index 8f4b4c2726..6372137edc 100644 --- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm +++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_soup.dm @@ -13,6 +13,17 @@ result = /obj/item/reagent_containers/food/snacks/soup/amanitajelly subcategory = CAT_SOUP +/datum/crafting_recipe/food/bearchili + name = "Bear chili" + reqs = list( + /datum/reagent/water = 10, + /obj/item/reagent_containers/glass/bowl = 1, + /obj/item/reagent_containers/food/snacks/meat/steak/bear = 1, + /obj/item/reagent_containers/food/snacks/grown/chili = 1, + ) + result = /obj/item/reagent_containers/food/snacks/soup/bearchili + subcategory = CAT_SOUP + /datum/crafting_recipe/food/beetsoup name = "Beet soup" reqs = list( @@ -204,6 +215,18 @@ result = /obj/item/reagent_containers/food/snacks/soup/spacylibertyduff subcategory = CAT_SOUP +/datum/crafting_recipe/food/spiralsoup + name = "Spiral soup" + reqs = list( + /obj/item/reagent_containers/glass/bowl = 1, + /obj/item/reagent_containers/food/snacks/grown/mushroom/jupitercup = 2, + /datum/reagent/cryptobiolin = 15, + /datum/reagent/toxin/rotatium = 15, + /datum/reagent/consumable/milk = 10 + ) + result = /obj/item/reagent_containers/food/snacks/soup/spacylibertyduff + subcategory = CAT_SOUP + /datum/crafting_recipe/food/sweetpotatosoup name = "Sweet potato soup" reqs = list( diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm index 6d9e141309..ce27dccb74 100644 --- a/code/modules/goonchat/browserOutput.dm +++ b/code/modules/goonchat/browserOutput.dm @@ -2,18 +2,30 @@ For the main html chat area *********************************/ -//Precaching a bunch of shit +/// Should match the value set in the browser js +#define MAX_COOKIE_LENGTH 5 + +//Precaching a bunch of shit. Someone ship this out of here GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of icons for the browser output -//On client, created on login +//lazy renaming to chat_output, instead renamed to old chatOutput +/** + * The chatOutput datum exists to handle the goonchat browser. + * On client, created on Client/New() + */ /datum/chatOutput - var/client/owner //client ref + /// The client that owns us. + var/client/owner + /// How many times client data has been checked var/total_checks = 0 - var/last_check = 0 - var/loaded = FALSE // Has the client loaded the browser output area? - var/list/messageQueue //If they haven't loaded chat, this is where messages will go until they do - var/cookieSent = FALSE // Has the client sent a cookie for analysis - var/broken = FALSE + /// When to next clear the client data checks counter + var/next_time_to_clear = 0 + /// Has the client loaded the browser output area? + var/loaded = FALSE + /// If they haven't loaded chat, this is where messages will go until they do + var/list/messageQueue + var/cookieSent = FALSE // Has the client sent a cookie for analysis + var/broken = FALSE var/list/connectionHistory //Contains the connection history passed from chat cookie var/adminMusicVolume = 25 //This is for the Play Global Sound verb @@ -22,13 +34,18 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico messageQueue = list() connectionHistory = list() +/** + * start: Tries to load the chat browser + * Aborts if a problem is encountered. + * Async because this is called from Client/New. + */ /datum/chatOutput/proc/start() + set waitfor = FALSE //Check for existing chat if(!owner) return FALSE if(!winexists(owner, "browseroutput")) // Oh goddamnit. - set waitfor = FALSE broken = TRUE message_admins("Couldn't start chat for [key_name_admin(owner)]!") . = FALSE @@ -43,6 +60,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico return TRUE +/// Loads goonchat and sends assets. /datum/chatOutput/proc/load() set waitfor = FALSE if(!owner) @@ -53,6 +71,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico owner << browse(file('code/modules/goonchat/browserassets/html/browserOutput.html'), "window=browseroutput") +/// Interprets input from the client. Will send data back if required. /datum/chatOutput/Topic(href, list/href_list) if(usr.client != owner) return TRUE @@ -83,20 +102,22 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico if("setMusicVolume") data = setMusicVolume(arglist(params)) - if("colorPresetPost") //User just swapped color presets in their goonchat preferences. Do we do anything else? switch(href_list["preset"]) if("light") owner.force_white_theme() if("dark" || "normal") owner.force_dark_theme() - + // if("swaptodarkmode") + // swaptodarkmode() + // if("swaptolightmode") + // swaptolightmode() if(data) ehjax_send(data = data) -//Called on chat output done-loading by JS. +/// Called on chat output done-loading by JS. /datum/chatOutput/proc/doneLoading() if(loaded) return @@ -113,34 +134,75 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico messageQueue = null sendClientData() + syncRegex() + //do not convert to to_chat() SEND_TEXT(owner, "Failed to load fancy chat, reverting to old chat. Certain features won't work.") +/// Hides the standard output and makes the browser visible. /datum/chatOutput/proc/showChat() winset(owner, "output", "is-visible=false") winset(owner, "browseroutput", "is-disabled=false;is-visible=true") +/// Calls syncRegex on all currently owned chatOutput datums +/proc/syncChatRegexes() + for (var/user in GLOB.clients) + var/client/C = user + var/datum/chatOutput/Cchat = C.chatOutput + if (Cchat && !Cchat.broken && Cchat.loaded) + Cchat.syncRegex() + +/// Used to dynamically add regexes to the browser output. Currently only used by the IC filter. +/datum/chatOutput/proc/syncRegex() + var/list/regexes = list() + /* + if (config.ic_filter_regex) + regexes["show_filtered_ic_chat"] = list( + config.ic_filter_regex.name, + "ig", + "$1" + ) + */ + if (regexes.len) + ehjax_send(data = list("syncRegex" = regexes)) + +/// Sends json encoded data to the browser. /datum/chatOutput/proc/ehjax_send(client/C = owner, window = "browseroutput", data) if(islist(data)) data = json_encode(data) C << output("[data]", "[window]:ehjaxCallback") -/datum/chatOutput/proc/sendMusic(music, pitch) +/** + * Sends music data to the browser. If enabled by the browser, it will start playing. + * Arguments: + * music must be a https adress. + * extra_data is a list. The keys "pitch", "start" and "end" are used. + ** "pitch" determines the playback rate + ** "start" determines the start time of the sound + ** "end" determines when the musics stops playing + */ +/datum/chatOutput/proc/sendMusic(music, pitch, list/extra_data) //someone remove pitch if(!findtext(music, GLOB.is_http_protocol)) return var/list/music_data = list("adminMusic" = url_encode(url_encode(music))) - if(pitch) - music_data["musicRate"] = pitch + + if(extra_data?.len) + music_data["musicRate"] = extra_data["pitch"] || pitch + music_data["musicSeek"] = extra_data["start"] + music_data["musicHalt"] = extra_data["end"] + ehjax_send(data = music_data) +/// Stops music playing throw the browser. /datum/chatOutput/proc/stopMusic() ehjax_send(data = "stopMusic") +/// Setter for adminMusicVolume. Sanitizes the value to between 0 and 100. /datum/chatOutput/proc/setMusicVolume(volume = "") if(volume) adminMusicVolume = clamp(text2num(volume), 0, 100) -//Sends client connection details to the chat to handle and save +/// Sends client connection details to the chat to handle and save /datum/chatOutput/proc/sendClientData() //Get dem deets var/list/deets = list("clientData" = list()) @@ -150,11 +212,11 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico var/data = json_encode(deets) ehjax_send(data = data) -//Called by client, sent data to investigate (cookie history so far) +/// Called by client, sent data to investigate (cookie history so far) /datum/chatOutput/proc/analyzeClientData(cookie = "") //Spam check - if(world.time > last_check + (3 SECONDS)) - last_check = world.time + if(world.time > next_time_to_clear) + next_time_to_clear = world.time + (3 SECONDS) total_checks = 0 total_checks += 1 @@ -172,12 +234,13 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico if (connData && islist(connData) && connData.len > 0 && connData["connData"]) connectionHistory = connData["connData"] //lol fuck var/list/found = new() - if(connectionHistory.len > 5) + + if(connectionHistory.len > MAX_COOKIE_LENGTH) message_admins("[key_name(src.owner)] was kicked for an invalid ban cookie)") qdel(owner) return - for(var/i in min(connectionHistory.len, 5) to 1 step -1) + for(var/i in connectionHistory.len to 1 step -1) if(QDELETED(owner)) //he got cleaned up before we were done return @@ -191,45 +254,33 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico //Uh oh this fucker has a history of playing on a banned account!! if (found.len > 0) - //TODO: add a new evasion ban for the CURRENT client details, using the matched row details message_admins("[key_name(src.owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])") log_admin_private("[key_name(owner)] has a cookie from a banned account! (Matched: [found["ckey"]], [found["ip"]], [found["compid"]])") cookieSent = TRUE -//Called by js client every 60 seconds +/// Called by js client every 60 seconds /datum/chatOutput/proc/ping() return "pong" -//Called by js client on js error +/// Called by js client on js error /datum/chatOutput/proc/debug(error) log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]") -//Global chat procs -/proc/to_chat_immediate(target, message, handle_whitespace=TRUE) +/// Global chat proc. to_chat_immediate will circumvent SSchat and send data as soon as possible. +/proc/to_chat_immediate(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE) if(!target || !message) return - //Ok so I did my best but I accept that some calls to this will be for shit like sound and images - //It stands that we PROBABLY don't want to output those to the browser output so just handle them here - if (istype(target, /savefile)) - CRASH("Invalid message! [message]") - - if(!istext(message)) - if (istype(message, /image) || istype(message, /sound)) - CRASH("Invalid message! [message]") - return - if(target == world) target = GLOB.clients var/original_message = message - //Some macros remain in the string even after parsing and fuck up the eventual output - message = replacetext(message, "\improper", "") - message = replacetext(message, "\proper", "") if(handle_whitespace) message = replacetext(message, "\n", "
    ") - message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") + message = replacetext(message, "\t", "[FOURSPACES][FOURSPACES]") //EIGHT SPACES IN TOTAL!! + if(trailing_newline) + message += "
    " if(islist(target)) // Do the double-encoding outside the loop to save nanoseconds @@ -272,14 +323,19 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("tmp/iconCache.sav")) //Cache of ico // url_encode it TWICE, this way any UTF-8 characters are able to be decoded by the Javascript. C << output(url_encode(url_encode(message)), "browseroutput:output") -/proc/to_chat(target, message, handle_whitespace = TRUE) +/// Sends a text message to the target. +/proc/to_chat(target, message, handle_whitespace = TRUE, trailing_newline = TRUE, confidential = FALSE) if(Master.current_runlevel == RUNLEVEL_INIT || !SSchat?.initialized) - to_chat_immediate(target, message, handle_whitespace) + to_chat_immediate(target, message, handle_whitespace, trailing_newline, confidential) return - SSchat.queue(target, message, handle_whitespace) + SSchat.queue(target, message, handle_whitespace, trailing_newline, confidential) -/datum/chatOutput/proc/swaptolightmode() //Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation) +/// Dark mode light mode stuff. Yell at KMC if this breaks! (See darkmode.dm for documentation) +/datum/chatOutput/proc/swaptolightmode() owner.force_white_theme() +/// Light mode stuff. (See darkmode.dm for documentation) /datum/chatOutput/proc/swaptodarkmode() owner.force_dark_theme() + +#undef MAX_COOKIE_LENGTH diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index 3455a97ba2..2669a3634a 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -303,7 +303,10 @@ h1.alert, h2.alert {color: #000000;} .passive {color: #660000;} .userdanger {color: #ff0000; font-weight: bold; font-size: 185%;} +.bolddanger {color: #c51e1e;font-weight: bold;} .danger {color: #ff0000;} +.tinydanger {color: #c51e1e; font-size: 85%;} +.smalldanger {color: #c51e1e; font-size: 90%;} .warning {color: #ff0000; font-style: italic;} .alertwarning {color: #FF0000; font-weight: bold} .boldwarning {color: #ff0000; font-style: italic; font-weight: bold} @@ -313,6 +316,9 @@ h1.alert, h2.alert {color: #000000;} .rose {color: #ff5050;} .info {color: #0000CC;} .notice {color: #000099;} +.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;} +.smallnotice {color: #6685f5; font-size: 90%;} +.smallnoticeital {color: #6685f5; font-style: italic; font-size: 90%;} .boldnotice {color: #000099; font-weight: bold;} .adminnotice {color: #0000ff;} .adminhelp {color: #ff0000; font-weight: bold;} diff --git a/code/modules/goonchat/browserassets/html/browserOutput.html b/code/modules/goonchat/browserassets/html/browserOutput.html index 0acb127517..ce51cd8de8 100644 --- a/code/modules/goonchat/browserassets/html/browserOutput.html +++ b/code/modules/goonchat/browserassets/html/browserOutput.html @@ -38,10 +38,10 @@
    - Decrease font size - - Increase font size + - Decrease line height - - Increase line height + + Decrease font size + Increase font size + Decrease line height + Increase line height Toggle ping display Highlight string Save chat log diff --git a/code/modules/goonchat/browserassets/js/browserOutput.js b/code/modules/goonchat/browserassets/js/browserOutput.js index 0d53b44ba8..ac30076de4 100644 --- a/code/modules/goonchat/browserassets/js/browserOutput.js +++ b/code/modules/goonchat/browserassets/js/browserOutput.js @@ -29,12 +29,13 @@ var opts = { 'scrollSnapTolerance': 10, //If within x pixels of bottom 'clickTolerance': 10, //Keep focus if outside x pixels of mousedown position on mouseup 'imageRetryDelay': 50, //how long between attempts to reload images (in ms) - 'imageRetryLimit': 50, //how many attempts should we make? + 'imageRetryLimit': 50, //how many attempts should we make? 'popups': 0, //Amount of popups opened ever 'wasd': false, //Is the user in wasd mode? 'priorChatHeight': 0, //Thing for height-resizing detection 'restarting': false, //Is the round restarting? 'colorPreset': 0, // index in the color presets list. + //'darkmode':false, //Are we using darkmode? If not WHY ARE YOU LIVING IN 2009??? <- /tg/ take on darktheme //Options menu 'selectedSubLoop': null, //Contains the interval loop for closing the selected sub menu @@ -65,14 +66,17 @@ var opts = { 'volumeUpdateDelay': 5000, //Time from when the volume updates to data being sent to the server 'volumeUpdating': false, //True if volume update function set to fire 'updatedVolume': 0, //The volume level that is sent to the server - + 'musicStartAt': 0, //The position the music starts playing + 'musicEndAt': 0, //The position the music... stops playing... if null, doesn't apply (so the music runs through) + 'defaultMusicVolume': 25, 'messageCombining': true, }; +var replaceRegexes = {}; -// Array of names for chat display color presets. +// Array of names for chat display color presets. CIT SPECIFIC. // If not set to normal, a CSS file `browserOutput_${name}.css` will be added to the head. var colorPresets = [ 'normal', @@ -84,12 +88,6 @@ function clamp(val, min, max) { return Math.max(min, Math.min(val, max)) } -function outerHTML(el) { - var wrap = document.createElement('div'); - wrap.appendChild(el.cloneNode(true)); - return wrap.innerHTML; -} - //Polyfill for fucking date now because of course IE8 and below don't support it if (!Date.now) { Date.now = function now() { @@ -103,6 +101,7 @@ if (typeof String.prototype.trim !== 'function') { }; } +// CIT SPECIFIC. function updateColorPreset() { var el = $("#colorPresetLink")[0]; el.href = "browserOutput_"+colorPresets[opts.colorPreset]+".css"; @@ -172,7 +171,7 @@ function byondDecode(message) { // The replace for + is because FOR SOME REASON, BYOND replaces spaces with a + instead of %20, and a plus with %2b. // Marvelous. message = message.replace(/\+/g, "%20"); - try { + try { // This is a workaround for the above not always working when BYOND's shitty url encoding breaks. (byond bug id:2399401) if (decodeURIComponent) { message = decodeURIComponent(message); @@ -185,57 +184,71 @@ function byondDecode(message) { return message; } -//Actually turns the highlight term match into appropriate html -function addHighlightMarkup(match) { - var extra = ''; - if (opts.highlightColor) { - extra += ' style="background-color: '+opts.highlightColor+'"'; +function replaceRegex() { + var selectedRegex = replaceRegexes[$(this).attr('replaceRegex')]; + if (selectedRegex) { + var replacedText = $(this).html().replace(selectedRegex[0], selectedRegex[1]); + $(this).html(replacedText); } - return ''+match+''; + $(this).removeAttr('replaceRegex'); } -//Highlights words based on user settings +// Get a highlight markup span +function createHighlightMarkup() { + var extra = ''; + if (opts.highlightColor) { + extra += ' style="background-color: ' + opts.highlightColor + '"'; + } + return ''; +} + +// Get all child text nodes that match a regex pattern +function getTextNodes(elem, pattern) { + var result = $([]); + $(elem).contents().each(function(idx, child) { + if (child.nodeType === 3 && /\S/.test(child.nodeValue) && pattern.test(child.nodeValue)) { + result = result.add(child); + } + else { + result = result.add(getTextNodes(child, pattern)); + } + }); + return result; +} + +// Highlight all text terms matching the registered regex patterns function highlightTerms(el) { - if (el.children.length > 0) { - for(var h = 0; h < el.children.length; h++){ - highlightTerms(el.children[h]); - } - } + var pattern = new RegExp("(" + opts.highlightTerms.join('|') + ")", 'gi'); + var nodes = getTextNodes(el, pattern); - var hasTextNode = false; - for (var node = 0; node < el.childNodes.length; node++) - { - if (el.childNodes[node].nodeType === 3) - { - hasTextNode = true; - break; - } - } - - if (hasTextNode) { //If element actually has text - var newText = ''; - for (var c = 0; c < el.childNodes.length; c++) { //Each child element - if (el.childNodes[c].nodeType === 3) { //Is it text only? - var words = el.childNodes[c].data.split(' '); - for (var w = 0; w < words.length; w++) { //Each word in the text - var newWord = null; - for (var i = 0; i < opts.highlightTerms.length; i++) { //Each highlight term - if (opts.highlightTerms[i] && words[w].toLowerCase().indexOf(opts.highlightTerms[i].toLowerCase()) > -1) { //If a match is found - newWord = words[w].replace("<", "<").replace(new RegExp(opts.highlightTerms[i], 'gi'), addHighlightMarkup); - break; - } - if (window.console) - console.log(newWord) - } - newText += newWord || words[w].replace("<", "<"); - newText += w >= words.length - 1 ? '' : ' '; - } - } else { //Every other type of element - newText += outerHTML(el.childNodes[c]); + nodes.each(function (idx, node) { + var content = $(node).text(); + var parent = $(node).parent(); + var pre = $(node.previousSibling); + $(node).remove(); + content.split(pattern).forEach(function (chunk) { + // Get our highlighted span/text node + var toInsert = null; + if (pattern.test(chunk)) { + var tmpElem = $(createHighlightMarkup()); + tmpElem.text(chunk); + toInsert = tmpElem; } - } - el.innerHTML = newText; - } + else { + toInsert = document.createTextNode(chunk); + } + + // Insert back into our element + if (pre.length == 0) { + var result = parent.prepend(toInsert); + pre = $(result[0].firstChild); + } + else { + pre.after(toInsert); + pre = $(pre[0].nextSibling); + } + }); + }); } function iconError(E) { @@ -268,41 +281,96 @@ function output(message, flag) { message = byondDecode(message).trim(); - //Stuff we do along with appending a message - var atBottom = false; - var bodyHeight = $('body').height(); - var messagesHeight = $messages.outerHeight(); - var scrollPos = $('body,html').scrollTop(); - - //Should we snap the output to the bottom? - if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) { - atBottom = true; - if ($('#newMessages').length) { - $('#newMessages').remove(); - } - //If not, put the new messages box in - } else { - if ($('#newMessages').length) { - var messages = $('#newMessages .number').text(); - messages = parseInt(messages); - messages++; - $('#newMessages .number').text(messages); - if (messages == 2) { - $('#newMessages .messageWord').append('s'); + //The behemoth of filter-code (for Admin message filters) + //Note: This is proooobably hella inefficient + var filteredOut = false; + if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) { + //Get this filter type (defined by class on message) + var messageHtml = $.parseHTML(message), + messageClasses; + if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) { + var internal = false; + messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false); + if (messageClasses) { + for (var i = 0; i < messageClasses.length; i++) { //Every class + if (messageClasses[i] == 'internal') { + internal = true; + break; + } + } + } + if (!internal) { + filteredOut = 'All'; } } else { - $messages.after('1 new message '); + //If the element or it's child have any classes + if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) { + messageClasses = $(messageHtml).attr('class').split(/\s+/); + if (!!$(messageHtml).children().attr('class')) { + messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/)); + } + var tempCount = 0; + for (var i = 0; i < messageClasses.length; i++) { //Every class + var thisClass = messageClasses[i]; + $.each(opts.showMessagesFilters, function(key, val) { //Every filter + if (key !== 'All' && val.show === false && typeof val.match != 'undefined') { + for (var i = 0; i < val.match.length; i++) { + var matchClass = val.match[i]; + if (matchClass == thisClass) { + filteredOut = key; + break; + } + } + } + if (filteredOut) return false; + }); + if (filteredOut) break; + tempCount++; + } + } else { + if (!opts.showMessagesFilters['Misc'].show) { + filteredOut = 'Misc'; + } + } } } + //Stuff we do along with appending a message + var atBottom = false; + if (!filteredOut) { + var bodyHeight = $('body').height(); + var messagesHeight = $messages.outerHeight(); + var scrollPos = $('body,html').scrollTop(); + + //Should we snap the output to the bottom? + if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) { + atBottom = true; + if ($('#newMessages').length) { + $('#newMessages').remove(); + } + //If not, put the new messages box in + } else { + if ($('#newMessages').length) { + var messages = $('#newMessages .number').text(); + messages = parseInt(messages); + messages++; + $('#newMessages .number').text(messages); + if (messages == 2) { + $('#newMessages .messageWord').append('s'); + } + } else { + $messages.after('1 new message '); + } + } + } opts.messageCount++; //Pop the top message off if history limit reached - //if (opts.messageCount >= opts.messageLimit) { - //$messages.children('div.entry:first-child').remove(); - //opts.messageCount--; //I guess the count should only ever equal the limit - //} + if (opts.messageCount >= opts.messageLimit) { + $messages.children('div.entry:first-child').remove(); + opts.messageCount--; //I guess the count should only ever equal the limit + } // Create the element - if combining is off, we use it, and if it's on, we // might discard it bug need to check its text content. Some messages vary @@ -323,6 +391,7 @@ function output(message, flag) { badge = $('', {'class': 'r', 'text': 2}); } lastmessages.html(message); + lastmessages.find('[replaceRegex]').each(replaceRegex); lastmessages.append(badge); badge.animate({ "font-size": "0.9em" @@ -340,6 +409,13 @@ function output(message, flag) { //Actually append the message entry.className = 'entry'; + if (filteredOut) { + entry.className += ' hidden'; + entry.setAttribute('data-filter', filteredOut); + } + + $(entry).find('[replaceRegex]').each(replaceRegex); + $last_message = trimmed_message; $messages[0].appendChild(entry); $(entry).find("img.icon").error(iconError); @@ -360,11 +436,11 @@ function output(message, flag) { //Actually do the snap //Stuff we can do after the message shows can go here, in the interests of responsiveness if (opts.highlightTerms && opts.highlightTerms.length > 0) { - highlightTerms(entry); + highlightTerms($(entry)); } } - if (atBottom) { + if (!filteredOut && atBottom) { $('body,html').scrollTop($messages.outerHeight()); } } @@ -408,6 +484,20 @@ function toHex(n) { return "0123456789ABCDEF".charAt((n-n%16)/16) + "0123456789ABCDEF".charAt(n%16); } +/* +function swap() { //Swap to darkmode + if (opts.darkmode){ + document.getElementById("sheetofstyles").href = "browserOutput_white.css"; + opts.darkmode = false; + runByond('?_src_=chat&proc=swaptolightmode'); + } else { + document.getElementById("sheetofstyles").href = "browserOutput.css"; + opts.darkmode = true; + runByond('?_src_=chat&proc=swaptodarkmode'); + } + setCookie('darkmode', (opts.darkmode ? 'true' : 'false'), 365); +} +*/ function handleClientData(ckey, ip, compid) { //byond sends player info to here var currentData = {'ckey': ckey, 'ip': ip, 'compid': compid}; @@ -488,6 +578,7 @@ function ehjaxCallback(data) { } else if (data.adminMusic) { if (typeof data.adminMusic === 'string') { var adminMusic = byondDecode(data.adminMusic); + var bindLoadedData = false; adminMusic = adminMusic.match(/https?:\/\/\S+/) || ''; if (data.musicRate) { var newRate = Number(data.musicRate); @@ -497,9 +588,32 @@ function ehjaxCallback(data) { } else { $('#adminMusic').prop('defaultPlaybackRate', 1.0); } + if (data.musicSeek) { + opts.musicStartAt = Number(data.musicSeek) || 0; + bindLoadedData = true; + } else { + opts.musicStartAt = 0; + } + if (data.musicHalt) { + opts.musicEndAt = Number(data.musicHalt) || null; + bindLoadedData = true; + } + if (bindLoadedData) { + $('#adminMusic').one('loadeddata', adminMusicLoadedData); + } $('#adminMusic').prop('src', adminMusic); $('#adminMusic').trigger("play"); } + } else if (data.syncRegex) { + for (var i in data.syncRegex) { + + var regexData = data.syncRegex[i]; + var regexName = regexData[0]; + var regexFlags = regexData[1]; + var regexReplaced = regexData[2]; + + replaceRegexes[i] = [new RegExp(regexName, regexFlags), regexReplaced]; + } } } } @@ -530,6 +644,27 @@ function sendVolumeUpdate() { } } +function adminMusicEndCheck(event) { + if (opts.musicEndAt) { + if ($('#adminMusic').prop('currentTime') >= opts.musicEndAt) { + $('#adminMusic').off(event); + $('#adminMusic').trigger('pause'); + $('#adminMusic').prop('src', ''); + } + } else { + $('#adminMusic').off(event); + } +} + +function adminMusicLoadedData(event) { + if (opts.musicStartAt && ($('#adminMusic').prop('duration') === Infinity || (opts.musicStartAt <= $('#adminMusic').prop('duration'))) ) { + $('#adminMusic').prop('currentTime', opts.musicStartAt); + } + if (opts.musicEndAt) { + $('#adminMusic').on('timeupdate', adminMusicEndCheck); + } +} + function subSlideUp() { $(this).removeClass('scroll'); $(this).css('height', ''); @@ -608,23 +743,32 @@ $(function() { * ******************************************/ var savedConfig = { - 'sfontSize': getCookie('fontsize'), - 'slineHeight': getCookie('lineheight'), + fontsize: getCookie('fontsize'), //no need for compatabiliy, cookie name is the same + lineheight: getCookie('lineheight'), 'spingDisabled': getCookie('pingdisabled'), 'shighlightTerms': getCookie('highlightterms'), 'shighlightColor': getCookie('highlightcolor'), 'smusicVolume': getCookie('musicVolume'), 'smessagecombining': getCookie('messagecombining'), + 'sdarkmode': getCookie('darkmode'), 'scolorPreset': getCookie('colorpreset'), }; - if (savedConfig.sfontSize) { - $messages.css('font-size', savedConfig.sfontSize); - internalOutput('Loaded font size setting of: '+savedConfig.sfontSize+'', 'internal'); + if (savedConfig.fontsize) { + $messages.css('font-size', savedConfig.fontsize); + internalOutput('Loaded font size setting of: '+savedConfig.fontsize+'', 'internal'); } - if (savedConfig.slineHeight) { - $("body").css('line-height', savedConfig.slineHeight); - internalOutput('Loaded line height setting of: '+savedConfig.slineHeight+'', 'internal'); + if (savedConfig.lineheight) { + $("body").css('line-height', savedConfig.lineheight); + internalOutput('Loaded line height setting of: '+savedConfig.lineheight+'', 'internal'); + } + // if(savedConfig.sdarkmode == 'true'){ + // swap(); + // } + if (savedConfig.scolorPreset) { + opts.colorPreset = Number(savedConfig.scolorPreset); + updateColorPreset(); + internalOutput('Loaded color preset of: '+colorPresets[opts.colorPreset]+'', 'internal'); } if (savedConfig.spingDisabled) { if (savedConfig.spingDisabled == 'true') { @@ -634,15 +778,11 @@ $(function() { internalOutput('Loaded ping display of: '+(opts.pingDisabled ? 'hidden' : 'visible')+'', 'internal'); } if (savedConfig.shighlightTerms) { - var savedTerms = $.parseJSON(savedConfig.shighlightTerms); - var actualTerms = ''; - for (var i = 0; i < savedTerms.length; i++) { - if (savedTerms[i]) { - actualTerms += savedTerms[i] + ', '; - } - } + var savedTerms = $.parseJSON(savedConfig.shighlightTerms).filter(function (entry) { + return entry !== null && /\S/.test(entry); + }); + var actualTerms = savedTerms.length != 0 ? savedTerms.join(', ') : null; if (actualTerms) { - actualTerms = actualTerms.substring(0, actualTerms.length - 2); internalOutput('Loaded highlight strings of: ' + actualTerms+'', 'internal'); opts.highlightTerms = savedTerms; } @@ -651,13 +791,6 @@ $(function() { opts.highlightColor = savedConfig.shighlightColor; internalOutput('Loaded highlight color of: '+savedConfig.shighlightColor+'', 'internal'); } - - if (savedConfig.scolorPreset) { - opts.colorPreset = Number(savedConfig.scolorPreset); - updateColorPreset(); - internalOutput('Loaded color preset of: '+colorPresets[opts.colorPreset]+'', 'internal'); - } - if (savedConfig.smusicVolume) { var newVolume = clamp(savedConfig.smusicVolume, 0, 100); $('#adminMusic').prop('volume', newVolume / 100); @@ -669,7 +802,7 @@ $(function() { else{ $('#adminMusic').prop('volume', opts.defaultMusicVolume / 100); } - + if (savedConfig.smessagecombining) { if (savedConfig.smessagecombining == 'false') { opts.messageCombining = false; @@ -746,76 +879,17 @@ $(function() { href = escaper(href); runByond('?action=openLink&link='+href); } + runByond('byond://winset?mapwindow.map.focus=true'); }); - //Fuck everything about this event. Will look into alternatives. $('body').on('keydown', function(e) { if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') { return; } - if (e.ctrlKey || e.altKey || e.shiftKey) { //Band-aid "fix" for allowing ctrl+c copy paste etc. Needs a proper fix. return; } - - e.preventDefault() - - var k = e.which; - // Hardcoded because else there would be no feedback message. - if (k == 113) { // F2 - runByond('byond://winset?screenshot=auto'); - internalOutput('Screenshot taken', 'internal'); - } - - var c = ""; - switch (k) { - case 8: - c = 'BACK'; - case 9: - c = 'TAB'; - case 13: - c = 'ENTER'; - case 19: - c = 'PAUSE'; - case 27: - c = 'ESCAPE'; - case 33: // Page up - c = 'NORTHEAST'; - case 34: // Page down - c = 'SOUTHEAST'; - case 35: // End - c = 'SOUTHWEST'; - case 36: // Home - c = 'NORTHWEST'; - case 37: - c = 'WEST'; - case 38: - c = 'NORTH'; - case 39: - c = 'EAST'; - case 40: - c = 'SOUTH'; - case 45: - c = 'INSERT'; - case 46: - c = 'DELETE'; - case 93: // That weird thing to the right of alt gr. - c = 'APPS'; - - default: - c = String.fromCharCode(k); - } - - if (c.length == 0) { - if (!e.shiftKey) { - c = c.toLowerCase(); - } - runByond('byond://winset?mapwindow.map.focus=true;mainwindow.input.text='+c); - return false; - } else { - runByond('byond://winset?mapwindow.map.focus=true'); - return false; - } + runByond('byond://winset?mapwindow.map.focus=true'); }); //Mildly hacky fix for scroll issues on mob change (interface gets resized sometimes, messing up snap-scroll) @@ -843,6 +917,9 @@ $(function() { $('#toggleOptions').click(function(e) { handleToggleClick($subOptions, $(this)); }); + // $('#darkmodetoggle').click(function(e) { + // swap(); + // }); $('#toggleAudio').click(function(e) { handleToggleClick($subAudio, $(this)); }); @@ -856,41 +933,31 @@ $(function() { }); $('#decreaseFont').click(function(e) { - var fontSize = parseInt($messages.css('font-size')); - fontSize = fontSize - 1 + 'px'; - $messages.css({'font-size': fontSize}); - setCookie('fontsize', fontSize, 365); - internalOutput('Font size set to '+fontSize+'', 'internal'); + savedConfig.fontsize = Math.max(parseInt(savedConfig.fontsize || 13) - 1, 1) + 'px'; + $messages.css({'font-size': savedConfig.fontsize}); + setCookie('fontsize', savedConfig.fontsize, 365); + internalOutput('Font size set to '+savedConfig.fontsize+'', 'internal'); }); $('#increaseFont').click(function(e) { - var fontSize = parseInt($messages.css('font-size')); - fontSize = fontSize + 1 + 'px'; - $messages.css({'font-size': fontSize}); - setCookie('fontsize', fontSize, 365); - internalOutput('Font size set to '+fontSize+'', 'internal'); + savedConfig.fontsize = (parseInt(savedConfig.fontsize || 13) + 1) + 'px'; + $messages.css({'font-size': savedConfig.fontsize}); + setCookie('fontsize', savedConfig.fontsize, 365); + internalOutput('Font size set to '+savedConfig.fontsize+'', 'internal'); }); $('#decreaseLineHeight').click(function(e) { - var Heightline = parseFloat($("body").css('line-height')); - var Sizefont = parseFloat($("body").css('font-size')); - var lineheightvar = Heightline / Sizefont - lineheightvar -= 0.1; - lineheightvar = lineheightvar.toFixed(1) - $("body").css({'line-height': lineheightvar}); - setCookie('lineheight', lineheightvar, 365); - internalOutput('Line height set to '+lineheightvar+'', 'internal'); + savedConfig.lineheight = Math.max(parseFloat(savedConfig.lineheight || 1.2) - 0.1, 0.1).toFixed(1); + $("body").css({'line-height': savedConfig.lineheight}); + setCookie('lineheight', savedConfig.lineheight, 365); + internalOutput('Line height set to '+savedConfig.lineheight+'', 'internal'); }); $('#increaseLineHeight').click(function(e) { - var Heightline = parseFloat($("body").css('line-height')); - var Sizefont = parseFloat($("body").css('font-size')); - var lineheightvar = Heightline / Sizefont - lineheightvar += 0.1; - lineheightvar = lineheightvar.toFixed(1) - $("body").css({'line-height': lineheightvar}); - setCookie('lineheight', lineheightvar, 365); - internalOutput('Line height set to '+lineheightvar+'', 'internal'); + savedConfig.lineheight = (parseFloat(savedConfig.lineheight || 1.2) + 0.1).toFixed(1); + $("body").css({'line-height': savedConfig.lineheight}); + setCookie('lineheight', savedConfig.lineheight, 365); + internalOutput('Line height set to '+savedConfig.lineheight+'', 'internal'); }); $('#togglePing').click(function(e) { @@ -908,13 +975,13 @@ $(function() { // Requires IE 10+ to issue download commands. Just opening a popup // window will cause Ctrl+S to save a blank page, ignoring innerHTML. if (!window.Blob) { - output('This function is only supported on IE 10+. Upgrade if possible.', 'internal'); + output('This function is only supported on IE 10 and up. Upgrade if possible.', 'internal'); return; } $.ajax({ type: 'GET', - url: 'browserOutput.css', + url: 'browserOutput.css', // browserOutput_white.css success: function(styleData) { var blob = new Blob(['Chat Log', $messages.html(), '']); @@ -958,20 +1025,12 @@ $(function() { $('body').on('submit', '#highlightTermForm', function(e) { e.preventDefault(); - var count = 0; - while (count < opts.highlightLimit) { + opts.highlightTerms = []; + for (var count = 0; count < opts.highlightLimit; count++) { var term = $('#highlightTermInput'+count).val(); - if (term) { - term = term.trim(); - if (term === '') { - opts.highlightTerms[count] = null; - } else { - opts.highlightTerms[count] = term.toLowerCase(); - } - } else { - opts.highlightTerms[count] = null; + if (term !== null && /\S/.test(term)) { + opts.highlightTerms.push(term.trim().toLowerCase()); } - count++; } var color = $('#highlightColor').val(); @@ -992,8 +1051,8 @@ $(function() { $messages.empty(); opts.messageCount = 0; }); - - $('#changeColorPreset').click(function() { + + $('#changeColorPreset').click(function() { //CIT SPECIFIC opts.colorPreset = (opts.colorPreset+1) % colorPresets.length; updateColorPreset(); setCookie('colorpreset', opts.colorPreset, 365); @@ -1026,9 +1085,9 @@ $(function() { }); $('img.icon').error(iconError); - - - + + + /***************************************** * diff --git a/code/modules/holiday/halloween/bartholomew.dm b/code/modules/holiday/halloween/bartholomew.dm index 82ac374525..c9a4a946a3 100644 --- a/code/modules/holiday/halloween/bartholomew.dm +++ b/code/modules/holiday/halloween/bartholomew.dm @@ -31,7 +31,7 @@ return say("It doesn't seem like that's magical enough!") -/obj/item/barthpot/attack_hand(mob/user) +/obj/item/barthpot/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!active) say("Meow!") return diff --git a/code/modules/holiday/halloween/halloween.dm b/code/modules/holiday/halloween/halloween.dm index 6c9e527f38..d3b9b92b4f 100644 --- a/code/modules/holiday/halloween/halloween.dm +++ b/code/modules/holiday/halloween/halloween.dm @@ -190,7 +190,6 @@ icon_dead = "scary_clown" icon_gib = "scary_clown" speak = list("...", ". . .") - threat = 3 maxHealth = 120 health = 120 emote_see = list("silently stares") diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 107282b642..4561e0ae3e 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -56,8 +56,9 @@ cached_z = z poof() -/mob/living/simple_animal/jacq/Life() - ..() +/mob/living/simple_animal/jacq/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!ckey) if((last_poof+3 MINUTES) < world.realtime) poof() @@ -75,7 +76,7 @@ health = 25 poof() -/mob/living/simple_animal/jacq/attack_hand(mob/living/carbon/human/M) +/mob/living/simple_animal/jacq/on_attack_hand(mob/living/carbon/human/M) if(!active) say("Hello there [gender_check(M)]!") return ..() @@ -405,14 +406,14 @@ . = ..() ADD_TRAIT(src, TRAIT_NODROP, GLUED_ITEM_TRAIT) -/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user) +/obj/item/clothing/suit/ghost_sheet/sticky/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) to_chat(user, "Boooooo~!") return else ..() -/obj/item/clothing/suit/ghost_sheet/sticky/attack_hand(mob/user) +/obj/item/clothing/suit/ghost_sheet/sticky/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) to_chat(user, "Boooooo~!") return diff --git a/code/modules/holodeck/computer.dm b/code/modules/holodeck/computer.dm index 65c69b995f..e5cd36cad6 100644 --- a/code/modules/holodeck/computer.dm +++ b/code/modules/holodeck/computer.dm @@ -2,10 +2,7 @@ Holodeck Update The on-station holodeck area is of type [holodeck_type]. - All types found in GLOB.holodeck_areas_per_comp_type[src.type], generated on make_datum_references_lists(), - are loaded into the program cache or emag programs list. - Paths with their abstract_type variable equal to themselves will be skipped. - + All subtypes of [program_type] are loaded into the program cache or emag programs list. If init_program is null, a random program will be loaded on startup. If you don't wish this, set it to the offline program or another of your choosing. @@ -15,6 +12,7 @@ 3) Create a new control console that uses those areas Non-mapped areas should be skipped but you should probably comment them out anyway. + The base of program_type will always be ignored; only subtypes will be loaded. */ #define HOLODECK_CD 25 @@ -26,18 +24,20 @@ icon_screen = "holocontrol" idle_power_usage = 10 active_power_usage = 50 + var/area/holodeck/linked var/area/holodeck/program var/area/holodeck/last_program var/area/offline_program = /area/holodeck/rec_center/offline - // Splitting this up allows two holodecks of the same size - // to use the same source patterns. Y'know, if you want to. - var/holodeck_type = /area/holodeck/rec_center - var/list/program_cache var/list/emag_programs + // Splitting this up allows two holodecks of the same size + // to use the same source patterns. Y'know, if you want to. + var/holodeck_type = /area/holodeck/rec_center // locate(this) to get the target holodeck + var/program_type = /area/holodeck/rec_center // subtypes of this (but not this itself) are loadable programs + var/active = FALSE var/damaged = FALSE var/list/spawned = list() @@ -49,41 +49,47 @@ return INITIALIZE_HINT_LATELOAD /obj/machinery/computer/holodeck/LateInitialize() - linked = SSholodeck.target_holodeck_area[type] - offline_program = SSholodeck.offline_programs[type] + if(ispath(holodeck_type, /area)) + linked = pop(get_areas(holodeck_type, FALSE)) + if(ispath(offline_program, /area)) + offline_program = pop(get_areas(offline_program), FALSE) + // the following is necessary for power reasons if(!linked || !offline_program) log_world("No matching holodeck area found") qdel(src) return - - program_cache = SSholodeck.program_cache[type] - emag_programs = SSholodeck.emag_program_cache[type] - - // the following is necessary for power reasons - var/area/AS = get_base_area(src) + var/area/AS = get_area(src) if(istype(AS, /area/holodeck)) log_mapping("Holodeck computer cannot be in a holodeck, This would cause circular power dependency.") qdel(src) return else linked.linked = src - + /* + var/area/my_area = get_area(src) + if(my_area) + linked.power_usage = my_area.power_usage + else + linked.power_usage = new /list(AREA_USAGE_LEN) + */ + generate_program_list() load_program(offline_program, FALSE, FALSE) /obj/machinery/computer/holodeck/Destroy() emergency_shutdown() if(linked) linked.linked = null + //linked.power_usage = new /list(AREA_USAGE_LEN) return ..() /obj/machinery/computer/holodeck/power_change() . = ..() toggle_power(!stat) -/obj/machinery/computer/holodeck/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/holodeck/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "holodeck", name, 400, 500, master_ui, state) + ui = new(user, src, "Holodeck", name) ui.open() /obj/machinery/computer/holodeck/ui_data(mob/user) @@ -107,19 +113,27 @@ var/program_to_load = text2path(params["type"]) if(!ispath(program_to_load)) return FALSE + var/valid = FALSE + var/list/checked = program_cache.Copy() + if(obj_flags & EMAGGED) + checked |= emag_programs + for(var/prog in checked) + var/list/P = prog + if(P["type"] == program_to_load) + valid = TRUE + break + if(!valid) + return FALSE + var/area/A = locate(program_to_load) in GLOB.sortedAreas if(A) load_program(A) if("safety") - if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr)) - var/msg = "[key_name(usr)] attempted to emag the holodeck using a href they shouldn't have!" - message_admins(msg) - log_admin(msg) - return - obj_flags ^= EMAGGED - if((obj_flags & EMAGGED) && program && emag_programs[program.name]) + if((obj_flags & EMAGGED) && program) emergency_shutdown() nerf(obj_flags & EMAGGED) + obj_flags ^= EMAGGED + say("Safeties restored. Restarting...") /obj/machinery/computer/holodeck/process() if(damaged && prob(10)) @@ -160,13 +174,12 @@ if(!LAZYLEN(emag_programs)) to_chat(user, "[src] does not seem to have a card swipe port. It must be an inferior model.") return - playsound(src, "sparks", 75, 1) + playsound(src, "sparks", 75, TRUE) obj_flags |= EMAGGED to_chat(user, "You vastly increase projector power and override the safety and security protocols.") - to_chat(user, "Warning. Automatic shutoff and derezing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator.") + say("Warning. Automatic shutoff and derezzing protocols have been corrupted. Please call Nanotrasen maintenance and do not use the simulator.") log_game("[key_name(user)] emagged the Holodeck Control Console") nerf(!(obj_flags & EMAGGED)) - return TRUE /obj/machinery/computer/holodeck/emp_act(severity) . = ..() @@ -182,6 +195,19 @@ emergency_shutdown() return ..() +/obj/machinery/computer/holodeck/proc/generate_program_list() + for(var/typekey in subtypesof(program_type)) + var/area/holodeck/A = GLOB.areas_by_type[typekey] + if(!A || !A.contents.len) + continue + var/list/info_this = list() + info_this["name"] = A.name + info_this["type"] = A.type + if(A.restricted) + LAZYADD(emag_programs, list(info_this)) + else + LAZYADD(program_cache, list(info_this)) + /obj/machinery/computer/holodeck/proc/toggle_power(toggleOn = FALSE) if(active == toggleOn) return @@ -281,7 +307,7 @@ silent = FALSE // otherwise make sure they are dropped if(!silent) - visible_message("[O] fades away!") + visible_message("[O] fades away!") qdel(O) #undef HOLODECK_CD diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index c68c5de804..e4564ecb7e 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -105,10 +105,7 @@ if(user.transferItemToLoc(W, drop_location())) visible_message(" [user] dunks [W] into \the [src]!") -/obj/structure/holohoop/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/holohoop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.pulling && user.a_intent == INTENT_GRAB && isliving(user.pulling)) var/mob/living/L = user.pulling if(user.grab_state < GRAB_AGGRESSIVE) @@ -164,7 +161,7 @@ /obj/machinery/readybutton/attackby(obj/item/W as obj, mob/user as mob, params) to_chat(user, "The device is a solid button, there's nothing you can do with it!") -/obj/machinery/readybutton/attack_hand(mob/user as mob) +/obj/machinery/readybutton/on_attack_hand(mob/user as mob) . = ..() if(.) return @@ -219,7 +216,7 @@ /obj/item/paper/fluff/holodeck/trek_diploma name = "paper - Starfleet Academy Diploma" - info = {"

    Starfleet Academy


    Official Diploma


    "} + info = {"__Starfleet Academy__\nOfficial Diploma"} /obj/item/paper/fluff/holodeck/disclaimer name = "Holodeck Disclaimer" diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm index 7b5b0586d1..169c9061d3 100644 --- a/code/modules/holodeck/turfs.dm +++ b/code/modules/holodeck/turfs.dm @@ -134,7 +134,7 @@ tiled_dirt = FALSE baseturfs = /turf/open/floor/holofloor/snow -/turf/open/floor/holofloor/snow/attack_hand(mob/living/user) +/turf/open/floor/holofloor/snow/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index 06d2b3efda..b61d9451ef 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -10,13 +10,13 @@ var/processing = FALSE var/obj/item/reagent_containers/glass/beaker = null var/points = 0 - var/menustat = "menu" var/efficiency = 0 var/productivity = 0 var/max_items = 40 var/datum/techweb/stored_research var/list/show_categories = list("Food", "Botany Chemicals", "Organic Materials") - var/list/timesFiveCategories = list("Food", "Botany Chemicals") + /// Currently selected category in the UI + var/selected_cat /obj/machinery/biogenerator/Initialize() . = ..() @@ -37,22 +37,20 @@ if(A == beaker) beaker = null update_icon() - updateUsrDialog() /obj/machinery/biogenerator/RefreshParts() - var/E = 0.5 - var/P = 0.5 - var/max_storage = 20 + var/E = 0 + var/P = 0 + var/max_storage = 40 for(var/obj/item/stock_parts/matter_bin/B in component_parts) - P += B.rating * 0.5 - max_storage = max(20 * B.rating, max_storage) + P += B.rating + max_storage = 40 * B.rating for(var/obj/item/stock_parts/manipulator/M in component_parts) - E += M.rating * 0.5 + E += M.rating efficiency = E productivity = P max_items = max_storage - /obj/machinery/biogenerator/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) @@ -70,7 +68,6 @@ icon_state = "biogen-stand" else icon_state = "biogen-work" - return /obj/machinery/biogenerator/attackby(obj/item/O, mob/user, params) if(user.a_intent == INTENT_HARM) @@ -102,7 +99,6 @@ beaker = O to_chat(user, "You add the container to the machine.") update_icon() - updateUsrDialog() else to_chat(user, "Close the maintenance panel first.") return @@ -139,9 +135,9 @@ to_chat(user, "You put [O.name] in [src.name]") return TRUE //no afterattack else if (istype(O, /obj/item/disk/design_disk)) - user.visible_message("[user] begins to load \the [O] in \the [src]...", - "You begin to load a design from \the [O]...", - "You hear the chatter of a floppy drive.") + user.visible_message("[user] begins to load \the [O] in \the [src]...", + "You begin to load a design from \the [O]...", + "You hear the chatter of a floppy drive.") processing = TRUE var/obj/item/disk/design_disk/D = O if(do_after(user, 10, target = src)) @@ -153,106 +149,53 @@ else to_chat(user, "You cannot put this in [src.name]!") -/obj/machinery/biogenerator/ui_interact(mob/user) - if(stat & BROKEN || panel_open) - return - . = ..() - var/dat - if(processing) - dat += "
    Biogenerator is processing! Please wait...

    " - else - switch(menustat) - if("nopoints") - dat += "
    You do not have enough biomass to create products.
    Please, put growns into reactor and activate it.
    " - menustat = "menu" - if("complete") - dat += "
    Operation complete.
    " - menustat = "menu" - if("void") - dat += "
    Error: No growns inside.
    Please, put growns into reactor.
    " - menustat = "menu" - if("nobeakerspace") - dat += "
    Not enough space left in container. Unable to create product.
    " - menustat = "menu" - if(beaker) - var/categories = show_categories.Copy() - for(var/V in categories) - categories[V] = list() - for(var/V in stored_research.researched_designs) - var/datum/design/D = SSresearch.techweb_design_by_id(V) - for(var/C in categories) - if(C in D.category) - categories[C] += D - - dat += "
    Biomass: [points] units.

    " - dat += "ActivateDetach Container" - for(var/cat in categories) - dat += "

    [cat]:

    " - dat += "
    " - for(var/V in categories[cat]) - var/datum/design/D = V - dat += "[D.name]: Make" - if(cat in timesFiveCategories) - dat += "x5" - if(ispath(D.build_path, /obj/item/stack)) - dat += "x10" - dat += "([CEILING(D.materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]/efficiency, 1)])
    " - dat += "
    " - else - dat += "
    No container inside, please insert container.
    " - - var/datum/browser/popup = new(user, "biogen", name, 350, 520) - popup.set_content(dat) - popup.open() - /obj/machinery/biogenerator/AltClick(mob/living/user) . = ..() - if(istype(user) && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK) && can_interact(user)) detach(user) -/obj/machinery/biogenerator/proc/activate() - if (usr.stat != CONSCIOUS) +/** + * activate: Activates biomass processing and converts all inserted grown products into biomass + * + * Arguments: + * * user The mob starting the biomass processing + */ +/obj/machinery/biogenerator/proc/activate(mob/user) + if(user.stat != CONSCIOUS) return - if (src.stat != NONE) //NOPOWER etc + if(stat != NONE) return if(processing) - to_chat(usr, "The biogenerator is in the process of working.") + to_chat(user, "The biogenerator is in the process of working.") return var/S = 0 - var/total = 0 for(var/obj/item/reagent_containers/food/snacks/grown/I in contents) S += 5 - var/nutri_amount = I.reagents.get_reagent_amount(/datum/reagent/consumable/nutriment) - if(nutri_amount < 0.1) - total += 1*productivity + if(I.reagents.get_reagent_amount(/datum/reagent/consumable/nutriment) < 0.1) + points += 1 * productivity else - total += nutri_amount*10*productivity + points += I.reagents.get_reagent_amount(/datum/reagent/consumable/nutriment) * 10 * productivity qdel(I) - points += round(total) if(S) processing = TRUE update_icon() - updateUsrDialog() - playsound(src.loc, 'sound/machines/blender.ogg', 50, 1) - use_power(S*30) - sleep(S+15/productivity) + playsound(loc, 'sound/machines/blender.ogg', 50, TRUE) + use_power(S * 30) + sleep(S + 15 / productivity) + if(QDELETED(src)) //let's not. + return processing = FALSE update_icon() - else - menustat = "void" /obj/machinery/biogenerator/proc/check_cost(list/materials, multiplier = 1, remove_points = TRUE) if(materials.len != 1 || materials[1] != SSmaterials.GetMaterialRef(/datum/material/biomass)) return FALSE - var/cost = CEILING(materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency, 1) - if (cost > points) - menustat = "nopoints" + if (materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency > points) return FALSE else if(remove_points) - points -= cost + points -= materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]*multiplier/efficiency update_icon() - updateUsrDialog() return TRUE /obj/machinery/biogenerator/proc/check_container_volume(list/reagents, multiplier = 1) @@ -262,7 +205,6 @@ sum_reagents *= multiplier if(beaker.reagents.total_volume + sum_reagents > beaker.reagents.maximum_volume) - menustat = "nobeakerspace" return FALSE return TRUE @@ -284,6 +226,7 @@ var/i = amount while(i > 0) if(!check_container_volume(D.make_reagents)) + say("Warning: Attached container does not have enough free capacity!") return . if(!check_cost(D.materials)) return . @@ -293,51 +236,100 @@ beaker.reagents.add_reagent(R, D.make_reagents[R]) . = 1 --i - - menustat = "complete" update_icon() return . /obj/machinery/biogenerator/proc/detach(mob/living/user) if(beaker) - user.put_in_hands(beaker) + if(can_interact(user)) + user.put_in_hands(beaker) + else + beaker.drop_location(get_turf(src)) beaker = null update_icon() -/obj/machinery/biogenerator/Topic(href, href_list) - if(..() || panel_open) +/obj/machinery/biogenerator/ui_status(mob/user) + if(stat & BROKEN || panel_open) + return UI_CLOSE + return ..() + +/obj/machinery/biogenerator/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/research_designs), + ) + +/obj/machinery/biogenerator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "Biogenerator", name) + ui.open() + +/obj/machinery/biogenerator/ui_data(mob/user) + var/list/data = list() + data["beaker"] = beaker ? TRUE : FALSE + data["biomass"] = points + data["processing"] = processing + if(locate(/obj/item/reagent_containers/food/snacks/grown) in contents) + data["can_process"] = TRUE + else + data["can_process"] = FALSE + return data + +/obj/machinery/biogenerator/ui_static_data(mob/user) + var/list/data = list() + data["categories"] = list() + + var/categories = show_categories.Copy() + for(var/V in categories) + categories[V] = list() + for(var/V in stored_research.researched_designs) + var/datum/design/D = SSresearch.techweb_design_by_id(V) + for(var/C in categories) + if(C in D.category) + categories[C] += D + + for(var/category in categories) + var/list/cat = list( + "name" = category, + "items" = (category == selected_cat ? list() : null)) + for(var/item in categories[category]) + var/datum/design/D = item + cat["items"] += list(list( + "id" = D.id, + "name" = D.name, + "cost" = D.materials[SSmaterials.GetMaterialRef(/datum/material/biomass)]/efficiency, + )) + data["categories"] += list(cat) + + return data + +/obj/machinery/biogenerator/ui_act(action, list/params) + if(..()) return - usr.set_machine(src) - - if(href_list["activate"]) - activate() - updateUsrDialog() - - else if(href_list["detach"]) - detach(usr) - updateUsrDialog() - - else if(href_list["create"]) - var/amount = (text2num(href_list["amount"])) - //Can't be outside these (if you change this keep a sane limit) - amount = clamp(amount, 1, 50) - var/id = href_list["create"] - if(!stored_research.researched_designs.Find(id)) - //naughty naughty - stack_trace("ID did not map to a researched datum [id]") - return - - //Get design by id (or may return error design) - var/datum/design/D = SSresearch.techweb_design_by_id(id) - //Valid design datum, amount and the datum is not the error design, lets proceed - if(D && amount && !istype(D, /datum/design/error_design)) - create_product(D, amount) - //This shouldnt happen normally but href forgery is real - else - stack_trace("ID could not be turned into a valid techweb design datum [id]") - updateUsrDialog() - - else if(href_list["menu"]) - menustat = "menu" - updateUsrDialog() + switch(action) + if("activate") + activate(usr) + return TRUE + if("detach") + detach(usr) + return TRUE + if("create") + var/amount = text2num(params["amount"]) + amount = clamp(amount, 1, 10) + if(!amount) + return + var/id = params["id"] + if(!stored_research.researched_designs.Find(id)) + stack_trace("ID did not map to a researched datum [id]") + return + var/datum/design/D = SSresearch.techweb_design_by_id(id) + if(D && !istype(D, /datum/design/error_design)) + create_product(D, amount) + else + stack_trace("ID could not be turned into a valid techweb design datum [id]") + return + return TRUE + if("select") + selected_cat = params["category"] + return TRUE diff --git a/code/modules/hydroponics/fermenting_barrel.dm b/code/modules/hydroponics/fermenting_barrel.dm index 11bb44ce97..76e36a1725 100644 --- a/code/modules/hydroponics/fermenting_barrel.dm +++ b/code/modules/hydroponics/fermenting_barrel.dm @@ -56,7 +56,7 @@ else return ..() -/obj/structure/fermenting_barrel/attack_hand(mob/user) +/obj/structure/fermenting_barrel/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) open = !open if(open) DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE) diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm index 4e545c13ee..a0c273613f 100644 --- a/code/modules/hydroponics/gene_modder.dm +++ b/code/modules/hydroponics/gene_modder.dm @@ -3,9 +3,9 @@ desc = "An advanced device designed to manipulate plant genetic makeup." icon = 'icons/obj/hydroponics/equipment.dmi' icon_state = "dnamod" - density = TRUE circuit = /obj/item/circuitboard/machine/plantgenes - pass_flags = PASSTABLE + pass_flags = PASSTABLE | LETPASSTHROW + flags_1 = DEFAULT_RICOCHET_1 var/obj/item/seeds/seed var/obj/item/disk/plantgene/disk diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm index 0411a80443..81318f8fe1 100644 --- a/code/modules/hydroponics/grown/banana.dm +++ b/code/modules/hydroponics/grown/banana.dm @@ -27,6 +27,12 @@ juice_results = list(/datum/reagent/consumable/banana = 0) distill_reagent = /datum/reagent/consumable/ethanol/bananahonk +/obj/item/reagent_containers/food/snacks/grown/banana/generate_trash(atom/location) + . = ..() + var/obj/item/grown/bananapeel/peel = . + if(istype(peel)) + peel.grind_results = list(/datum/reagent/consumable/banana_peel = seed.potency * 0.2) + /obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user) user.visible_message("[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1) diff --git a/code/modules/hydroponics/grown/cannabis.dm b/code/modules/hydroponics/grown/cannabis.dm index 621e79fb77..6525ac42d4 100644 --- a/code/modules/hydroponics/grown/cannabis.dm +++ b/code/modules/hydroponics/grown/cannabis.dm @@ -14,9 +14,7 @@ icon_dead = "cannabis-dead" // Same for the dead icon genes = list(/datum/plant_gene/trait/repeated_harvest) mutatelist = list(/obj/item/seeds/cannabis/rainbow, - /obj/item/seeds/cannabis/death, - /obj/item/seeds/cannabis/white, - /obj/item/seeds/cannabis/ultimate) + /obj/item/seeds/cannabis/death) reagents_add = list(/datum/reagent/drug/space_drugs = 0.15, /datum/reagent/toxin/lipolicide = 0.35) // gives u the munchies @@ -27,7 +25,7 @@ species = "megacannabis" plantname = "Rainbow Weed" product = /obj/item/reagent_containers/food/snacks/grown/cannabis/rainbow - mutatelist = list() + mutatelist = list(/obj/item/seeds/cannabis/ultimate) reagents_add = list(/datum/reagent/toxin/mindbreaker = 0.15, /datum/reagent/toxin/lipolicide = 0.35) rarity = 40 @@ -38,7 +36,7 @@ species = "blackcannabis" plantname = "Deathweed" product = /obj/item/reagent_containers/food/snacks/grown/cannabis/death - mutatelist = list() + mutatelist = list(/obj/item/seeds/cannabis/white) reagents_add = list(/datum/reagent/toxin/cyanide = 0.35, /datum/reagent/drug/space_drugs = 0.15, /datum/reagent/toxin/lipolicide = 0.15) rarity = 40 diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm index 0522b5fd45..001a90b441 100644 --- a/code/modules/hydroponics/grown/chili.dm +++ b/code/modules/hydroponics/grown/chili.dm @@ -80,11 +80,9 @@ foodtype = FRUIT wine_power = 50 -/obj/item/reagent_containers/food/snacks/grown/ghost_chili/attack_hand(mob/user) +/obj/item/reagent_containers/food/snacks/grown/ghost_chili/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() - if(.) - return - if( ismob(loc) ) + if(ishuman(loc)) held_mob = loc START_PROCESSING(SSobj, src) diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm index f4748ccde8..d130d50aa5 100644 --- a/code/modules/hydroponics/grown/citrus.dm +++ b/code/modules/hydroponics/grown/citrus.dm @@ -33,26 +33,6 @@ filling_color = "#00FF00" juice_results = list(/datum/reagent/consumable/limejuice = 0) -// Electric Lime -/obj/item/seeds/lime/electric - name = "pack of electric lime seeds" - desc = "Electrically sour seeds." - icon_state = "seed-electriclime" - species = "electric lime" - plantname = "Electric Lime Tree" - growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi' - icon_grow = "lime-grow" - icon_dead = "lime-dead" - icon_harvest = "lime-harvest" - product = /obj/item/reagent_containers/food/snacks/grown/citrus/lime/electric - genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/cell_charge, /datum/plant_gene/trait/glow/green) - -/obj/item/reagent_containers/food/snacks/grown/citrus/lime/electric - seed = /obj/item/seeds/lime/electric - name = "electric lime" - desc = "It's so sour, you'll be shocked!" - icon_state = "electriclime" - // Orange /obj/item/seeds/orange name = "pack of orange seeds" @@ -107,8 +87,8 @@ icon_state = "orang" filling_color = "#FFA500" juice_results = list(/datum/reagent/consumable/orangejuice = 0) - distill_reagent = /datum/reagent/consumable/ethanol/triple_sec - tastes = list("polygons" = 1, "oranges" = 1) + distill_reagent = /datum/reagent/toxin/mindbreaker + tastes = list("polygons" = 1, "bluespace" = 1, "the true nature of reality" = 1) /obj/item/reagent_containers/food/snacks/grown/citrus/orange_3d/pickup(mob/user) . = ..() diff --git a/code/modules/hydroponics/grown/corn.dm b/code/modules/hydroponics/grown/corn.dm index 6c852c426d..ad09751e44 100644 --- a/code/modules/hydroponics/grown/corn.dm +++ b/code/modules/hydroponics/grown/corn.dm @@ -38,6 +38,7 @@ throwforce = 0 throw_speed = 3 throw_range = 7 + grind_results = list(/datum/reagent/cellulose = 10) /obj/item/grown/corncob/attackby(obj/item/grown/W, mob/user, params) if(W.get_sharpness()) diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm index 8b0dcdaae1..abd06775af 100644 --- a/code/modules/hydroponics/grown/flowers.dm +++ b/code/modules/hydroponics/grown/flowers.dm @@ -277,7 +277,7 @@ growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi' icon_grow = "bee_balm-grow" icon_dead = "bee_balm-dead" - mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey) //Lower odds of becoming honey + mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/bee_balm/honey_balm) //Lower odds of becoming honey reagents_add = list(/datum/reagent/medicine/spaceacillin = 0.1, /datum/reagent/space_cleaner/sterilizine = 0.05) /obj/item/reagent_containers/food/snacks/grown/bee_balm @@ -291,11 +291,11 @@ foodtype = GROSS // Beebalm -/obj/item/seeds/bee_balm/honey +/obj/item/seeds/bee_balm/honey_balm name = "pack of Honey Balm seeds" desc = "These seeds grow into Honey Balms." - icon_state = "seed-bee_balmalt" - species = "seed-bee_balm_alt" + icon_state = "seed-honey_balm" + species = "honey_balm" plantname = "Honey Balm Pods" product = /obj/item/reagent_containers/food/snacks/grown/bee_balm/honey endurance = 1 @@ -304,16 +304,16 @@ potency = 1 growthstages = 3 growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi' - icon_grow = "bee_balmalt-grow" - icon_dead = "bee_balmalt-dead" + icon_grow = "honey_balm-grow" + icon_dead = "honey_balm-dead" reagents_add = list(/datum/reagent/consumable/honey = 0.1, /datum/reagent/lye = 0.3) //To make wax rarity = 30 /obj/item/reagent_containers/food/snacks/grown/bee_balm/honey - seed = /obj/item/seeds/bee_balm/honey + seed = /obj/item/seeds/bee_balm/honey_balm name = "honey balm" desc = "A large honey filled pod of a flower." - icon_state = "bee_balmalt" + icon_state = "honey_balm" filling_color = "#FF6347" bitesize_mod = 8 tastes = list("wax" = 1) diff --git a/code/modules/hydroponics/grown/garlic.dm b/code/modules/hydroponics/grown/garlic.dm index 4184b85008..2cc3f41860 100644 --- a/code/modules/hydroponics/grown/garlic.dm +++ b/code/modules/hydroponics/grown/garlic.dm @@ -9,6 +9,9 @@ potency = 25 growthstages = 3 growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + icon_grow = "garlic-grow" + icon_harvest = "garlic-harvest" + icon_dead = "garlic-dead" reagents_add = list(/datum/reagent/consumable/garlic = 0.15, /datum/reagent/consumable/nutriment = 0.1) /obj/item/reagent_containers/food/snacks/grown/garlic diff --git a/code/modules/hydroponics/grown/grass_carpet.dm b/code/modules/hydroponics/grown/grass_carpet.dm index 3b5159465c..a74850f3be 100644 --- a/code/modules/hydroponics/grown/grass_carpet.dm +++ b/code/modules/hydroponics/grown/grass_carpet.dm @@ -51,6 +51,7 @@ icon_grow = "fairygrass-grow" icon_dead = "fairygrass-dead" genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/glow/blue) + mutatelist = list (/obj/item/seeds/grass/carpet) reagents_add = list(/datum/reagent/consumable/nutriment = 0.02, /datum/reagent/hydrogen = 0.05, /datum/reagent/drug/space_drugs = 0.15) /obj/item/reagent_containers/food/snacks/grown/grass/fairy @@ -99,7 +100,7 @@ species = "carpet" plantname = "Carpet" product = /obj/item/reagent_containers/food/snacks/grown/grass/carpet - mutatelist = list() + mutatelist = list(/obj/item/seeds/grass/fairy) rarity = 10 /obj/item/reagent_containers/food/snacks/grown/grass/carpet diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm index e5c8f72dfe..fe60e9f397 100644 --- a/code/modules/hydroponics/grown/misc.dm +++ b/code/modules/hydroponics/grown/misc.dm @@ -57,8 +57,8 @@ return var/datum/gas_mixture/stank = new - stank.gases[/datum/gas/miasma] = (yield + 6)*7*0.02 // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses - stank.temperature = T20C // without this the room would eventually freeze and miasma mining would be easier + stank.adjust_moles(/datum/gas/miasma,(yield + 6)*7*0.02) // this process is only being called about 2/7 as much as corpses so this is 12-32 times a corpses + stank.set_temperature(T20C) // without this the room would eventually freeze and miasma mining would be easier T.assume_air(stank) T.air_update_turf() @@ -504,3 +504,34 @@ prime() if(!QDELETED(src)) qdel(src) + +/obj/item/seeds/aloe + name = "pack of aloe seeds" + desc = "These seeds grow into aloe." + icon_state = "seed-aloe" + species = "aloe" + plantname = "Aloe" + product = /obj/item/reagent_containers/food/snacks/grown/aloe + lifespan = 60 + endurance = 25 + maturation = 4 + production = 4 + yield = 6 + growthstages = 5 + growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' + reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.05, /datum/reagent/consumable/nutriment = 0.05) + +/obj/item/reagent_containers/food/snacks/grown/aloe + seed = /obj/item/seeds/aloe + name = "aloe" + desc = "Cut leaves from the aloe plant." + icon_state = "aloe" + filling_color = "#90EE90" + bitesize_mod = 5 + foodtype = VEGETABLES + juice_results = list(/datum/reagent/consumable/aloejuice = 0) + distill_reagent = /datum/reagent/consumable/ethanol/tequila + +/obj/item/reagent_containers/food/snacks/grown/aloe/microwave_act(obj/machinery/microwave/M) + new /obj/item/stack/medical/aloe(drop_location(), 2) + qdel(src) \ No newline at end of file diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm index 0979ea483f..cee7748c59 100644 --- a/code/modules/hydroponics/grown/nettle.dm +++ b/code/modules/hydroponics/grown/nettle.dm @@ -90,6 +90,7 @@ icon_state = "deathnettle" force = 30 throwforce = 15 + wound_bonus = CANT_WOUND /obj/item/reagent_containers/food/snacks/grown/nettle/death/add_juice() ..() diff --git a/code/modules/hydroponics/grown/peas.dm b/code/modules/hydroponics/grown/peas.dm index 6229d98b2c..79d506cf56 100644 --- a/code/modules/hydroponics/grown/peas.dm +++ b/code/modules/hydroponics/grown/peas.dm @@ -61,6 +61,7 @@ filling_color = "#ee7bee" bitesize_mod = 2 foodtype = VEGETABLES + juice_results = list (/datum/reagent/consumable/laughsyrup = 0) 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" diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index aeddf771b8..328b4c391c 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -29,6 +29,28 @@ create_reagents(volume, INJECTABLE | DRAWABLE) +/obj/item/seeds/replicapod/pre_attack(obj/machinery/hydroponics/I) + if(istype(I, /obj/machinery/hydroponics)) + if(!I.myseed) + START_PROCESSING(SSobj, src) + return ..() + +/obj/item/seeds/replicapod/proc/check_mind_orbiting(atom/A) + for(var/mob/M in A.orbiters?.orbiters) + if(mind && M.mind && ckey(M.mind.key) == ckey(mind.key) && M.ckey && M.client && M.stat == DEAD && !M.suiciding && isobserver(M)) + return TRUE + return FALSE + +/obj/item/seeds/replicapod/process() + var/obj/machinery/hydroponics/parent = loc + if(parent.harvest != 1) + return + if (check_mind_orbiting(parent)) + icon_harvest = "replicapod-orbit" + else + icon_harvest = "replicapod-harvest" + parent.update_icon_plant() + /obj/item/seeds/replicapod/on_reagent_change(changetype) if(changetype == ADD_REAGENT) var/datum/reagent/blood/B = reagents.has_reagent(/datum/reagent/blood) @@ -59,8 +81,11 @@ /obj/item/seeds/replicapod/get_analyzer_text() var/text = ..() + var/obj/machinery/hydroponics/parent = loc if(contains_sample) text += "\n It contains a blood sample!" + if (parent && istype(parent) && check_mind_orbiting(parent)) + text += "\n The soul is ready to enter the body." return text diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm index 48990d88c9..223b2c7bce 100644 --- a/code/modules/hydroponics/grown/tea_coffee.dm +++ b/code/modules/hydroponics/grown/tea_coffee.dm @@ -44,14 +44,17 @@ filling_color = "#4582B4" grind_results = list(/datum/reagent/toxin/teapowder = 0, /datum/reagent/medicine/salglu_solution = 0) -// Kitty drugs +// Catnip /obj/item/seeds/tea/catnip name = "pack of catnip seeds" icon_state = "seed-catnip" - desc = "Long stocks with flowering tips that has a chemical to make feline attracted to it." + desc = "Long stocks with flowering tips that contain a chemical to make felines attracted to it." species = "catnip" plantname = "Catnip Plant" growthstages = 3 + icon_grow = "catnip-grow" + icon_harvest = "catnip-harvest" + icon_dead = "tea-dead" product = /obj/item/reagent_containers/food/snacks/grown/tea/catnip reagents_add = list(/datum/reagent/pax/catnip = 0.1, /datum/reagent/consumable/nutriment/vitamin = 0.06, /datum/reagent/toxin/teapowder = 0.3) rarity = 50 diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm index a18dbe165d..ecbfa7584b 100644 --- a/code/modules/hydroponics/grown/towercap.dm +++ b/code/modules/hydroponics/grown/towercap.dm @@ -16,6 +16,7 @@ icon_dead = "towercap-dead" genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism) mutatelist = list(/obj/item/seeds/tower/steel) + reagents_add = list(/datum/reagent/cellulose = 0.05) /obj/item/seeds/tower/steel name = "pack of steel-cap mycelium" @@ -25,6 +26,7 @@ plantname = "Steel Caps" product = /obj/item/grown/log/steel mutatelist = list() + reagents_add = list(/datum/reagent/cellulose = 0.05, /datum/reagent/iron = 0.05) rarity = 20 /obj/item/grown/log @@ -205,10 +207,7 @@ return ..() -/obj/structure/bonfire/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/bonfire/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(burning) to_chat(user, "You need to extinguish [src] before removing the logs!") return @@ -226,8 +225,8 @@ if(isopenturf(loc)) var/turf/open/O = loc if(O.air) - var/loc_gases = O.air.gases - if(loc_gases[/datum/gas/oxygen] > 13) + var/datum/gas_mixture/loc_air = O.air + if(loc_air.get_moles(/datum/gas/oxygen) > 13) return TRUE return FALSE diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm index 9b5983c8e9..f6be9db9a2 100644 --- a/code/modules/hydroponics/hydroitemdefines.dm +++ b/code/modules/hydroponics/hydroitemdefines.dm @@ -82,7 +82,7 @@ custom_materials = list(/datum/material/iron = 15000) attack_verb = list("chopped", "torn", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/hatchet/Initialize() . = ..() @@ -103,6 +103,7 @@ throwforce = 5 throw_speed = 2 throw_range = 3 + attack_speed = CLICK_CD_MELEE w_class = WEIGHT_CLASS_BULKY flags_1 = CONDUCT_1 armour_penetration = 20 @@ -125,9 +126,12 @@ playsound(src,pick('sound/misc/desceration-01.ogg','sound/misc/desceration-02.ogg','sound/misc/desceration-01.ogg') ,50, 1, -1) return (BRUTELOSS) -/obj/item/scythe/pre_attack(atom/A, mob/living/user, params) +/obj/item/scythe/pre_attack(atom/A, mob/living/user, params, attackchain_flags, damage_multiplier) + . = ..() + if(. & STOP_ATTACK_PROC_CHAIN) + return if(swiping || !istype(A, /obj/structure/spacevine) || get_turf(A) == get_turf(user)) - return ..() + return else var/turf/user_turf = get_turf(user) var/dir_to_target = get_dir(user_turf, get_turf(A)) @@ -138,11 +142,12 @@ var/turf/T = get_step(user_turf, turn(dir_to_target, i)) for(var/obj/structure/spacevine/V in T) if(user.Adjacent(V)) - melee_attack_chain(user, V) + melee_attack_chain(user, V, attackchain_flags = ATTACK_IGNORE_CLICKDELAY) stam_gain += 5 //should be hitcost swiping = FALSE stam_gain += 2 //Initial hitcost user.adjustStaminaLoss(-stam_gain) + user.DelayNextAction() // ************************************* // Nutrient defines for hydroponics @@ -192,4 +197,4 @@ /obj/item/reagent_containers/glass/bottle/killer/pestkiller name = "bottle of pest spray" desc = "Contains a pesticide." - list_reagents = list(/datum/reagent/toxin/pestkiller = 50) \ No newline at end of file + list_reagents = list(/datum/reagent/toxin/pestkiller = 50) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index b7665d7b5d..a208f2de3c 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -30,7 +30,7 @@ var/self_sufficiency_req = 20 //Required total dose to make a self-sufficient hydro tray. 1:1 with earthsblood. var/self_sufficiency_progress = 0 var/self_sustaining = FALSE //If the tray generates nutrients and water on its own - + var/canirrigate = TRUE //tin /obj/machinery/hydroponics/constructable name = "hydroponics tray" @@ -847,12 +847,13 @@ if (!anchored) to_chat(user, "Anchor the tray first!") return - using_irrigation = !using_irrigation - O.play_tool_sound(src) - user.visible_message("[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.", \ - "You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.") - for(var/obj/machinery/hydroponics/h in range(1,src)) - h.update_icon() + if(canirrigate) + using_irrigation = !using_irrigation + O.play_tool_sound(src) + user.visible_message("[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.", \ + "You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.") + for(var/obj/machinery/hydroponics/h in range(1,src)) + h.update_icon() else if(istype(O, /obj/item/shovel/spade)) if(!myseed && !weedlevel) @@ -888,10 +889,7 @@ return ..() -/obj/machinery/hydroponics/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/hydroponics/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(issilicon(user)) //How does AI know what plant is? return if(harvest) @@ -913,11 +911,14 @@ harvest = 0 lastproduce = age if(istype(myseed, /obj/item/seeds/replicapod)) - to_chat(user, "You harvest from the [myseed.plantname].") + if(user)//runtimes + to_chat(user, "You harvest from the [myseed.plantname].") else if(myseed.getYield() <= 0) - to_chat(user, "You fail to harvest anything useful!") + if(user) + to_chat(user, "You fail to harvest anything useful!") else - to_chat(user, "You harvest [myseed.getYield()] items from the [myseed.plantname].") + if(user) + to_chat(user, "You harvest [myseed.getYield()] items from the [myseed.plantname].") if(!myseed.get_gene(/datum/plant_gene/trait/repeated_harvest)) qdel(myseed) myseed = null diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm index b18f4396d6..887ea0417c 100644 --- a/code/modules/hydroponics/plant_genes.dm +++ b/code/modules/hydroponics/plant_genes.dm @@ -157,12 +157,12 @@ /datum/plant_gene/reagent/polypyr name = "Polypyrylium Oligomers" - reagent_id = "polypyr" + reagent_id = /datum/reagent/medicine/polypyr rate = 0.15 /datum/plant_gene/reagent/liquidelectricity name = "Liquid Electricity" - reagent_id = "liquidelectricity" + reagent_id = /datum/reagent/consumable/liquidelectricity rate = 0.1 // Various traits affecting the product. Each must be somehow useful. @@ -392,7 +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)) - if(I.use_tool(src, user, 0, 5, max_level = JOB_SKILL_EXPERT)) + if(I.use_tool(src, user, 0, 5, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)) 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/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm index 63b96632e6..71701d9637 100644 --- a/code/modules/hydroponics/seed_extractor.dm +++ b/code/modules/hydroponics/seed_extractor.dm @@ -1,3 +1,18 @@ +/** + * Finds and extracts seeds from an object + * + * Checks if the object is such that creates a seed when extracted. Used by seed + * extractors or posably anything that would create seeds in some way. The seeds + * are dropped either at the extractor, if it exists, or where the original object + * was and it qdel's the object + * + * Arguments: + * * O - Object containing the seed, can be the loc of the dumping of seeds + * * t_max - Amount of seed copies to dump, -1 is ranomized + * * extractor - Seed Extractor, used as the dumping loc for the seeds and seed multiplier + * * user - checks if we can remove the object from the inventory + * * + */ /proc/seedify(obj/item/O, t_max, obj/machinery/seed_extractor/extractor, mob/living/user) var/t_amount = 0 var/list/seeds = list() @@ -46,20 +61,22 @@ icon_state = "sextractor" density = TRUE circuit = /obj/item/circuitboard/machine/seed_extractor - var/piles = list() + /// Associated list of seeds, they are all weak refs. We check the len to see how many refs we have for each + // seed + var/list/piles = list() var/max_seeds = 1000 var/seed_multiplier = 1 /obj/machinery/seed_extractor/RefreshParts() for(var/obj/item/stock_parts/matter_bin/B in component_parts) - max_seeds = 1000 * B.rating + max_seeds = initial(max_seeds) * B.rating for(var/obj/item/stock_parts/manipulator/M in component_parts) - seed_multiplier = M.rating + seed_multiplier = initial(seed_multiplier) * M.rating /obj/machinery/seed_extractor/examine(mob/user) . = ..() if(in_range(user, src) || isobserver(user)) - . += "The status display reads: Extracting [seed_multiplier] seed(s) per piece of produce.
    Machine can store up to [max_seeds] seeds.
    " + . += "The status display reads: Extracting [seed_multiplier] seed(s) per piece of produce.
    Machine can store up to [max_seeds]% seeds.
    " /obj/machinery/seed_extractor/attackby(obj/item/O, mob/user, params) @@ -102,78 +119,26 @@ else return ..() -/datum/seed_pile - var/name = "" - var/lifespan = 0 //Saved stats - var/endurance = 0 - var/maturation = 0 - var/production = 0 - var/yield = 0 - var/potency = 0 - var/amount = 0 +/** + * Generate seed string + * + * Creates a string based of the traits of a seed. We use this string as a bucket for all + * seeds that match as well as the key the ui uses to get the seed. We also use the key + * for the data shown in the ui. Javascript parses this string to display + * + * Arguments: + * * O - seed to generate the string from + */ +/obj/machinery/seed_extractor/proc/generate_seed_string(obj/item/seeds/O) + return "name=[O.name];lifespan=[O.lifespan];endurance=[O.endurance];maturation=[O.maturation];production=[O.production];yield=[O.yield];potency=[O.potency];instability=0" -/datum/seed_pile/New(var/name, var/life, var/endur, var/matur, var/prod, var/yie, var/poten, var/am = 1) - src.name = name - src.lifespan = life - src.endurance = endur - src.maturation = matur - src.production = prod - src.yield = yie - src.potency = poten - src.amount = am - -/obj/machinery/seed_extractor/ui_interact(mob/user) - . = ..() - if (stat) - return FALSE - - var/dat = "Stored seeds:
    " - - if (contents.len == 0) - dat += "No seeds" - else - dat += "" - for (var/datum/seed_pile/O in piles) - dat += "" - dat += "" - dat += "
    NameLifespanEnduranceMaturationProductionYieldPotencyStock
    [O.name][O.lifespan][O.endurance][O.maturation][O.production][O.yield][O.potency]" - dat += "Vend ([O.amount] left)
    " - var/datum/browser/popup = new(user, "seed_ext", name, 700, 400) - popup.set_content(dat) - popup.open() - return - -/obj/machinery/seed_extractor/Topic(var/href, var/list/href_list) - if(..()) - return - usr.set_machine(src) - - href_list["li"] = text2num(href_list["li"]) - href_list["en"] = text2num(href_list["en"]) - href_list["ma"] = text2num(href_list["ma"]) - href_list["pr"] = text2num(href_list["pr"]) - href_list["yi"] = text2num(href_list["yi"]) - href_list["pot"] = text2num(href_list["pot"]) - - for (var/datum/seed_pile/N in piles)//Find the pile we need to reduce... - if (href_list["name"] == N.name && href_list["li"] == N.lifespan && href_list["en"] == N.endurance && href_list["ma"] == N.maturation && href_list["pr"] == N.production && href_list["yi"] == N.yield && href_list["pot"] == N.potency) - if(N.amount <= 0) - return - N.amount = max(N.amount - 1, 0) - if (N.amount <= 0) - piles -= N - qdel(N) - break - - for (var/obj/T in contents)//Now we find the seed we need to vend - var/obj/item/seeds/O = T - if (O.plantname == href_list["name"] && O.lifespan == href_list["li"] && O.endurance == href_list["en"] && O.maturation == href_list["ma"] && O.production == href_list["pr"] && O.yield == href_list["yi"] && O.potency == href_list["pot"]) - O.forceMove(drop_location()) - break - - src.updateUsrDialog() - return +/** Add Seeds Proc. + * + * Adds the seeds to the contents and to an associated list that pregenerates the data + * needed to go to the ui handler + * + **/ /obj/machinery/seed_extractor/proc/add_seed(obj/item/seeds/O) if(contents.len >= 999) to_chat(usr, "\The [src] is full.") @@ -188,10 +153,47 @@ if(!M.transferItemToLoc(O, src)) return FALSE - . = TRUE - for (var/datum/seed_pile/N in piles) - if (O.plantname == N.name && O.lifespan == N.lifespan && O.endurance == N.endurance && O.maturation == N.maturation && O.production == N.production && O.yield == N.yield && O.potency == N.potency) - ++N.amount - return + var/seed_string = generate_seed_string(O) + if(piles[seed_string]) + piles[seed_string] += WEAKREF(O) + else + piles[seed_string] = list(WEAKREF(O)) + + . = TRUE + +/obj/machinery/seed_extractor/ui_state(mob/user) + return GLOB.notcontained_state + +/obj/machinery/seed_extractor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "SeedExtractor", name) + ui.open() + +/obj/machinery/seed_extractor/ui_data() + var/list/V = list() + for(var/key in piles) + if(piles[key]) + var/len = length(piles[key]) + if(len) + V[key] = len + + . = list() + .["seeds"] = V + +/obj/machinery/seed_extractor/ui_act(action, params) + if(..()) + return + + switch(action) + if("select") + var/item = params["item"] + if(piles[item] && length(piles[item]) > 0) + var/datum/weakref/WO = piles[item][1] + var/obj/item/seeds/O = WO.resolve() + if(O) + piles[item] -= WO + O.forceMove(drop_location()) + . = TRUE + //to_chat(usr, "[src] clanks to life briefly before vending [prize.equipment_name]!") - piles += new /datum/seed_pile(O.plantname, O.lifespan, O.endurance, O.maturation, O.production, O.yield, O.potency) diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 5e49a32a23..c7314bf180 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -190,6 +190,31 @@ obj/item/seeds/proc/is_gene_forbidden(typepath) parent.update_tray(user) return result +/obj/item/seeds/proc/harvest_userless() + var/obj/machinery/hydroponics/parent = loc //for ease of access + var/t_amount = 0 + var/list/result = list() + var/output_loc = parent.loc + var/product_name + while(t_amount < getYield()) + var/obj/item/reagent_containers/food/snacks/grown/t_prod = new product(output_loc, src) + if(parent.myseed.plantname != initial(parent.myseed.plantname)) + t_prod.name = lowertext(parent.myseed.plantname) + if(productdesc) + t_prod.desc = productdesc + t_prod.seed.name = parent.myseed.name + t_prod.seed.desc = parent.myseed.desc + t_prod.seed.plantname = parent.myseed.plantname + result.Add(t_prod) // User gets a consumable + if(!t_prod) + return + t_amount++ + product_name = parent.myseed.plantname + if(getYield() >= 1) + SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name) + parent.investigate_log("autmoatic harvest of [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY) + parent.update_tray() + return result /obj/item/seeds/proc/prepare_result(var/obj/item/reagent_containers/food/snacks/grown/T) if(!T.reagents) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 463398d2f2..a0d96658e6 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -2,6 +2,12 @@ #define MUSIC_MAXLINES 1000 #define MUSIC_MAXLINECHARS 300 +/** + * # Song datum + * + * These are the actual backend behind instruments. + * They attach to an atom and provide the editor + playback functionality. + */ /datum/song /// Name of the song var/name = "Untitled" @@ -15,6 +21,9 @@ /// delay between notes in deciseconds var/tempo = 5 + /// How far we can be heard + var/instrument_range = 15 + /// Are we currently playing? var/playing = FALSE @@ -53,17 +62,24 @@ /////////////////// Playing variables //////////////// /** - * Only used in synthesized playback - The chords we compiled. Non assoc list of lists: - * list(list(key1, key2, key3..., tempo_divisor), list(key1, key2..., tempo_divisor), ...) - * tempo_divisor always exists - * if key1 (and so if there's no keys) doesn't exist it's a rest + * Build by compile_chords() + * Must be rebuilt on instrument switch. * Compilation happens when we start playing and is cleared after we finish playing. + * Format: list of chord lists, with chordlists having (key1, key2, key3, tempodiv) */ var/list/compiled_chords + /// Current section of a long chord we're on, so we don't need to make a billion chords, one for every unit ticklag. + var/elapsed_delay + /// Amount of delay to wait before playing the next chord + var/delay_by + /// Current chord we're on. + var/current_chord /// Channel as text = current volume percentage but it's 0 to 100 instead of 0 to 1. var/list/channels_playing = list() /// List of channels that aren't being used, as text. This is to prevent unnecessary freeing and reallocations from SSsounds/SSinstruments. var/list/channels_idle = list() + /// Person playing us + var/mob/user_playing ////////////////////////////////////////////////////// /// Last world.time we checked for who can hear us @@ -72,8 +88,6 @@ var/list/hearing_mobs /// If this is enabled, some things won't be strictly cleared when they usually are (liked compiled_chords on play stop) var/debug_mode = FALSE - /// Last time we processed decay - var/last_process_decay /// Max sound channels to occupy var/max_sound_channels = CHANNELS_PER_INSTRUMENT /// Current channels, so we can save a length() call. @@ -113,7 +127,7 @@ var/cached_exponential_dropoff = 1.045 ///////////////////////////////////////////////////////////////////////// -/datum/song/New(atom/parent, list/instrument_ids) +/datum/song/New(atom/parent, list/instrument_ids, new_range) SSinstruments.on_song_new(src) lines = list() tempo = sanitize_tempo(tempo) @@ -125,6 +139,8 @@ hearing_mobs = list() volume = clamp(volume, min_volume, max_volume) update_sustain() + if(new_range) + instrument_range = new_range /datum/song/Destroy() stop_playing() @@ -135,12 +151,15 @@ parent = null return ..() +/** + * Checks and stores which mobs can hear us. Terminates sounds for mobs that leave our range. + */ /datum/song/proc/do_hearcheck() last_hearcheck = world.time var/list/old = hearing_mobs.Copy() hearing_mobs.len = 0 var/turf/source = get_turf(parent) - for(var/mob/M in get_hearers_in_view(15, source)) + for(var/mob/M in get_hearers_in_view(instrument_range, source)) if(!(M?.client?.prefs?.toggles & SOUND_INSTRUMENTS)) continue hearing_mobs[M] = get_dist(M, source) @@ -148,10 +167,15 @@ for(var/i in exited) terminate_sound_mob(i) -/// I can either be a datum, id, or path (if the instrument has no id). +/** + * Sets our instrument, caching anything necessary for faster accessing. Accepts an ID, typepath, or instantiated instrument datum. + */ /datum/song/proc/set_instrument(datum/instrument/I) + terminate_all_sounds() + var/old_legacy if(using_instrument) using_instrument.songs_using -= src + old_legacy = (using_instrument.instrument_flags & INSTRUMENT_LEGACY) using_instrument = null cached_samples = null cached_legacy_ext = null @@ -162,7 +186,7 @@ if(istype(I)) using_instrument = I I.songs_using += src - var/instrument_legacy = CHECK_BITFIELD(I.instrument_flags, INSTRUMENT_LEGACY) + var/instrument_legacy = (I.instrument_flags & INSTRUMENT_LEGACY) if(instrument_legacy) cached_legacy_ext = I.legacy_instrument_ext cached_legacy_dir = I.legacy_instrument_path @@ -170,23 +194,37 @@ else cached_samples = I.samples legacy = FALSE + if(isnull(old_legacy) || (old_legacy != instrument_legacy)) + if(playing) + compile_chords() -/// THIS IS A BLOCKING CALL. +/** + * Attempts to start playing our song. + */ /datum/song/proc/start_playing(mob/user) if(playing) return if(!using_instrument?.ready()) to_chat(user, "An error has occured with [src]. Please reset the instrument.") return + compile_chords() + if(!length(compiled_chords)) + to_chat(user, "Song is empty.") + return playing = TRUE - updateDialog() + updateDialog(user_playing) //we can not afford to runtime, since we are going to be doing sound channel reservations and if we runtime it means we have a channel allocation leak. //wrap the rest of the stuff to ensure stop_playing() is called. - last_process_decay = world.time + do_hearcheck() + elapsed_delay = 0 + delay_by = 0 + current_chord = 1 + user_playing = user START_PROCESSING(SSinstruments, src) - . = do_play_lines(user) - stop_playing() +/** + * Stops playing, terminating all sounds if in synthesized mode. Clears hearing_mobs. + */ /datum/song/proc/stop_playing() if(!playing) return @@ -196,42 +234,93 @@ STOP_PROCESSING(SSinstruments, src) terminate_all_sounds(TRUE) hearing_mobs.len = 0 - updateDialog() + user_playing = null -/// THIS IS A BLOCKING CALL. -/datum/song/proc/do_play_lines(user) - if(!playing) +/** + * Processes our song. + */ +/datum/song/proc/process_song(wait) + if(!length(compiled_chords) || should_stop_playing(user_playing)) + stop_playing() return - do_hearcheck() - if(legacy) - do_play_lines_legacy(user) - else - do_play_lines_synthesized(user) + var/list/chord = compiled_chords[current_chord] + if(++elapsed_delay >= delay_by) + play_chord(chord) + elapsed_delay = 0 + delay_by = tempodiv_to_delay(chord[length(chord)]) + current_chord++ + if(current_chord > length(compiled_chords)) + if(repeat) + repeat-- + current_chord = 1 + return + else + stop_playing() + return +/** + * Converts a tempodiv to ticks to elapse before playing the next chord, taking into account our tempo. + */ +/datum/song/proc/tempodiv_to_delay(tempodiv) + if(!tempodiv) + tempodiv = 1 // no division by 0. some song converters tend to use 0 for when it wants to have no div, for whatever reason. + return max(1, round((tempo/tempodiv) / world.tick_lag, 1)) + +/** + * Compiles chords. + */ +/datum/song/proc/compile_chords() + legacy? compile_legacy() : compile_synthesized() + +/** + * Plays a chord. + */ +/datum/song/proc/play_chord(list/chord) + // last value is timing information + for(var/i in 1 to (length(chord) - 1)) + legacy? playkey_legacy(chord[i][1], chord[i][2], chord[i][3], user_playing) : playkey_synth(chord[i], user_playing) + +/** + * Checks if we should halt playback. + */ /datum/song/proc/should_stop_playing(mob/user) return QDELETED(parent) || !using_instrument || !playing +/** + * Sanitizes tempo to a value that makes sense and fits the current world.tick_lag. + */ /datum/song/proc/sanitize_tempo(new_tempo) new_tempo = abs(new_tempo) return clamp(round(new_tempo, world.tick_lag), world.tick_lag, 5 SECONDS) +/** + * Gets our beats per minute based on our tempo. + */ /datum/song/proc/get_bpm() return 600 / tempo +/** + * Sets our tempo from a beats-per-minute, sanitizing it to a valid number first. + */ /datum/song/proc/set_bpm(bpm) tempo = sanitize_tempo(600 / bpm) -/// Updates the window for our user. Override in subtypes. -/datum/song/proc/updateDialog(mob/user = usr) +/** + * Updates the window for our users. Override down the line. + */ +/datum/song/proc/updateDialog(mob/user) ui_interact(user) /datum/song/process(wait) if(!playing) return PROCESS_KILL - var/delay = world.time - last_process_decay - process_decay(delay) - last_process_decay = world.time + // it's expected this ticks at every world.tick_lag. if it lags, do not attempt to catch up. + process_song(world.tick_lag) + process_decay(world.tick_lag) +/** + * Updates our cached linear/exponential falloff stuff, saving calculations down the line. + */ /datum/song/proc/update_sustain() // Exponential is easy cached_exponential_dropoff = sustain_exponential_dropoff @@ -241,21 +330,33 @@ var/volume_decrease_per_decisecond = volume_diff / target_duration cached_linear_dropoff = volume_decrease_per_decisecond +/** + * Setter for setting output volume. + */ /datum/song/proc/set_volume(volume) src.volume = clamp(volume, max(0, min_volume), min(100, max_volume)) update_sustain() updateDialog() +/** + * Setter for setting how low the volume has to get before a note is considered "dead" and dropped + */ /datum/song/proc/set_dropoff_volume(volume) sustain_dropoff_volume = clamp(volume, INSTRUMENT_MIN_SUSTAIN_DROPOFF, 100) update_sustain() updateDialog() +/** + * Setter for setting exponential falloff factor. + */ /datum/song/proc/set_exponential_drop_rate(drop) sustain_exponential_dropoff = clamp(drop, INSTRUMENT_EXP_FALLOFF_MIN, INSTRUMENT_EXP_FALLOFF_MAX) update_sustain() updateDialog() +/** + * Setter for setting linear falloff duration. + */ /datum/song/proc/set_linear_falloff_duration(duration) sustain_linear_duration = clamp(duration, 0.1, INSTRUMENT_MAX_TOTAL_SUSTAIN) update_sustain() @@ -277,10 +378,8 @@ // subtype for handheld instruments, like violin /datum/song/handheld -/datum/song/handheld/updateDialog(mob/user = usr) - if(user.machine != src) - return - parent.ui_interact(user) +/datum/song/handheld/updateDialog(mob/user) + parent.ui_interact(user || usr) /datum/song/handheld/should_stop_playing(mob/user) . = ..() @@ -292,10 +391,8 @@ // subtype for stationary structures, like pianos /datum/song/stationary -/datum/song/stationary/updateDialog(mob/user = usr) - if(user.machine != src) - return - parent.ui_interact(user) +/datum/song/stationary/updateDialog(mob/user) + parent.ui_interact(user || usr) /datum/song/stationary/should_stop_playing(mob/user) . = ..() @@ -303,3 +400,19 @@ return TRUE var/obj/structure/musician/M = parent return M.should_stop_playing(user) + +/datum/song/holoparasite + var/mob/living/simple_animal/hostile/guardian/stand + +/datum/song/holoparasite/New(atom/parent, list/instrument_ids) + . = ..() + stand = istype(parent, /mob/living/simple_animal/hostile/guardian) && parent + +/datum/song/holoparasite/updateDialog() + stand.ui_interact(src) + +/datum/song/holoparasite/should_stop_playing(mob/user) + return FALSE + +/datum/song/holoparasite/check_can_use(mob/user) + return (user == stand) diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm index d9595797d7..8c5171667a 100644 --- a/code/modules/instruments/songs/editor.dm +++ b/code/modules/instruments/songs/editor.dm @@ -109,8 +109,11 @@ linenum++ updateDialog(usr) // make sure updates when complete +/datum/song/proc/check_can_use(mob/user) + return user.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE) + /datum/song/Topic(href, href_list) - if(!usr.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE)) + if(!check_can_use(usr)) usr << browse(null, "window=instrument") usr.unset_machine() return diff --git a/code/modules/instruments/songs/play_legacy.dm b/code/modules/instruments/songs/play_legacy.dm index fa64656ebc..eee9be3cc7 100644 --- a/code/modules/instruments/songs/play_legacy.dm +++ b/code/modules/instruments/songs/play_legacy.dm @@ -1,48 +1,52 @@ -/// Playing legacy instruments - None of the "advanced" like sound reservations and decay are invoked. -/datum/song/proc/do_play_lines_legacy(mob/user) - while(repeat >= 0) - var/cur_oct[7] - var/cur_acc[7] - for(var/i = 1 to 7) - cur_oct[i] = 3 - cur_acc[i] = "n" +/** + * Compiles our lines into "chords" with filenames for legacy playback. This makes there have to be a bit of lag at the beginning of the song, but repeats will not have to parse it again, and overall playback won't be impacted by as much lag. + */ +/datum/song/proc/compile_legacy() + if(!length(src.lines)) + return + var/list/lines = src.lines //cache for hyepr speed! + compiled_chords = list() + var/list/octaves = list(3, 3, 3, 3, 3, 3, 3) + var/list/accents = list("n", "n", "n", "n", "n", "n", "n") + for(var/line in lines) + var/list/chords = splittext(lowertext(line), ",") + for(var/chord in chords) + var/list/compiled_chord = list() + var/tempodiv = 1 + var/list/notes_tempodiv = splittext(chord, "/") + var/len = length(notes_tempodiv) + if(len >= 2) + tempodiv = text2num(notes_tempodiv[2]) + if(len) //some dunkass is going to do ,,,, to make 3 rests instead of ,/1 because there's no standardization so let's be prepared for that. + var/list/notes = splittext(notes_tempodiv[1], "-") + for(var/note in notes) + if(length(note) == 0) + continue + // 1-7, A-G + var/key = text2ascii(note) - 96 + if((key < 1) || (key > 7)) + continue + for(var/i in 2 to length(note)) + var/oct_acc = copytext(note, i, i + 1) + var/num = text2num(oct_acc) + if(!num) //it's an accidental + accents[key] = oct_acc //if they misspelled it/fucked up that's on them lmao, no safety checks. + else //octave + octaves[key] = clamp(num, octave_min, octave_max) + compiled_chord[++compiled_chord.len] = list(key, accents[key], octaves[key]) + compiled_chord += tempodiv //this goes last + if(length(compiled_chord)) + compiled_chords[++compiled_chords.len] = compiled_chord - for(var/line in lines) - for(var/beat in splittext(lowertext(line), ",")) - if(should_stop_playing(user)) - return - var/list/notes = splittext(beat, "/") - if(length(notes)) //because some jack-butts are going to do ,,,, to symbolize 3 rests instead of something reasonable like ,/1. - for(var/note in splittext(notes[1], "-")) - if(length(note) == 0) - continue - var/cur_note = text2ascii(note) - 96 - if(cur_note < 1 || cur_note > 7) - continue - for(var/i=2 to length(note)) - var/ni = copytext(note,i,i+1) - if(!text2num(ni)) - if(ni == "#" || ni == "b" || ni == "n") - cur_acc[cur_note] = ni - else if(ni == "s") - cur_acc[cur_note] = "#" // so shift is never required - else - cur_oct[cur_note] = text2num(ni) - playnote_legacy(cur_note, cur_acc[cur_note], cur_oct[cur_note]) - if(notes.len >= 2 && text2num(notes[2])) - sleep(sanitize_tempo(tempo / text2num(notes[2]))) - else - sleep(tempo) - if(should_stop_playing(user)) - return - repeat-- - updateDialog() - repeat = 0 - -// note is a number from 1-7 for A-G -// acc is either "b", "n", or "#" -// oct is 1-8 (or 9 for C) -/datum/song/proc/playnote_legacy(note, acc as text, oct) +/** + * Proc to play a legacy note. Just plays the sound to hearing mobs (and does hearcheck if necessary), no fancy channel/sustain/management. + * + * Arguments: + * * note is a number from 1-7 for A-G + * * acc is either "b", "n", or "#" + * * oct is 1-8 (or 9 for C) + */ +/datum/song/proc/playkey_legacy(note, acc as text, oct, mob/user) // handle accidental -> B<>C of E<>F if(acc == "b" && (note == 3 || note == 6)) // C or F if(note == 3) diff --git a/code/modules/instruments/songs/play_synthesized.dm b/code/modules/instruments/songs/play_synthesized.dm index 5e7c5652a0..4df54f5e6b 100644 --- a/code/modules/instruments/songs/play_synthesized.dm +++ b/code/modules/instruments/songs/play_synthesized.dm @@ -1,27 +1,7 @@ -/datum/song/proc/do_play_lines_synthesized(mob/user) - compile_lines() - while(repeat >= 0) - if(should_stop_playing(user)) - return - var/warned = FALSE - for(var/_chord in compiled_chords) - if(should_stop_playing(user)) - return - var/list/chord = _chord - var/tempodiv = chord[chord.len] - for(var/i in 1 to chord.len - 1) - var/key = chord[i] - if(!playkey_synth(key)) - if(!warned) - warned = TRUE - to_chat(user, "Your instrument has ran out of channels. You might be playing your song too fast or be setting sustain to too high of a value. This warning will be suppressed for the rest of this cycle.") - sleep(sanitize_tempo(tempo / (tempodiv || 1))) - repeat-- - updateDialog() - repeat = 0 - -/// C-Db2-A-A4/2,A-B#4-C/3,/4,A,A-B-C as an example -/datum/song/proc/compile_lines() +/** + * Compiles our lines into "chords" with numbers. This makes there have to be a bit of lag at the beginning of the song, but repeats will not have to parse it again, and overall playback won't be impacted by as much lag. + */ +/datum/song/proc/compile_synthesized() if(!length(src.lines)) return var/list/lines = src.lines //cache for hyepr speed! @@ -57,10 +37,12 @@ compiled_chord += tempodiv //this goes last if(length(compiled_chord)) compiled_chords[++compiled_chords.len] = compiled_chord - CHECK_TICK - return compiled_chords -/datum/song/proc/playkey_synth(key) +/** + * Plays a specific numerical key from our instrument to anyone who can hear us. + * Does a hearing check if enough time has passed. + */ +/datum/song/proc/playkey_synth(key, mob/user) if(can_noteshift) key = clamp(key + note_shift, key_min, key_max) if((world.time - MUSICIAN_HEARCHECK_MINDELAY) > last_hearcheck) @@ -83,6 +65,9 @@ M.playsound_local(get_turf(parent), null, volume, FALSE, K.frequency, INSTRUMENT_DISTANCE_NO_FALLOFF, channel, null, copy, distance_multiplier = INSTRUMENT_DISTANCE_FALLOFF_BUFF) // Could do environment and echo later but not for now +/** + * Stops all sounds we are "responsible" for. Only works in synthesized mode. + */ /datum/song/proc/terminate_all_sounds(clear_channels = TRUE) for(var/i in hearing_mobs) terminate_sound_mob(i) @@ -93,10 +78,16 @@ using_sound_channels = 0 SSsounds.free_datum_channels(src) +/** + * Stops all sounds we are responsible for in a given person. Only works in synthesized mode. + */ /datum/song/proc/terminate_sound_mob(mob/M) for(var/channel in channels_playing) M.stop_sound_channel(text2num(channel)) +/** + * Pops a channel we have reserved so we don't have to release and re-request them from SSsounds every time we play a note. This is faster. + */ /datum/song/proc/pop_channel() if(length(channels_idle)) //just pop one off of here if we have one available . = text2num(channels_idle[1]) @@ -108,6 +99,12 @@ if(!isnull(.)) using_sound_channels++ +/** + * Decays our channels and updates their volumes to mobs who can hear us. + * + * Arguments: + * * wait_ds - the deciseconds we should decay by. This is to compensate for any lag, as otherwise songs would get pretty nasty during high time dilation. + */ /datum/song/proc/process_decay(wait_ds) var/linear_dropoff = cached_linear_dropoff * wait_ds var/exponential_dropoff = cached_exponential_dropoff ** wait_ds diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index 384991e976..903ff13fa8 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -519,6 +519,7 @@ /obj/item/electronic_assembly/attack_self(mob/user) + set waitfor = FALSE if(!check_interactivity(user)) return if(opened) @@ -611,7 +612,7 @@ return ..() -/obj/item/electronic_assembly/attack_hand(mob/user) +/obj/item/electronic_assembly/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(anchored) attack_self(user) return @@ -650,11 +651,6 @@ icon_state = "setup_small_pda" desc = "It's a case, for building small electronics with. This one resembles a PDA." -/obj/item/electronic_assembly/dildo - name = "type-g electronic assembly" - icon_state = "setup_dildo_medium" - desc = "It's a case, for building small electronics with. This one has a phallic design." - /obj/item/electronic_assembly/small name = "electronic device" icon_state = "setup_device" @@ -686,11 +682,6 @@ icon_state = "setup_device_box" desc = "It's a case, for building tiny-sized electronics with. This one has a boxy design." -/obj/item/electronic_assembly/small/dildo - name = "type-f electronic device" - icon_state = "setup_dildo_small" - desc = "It's a case, for building tiny-sized electronics with. This one has a phallic design." - /obj/item/electronic_assembly/medium name = "electronic mechanism" icon_state = "setup_medium" @@ -731,12 +722,6 @@ icon_state = "setup_medium_radio" desc = "It's a case, for building medium-sized electronics with. This one resembles an old radio." -/obj/item/electronic_assembly/medium/dildo - name = "type-g electronic mechanism" - icon_state = "setup_dildo_large" - desc = "It's a case, for building medium-sized electronics with. This one has a phallic design." - - /obj/item/electronic_assembly/large name = "electronic machine" icon_state = "setup_large" diff --git a/code/modules/integrated_electronics/subtypes/atmospherics.dm b/code/modules/integrated_electronics/subtypes/atmospherics.dm index 219e30c57f..d9a18bc509 100644 --- a/code/modules/integrated_electronics/subtypes/atmospherics.dm +++ b/code/modules/integrated_electronics/subtypes/atmospherics.dm @@ -125,12 +125,12 @@ return // Negative Kelvin temperatures should never happen and if they do, normalize them - if(source_air.temperature < TCMB) - source_air.temperature = TCMB + if(source_air.return_temperature() < TCMB) + source_air.set_temperature(TCMB) var/pressure_delta = target_pressure - target_air.return_pressure() if(pressure_delta > 0.1) - var/transfer_moles = (pressure_delta*target_air.volume/(source_air.temperature * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY + var/transfer_moles = (pressure_delta*target_air.return_volume()/(source_air.return_temperature() * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY var/datum/gas_mixture/removed = source_air.remove(transfer_moles) target_air.merge(removed) @@ -171,14 +171,14 @@ return // Negative Kelvin temperatures should never happen and if they do, normalize them - if(source_air.temperature < TCMB) - source_air.temperature = TCMB + if(source_air.return_temperature() < TCMB) + source_air.set_temperature(TCMB) if((source_air.return_pressure() < 0.01) || (target_air.return_pressure() >= PUMP_MAX_PRESSURE)) return //The second part of the min caps the pressure built by the volume pumps to the max pump pressure - var/transfer_ratio = min(transfer_rate,target_air.volume*PUMP_MAX_PRESSURE/source_air.return_pressure())/source_air.volume + var/transfer_ratio = min(transfer_rate,target_air.return_volume()*PUMP_MAX_PRESSURE/source_air.return_pressure())/source_air.return_volume() var/datum/gas_mixture/removed = source_air.remove_ratio(transfer_ratio * PUMP_EFFICIENCY) @@ -351,10 +351,10 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() var/transfer_moles //Negative Kelvins are an anomaly and should be normalized if encountered - if(source_air.temperature < TCMB) - source_air.temperature = TCMB + if(source_air.return_temperature(TCMB)) + source_air.set_temperature(TCMB) - transfer_moles = (pressure_delta*contaminated_air.volume/(source_air.temperature * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY + transfer_moles = (pressure_delta*contaminated_air.return_volume()/(source_air.return_temperature() * R_IDEAL_GAS_EQUATION))*PUMP_EFFICIENCY //If there is nothing to transfer, just return if(transfer_moles <= 0) @@ -368,16 +368,15 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() //This is the gas that will be moved from source to filtered var/datum/gas_mixture/filtered_out = new - for(var/filtered_gas in removed.gases) + for(var/filtered_gas in removed.get_gases()) //Get the name of the gas and see if it is in the list if(GLOB.meta_gas_names[filtered_gas] in wanted) //The gas that is put in all the filtered out gases - filtered_out.temperature = removed.temperature - filtered_out.gases[filtered_gas] = removed.gases[filtered_gas] + filtered_out.set_temperature(removed.return_temperature()) + filtered_out.set_moles(filtered_gas, removed.get_moles(filtered_gas)) //The filtered out gas is entirely removed from the currently filtered gases - removed.gases[filtered_gas] = 0 - GAS_GARBAGE_COLLECT(removed.gases) + removed.set_moles(filtered_gas, 0) //Check if the pressure is high enough to put stuff in filtered, or else just put it back in the source var/datum/gas_mixture/target = (filtered_air.return_pressure() < target_pressure ? filtered_air : source_air) @@ -444,7 +443,7 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() var/gas_percentage = round(max(min(get_pin_data(IC_INPUT, 4),100),0) / 100) //Basically: number of moles = percentage of pressure filled up * efficiency coefficient * (pressure from both gases * volume of output) / (R * Temperature) - var/transfer_moles = (get_pin_data(IC_INPUT, 5) / max(1,output_gases.return_pressure())) * PUMP_EFFICIENCY * (source_1_gases.return_pressure() * gas_percentage + source_2_gases.return_pressure() * (1 - gas_percentage)) * output_gases.volume/ (R_IDEAL_GAS_EQUATION * max(output_gases.temperature,TCMB)) + var/transfer_moles = (get_pin_data(IC_INPUT, 5) / max(1,output_gases.return_pressure())) * PUMP_EFFICIENCY * (source_1_gases.return_pressure() * gas_percentage + source_2_gases.return_pressure() * (1 - gas_percentage)) * output_gases.return_volume()/ (R_IDEAL_GAS_EQUATION * max(output_gases.return_temperature(),TCMB)) if(transfer_moles <= 0) @@ -544,10 +543,10 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() push_data() //Cool the tank if the power is on and the temp is above - if(!power_draw_idle || air_contents.temperature < temperature) + if(!power_draw_idle || air_contents.return_temperature() < temperature) return - air_contents.temperature = max(73.15,air_contents.temperature - (air_contents.temperature - temperature) * heater_coefficient) + air_contents.set_temperature(max(73.15,air_contents.return_temperature() - (air_contents.return_temperature() - temperature) * heater_coefficient)) // - heater tank - // **works** @@ -574,10 +573,10 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() push_data() //Heat the tank if the power is on or its temperature is below what is set - if(!power_draw_idle || air_contents.temperature > temperature) + if(!power_draw_idle || air_contents.return_temperature() > temperature) return - air_contents.temperature = min(573.15,air_contents.temperature + (temperature - air_contents.temperature) * heater_coefficient) + air_contents.set_temperature(min(573.15,air_contents.return_temperature() + (temperature - air_contents.return_temperature()) * heater_coefficient)) // - atmospheric cooler - // **works** @@ -621,11 +620,11 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() return var/datum/gas_mixture/turf_air = current_turf.return_air() - if(!power_draw_idle || turf_air.temperature < temperature) + if(!power_draw_idle || turf_air.return_temperature() < temperature) return //Cool the gas - turf_air.temperature = max(243.15,turf_air.temperature - (turf_air.temperature - temperature) * heater_coefficient) + turf_air.set_temperature(max(243.15,turf_air.return_temperature() - (turf_air.return_temperature() - temperature) * heater_coefficient)) // - atmospheric heater - // **works** @@ -650,11 +649,11 @@ obj/item/integrated_circuit/atmospherics/connector/portableConnectorReturnAir() return var/datum/gas_mixture/turf_air = current_turf.return_air() - if(!power_draw_idle || turf_air.temperature > temperature) + if(!power_draw_idle || turf_air.return_temperature() > temperature) return //Heat the gas - turf_air.temperature = min(323.15,turf_air.temperature + (temperature - turf_air.temperature) * heater_coefficient) + turf_air.set_temperature(min(323.15,turf_air.return_temperature() + (temperature - turf_air.return_temperature()) * heater_coefficient)) // - tank slot - // **works** diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index a0608bb5ed..e8981ed685 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -1162,12 +1162,11 @@ activate_pin(3) return - var/list/gases = air_contents.gases var/list/gas_names = list() var/list/gas_amounts = list() - for(var/id in gases) + for(var/id in air_contents.get_gases()) var/name = GLOB.meta_gas_names[id] - var/amt = round(gases[id], 0.001) + var/amt = round(air_contents.get_moles(id), 0.001) gas_names.Add(name) gas_amounts.Add(amt) @@ -1175,7 +1174,7 @@ set_pin_data(IC_OUTPUT, 2, gas_amounts) set_pin_data(IC_OUTPUT, 3, round(air_contents.total_moles(), 0.001)) set_pin_data(IC_OUTPUT, 4, round(air_contents.return_pressure(), 0.001)) - set_pin_data(IC_OUTPUT, 5, round(air_contents.temperature, 0.001)) + set_pin_data(IC_OUTPUT, 5, round(air_contents.return_temperature(), 0.001)) set_pin_data(IC_OUTPUT, 6, round(air_contents.return_volume(), 0.001)) push_data() activate_pin(2) diff --git a/code/modules/integrated_electronics/subtypes/manipulation.dm b/code/modules/integrated_electronics/subtypes/manipulation.dm index fd4e6abfc5..eac16d2950 100644 --- a/code/modules/integrated_electronics/subtypes/manipulation.dm +++ b/code/modules/integrated_electronics/subtypes/manipulation.dm @@ -78,7 +78,7 @@ for(var/i in 1 to length(harvest_output)) harvest_output[i] = WEAKREF(harvest_output[i]) - if(harvest_output.len) + if(length(harvest_output)) set_pin_data(IC_OUTPUT, 1, harvest_output) push_data() if(1) @@ -162,7 +162,7 @@ /obj/item/integrated_circuit/manipulation/grabber/do_work() var/obj/item/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/item) - if(!QDELETED(AM) && !istype(AM, /obj/item/electronic_assembly) && !istype(AM, /obj/item/transfer_valve) && !istype(AM, /obj/item/twohanded) && !istype(assembly.loc, /obj/item/implant/storage)) + if(!QDELETED(AM) && !istype(AM, /obj/item/electronic_assembly) && !istype(AM, /obj/item/transfer_valve) && !istype(assembly.loc, /obj/item/implant/storage) && !AM.GetComponent(/datum/component/two_handed)) var/mode = get_pin_data(IC_INPUT, 2) switch(mode) if(1) @@ -300,7 +300,7 @@ var/target_y_rel = round(get_pin_data(IC_INPUT, 2)) var/obj/item/A = get_pin_data_as_type(IC_INPUT, 3, /obj/item) - if(!A || A.anchored || A.throwing || A == assembly || istype(A, /obj/item/twohanded) || istype(A, /obj/item/transfer_valve)) + if(!A || A.anchored || A.throwing || A == assembly || istype(A, /obj/item/transfer_valve) || A.GetComponent(/datum/component/two_handed)) return if (istype(assembly.loc, /obj/item/implant/storage)) //Prevents the more abusive form of chestgun. diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index 47b6e151cb..efd98c4d50 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -35,7 +35,7 @@ stuff_to_display = replacetext("[I.data]", eol , "
    ") /obj/item/integrated_circuit/output/screen/large - name = "large screen" + name = "medium screen" desc = "Takes any data type as an input and displays it to anybody near the device when pulsed. \ It can also be examined to see the last thing it displayed." icon_state = "screen_medium" @@ -51,15 +51,29 @@ else if(!isturf(assembly.loc)) return + + var/atom/host = assembly || src + var/list/mobs = list() + for(var/mob/M in range(0, get_turf(src))) + mobs += M + to_chat(mobs, "[icon2html(host.icon, world, host.icon_state)] flashes a message: [stuff_to_display]") + host.investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT) - var/list/nearby_things = range(0, get_turf(src)) - for(var/mob/M in nearby_things) - var/obj/O = assembly ? assembly : src - to_chat(M, "[icon2html(O.icon, world, O.icon_state)] [stuff_to_display]") - if(assembly) - assembly.investigate_log("displayed \"[html_encode(stuff_to_display)]\" with [type].", INVESTIGATE_CIRCUIT) - else - investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT) +/obj/item/integrated_circuit/output/screen/extralarge // the subtype is called "extralarge" because tg brought back medium screens and they named the subtype /screen/large + name = "large screen" + desc = "Takes any data type as an input and displays it to the user upon examining, and to all nearby beings when pulsed." + icon_state = "screen_large" + power_draw_per_use = 40 + cooldown_per_use = 10 + +/obj/item/integrated_circuit/output/screen/extralarge/do_work() + ..() + var/atom/host = assembly || src + var/list/mobs = list() + for(var/mob/M in viewers(7, get_turf(src))) + mobs += M + to_chat(mobs, "[icon2html(host.icon, world, host.icon_state)] flashes a message: [stuff_to_display]") + host.investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT) /obj/item/integrated_circuit/output/light name = "light" @@ -389,25 +403,4 @@ //Hippie Ported Code-------------------------------------------------------------------------------------------------------- - - /obj/item/radio/headset/integrated - -/obj/item/integrated_circuit/output/screen/large - name = "medium screen" - -/obj/item/integrated_circuit/output/screen/extralarge // the subtype is called "extralarge" because tg brought back medium screens and they named the subtype /screen/large - name = "large screen" - desc = "Takes any data type as an input and displays it to the user upon examining, and to all nearby beings when pulsed." - icon_state = "screen_large" - power_draw_per_use = 40 - cooldown_per_use = 10 - -/obj/item/integrated_circuit/output/screen/extralarge/do_work() - ..() - var/obj/O = assembly ? get_turf(assembly) : loc - O.visible_message("[icon2html(O.icon, world, O.icon_state)] [stuff_to_display]") - if(assembly) - assembly.investigate_log("displayed \"[html_encode(stuff_to_display)]\" with [type].", INVESTIGATE_CIRCUIT) - else - investigate_log("displayed \"[html_encode(stuff_to_display)]\" as [type].", INVESTIGATE_CIRCUIT) diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm index 663ba9fe16..991c806f43 100644 --- a/code/modules/integrated_electronics/subtypes/reagents.dm +++ b/code/modules/integrated_electronics/subtypes/reagents.dm @@ -514,6 +514,8 @@ outputs = list("volume used" = IC_PINTYPE_NUMBER,"self reference" = IC_PINTYPE_SELFREF,"temperature" = IC_PINTYPE_NUMBER) spawn_flags = IC_SPAWN_RESEARCH var/heater_coefficient = 0.1 + var/max_temp = 1000 + var/min_temp = 2.7 /obj/item/integrated_circuit/reagent/storage/heater/on_data_written() if(get_pin_data(IC_INPUT, 2)) @@ -531,7 +533,7 @@ /obj/item/integrated_circuit/reagent/storage/heater/process() if(power_draw_idle) - var/target_temperature = get_pin_data(IC_INPUT, 1) + var/target_temperature = clamp(get_pin_data(IC_INPUT, 1), min_temp, max_temp) if(reagents.chem_temp > target_temperature) reagents.chem_temp += min(-1, (target_temperature - reagents.chem_temp) * heater_coefficient) if(reagents.chem_temp < target_temperature) @@ -795,4 +797,4 @@ ..() if(istype(loc,/obj/item/integrated_circuit/input/beaker_connector)) var/obj/item/integrated_circuit/input/beaker_connector/current_circuit = loc - current_circuit.push_vol() \ No newline at end of file + current_circuit.push_vol() diff --git a/code/modules/integrated_electronics/subtypes/weaponized.dm b/code/modules/integrated_electronics/subtypes/weaponized.dm index 3123eeabbe..96a732d08f 100644 --- a/code/modules/integrated_electronics/subtypes/weaponized.dm +++ b/code/modules/integrated_electronics/subtypes/weaponized.dm @@ -45,6 +45,9 @@ /obj/item/integrated_circuit/weaponized/weapon_firing/attackby(var/obj/O, var/mob/user) if(istype(O, /obj/item/gun/energy)) var/obj/item/gun/gun = O + if(!gun.can_circuit) + to_chat(user, "[gun] does not fit into circuits.") + return if(installed_gun) to_chat(user, "There's already a weapon installed.") return @@ -81,7 +84,7 @@ to_chat(user, "There's no weapon to remove from the mechanism.") /obj/item/integrated_circuit/weaponized/weapon_firing/do_work() - if(!assembly || !installed_gun) + if(!assembly || !installed_gun || !installed_gun.can_shoot()) return if(isliving(assembly.loc)) var/mob/living/L = assembly.loc @@ -246,7 +249,7 @@ var/obj/item/A = get_pin_data_as_type(IC_INPUT, 3, /obj/item) var/obj/item/integrated_circuit/atmospherics/AT = get_pin_data_as_type(IC_INPUT, 4, /obj/item/integrated_circuit/atmospherics) - if(!A || A.anchored || A.throwing || A == assembly || istype(A, /obj/item/twohanded) || istype(A, /obj/item/transfer_valve)) + if(!A || A.anchored || A.throwing || A == assembly || istype(A, /obj/item/transfer_valve) || A.GetComponent(/datum/component/two_handed)) return var/obj/item/I = get_object() diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index c700d668c5..1238b37919 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -46,6 +46,7 @@ var/minimal_player_age = 0 var/outfit = null + var/plasma_outfit = null //the outfit given to plasmamen var/exp_requirements = 0 @@ -203,21 +204,24 @@ var/pda_slot = SLOT_BELT /datum/outfit/job/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) - switch(preference_source?.prefs.backbag) - if(GBACKPACK) - back = /obj/item/storage/backpack //Grey backpack - if(GSATCHEL) - back = /obj/item/storage/backpack/satchel //Grey satchel - if(GDUFFELBAG) - back = /obj/item/storage/backpack/duffelbag //Grey Duffel bag - if(LSATCHEL) - back = /obj/item/storage/backpack/satchel/leather //Leather Satchel - if(DSATCHEL) - back = satchel //Department satchel - if(DDUFFELBAG) - back = duffelbag //Department duffel bag - else - back = backpack //Department backpack + var/preference_backpack = preference_source?.prefs.backbag + + if(preference_backpack) + switch(preference_backpack) + if(DBACKPACK) + back = backpack //Department backpack + if(DSATCHEL) + back = satchel //Department satchel + if(DDUFFELBAG) + back = duffelbag //Department duffel bag + else + var/find_preference_backpack = GLOB.backbaglist[preference_backpack] //attempt to find non-department backpack + if(find_preference_backpack) + back = find_preference_backpack + else //tried loading in a backpack that we don't allow as a loadout one + back = backpack + else //somehow doesn't have a preference set, should never reach this point but just-in-case + back = backpack //converts the uniform string into the path we'll wear, whether it's the skirt or regular variant var/holder diff --git a/code/modules/jobs/job_types/atmospheric_technician.dm b/code/modules/jobs/job_types/atmospheric_technician.dm index 1962b8e8a9..bff56d1d16 100644 --- a/code/modules/jobs/job_types/atmospheric_technician.dm +++ b/code/modules/jobs/job_types/atmospheric_technician.dm @@ -12,6 +12,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/atmos + plasma_outfit = /datum/outfit/plasmaman/atmospherics access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/bartender.dm b/code/modules/jobs/job_types/bartender.dm index e5cd015460..8290adbbd7 100644 --- a/code/modules/jobs/job_types/bartender.dm +++ b/code/modules/jobs/job_types/bartender.dm @@ -11,6 +11,7 @@ exp_type_department = EXP_TYPE_SERVICE // This is so the jobs menu can work properly outfit = /datum/outfit/job/bartender + plasma_outfit = /datum/outfit/plasmaman/bar access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_BAR, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/botanist.dm b/code/modules/jobs/job_types/botanist.dm index 65f3e7ca48..4c91f87791 100644 --- a/code/modules/jobs/job_types/botanist.dm +++ b/code/modules/jobs/job_types/botanist.dm @@ -10,6 +10,7 @@ selection_color = "#bbe291" outfit = /datum/outfit/job/botanist + plasma_outfit = /datum/outfit/plasmaman/botany access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_HYDROPONICS, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm index 3733658c33..047a07062d 100644 --- a/code/modules/jobs/job_types/captain.dm +++ b/code/modules/jobs/job_types/captain.dm @@ -17,6 +17,7 @@ outfit = /datum/outfit/job/captain + plasma_outfit = /datum/outfit/plasmaman/captain access = list() //See get_access() minimal_access = list() //See get_access() diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index 840af56a0e..1f87a5265d 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -10,6 +10,7 @@ selection_color = "#ca8f55" outfit = /datum/outfit/job/cargo_tech + plasma_outfit = /datum/outfit/plasmaman/cargo access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/chaplain.dm b/code/modules/jobs/job_types/chaplain.dm index 5f66519365..a9e891a303 100644 --- a/code/modules/jobs/job_types/chaplain.dm +++ b/code/modules/jobs/job_types/chaplain.dm @@ -10,6 +10,7 @@ selection_color = "#dddddd" outfit = /datum/outfit/job/chaplain + plasma_outfit = /datum/outfit/plasmaman/chaplain access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_THEATRE) minimal_access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_THEATRE) diff --git a/code/modules/jobs/job_types/chemist.dm b/code/modules/jobs/job_types/chemist.dm index b2699071e3..6d4204d041 100644 --- a/code/modules/jobs/job_types/chemist.dm +++ b/code/modules/jobs/job_types/chemist.dm @@ -12,6 +12,7 @@ exp_requirements = 60 outfit = /datum/outfit/job/chemist + plasma_outfit = /datum/outfit/plasmaman/chemist 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) diff --git a/code/modules/jobs/job_types/chief_engineer.dm b/code/modules/jobs/job_types/chief_engineer.dm index d8df767a9f..18be8c9835 100644 --- a/code/modules/jobs/job_types/chief_engineer.dm +++ b/code/modules/jobs/job_types/chief_engineer.dm @@ -17,6 +17,7 @@ exp_type_department = EXP_TYPE_ENGINEERING outfit = /datum/outfit/job/ce + plasma_outfit = /datum/outfit/plasmaman/ce access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ATMOSPHERICS, ACCESS_EVA, diff --git a/code/modules/jobs/job_types/chief_medical_officer.dm b/code/modules/jobs/job_types/chief_medical_officer.dm index adee2856fa..627a7a2ca1 100644 --- a/code/modules/jobs/job_types/chief_medical_officer.dm +++ b/code/modules/jobs/job_types/chief_medical_officer.dm @@ -17,6 +17,7 @@ exp_type_department = EXP_TYPE_MEDICAL outfit = /datum/outfit/job/cmo + plasma_outfit = /datum/outfit/plasmaman/cmo 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, @@ -45,7 +46,7 @@ shoes = /obj/item/clothing/shoes/sneakers/brown suit = /obj/item/clothing/suit/toggle/labcoat/cmo l_hand = /obj/item/storage/firstaid/regular - suit_store = /obj/item/flashlight/pen + suit_store = /obj/item/flashlight/pen/paramedic backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1) backpack = /obj/item/storage/backpack/medic diff --git a/code/modules/jobs/job_types/clown.dm b/code/modules/jobs/job_types/clown.dm index 7ad7148614..dc2f60434c 100644 --- a/code/modules/jobs/job_types/clown.dm +++ b/code/modules/jobs/job_types/clown.dm @@ -10,6 +10,7 @@ selection_color = "#dddddd" outfit = /datum/outfit/job/clown + plasma_outfit = /datum/outfit/plasmaman/clown access = list(ACCESS_THEATRE) minimal_access = list(ACCESS_THEATRE) diff --git a/code/modules/jobs/job_types/cook.dm b/code/modules/jobs/job_types/cook.dm index 5a5916cb7e..666ee8f036 100644 --- a/code/modules/jobs/job_types/cook.dm +++ b/code/modules/jobs/job_types/cook.dm @@ -11,6 +11,7 @@ var/cooks = 0 //Counts cooks amount outfit = /datum/outfit/job/cook + plasma_outfit = /datum/outfit/plasmaman/chef access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/curator.dm b/code/modules/jobs/job_types/curator.dm index 47bfd4914a..254fc15bd4 100644 --- a/code/modules/jobs/job_types/curator.dm +++ b/code/modules/jobs/job_types/curator.dm @@ -10,6 +10,7 @@ selection_color = "#dddddd" outfit = /datum/outfit/job/curator + plasma_outfit = /datum/outfit/plasmaman/curator access = list(ACCESS_LIBRARY) minimal_access = list(ACCESS_LIBRARY, ACCESS_CONSTRUCTION, ACCESS_MINING_STATION) diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index e5afe7e1b3..65724765e1 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -14,6 +14,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/detective + plasma_outfit = /datum/outfit/plasmaman/detective 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) @@ -23,7 +24,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_DETECTIVE - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/monophobia) threat = 1 /datum/outfit/job/detective diff --git a/code/modules/jobs/job_types/geneticist.dm b/code/modules/jobs/job_types/geneticist.dm index a40ca0fca3..5ff1bebfbf 100644 --- a/code/modules/jobs/job_types/geneticist.dm +++ b/code/modules/jobs/job_types/geneticist.dm @@ -12,6 +12,7 @@ exp_requirements = 60 outfit = /datum/outfit/job/geneticist + plasma_outfit = /datum/outfit/plasmaman/genetics 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) diff --git a/code/modules/jobs/job_types/head_of_personnel.dm b/code/modules/jobs/job_types/head_of_personnel.dm index 8015c19c36..41fb4b99da 100644 --- a/code/modules/jobs/job_types/head_of_personnel.dm +++ b/code/modules/jobs/job_types/head_of_personnel.dm @@ -17,6 +17,7 @@ exp_type_department = EXP_TYPE_SERVICE outfit = /datum/outfit/job/hop + plasma_outfit = /datum/outfit/plasmaman/hop access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS, diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 69ed63a514..cfd8d7f6c0 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -17,6 +17,8 @@ exp_type_department = EXP_TYPE_SECURITY outfit = /datum/outfit/job/hos + plasma_outfit = /datum/outfit/plasmaman/hos + mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_WEAPONS, ACCESS_ENTER_GENPOP, ACCESS_LEAVE_GENPOP, @@ -31,7 +33,7 @@ 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) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity) threat = 3 /datum/outfit/job/hos diff --git a/code/modules/jobs/job_types/janitor.dm b/code/modules/jobs/job_types/janitor.dm index 2f6d6f0e32..c62c2e5b26 100644 --- a/code/modules/jobs/job_types/janitor.dm +++ b/code/modules/jobs/job_types/janitor.dm @@ -10,6 +10,7 @@ selection_color = "#bbe291" outfit = /datum/outfit/job/janitor + plasma_outfit = /datum/outfit/plasmaman/janitor access = list(ACCESS_JANITOR, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) minimal_access = list(ACCESS_JANITOR, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/lawyer.dm b/code/modules/jobs/job_types/lawyer.dm index 1a7499800b..17c376a5de 100644 --- a/code/modules/jobs/job_types/lawyer.dm +++ b/code/modules/jobs/job_types/lawyer.dm @@ -11,6 +11,7 @@ var/lawyers = 0 //Counts lawyer amount outfit = /datum/outfit/job/lawyer + plasma_outfit = /datum/outfit/plasmaman/bar //yes, this is correct, there's no 'lawyer' plasmeme outfit access = list(ACCESS_LAWYER, ACCESS_COURT, ACCESS_SEC_DOORS) minimal_access = list(ACCESS_LAWYER, ACCESS_COURT, ACCESS_SEC_DOORS) diff --git a/code/modules/jobs/job_types/medical_doctor.dm b/code/modules/jobs/job_types/medical_doctor.dm index 5ec4b83b2f..d6a763acfe 100644 --- a/code/modules/jobs/job_types/medical_doctor.dm +++ b/code/modules/jobs/job_types/medical_doctor.dm @@ -10,6 +10,7 @@ selection_color = "#74b5e0" outfit = /datum/outfit/job/doctor + plasma_outfit = /datum/outfit/plasmaman/medical 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) diff --git a/code/modules/jobs/job_types/mime.dm b/code/modules/jobs/job_types/mime.dm index 4ba2489ab2..e00b3a1e29 100644 --- a/code/modules/jobs/job_types/mime.dm +++ b/code/modules/jobs/job_types/mime.dm @@ -10,6 +10,7 @@ selection_color = "#dddddd" outfit = /datum/outfit/job/mime + plasma_outfit = /datum/outfit/plasmaman/mime access = list(ACCESS_THEATRE) minimal_access = list(ACCESS_THEATRE) diff --git a/code/modules/jobs/job_types/paramedic.dm b/code/modules/jobs/job_types/paramedic.dm index 9bdfdfe279..c8188cae8a 100644 --- a/code/modules/jobs/job_types/paramedic.dm +++ b/code/modules/jobs/job_types/paramedic.dm @@ -36,7 +36,7 @@ suit = /obj/item/clothing/suit/toggle/labcoat/paramedic belt = /obj/item/storage/belt/medical l_hand = /obj/item/storage/firstaid/regular - suit_store = /obj/item/flashlight/pen + suit_store = /obj/item/flashlight/pen/paramedic id = /obj/item/card/id r_pocket = /obj/item/pinpointer/crew l_pocket = /obj/item/pda/medical diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index 7128fbe2c7..33f7df8260 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -17,6 +17,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/rd + plasma_outfit = /datum/outfit/plasmaman/rd access = list(ACCESS_RD, ACCESS_HEADS, ACCESS_TOX, ACCESS_GENETICS, ACCESS_MORGUE, ACCESS_TOX_STORAGE, ACCESS_TELEPORTER, ACCESS_SEC_DOORS, diff --git a/code/modules/jobs/job_types/roboticist.dm b/code/modules/jobs/job_types/roboticist.dm index f5ae93bb6a..aa52b353df 100644 --- a/code/modules/jobs/job_types/roboticist.dm +++ b/code/modules/jobs/job_types/roboticist.dm @@ -12,6 +12,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/roboticist + plasma_outfit = /datum/outfit/plasmaman/robotics 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) diff --git a/code/modules/jobs/job_types/scientist.dm b/code/modules/jobs/job_types/scientist.dm index 476f740b9d..a851b333fe 100644 --- a/code/modules/jobs/job_types/scientist.dm +++ b/code/modules/jobs/job_types/scientist.dm @@ -12,6 +12,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/scientist + plasma_outfit = /datum/outfit/plasmaman/science 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) diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index bc6f6a94c7..bc83eb752d 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -14,6 +14,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/security + plasma_outfit = /datum/outfit/plasmaman/security 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() @@ -23,7 +24,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia) threat = 2 /datum/job/officer/get_access() diff --git a/code/modules/jobs/job_types/shaft_miner.dm b/code/modules/jobs/job_types/shaft_miner.dm index a09c4376fb..04d3fb53b8 100644 --- a/code/modules/jobs/job_types/shaft_miner.dm +++ b/code/modules/jobs/job_types/shaft_miner.dm @@ -12,11 +12,12 @@ outfit = /datum/outfit/job/miner + plasma_outfit = /datum/outfit/plasmaman/mining 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 = PAYCHECK_EASY ///Not necessarily easy itself, but it can be trivial to make lot of cash on this job. 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 d3f5db7dbb..2396728ad8 100644 --- a/code/modules/jobs/job_types/station_engineer.dm +++ b/code/modules/jobs/job_types/station_engineer.dm @@ -12,6 +12,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/engineer + plasma_outfit = /datum/outfit/plasmaman/engineering access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM) diff --git a/code/modules/jobs/job_types/virologist.dm b/code/modules/jobs/job_types/virologist.dm index 790e828931..3e9b3ba06c 100644 --- a/code/modules/jobs/job_types/virologist.dm +++ b/code/modules/jobs/job_types/virologist.dm @@ -12,6 +12,7 @@ exp_requirements = 60 outfit = /datum/outfit/job/virologist + plasma_outfit = /datum/outfit/plasmaman/viro 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) diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 5762731f62..c909342d6f 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -14,6 +14,7 @@ exp_type = EXP_TYPE_CREW outfit = /datum/outfit/job/warden + plasma_outfit = /datum/outfit/plasmaman/warden 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() @@ -24,7 +25,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_WARDEN - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia) threat = 2 /datum/job/warden/get_access() diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm index b4940e0085..3a47cd2315 100644 --- a/code/modules/keybindings/bindings_client.dm +++ b/code/modules/keybindings/bindings_client.dm @@ -91,6 +91,11 @@ if(!(next_move_dir_add & movement)) next_move_dir_sub |= movement + if(prefs.modless_key_bindings[_key]) + var/datum/keybinding/kb = GLOB.keybindings_by_name[prefs.modless_key_bindings[_key]] + if(kb.can_use(src)) + kb.up(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]) diff --git a/code/modules/keybindings/keybind/combat.dm b/code/modules/keybindings/keybind/combat.dm index 457fbb0cb2..c4b44b5283 100644 --- a/code/modules/keybindings/keybind/combat.dm +++ b/code/modules/keybindings/keybind/combat.dm @@ -25,6 +25,18 @@ var/mob/living/L = user.mob L.keybind_stop_active_blocking() +/datum/keybinding/living/active_block_toggle + hotkey_keys = list("Unbound") + name = "active_block_toggle" + full_name = "Block (Toggle)" + category = CATEGORY_COMBAT + description = "Toggles active blocking system using currenet in hand object, or any found object if applicable." + +/datum/keybinding/living/active_block_toggle/down(client/user) + var/mob/living/L = user.mob + L.keybind_toggle_active_blocking() + return TRUE + /datum/keybinding/living/active_parry hotkey_keys = list("Insert", "G") name = "active_parry" diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index 6e3d27f2b8..c1677117e9 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -276,7 +276,8 @@ Key procs /datum/language/draconic = list(LANGUAGE_ATOM)) /datum/language_holder/lizard/ash - selected_language = /datum/language/draconic + understood_languages = list(/datum/language/draconic = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/draconic = list(LANGUAGE_ATOM)) /datum/language_holder/monkey understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), @@ -323,6 +324,12 @@ Key procs /datum/language/sylvan = list(LANGUAGE_ATOM)) spoken_languages = list(/datum/language/sylvan = list(LANGUAGE_ATOM)) +/datum/language_holder/ethereal + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/voltaic = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/voltaic = list(LANGUAGE_ATOM)) + /datum/language_holder/empty understood_languages = list() spoken_languages = list() diff --git a/code/modules/language/language_menu.dm b/code/modules/language/language_menu.dm index a7ce211a18..bffd3d59af 100644 --- a/code/modules/language/language_menu.dm +++ b/code/modules/language/language_menu.dm @@ -8,10 +8,13 @@ language_holder = null . = ..() -/datum/language_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.language_menu_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/language_menu/ui_state(mob/user) + return GLOB.language_menu_state + +/datum/language_menu/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "language_menu", "Language Menu", 700, 600, master_ui, state) + ui = new(user, src, "LanguageMenu") ui.open() /datum/language_menu/ui_data(mob/user) diff --git a/code/modules/language/voltaic.dm b/code/modules/language/voltaic.dm new file mode 100644 index 0000000000..ead7fe7c7f --- /dev/null +++ b/code/modules/language/voltaic.dm @@ -0,0 +1,14 @@ +// One of these languages will actually work, I'm certain of it. +/datum/language/voltaic + name = "Voltaic" + desc = "A sparky language made by manipulating electrical discharge." + key = "v" + space_chance = 20 + syllables = list( + "bzzt", "skrrt", "zzp", "mmm", "hzz", "tk", "shz", "k", "z", + "bzt", "zzt", "skzt", "skzz", "hmmt", "zrrt", "hzzt", "hz", + "vzt", "zt", "vz", "zip", "tzp", "lzzt", "dzzt", "zdt", "kzt", + "zzzz", "mzz" + ) + icon_state = "volt" + default_priority = 90 diff --git a/code/modules/library/lib_codex_gigas.dm b/code/modules/library/lib_codex_gigas.dm index 57bf37d528..26fa5b6f3d 100644 --- a/code/modules/library/lib_codex_gigas.dm +++ b/code/modules/library/lib_codex_gigas.dm @@ -34,13 +34,13 @@ if(U.check_acedia()) to_chat(user, "None of this matters, why are you reading this? You put [title] down.") return - user.visible_message("[user] opens [title] and begins reading intently.") + user.visible_message("[user] opens [title] and begins reading intently.") ask_name(user) /obj/item/book/codex_gigas/proc/perform_research(mob/user, devilName) if(!devilName) - user.visible_message("[user] closes [title] without looking anything up.") + user.visible_message("[user] closes [title] without looking anything up.") return inUse = TRUE var/speed = 300 @@ -50,7 +50,7 @@ if(U.job in list("Curator")) // the curator is both faster, and more accurate than normal crew members at research speed = 100 correctness = 100 - correctness -= U.getOrganLoss(ORGAN_SLOT_BRAIN) *0.5 //Brain damage makes researching hard. + correctness -= U.getOrganLoss(ORGAN_SLOT_BRAIN) * 0.5 //Brain damage makes researching hard. speed += U.getOrganLoss(ORGAN_SLOT_BRAIN) * 3 if(do_after(user, speed, 0, user)) var/usedName = devilName @@ -95,11 +95,10 @@ currentSection = SUFFIX return currentSection != oldSection -/obj/item/book/codex_gigas/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/book/codex_gigas/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "codex_gigas", name, 450, 450, master_ui, state) + ui = new(user, src, "CodexGigas", name) ui.open() /obj/item/book/codex_gigas/ui_data(mob/user) diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 89fa3ac6cf..80ce2522ff 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -112,7 +112,7 @@ else return ..() -/obj/structure/bookcase/attack_hand(mob/living/user) +/obj/structure/bookcase/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(. || !istype(user)) return diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index 144037b3a7..f777246453 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -523,10 +523,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums else return ..() -/obj/machinery/libraryscanner/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/libraryscanner/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) usr.set_machine(src) var/dat = "" // if(cache) diff --git a/code/modules/library/soapstone.dm b/code/modules/library/soapstone.dm index 272e39957e..f17040a938 100644 --- a/code/modules/library/soapstone.dm +++ b/code/modules/library/soapstone.dm @@ -35,13 +35,13 @@ return if(existing_message) - user.visible_message("[user] starts erasing [existing_message].", "You start erasing [existing_message].", "You hear a chipping sound.") - playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1) + user.visible_message("[user] starts erasing [existing_message].", "You start erasing [existing_message].", "You hear a chipping sound.") + playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1) if(do_after(user, tool_speed, target = existing_message)) user.visible_message("[user] erases [existing_message].", "You erase [existing_message][existing_message.creator_key == user.ckey ? ", refunding a use" : ""].") existing_message.persists = FALSE qdel(existing_message) - playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1) + playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1) if(existing_message.creator_key == user.ckey) refund_use() return @@ -54,12 +54,12 @@ if(!target.Adjacent(user) && locate(/obj/structure/chisel_message) in T) to_chat(user, "Someone wrote here before you chose! Find another spot.") return - playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1) - user.visible_message("[user] starts engraving a message into [T]...", "You start engraving a message into [T]...", "You hear a chipping sound.") + playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1) + user.visible_message("[user] starts engraving a message into [T]...", "You start engraving a message into [T]...", "You hear a chipping sound.") if(can_use() && do_after(user, tool_speed, target = T) && can_use()) //This looks messy but it's actually really clever! if(!locate(/obj/structure/chisel_message) in T) - user.visible_message("[user] leaves a message for future spacemen!", "You engrave a message into [T]!", "You hear a chipping sound.") - playsound(loc, 'sound/items/gavel.ogg', 50, 1, -1) + user.visible_message("[user] leaves a message for future spacemen!", "You engrave a message into [T]!", "You hear a chipping sound.") + playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1) var/obj/structure/chisel_message/M = new(T) M.register(user, message) remove_use() @@ -112,12 +112,10 @@ desc = "A message from a past traveler." icon = 'icons/obj/stationobjs.dmi' icon_state = "soapstone_message" - layer = HIGH_OBJ_LAYER + layer = LATTICE_LAYER density = FALSE anchored = TRUE max_integrity = 30 - layer = LATTICE_LAYER - light_power = 0.3 var/hidden_message var/creator_key @@ -206,10 +204,13 @@ /obj/structure/chisel_message/interact() return -/obj/structure/chisel_message/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/structure/chisel_message/ui_state(mob/user) + return GLOB.always_state + +/obj/structure/chisel_message/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "engraved_message", name, 600, 300, master_ui, state) + ui = new(user, src, "EngravedMessage", name) ui.open() /obj/structure/chisel_message/ui_data(mob/user) diff --git a/code/modules/lighting/lighting_area.dm b/code/modules/lighting/lighting_area.dm index 58e9a4337a..7e54456483 100644 --- a/code/modules/lighting/lighting_area.dm +++ b/code/modules/lighting/lighting_area.dm @@ -24,7 +24,7 @@ /area/vv_edit_var(var_name, var_value) switch(var_name) - if("dynamic_lighting") + if(NAMEOF(src, dynamic_lighting)) set_dynamic_lighting(var_value) return TRUE - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 779dd9c3ea..71702bef12 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -89,17 +89,17 @@ /atom/vv_edit_var(var_name, var_value) switch (var_name) - if ("light_range") + if (NAMEOF(src, light_range)) set_light(l_range=var_value) datum_flags |= DF_VAR_EDITED return TRUE - if ("light_power") + if (NAMEOF(src, light_power)) set_light(l_power=var_value) datum_flags |= DF_VAR_EDITED return TRUE - if ("light_color") + if (NAMEOF(src, light_color)) set_light(l_color=var_value) datum_flags |= DF_VAR_EDITED return TRUE diff --git a/code/modules/mafia/_defines.dm b/code/modules/mafia/_defines.dm new file mode 100644 index 0000000000..194851beed --- /dev/null +++ b/code/modules/mafia/_defines.dm @@ -0,0 +1,65 @@ +///how many people can play mafia without issues (running out of spawns, procs not expecting more than this amount of people, etc) +#define MAFIA_MAX_PLAYER_COUNT 12 + +#define MAFIA_TEAM_TOWN "town" +#define MAFIA_TEAM_MAFIA "mafia" +#define MAFIA_TEAM_SOLO "solo" + +//types of town roles for random setup gen +/// assistants it's just assistants filling up the rest of the roles +#define TOWN_OVERFLOW "overflow" +/// roles that learn info about others in the game (chaplain, detective, psych) +#define TOWN_INVEST "invest" +/// roles that keep other roles safe (doctor, and weirdly enough lawyer counts) +#define TOWN_PROTECT "protect" +/// roles that don't fit into anything else (hop) +#define TOWN_MISC "misc" + +//other types (mafia team, neutrals) +/// normal vote kill changelings +#define MAFIA_REGULAR "regular" +/// every other changeling role that has extra abilities +#define MAFIA_SPECIAL "special" +/// role that wins solo that nobody likes +#define NEUTRAL_KILL "kill" +/// role that upsets the game aka obsessed, usually worse for town than mafia but they can vote against mafia +#define NEUTRAL_DISRUPT "disrupt" + +#define MAFIA_PHASE_SETUP 1 +#define MAFIA_PHASE_DAY 2 +#define MAFIA_PHASE_VOTING 3 +#define MAFIA_PHASE_JUDGEMENT 4 +#define MAFIA_PHASE_NIGHT 5 +#define MAFIA_PHASE_VICTORY_LAP 6 + +#define MAFIA_ALIVE 1 +#define MAFIA_DEAD 2 + +#define COMSIG_MAFIA_ON_KILL "mafia_onkill" +#define MAFIA_PREVENT_KILL 1 + +#define COMSIG_MAFIA_CAN_PERFORM_ACTION "mafia_can_perform_action" +#define MAFIA_PREVENT_ACTION 1 + +//in order of events + game end + +/// when the shutters fall, before the 45 second wait and night event resolution +#define COMSIG_MAFIA_SUNDOWN "sundown" +/// after the 45 second wait, for actions that must go first +#define COMSIG_MAFIA_NIGHT_START "night_start" +/// most night actions now resolve +#define COMSIG_MAFIA_NIGHT_ACTION_PHASE "night_actions" +/// now killing happens from the roles that do that. the reason this is post action phase is to ensure doctors can protect and lawyers can block +#define COMSIG_MAFIA_NIGHT_KILL_PHASE "night_kill" +/// now undoing states like protection, actions that must happen last, etc. right before shutters raise and the day begins +#define COMSIG_MAFIA_NIGHT_END "night_end" + +/// signal sent to roles when the game is confirmed ending +#define COMSIG_MAFIA_GAME_END "game_end" + +/// list of ghosts who want to play mafia, every time someone enters the list it checks to see if enough are in +GLOBAL_LIST_EMPTY(mafia_signup) +/// list of ghosts who want to play mafia that have since disconnected. They are kept in the lobby, but not counted for starting a game. +GLOBAL_LIST_EMPTY(mafia_bad_signup) +/// the current global mafia game running. +GLOBAL_VAR(mafia_game) diff --git a/code/modules/mafia/controller.dm b/code/modules/mafia/controller.dm new file mode 100644 index 0000000000..cd8c382f30 --- /dev/null +++ b/code/modules/mafia/controller.dm @@ -0,0 +1,971 @@ + + +/** + * The mafia controller handles the mafia minigame in progress. + * It is first created when the first ghost signs up to play. + */ +/datum/mafia_controller + ///list of observers that should get game updates. + var/list/spectators = list() + ///all roles in the game, dead or alive. check their game status if you only want living or dead. + var/list/all_roles = list() + ///exists to speed up role retrieval, it's a dict. player_role_lookup[player ckey] will give you the role they play + var/list/player_role_lookup = list() + ///what part of the game you're playing in. day phases, night phases, judgement phases, etc. + var/phase = MAFIA_PHASE_SETUP + ///how long the game has gone on for, changes with every sunrise. day one, night one, day two, etc. + var/turn = 0 + ///for debugging and testing a full game, or adminbuse. If this is not null, it will use this as a setup. clears when game is over + var/list/custom_setup = list() + ///first day has no voting, and thus is shorter + var/first_day_phase_period = 20 SECONDS + ///talk with others about the last night + var/day_phase_period = 1 MINUTES + ///vote someone to get put on trial + var/voting_phase_period = 30 SECONDS + ///defend yourself! don't get lynched! sometimes skipped if nobody votes. + var/judgement_phase_period = 30 SECONDS + ///guilty or innocent, we want a bit of time for players to process the outcome of the vote + var/judgement_lynch_period = 5 SECONDS + ///mafia talk at night and pick someone to kill, some town roles use their actions, etc etc. + var/night_phase_period = 45 SECONDS + ///like the lynch period, players need to see what the other players in the game's roles were + var/victory_lap_period = 20 SECONDS + + ///template picked when the game starts. used for the name and desc reading + var/datum/map_template/mafia/current_map + ///map generation tool that deletes the current map after the game finishes + var/datum/mapGenerator/massdelete/map_deleter + + ///Readable list of roles in current game, sent to the tgui panel for roles list > list("Psychologist x1", "Clown x2") + var/list/current_setup_text + + ///starting outfit for all mafia players. it's just a grey jumpsuit. + var/player_outfit = /datum/outfit/mafia + + ///spawn points for players, each one has a house + var/list/landmarks = list() + ///town center for when people get put on trial + var/town_center_landmark + + ///group voting on one person, like putting people to trial or choosing who to kill as mafia + var/list/votes = list() + ///and these (judgement_innocent_votes, judgement_abstain_votes and judgement_guilty_votes) are the judgement phase votes, aka people sorting themselves into guilty and innocent, and "eh, i don't really care" lists. whichever has more inno or guilty wins! + var/list/judgement_abstain_votes = list() + var/list/judgement_innocent_votes = list() + var/list/judgement_guilty_votes = list() + ///current role on trial for the judgement phase, will die if guilty is greater than innocent + var/datum/mafia_role/on_trial + + ///current timer for phase + var/next_phase_timer + + ///used for debugging in testing (doesn't put people out of the game, some other shit i forgot, who knows just don't set this in live) honestly kinda deprecated + var/debug = FALSE + + ///Max player count + var/max_player = MAFIA_MAX_PLAYER_COUNT + ///Required player count + var/required_player = 5 + ///Prioritizes clients to have cool antag roles + var/low_pop_mode = FALSE + +/datum/mafia_controller/New() + . = ..() + GLOB.mafia_game = src + map_deleter = new + +/datum/mafia_controller/Destroy(force, ...) + . = ..() + GLOB.mafia_game = null + end_game() + qdel(map_deleter) + +/** + * Triggers at beginning of the game when there is a confirmed list of valid, ready players. + * Creates a 100% ready game that has NOT started (no players in bodies) + * Followed by start game + * + * Does the following: + * * Picks map, and loads it + * * Grabs landmarks if it is the first time it's loading + * * Sets up the role list + * * Puts players in each role randomly + * Arguments: + * * setup_list: list of all the datum setups (fancy list of roles) that would work for the game + * * ready_players: list of filtered, sane players (so not playing or disconnected) for the game to put into roles + */ +/datum/mafia_controller/proc/prepare_game(setup_list, ready_players) + + var/list/possible_maps = subtypesof(/datum/map_template/mafia) + var/turf/spawn_area = get_turf(locate(/obj/effect/landmark/mafia_game_area) in GLOB.landmarks_list) + + current_map = pick(possible_maps) + current_map = new current_map + + if(!spawn_area) + CRASH("No spawn area detected for Mafia!") + var/list/bounds = current_map.load(spawn_area) + if(!bounds) + CRASH("Loading mafia map failed!") + map_deleter.defineRegion(spawn_area, locate(spawn_area.x + 23,spawn_area.y + 23,spawn_area.z), replace = TRUE) //so we're ready to mass delete when round ends + + if(!landmarks.len)//we grab town center when we grab landmarks, if there is none (the first game signed up for let's grab them post load) + for(var/obj/effect/landmark/mafia/possible_spawn in GLOB.landmarks_list) + if(istype(possible_spawn, /obj/effect/landmark/mafia/town_center)) + town_center_landmark = possible_spawn + else + landmarks += possible_spawn + + current_setup_text = list() + + var/list/boring_roles = list() + var/list/not_boring_roles = list() + + for(var/rtype in setup_list) + for(var/i in 1 to setup_list[rtype]) + var/datum/mafia_role/role = new rtype(src) + all_roles += role + if(role.role_type == TOWN_PROTECT || role.role_type == TOWN_INVEST || role.role_type == MAFIA_SPECIAL || role.role_type == MAFIA_REGULAR) + not_boring_roles += role + else + boring_roles += role + var/datum/mafia_role/rp = rtype + current_setup_text += "[initial(rp.name)] x[setup_list[rtype]]" + + var/list/spawnpoints = landmarks.Copy() + + if(length(ready_players) < 7 || low_pop_mode) + //do normal assign + for(var/datum/mafia_role/role in not_boring_roles) + role.assigned_landmark = pick_n_take(spawnpoints) + role.player_key = pick_n_take(ready_players) + //shame! + for(var/datum/mafia_role/role in boring_roles) + role.assigned_landmark = pick_n_take(spawnpoints) + role.player_key = pick_n_take(ready_players) + + else //go run the normal one + for(var/datum/mafia_role/role in all_roles) + role.assigned_landmark = pick_n_take(spawnpoints) + if(!debug) + role.player_key = pick_n_take(ready_players) + else + role.player_key = pop(ready_players) + +/datum/mafia_controller/proc/send_message(msg,team) + for(var/datum/mafia_role/R in all_roles) + if(team && R.team != team) + continue + to_chat(R.body,msg) + var/team_suffix = team ? "([uppertext(team)] CHAT)" : "" + for(var/M in GLOB.dead_mob_list) + var/mob/spectator = M + if(spectator.ckey in spectators) //was in current game, or spectatin' (won't send to living) + var/link = FOLLOW_LINK(M, town_center_landmark) + to_chat(M, "[link] MAFIA: [msg] [team_suffix]") + +/** + * The game by this point is now all set up, and so we can put people in their bodies and start the first phase. + * + * Does the following: + * * Creates bodies for all of the roles with the first proc + * * Starts the first day manually (so no timer) with the second proc + */ +/datum/mafia_controller/proc/start_game() + create_bodies() + start_day() + +/** + * How every day starts. + * + * What players do in this phase: + * * If day one, just a small starting period to see who is in the game and check role, leading to the night phase. + * * Otherwise, it's a longer period used to discuss events that happened during the night, leading to the voting phase. + */ +/datum/mafia_controller/proc/start_day() + turn += 1 + phase = MAFIA_PHASE_DAY + if(!check_victory()) + if(turn == 1) + send_message("The selected map is [current_map.name]!
    [current_map.description]
    ") + send_message("Day [turn] started! There is no voting on the first day. Say hello to everybody!") + next_phase_timer = addtimer(CALLBACK(src,.proc/check_trial, FALSE),first_day_phase_period,TIMER_STOPPABLE) //no voting period = no votes = instant night + else + send_message("Day [turn] started! Voting will start in 1 minute.") + next_phase_timer = addtimer(CALLBACK(src,.proc/start_voting_phase),day_phase_period,TIMER_STOPPABLE) + + SStgui.update_uis(src) + +/** + * Players have finished the discussion period, and now must put up someone to the chopping block. + * + * What players do in this phase: + * * Vote on which player to put up for lynching, leading to the judgement phase. + * * If no votes are case, the judgement phase is skipped, leading to the night phase. + */ +/datum/mafia_controller/proc/start_voting_phase() + phase = MAFIA_PHASE_VOTING + next_phase_timer = addtimer(CALLBACK(src, .proc/check_trial, TRUE),voting_phase_period,TIMER_STOPPABLE) //be verbose! + send_message("Voting started! Vote for who you want to see on trial today.") + SStgui.update_uis(src) + +/** + * Players have voted someone up, and now the person must defend themselves while the town votes innocent or guilty. + * + * What players do in this phase: + * * Vote innocent or guilty, if they are not on trial. + * * Defend themselves and wait for judgement, if they are. + * * Leads to the lynch phase. + * Arguments: + * * verbose: boolean, announces whether there were votes or not. after judgement it goes back here with no voting period to end the day. + */ +/datum/mafia_controller/proc/check_trial(verbose = TRUE) + var/datum/mafia_role/loser = get_vote_winner("Day")//, majority_of_town = TRUE) + // var/loser_votes = get_vote_count(loser,"Day") + if(loser) + // if(loser_votes > 12) + // loser.body.client?.give_award(/datum/award/achievement/mafia/universally_hated, loser.body) + send_message("[loser.body.real_name] wins the day vote, Listen to their defense and vote \"INNOCENT\" or \"GUILTY\"!") + //refresh the lists + judgement_abstain_votes = list() + judgement_innocent_votes = list() + judgement_guilty_votes = list() + for(var/i in all_roles) + var/datum/mafia_role/abstainee = i + if(abstainee.game_status == MAFIA_ALIVE && abstainee != loser) + judgement_abstain_votes += abstainee + on_trial = loser + on_trial.body.forceMove(get_turf(town_center_landmark)) + phase = MAFIA_PHASE_JUDGEMENT + next_phase_timer = addtimer(CALLBACK(src, .proc/lynch),judgement_phase_period,TIMER_STOPPABLE) + reset_votes("Day") + else + if(verbose) + send_message("Not enough people have voted to put someone on trial, nobody will be lynched today.") + if(!check_victory()) + lockdown() + SStgui.update_uis(src) + +/** + * Players have voted innocent or guilty on the person on trial, and that person is now killed or returned home. + * + * What players do in this phase: + * * r/watchpeopledie + * * If the accused is killed, their true role is revealed to the rest of the players. + */ +/datum/mafia_controller/proc/lynch() + for(var/i in judgement_innocent_votes) + var/datum/mafia_role/role = i + send_message("[role.body.real_name] voted innocent.") + for(var/ii in judgement_abstain_votes) + var/datum/mafia_role/role = ii + send_message("[role.body.real_name] abstained.") + for(var/iii in judgement_guilty_votes) + var/datum/mafia_role/role = iii + send_message("[role.body.real_name] voted guilty.") + if(judgement_guilty_votes.len > judgement_innocent_votes.len) //strictly need majority guilty to lynch + send_message("Guilty wins majority, [on_trial.body.real_name] has been lynched.") + on_trial.kill(src, lynch = TRUE) + addtimer(CALLBACK(src, .proc/send_home, on_trial),judgement_lynch_period) + else + send_message("Innocent wins majority, [on_trial.body.real_name] has been spared.") + on_trial.body.forceMove(get_turf(on_trial.assigned_landmark)) + on_trial = null + //day votes are already cleared, so this will skip the trial and check victory/lockdown/whatever else + next_phase_timer = addtimer(CALLBACK(src, .proc/check_trial, FALSE),judgement_lynch_period,TIMER_STOPPABLE)// small pause to see the guy dead, no verbosity since we already did this + +/** + * Teenie helper proc to move players back to their home. + * Used in the above, but also used in the debug button "send all players home" + * Arguments: + * * role: mafia role that is getting sent back to the game. + */ +/datum/mafia_controller/proc/send_home(datum/mafia_role/role) + role.body.forceMove(get_turf(role.assigned_landmark)) + +/** + * Checks to see if a faction (or solo antagonist) has won. + * + * Calculates in this order: + * * counts up town, mafia, and solo + * * solos can count as town members for the purposes of mafia winning + * * sends the amount of living people to the solo antagonists, and see if they won OR block the victory of the teams + * * checks if solos won from above, then if town, then if mafia + * * starts the end of the game if a faction won + * * returns TRUE if someone won the game, halting other procs from continuing in the case of a victory + */ +/datum/mafia_controller/proc/check_victory() + //needed for achievements + var/list/total_town = list() + var/list/total_mafia = list() + + var/alive_town = 0 + var/alive_mafia = 0 + var/list/solos_to_ask = list() //need to ask after because first round is counting team sizes + var/list/total_victors = list() //if this list gets filled with anyone, they win. list because side antags can with with people + var/blocked_victory = FALSE //if a solo antagonist is stopping the town or mafia from finishing the game. + + ///PHASE ONE: TALLY UP ALL NUMBERS OF PEOPLE STILL ALIVE + + for(var/datum/mafia_role/R in all_roles) + switch(R.team) + if(MAFIA_TEAM_MAFIA) + total_mafia += R + if(R.game_status == MAFIA_ALIVE) + alive_mafia += R.vote_power + if(MAFIA_TEAM_TOWN) + total_town += R + if(R.game_status == MAFIA_ALIVE) + alive_town += R.vote_power + if(MAFIA_TEAM_SOLO) + if(R.game_status == MAFIA_ALIVE) + if(R.solo_counts_as_town) + alive_town += R.vote_power + solos_to_ask += R + + ///PHASE TWO: SEND STATS TO SOLO ANTAGS, SEE IF THEY WON OR TEAMS CANNOT WIN + + for(var/datum/mafia_role/solo in solos_to_ask) + if(solo.check_total_victory(alive_town, alive_mafia)) + total_victors += solo + if(solo.block_team_victory(alive_town, alive_mafia)) + blocked_victory = TRUE + + //solo victories! + var/solo_end = FALSE + for(var/datum/mafia_role/winner in total_victors) + send_message("!! [uppertext(winner.name)] VICTORY !!") + // var/client/winner_client = GLOB.directory[winner.player_key] + // winner_client?.give_award(winner.winner_award, winner.body) + solo_end = TRUE + if(solo_end) + start_the_end() + return TRUE + if(blocked_victory) + return FALSE + if(alive_mafia == 0) + // for(var/datum/mafia_role/townie in total_town) + // var/client/townie_client = GLOB.directory[townie.player_key] + // townie_client?.give_award(townie.winner_award, townie.body) + start_the_end("!! TOWN VICTORY !!") + return TRUE + else if(alive_mafia >= alive_town) //guess could change if town nightkill is added + start_the_end("!! MAFIA VICTORY !!") + // for(var/datum/mafia_role/changeling in total_mafia) + // var/client/changeling_client = GLOB.directory[changeling.player_key] + // changeling_client?.give_award(changeling.winner_award, changeling.body) + return TRUE + +/** + * The end of the game is in two procs, because we want a bit of time for players to see eachothers roles. + * Because of how check_victory works, the game is halted in other places by this point. + * + * What players do in this phase: + * * See everyone's role postgame + * * See who won the game + * Arguments: + * * message: string, if non-null it sends it to all players. used to announce team victories while solos are handled in check victory + */ +/datum/mafia_controller/proc/start_the_end(message) + SEND_SIGNAL(src,COMSIG_MAFIA_GAME_END) + if(message) + send_message(message) + for(var/datum/mafia_role/R in all_roles) + R.reveal_role(src) + phase = MAFIA_PHASE_VICTORY_LAP + next_phase_timer = addtimer(CALLBACK(src,.proc/end_game),victory_lap_period,TIMER_STOPPABLE) + +/** + * Cleans up the game, resetting variables back to the beginning and removing the map with the generator. + */ +/datum/mafia_controller/proc/end_game() + map_deleter.generate() //remove the map, it will be loaded at the start of the next one + QDEL_LIST(all_roles) + current_setup_text = null + custom_setup = list() + turn = 0 + votes = list() + //map gen does not deal with landmarks + QDEL_LIST(landmarks) + QDEL_NULL(town_center_landmark) + phase = MAFIA_PHASE_SETUP + +/** + * After the voting and judgement phases, the game goes to night shutting the windows and beginning night with a proc. + */ +/datum/mafia_controller/proc/lockdown() + toggle_night_curtains(close=TRUE) + start_night() + +/** + * Shuts poddoors attached to mafia. + * Arguments: + * * close: boolean, the state you want the curtains in. + */ +/datum/mafia_controller/proc/toggle_night_curtains(close) + for(var/obj/machinery/door/poddoor/D in GLOB.machines) //I really dislike pathing of these + if(D.id != "mafia") //so as to not trigger shutters on station, lol + continue + if(close) + INVOKE_ASYNC(D, /obj/machinery/door/poddoor.proc/close) + else + INVOKE_ASYNC(D, /obj/machinery/door/poddoor.proc/open) + +/** + * The actual start of night for players. Mostly info is given at the start of the night as the end of the night is when votes and actions are submitted and tried. + * + * What players do in this phase: + * * Mafia are told to begin voting on who to kill + * * Powers that are picked during the day announce themselves right now + */ +/datum/mafia_controller/proc/start_night() + phase = MAFIA_PHASE_NIGHT + send_message("Night [turn] started! Lockdown will end in 45 seconds.") + SEND_SIGNAL(src,COMSIG_MAFIA_SUNDOWN) + next_phase_timer = addtimer(CALLBACK(src, .proc/resolve_night),night_phase_period,TIMER_STOPPABLE) + SStgui.update_uis(src) + +/** + * The end of the night, and a series of signals for the order of events on a night. + * + * Order of events, and what they mean: + * * Start of resolve (NIGHT_START) is for activating night abilities that MUST go first + * * Action phase (NIGHT_ACTION_PHASE) is for non-lethal day abilities + * * Mafia then tallies votes and kills the highest voted person (note: one random voter visits that person for the purposes of roleblocking) + * * Killing phase (NIGHT_KILL_PHASE) is for lethal night abilities + * * End of resolve (NIGHT_END) is for cleaning up abilities that went off and i guess doing some that must go last + * * Finally opens the curtains and calls the start of day phase, completing the cycle until check victory returns TRUE + */ +/datum/mafia_controller/proc/resolve_night() + SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_START) + SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_ACTION_PHASE) + //resolve mafia kill, todo unsnowflake this + var/datum/mafia_role/R = get_vote_winner("Mafia") + if(R) + var/datum/mafia_role/killer = get_random_voter("Mafia") + if(SEND_SIGNAL(killer,COMSIG_MAFIA_CAN_PERFORM_ACTION,src,"mafia killing",R) & MAFIA_PREVENT_ACTION) + send_message("[killer.body.real_name] was unable to attack [R.body.real_name] tonight!",MAFIA_TEAM_MAFIA) + else + send_message("[killer.body.real_name] has attacked [R.body.real_name]!",MAFIA_TEAM_MAFIA) + R.kill(src) + reset_votes("Mafia") + SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_KILL_PHASE) + SEND_SIGNAL(src,COMSIG_MAFIA_NIGHT_END) + toggle_night_curtains(close=FALSE) + start_day() + SStgui.update_uis(src) + +/** + * Proc that goes off when players vote for something with their mafia panel. + * + * If teams, it hides the tally overlay and only sends the vote messages to the team that is voting + * Arguments: + * * voter: the mafia role that is trying to vote for... + * * target: the mafia role that is getting voted for + * * vote_type: type of vote submitted (is this the day vote? is this the mafia night vote?) + * * teams: see mafia team defines for what to put in, makes the messages only send to a specific team (so mafia night votes only sending messages to mafia at night) + */ +/datum/mafia_controller/proc/vote_for(datum/mafia_role/voter,datum/mafia_role/target,vote_type, teams) + if(!votes[vote_type]) + votes[vote_type] = list() + var/old_vote = votes[vote_type][voter] + if(old_vote && old_vote == target) + votes[vote_type] -= voter + else + votes[vote_type][voter] = target + if(old_vote && old_vote == target) + send_message("[voter.body.real_name] retracts their vote for [target.body.real_name]!", team = teams) + else + send_message("[voter.body.real_name] voted for [target.body.real_name]!",team = teams) + if(!teams) + target.body.update_icon() //Update the vote display if it's a public vote + var/datum/mafia_role/old = old_vote + if(old) + old.body.update_icon() + +/** + * Clears out the votes of a certain type (day votes, mafia kill votes) while leaving others untouched + */ +/datum/mafia_controller/proc/reset_votes(vote_type) + var/list/bodies_to_update = list() + for(var/vote in votes[vote_type]) + var/datum/mafia_role/R = votes[vote_type][vote] + bodies_to_update += R.body + votes[vote_type] = list() + for(var/mob/M in bodies_to_update) + M.update_icon() + +/** + * Returns how many people voted for the role, in whatever vote (day vote, night kill vote) + * Arguments: + * * role: the mafia role the proc tries to get the amount of votes for + * * vote_type: the vote type (getting how many day votes were for the role, or mafia night votes for the role) + */ +/datum/mafia_controller/proc/get_vote_count(role,vote_type) + . = 0 + for(var/v in votes[vote_type]) + var/datum/mafia_role/votee = v + if(votes[vote_type][votee] == role) + . += votee.vote_power + +/** + * Returns whichever role got the most votes, in whatever vote (day vote, night kill vote) + * returns null if no votes + * Arguments: + * * vote_type: the vote type (getting the role that got the most day votes, or the role that got the most mafia votes) + */ +/datum/mafia_controller/proc/get_vote_winner(vote_type) + var/list/tally = list() + for(var/votee in votes[vote_type]) + if(!tally[votes[vote_type][votee]]) + tally[votes[vote_type][votee]] = 1 + else + tally[votes[vote_type][votee]] += 1 + sortTim(tally,/proc/cmp_numeric_dsc,associative=TRUE) + return length(tally) ? tally[1] : null + +/** + * Returns a random person who voted for whatever vote (day vote, night kill vote) + * Arguments: + * * vote_type: vote type (getting a random day voter, or mafia night voter) + */ +/datum/mafia_controller/proc/get_random_voter(vote_type) + if(length(votes[vote_type])) + return pick(votes[vote_type]) + +/** + * Adds mutable appearances to people who get publicly voted on (so not night votes) showing how many people are picking them + * Arguments: + * * source: the body of the role getting the overlays + * * overlay_list: signal var passing the overlay list of the mob + */ +/datum/mafia_controller/proc/display_votes(atom/source, list/overlay_list) + if(phase != MAFIA_PHASE_VOTING) + return + var/v = get_vote_count(player_role_lookup[source],"Day") + var/mutable_appearance/MA = mutable_appearance('icons/obj/mafia.dmi',"vote_[v > 12 ? "over_12" : v]") + overlay_list += MA + +/** + * Called when the game is setting up, AFTER map is loaded but BEFORE the phase timers start. Creates and places each role's body and gives the correct player key + * + * Notably: + * * Toggles godmode so the mafia players cannot kill themselves + * * Adds signals for voting overlays, see display_votes proc + * * gives mafia panel + * * sends the greeting text (goals, role name, etc) + */ +/datum/mafia_controller/proc/create_bodies() + for(var/datum/mafia_role/role in all_roles) + var/mob/living/carbon/human/H = new(get_turf(role.assigned_landmark)) + H.equipOutfit(player_outfit) + H.status_flags |= GODMODE + RegisterSignal(H,COMSIG_ATOM_UPDATE_OVERLAYS,.proc/display_votes) + var/datum/action/innate/mafia_panel/mafia_panel = new(null,src) + mafia_panel.Grant(H) + var/client/player_client = GLOB.directory[role.player_key] + if(player_client) + player_client.prefs.copy_to(H) + if(H.dna.species.outfit_important_for_life) //plasmamen + H.set_species(/datum/species/human) + role.body = H + player_role_lookup[H] = role + H.key = role.player_key + role.greet() + +/datum/mafia_controller/ui_data(mob/user) + . = ..() + switch(phase) + if(MAFIA_PHASE_DAY,MAFIA_PHASE_VOTING,MAFIA_PHASE_JUDGEMENT) + .["phase"] = "Day [turn]" + if(MAFIA_PHASE_NIGHT) + .["phase"] = "Night [turn]" + else + .["phase"] = "No Game" + if(user.client?.holder) + .["admin_controls"] = TRUE //show admin buttons to start/setup/stop + if(phase == MAFIA_PHASE_JUDGEMENT) + .["judgement_phase"] = TRUE //show judgement section + else + .["judgement_phase"] = FALSE + var/datum/mafia_role/user_role = player_role_lookup[user] + if(user_role) + .["roleinfo"] = list("role" = user_role.name,"desc" = user_role.desc, "action_log" = user_role.role_notes, "hud_icon" = user_role.hud_icon, "revealed_icon" = user_role.revealed_icon) + var/actions = list() + for(var/action in user_role.actions) + if(user_role.validate_action_target(src,action,null)) + actions += action + .["actions"] = actions + .["role_theme"] = user_role.special_theme + else + var/list/lobby_data = list() + for(var/key in GLOB.mafia_signup + GLOB.mafia_bad_signup) + var/list/lobby_member = list() + lobby_member["name"] = key + lobby_member["status"] = "Ready" + if(key in GLOB.mafia_bad_signup) + lobby_member["status"] = "Disconnected" + lobby_member["spectating"] = "Ghost" + if(key in spectators) + lobby_member["spectating"] = "Spectator" + lobby_data += list(lobby_member) + .["lobbydata"] = lobby_data + var/list/player_data = list() + for(var/datum/mafia_role/R in all_roles) + var/list/player_info = list() + var/list/actions = list() + if(user_role) //not observer + for(var/action in user_role.targeted_actions) + if(user_role.validate_action_target(src,action,R)) + actions += action + //Awful snowflake, could use generalizing + if(phase == MAFIA_PHASE_VOTING) + player_info["votes"] = get_vote_count(R,"Day") + if(R.game_status == MAFIA_ALIVE && R != user_role) + actions += "Vote" + if(phase == MAFIA_PHASE_NIGHT && user_role.team == MAFIA_TEAM_MAFIA && R.game_status == MAFIA_ALIVE && R.team != MAFIA_TEAM_MAFIA) + actions += "Kill Vote" + player_info["name"] = R.body.real_name + player_info["ref"] = REF(R) + player_info["actions"] = actions + player_info["alive"] = R.game_status == MAFIA_ALIVE + player_data += list(player_info) + .["players"] = player_data + .["timeleft"] = next_phase_timer ? timeleft(next_phase_timer) : 0 + + //Not sure on this, should this info be visible + .["all_roles"] = current_setup_text + +/datum/mafia_controller/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/mafia), + ) + +/datum/mafia_controller/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + . = ..() + if(.) + return + var/datum/mafia_role/user_role = player_role_lookup[usr] + //Admin actions + if(usr.client?.holder) + switch(action) + if("new_game") + end_game() + basic_setup() + if("nuke") + end_game() + qdel(src) + if("next_phase") + var/datum/timedevent/timer = SStimer.timer_id_dict[next_phase_timer] + if(!timer.spent) + var/datum/callback/tc = timer.callBack + deltimer(next_phase_timer) + tc.InvokeAsync() + return TRUE + if("players_home") + var/list/failed = list() + for(var/datum/mafia_role/player in all_roles) + if(!player.body) + failed += player + continue + player.body.forceMove(get_turf(player.assigned_landmark)) + if(failed.len) + to_chat(usr, "List of players who no longer had a body (if you see this, the game is runtiming anyway so just hit \"New Game\" to end it)") + for(var/i in failed) + var/datum/mafia_role/fail = i + to_chat(usr, fail.player_key) + if("debug_setup") + var/list/debug_setup = list() + var/list/rolelist_dict = list() + var/done = FALSE + for(var/p in typesof(/datum/mafia_role)) + var/datum/mafia_role/path = p + rolelist_dict[initial(path.name) + " ([uppertext(initial(path.team))])"] = path + rolelist_dict = list("CANCEL", "FINISH") + rolelist_dict + while(!done) + to_chat(usr, "You have a total player count of [assoc_value_sum(debug_setup)] in this setup.") + var/chosen_role_name = input(usr,"Select a role!","Custom Setup Creation",rolelist_dict[1]) as null|anything in rolelist_dict + if(chosen_role_name == "CANCEL") + return + if(chosen_role_name == "FINISH") + break + var/found_path = rolelist_dict[chosen_role_name] + var/role_count = input(usr,"How many? Zero to cancel.","Custom Setup Creation",0) as null|num + if(role_count > 0) + debug_setup[found_path] = role_count + custom_setup = debug_setup + if("cancel_setup") + custom_setup = list() + switch(action) //both living and dead + if("mf_lookup") + var/role_lookup = params["atype"] + var/datum/mafia_role/helper + for(var/datum/mafia_role/role in all_roles) + if(role_lookup == role.name) + helper = role + break + helper.show_help(usr) + if(!user_role)//just the dead + var/client/C = ui.user.client + switch(action) + if("mf_signup") + if(!SSticker.HasRoundStarted()) + to_chat(usr, "Wait for the round to start.") + return + if(GLOB.mafia_signup[C.ckey]) + GLOB.mafia_signup -= C.ckey + to_chat(usr, "You unregister from Mafia.") + return + else + GLOB.mafia_signup[C.ckey] = C + to_chat(usr, "You sign up for Mafia.") + if(phase == MAFIA_PHASE_SETUP) + check_signups() + try_autostart() + if("mf_spectate") + if(C.ckey in spectators) + to_chat(usr, "You will no longer get messages from the game.") + spectators -= C.ckey + else + to_chat(usr, "You will now get messages from the game.") + spectators += C.ckey + if(user_role.game_status == MAFIA_DEAD) + return + //User actions (just living) + switch(action) + if("mf_action") + if(!user_role.actions.Find(params["atype"])) + return + user_role.handle_action(src,params["atype"],null) + return TRUE //vals for self-ui update + if("mf_targ_action") + var/datum/mafia_role/target = locate(params["target"]) in all_roles + if(!istype(target)) + return + switch(params["atype"]) + if("Vote") + if(phase != MAFIA_PHASE_VOTING) + return + vote_for(user_role,target,vote_type="Day") + if("Kill Vote") + if(phase != MAFIA_PHASE_NIGHT || user_role.team != MAFIA_TEAM_MAFIA) + return + vote_for(user_role,target,"Mafia", MAFIA_TEAM_MAFIA) + to_chat(user_role.body,"You will vote for [target.body.real_name] for tonights killing.") + else + if(!user_role.targeted_actions.Find(params["atype"])) + return + if(!user_role.validate_action_target(src,params["atype"],target)) + return + user_role.handle_action(src,params["atype"],target) + return TRUE + if(user_role != on_trial) + switch(action) + if("vote_abstain") + if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_abstain_votes)) + return + to_chat(user_role.body,"You have decided to abstain.") + judgement_innocent_votes -= user_role + judgement_guilty_votes -= user_role + judgement_abstain_votes += user_role + if("vote_innocent") + if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_innocent_votes)) + return + to_chat(user_role.body,"Your vote on [on_trial.body.real_name] submitted as INNOCENT!") + judgement_abstain_votes -= user_role//no fakers, and... + judgement_guilty_votes -= user_role//no radical centrism + judgement_innocent_votes += user_role + if("vote_guilty") + if(phase != MAFIA_PHASE_JUDGEMENT || (user_role in judgement_guilty_votes)) + return + to_chat(user_role.body,"Your vote on [on_trial.body.real_name] submitted as GUILTY!") + judgement_abstain_votes -= user_role//no fakers, and... + judgement_innocent_votes -= user_role//no radical centrism + judgement_guilty_votes += user_role + +/datum/mafia_controller/ui_state(mob/user) + return GLOB.always_state + +/datum/mafia_controller/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, null) + if(!ui) + ui = new(user, src, "MafiaPanel") + ui.set_autoupdate(FALSE) + ui.open() + +/proc/assoc_value_sum(list/L) + . = 0 + for(var/key in L) + . += L[key] + +/** + * Returns a semirandom setup, with... + * Town, Two invest roles, one protect role, sometimes a misc role, and the rest assistants for town. + * Mafia, 2 normal mafia and one special. + * Neutral, two disruption roles, sometimes one is a killing. + * + * See _defines.dm in the mafia folder for a rundown on what these groups of roles include. + */ +/datum/mafia_controller/proc/generate_random_setup() + var/invests_left = 2 + var/protects_left = 1 + var/miscs_left = prob(35) + var/mafiareg_left = 2 + var/mafiaspe_left = 1 + var/killing_role = prob(50) + var/disruptors = killing_role ? 1 : 2 //still required to calculate overflow + var/overflow_left = max_player - (invests_left + protects_left + miscs_left + mafiareg_left + mafiaspe_left + killing_role + disruptors) + + var/list/random_setup = list() + for(var/i in 1 to max_player) //should match the number of roles to add + if(overflow_left) + add_setup_role(random_setup, TOWN_OVERFLOW) + overflow_left-- + else if(invests_left) + add_setup_role(random_setup, TOWN_INVEST) + invests_left-- + else if(protects_left) + add_setup_role(random_setup, TOWN_PROTECT) + protects_left-- + else if(miscs_left) + add_setup_role(random_setup, TOWN_MISC) + miscs_left-- + else if(mafiareg_left) + add_setup_role(random_setup, MAFIA_REGULAR) + mafiareg_left-- + else if(mafiaspe_left) + add_setup_role(random_setup, MAFIA_SPECIAL) + mafiaspe_left-- + else if(killing_role) + add_setup_role(random_setup, NEUTRAL_KILL) + killing_role-- + else + add_setup_role(random_setup, NEUTRAL_DISRUPT) + return random_setup + +/** + * Helper proc that adds a random role of a type to a setup. if it doesn't exist in the setup, it adds the path to the list and otherwise bumps the path in the list up one + */ +/datum/mafia_controller/proc/add_setup_role(setup_list, wanted_role_type) + var/list/role_type_paths = list() + for(var/path in typesof(/datum/mafia_role)) + var/datum/mafia_role/instance = path + if(initial(instance.role_type) == wanted_role_type) + role_type_paths += instance + + var/mafia_path = pick(role_type_paths) + var/datum/mafia_role/mafia_path_type = mafia_path + var/found_role + for(var/searched_path in setup_list) + var/datum/mafia_role/searched_path_type = searched_path + if(initial(mafia_path_type.name) == initial(searched_path_type.name)) + found_role = searched_path + break + if(found_role) + setup_list[found_role] += 1 + return + setup_list[mafia_path] = 1 + +/** + * Called when enough players have signed up to fill a setup. DOESN'T NECESSARILY MEAN THE GAME WILL START. + * + * Checks for a custom setup, if so gets the required players from that and if not it sets the player requirement to required_player(max_player) and generates one IF basic setup starts a game. + * Checks if everyone signed up is an observer, and is still connected. If people aren't, they're removed from the list. + * If there aren't enough players post sanity, it aborts. otherwise, it selects enough people for the game and starts preparing the game for real. + */ +/datum/mafia_controller/proc/basic_setup() + var/req_players + var/list/setup = custom_setup + if(!setup.len) + req_players = required_player //max_player + else + req_players = assoc_value_sum(setup) + + //final list for all the players who will be in this game + var/list/filtered_keys = list() + //cuts invalid players from signups (disconnected/not a ghost) + var/list/possible_keys = list() + for(var/key in GLOB.mafia_signup) + if(GLOB.directory[key]) + var/client/C = GLOB.directory[key] + if(isobserver(C.mob)) + possible_keys += key + continue + GLOB.mafia_signup -= key //not valid to play when we checked so remove them from signups + + //if there were not enough players, don't start. we already trimmed the list to now hold only valid signups + if(length(possible_keys) < req_players) + return + else //hacky implementation of max players + req_players = clamp(length(possible_keys), 1, max_player) + + //if there were too many players, still start but only make filtered keys as big as it needs to be (cut excess) + //also removes people who do get into final player list from the signup so they have to sign up again when game ends + for(var/i in 1 to req_players) + var/chosen_key = pick_n_take(possible_keys) + filtered_keys += chosen_key + GLOB.mafia_signup -= chosen_key + //small message about not getting into this game for clarity on why they didn't get in + for(var/unpicked in possible_keys) + var/client/unpicked_client = GLOB.directory[unpicked] + to_chat(unpicked_client, "Sorry, the starting mafia game has too many players and you were not picked.") + to_chat(unpicked_client, "You're still signed up, getting messages from the current round, and have another chance to join when the one starting now finishes.") + + if(!setup.len) //don't actually have one yet, so generate a max player random setup. it's good to do this here instead of above so it doesn't generate one every time a game could possibly start. + setup = generate_random_setup() + prepare_game(setup,filtered_keys) + start_game() + +/** + * Called when someone signs up, and sees if there are enough people in the signup list to begin. + * + * Only checks if everyone is actually valid to start (still connected and an observer) if there are enough players (basic_setup) + */ +/datum/mafia_controller/proc/try_autostart() + if(phase != MAFIA_PHASE_SETUP) // || !(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME)) + return + if(GLOB.mafia_signup.len >= max_player || GLOB.mafia_signup.len >= required_player|| custom_setup.len)//enough people to try and make something (or debug mode) + basic_setup() + +/** + * Filters inactive player into a different list until they reconnect, and removes players who are no longer ghosts. + * + * If a disconnected player gets a non-ghost mob and reconnects, they will be first put back into mafia_signup then filtered by that. + */ +/datum/mafia_controller/proc/check_signups() + for(var/bad_key in GLOB.mafia_bad_signup) + if(GLOB.directory[bad_key])//they have reconnected if we can search their key and get a client + GLOB.mafia_bad_signup -= bad_key + GLOB.mafia_signup += bad_key + for(var/key in GLOB.mafia_signup) + var/client/C = GLOB.directory[key] + if(!C)//vice versa but in a variable we use later + GLOB.mafia_signup -= key + GLOB.mafia_bad_signup += key + if(!isobserver(C.mob)) + //they are back to playing the game, remove them from the signups + GLOB.mafia_signup -= key + +/datum/action/innate/mafia_panel + name = "Mafia Panel" + desc = "Use this to play." + icon_icon = 'icons/obj/mafia.dmi' + button_icon_state = "board" + var/datum/mafia_controller/parent + +/datum/action/innate/mafia_panel/New(Target,mf) + . = ..() + parent = mf + +/datum/action/innate/mafia_panel/Activate() + parent.ui_interact(owner) + +/** + * Creates the global datum for playing mafia games, destroys the last if that's required and returns the new. + */ +/proc/create_mafia_game() + if(GLOB.mafia_game) + QDEL_NULL(GLOB.mafia_game) + var/datum/mafia_controller/MF = new() + return MF diff --git a/code/modules/mafia/map_pieces.dm b/code/modules/mafia/map_pieces.dm new file mode 100644 index 0000000000..3339c596b4 --- /dev/null +++ b/code/modules/mafia/map_pieces.dm @@ -0,0 +1,79 @@ +/obj/effect/landmark/mafia_game_area //locations where mafia will be loaded by the datum + name = "Mafia Area Spawn" + var/game_id = "mafia" + +/obj/effect/landmark/mafia + name = "Mafia Player Spawn" + var/game_id = "mafia" + +/obj/effect/landmark/mafia/town_center + name = "Mafia Town Center" + +//for ghosts/admins +/obj/mafia_game_board + name = "Mafia Game Board" + icon = 'icons/obj/mafia.dmi' + icon_state = "board" + anchored = TRUE + var/game_id = "mafia" + var/datum/mafia_controller/MF + +/obj/mafia_game_board/attack_ghost(mob/user) + . = ..() + if(!MF) + MF = GLOB.mafia_game + if(!MF) + MF = create_mafia_game() + MF.ui_interact(user) + +/area/mafia + name = "Mafia Minigame" + icon_state = "mafia" + dynamic_lighting = DYNAMIC_LIGHTING_DISABLED + requires_power = FALSE + has_gravity = STANDARD_GRAVITY + flags_1 = NONE + // block_suicide = TRUE + +/datum/map_template/mafia + var/description = "" + +/datum/map_template/mafia/summerball + name = "Summerball 2020" + description = "The original, the OG. The 2020 Summer ball was where mafia came from, with this map." + mappath = "_maps/map_files/Mafia/mafia_ball.dmm" + +/datum/map_template/mafia/syndicate + name = "Syndicate Megastation" + description = "Yes, it's a very confusing day at the Megastation. Will the syndicate conflict resolution operatives succeed?" + mappath = "_maps/map_files/Mafia/mafia_syndie.dmm" + +/datum/map_template/mafia/lavaland + name = "Lavaland Excursion" + description = "The station has no idea what's going down on lavaland right now, we got changelings... traitors, and worst of all... lawyers roleblocking you every night." + mappath = "_maps/map_files/Mafia/mafia_lavaland.dmm" + +/datum/map_template/mafia/ufo + name = "Alien Mothership" + description = "The haunted ghost UFO tour has gone south and now it's up to our fine townies and scare seekers to kill the actual real alien changelings..." + mappath = "_maps/map_files/Mafia/mafia_ayylmao.dmm" + +/datum/map_template/mafia/spider_clan + name = "Spider Clan Kidnapping" + description = "New and improved spider clan kidnappings are a lot less boring and have a lot more lynching. Damn westaboos!" + mappath = "_maps/map_files/Mafia/mafia_spiderclan.dmm" + +/datum/map_template/mafia/snowy + name = "Snowdin" + description = "Based off of the icey moon map of the same name, the guy who reworked it pretty much did it for nothing since away missions are disabled but at least he'll get this...?" + mappath = "_maps/map_files/Mafia/mafia_snow.dmm" + +/datum/map_template/mafia/gothic + name = "Vampire's Castle" + description = "Vampires and changelings clash to find out who's the superior bloodsucking monster in this creepy castle map." + mappath = "_maps/map_files/Mafia/mafia_gothic.dmm" + +/datum/map_template/mafia/reebe + name = "Reebe" + description = "Trouble in Reebe station! Copypaste guranteed by ClockCo™" + mappath = "_maps/map_files/Mafia/mafia_reebe.dmm" diff --git a/code/modules/mafia/outfits.dm b/code/modules/mafia/outfits.dm new file mode 100644 index 0000000000..bbc72bd120 --- /dev/null +++ b/code/modules/mafia/outfits.dm @@ -0,0 +1,108 @@ + +//what people wear unrevealed + +/datum/outfit/mafia + name = "Mafia Game Outfit" + uniform = /obj/item/clothing/under/color/grey + shoes = /obj/item/clothing/shoes/sneakers/black + +//town + +/datum/outfit/mafia/assistant + name = "Mafia Assistant" + + uniform = /obj/item/clothing/under/color/rainbow + +/datum/outfit/mafia/detective + name = "Mafia Detective" + + uniform = /obj/item/clothing/under/rank/security/detective + // neck = /obj/item/clothing/neck/tie/detective + shoes = /obj/item/clothing/shoes/sneakers/brown + suit = /obj/item/clothing/suit/det_suit + gloves = /obj/item/clothing/gloves/color/black + head = /obj/item/clothing/head/fedora/det_hat + mask = /obj/item/clothing/mask/cigarette + +/datum/outfit/mafia/psychologist + name = "Mafia Psychologist" + + uniform = /obj/item/clothing/under/suit/black + shoes = /obj/item/clothing/shoes/laceup + +/datum/outfit/mafia/md + name = "Mafia Medical Doctor" + + uniform = /obj/item/clothing/under/rank/medical/doctor + shoes = /obj/item/clothing/shoes/sneakers/white + suit = /obj/item/clothing/suit/toggle/labcoat + +/datum/outfit/mafia/chaplain + name = "Mafia Chaplain" + + uniform = /obj/item/clothing/under/rank/civilian/chaplain + +/datum/outfit/mafia/lawyer + name = "Mafia Lawyer" + + uniform = /obj/item/clothing/under/rank/civilian/lawyer/bluesuit + suit = /obj/item/clothing/suit/toggle/lawyer + shoes = /obj/item/clothing/shoes/laceup + +/datum/outfit/mafia/hop + name = "Mafia Head of Personnel" + + uniform = /obj/item/clothing/under/rank/civilian/head_of_personnel + suit = /obj/item/clothing/suit/armor/vest/alt + shoes = /obj/item/clothing/shoes/sneakers/brown + head = /obj/item/clothing/head/hopcap + glasses = /obj/item/clothing/glasses/sunglasses + +//mafia + +/datum/outfit/mafia/changeling + name = "Mafia Changeling" + + head = /obj/item/clothing/head/helmet/changeling + suit = /obj/item/clothing/suit/armor/changeling + +//solo + +/datum/outfit/mafia/fugitive + name = "Mafia Fugitive" + + uniform = /obj/item/clothing/under/rank/prisoner + shoes = /obj/item/clothing/shoes/sneakers/orange + +/datum/outfit/mafia/obsessed + name = "Mafia Obsessed" + uniform = /obj/item/clothing/under/misc/overalls + shoes = /obj/item/clothing/shoes/sneakers/white + gloves = /obj/item/clothing/gloves/color/latex + mask = /obj/item/clothing/mask/surgical + suit = /obj/item/clothing/suit/apron + +/datum/outfit/mafia/obsessed/post_equip(mob/living/carbon/human/H) + for(var/obj/item/carried_item in H.get_equipped_items(TRUE)) + carried_item.add_mob_blood(H)//Oh yes, there will be blood... + H.regenerate_icons() + +/datum/outfit/mafia/clown + name = "Mafia Clown" + + uniform = /obj/item/clothing/under/rank/civilian/clown + shoes = /obj/item/clothing/shoes/clown_shoes + mask = /obj/item/clothing/mask/gas/clown_hat + +/datum/outfit/mafia/traitor + name = "Mafia Traitor" + + mask = /obj/item/clothing/mask/gas/syndicate + uniform = /obj/item/clothing/under/syndicate/tacticool + shoes = /obj/item/clothing/shoes/jackboots + +/datum/outfit/mafia/nightmare + name = "Mafia Nightmare" + + uniform = null + shoes = null diff --git a/code/modules/mafia/roles.dm b/code/modules/mafia/roles.dm new file mode 100644 index 0000000000..2461a93976 --- /dev/null +++ b/code/modules/mafia/roles.dm @@ -0,0 +1,705 @@ +/datum/mafia_role + var/name = "Assistant" + var/desc = "You are a crewmember without any special abilities." + var/win_condition = "kill all mafia and solo killing roles." + var/team = MAFIA_TEAM_TOWN + ///how the random setup chooses which roles get put in + var/role_type = TOWN_OVERFLOW + + var/player_key + var/mob/living/carbon/human/body + var/obj/effect/landmark/mafia/assigned_landmark + + ///how many votes submitted when you vote. + var/vote_power = 1 + var/detect_immune = FALSE + var/revealed = FALSE + var/datum/outfit/revealed_outfit = /datum/outfit/mafia/assistant //the assistants need a special path to call out they were in fact assistant, everything else can just use job equipment + //action = uses + var/list/actions = list() + var/list/targeted_actions = list() + //what the role gets when it wins a game + // var/winner_award = /datum/award/achievement/mafia/assistant + + //so mafia have to also kill them to have a majority + var/solo_counts_as_town = FALSE //(don't set this for town) + var/game_status = MAFIA_ALIVE + + ///icon state in the mafia dmi of the hud of the role, used in the mafia ui + var/hud_icon = "hudassistant" + ///icon state in the mafia dmi of the hud of the role, used in the mafia ui + var/revealed_icon = "assistant" + ///set this to something cool for antagonists and their window will look different + var/special_theme + + var/list/role_notes = list() + + +/datum/mafia_role/New(datum/mafia_controller/game) + . = ..() + +/datum/mafia_role/proc/kill(datum/mafia_controller/game,lynch=FALSE) + if(SEND_SIGNAL(src,COMSIG_MAFIA_ON_KILL,game,lynch) & MAFIA_PREVENT_KILL) + return FALSE + game_status = MAFIA_DEAD + body.death() + if(lynch) + reveal_role(game, verbose = TRUE) + if(!(player_key in game.spectators)) //people who played will want to see the end of the game more often than not + game.spectators += player_key + return TRUE + +/datum/mafia_role/Destroy(force, ...) + QDEL_NULL(body) + . = ..() + +/datum/mafia_role/proc/greet() + SEND_SOUND(body, 'sound/ambience/ambifailure.ogg') + to_chat(body,"You are the [name].") + to_chat(body,"[desc]") + switch(team) + if(MAFIA_TEAM_MAFIA) + to_chat(body,"You and your co-conspirators win if you outnumber crewmembers.") + if(MAFIA_TEAM_TOWN) + to_chat(body,"You are a crewmember. Find out and lynch the changelings!") + if(MAFIA_TEAM_SOLO) + to_chat(body,"You are not aligned to town or mafia. Accomplish your own objectives!") + to_chat(body, "Be sure to read the wiki page to learn more, if you have no idea what's going on.") + +/datum/mafia_role/proc/reveal_role(datum/mafia_controller/game, verbose = FALSE) + if(revealed) + return + if(verbose) + game.send_message("It is revealed that the true role of [body] [game_status == MAFIA_ALIVE ? "is" : "was"] [name]!") + var/list/oldoutfit = body.get_equipped_items() + for(var/thing in oldoutfit) + qdel(thing) + special_reveal_equip(game) + body.equipOutfit(revealed_outfit) + revealed = TRUE + +/datum/mafia_role/proc/special_reveal_equip(datum/mafia_controller/game) + return + +/datum/mafia_role/proc/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target) + return + +/datum/mafia_role/proc/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target) + if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,action,target) & MAFIA_PREVENT_ACTION) + return FALSE + return TRUE + +/datum/mafia_role/proc/add_note(note) + role_notes += note + +/datum/mafia_role/proc/check_total_victory(alive_town, alive_mafia) //solo antags can win... solo. + return FALSE + +/datum/mafia_role/proc/block_team_victory(alive_town, alive_mafia) //solo antags can also block team wins. + return FALSE + +/datum/mafia_role/proc/show_help(clueless) + var/list/result = list() + var/team_desc = "" + var/team_span = "" + var/the = TRUE + switch(team) + if(MAFIA_TEAM_TOWN) + team_desc = "Town" + team_span = "nicegreen" + if(MAFIA_TEAM_MAFIA) + team_desc = "Mafia" + team_span = "red" + if(MAFIA_TEAM_SOLO) + team_desc = "Nobody" + team_span = "comradio" + the = FALSE + result += "The [name] is aligned with [the ? "the " : ""][team_desc]" + result += "\"[desc]\"" + result += "[name] wins when they [win_condition]" + to_chat(clueless, result.Join("
    ")) + +/datum/mafia_role/detective + name = "Detective" + desc = "You can investigate a single person each night to learn their team." + revealed_outfit = /datum/outfit/mafia/detective + role_type = TOWN_INVEST + // winner_award = /datum/award/achievement/mafia/detective + + hud_icon = "huddetective" + revealed_icon = "detective" + + targeted_actions = list("Investigate") + + var/datum/mafia_role/current_investigation + +/datum/mafia_role/detective/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/investigate) + +/datum/mafia_role/detective/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target) + . = ..() + if(!.) + return + return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src + +/datum/mafia_role/detective/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target) + if(!target || target.game_status != MAFIA_ALIVE) + to_chat(body,"You can only investigate alive people.") + return + to_chat(body,"You will investigate [target.body.real_name] tonight.") + current_investigation = target + +/datum/mafia_role/detective/proc/investigate(datum/mafia_controller/game) + var/datum/mafia_role/target = current_investigation + if(target) + if(target.detect_immune) + to_chat(body,"Your investigations reveal that [target.body.real_name] is a true member of the station.") + add_note("N[game.turn] - [target.body.real_name] - Town") + else + var/team_text + var/fluff + switch(target.team) + if(MAFIA_TEAM_TOWN) + team_text = "Town" + fluff = "a true member of the station." + if(MAFIA_TEAM_MAFIA) + team_text = "Mafia" + fluff = "an unfeeling, hideous changeling!" + if(MAFIA_TEAM_SOLO) + team_text = "Solo" + fluff = "a rogue, with their own objectives..." + to_chat(body,"Your investigations reveal that [target.body.real_name] is [fluff]") + add_note("N[game.turn] - [target.body.real_name] - [team_text]") + current_investigation = null + +/datum/mafia_role/psychologist + name = "Psychologist" + desc = "You can visit someone ONCE PER GAME to reveal their true role in the morning!" + revealed_outfit = /datum/outfit/mafia/psychologist + role_type = TOWN_INVEST + // winner_award = /datum/award/achievement/mafia/psychologist + + hud_icon = "hudpsychologist" + revealed_icon = "psychologist" + + targeted_actions = list("Reveal") + var/datum/mafia_role/current_target + var/can_use = TRUE + +/datum/mafia_role/psychologist/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/therapy_reveal) + +/datum/mafia_role/psychologist/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!. || !can_use || game.phase == MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE || target.revealed || target == src) + return FALSE + +/datum/mafia_role/psychologist/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + to_chat(body,"You will reveal [target.body.real_name] tonight.") + current_target = target + +/datum/mafia_role/psychologist/proc/therapy_reveal(datum/mafia_controller/game) + if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,"reveal",current_target) & MAFIA_PREVENT_ACTION || game_status != MAFIA_ALIVE) //Got lynched or roleblocked by a lawyer. + current_target = null + if(current_target) + add_note("N[game.turn] - [current_target.body.real_name] - Revealed true identity") + to_chat(body,"You have revealed the true nature of the [current_target]!") + current_target.reveal_role(game, verbose = TRUE) + current_target = null + can_use = FALSE + +/datum/mafia_role/chaplain + name = "Chaplain" + desc = "You can communicate with spirits of the dead each night to discover dead crewmember roles." + revealed_outfit = /datum/outfit/mafia/chaplain + role_type = TOWN_INVEST + hud_icon = "hudchaplain" + revealed_icon = "chaplain" + // winner_award = /datum/award/achievement/mafia/chaplain + + targeted_actions = list("Pray") + var/current_target + +/datum/mafia_role/chaplain/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/commune) + +/datum/mafia_role/chaplain/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!.) + return + return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_DEAD && target != src && !target.revealed + +/datum/mafia_role/chaplain/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + to_chat(body,"You will commune with the spirit of [target.body.real_name] tonight.") + current_target = target + +/datum/mafia_role/chaplain/proc/commune(datum/mafia_controller/game) + var/datum/mafia_role/target = current_target + if(target) + to_chat(body,"You invoke spirit of [target.body.real_name] and learn their role was [target.name].") + add_note("N[game.turn] - [target.body.real_name] - [target.name]") + current_target = null + +/datum/mafia_role/md + name = "Medical Doctor" + desc = "You can protect a single person each night from killing." + revealed_outfit = /datum/outfit/mafia/md // /mafia <- outfit must be readded (just make a new mafia outfits file for all of these) + role_type = TOWN_PROTECT + hud_icon = "hudmedicaldoctor" + revealed_icon = "medicaldoctor" + // winner_award = /datum/award/achievement/mafia/md + + targeted_actions = list("Protect") + var/datum/mafia_role/current_protected + +/datum/mafia_role/md/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/protect) + RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/end_protection) + +/datum/mafia_role/md/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target) + . = ..() + if(!.) + return + if(target.name == "Head of Personnel" && target.revealed) + return FALSE + return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src + +/datum/mafia_role/md/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target) + if(!target || target.game_status != MAFIA_ALIVE) + to_chat(body,"You can only protect alive people.") + return + to_chat(body,"You will protect [target.body.real_name] tonight.") + current_protected = target + +/datum/mafia_role/md/proc/protect(datum/mafia_controller/game) + if(current_protected) + RegisterSignal(current_protected,COMSIG_MAFIA_ON_KILL,.proc/prevent_kill) + add_note("N[game.turn] - Protected [current_protected.body.real_name]") + +/datum/mafia_role/md/proc/prevent_kill(datum/source) + to_chat(body,"The person you protected tonight was attacked!") + to_chat(current_protected.body,"You were attacked last night, but someone nursed you back to life!") + return MAFIA_PREVENT_KILL + +/datum/mafia_role/md/proc/end_protection(datum/mafia_controller/game) + if(current_protected) + UnregisterSignal(current_protected,COMSIG_MAFIA_ON_KILL) + current_protected = null + +/datum/mafia_role/lawyer + name = "Lawyer" + desc = "You can choose a person during the day to provide extensive legal advice to during the night, preventing night actions." + revealed_outfit = /datum/outfit/mafia/lawyer + role_type = TOWN_PROTECT + hud_icon = "hudlawyer" + revealed_icon = "lawyer" + // winner_award = /datum/award/achievement/mafia/lawyer + + targeted_actions = list("Advise") + var/datum/mafia_role/current_target + +/datum/mafia_role/lawyer/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/roleblock_text) + RegisterSignal(game,COMSIG_MAFIA_NIGHT_START,.proc/try_to_roleblock) + RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/release) + +/datum/mafia_role/lawyer/proc/roleblock_text(datum/mafia_controller/game) + if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,"roleblock",current_target) & MAFIA_PREVENT_ACTION || game_status != MAFIA_ALIVE) //Got lynched or roleblocked by another lawyer. + current_target = null + if(current_target) + to_chat(current_target.body,"YOU HAVE BEEN BLOCKED! YOU CANNOT PERFORM ANY ACTIONS TONIGHT.") + add_note("N[game.turn] - [current_target.body.real_name] - Blocked") + +/datum/mafia_role/lawyer/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!.) + return FALSE + if(game.phase == MAFIA_PHASE_NIGHT) + return FALSE + if(target.game_status != MAFIA_ALIVE) + return FALSE + +/datum/mafia_role/lawyer/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(target == current_target) + current_target = null + to_chat(body,"You have decided against blocking anyone tonight.") + else + current_target = target + to_chat(body,"You will block [target.body.real_name] tonight.") + +/datum/mafia_role/lawyer/proc/try_to_roleblock(datum/mafia_controller/game) + if(current_target) + RegisterSignal(current_target,COMSIG_MAFIA_CAN_PERFORM_ACTION, .proc/prevent_action) + +/datum/mafia_role/lawyer/proc/release(datum/mafia_controller/game) + . = ..() + if(current_target) + UnregisterSignal(current_target, COMSIG_MAFIA_CAN_PERFORM_ACTION) + current_target = null + +/datum/mafia_role/lawyer/proc/prevent_action(datum/source) + if(game_status == MAFIA_ALIVE) //in case we got killed while imprisoning sk - bad luck edge + return MAFIA_PREVENT_ACTION + +/datum/mafia_role/hop + name = "Head of Personnel" + desc = "You can reveal yourself once per game, tripling your vote power but becoming unable to be protected!" + revealed_outfit = /datum/outfit/mafia/hop + role_type = TOWN_MISC + hud_icon = "hudheadofpersonnel" + revealed_icon = "headofpersonnel" + // winner_award = /datum/award/achievement/mafia/hop + + targeted_actions = list("Reveal") + +/datum/mafia_role/hop/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!. || game.phase == MAFIA_PHASE_NIGHT || game.turn == 1 || target.game_status != MAFIA_ALIVE || target != src || revealed) + return FALSE + +/datum/mafia_role/hop/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + reveal_role(game, TRUE) + vote_power = 2 + +///MAFIA ROLES/// only one until i rework this to allow more, they're the "anti-town" working to kill off townies to win + +/datum/mafia_role/mafia + name = "Changeling" + desc = "You're a member of the changeling hive. Use ':j' talk prefix to talk to your fellow lings." + team = MAFIA_TEAM_MAFIA + role_type = MAFIA_REGULAR + hud_icon = "hudchangeling" + revealed_icon = "changeling" + // winner_award = /datum/award/achievement/mafia/changeling + + revealed_outfit = /datum/outfit/mafia/changeling + special_theme = "syndicate" + win_condition = "become majority over the town and no solo killing role can stop them." + +/datum/mafia_role/mafia/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/mafia_text) + +/datum/mafia_role/mafia/proc/mafia_text(datum/mafia_controller/source) + to_chat(body,"Vote for who to kill tonight. The killer will be chosen randomly from voters.") + +//better detective for mafia +/datum/mafia_role/mafia/thoughtfeeder + name = "Thoughtfeeder" + desc = "You're a changeling variant that feeds on the memories of others. Use ':j' talk prefix to talk to your fellow lings, and visit people at night to learn their role." + role_type = MAFIA_SPECIAL + hud_icon = "hudthoughtfeeder" + revealed_icon = "thoughtfeeder" + // winner_award = /datum/award/achievement/mafia/thoughtfeeder + + targeted_actions = list("Learn Role") + var/datum/mafia_role/current_investigation + +/datum/mafia_role/mafia/thoughtfeeder/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_NIGHT_ACTION_PHASE,.proc/investigate) + +/datum/mafia_role/mafia/thoughtfeeder/validate_action_target(datum/mafia_controller/game,action,datum/mafia_role/target) + . = ..() + if(!.) + return + return game.phase == MAFIA_PHASE_NIGHT && target.game_status == MAFIA_ALIVE && target != src + +/datum/mafia_role/mafia/thoughtfeeder/handle_action(datum/mafia_controller/game,action,datum/mafia_role/target) + to_chat(body,"You will feast on the memories of [target.body.real_name] tonight.") + current_investigation = target + +/datum/mafia_role/mafia/thoughtfeeder/proc/investigate(datum/mafia_controller/game) + var/datum/mafia_role/target = current_investigation + current_investigation = null + if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,game,"thoughtfeed",target) & MAFIA_PREVENT_ACTION) + to_chat(body,"You were unable to investigate [target.body.real_name].") + add_note("N[game.turn] - [target.body.real_name] - Unable to investigate") + return + if(target) + if(target.detect_immune) + to_chat(body,"[target.body.real_name]'s memories reveal that they are the Assistant.") + add_note("N[game.turn] - [target.body.real_name] - Assistant") + else + to_chat(body,"[target.body.real_name]'s memories reveal that they are the [target.name].") + add_note("N[game.turn] - [target.body.real_name] - [target.name]") + + +///SOLO ROLES/// they range from anomalous factors to deranged killers that try to win alone. + +/datum/mafia_role/traitor + name = "Traitor" + desc = "You're a solo traitor. You are immune to night kills, can kill every night and you win by outnumbering everyone else." + win_condition = "kill everyone." + team = MAFIA_TEAM_SOLO + role_type = NEUTRAL_KILL + // winner_award = /datum/award/achievement/mafia/traitor + + targeted_actions = list("Night Kill") + revealed_outfit = /datum/outfit/mafia/traitor + + hud_icon = "hudtraitor" + revealed_icon = "traitor" + special_theme = "neutral" + + var/datum/mafia_role/current_victim + +/datum/mafia_role/traitor/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/nightkill_immunity) + RegisterSignal(game,COMSIG_MAFIA_NIGHT_KILL_PHASE,.proc/try_to_kill) + +/datum/mafia_role/traitor/check_total_victory(alive_town, alive_mafia) //serial killers just want teams dead + return alive_town + alive_mafia <= 1 + +/datum/mafia_role/traitor/block_team_victory(alive_town, alive_mafia) //no team can win until they're dead + return TRUE //while alive, town AND mafia cannot win (though since mafia know who is who it's pretty easy to win from that point) + +/datum/mafia_role/traitor/proc/nightkill_immunity(datum/source,datum/mafia_controller/game,lynch) + if(game.phase == MAFIA_PHASE_NIGHT && !lynch) + to_chat(body,"You were attacked, but they'll have to try harder than that to put you down.") + return MAFIA_PREVENT_KILL + +/datum/mafia_role/traitor/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!.) + return FALSE + if(game.phase != MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE || target == src) + return FALSE + +/datum/mafia_role/traitor/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + current_victim = target + to_chat(body,"You will attempt to kill [target.body.real_name] tonight.") + +/datum/mafia_role/traitor/proc/try_to_kill(datum/mafia_controller/source) + var/datum/mafia_role/target = current_victim + current_victim = null + if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,source,"traitor kill",target) & MAFIA_PREVENT_ACTION) + return + if(game_status == MAFIA_ALIVE && target && target.game_status == MAFIA_ALIVE) + if(!target.kill(source)) + to_chat(body,"Your attempt at killing [target.body] was prevented!") + +/datum/mafia_role/nightmare + name = "Nightmare" + desc = "You're a solo monster that cannot be detected by detective roles. You can flicker lights of another room each night. You can instead decide to hunt, killing everyone in a flickering room. Kill everyone to win." + win_condition = "kill everyone." + revealed_outfit = /datum/outfit/mafia/nightmare + detect_immune = TRUE + team = MAFIA_TEAM_SOLO + role_type = NEUTRAL_KILL + special_theme = "neutral" + hud_icon = "hudnightmare" + revealed_icon = "nightmare" + // winner_award = /datum/award/achievement/mafia/nightmare + + targeted_actions = list("Flicker", "Hunt") + var/list/flickering = list() + var/datum/mafia_role/flicker_target + +/datum/mafia_role/nightmare/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_NIGHT_KILL_PHASE,.proc/flicker_or_hunt) + +/datum/mafia_role/nightmare/check_total_victory(alive_town, alive_mafia) //nightmares just want teams dead + return alive_town + alive_mafia <= 1 + +/datum/mafia_role/nightmare/block_team_victory(alive_town, alive_mafia) //no team can win until they're dead + return TRUE //while alive, town AND mafia cannot win (though since mafia know who is who it's pretty easy to win from that point) + +/datum/mafia_role/nightmare/special_reveal_equip() + body.underwear = "Nude" + body.undershirt = "Nude" + body.socks = "Nude" + body.set_species(/datum/species/shadow) + body.update_body() + +/datum/mafia_role/nightmare/validate_action_target(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!. || game.phase != MAFIA_PHASE_NIGHT || target.game_status != MAFIA_ALIVE) + return FALSE + if(action == "Flicker") + return target != src && !(target in flickering) + return target == src + +/datum/mafia_role/nightmare/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(target == flicker_target) + to_chat(body,"You will do nothing tonight.") + flicker_target = null + flicker_target = target + if(action == "Flicker") + to_chat(body,"You will attempt to flicker [target.body.real_name]'s room tonight.") + else + to_chat(body,"You will hunt everyone in a flickering room down tonight.") + +/datum/mafia_role/nightmare/proc/flicker_or_hunt(datum/mafia_controller/source) + if(game_status != MAFIA_ALIVE || !flicker_target) + return + if(SEND_SIGNAL(src,COMSIG_MAFIA_CAN_PERFORM_ACTION,source,"nightmare actions",flicker_target) & MAFIA_PREVENT_ACTION) + to_chat(flicker_target.body, "Your actions were prevented!") + return + var/datum/mafia_role/target = flicker_target + flicker_target = null + if(target != src) //flicker instead of hunt + to_chat(target.body, "The lights begin to flicker and dim. You're in danger.") + flickering += target + return + for(var/r in flickering) + var/datum/mafia_role/role = r + if(role && role.game_status == MAFIA_ALIVE) + to_chat(role.body, "A shadowy monster appears out of the darkness!") + role.kill(source) + flickering -= role + +//just helps read better +#define FUGITIVE_NOT_PRESERVING 0//will not become night immune tonight +#define FUGITIVE_WILL_PRESERVE 1 //will become night immune tonight + +/datum/mafia_role/fugitive + name = "Fugitive" + desc = "You're on the run. You can become immune to night kills exactly twice, and you win by surviving to the end of the game with anyone." + win_condition = "survive to the end of the game, with anyone" + solo_counts_as_town = TRUE //should not count towards mafia victory, they should have the option to work with town + revealed_outfit = /datum/outfit/mafia/fugitive + team = MAFIA_TEAM_SOLO + role_type = NEUTRAL_DISRUPT + special_theme = "neutral" + hud_icon = "hudfugitive" + revealed_icon = "fugitive" + // winner_award = /datum/award/achievement/mafia/fugitive + + actions = list("Self Preservation") + var/charges = 2 + var/protection_status = FUGITIVE_NOT_PRESERVING + + +/datum/mafia_role/fugitive/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/night_start) + RegisterSignal(game,COMSIG_MAFIA_NIGHT_END,.proc/night_end) + RegisterSignal(game,COMSIG_MAFIA_GAME_END,.proc/survived) + +/datum/mafia_role/fugitive/handle_action(datum/mafia_controller/game, action, datum/mafia_role/target) + . = ..() + if(!charges) + to_chat(body,"You're out of supplies and cannot protect yourself anymore.") + return + if(game.phase == MAFIA_PHASE_NIGHT) + to_chat(body,"You don't have time to prepare, night has already arrived.") + return + if(protection_status == FUGITIVE_WILL_PRESERVE) + to_chat(body,"You decide to not prepare tonight.") + else + to_chat(body,"You decide to prepare for a horrible night.") + protection_status = !protection_status + +/datum/mafia_role/fugitive/proc/night_start(datum/mafia_controller/game) + if(protection_status == FUGITIVE_WILL_PRESERVE) + to_chat(body,"Your preparations are complete. Nothing could kill you tonight!") + RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/prevent_death) + +/datum/mafia_role/fugitive/proc/night_end(datum/mafia_controller/game) + if(protection_status == FUGITIVE_WILL_PRESERVE) + charges-- + UnregisterSignal(src,COMSIG_MAFIA_ON_KILL) + to_chat(body,"You are no longer protected. You have [charges] use[charges == 1 ? "" : "s"] left of your power.") + protection_status = FUGITIVE_NOT_PRESERVING + +/datum/mafia_role/fugitive/proc/prevent_death(datum/mafia_controller/game) + to_chat(body,"You were attacked! Luckily, you were ready for this!") + return MAFIA_PREVENT_KILL + +/datum/mafia_role/fugitive/proc/survived(datum/mafia_controller/game) + if(game_status == MAFIA_ALIVE) + // var/client/winner_client = GLOB.directory[player_key] + // winner_client?.give_award(winner_award, body) + game.send_message("!! FUGITIVE VICTORY !!") + +#undef FUGITIVE_NOT_PRESERVING +#undef FUGITIVE_WILL_PRESERVE + +/datum/mafia_role/obsessed + name = "Obsessed" + desc = "You're completely lost in your own mind. You win by lynching your obsession before you get killed in this mess. Obsession assigned on the first night!" + win_condition = "lynch their obsession." + revealed_outfit = /datum/outfit/mafia/obsessed // /mafia <- outfit must be readded (just make a new mafia outfits file for all of these) + solo_counts_as_town = TRUE //after winning or whatever, can side with whoever. they've already done their objective! + team = MAFIA_TEAM_SOLO + role_type = NEUTRAL_DISRUPT + special_theme = "neutral" + hud_icon = "hudobsessed" + revealed_icon = "obsessed" + + // winner_award = /datum/award/achievement/mafia/obsessed + + revealed_outfit = /datum/outfit/mafia/obsessed // /mafia <- outfit must be readded (just make a new mafia outfits file for all of these) + solo_counts_as_town = TRUE //after winning or whatever, can side with whoever. they've already done their objective! + var/datum/mafia_role/obsession + var/lynched_target = FALSE + +/datum/mafia_role/obsessed/New(datum/mafia_controller/game) //note: obsession is always a townie + . = ..() + RegisterSignal(game,COMSIG_MAFIA_SUNDOWN,.proc/find_obsession) + +/datum/mafia_role/obsessed/proc/find_obsession(datum/mafia_controller/game) + var/list/all_roles_shuffle = shuffle(game.all_roles) + for(var/role in all_roles_shuffle) + var/datum/mafia_role/possible = role + if(possible.team == MAFIA_TEAM_TOWN && possible.game_status != MAFIA_DEAD) + obsession = possible + break + if(!obsession) + obsession = pick(all_roles_shuffle) //okay no town just pick anyone here + //if you still don't have an obsession you're playing a single player game like i can't help your dumb ass + to_chat(body, "Your obsession is [obsession.body.real_name]! Get them lynched to win!") + add_note("N[game.turn] - I vowed to watch my obsession, [obsession.body.real_name], hang!") //it'll always be N1 but whatever + RegisterSignal(obsession,COMSIG_MAFIA_ON_KILL,.proc/check_victory) + UnregisterSignal(game,COMSIG_MAFIA_SUNDOWN) + +/datum/mafia_role/obsessed/proc/check_victory(datum/source,datum/mafia_controller/game,lynch) + UnregisterSignal(source,COMSIG_MAFIA_ON_KILL) + if(game_status == MAFIA_DEAD) + return + if(lynch) + game.send_message("!! OBSESSED VICTORY !!") + // var/client/winner_client = GLOB.directory[player_key] + // winner_client?.give_award(winner_award, body) + reveal_role(game, FALSE) + else + to_chat(body, "You have failed your objective to lynch [obsession.body]!") + +/datum/mafia_role/clown + name = "Clown" + desc = "If you are lynched you take down one of your voters (guilty or abstain) with you and win. HONK!" + win_condition = "get themselves lynched!" + revealed_outfit = /datum/outfit/mafia/clown + solo_counts_as_town = TRUE + team = MAFIA_TEAM_SOLO + role_type = NEUTRAL_DISRUPT + special_theme = "neutral" + hud_icon = "hudclown" + revealed_icon = "clown" + // winner_award = /datum/award/achievement/mafia/clown + +/datum/mafia_role/clown/New(datum/mafia_controller/game) + . = ..() + RegisterSignal(src,COMSIG_MAFIA_ON_KILL,.proc/prank) + +/datum/mafia_role/clown/proc/prank(datum/source,datum/mafia_controller/game,lynch) + if(lynch) + var/datum/mafia_role/victim = pick(game.judgement_guilty_votes + game.judgement_abstain_votes) + game.send_message("[body.real_name] WAS A CLOWN! HONK! They take down [victim.body.real_name] with their last prank.") + game.send_message("!! CLOWN VICTORY !!") + // var/client/winner_client = GLOB.directory[player_key] + // winner_client?.give_award(winner_award, body) + victim.kill(game,FALSE) diff --git a/code/modules/mapping/map_config.dm b/code/modules/mapping/map_config.dm index efa2655325..c03ef65f43 100644 --- a/code/modules/mapping/map_config.dm +++ b/code/modules/mapping/map_config.dm @@ -20,7 +20,7 @@ var/map_file = "BoxStation.dmm" var/traits = null - var/space_ruin_levels = 2 + var/space_ruin_levels = 4 var/space_empty_levels = 1 var/station_ruin_budget = -1 // can be set to manually override the station ruins budget on maps that don't support station ruins, stopping the error from being unable to place the ruins. diff --git a/code/modules/mapping/minimaps.dm b/code/modules/mapping/minimaps.dm index 29a9fca9b7..7a62e9ab44 100644 --- a/code/modules/mapping/minimaps.dm +++ b/code/modules/mapping/minimaps.dm @@ -1,21 +1,27 @@ /datum/minimap - var/name + var/name = "minimap" + var/icon/overlay_icon + // The map icons var/icon/map_icon var/icon/meta_icon - var/icon/overlay_icon + var/list/color_area_names = list() + var/minx var/maxx var/miny var/maxy - var/z_level - var/id = 0 - var/static/next_id = 0 -/datum/minimap/New(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy, name) + var/z_level + var/id = "" + +/datum/minimap/New(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy, name = "minimap") + if(!z) + CRASH("ERROR: new minimap requested without z level") //CRASH to halt the operatio + src.name = name - id = ++next_id z_level = z + id = "[md5("[z_level]" + src.name + REF(src))]" //use it's own md5 as a special identifier var/crop_x1 = x2 var/crop_x2 = x1 @@ -25,10 +31,11 @@ // do the generating map_icon = new('html/blank.png') meta_icon = new('html/blank.png') - map_icon.Scale(x2-x1+1, y2-y1+1) // arrays start at 1 - meta_icon.Scale(x2-x1+1, y2-y1+1) + map_icon.Scale(x2 - x1 + 1, y2 - y1 + 1) // arrays start at 1 + meta_icon.Scale(x2 - x1 + 1, y2 - y1 + 1) + var/list/area_to_color = list() - for(var/turf/T in block(locate(x1,y1,z),locate(x2,y2,z))) + for(var/turf/T in block(locate(x1, y1, z_level), locate(x2, y2, z_level))) var/area/A = T.loc var/img_x = T.x - x1 + 1 // arrays start at 1 var/img_y = T.y - y1 + 1 @@ -37,21 +44,26 @@ crop_x2 = max(crop_x2, T.x) crop_y1 = min(crop_y1, T.y) crop_y2 = max(crop_y2, T.y) + var/meta_color = area_to_color[A] if(!meta_color) - meta_color = rgb(rand(0,255),rand(0,255),rand(0,255)) // technically conflicts could happen but it's like very unlikely and it's not that big of a deal if one happens + meta_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) // technically conflicts could happen but it's like very unlikely and it's not that big of a deal if one happens area_to_color[A] = meta_color color_area_names[meta_color] = A.name meta_icon.DrawBox(meta_color, img_x, img_y) + if(istype(T, /turf/closed/wall)) map_icon.DrawBox("#000000", img_x, img_y) + else if(!istype(A, /area/space)) var/color = A.minimap_color || "#FF00FF" if(locate(/obj/machinery/power/solar) in T) color = "#02026a" + if((locate(/obj/effect/spawner/structure/window) in T) || (locate(/obj/structure/grille) in T)) color = BlendRGB(color, "#000000", 0.5) map_icon.DrawBox(color, img_x, img_y) + map_icon.Crop(crop_x1, crop_y1, crop_x2, crop_y2) meta_icon.Crop(crop_x1, crop_y1, crop_x2, crop_y2) minx = crop_x1 @@ -60,14 +72,17 @@ maxy = crop_y2 overlay_icon = new(map_icon) overlay_icon.Scale(16, 16) - -/datum/minimap/proc/send(mob/user) + //we're done baking, now we ship it. register_asset("minimap-[id].png", map_icon) register_asset("minimap-[id]-meta.png", meta_icon) - send_asset_list(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon), verify=FALSE) + +/datum/minimap/proc/send(mob/user) + if(!id) + CRASH("ERROR: send called, but the minimap id is null/missing. ID: [id]") + send_asset_list(user, list("minimap-[id].png" = map_icon, "minimap-[id]-meta.png" = meta_icon)) /datum/minimap_group - var/list/minimaps + var/list/minimaps = list() var/static/next_id = 0 var/id var/name @@ -75,46 +90,62 @@ /datum/minimap_group/New(list/maps, name) id = ++next_id src.name = name - minimaps = maps || list() + if(maps) + minimaps = maps /datum/minimap_group/proc/show(mob/user) if(!length(minimaps)) to_chat(user, "ERROR: Attempted to access an empty datum/minimap_group. This should probably not happen.") return + var/list/datas = list() var/list/info = list() - var/datum/minimap/first_map = minimaps[1] - for(var/i in 1 to length(minimaps)) + + for(var/i in 1 to length(minimaps))// OLD: for(var/i in 1 to length(minimaps)) var/datum/minimap/M = minimaps[i] M.send(user) - info += "
    " + info += {" +
    +
    + + +
    +
    +
    + "} datas += json_encode(M.color_area_names); - info = info.Join() - var/html = {" - - - - - - - -[name] - -[info] -"} + + + "} - user << browse(html, "window=minimap_[id];size=768x[round(768 / first_map.map_icon.Width() * first_map.map_icon.Height() + 50)]") + var/datum/browser/popup = new(user, "minimap_[id]", name, 500, 700) + popup.add_head_content(headerJS) //set the head + popup.set_content(info) + var/datum/minimap/MICO = minimaps[1] + popup.set_title_image(MICO.overlay_icon) + popup.open(FALSE) diff --git a/code/modules/mapping/reader.dm b/code/modules/mapping/reader.dm index a792ee280f..11bcc0ffcf 100644 --- a/code/modules/mapping/reader.dm +++ b/code/modules/mapping/reader.dm @@ -213,6 +213,7 @@ var/list/modelCache = build_cache(no_changeturf) var/space_key = modelCache[SPACE_KEY] var/list/bounds + var/did_expand = FALSE src.bounds = bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF) var/datum/map_orientation_pattern/mode = forced_pattern || GLOB.map_orientation_patterns["[orientation]"] || GLOB.map_orientation_patterns["[SOUTH]"] var/invert_y = mode.invert_y @@ -235,6 +236,7 @@ else while(parsed_z > world.maxz) world.incrementMaxZ() + did_expand = TRUE if(!no_changeturf) WARNING("Z-level expansion occurred without no_changeturf set, this may cause problems when /turf/AfterChange is called") //these values are the same until a new gridset is reached. @@ -256,11 +258,13 @@ continue else world.maxx = placement_x + did_expand = TRUE if(placement_y > world.maxy) if(cropMap) break else world.maxy = placement_y + did_expand = TRUE if(placement_x < 1) actual_x += xi continue @@ -301,6 +305,9 @@ testing("Skipped loading [turfsSkipped] default turfs") #endif + if(did_expand) + world.refresh_atmos_grid() + return TRUE /datum/parsed_map/proc/build_cache(no_changeturf, bad_paths=null) diff --git a/code/modules/mapping/space_management/multiz_helpers.dm b/code/modules/mapping/space_management/multiz_helpers.dm index f6db12420a..81c78cec8c 100644 --- a/code/modules/mapping/space_management/multiz_helpers.dm +++ b/code/modules/mapping/space_management/multiz_helpers.dm @@ -7,6 +7,20 @@ return get_step(SSmapping.get_turf_below(get_turf(ref)), dir) return get_step(ref, dir) +/proc/get_multiz_accessible_levels(center_z) + . = list(center_z) + var/other_z = center_z + var/offset + while((offset = SSmapping.level_trait(other_z, ZTRAIT_DOWN))) + other_z += offset + . += other_z + other_z = center_z + while((offset = SSmapping.level_trait(other_z, ZTRAIT_UP))) + other_z += offset + . += other_z + return . + + /proc/get_dir_multiz(turf/us, turf/them) us = get_turf(us) them = get_turf(them) @@ -32,16 +46,4 @@ /turf/proc/below() return get_step_multiz(src, DOWN) - -/proc/dir_inverse_multiz(dir) - var/holder = dir & (UP|DOWN) - if((holder == NONE) || (holder == (UP|DOWN))) - return turn(dir, 180) - dir &= ~(UP|DOWN) - dir = turn(dir, 180) - if(holder == UP) - holder = DOWN - else - holder = UP - dir |= holder - return dir \ No newline at end of file + \ No newline at end of file diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm index 94f5be65bf..8c9b0b53e1 100644 --- a/code/modules/mining/abandoned_crates.dm +++ b/code/modules/mining/abandoned_crates.dm @@ -149,8 +149,7 @@ if(100) new /obj/item/clothing/head/bearpelt(src) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/closet/crate/secure/loot/attack_hand(mob/user) +/obj/structure/closet/crate/secure/loot/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(locked) to_chat(user, "The crate is locked with a Deca-code lock.") var/input = input(usr, "Enter [codelen] digits. All digits must be unique.", "Deca-Code Lock", "") as text diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm index 6ec205bf7c..006065d048 100644 --- a/code/modules/mining/aux_base.dm +++ b/code/modules/mining/aux_base.dm @@ -92,13 +92,13 @@ interface with the mining shuttle at the landing site if a mobile beacon is also say("Launch sequence activated! Prepare for drop!!") playsound(loc, 'sound/machines/warning-buzzer.ogg', 70, 0) launch_warning = FALSE + log_shuttle("[key_name(usr)] has launched the auxillary base.") else if(!shuttle_error) say("Shuttle request uploaded. Please stand away from the doors.") else say("Shuttle interface failed.") if(href_list["random"] && !possible_destinations) - usr.changeNext_move(CLICK_CD_RAPID) //Anti-spam var/list/all_mining_turfs = list() for (var/z_level in SSmapping.levels_by_trait(ZTRAIT_MINING)) all_mining_turfs += Z_TURFS(z_level) @@ -274,10 +274,7 @@ interface with the mining shuttle at the landing site if a mobile beacon is also var/anti_spam_cd = 0 //The linking process might be a bit intensive, so this here to prevent over use. var/console_range = 15 //Wifi range of the beacon to find the aux base console -/obj/structure/mining_shuttle_beacon/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/mining_shuttle_beacon/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(anchored) to_chat(user, "Landing zone already set.") return diff --git a/code/modules/mining/aux_base_camera.dm b/code/modules/mining/aux_base_camera.dm index d461523744..be0a41427f 100644 --- a/code/modules/mining/aux_base_camera.dm +++ b/code/modules/mining/aux_base_camera.dm @@ -187,7 +187,7 @@ if(LAZYLEN(S.rcd_vals(owner,B.RCD))) rcd_target = S //If we don't break out of this loop we'll get the last placed thing - owner.changeNext_move(CLICK_CD_RANGE) + owner.DelayNextAction(CLICK_CD_RANGE) B.RCD.afterattack(rcd_target, owner, TRUE) //Activate the RCD and force it to work remotely! playsound(target_turf, 'sound/items/deconstruct.ogg', 60, 1) diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm index 39f8e296af..cda38033c2 100644 --- a/code/modules/mining/equipment/explorer_gear.dm +++ b/code/modules/mining/equipment/explorer_gear.dm @@ -5,10 +5,8 @@ icon_state = "explorer" item_state = "explorer" body_parts_covered = CHEST|GROIN|LEGS|ARMS - min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT cold_protection = CHEST|GROIN|LEGS|ARMS - max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT - heat_protection = CHEST|GROIN|LEGS|ARMS + min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT hoodtype = /obj/item/clothing/head/hooded/explorer armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50) flags_inv = HIDEJUMPSUIT|HIDETAUR @@ -24,9 +22,7 @@ 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) + armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50, "wound" = 10) resistance_flags = FIRE_PROOF /obj/item/clothing/suit/hooded/explorer/standard @@ -50,7 +46,7 @@ visor_flags_inv = HIDEFACIALHAIR visor_flags_cover = MASKCOVERSMOUTH actions_types = list(/datum/action/item_action/adjust) - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 5, "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, "wound" = 5) resistance_flags = FIRE_PROOF /obj/item/clothing/mask/gas/explorer/attack_self(mob/user) diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index dcd8e1a4ae..a6f456ce6f 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -1,5 +1,5 @@ /*********************Mining Hammer****************/ -/obj/item/twohanded/kinetic_crusher +/obj/item/kinetic_crusher icon = 'icons/obj/mining.dmi' icon_state = "crusher" item_state = "crusher0" @@ -11,15 +11,13 @@ force = 0 //You can't hit stuff unless wielded w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK - force_unwielded = 0 - force_wielded = 20 throwforce = 5 throw_speed = 4 armour_penetration = 10 custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075) hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped") - sharpness = IS_SHARP + sharpness = SHARP_EDGED actions_types = list(/datum/action/item_action/toggle_light) var/list/trophies = list() var/charged = TRUE @@ -28,33 +26,45 @@ var/backstab_bonus = 30 var/light_on = FALSE var/brightness_on = 7 + var/wielded = FALSE // track wielded status on item -/obj/item/twohanded/kinetic_crusher/cyborg //probably give this a unique sprite later +/obj/item/kinetic_crusher/cyborg //probably give this a unique sprite later desc = "An integrated version of the standard kinetic crusher with a grinded down axe head to dissuade mis-use against crewmen. Deals damage equal to the standard crusher against creatures, however." force = 10 //wouldn't want to give a borg a 20 brute melee weapon unemagged now would we detonation_damage = 60 wielded = 1 -/obj/item/twohanded/kinetic_crusher/cyborg/unwield() - return +/obj/item/kinetic_crusher/Initialize() + . = ..() + RegisterSignal(src, COMSIG_TWOHANDED_WIELD, .proc/on_wield) + RegisterSignal(src, COMSIG_TWOHANDED_UNWIELD, .proc/on_unwield) -/obj/item/twohanded/kinetic_crusher/Initialize() +/obj/item/kinetic_crusher/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 60, 110) //technically it's huge and bulky, but this provides an incentive to use it + AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=20) -/obj/item/twohanded/kinetic_crusher/Destroy() +/obj/item/kinetic_crusher/Destroy() QDEL_LIST(trophies) return ..() -/obj/item/twohanded/kinetic_crusher/examine(mob/living/user) +/// triggered on wield of two handed item +/obj/item/kinetic_crusher/proc/on_wield(obj/item/source, mob/user) + wielded = TRUE + +/// triggered on unwield of two handed item +/obj/item/kinetic_crusher/proc/on_unwield(obj/item/source, mob/user) + wielded = FALSE + +/obj/item/kinetic_crusher/examine(mob/living/user) . = ..() - . += "Mark a large creature with the destabilizing force, then hit them in melee to do [force_wielded + detonation_damage] damage." - . += "Does [force_wielded + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force_wielded + detonation_damage]." + . += "Mark a large creature with the destabilizing force, then hit them in melee to do [force + detonation_damage] damage." + . += "Does [force + detonation_damage + backstab_bonus] damage if the target is backstabbed, instead of [force + detonation_damage]." for(var/t in trophies) var/obj/item/crusher_trophy/T = t . += "It has \a [T] attached, which causes [T.effect_desc()]." -/obj/item/twohanded/kinetic_crusher/attackby(obj/item/I, mob/living/user) +/obj/item/kinetic_crusher/attackby(obj/item/I, mob/living/user) if(istype(I, /obj/item/crowbar)) if(LAZYLEN(trophies)) to_chat(user, "You remove [src]'s trophies.") @@ -70,7 +80,7 @@ else return ..() -/obj/item/twohanded/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) +/obj/item/kinetic_crusher/attack(mob/living/target, mob/living/carbon/user) if(!wielded) to_chat(user, "[src] is too heavy to use with one hand.") return @@ -84,7 +94,7 @@ if(!QDELETED(C) && !QDELETED(target)) C.total_damage += target_health - target.health //we did some damage, but let's not assume how much we did -/obj/item/twohanded/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams) +/obj/item/kinetic_crusher/afterattack(atom/target, mob/living/user, proximity_flag, clickparams) . = ..() if(istype(target, /obj/item/crusher_trophy)) var/obj/item/crusher_trophy/T = target @@ -137,34 +147,88 @@ if(user && lavaland_equipment_pressure_check(get_turf(user))) //CIT CHANGE - makes sure below only happens in low pressure environments user.adjustStaminaLoss(-30)//CIT CHANGE - makes crushers heal stamina -/obj/item/twohanded/kinetic_crusher/proc/Recharge() +/obj/item/kinetic_crusher/proc/Recharge() if(!charged) charged = TRUE update_icon() playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1) -/obj/item/twohanded/kinetic_crusher/ui_action_click(mob/user, actiontype) +/obj/item/kinetic_crusher/ui_action_click(mob/user, actiontype) light_on = !light_on playsound(user, 'sound/weapons/empty.ogg', 100, TRUE) update_brightness(user) update_icon() -/obj/item/twohanded/kinetic_crusher/proc/update_brightness(mob/user = null) +/obj/item/kinetic_crusher/proc/update_brightness(mob/user = null) if(light_on) set_light(brightness_on) else set_light(0) -/obj/item/twohanded/kinetic_crusher/update_icon_state() - item_state = "crusher[wielded]" +/obj/item/kinetic_crusher/update_icon_state() + item_state = "crusher[wielded]" // this is not icon_state and not supported by 2hcomponent -/obj/item/twohanded/kinetic_crusher/update_overlays() +/obj/item/kinetic_crusher/update_overlays() . = ..() if(!charged) . += "[icon_state]_uncharged" if(light_on) . += "[icon_state]_lit" +/obj/item/kinetic_crusher/glaive + name = "proto-kinetic glaive" + desc = "A modified design of a proto-kinetic crusher, it is still little more of a combination of various mining tools cobbled together \ + and kit-bashed into a high-tech cleaver on a stick - with a handguard and a goliath hide grip. While it is still of little use to any \ + but the most skilled and/or suicidal miners against local fauna, it's an elegant weapon for a more civilized hunter." + attack_verb = list("stabbed", "diced", "sliced", "cleaved", "chopped", "lacerated", "cut", "jabbed", "punctured") + icon_state = "crusher-glaive" + item_state = "crusher0-glaive" + block_parry_data = /datum/block_parry_data/crusherglaive + //ideas: altclick that lets you pummel people with the handguard/handle? + //parrying functionality? + +/datum/block_parry_data/crusherglaive // small perfect window, active for a fair while, time it right or use the Forbidden Technique + parry_time_windup = 0 + parry_time_active = 8 + parry_time_spindown = 0 + parry_time_perfect = 1 + parry_time_perfect_leeway = 2 + parry_imperfect_falloff_percent = 20 + parry_efficiency_to_counterattack = 100 // perfect parry or you're cringe + parry_failed_stagger_duration = 1.5 SECONDS // a good time to reconsider your actions... + parry_failed_clickcd_duration = 1.5 SECONDS // or your failures + +/obj/item/kinetic_crusher/glaive/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) // if you're dumb enough to go for a parry... + var/turf/proj_turf = owner.loc // destabilizer bolt, ignoring cooldown + if(!isturf(proj_turf)) + return + var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(proj_turf) + for(var/t in trophies) + var/obj/item/crusher_trophy/T = t + T.on_projectile_fire(D, owner) + D.preparePixelProjectile(attacker, owner) + D.firer = owner + D.hammer_synced = src + playsound(owner, 'sound/weapons/plasma_cutter.ogg', 100, 1) + D.fire() + +/obj/item/kinetic_crusher/glaive/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency, list/effect_text) + if(owner.Adjacent(attacker) && (!attacker.anchored || ismegafauna(attacker))) // free backstab, if you perfect parry + attacker.dir = get_dir(owner,attacker) + +/// triggered on wield of two handed item +/obj/item/kinetic_crusher/glaive/on_wield(obj/item/source, mob/user) + wielded = TRUE + item_flags |= (ITEM_CAN_PARRY) + +/// triggered on unwield of two handed item +/obj/item/kinetic_crusher/glaive/on_unwield(obj/item/source, mob/user) + wielded = FALSE + item_flags &= ~(ITEM_CAN_PARRY) + +/obj/item/kinetic_crusher/glaive/update_icon_state() + item_state = "crusher[wielded]-glaive" // this is not icon_state and not supported by 2hcomponent + //destablizing force /obj/item/projectile/destabilizer name = "destabilizing force" @@ -175,7 +239,7 @@ flag = "bomb" range = 6 log_override = TRUE - var/obj/item/twohanded/kinetic_crusher/hammer_synced + var/obj/item/kinetic_crusher/hammer_synced /obj/item/projectile/destabilizer/Destroy() hammer_synced = null @@ -214,12 +278,12 @@ return "errors" /obj/item/crusher_trophy/attackby(obj/item/A, mob/living/user) - if(istype(A, /obj/item/twohanded/kinetic_crusher)) + if(istype(A, /obj/item/kinetic_crusher)) add_to(A, user) else ..() -/obj/item/crusher_trophy/proc/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user) +/obj/item/crusher_trophy/proc/add_to(obj/item/kinetic_crusher/H, mob/living/user) for(var/t in H.trophies) var/obj/item/crusher_trophy/T = t if(istype(T, denied_type) || istype(src, T.denied_type)) @@ -231,7 +295,7 @@ to_chat(user, "You attach [src] to [H].") return TRUE -/obj/item/crusher_trophy/proc/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user) +/obj/item/crusher_trophy/proc/remove_from(obj/item/kinetic_crusher/H, mob/living/user) forceMove(get_turf(H)) H.trophies -= src return TRUE @@ -318,12 +382,12 @@ /obj/item/crusher_trophy/legion_skull/effect_desc() return "a kinetic crusher to recharge [bonus_value*0.1] second\s faster" -/obj/item/crusher_trophy/legion_skull/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user) +/obj/item/crusher_trophy/legion_skull/add_to(obj/item/kinetic_crusher/H, mob/living/user) . = ..() if(.) H.charge_time -= bonus_value -/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user) +/obj/item/crusher_trophy/legion_skull/remove_from(obj/item/kinetic_crusher/H, mob/living/user) . = ..() if(.) H.charge_time += bonus_value @@ -376,21 +440,19 @@ /obj/item/crusher_trophy/demon_claws/effect_desc() return "melee hits to do [bonus_value * 0.2] more damage and heal you for [bonus_value * 0.1], with 5X effect on mark detonation" -/obj/item/crusher_trophy/demon_claws/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user) +/obj/item/crusher_trophy/demon_claws/add_to(obj/item/kinetic_crusher/H, mob/living/user) . = ..() if(.) H.force += bonus_value * 0.2 - H.force_unwielded += bonus_value * 0.2 - H.force_wielded += bonus_value * 0.2 H.detonation_damage += bonus_value * 0.8 + AddComponent(/datum/component/two_handed, force_wielded=(20 + bonus_value * 0.2)) -/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user) +/obj/item/crusher_trophy/demon_claws/remove_from(obj/item/kinetic_crusher/H, mob/living/user) . = ..() if(.) H.force -= bonus_value * 0.2 - H.force_unwielded -= bonus_value * 0.2 - H.force_wielded -= bonus_value * 0.2 H.detonation_damage -= bonus_value * 0.8 + AddComponent(/datum/component/two_handed, force_wielded=20) /obj/item/crusher_trophy/demon_claws/on_melee_hit(mob/living/target, mob/living/user) user.heal_ordered_damage(bonus_value * 0.1, damage_heal_order) diff --git a/code/modules/mining/equipment/marker_beacons.dm b/code/modules/mining/equipment/marker_beacons.dm index 8853a56911..296513af8d 100644 --- a/code/modules/mining/equipment/marker_beacons.dm +++ b/code/modules/mining/equipment/marker_beacons.dm @@ -103,7 +103,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list( icon_state = "[initial(icon_state)][lowertext(picked_color)]-on" set_light(light_range, light_power, GLOB.marker_beacon_colors[picked_color]) -/obj/structure/marker_beacon/attack_hand(mob/living/user) +/obj/structure/marker_beacon/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 50a3dec9dd..27259ce812 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -143,7 +143,7 @@ w_class = WEIGHT_CLASS_NORMAL custom_materials = list(/datum/material/iron=350) attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked") - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/shovel/Initialize() . = ..() @@ -181,4 +181,4 @@ w_class = WEIGHT_CLASS_NORMAL toolspeed = 0.7 attack_verb = list("slashed", "impaled", "stabbed", "sliced") - sharpness = IS_SHARP + sharpness = SHARP_EDGED diff --git a/code/modules/mining/equipment/regenerative_core.dm b/code/modules/mining/equipment/regenerative_core.dm index 439929b9c1..1de3a86702 100644 --- a/code/modules/mining/equipment/regenerative_core.dm +++ b/code/modules/mining/equipment/regenerative_core.dm @@ -111,9 +111,6 @@ go_inert() return ..() -/obj/item/organ/regenerative_core/prepare_eat() - return null - /*************************Legion core********************/ /obj/item/organ/regenerative_core/legion desc = "A strange rock that crackles with power. It can be used to heal completely, but it will rapidly decay into uselessness." diff --git a/code/modules/mining/equipment/resonator.dm b/code/modules/mining/equipment/resonator.dm index 133cb41c33..16dd893c3a 100644 --- a/code/modules/mining/equipment/resonator.dm +++ b/code/modules/mining/equipment/resonator.dm @@ -41,7 +41,7 @@ return if(LAZYLEN(fields) < fieldlimit) new /obj/effect/temp_visual/resonance(T, user, src, burst_time) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) /obj/item/resonator/pre_attack(atom/target, mob/user, params) if(check_allowed_items(target, 1)) diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index ab0356aa66..c69e990033 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -167,10 +167,7 @@ qdel(src) return TRUE -/obj/item/gps/computer/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/gps/computer/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) attack_self(user) //Bed @@ -204,7 +201,7 @@ var/obj/item/reagent_containers/food/snacks/donkpocket/warm/W = new(src) load(W) if(prob(50)) - var/obj/item/storage/pill_bottle/dice/D = new(src) + var/obj/item/storage/box/dice/D = new(src) load(D) else var/obj/item/instrument/guitar/G = new(src) @@ -318,4 +315,4 @@ icon = initial(I.icon) desc = initial(I.desc) icon_state = initial(I.icon_state) - item_state = initial(I.item_state) \ No newline at end of file + item_state = initial(I.item_state) diff --git a/code/modules/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm index c31008fa62..c17b62ba6c 100644 --- a/code/modules/mining/equipment/wormhole_jaunter.dm +++ b/code/modules/mining/equipment/wormhole_jaunter.dm @@ -35,18 +35,20 @@ return destinations -/obj/item/wormhole_jaunter/proc/activate(mob/user, adjacent) +/obj/item/wormhole_jaunter/proc/activate(mob/user, adjacent, force_entry = FALSE) if(!turf_check(user)) return var/list/L = get_destinations(user) if(!L.len) - to_chat(user, "The [src.name] found no beacons in the world to anchor a wormhole to.") + to_chat(user, "The [name] found no beacons in the world to anchor a wormhole to.") return var/chosen_beacon = pick(L) - var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), src, 100, null, FALSE, get_turf(chosen_beacon)) + var/obj/effect/portal/jaunt_tunnel/J = new (get_turf(src), 100, null, FALSE, get_turf(chosen_beacon)) if(adjacent) try_move_adjacent(J) + if(force_entry) + J.teleport(user, force = TRUE) playsound(src,'sound/effects/sparks4.ogg',50,1) qdel(src) @@ -73,7 +75,7 @@ if(user.get_item_by_slot(SLOT_BELT) == src) to_chat(user, "Your [name] activates, saving you from the chasm!") SSblackbox.record_feedback("tally", "jaunter", 1, "Chasm") // chasm automatic activation - activate(user, FALSE) + activate(user, FALSE, TRUE) else to_chat(user, "[src] is not attached to your belt, preventing it from saving you from the chasm. RIP.
    ") @@ -84,9 +86,10 @@ icon_state = "bhole3" desc = "A stable hole in the universe made by a wormhole jaunter. Turbulent doesn't even begin to describe how rough passage through one of these is, but at least it will always get you somewhere near a beacon." mech_sized = TRUE //save your ripley + teleport_channel = TELEPORT_CHANNEL_WORMHOLE innate_accuracy_penalty = 6 -/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M) +/obj/effect/portal/jaunt_tunnel/teleport(atom/movable/M, force = FALSE) . = ..() if(.) // KERPLUNK diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index 14a277a66c..429dc98e8a 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -8,6 +8,7 @@ GLOBAL_LIST(labor_sheet_values) icon = 'icons/obj/machines/mining_machines.dmi' icon_state = "console" density = FALSE + var/obj/machinery/mineral/stacking_machine/laborstacker/stacking_machine = null var/machinedir = SOUTH var/obj/machinery/door/airlock/release_door @@ -32,11 +33,10 @@ GLOBAL_LIST(labor_sheet_values) /proc/cmp_sheet_list(list/a, list/b) return a["value"] - b["value"] -/obj/machinery/mineral/labor_claim_console/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/mineral/labor_claim_console/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "labor_claim_console", name, 315, 430, master_ui, state) + ui = new(user, src, "LaborClaimConsole", name) ui.open() /obj/machinery/mineral/labor_claim_console/ui_data(mob/user) @@ -100,7 +100,6 @@ GLOBAL_LIST(labor_sheet_values) Radio.talk_into(src, "A prisoner has returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY) to_chat(usr, "Shuttle received message and will be sent shortly.") . = TRUE - /obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine() stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir)) @@ -110,19 +109,16 @@ GLOBAL_LIST(labor_sheet_values) qdel(src) /obj/machinery/mineral/labor_claim_console/emag_act(mob/user) - . = ..() - if(obj_flags & EMAGGED) - return - obj_flags |= EMAGGED - to_chat(user, "PZZTTPFFFT") - return TRUE + if(!(obj_flags & EMAGGED)) + obj_flags |= EMAGGED + to_chat(user, "PZZTTPFFFT") /**********************Prisoner Collection Unit**************************/ /obj/machinery/mineral/stacking_machine/laborstacker force_connect = TRUE var/points = 0 //The unclaimed value of ore stacked. - + //damage_deflection = 21 /obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp) points += inp.point_value * inp.amount ..() @@ -142,10 +138,7 @@ GLOBAL_LIST(labor_sheet_values) icon_state = "console" density = FALSE -/obj/machinery/mineral/labor_points_checker/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/mineral/labor_points_checker/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) user.examinate(src) /obj/machinery/mineral/labor_points_checker/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index 38830fd824..9710773309 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -62,10 +62,7 @@ else return ..() -/obj/structure/flora/ash/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/flora/ash/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!harvested && !needs_sharp_harvest) user.visible_message("[user] starts to harvest from [src].","You begin to harvest from [src].") if(do_after(user, harvest_time, target = src)) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index b511cc793e..e03de83e02 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -79,9 +79,9 @@ new /obj/item/clothing/neck/necklace/memento_mori(src) if(29) if(prob(50)) - new /obj/item/malf_upgrade + new /obj/item/malf_upgrade(src) else - new /obj/item/disk/tech_disk/illegal + new /obj/item/disk/tech_disk/illegal(src) //KA modkit design discs /obj/item/disk/design_disk/modkit_disc @@ -492,7 +492,7 @@ setDir(user.dir) user.forceMove(src) - user.notransform = TRUE + user.mob_transforming = TRUE user.status_flags |= GODMODE can_destroy = FALSE @@ -501,7 +501,7 @@ /obj/effect/immortality_talisman/proc/unvanish(mob/user) user.status_flags &= ~GODMODE - user.notransform = FALSE + user.mob_transforming = FALSE user.forceMove(get_turf(src)) user.visible_message("[user] pops back into reality!") @@ -659,7 +659,7 @@ hitsound = 'sound/weapons/bladeslice.ogg' hitsound_on = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_BULKY - sharpness = IS_SHARP + sharpness = SHARP_EDGED faction_bonus_force = 30 nemesis_factions = list("mining", "boss") var/transform_cooldown @@ -667,6 +667,8 @@ var/bleed_stacks_per_hit = 3 total_mass = 2.75 total_mass_on = 5 + attack_speed = 0 + attack_unwieldlyness = CLICK_CD_MELEE * 0.5 /obj/item/melee/transforming/cleaving_saw/examine(mob/user) . = ..() @@ -685,8 +687,12 @@ return FALSE . = ..() if(.) + if(active) + attack_unwieldlyness = CLICK_CD_MELEE + else + attack_unwieldlyness = CLICK_CD_MELEE * 0.5 transform_cooldown = world.time + (CLICK_CD_MELEE * 0.5) - user.changeNext_move(CLICK_CD_MELEE * 0.25) + user.SetNextAction(CLICK_CD_MELEE * 0.25, considered_action = FALSE, flush = TRUE) /obj/item/melee/transforming/cleaving_saw/transform_messages(mob/living/user, supress_message_text) if(!supress_message_text) @@ -701,11 +707,6 @@ to_chat(user, "You accidentally cut yourself with [src], like a doofus!") user.take_bodypart_damage(10) -/obj/item/melee/transforming/cleaving_saw/melee_attack_chain(mob/user, atom/target, params) - ..() - if(!active) - user.changeNext_move(CLICK_CD_MELEE * 0.5) //when closed, it attacks very rapidly - /obj/item/melee/transforming/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target) var/datum/status_effect/stacking/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED) if(!B) @@ -765,7 +766,7 @@ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' flags_1 = CONDUCT_1 - sharpness = IS_SHARP + sharpness = SHARP_EDGED w_class = WEIGHT_CLASS_BULKY force = 1 throwforce = 1 @@ -929,6 +930,9 @@ /obj/item/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() + INVOKE_ASYNC(src, .proc/attempt_lava, target, user, proximity_flag, click_parameters) + +/obj/item/lava_staff/proc/attempt_lava(atom/target, mob/user, proximity_flag, click_parameters) if(timer > world.time) return @@ -1104,7 +1108,7 @@ var/blast_range = 13 //how long the cardinal blast's walls are var/obj/effect/hierophant/beacon //the associated beacon we teleport to var/teleporting = FALSE //if we ARE teleporting - var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets + var/friendly_fire_check = TRUE //if the blasts we make will consider our faction against the faction of hit targets /obj/item/hierophant_club/ComponentInitialize() . = ..() diff --git a/code/modules/mining/lavaland/ruins/gym.dm b/code/modules/mining/lavaland/ruins/gym.dm index 1c535fd9ab..c26631be74 100644 --- a/code/modules/mining/lavaland/ruins/gym.dm +++ b/code/modules/mining/lavaland/ruins/gym.dm @@ -8,7 +8,7 @@ var/list/hit_sounds = list('sound/weapons/genhit1.ogg', 'sound/weapons/genhit2.ogg', 'sound/weapons/genhit3.ogg',\ 'sound/weapons/punch1.ogg', 'sound/weapons/punch2.ogg', 'sound/weapons/punch3.ogg', 'sound/weapons/punch4.ogg') -/obj/structure/punching_bag/attack_hand(mob/user as mob) +/obj/structure/punching_bag/on_attack_hand(mob/user as mob) . = ..() if(.) return @@ -29,7 +29,7 @@ /obj/structure/weightmachine/proc/AnimateMachine(mob/living/user) return -/obj/structure/weightmachine/attack_hand(mob/living/user) +/obj/structure/weightmachine/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -92,4 +92,4 @@ sleep(3) animate(user, pixel_y = 2, time = 3) sleep(3) - cut_overlay(swole_overlay) \ No newline at end of file + cut_overlay(swole_overlay) diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 512fa8f3e4..851d78004b 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -3,9 +3,54 @@ /**********************Mineral processing unit console**************************/ /obj/machinery/mineral + speed_process = TRUE + init_process = FALSE + /// The current direction of `input_turf`, in relation to the machine. var/input_dir = NORTH + /// The current direction, in relation to the machine, that items will be output to. var/output_dir = SOUTH + /// The turf the machines listens to for items to pick up. Calls the `pickup_item()` proc. + var/turf/input_turf = null + /// Determines if this machine needs to pick up items. Used to avoid registering signals to `/mineral` machines that don't pickup items. + var/needs_item_input = FALSE +/obj/machinery/mineral/Initialize(mapload) + . = ..() + if(needs_item_input && anchored) + register_input_turf() + +/// Gets the turf in the `input_dir` direction adjacent to the machine, and registers signals for ATOM_ENTERED and ATOM_CREATED. Calls the `pickup_item()` proc when it receives these signals. +/obj/machinery/mineral/proc/register_input_turf() + input_turf = get_step(src, input_dir) + if(input_turf) // make sure there is actually a turf + RegisterSignal(input_turf, list(COMSIG_ATOM_CREATED, COMSIG_ATOM_ENTERED), .proc/pickup_item) + +/// Unregisters signals that are registered the machine's input turf, if it has one. +/obj/machinery/mineral/proc/unregister_input_turf() + if(input_turf) + UnregisterSignal(input_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_CREATED)) + +/obj/machinery/mineral/Moved() + . = ..() + if(!needs_item_input || !anchored) + return + unregister_input_turf() + register_input_turf() + +/** + Base proc for all `/mineral` subtype machines to use. Place your item pickup behavior in this proc when you override it for your specific machine. + + Called when the COMSIG_ATOM_ENTERED and COMSIG_ATOM_CREATED signals are sent. + + Arguments: + * source - the turf that is listening for the signals. + * target - the atom that just moved onto the `source` turf. + * oldLoc - the old location that `target` was at before moving onto `source`. +*/ +/obj/machinery/mineral/proc/pickup_item(datum/source, atom/movable/target, atom/oldLoc) + return + +/// Generic unloading proc. Takes an atom as an argument and forceMove's it to the turf adjacent to this machine in the `output_dir` direction. /obj/machinery/mineral/proc/unload_mineral(atom/movable/S) S.forceMove(drop_location()) var/turf/T = get_step(src,output_dir) @@ -19,7 +64,6 @@ density = TRUE var/obj/machinery/mineral/processing_unit/machine = null var/machinedir = EAST - speed_process = TRUE /obj/machinery/mineral/processing_unit_console/Initialize() . = ..() @@ -58,6 +102,7 @@ if(href_list["set_on"]) machine.on = (href_list["set_on"] == "on") + START_PROCESSING(SSmachines, machine) updateUsrDialog() return @@ -75,6 +120,7 @@ icon = 'icons/obj/machines/mining_machines.dmi' icon_state = "furnace" density = TRUE + needs_item_input = TRUE var/obj/machinery/mineral/CONSOLE = null var/on = FALSE var/datum/material/selected_material = null @@ -93,11 +139,10 @@ QDEL_NULL(stored_research) return ..() -/obj/machinery/mineral/processing_unit/HasProximity(atom/movable/AM) - if(istype(AM, /obj/item/stack/ore) && AM.loc == get_step(src, input_dir)) - process_ore(AM) /obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/ore/O) + if(QDELETED(O)) + return var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!materials.has_space(material_amount)) @@ -142,8 +187,14 @@ return dat +/obj/machinery/mineral/processing_unit/pickup_item(datum/source, atom/movable/target, atom/oldLoc) + if(QDELETED(target)) + return + if(istype(target, /obj/item/stack/ore)) + process_ore(target) + /obj/machinery/mineral/processing_unit/process() - if (on) + if(on) if(selected_material) smelt_ore() @@ -153,6 +204,8 @@ if(CONSOLE) CONSOLE.updateUsrDialog() + else + STOP_PROCESSING(SSmachines, src) /obj/machinery/mineral/processing_unit/proc/smelt_ore() var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index a7b7a84b27..0268d32a6b 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -57,6 +57,8 @@ . += "The status display reads: Smelting [ore_multiplier] sheet(s) per piece of ore.
    Reward point generation at [point_upgrade*100]%.
    Ore pickup speed at [ore_pickup_rate].
    " /obj/machinery/mineral/ore_redemption/proc/smelt_ore(obj/item/stack/ore/O) + if(QDELETED(O)) + return var/datum/component/material_container/mat_container = materials.mat_container if (!mat_container) return @@ -193,10 +195,10 @@ to_chat(user, "You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)].") return TRUE -/obj/machinery/mineral/ore_redemption/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/mineral/ore_redemption/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "ore_redemption_machine", "Ore Redemption Machine", 440, 550, master_ui, state) + ui = new(user, src, "OreRedemptionMachine") ui.open() /obj/machinery/mineral/ore_redemption/ui_data(mob/user) diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm index 5a83955bce..a5ff27e75e 100644 --- a/code/modules/mining/machine_stacking.dm +++ b/code/modules/mining/machine_stacking.dm @@ -92,6 +92,8 @@ return ..() /obj/machinery/mineral/stacking_machine/HasProximity(atom/movable/AM) + if(QDELETED(AM)) + return if(istype(AM, /obj/item/stack/sheet) && AM.loc == get_step(src, input_dir)) process_sheet(AM) @@ -104,6 +106,8 @@ return TRUE /obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp) + if(QDELETED(inp)) + return var/key = inp.merge_type var/obj/item/stack/sheet/storage = stack_list[key] if(!storage) //It's the first of this sheet added diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index ed6d9e31db..2cbb965ef5 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -30,7 +30,7 @@ new /datum/data/mining_equipment("500 Point Transfer Card", /obj/item/card/mining_point_card/mp500, 500), new /datum/data/mining_equipment("Tracking Implant Kit", /obj/item/storage/box/minertracker, 600), new /datum/data/mining_equipment("Jaunter", /obj/item/wormhole_jaunter, 750), - new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/twohanded/kinetic_crusher, 750), + new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/kinetic_crusher, 750), new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/gun/energy/kinetic_accelerator, 750), new /datum/data/mining_equipment("Survival Medipen", /obj/item/reagent_containers/hypospray/medipen/survival, 750), new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/storage/firstaid/brute, 800), @@ -71,7 +71,8 @@ new /datum/data/mining_equipment("KA Cooldown Decrease", /obj/item/borg/upgrade/modkit/cooldown, 1000), new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000), new /datum/data/mining_equipment("Miner Full Replacement", /obj/item/storage/backpack/duffelbag/mining_cloned, 3000), - new /datum/data/mining_equipment("Premium Accelerator", /obj/item/gun/energy/kinetic_accelerator/premiumka, 8000) + new /datum/data/mining_equipment("Premium Accelerator", /obj/item/gun/energy/kinetic_accelerator/premiumka, 8000), + new /datum/data/mining_equipment("Kinetic Glaive", /obj/item/kinetic_crusher/glaive, 2250), ) /datum/data/mining_equipment @@ -84,9 +85,14 @@ src.equipment_path = path src.cost = cost -/obj/machinery/mineral/equipment_vendor/power_change() - ..() - update_icon() +/obj/machinery/mineral/equipment_vendor/Initialize() + . = ..() + build_inventory() + +/obj/machinery/mineral/equipment_vendor/proc/build_inventory() + for(var/p in prize_list) + var/datum/data/mining_equipment/M = p + GLOB.vending_products[M.equipment_path] = 1 /obj/machinery/mineral/equipment_vendor/update_icon_state() if(powered()) @@ -94,44 +100,82 @@ else icon_state = "[initial(icon_state)]-off" -/obj/machinery/mineral/equipment_vendor/ui_interact(mob/user) - . = ..() - var/list/dat = list() - dat += "
    Equipment point cost list:
    " +/obj/machinery/mineral/equipment_vendor/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/vending), + ) + +/obj/machinery/mineral/equipment_vendor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "MiningVendor", name) + ui.open() + +/obj/machinery/mineral/equipment_vendor/ui_static_data(mob/user) + . = list() + .["product_records"] = list() for(var/datum/data/mining_equipment/prize in prize_list) - dat += "" - dat += "
    [prize.equipment_name][prize.cost]Purchase
    " + var/list/product_data = list( + path = replacetext(replacetext("[prize.equipment_path]", "/obj/item/", ""), "/", "-"), + name = prize.equipment_name, + price = prize.cost, + ref = REF(prize) + ) + .["product_records"] += list(product_data) - var/datum/browser/popup = new(user, "miningvendor", "Mining Equipment Vendor", 400, 350) - popup.set_content(dat.Join()) - popup.open() - return +/obj/machinery/mineral/equipment_vendor/ui_data(mob/user) + . = list() + var/mob/living/carbon/human/H + var/obj/item/card/id/C + if(ishuman(user)) + H = user + C = H.get_idcard(TRUE) + if(C) + .["user"] = list() + .["user"]["points"] = C.mining_points + if(C.registered_account) + .["user"]["name"] = C.registered_account.account_holder + if(C.registered_account.account_job) + .["user"]["job"] = C.registered_account.account_job.title + else + .["user"]["job"] = "No Job" -/obj/machinery/mineral/equipment_vendor/Topic(href, href_list) +/obj/machinery/mineral/equipment_vendor/ui_act(action, params) if(..()) return - if(href_list["purchase"]) - var/mob/M = usr - var/obj/item/card/id/I = M.get_idcard(TRUE) - if(istype(I)) - var/datum/data/mining_equipment/prize = locate(href_list["purchase"]) in prize_list - if (!prize || !(prize in prize_list)) - to_chat(usr, "Error: Invalid choice!") + + switch(action) + if("purchase") + var/mob/M = usr + var/obj/item/card/id/I = M.get_idcard(TRUE) + if(!istype(I)) + to_chat(usr, "Error: An ID is required!") + flick(icon_deny, src) + return + var/datum/data/mining_equipment/prize = locate(params["ref"]) in prize_list + if(!prize || !(prize in prize_list)) + to_chat(usr, "Error: Invalid choice!") flick(icon_deny, src) return if(prize.cost > I.mining_points) - to_chat(usr, "Error: Insufficient credits for [prize.equipment_name] on [I]!") + to_chat(usr, "Error: Insufficient points for [prize.equipment_name] on [I]!") flick(icon_deny, src) - else - I.mining_points -= prize.cost - to_chat(usr, "[src] clanks to life briefly before vending [prize.equipment_name]!") - new prize.equipment_path(src.loc) - SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]")) - else - to_chat(usr, "Error: An ID with a registered account is required!") - flick(icon_deny, src) - updateUsrDialog() - return + return + I.mining_points -= prize.cost + to_chat(usr, "[src] clanks to life briefly before vending [prize.equipment_name]!") + new prize.equipment_path(loc) + SSblackbox.record_feedback("nested tally", "mining_equipment_bought", 1, list("[type]", "[prize.equipment_path]")) + . = TRUE + +/obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/mining_voucher)) + RedeemVoucher(I, user) + return + if(default_deconstruction_screwdriver(user, "mining-open", "mining", I)) + return + if(default_deconstruction_crowbar(I)) + return + return ..() /obj/machinery/mineral/equipment_vendor/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/mining_voucher)) @@ -176,7 +220,7 @@ new /obj/item/stack/marker_beacon/thirty(drop_location) if("Crusher Kit") new /obj/item/extinguisher/mini(drop_location) - new /obj/item/twohanded/kinetic_crusher(drop_location) + new /obj/item/kinetic_crusher(drop_location) if("Mining Conscription Kit") new /obj/item/storage/backpack/duffelbag/mining_conscript(drop_location) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index f10229f4bf..143aba3fe4 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -79,8 +79,7 @@ no_destination_swap = 1 var/static/list/dumb_rev_heads = list() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/machinery/computer/shuttle/mining/attack_hand(mob/user) +/obj/machinery/computer/shuttle/mining/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(is_station_level(user.z) && user.mind && is_head_revolutionary(user) && !(user.mind in dumb_rev_heads)) to_chat(user, "You get a feeling that leaving the station might be a REALLY dumb idea...") dumb_rev_heads += user.mind diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index fb37dcbca0..627d79d6ba 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -118,7 +118,7 @@ deathmessage = "blows apart!" ..() -/mob/living/simple_animal/hostile/mining_drone/attack_hand(mob/living/carbon/human/M) +/mob/living/simple_animal/hostile/mining_drone/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) return diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index e89bbef58d..57a79553c3 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -6,11 +6,14 @@ icon = 'icons/obj/economy.dmi' icon_state = "coinpress0" density = TRUE - var/newCoins = 0 //how many coins the machine made in it's last load + input_dir = EAST + ui_x = 300 + ui_y = 250 + needs_item_input = TRUE + var/obj/item/storage/bag/money/bag_to_use + var/produced_coins = 0 // how many coins the machine has made in it's last cycle var/processing = FALSE var/chosen = /datum/material/iron //which material will be used to make coins - var/coinsToProduce = 10 - speed_process = TRUE /obj/machinery/mineral/mint/Initialize() @@ -28,89 +31,105 @@ /datum/material/mythril, /datum/material/plastic, /datum/material/runite - ), MINERAL_MATERIAL_AMOUNT * 50, FALSE, /obj/item/stack) - chosen = SSmaterials.GetMaterialRef(chosen) + ), MINERAL_MATERIAL_AMOUNT * 75, FALSE, /obj/item/stack) + chosen = SSmaterials.GetMaterialRef(chosen) -/obj/machinery/mineral/mint/process() - var/turf/T = get_step(src, input_dir) - if(!T) + +/obj/machinery/mineral/mint/pickup_item(datum/source, atom/movable/target, atom/oldLoc) + if(QDELETED(target)) + return + if(!istype(target, /obj/item/stack)) return var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - for(var/obj/item/stack/sheet/O in T) - var/inserted = materials.insert_item(O) - if(inserted) - qdel(O) + var/obj/item/stack/S = target -/obj/machinery/mineral/mint/attack_hand(mob/user) + if(materials.insert_item(S)) + qdel(S) + +/obj/machinery/mineral/mint/process() + if(processing) + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + var/datum/material/M = chosen + + if(!M) + processing = FALSE + icon_state = "coinpress0" + return + + icon_state = "coinpress1" + var/coin_mat = MINERAL_MATERIAL_AMOUNT + + for(var/sheets in 1 to 2) + if(materials.use_amount_mat(coin_mat, chosen)) + for(var/coin_to_make in 1 to 5) + create_coins() + produced_coins++ + CHECK_TICK + else + var/found_new = FALSE + for(var/datum/material/inserted_material in materials.materials) + var/amount = materials.get_material_amount(inserted_material) + + if(amount) + chosen = inserted_material + found_new = TRUE + + if(!found_new) + processing = FALSE + else + STOP_PROCESSING(SSmachines, src) + icon_state = "coinpress0" + +/obj/machinery/mineral/mint/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) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "Mint", name, ui_x, ui_y, master_ui, state) + ui.open() + +/obj/machinery/mineral/mint/ui_data() + var/list/data = list() + data["inserted_materials"] = list() + data["chosen_material"] = null + + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + for(var/datum/material/inserted_material in materials.materials) + var/amount = materials.get_material_amount(inserted_material) + if(!amount) + continue + data["inserted_materials"] += list(list( + "material" = inserted_material.name, + "amount" = amount, + )) + if(chosen == inserted_material) + data["chosen_material"] = inserted_material.name + + data["produced_coins"] = produced_coins + data["processing"] = processing + + return data; + +/obj/machinery/mineral/mint/ui_act(action, params, datum/tgui/ui) . = ..() if(.) return - var/dat = "Coin Press
    " - - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - for(var/datum/material/M in materials.materials) - var/amount = materials.get_material_amount(M) - if(!amount && chosen != M) - continue - dat += "
    [M.name] amount: [amount] cm3 " - if (chosen == M) - dat += "Chosen" - else - dat += "Choose" - - var/datum/material/M = chosen - - dat += "

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

    In total this machine produced [newCoins] coins." - dat += "
    Make coins" - user << browse(dat, "window=mint") - -/obj/machinery/mineral/mint/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(processing==1) - to_chat(usr, "The machine is processing.") - return - var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) - if(href_list["choose"]) - var/datum/material/new_material = locate(href_list["choose"]) - if(istype(new_material)) - chosen = new_material - if(href_list["chooseAmt"]) - coinsToProduce = clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000) - updateUsrDialog() - if(href_list["makeCoins"]) - var/temp_coins = coinsToProduce + if(action == "startpress") + if (!processing) + produced_coins = 0 processing = TRUE - icon_state = "coinpress1" - var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2 - var/datum/material/M = chosen - if(!M) - updateUsrDialog() - return - - while(coinsToProduce > 0 && materials.use_amount_mat(coin_mat, chosen)) - create_coins() - coinsToProduce-- - newCoins++ - src.updateUsrDialog() - sleep(5) - - icon_state = "coinpress0" + START_PROCESSING(SSmachines, src) + return TRUE + if (action == "stoppress") processing = FALSE - coinsToProduce = temp_coins - src.updateUsrDialog() - return + STOP_PROCESSING(SSmachines, src) + return TRUE + if (action == "changematerial") + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + for(var/datum/material/mat in materials.materials) + if (params["material_name"] == mat.name) + chosen = mat + return TRUE /obj/machinery/mineral/mint/proc/create_coins() var/turf/T = get_step(src,output_dir) @@ -118,9 +137,10 @@ temp_list[chosen] = 400 if(T) var/obj/item/O = new /obj/item/coin(src) - var/obj/item/storage/bag/money/B = locate(/obj/item/storage/bag/money, T) O.set_custom_materials(temp_list) - if(!B) - B = new /obj/item/storage/bag/money(src) - unload_mineral(B) - O.forceMove(B) + if(QDELETED(bag_to_use) || (bag_to_use.loc != T) || !SEND_SIGNAL(bag_to_use, COMSIG_TRY_STORAGE_INSERT, O, null, TRUE)) //important to send the signal so we don't overfill the bag. + bag_to_use = new(src) //make a new bag if we can't find or use the old one. + unload_mineral(bag_to_use) //just forcemove memes. + O.forceMove(bag_to_use) //don't bother sending the signal, the new bag is empty and all that. + + SSblackbox.record_feedback("amount", "coins_minted", 1) diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index 66f99ec40c..7dd13a6fc1 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -24,4 +24,8 @@ new /obj/item/coin/silver(src) new /obj/item/coin/gold(src) new /obj/item/coin/gold(src) - new /obj/item/coin/adamantine(src) \ No newline at end of file + new /obj/item/coin/adamantine(src) + +/obj/item/storage/bag/money/c5000/PopulateContents() + for(var/i = 0, i < 5, i++) + new /obj/item/stack/spacecash/c1000(src) \ No newline at end of file diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index f6b7110803..8bc9cc4512 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -17,7 +17,6 @@ var/points = 0 //How many points this ore gets you from the ore redemption machine var/refined_type = null //What this ore defaults to being refined into novariants = TRUE // Ore stacks handle their icon updates themselves to keep the illusion that there's more going - mats_per_stack = MINERAL_MATERIAL_AMOUNT var/list/stack_overlays /obj/item/stack/ore/update_overlays() @@ -211,7 +210,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ item_state = "slag" singular_name = "slag chunk" -/obj/item/twohanded/required/gibtonite +/obj/item/gibtonite name = "gibtonite ore" desc = "Extremely explosive if struck with mining equipment, Gibtonite is often used by miners to speed up their work by using it as a mining charge. This material is illegal to possess by unauthorized personnel under space law." icon = 'icons/obj/mining.dmi' @@ -225,12 +224,16 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ var/attacher = "UNKNOWN" var/det_timer -/obj/item/twohanded/required/gibtonite/Destroy() +/obj/item/gibtonite/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, require_twohands=TRUE) + +/obj/item/gibtonite/Destroy() qdel(wires) wires = null return ..() -/obj/item/twohanded/required/gibtonite/attackby(obj/item/I, mob/user, params) +/obj/item/gibtonite/attackby(obj/item/I, mob/user, params) if(!wires && istype(I, /obj/item/assembly/igniter)) user.visible_message("[user] attaches [I] to [src].", "You attach [I] to [src].") wires = new /datum/wires/explosive/gibtonite(src) @@ -258,22 +261,22 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ return ..() -/obj/item/twohanded/required/gibtonite/attack_self(user) +/obj/item/gibtonite/attack_self(user) if(wires) wires.interact(user) else ..() -/obj/item/twohanded/required/gibtonite/bullet_act(obj/item/projectile/P) +/obj/item/gibtonite/bullet_act(obj/item/projectile/P) GibtoniteReaction(P.firer) return ..() -/obj/item/twohanded/required/gibtonite/ex_act() +/obj/item/gibtonite/ex_act() GibtoniteReaction(null, 1) -/obj/item/twohanded/required/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by = 0) +/obj/item/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by = 0) if(!primed) primed = TRUE playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,1) @@ -299,7 +302,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ log_game("[key_name(user)] has primed a [name] for detonation at [AREACOORD(bombturf)]") det_timer = addtimer(CALLBACK(src, .proc/detonate, notify_admins), det_time, TIMER_STOPPABLE) -/obj/item/twohanded/required/gibtonite/proc/detonate(notify_admins) +/obj/item/gibtonite/proc/detonate(notify_admins) if(primed) switch(quality) if(GIBTONITE_QUALITY_HIGH) @@ -335,7 +338,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ throwforce = 2 w_class = WEIGHT_CLASS_TINY custom_materials = list(/datum/material/iron = 400) - material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS | MATERIAL_EFFECTS + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS var/string_attached var/list/sideslist = list("heads","tails") var/cooldown = 0 @@ -387,7 +390,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ to_chat(user, "There already is a string attached to this coin!") return - if (W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC)) + if (W.use_tool(src, user, 0, 1, skill_gain_mult = BARE_USE_TOOL_MULT)) add_overlay("coin_string_overlay") string_attached = 1 to_chat(user, "You attach a string to the coin.") diff --git a/code/modules/mining/satchel_ore_boxdm.dm b/code/modules/mining/satchel_ore_boxdm.dm index 1d803371be..36da9d5db9 100644 --- a/code/modules/mining/satchel_ore_boxdm.dm +++ b/code/modules/mining/satchel_ore_boxdm.dm @@ -24,21 +24,18 @@ /obj/structure/ore_box/crowbar_act(mob/living/user, obj/item/I) if(I.use_tool(src, user, 50, volume=50)) - user.visible_message("[user] pries \the [src] apart.", + user.visible_message("[user] pries \the [src] apart.", "You pry apart \the [src].", - "You hear splitting wood.") + "You hear splitting wood.") deconstruct(TRUE, user) return TRUE /obj/structure/ore_box/examine(mob/living/user) if(Adjacent(user) && istype(user)) ui_interact(user) - return ..() - -/obj/structure/ore_box/attack_hand(mob/user) . = ..() - if(.) - return + +/obj/structure/ore_box/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(Adjacent(user)) ui_interact(user) @@ -58,11 +55,10 @@ stoplag() drop = drop_location() -/obj/structure/ore_box/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/structure/ore_box/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "ore_box", name, 335, 415, master_ui, state) + ui = new(user, src, "OreBox", name) ui.open() /obj/structure/ore_box/ui_data() diff --git a/code/modules/mob/clickdelay.dm b/code/modules/mob/clickdelay.dm new file mode 100644 index 0000000000..b1df87303e --- /dev/null +++ b/code/modules/mob/clickdelay.dm @@ -0,0 +1,200 @@ +/** + * CLICKDELAY HANDLING SYSTEM + * How this works is mobs can never do actions until their next_action is at or below world.time, but things can specify extra cooldown + * to check for either from the time of last_action or from the end of next_action. + * + * Clickdelay should always be checked via [CheckActionCooldown()], never manually! + */ + +/mob + // CLICKDELAY AND RELATED + // Generic clickdelay - Hybrid time-since-last-attack and time-to-next-attack system. + // next_action is a hard cooldown, as Click()s will not pass unless it is passed. + // last_action is not a hard cooldown and different items can check for different delays. + /// Generic clickdelay variable. Marks down the last world.time we did something that should cause or impact generic clickdelay. This should be directly set or set using [DelayNextAction()]. This should only be checked using [CheckActionCooldown()]. + var/last_action = 0 + /** + * The difference between the above and this is this is set immediately before even the pre-attack begins to ensure clickdelay is respected. + * Then, it is flushed or discarded using [FlushLastAttack()] or [DiscardLastAttack()] respectively. + */ + + var/last_action_immediate = 0 + /// Generic clickdelay variable. Next world.time we should be able to do something that respects generic clickdelay. This should be set using [DelayNextAction()] This should only be checked using [CheckActionCooldown()]. + var/next_action = 0 + /// Ditto + var/next_action_immediate = 0 + /// Default clickdelay for an UnarmedAttack() that successfully passes. Respects action_cooldown_mod. + var/unarmed_attack_speed = CLICK_CD_MELEE + /// Simple modification variable multiplied to next action modifier on adjust and on checking time since last action using [CheckActionCooldown()]. + /// This should only be manually modified using multipliers. + var/action_cooldown_mod = 1 + /// Simple modification variable added to amount on adjust and on checking time since last action using [CheckActionCooldown()]. + /// This should only be manually modified via addition. + var/action_cooldown_adjust = 0 + + // Resisting - While resisting will give generic clickdelay, it is also on its own resist delay system. However, resisting does not check generic movedelay. + // Resist cooldown should only be set at the start of a resist chain - whether this is clicking an alert button, pressing or hotkeying the resist button, or moving to resist out of a locker. + /* + * Special clickdelay variable for resisting. Last time we did a special action like resisting. This should only be set using [MarkResistTime()]. + * Use [CheckResistCooldown()] to check cooldowns, this should only be used for the resist action bar visual. + */ + var/last_resist = 0 + /// How long we should wait before allowing another resist. This should only be manually modified using multipliers. + var/resist_cooldown = CLICK_CD_RESIST + /// Minimum world time for another resist. This should only be checked using [CheckResistCooldown()]. + var/next_resist = 0 + +/** + * Applies a delay to next_action before we can do our next action. + * + * @params + * * amount - Amount to delay by + * * ignore_mod - ignores next action adjust and mult + * * considered_action - Defaults to TRUE - If TRUE, sets last_action to world.time. + * * immediate - defaults to TRUE - if TRUE, writes to cached/last_attack_immediate instead of last_attack. This ensures it can't collide with any delay checks in the actual attack. + * * flush - defaults to FALSE - Use this while using this proc outside of clickcode to ensure everything is set properly. This should never be set to TRUE if this is called from clickcode. + */ +/mob/proc/DelayNextAction(amount = 0, ignore_mod = FALSE, considered_action = TRUE, immediate = TRUE, flush = FALSE) + if(immediate) + if(considered_action) + last_action_immediate = world.time + next_action_immediate = max(next_action, world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust()))) + else + if(considered_action) + last_action = world.time + next_action = max(next_action, world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust()))) + if(flush) + FlushCurrentAction() + else + hud_used?.clickdelay?.mark_dirty() + +/** + * Get estimated time of next attack. + */ +/mob/proc/EstimatedNextActionTime() + var/attack_speed = unarmed_attack_speed * GetActionCooldownMod() + GetActionCooldownAdjust() + var/obj/item/I = get_active_held_item() + if(I) + attack_speed = I.GetEstimatedAttackSpeed() + if(!I.clickdelay_mod_bypass) + attack_speed = attack_speed * GetActionCooldownMod() + GetActionCooldownAdjust() + return max(next_action, next_action_immediate, max(last_action, last_action_immediate) + attack_speed) + +/** + * Sets our next action to. The difference is DelayNextAction cannot reduce next_action under any circumstances while this can. + */ +/mob/proc/SetNextAction(amount = 0, ignore_mod = FALSE, considered_action = TRUE, immediate = TRUE, flush = FALSE) + if(immediate) + if(considered_action) + last_action_immediate = world.time + next_action_immediate = world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust())) + else + if(considered_action) + last_action = world.time + next_action = world.time + (ignore_mod? amount : (amount * GetActionCooldownMod() + GetActionCooldownAdjust())) + if(flush) + FlushCurrentAction() + else + hud_used?.clickdelay?.mark_dirty() + +/** + * Checks if we can do another action. + * Returns TRUE if we can and FALSE if we cannot. + * + * @params + * * cooldown - Time required since last action. Defaults to 0.5 + * * from_next_action - Defaults to FALSE. Should we check from the tail end of next_action instead of last_action? + * * ignore_mod - Defaults to FALSE. Ignore all adjusts and multipliers. Do not use this unless you know what you are doing and have a good reason. + * * ignore_next_action - Defaults to FALSE. Ignore next_action and only care about cooldown param and everything else. Generally unused. + * * immediate - Defaults to FALSE. Checks last action using immediate, used on the head end of an attack. This is to prevent colliding attacks in case of sleep. Not that you should sleep() in an attack but.. y'know. + */ +/mob/proc/CheckActionCooldown(cooldown = 0.5, from_next_action = FALSE, ignore_mod = FALSE, ignore_next_action = FALSE, immediate = FALSE) + return (ignore_next_action || (world.time >= (immediate? next_action_immediate : next_action))) && \ + (world.time >= ((from_next_action? (immediate? next_action_immediate : next_action) : (immediate? last_action_immediate : last_action)) + max(0, ignore_mod? cooldown : (cooldown * GetActionCooldownMod() + GetActionCooldownAdjust())))) + +/** + * Gets action_cooldown_mod. + */ +/mob/proc/GetActionCooldownMod() + return action_cooldown_mod + +/** + * Gets action_cooldown_adjust + */ +/mob/proc/GetActionCooldownAdjust() + return action_cooldown_adjust + +/** + * Flushes last_action and next_action + */ +/mob/proc/FlushCurrentAction() + last_action = last_action_immediate + next_action = next_action_immediate + hud_used?.clickdelay?.mark_dirty() + +/** + * Discards last_action and next_action + */ +/mob/proc/DiscardCurrentAction() + last_action_immediate = last_action + next_action_immediate = next_action + hud_used?.clickdelay?.mark_dirty() + +/** + * Checks if we can resist again. + */ +/mob/proc/CheckResistCooldown() + return (world.time >= next_resist) + +/** + * Mark the last resist as now. + * + * @params + * * extra_cooldown - Extra cooldown to apply to next_resist. Defaults to this mob's resist_cooldown. + * * override - Defaults to FALSE - if TRUE, extra_cooldown will replace the old next_resist even if the old is longer. + */ +/mob/proc/MarkResistTime(extra_cooldown = resist_cooldown, override = FALSE) + last_resist = world.time + next_resist = override? (world.time + extra_cooldown) : max(next_resist, world.time + extra_cooldown) + hud_used?.resistdelay?.mark_dirty() + +/atom + // Standard clickdelay variables + // These 3 are all handled at base of atom/attack_hand so uh.. yeah. Make sure that's called. + /// Amount of time to check for from a mob's last attack to allow an attack_hand(). + var/attack_hand_speed = CLICK_CD_MELEE + /// Amount of time to hard stagger (no clicking at all) the mob post attack_hand(). Lower = better + var/attack_hand_unwieldlyness = 0 + /// Should we set last action for attack hand? This implies that attack_hands to this atom should flush to clickdelay buffers instead of discarding. + var/attack_hand_is_action = FALSE + +/obj/item + // Standard clickdelay variables + /// Amount of time to check for from a mob's last attack, checked before an attack happens. Lower = faster attacks + var/attack_speed = CLICK_CD_MELEE + /// Amount of time to hard-stagger (no clicking at all) the mob when attacking. Lower = better + var/attack_unwieldlyness = 0 + /// This item bypasses any click delay mods + var/clickdelay_mod_bypass = FALSE + /// This item checks clickdelay from a user's delayed next action variable rather than the last time they attacked. + var/clickdelay_from_next_action = FALSE + /// This item ignores next action delays. + var/clickdelay_ignores_next_action = FALSE + +/** + * Checks if a user's clickdelay is met for a standard attack, this is called before an attack happens. + */ +/obj/item/proc/CheckAttackCooldown(mob/user, atom/target) + return user.CheckActionCooldown(attack_speed, clickdelay_from_next_action, clickdelay_mod_bypass, clickdelay_ignores_next_action) + +/** + * Called after a successful attack to set a mob's clickdelay. + */ +/obj/item/proc/ApplyAttackCooldown(mob/user, atom/target, attackchain_flags) + user.DelayNextAction(attack_unwieldlyness, clickdelay_mod_bypass, !(attackchain_flags & ATTACK_IGNORE_ACTION)) + +/** + * Get estimated time that a user has to not attack for to use us + */ +/obj/item/proc/GetEstimatedAttackSpeed() + return attack_speed diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index 0c50cb0468..bd3a3d304a 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -68,7 +68,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) set category = "OOC" set name = "Server Hop!" set desc= "Jump to the other server" - if(notransform) + if(mob_transforming) return var/list/csa = CONFIG_GET(keyed_list/cross_server) var/pick @@ -93,9 +93,9 @@ INITIALIZE_IMMEDIATE(/mob/dead) to_chat(C, "Sending you to [pick].") new /obj/screen/splash(C) - notransform = TRUE + mob_transforming = TRUE sleep(29) //let the animation play - notransform = FALSE + mob_transforming = FALSE if(!C) return diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index 36babd9b95..768c4c943e 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -398,7 +398,7 @@ humanc = character //Let's retypecast the var to be human, if(humanc) //These procs all expect humans - GLOB.data_core.manifest_inject(humanc) + GLOB.data_core.manifest_inject(humanc, humanc.client, humanc.client.prefs) if(SSshuttle.arrivals) SSshuttle.arrivals.QueueAnnounce(humanc, rank) else @@ -412,6 +412,8 @@ give_guns(humanc) if(GLOB.summon_magic_triggered) give_magic(humanc) + if(GLOB.curse_of_madness_triggered) + give_madness(humanc, GLOB.curse_of_madness_triggered) GLOB.joined_player_list += character.ckey GLOB.latejoiners += character @@ -555,6 +557,16 @@ if(frn) client.prefs.random_character() client.prefs.real_name = client.prefs.pref_species.random_name(gender,1) + var/cur_scar_index = client.prefs.scars_index + if(client.prefs.persistent_scars && client.prefs.scars_list["[cur_scar_index]"]) + var/scar_string = client.prefs.scars_list["[cur_scar_index]"] + var/valid_scars = "" + for(var/scar_line in splittext(scar_string, ";")) + if(H.load_scar(scar_line)) + valid_scars += "[scar_line];" + + client.prefs.scars_list["[cur_scar_index]"] = valid_scars + client.prefs.save_character() client.prefs.copy_to(H) H.dna.update_dna_identity() if(mind) @@ -562,6 +574,7 @@ mind.late_joiner = TRUE mind.active = 0 //we wish to transfer the key manually mind.transfer_to(H) //won't transfer key since the mind is not active + mind.original_character = H H.name = real_name diff --git a/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm b/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm index 020776a75f..3c2c850e3c 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/Citadel_Snowflake.dm @@ -1,9 +1,9 @@ -/datum/sprite_accessory/mam_tails/shark/datashark +/datum/sprite_accessory/tails/mam_tails/shark/datashark name = "DataShark" icon_state = "datashark" ckeys_allowed = list("rubyflamewing") -/datum/sprite_accessory/mam_tails_animated/shark/datashark +/datum/sprite_accessory/tails_animated/mam_tails_animated/shark/datashark name = "DataShark" icon_state = "datashark" ckeys_allowed = list("rubyflamewing") @@ -14,19 +14,19 @@ ckeys_allowed = list("rubyflamewing") //Sabresune -/datum/sprite_accessory/mam_ears/sabresune +/datum/sprite_accessory/ears/mam_ears/sabresune name = "Sabresune" icon_state = "sabresune" ckeys_allowed = list("poojawa") extra = TRUE extra_color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_tails/sabresune +/datum/sprite_accessory/tails/mam_tails/sabresune name = "Sabresune" icon_state = "sabresune" ckeys_allowed = list("poojawa") -/datum/sprite_accessory/mam_tails_animated/sabresune +/datum/sprite_accessory/tails_animated/mam_tails_animated/sabresune name = "Sabresune" icon_state = "sabresune" ckeys_allowed = list("poojawa") @@ -37,17 +37,17 @@ ckeys_allowed = list("poojawa") //Lunasune -/datum/sprite_accessory/mam_ears/lunasune +/datum/sprite_accessory/ears/mam_ears/lunasune name = "lunasune" icon_state = "lunasune" ckeys_allowed = list("invader4352") -/datum/sprite_accessory/mam_tails/lunasune +/datum/sprite_accessory/tails/mam_tails/lunasune name = "lunasune" icon_state = "lunasune" ckeys_allowed = list("invader4352") -/datum/sprite_accessory/mam_tails_animated/lunasune +/datum/sprite_accessory/tails_animated/mam_tails_animated/lunasune name = "lunasune" icon_state = "lunasune" ckeys_allowed = list("invader4352") diff --git a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm index 6514cb4f80..4cb8d080ff 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/_sprite_accessories.dm @@ -76,6 +76,9 @@ //For soft-restricting markings to species IDs var/list/recommended_species +/datum/sprite_accessory/proc/is_not_visible(var/mob/living/carbon/human/H, var/tauric) //return if the accessory shouldn't be shown + return FALSE + /datum/sprite_accessory/underwear icon = 'icons/mob/clothing/underwear.dmi' var/has_color = FALSE diff --git a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm index c8e7aca26d..d1f7f15ac9 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/alienpeople.dm @@ -7,18 +7,21 @@ mutant_part_string = "xenodorsal" relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/xeno_dorsal/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (!H.dna.features["xenodorsal"] || H.dna.features["xenodorsal"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))) + /datum/sprite_accessory/xeno_dorsal/standard name = "Standard" icon_state = "standard" -/datum/sprite_accessory/xeno_dorsal/royal - name = "Royal" - icon_state = "royal" - /datum/sprite_accessory/xeno_dorsal/down name = "Dorsal Down" icon_state = "down" +/datum/sprite_accessory/xeno_dorsal/royal + name = "Royal" + icon_state = "royal" + /****************************************** ************* Xeno Tails ****************** *******************************************/ @@ -27,6 +30,9 @@ mutant_part_string = "tail" relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/xeno_tail/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (!H.dna.features["xenotail"] || H.dna.features["xenotail"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) + /datum/sprite_accessory/xeno_tail/none name = "None" relevant_layers = null @@ -43,18 +49,22 @@ mutant_part_string = "xhead" relevant_layers = list(BODY_ADJ_LAYER) +/datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return (!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC) + /datum/sprite_accessory/xeno_head/standard name = "Standard" icon_state = "standard" -/datum/sprite_accessory/xeno_head/royal - name = "royal" - icon_state = "royal" - /datum/sprite_accessory/xeno_head/hollywood name = "hollywood" icon_state = "hollywood" +/datum/sprite_accessory/xeno_head/royal + name = "royal" + icon_state = "royal" + /datum/sprite_accessory/xeno_head/warrior name = "warrior" icon_state = "warrior" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm b/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm index 9950f0d76a..5286acb33a 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/body_markings.dm @@ -16,6 +16,12 @@ icon_state = "dtiger" gender_specific = 1 +/datum/sprite_accessory/body_markings/guilmon + name = "Guilmon" + icon_state = "guilmon" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' + /datum/sprite_accessory/body_markings/ltiger name = "Light Tiger Body" icon_state = "ltiger" @@ -49,11 +55,6 @@ icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' relevant_layers = null -/datum/sprite_accessory/mam_body_markings/plain - name = "Plain" - icon_state = "plain" - icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' - /datum/sprite_accessory/mam_body_markings/redpanda name = "Redpanda" icon_state = "redpanda" @@ -77,14 +78,14 @@ icon_state = "bellyslim" icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' -/datum/sprite_accessory/mam_body_markings/corgi - name = "Corgi" - icon_state = "corgi" - /datum/sprite_accessory/mam_body_markings/cow name = "Bovine" icon_state = "bovine" +/datum/sprite_accessory/mam_body_markings/corgi + name = "Corgi" + icon_state = "corgi" + /datum/sprite_accessory/mam_body_markings/corvid name = "Corvid" icon_state = "corvid" @@ -139,15 +140,19 @@ name = "Hyena" icon_state = "hyena" -/datum/sprite_accessory/mam_body_markings/lab - name = "Lab" - icon_state = "lab" - /datum/sprite_accessory/mam_body_markings/insect name = "Insect" icon_state = "insect" icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' +/datum/sprite_accessory/mam_body_markings/lab + name = "Lab" + icon_state = "lab" + +/datum/sprite_accessory/mam_body_markings/orca + name = "Orca" + icon_state = "orca" + /datum/sprite_accessory/mam_body_markings/otie name = "Otie" icon_state = "otie" @@ -156,14 +161,15 @@ name = "Otter" icon_state = "otter" -/datum/sprite_accessory/mam_body_markings/orca - name = "Orca" - icon_state = "orca" - /datum/sprite_accessory/mam_body_markings/panther name = "Panther" icon_state = "panther" +/datum/sprite_accessory/mam_body_markings/plain + name = "Plain" + icon_state = "plain" + icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' + /datum/sprite_accessory/mam_body_markings/possum name = "Possum" icon_state = "possum" @@ -172,6 +178,10 @@ name = "Raccoon" icon_state = "raccoon" +/datum/sprite_accessory/mam_body_markings/sergal + name = "Sergal" + icon_state = "sergal" + /datum/sprite_accessory/mam_body_markings/pede name = "Scolipede" icon_state = "scolipede" @@ -181,18 +191,14 @@ name = "Shark" icon_state = "shark" -/datum/sprite_accessory/mam_body_markings/skunk - name = "Skunk" - icon_state = "skunk" - -/datum/sprite_accessory/mam_body_markings/sergal - name = "Sergal" - icon_state = "sergal" - /datum/sprite_accessory/mam_body_markings/shepherd name = "Shepherd" icon_state = "shepherd" +/datum/sprite_accessory/mam_body_markings/skunk + name = "Skunk" + icon_state = "skunk" + /datum/sprite_accessory/mam_body_markings/tajaran name = "Tajaran" icon_state = "tajaran" @@ -224,80 +230,18 @@ color_src = 0 relevant_layers = list(BODY_FRONT_LAYER) +/datum/sprite_accessory/insect_fluff/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) + /datum/sprite_accessory/insect_fluff/none name = "None" icon_state = "none" relevant_layers = null -/datum/sprite_accessory/insect_fluff/plain - name = "Plain" - icon_state = "plain" - -/datum/sprite_accessory/insect_fluff/reddish - name = "Reddish" - icon_state = "redish" - -/datum/sprite_accessory/insect_fluff/royal - name = "Royal" - icon_state = "royal" - -/datum/sprite_accessory/insect_fluff/gothic - name = "Gothic" - icon_state = "gothic" - -/datum/sprite_accessory/insect_fluff/lovers - name = "Lovers" - icon_state = "lovers" - -/datum/sprite_accessory/insect_fluff/whitefly - name = "White Fly" - icon_state = "whitefly" - /datum/sprite_accessory/insect_fluff/punished name = "Burnt Off" icon_state = "punished" -/datum/sprite_accessory/insect_fluff/firewatch - name = "Firewatch" - icon_state = "firewatch" - -/datum/sprite_accessory/insect_fluff/deathhead - name = "Deathshead" - icon_state = "deathhead" - -/datum/sprite_accessory/insect_fluff/poison - name = "Poison" - icon_state = "poison" - -/datum/sprite_accessory/insect_fluff/ragged - name = "Ragged" - icon_state = "ragged" - -/datum/sprite_accessory/insect_fluff/moonfly - name = "Moon Fly" - icon_state = "moonfly" - -/datum/sprite_accessory/insect_fluff/snow - name = "Snow" - icon_state = "snow" - -/datum/sprite_accessory/insect_fluff/oakworm - name = "Oak Worm" - icon_state = "oakworm" - -/datum/sprite_accessory/insect_fluff/jungle - name = "Jungle" - icon_state = "jungle" - -/datum/sprite_accessory/insect_fluff/witchwing - name = "Witch Wing" - icon_state = "witchwing" - -/datum/sprite_accessory/insect_fluff/colored - name = "Colored (Hair)" - icon_state = "snow" - color_src = HAIR - /datum/sprite_accessory/insect_fluff/colored1 name = "Colored (Primary)" icon_state = "snow" @@ -311,4 +255,69 @@ /datum/sprite_accessory/insect_fluff/colored3 name = "Colored (Tertiary)" icon_state = "snow" - color_src = MUTCOLORS3 \ No newline at end of file + color_src = MUTCOLORS3 + +/datum/sprite_accessory/insect_fluff/colored + name = "Colored (Hair)" + icon_state = "snow" + color_src = HAIR + +/datum/sprite_accessory/insect_fluff/deathhead + name = "Deathshead" + icon_state = "deathhead" + +/datum/sprite_accessory/insect_fluff/firewatch + name = "Firewatch" + icon_state = "firewatch" + +/datum/sprite_accessory/insect_fluff/gothic + name = "Gothic" + icon_state = "gothic" + +/datum/sprite_accessory/insect_fluff/jungle + name = "Jungle" + icon_state = "jungle" + +/datum/sprite_accessory/insect_fluff/lovers + name = "Lovers" + icon_state = "lovers" + +/datum/sprite_accessory/insect_fluff/moonfly + name = "Moon Fly" + icon_state = "moonfly" + +/datum/sprite_accessory/insect_fluff/oakworm + name = "Oak Worm" + icon_state = "oakworm" + +/datum/sprite_accessory/insect_fluff/plain + name = "Plain" + icon_state = "plain" + +/datum/sprite_accessory/insect_fluff/poison + name = "Poison" + icon_state = "poison" + +/datum/sprite_accessory/insect_fluff/ragged + name = "Ragged" + icon_state = "ragged" + +/datum/sprite_accessory/insect_fluff/reddish + name = "Reddish" + icon_state = "redish" + +/datum/sprite_accessory/insect_fluff/royal + name = "Royal" + icon_state = "royal" + +/datum/sprite_accessory/insect_fluff/snow + name = "Snow" + icon_state = "snow" + +/datum/sprite_accessory/insect_fluff/whitefly + name = "White Fly" + icon_state = "whitefly" + +/datum/sprite_accessory/insect_fluff/witchwing + name = "Witch Wing" + icon_state = "witchwing" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm index bc269ccf62..7515ce560a 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/ears.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/ears.dm @@ -3,6 +3,10 @@ mutant_part_string = "ears" relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return (!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC) + /datum/sprite_accessory/ears/none name = "None" icon_state = "none" @@ -37,7 +41,7 @@ extra = TRUE extra_color_src = NONE -/datum/sprite_accessory/ears/human/bigwolfdark +/datum/sprite_accessory/ears/human/bigwolfdark //ignore alphabetical sort here for ease-of-use name = "Dark Big Wolf" icon_state = "bigwolfdark" icon = 'modular_citadel/icons/mob/mam_ears.dmi' @@ -51,6 +55,12 @@ extra = TRUE extra_color_src = NONE +/datum/sprite_accessory/ears/bunny + name = "Bunny" + icon_state = "bunny" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_ears.dmi' + /datum/sprite_accessory/ears/cat name = "Cat" icon_state = "cat" @@ -70,6 +80,12 @@ icon = 'modular_citadel/icons/mob/mam_ears.dmi' color_src = MUTCOLORS3 +/datum/sprite_accessory/ears/lab + name = "Dog, Floppy" + icon_state = "lab" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_ears.dmi' + /datum/sprite_accessory/ears/human/eevee name = "Eevee" icon_state = "eevee" @@ -111,12 +127,6 @@ icon_state = "jellyfish" color_src = HAIR -/datum/sprite_accessory/ears/lab - name = "Dog, Floppy" - icon_state = "lab" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_ears.dmi' - /datum/sprite_accessory/ears/murid name = "Murid" icon_state = "murid" @@ -129,18 +139,18 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_ears.dmi' -/datum/sprite_accessory/ears/human/pede - name = "Scolipede" - icon_state = "pede" - icon = 'modular_citadel/icons/mob/mam_ears.dmi' - color_src = MATRIXED - /datum/sprite_accessory/ears/human/rabbit name = "Rabbit" icon_state = "rabbit" color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_ears.dmi' +/datum/sprite_accessory/ears/human/pede + name = "Scolipede" + icon_state = "pede" + icon = 'modular_citadel/icons/mob/mam_ears.dmi' + color_src = MATRIXED + /datum/sprite_accessory/ears/human/sergal name = "Sergal" icon_state = "sergal" @@ -165,60 +175,62 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_ears.dmi' -/datum/sprite_accessory/ears/bunny - name = "Bunny" - icon_state = "bunny" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_ears.dmi' - /****************************************** *************** Furry Ears **************** *******************************************/ -/datum/sprite_accessory/mam_ears +/datum/sprite_accessory/ears/mam_ears icon = 'modular_citadel/icons/mob/mam_ears.dmi' color_src = MATRIXED mutant_part_string = "ears" relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) -/datum/sprite_accessory/mam_ears/none +/datum/sprite_accessory/ears/mam_ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return (!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC) + +/datum/sprite_accessory/ears/mam_ears/none name = "None" icon_state = "none" relevant_layers = null -/datum/sprite_accessory/mam_ears/axolotl +/datum/sprite_accessory/ears/mam_ears/axolotl name = "Axolotl" icon_state = "axolotl" -/datum/sprite_accessory/mam_ears/bat +/datum/sprite_accessory/ears/mam_ears/bat name = "Bat" icon_state = "bat" -/datum/sprite_accessory/mam_ears/bear +/datum/sprite_accessory/ears/mam_ears/bear name = "Bear" icon_state = "bear" -/datum/sprite_accessory/mam_ears/bigwolf +/datum/sprite_accessory/ears/mam_ears/bigwolf name = "Big Wolf" icon_state = "bigwolf" -/datum/sprite_accessory/mam_ears/bigwolfinner +/datum/sprite_accessory/ears/mam_ears/bigwolfinner name = "Big Wolf (ALT)" icon_state = "bigwolfinner" extra = TRUE extra_color_src = NONE -/datum/sprite_accessory/mam_ears/bigwolfdark +/datum/sprite_accessory/ears/mam_ears/bigwolfdark //alphabetical sort ignored here for ease-of-use name = "Dark Big Wolf" icon_state = "bigwolfdark" -/datum/sprite_accessory/mam_ears/bigwolfinnerdark +/datum/sprite_accessory/ears/mam_ears/bigwolfinnerdark name = "Dark Big Wolf (ALT)" icon_state = "bigwolfinnerdark" extra = TRUE extra_color_src = NONE -/datum/sprite_accessory/mam_ears/cat +/datum/sprite_accessory/ears/mam_ears/bunny + name = "Bunny" + icon_state = "bunny" + +/datum/sprite_accessory/ears/mam_ears/cat name = "Cat" icon_state = "cat" icon = 'icons/mob/mutant_bodyparts.dmi' @@ -226,100 +238,94 @@ extra = TRUE extra_color_src = NONE -/datum/sprite_accessory/mam_ears/catbig +/datum/sprite_accessory/ears/mam_ears/catbig name = "Cat, Big" icon_state = "catbig" -/datum/sprite_accessory/mam_ears/cow +/datum/sprite_accessory/ears/mam_ears/cow name = "Cow" icon_state = "cow" -/datum/sprite_accessory/mam_ears/curled +/datum/sprite_accessory/ears/mam_ears/curled name = "Curled Horn" icon_state = "horn1" color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_ears/deer +/datum/sprite_accessory/ears/mam_ears/deer name = "Deer" icon_state = "deer" color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_ears/eevee +/datum/sprite_accessory/ears/mam_ears/eevee name = "Eevee" icon_state = "eevee" - -/datum/sprite_accessory/mam_ears/elf +/datum/sprite_accessory/ears/mam_ears/elf name = "Elf" icon_state = "elf" color_src = MUTCOLORS3 - -/datum/sprite_accessory/mam_ears/elephant +/datum/sprite_accessory/ears/mam_ears/elephant name = "Elephant" icon_state = "elephant" -/datum/sprite_accessory/mam_ears/fennec +/datum/sprite_accessory/ears/mam_ears/fennec name = "Fennec" icon_state = "fennec" -/datum/sprite_accessory/mam_ears/fish +/datum/sprite_accessory/ears/mam_ears/fish name = "Fish" icon_state = "fish" -/datum/sprite_accessory/mam_ears/fox +/datum/sprite_accessory/ears/mam_ears/fox name = "Fox" icon_state = "fox" -/datum/sprite_accessory/mam_ears/husky +/datum/sprite_accessory/ears/mam_ears/husky name = "Husky" icon_state = "wolf" -/datum/sprite_accessory/mam_ears/kangaroo - name = "kangaroo" - icon_state = "kangaroo" - -/datum/sprite_accessory/mam_ears/jellyfish +/datum/sprite_accessory/ears/mam_ears/jellyfish name = "Jellyfish" icon_state = "jellyfish" color_src = HAIR -/datum/sprite_accessory/mam_ears/lab +/datum/sprite_accessory/ears/mam_ears/kangaroo + name = "kangaroo" + icon_state = "kangaroo" + +/datum/sprite_accessory/ears/mam_ears/lab name = "Dog, Long" icon_state = "lab" -/datum/sprite_accessory/mam_ears/murid +/datum/sprite_accessory/ears/mam_ears/murid name = "Murid" icon_state = "murid" -/datum/sprite_accessory/mam_ears/otie +/datum/sprite_accessory/ears/mam_ears/otie name = "Otusian" icon_state = "otie" -/datum/sprite_accessory/mam_ears/squirrel - name = "Squirrel" - icon_state = "squirrel" - -/datum/sprite_accessory/mam_ears/pede - name = "Scolipede" - icon_state = "pede" - -/datum/sprite_accessory/mam_ears/rabbit +/datum/sprite_accessory/ears/mam_ears/rabbit name = "Rabbit" icon_state = "rabbit" -/datum/sprite_accessory/mam_ears/sergal +/datum/sprite_accessory/ears/mam_ears/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/ears/mam_ears/sergal name = "Sergal" icon_state = "sergal" -/datum/sprite_accessory/mam_ears/skunk +/datum/sprite_accessory/ears/mam_ears/skunk name = "skunk" icon_state = "skunk" -/datum/sprite_accessory/mam_ears/wolf +/datum/sprite_accessory/ears/mam_ears/squirrel + name = "Squirrel" + icon_state = "squirrel" + +/datum/sprite_accessory/ears/mam_ears/wolf name = "Wolf" icon_state = "wolf" - -/datum/sprite_accessory/mam_ears/bunny - name = "Bunny" - icon_state = "bunny" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/frills.dm b/code/modules/mob/dead/new_player/sprite_accessories/frills.dm index 0aaec309a4..49013161a9 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/frills.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/frills.dm @@ -2,11 +2,19 @@ icon = 'icons/mob/mutant_bodyparts.dmi' relevant_layers = list(BODY_ADJ_LAYER) +/datum/sprite_accessory/frills/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return (!H.dna.features["frills"] || H.dna.features["frills"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC) + /datum/sprite_accessory/frills/none name = "None" icon_state = "none" relevant_layers = null +/datum/sprite_accessory/frills/aquatic + name = "Aquatic" + icon_state = "aqua" + /datum/sprite_accessory/frills/simple name = "Simple" icon_state = "simple" @@ -14,7 +22,3 @@ /datum/sprite_accessory/frills/short name = "Short" icon_state = "short" - -/datum/sprite_accessory/frills/aquatic - name = "Aquatic" - icon_state = "aqua" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm index 34988f5656..a07fdaa5d3 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_face.dm @@ -6,6 +6,10 @@ gender = MALE // barf (unless you're a dorf, dorfs dig chix w/ beards :P) // please make sure they're sorted alphabetically and categorized +/datum/sprite_accessory/facial_hair/shaved //this is exempt from the alphabetical sort + name = "Shaved" + icon_state = null + gender = NEUTER /datum/sprite_accessory/facial_hair/threeoclock name = "Beard (3 o\'Clock)" @@ -135,11 +139,6 @@ name = "Mutton Chops with Moustache" icon_state = "facial_muttonmus" -/datum/sprite_accessory/facial_hair/shaved - name = "Shaved" - icon_state = null - gender = NEUTER - /datum/sprite_accessory/facial_hair/sideburn name = "Sideburns" icon_state = "facial_sideburns" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm index 89f2dd5370..8e4e6ad617 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/hair_head.dm @@ -9,6 +9,10 @@ // try to spell // you do not need to define _s or _l sub-states, game automatically does this for you +/datum/sprite_accessory/hair/bald //this is exempt from the alphabetical sort + name = "Bald" + icon_state = "bald" + /datum/sprite_accessory/hair/afro name = "Afro" icon_state = "hair_afro" @@ -25,10 +29,6 @@ name = "Ahoge" icon_state = "hair_antenna" -/datum/sprite_accessory/hair/bald - name = "Bald" - icon_state = "bald" - /datum/sprite_accessory/hair/balding name = "Balding Hair" icon_state = "hair_e" @@ -791,6 +791,10 @@ name = "Volaju" icon_state = "hair_volaju" +/datum/sprite_accessory/hair/volajupompless + name = "Volaju (Alt)" + icon_state = "hair_volajupompless" + /datum/sprite_accessory/hair/wisp name = "Wisp" icon_state = "hair_wisp" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm index b39f48f858..aff342c7a6 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/horns.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/horns.dm @@ -3,27 +3,19 @@ color_src = HORNCOLOR relevant_layers = list(HORNS_LAYER) +/datum/sprite_accessory/horns/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return (!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC) + /datum/sprite_accessory/horns/none name = "None" icon_state = "none" relevant_layers = null -/datum/sprite_accessory/horns/simple - name = "Simple" - icon_state = "simple" - -/datum/sprite_accessory/horns/short - name = "Short" - icon_state = "short" - /datum/sprite_accessory/horns/curled name = "Curled" icon_state = "curled" -/datum/sprite_accessory/horns/ram - name = "Ram" - icon_state = "ram" - /datum/sprite_accessory/horns/angler name = "Angeler" icon_state = "angler" @@ -36,3 +28,15 @@ /datum/sprite_accessory/horns/guilmon name = "Guilmon" icon_state = "guilmon" + +/datum/sprite_accessory/horns/ram + name = "Ram" + icon_state = "ram" + +/datum/sprite_accessory/horns/simple + name = "Simple" + icon_state = "simple" + +/datum/sprite_accessory/horns/short + name = "Short" + icon_state = "short" 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 110ac69201..6019245b80 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 @@ -11,96 +11,90 @@ name = "Blank" icon_state = "blank" -/datum/sprite_accessory/screen/pink - name = "Pink" - icon_state = "pink" - -/datum/sprite_accessory/screen/green - name = "Green" - icon_state = "green" - -/datum/sprite_accessory/screen/red - name = "Red" - icon_state = "red" - /datum/sprite_accessory/screen/blue name = "Blue" icon_state = "blue" -/datum/sprite_accessory/screen/yellow - name = "Yellow" - icon_state = "yellow" - -/datum/sprite_accessory/screen/shower - name = "Shower" - icon_state = "shower" - -/datum/sprite_accessory/screen/nature - name = "Nature" - icon_state = "nature" - -/datum/sprite_accessory/screen/eight - name = "Eight" - icon_state = "eight" - -/datum/sprite_accessory/screen/goggles - name = "Goggles" - icon_state = "goggles" - -/datum/sprite_accessory/screen/heart - name = "Heart" - icon_state = "heart" - -/datum/sprite_accessory/screen/monoeye - name = "Mono eye" - icon_state = "monoeye" - /datum/sprite_accessory/screen/breakout name = "Breakout" icon_state = "breakout" -/datum/sprite_accessory/screen/purple - name = "Purple" - icon_state = "purple" - -/datum/sprite_accessory/screen/scroll - name = "Scroll" - icon_state = "scroll" +/datum/sprite_accessory/screen/bsod + name = "BSOD" + icon_state = "bsod" /datum/sprite_accessory/screen/console name = "Console" icon_state = "console" -/datum/sprite_accessory/screen/rgb - name = "RGB" - icon_state = "rgb" +/datum/sprite_accessory/screen/eight + name = "Eight" + icon_state = "eight" + +/datum/sprite_accessory/screen/eyes + name = "Eyes" + icon_state = "eyes" + +/datum/sprite_accessory/screen/ecgwave + name = "ECG wave" + icon_state = "ecgwave" + +/datum/sprite_accessory/screen/green + name = "Green" + icon_state = "green" + +/datum/sprite_accessory/screen/goggles + name = "Goggles" + icon_state = "goggles" /datum/sprite_accessory/screen/golglider name = "Gol Glider" icon_state = "golglider" +/datum/sprite_accessory/screen/heart + name = "Heart" + icon_state = "heart" + +/datum/sprite_accessory/screen/pink + name = "Pink" + icon_state = "pink" + +/datum/sprite_accessory/screen/red + name = "Red" + icon_state = "red" + +/datum/sprite_accessory/screen/monoeye + name = "Mono eye" + icon_state = "monoeye" + +/datum/sprite_accessory/screen/nature + name = "Nature" + icon_state = "nature" + +/datum/sprite_accessory/screen/purple + name = "Purple" + icon_state = "purple" + /datum/sprite_accessory/screen/rainbow name = "Rainbow" icon_state = "rainbow" -/datum/sprite_accessory/screen/sunburst - name = "Sunburst" - icon_state = "sunburst" - -/datum/sprite_accessory/screen/static - name = "Static" - icon_state = "static" - -//Oracle Station sprites - -/datum/sprite_accessory/screen/bsod - name = "BSOD" - icon_state = "bsod" - /datum/sprite_accessory/screen/redtext name = "Red Text" icon_state = "retext" +/datum/sprite_accessory/screen/rgb + name = "RGB" + icon_state = "rgb" + +/datum/sprite_accessory/screen/scroll + name = "Scroll" + icon_state = "scroll" + +/datum/sprite_accessory/screen/shower + name = "Shower" + icon_state = "shower" + /datum/sprite_accessory/screen/sinewave name = "Sine wave" icon_state = "sinewave" @@ -109,22 +103,25 @@ name = "Square wave" icon_state = "squarwave" -/datum/sprite_accessory/screen/ecgwave - name = "ECG wave" - icon_state = "ecgwave" +/datum/sprite_accessory/screen/stars + name = "Stars" + icon_state = "stars" -/datum/sprite_accessory/screen/eyes - name = "Eyes" - icon_state = "eyes" +/datum/sprite_accessory/screen/static + name = "Static" + icon_state = "static" + +/datum/sprite_accessory/screen/sunburst + name = "Sunburst" + icon_state = "sunburst" /datum/sprite_accessory/screen/textdrop name = "Text drop" icon_state = "textdrop" -/datum/sprite_accessory/screen/stars - name = "Stars" - icon_state = "stars" - +/datum/sprite_accessory/screen/yellow + name = "Yellow" + icon_state = "yellow" /****************************************** ************** IPC Antennas *************** @@ -145,14 +142,6 @@ name = "Angled Antennae" icon_state = "antennae" -/datum/sprite_accessory/antenna/tvantennae - name = "TV Antennae" - icon_state = "tvantennae" - -/datum/sprite_accessory/antenna/cyberhead - name = "Cyberhead" - icon_state = "cyberhead" - /datum/sprite_accessory/antenna/antlers name = "Antlers" icon_state = "antlers" @@ -160,3 +149,11 @@ /datum/sprite_accessory/antenna/crowned name = "Crowned" icon_state = "crowned" + +/datum/sprite_accessory/antenna/cyberhead + name = "Cyberhead" + icon_state = "cyberhead" + +/datum/sprite_accessory/antenna/tvantennae + name = "TV Antennae" + icon_state = "tvantennae" 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 2ec6da2da8..6f7b955d8f 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 @@ -30,6 +30,9 @@ var/alt_taur_mode = NONE //Same as above. var/hide_legs = USE_QUADRUPED_CLIP_MASK +/datum/sprite_accessory/taur/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (!tauric || (H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))) + /datum/sprite_accessory/taur/New() switch(hide_legs) if(USE_QUADRUPED_CLIP_MASK) @@ -46,6 +49,13 @@ relevant_layers = null hide_legs = FALSE +/datum/sprite_accessory/taur/canine + name = "Canine" + icon_state = "canine" + taur_mode = STYLE_PAW_TAURIC + color_src = MUTCOLORS + extra = TRUE + /datum/sprite_accessory/taur/cow name = "Cow" icon_state = "cow" @@ -92,6 +102,13 @@ color_src = MUTCOLORS extra = TRUE +/datum/sprite_accessory/taur/feline + name = "Feline" + icon_state = "feline" + taur_mode = STYLE_PAW_TAURIC + color_src = MUTCOLORS + extra = TRUE + /datum/sprite_accessory/taur/horse name = "Horse" icon_state = "horse" @@ -123,17 +140,3 @@ taur_mode = STYLE_SNEK_TAURIC color_src = MUTCOLORS hide_legs = USE_SNEK_CLIP_MASK - -/datum/sprite_accessory/taur/canine - name = "Canine" - icon_state = "canine" - taur_mode = STYLE_PAW_TAURIC - color_src = MUTCOLORS - extra = TRUE - -/datum/sprite_accessory/taur/feline - name = "Feline" - icon_state = "feline" - taur_mode = STYLE_PAW_TAURIC - color_src = MUTCOLORS - extra = TRUE diff --git a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm index 60e8ed1007..99d2c67cc9 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/snouts.dm @@ -3,14 +3,23 @@ mutant_part_string = "snout" relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) -/datum/sprite_accessory/snouts/sharp - name = "Sharp" - icon_state = "sharp" +/datum/sprite_accessory/snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC) + +/datum/sprite_accessory/snout/guilmon + name = "Guilmon" + icon_state = "guilmon" + color_src = MATRIXED /datum/sprite_accessory/snouts/round name = "Round" icon_state = "round" +/datum/sprite_accessory/snouts/sharp + name = "Sharp" + icon_state = "sharp" + /datum/sprite_accessory/snouts/sharplight name = "Sharp + Light" icon_state = "sharplight" @@ -19,11 +28,6 @@ name = "Round + Light" icon_state = "roundlight" -/datum/sprite_accessory/snout/guilmon - name = "Guilmon" - icon_state = "guilmon" - color_src = MATRIXED - //christ this was a mistake, but it's here just in case someone wants to selectively fix -- Pooj /************* Lizard compatable snoots *********** /datum/sprite_accessory/snouts/bird @@ -150,242 +154,251 @@ ************** Mammal Snouts ************** *******************************************/ -/datum/sprite_accessory/mam_snouts +/datum/sprite_accessory/snouts/mam_snouts color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_snouts.dmi' - recommended_species = list("mammal", "slimeperson", "insect", "podweak") + recommended_species = list("mammal", "slimeperson", "insect", "podweak", "lizard") mutant_part_string = "snout" relevant_layers = list(BODY_ADJ_LAYER, BODY_FRONT_LAYER) -/datum/sprite_accessory/mam_snouts/none +/datum/sprite_accessory/snouts/mam_snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) + return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC) + +/datum/sprite_accessory/snouts/mam_snouts/none name = "None" icon_state = "none" recommended_species = null relevant_layers = null -/datum/sprite_accessory/mam_snouts/bird +/datum/sprite_accessory/snouts/mam_snouts/bird name = "Beak" icon_state = "bird" -/datum/sprite_accessory/mam_snouts/bigbeak +/datum/sprite_accessory/snouts/mam_snouts/bigbeak name = "Big Beak" icon_state = "bigbeak" -/datum/sprite_accessory/mam_snouts/bug +/datum/sprite_accessory/snouts/mam_snouts/bug name = "Bug" icon_state = "bug" color_src = MUTCOLORS extra2 = TRUE extra2_color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_snouts/elephant +/datum/sprite_accessory/snouts/mam_snouts/elephant name = "Elephant" icon_state = "elephant" extra = TRUE extra_color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_snouts/lcanid - name = "Mammal, Long" - icon_state = "lcanid" +/datum/sprite_accessory/snouts/mam_snouts/husky + name = "Husky" + icon_state = "husky" -/datum/sprite_accessory/mam_snouts/lcanidalt - name = "Mammal, Long ALT" - icon_state = "lcanidalt" - -/datum/sprite_accessory/mam_snouts/scanid - name = "Mammal, Short" - icon_state = "scanid" - -/datum/sprite_accessory/mam_snouts/scanidalt - name = "Mammal, Short ALT" - icon_state = "scanidalt" - -/datum/sprite_accessory/mam_snouts/scanidalt2 - name = "Mammal, Short ALT 2" - icon_state = "scanidalt2" - -/datum/sprite_accessory/mam_snouts/wolf - name = "Mammal, Thick" - icon_state = "wolf" - -/datum/sprite_accessory/mam_snouts/wolfalt - name = "Mammal, Thick ALT" - icon_state = "wolfalt" - -/datum/sprite_accessory/mam_snouts/redpanda - name = "WahCoon" - icon_state = "wah" - -/datum/sprite_accessory/mam_snouts/redpandaalt - name = "WahCoon ALT" - icon_state = "wahalt" - -/datum/sprite_accessory/mam_snouts/rhino +/datum/sprite_accessory/snouts/mam_snouts/rhino name = "Horn" icon_state = "rhino" extra = TRUE extra = MUTCOLORS3 -/datum/sprite_accessory/mam_snouts/rodent +/datum/sprite_accessory/snouts/mam_snouts/rodent name = "Rodent" icon_state = "rodent" -/datum/sprite_accessory/mam_snouts/husky - name = "Husky" - icon_state = "husky" +/datum/sprite_accessory/snouts/mam_snouts/lcanid + name = "Mammal, Long" + icon_state = "lcanid" -/datum/sprite_accessory/mam_snouts/otie +/datum/sprite_accessory/snouts/mam_snouts/lcanidalt + name = "Mammal, Long ALT" + icon_state = "lcanidalt" + +/datum/sprite_accessory/snouts/mam_snouts/scanid + name = "Mammal, Short" + icon_state = "scanid" + +/datum/sprite_accessory/snouts/mam_snouts/scanidalt + name = "Mammal, Short ALT" + icon_state = "scanidalt" + +/datum/sprite_accessory/snouts/mam_snouts/scanidalt2 + name = "Mammal, Short ALT 2" + icon_state = "scanidalt2" + +/datum/sprite_accessory/snouts/mam_snouts/wolf + name = "Mammal, Thick" + icon_state = "wolf" + +/datum/sprite_accessory/snouts/mam_snouts/wolfalt + name = "Mammal, Thick ALT" + icon_state = "wolfalt" + +/datum/sprite_accessory/snouts/mam_snouts/otie name = "Otie" icon_state = "otie" -/datum/sprite_accessory/mam_snouts/pede - name = "Scolipede" - icon_state = "pede" - -/datum/sprite_accessory/mam_snouts/sergal - name = "Sergal" - icon_state = "sergal" - -/datum/sprite_accessory/mam_snouts/shark - name = "Shark" - icon_state = "shark" - -/datum/sprite_accessory/mam_snouts/hshark - name = "hShark" - icon_state = "hshark" - -/datum/sprite_accessory/mam_snouts/toucan - name = "Toucan" - icon_state = "toucan" - -/datum/sprite_accessory/mam_snouts/sharp - name = "Sharp" - icon_state = "sharp" - color_src = MUTCOLORS - -/datum/sprite_accessory/mam_snouts/round +/datum/sprite_accessory/snouts/mam_snouts/round name = "Round" icon_state = "round" color_src = MUTCOLORS -/datum/sprite_accessory/mam_snouts/sharplight - name = "Sharp + Light" - icon_state = "sharplight" - color_src = MUTCOLORS - -/datum/sprite_accessory/mam_snouts/roundlight +/datum/sprite_accessory/snouts/mam_snouts/roundlight name = "Round + Light" icon_state = "roundlight" color_src = MUTCOLORS +/datum/sprite_accessory/snouts/mam_snouts/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/snouts/mam_snouts/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/snouts/mam_snouts/shark + name = "Shark" + icon_state = "shark" + +/datum/sprite_accessory/snouts/mam_snouts/hshark + name = "hShark" + icon_state = "hshark" + +/datum/sprite_accessory/snouts/mam_snouts/sharp + name = "Sharp" + icon_state = "sharp" + color_src = MUTCOLORS + +/datum/sprite_accessory/snouts/mam_snouts/sharplight + name = "Sharp + Light" + icon_state = "sharplight" + color_src = MUTCOLORS + +/datum/sprite_accessory/snouts/mam_snouts/skulldog + name = "Skulldog" + icon_state = "skulldog" + extra = TRUE + extra_color_src = MATRIXED + +/datum/sprite_accessory/snouts/mam_snouts/toucan + name = "Toucan" + icon_state = "toucan" + +/datum/sprite_accessory/snouts/mam_snouts/redpanda + name = "WahCoon" + icon_state = "wah" + +/datum/sprite_accessory/snouts/mam_snouts/redpandaalt + name = "WahCoon ALT" + icon_state = "wahalt" /****************************************** **************** Snouts ******************* *************but higher up*****************/ -/datum/sprite_accessory/mam_snouts/fbird +/datum/sprite_accessory/snouts/mam_snouts/fbird name = "Beak (Top)" icon_state = "fbird" -/datum/sprite_accessory/mam_snouts/fbigbeak +/datum/sprite_accessory/snouts/mam_snouts/fbigbeak name = "Big Beak (Top)" icon_state = "fbigbeak" -/datum/sprite_accessory/mam_snouts/fbug +/datum/sprite_accessory/snouts/mam_snouts/fbug name = "Bug (Top)" icon_state = "fbug" color_src = MUTCOLORS extra2 = TRUE extra2_color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_snouts/felephant +/datum/sprite_accessory/snouts/mam_snouts/felephant name = "Elephant (Top)" icon_state = "felephant" extra = TRUE extra_color_src = MUTCOLORS3 -/datum/sprite_accessory/mam_snouts/flcanid - name = "Mammal, Long (Top)" - icon_state = "flcanid" - -/datum/sprite_accessory/mam_snouts/flcanidalt - name = "Mammal, Long ALT (Top)" - icon_state = "flcanidalt" - -/datum/sprite_accessory/mam_snouts/fscanid - name = "Mammal, Short (Top)" - icon_state = "fscanid" - -/datum/sprite_accessory/mam_snouts/fscanidalt - name = "Mammal, Short ALT (Top)" - icon_state = "fscanidalt" - -/datum/sprite_accessory/mam_snouts/fscanidalt2 - name = "Mammal, Short ALT 2 (Top)" - icon_state = "fscanidalt2" - -/datum/sprite_accessory/mam_snouts/fwolf - name = "Mammal, Thick (Top)" - icon_state = "fwolf" - -/datum/sprite_accessory/mam_snouts/fwolfalt - name = "Mammal, Thick ALT (Top)" - icon_state = "fwolfalt" - -/datum/sprite_accessory/mam_snouts/fredpanda - name = "WahCoon (Top)" - icon_state = "fwah" - -/datum/sprite_accessory/mam_snouts/frhino +/datum/sprite_accessory/snouts/mam_snouts/frhino name = "Horn (Top)" icon_state = "frhino" extra = TRUE extra = MUTCOLORS3 -/datum/sprite_accessory/mam_snouts/frodent - name = "Rodent (Top)" - icon_state = "frodent" - -/datum/sprite_accessory/mam_snouts/fhusky +/datum/sprite_accessory/snouts/mam_snouts/fhusky name = "Husky (Top)" icon_state = "fhusky" -/datum/sprite_accessory/mam_snouts/fotie +/datum/sprite_accessory/snouts/mam_snouts/flcanid + name = "Mammal, Long (Top)" + icon_state = "flcanid" + +/datum/sprite_accessory/snouts/mam_snouts/flcanidalt + name = "Mammal, Long ALT (Top)" + icon_state = "flcanidalt" + +/datum/sprite_accessory/snouts/mam_snouts/fscanid + name = "Mammal, Short (Top)" + icon_state = "fscanid" + +/datum/sprite_accessory/snouts/mam_snouts/fscanidalt + name = "Mammal, Short ALT (Top)" + icon_state = "fscanidalt" + +/datum/sprite_accessory/snouts/mam_snouts/fscanidalt2 + name = "Mammal, Short ALT 2 (Top)" + icon_state = "fscanidalt2" + +/datum/sprite_accessory/snouts/mam_snouts/fwolf + name = "Mammal, Thick (Top)" + icon_state = "fwolf" + +/datum/sprite_accessory/snouts/mam_snouts/fwolfalt + name = "Mammal, Thick ALT (Top)" + icon_state = "fwolfalt" + +/datum/sprite_accessory/snouts/mam_snouts/fotie name = "Otie (Top)" icon_state = "fotie" -/datum/sprite_accessory/mam_snouts/fpede - name = "Scolipede (Top)" - icon_state = "fpede" +/datum/sprite_accessory/snouts/mam_snouts/frodent + name = "Rodent (Top)" + icon_state = "frodent" -/datum/sprite_accessory/mam_snouts/fsergal - name = "Sergal (Top)" - icon_state = "fsergal" - -/datum/sprite_accessory/mam_snouts/fshark - name = "Shark (Top)" - icon_state = "fshark" - -/datum/sprite_accessory/mam_snouts/ftoucan - name = "Toucan (Top)" - icon_state = "ftoucan" - -/datum/sprite_accessory/mam_snouts/fsharp - name = "Sharp (Top)" - icon_state = "fsharp" - color_src = MUTCOLORS - -/datum/sprite_accessory/mam_snouts/fround +/datum/sprite_accessory/snouts/mam_snouts/fround name = "Round (Top)" icon_state = "fround" color_src = MUTCOLORS -/datum/sprite_accessory/mam_snouts/fsharplight +/datum/sprite_accessory/snouts/mam_snouts/froundlight + name = "Round + Light (Top)" + icon_state = "froundlight" + color_src = MUTCOLORS + +/datum/sprite_accessory/snouts/mam_snouts/fpede + name = "Scolipede (Top)" + icon_state = "fpede" + +/datum/sprite_accessory/snouts/mam_snouts/fsergal + name = "Sergal (Top)" + icon_state = "fsergal" + +/datum/sprite_accessory/snouts/mam_snouts/fshark + name = "Shark (Top)" + icon_state = "fshark" + +/datum/sprite_accessory/snouts/mam_snouts/fsharp + name = "Sharp (Top)" + icon_state = "fsharp" + color_src = MUTCOLORS + +/datum/sprite_accessory/snouts/mam_snouts/fsharplight name = "Sharp + Light (Top)" icon_state = "fsharplight" color_src = MUTCOLORS -/datum/sprite_accessory/mam_snouts/froundlight - name = "Round + Light (Top)" - icon_state = "froundlight" - color_src = MUTCOLORS +/datum/sprite_accessory/snouts/mam_snouts/ftoucan + name = "Toucan (Top)" + icon_state = "ftoucan" + +/datum/sprite_accessory/snouts/mam_snouts/fredpanda + name = "WahCoon (Top)" + icon_state = "fwah" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm index 19ec677a72..ffb808eede 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/socks.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/socks.dm @@ -20,6 +20,10 @@ name = "Knee-high - Bee" icon_state = "bee_knee" +/datum/sprite_accessory/underwear/socks/christmas_knee + name = "Knee-High - Christmas" + icon_state = "christmas_knee" + /datum/sprite_accessory/underwear/socks/commie_knee name = "Knee-High - Commie" icon_state = "commie_knee" @@ -32,6 +36,14 @@ name = "Knee-high - Rainbow" icon_state = "rainbow_knee" +/datum/sprite_accessory/underwear/socks/candycaner_knee + name = "Knee-High - Red Candy Cane" + icon_state = "candycaner_knee" + +/datum/sprite_accessory/underwear/socks/candycaneg_knee //ignore alphabetisation for ease of use in scenarios like this + name = "Knee-High - Green Candy Cane" + icon_state = "candycaneg_knee" + /datum/sprite_accessory/underwear/socks/striped_knee name = "Knee-high - Striped" icon_state = "striped_knee" @@ -46,18 +58,6 @@ name = "Knee-High - UK" icon_state = "uk_knee" -/datum/sprite_accessory/underwear/socks/christmas_knee - name = "Knee-High - Christmas" - icon_state = "christmas_knee" - -/datum/sprite_accessory/underwear/socks/candycaner_knee - name = "Knee-High - Red Candy Cane" - icon_state = "candycaner_knee" - -/datum/sprite_accessory/underwear/socks/candycaneg_knee - name = "Knee-High - Green Candy Cane" - icon_state = "candycaneg_knee" - /datum/sprite_accessory/underwear/socks/socks_norm name = "Normal" icon_state = "socks_norm" @@ -129,22 +129,34 @@ name = "Thigh-high - Bee" icon_state = "bee_thigh" +/datum/sprite_accessory/underwear/socks/christmas_thigh + name = "Thigh-high - Christmas" + icon_state = "christmas_thigh" + /datum/sprite_accessory/underwear/socks/commie_thigh name = "Thigh-high - Commie" icon_state = "commie_thigh" -/datum/sprite_accessory/underwear/socks/usa_thigh - name = "Thigh-high - Freedom" - icon_state = "assblastusa_thigh" - /datum/sprite_accessory/underwear/socks/fishnet name = "Thigh-high - Fishnet" icon_state = "fishnet" +/datum/sprite_accessory/underwear/socks/usa_thigh + name = "Thigh-high - Freedom" + icon_state = "assblastusa_thigh" + /datum/sprite_accessory/underwear/socks/rainbow_thigh name = "Thigh-high - Rainbow" icon_state = "rainbow_thigh" +/datum/sprite_accessory/underwear/socks/candycaner_thigh + name = "Thigh-high - Red Candy Cane" + icon_state = "candycaner_thigh" + +/datum/sprite_accessory/underwear/socks/candycaneg_thigh + name = "Thigh-high - Green Candy Cane" + icon_state = "candycaneg_thigh" + /datum/sprite_accessory/underwear/socks/striped_thigh name = "Thigh-high - Striped" icon_state = "striped_thigh" @@ -157,16 +169,4 @@ /datum/sprite_accessory/underwear/socks/uk_thigh name = "Thigh-high - UK" - icon_state = "uk_thigh" - -/datum/sprite_accessory/underwear/socks/christmas_thigh - name = "Thigh-high - Christmas" - icon_state = "christmas_thigh" - -/datum/sprite_accessory/underwear/socks/candycaner_thigh - name = "Thigh-high - Red Candy Cane" - icon_state = "candycaner_thigh" - -/datum/sprite_accessory/underwear/socks/candycaneg_thigh - name = "Thigh-high - Green Candy Cane" - icon_state = "candycaneg_thigh" \ No newline at end of file + icon_state = "uk_thigh" \ No newline at end of file diff --git a/code/modules/mob/dead/new_player/sprite_accessories/spines.dm b/code/modules/mob/dead/new_player/sprite_accessories/spines.dm index 54749d5ea9..5d7207c934 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/spines.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/spines.dm @@ -2,10 +2,16 @@ icon = 'icons/mob/mutant_bodyparts.dmi' relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER) +/datum/sprite_accessory/spines/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) + /datum/sprite_accessory/spines_animated icon = 'icons/mob/mutant_bodyparts.dmi' relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER) +/datum/sprite_accessory/spines_animated/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return ((!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || H.dna.species.mutant_bodyparts["tail"]) + /datum/sprite_accessory/spines/none name = "None" icon_state = "none" @@ -15,21 +21,13 @@ name = "None" icon_state = "none" -/datum/sprite_accessory/spines/short - name = "Short" - icon_state = "short" +/datum/sprite_accessory/spines/aqautic + name = "Aquatic" + icon_state = "aqua" -/datum/sprite_accessory/spines_animated/short - name = "Short" - icon_state = "short" - -/datum/sprite_accessory/spines/shortmeme - name = "Short + Membrane" - icon_state = "shortmeme" - -/datum/sprite_accessory/spines_animated/shortmeme - name = "Short + Membrane" - icon_state = "shortmeme" +/datum/sprite_accessory/spines_animated/aqautic + name = "Aquatic" + icon_state = "aqua" /datum/sprite_accessory/spines/long name = "Long" @@ -47,10 +45,18 @@ name = "Long + Membrane" icon_state = "longmeme" -/datum/sprite_accessory/spines/aqautic - name = "Aquatic" - icon_state = "aqua" +/datum/sprite_accessory/spines/short + name = "Short" + icon_state = "short" -/datum/sprite_accessory/spines_animated/aqautic - name = "Aquatic" - icon_state = "aqua" +/datum/sprite_accessory/spines_animated/short + name = "Short" + icon_state = "short" + +/datum/sprite_accessory/spines/shortmeme + name = "Short + Membrane" + icon_state = "shortmeme" + +/datum/sprite_accessory/spines_animated/shortmeme + name = "Short + Membrane" + icon_state = "shortmeme" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm index a2884ab944..9addd15dca 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/synthliz.dm @@ -1,36 +1,30 @@ //Synth snouts (This is the most important part) -/datum/sprite_accessory/mam_snouts/synthliz +/datum/sprite_accessory/snouts/mam_snouts/synthliz recommended_species = list("synthliz") icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi' color_src = MUTCOLORS name = "Synthetic Lizard - Snout" icon_state = "synthliz_basic" -/datum/sprite_accessory/mam_snouts/synthliz/synthliz_under +/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_under icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi' color_src = MATRIXED name = "Synthetic Lizard - Snout Under" icon_state = "synthliz_under" -/datum/sprite_accessory/mam_snouts/synthliz/synthliz_tert +/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_tert icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi' color_src = MATRIXED name = "Synthetic Lizard - Snout Tertiary" icon_state = "synthliz_tert" -/datum/sprite_accessory/mam_snouts/synthliz/synthliz_tertunder +/datum/sprite_accessory/snouts/mam_snouts/synthliz/synthliz_tertunder icon = 'modular_citadel/icons/mob/synthliz_snouts.dmi' color_src = MATRIXED name = "Synthetic Lizard - Snout Tertiary Under" icon_state = "synthliz_tertunder" //Synth body markings -/datum/sprite_accessory/mam_body_markings/synthliz - recommended_species = list("synthliz") - icon = 'modular_citadel/icons/mob/synthliz_body_markings.dmi' - name = "Synthetic Lizard - Plates" - icon_state = "synthlizscutes" - /datum/sprite_accessory/mam_body_markings/synthliz/synthliz_pecs icon = 'modular_citadel/icons/mob/synthliz_body_markings.dmi' name = "Synthetic Lizard - Pecs" @@ -41,15 +35,21 @@ name = "Synthetic Lizard - Pecs Light" icon_state = "synthlizpecslight" +/datum/sprite_accessory/mam_body_markings/synthliz + recommended_species = list("synthliz") + icon = 'modular_citadel/icons/mob/synthliz_body_markings.dmi' + name = "Synthetic Lizard - Plates" + icon_state = "synthlizscutes" + //Synth tails -/datum/sprite_accessory/mam_tails/synthliz +/datum/sprite_accessory/tails/mam_tails/synthliz recommended_species = list("synthliz") icon = 'modular_citadel/icons/mob/synthliz_tails.dmi' color_src = MUTCOLORS name = "Synthetic Lizard" icon_state = "synthliz" -/datum/sprite_accessory/mam_tails_animated/synthliz +/datum/sprite_accessory/tails_animated/mam_tails_animated/synthliz recommended_species = list("synthliz") icon = 'modular_citadel/icons/mob/synthliz_tails.dmi' color_src = MUTCOLORS @@ -70,17 +70,17 @@ name = "Synthetic Lizard - Curled" icon_state = "synth_curled" -/datum/sprite_accessory/antenna/synthliz/synthliz_thick +/datum/sprite_accessory/antenna/synthliz/synth_horns icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi' color_src = MUTCOLORS - name = "Synthetic Lizard - Thick" - icon_state = "synth_thick" + name = "Synthetic Lizard - Horns" + icon_state = "synth_horns" -/datum/sprite_accessory/antenna/synthliz/synth_thicklight +/datum/sprite_accessory/antenna/synthliz/synth_hornslight icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi' color_src = MATRIXED - name = "Synthetic Lizard - Thick Light" - icon_state = "synth_thicklight" + name = "Synthetic Lizard - Horns Light" + icon_state = "synth_hornslight" /datum/sprite_accessory/antenna/synthliz/synth_short icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi' @@ -100,17 +100,17 @@ name = "Synthetic Lizard - Sharp Light" icon_state = "synth_sharplight" -/datum/sprite_accessory/antenna/synthliz/synth_horns +/datum/sprite_accessory/antenna/synthliz/synthliz_thick icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi' color_src = MUTCOLORS - name = "Synthetic Lizard - Horns" - icon_state = "synth_horns" + name = "Synthetic Lizard - Thick" + icon_state = "synth_thick" -/datum/sprite_accessory/antenna/synthliz/synth_hornslight +/datum/sprite_accessory/antenna/synthliz/synth_thicklight icon = 'modular_citadel/icons/mob/synthliz_antennas.dmi' color_src = MATRIXED - name = "Synthetic Lizard - Horns Light" - icon_state = "synth_hornslight" + name = "Synthetic Lizard - Thick Light" + icon_state = "synth_thicklight" //Synth Taurs (Ported from Virgo) /datum/sprite_accessory/taur/synthliz 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 33dbd7059f..d9e2de1525 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/tails.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/tails.dm @@ -3,6 +3,9 @@ mutant_part_string = "tail" relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/tails/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return ((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) + /datum/sprite_accessory/tails_animated icon = 'icons/mob/mutant_bodyparts.dmi' mutant_part_string = "tailwag" @@ -12,38 +15,10 @@ ************* Lizard Tails **************** *******************************************/ -/datum/sprite_accessory/tails/lizard/smooth - name = "Smooth" - icon_state = "smooth" - -/datum/sprite_accessory/tails_animated/lizard/smooth - name = "Smooth" - icon_state = "smooth" - -/datum/sprite_accessory/tails/lizard/dtiger - name = "Dark Tiger" - icon_state = "dtiger" - -/datum/sprite_accessory/tails_animated/lizard/dtiger - name = "Dark Tiger" - icon_state = "dtiger" - -/datum/sprite_accessory/tails/lizard/ltiger - name = "Light Tiger" - icon_state = "ltiger" - -/datum/sprite_accessory/tails_animated/lizard/ltiger - name = "Light Tiger" - icon_state = "ltiger" - -/datum/sprite_accessory/tails/lizard/spikes - name = "Spikes" - icon_state = "spikes" - -/datum/sprite_accessory/tails_animated/lizard/spikes - name = "Spikes" - icon_state = "spikes" +/datum/sprite_accessory/tails_animated/lizard/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) || H.dna.species.mutant_bodyparts["tail_lizard"]) +//this goes first regardless of alphabetical order /datum/sprite_accessory/tails/lizard/none name = "None" icon_state = "None" @@ -66,11 +41,13 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' -/datum/sprite_accessory/body_markings/guilmon - name = "Guilmon" - icon_state = "guilmon" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/markings_notmammals.dmi' +/datum/sprite_accessory/tails/lizard/dtiger + name = "Dark Tiger" + icon_state = "dtiger" + +/datum/sprite_accessory/tails_animated/lizard/dtiger + name = "Dark Tiger" + icon_state = "dtiger" /datum/sprite_accessory/tails/lizard/guilmon name = "Guilmon" @@ -84,6 +61,30 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/lizard/ltiger + name = "Light Tiger" + icon_state = "ltiger" + +/datum/sprite_accessory/tails_animated/lizard/ltiger + name = "Light Tiger" + icon_state = "ltiger" + +/datum/sprite_accessory/tails/lizard/smooth + name = "Smooth" + icon_state = "smooth" + +/datum/sprite_accessory/tails_animated/lizard/smooth + name = "Smooth" + icon_state = "smooth" + +/datum/sprite_accessory/tails/lizard/spikes + name = "Spikes" + icon_state = "spikes" + +/datum/sprite_accessory/tails_animated/lizard/spikes + name = "Spikes" + icon_state = "spikes" + /****************************************** ************** Human Tails **************** *******************************************/ @@ -98,17 +99,8 @@ icon_state = "none" relevant_layers = null -/datum/sprite_accessory/tails/human/ailurus - name = "Red Panda" - icon_state = "wah" - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - color_src = MATRIXED - -/datum/sprite_accessory/tails_animated/human/ailurus - name = "Red Panda" - icon_state = "wah" - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - color_src = MATRIXED +/datum/sprite_accessory/tails_animated/human/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric)|| H.dna.species.mutant_bodyparts["tail_human"]) /datum/sprite_accessory/tails/human/axolotl name = "Axolotl" @@ -122,22 +114,22 @@ icon = 'modular_citadel/icons/mob/mam_tails.dmi' color_src = MATRIXED -/datum/sprite_accessory/mam_tails/batl +/datum/sprite_accessory/tails/mam_tails/batl name = "Bat (Long)" icon = 'modular_citadel/icons/mob/mam_tails.dmi' icon_state = "batl" -/datum/sprite_accessory/mam_tails_animated/batl +/datum/sprite_accessory/tails_animated/mam_tails_animated/batl name = "Bat (Long)" icon = 'modular_citadel/icons/mob/mam_tails.dmi' icon_state = "batl" -/datum/sprite_accessory/mam_tails/bats +/datum/sprite_accessory/tails/mam_tails/bats name = "Bat (Short)" icon = 'modular_citadel/icons/mob/mam_tails.dmi' icon_state = "bats" -/datum/sprite_accessory/mam_tails_animated/bats +/datum/sprite_accessory/tails_animated/mam_tails_animated/bats name = "Bat (Short)" icon = 'modular_citadel/icons/mob/mam_tails.dmi' icon_state = "bats" @@ -190,6 +182,14 @@ icon = 'modular_citadel/icons/mob/mam_tails.dmi' color_src = MATRIXED +/datum/sprite_accessory/tails/human/corvid + name = "Corvid" + icon_state = "crow" + +/datum/sprite_accessory/tails_animated/human/corvid + name = "Corvid" + icon_state = "crow" + /datum/sprite_accessory/tails/human/cow name = "Cow" icon_state = "cow" @@ -202,13 +202,25 @@ icon = 'modular_citadel/icons/mob/mam_tails.dmi' color_src = MATRIXED -/datum/sprite_accessory/tails/human/corvid - name = "Corvid" - icon_state = "crow" +/datum/sprite_accessory/tails/human/dtiger + name = "Dark Tiger" + icon_state = "dtiger" -/datum/sprite_accessory/tails_animated/human/corvid - name = "Corvid" - icon_state = "crow" +/datum/sprite_accessory/tails_animated/human/dtiger + name = "Dark Tiger" + icon_state = "dtiger" + +/datum/sprite_accessory/tails/human/datashark + name = "datashark" + icon_state = "datashark" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + +/datum/sprite_accessory/tails_animated/human/datashark + name = "datashark" + icon_state = "datashark" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' /datum/sprite_accessory/tails/human/eevee name = "Eevee" @@ -289,7 +301,7 @@ color_src = MATRIXED /datum/sprite_accessory/tails_animated/human/insect - name = "insect" + name = "Insect" icon_state = "insect" icon = 'modular_citadel/icons/mob/mam_tails.dmi' color_src = MATRIXED @@ -306,6 +318,14 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/human/ltiger + name = "Light Tiger" + icon_state = "ltiger" + +/datum/sprite_accessory/tails_animated/human/ltiger + name = "Light Tiger" + icon_state = "ltiger" + /datum/sprite_accessory/tails/human/murid name = "Murid" icon_state = "murid" @@ -318,18 +338,6 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' -/datum/sprite_accessory/tails/human/otie - name = "Otusian" - icon_state = "otie" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - -/datum/sprite_accessory/tails_animated/human/otie - name = "Otusian" - icon_state = "otie" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - /datum/sprite_accessory/tails/orca name = "Orca" icon_state = "orca" @@ -342,15 +350,15 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' -/datum/sprite_accessory/tails/human/pede - name = "Scolipede" - icon_state = "pede" +/datum/sprite_accessory/tails/human/otie + name = "Otusian" + icon_state = "otie" color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' -/datum/sprite_accessory/tails_animated/human/pede - name = "Scolipede" - icon_state = "pede" +/datum/sprite_accessory/tails_animated/human/otie + name = "Otusian" + icon_state = "otie" color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' @@ -366,6 +374,30 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/human/ailurus + name = "Red Panda" + icon_state = "wah" + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + color_src = MATRIXED + +/datum/sprite_accessory/tails_animated/human/ailurus + name = "Red Panda" + icon_state = "wah" + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + color_src = MATRIXED + +/datum/sprite_accessory/tails/human/pede + name = "Scolipede" + icon_state = "pede" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + +/datum/sprite_accessory/tails_animated/human/pede + name = "Scolipede" + icon_state = "pede" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + /datum/sprite_accessory/tails/human/sergal name = "Sergal" icon_state = "sergal" @@ -378,6 +410,18 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' +/datum/sprite_accessory/tails/human/shark + name = "Shark" + icon_state = "shark" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + +/datum/sprite_accessory/tails_animated/human/shark + name = "Shark" + icon_state = "shark" + color_src = MATRIXED + icon = 'modular_citadel/icons/mob/mam_tails.dmi' + /datum/sprite_accessory/tails/human/skunk name = "skunk" icon_state = "skunk" @@ -406,30 +450,6 @@ name = "Spikes" icon_state = "spikes" -/datum/sprite_accessory/tails/human/shark - name = "Shark" - icon_state = "shark" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - -/datum/sprite_accessory/tails_animated/human/shark - name = "Shark" - icon_state = "shark" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - -/datum/sprite_accessory/tails/human/datashark - name = "datashark" - icon_state = "datashark" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - -/datum/sprite_accessory/tails_animated/human/datashark - name = "datashark" - icon_state = "datashark" - color_src = MATRIXED - icon = 'modular_citadel/icons/mob/mam_tails.dmi' - /datum/sprite_accessory/tails/human/straighttail name = "Straight Tail" icon_state = "straighttail" @@ -486,22 +506,6 @@ color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' -/datum/sprite_accessory/tails/human/dtiger - name = "Dark Tiger" - icon_state = "dtiger" - -/datum/sprite_accessory/tails_animated/human/dtiger - name = "Dark Tiger" - icon_state = "dtiger" - -/datum/sprite_accessory/tails/human/ltiger - name = "Light Tiger" - icon_state = "ltiger" - -/datum/sprite_accessory/tails_animated/human/ltiger - name = "Light Tiger" - icon_state = "ltiger" - /datum/sprite_accessory/tails/human/wolf name = "Wolf" icon_state = "wolf" @@ -518,368 +522,371 @@ ************** Furry Tails **************** *******************************************/ -/datum/sprite_accessory/mam_tails +/datum/sprite_accessory/tails/mam_tails color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' recommended_species = list("mammal", "slimeperson", "podweak", "felinid", "insect") mutant_part_string = "tail" relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) -/datum/sprite_accessory/mam_tails/none +/datum/sprite_accessory/tails/mam_tails/none name = "None" icon_state = "none" recommended_species = null relevant_layers = null -/datum/sprite_accessory/mam_tails_animated +/datum/sprite_accessory/tails_animated/mam_tails_animated color_src = MATRIXED icon = 'modular_citadel/icons/mob/mam_tails.dmi' mutant_part_string = "tailwag" relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER) -/datum/sprite_accessory/mam_tails_animated/none +/datum/sprite_accessory/tails_animated/mam_tails_animated/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) || H.dna.species.mutant_bodyparts["mam_tail"]) + +/datum/sprite_accessory/tails_animated/mam_tails_animated/none name = "None" icon_state = "none" relevant_layers = null -/datum/sprite_accessory/mam_tails/ailurus - name = "Red Panda" - icon_state = "wah" - extra = TRUE - -/datum/sprite_accessory/mam_tails_animated/ailurus - name = "Red Panda" - icon_state = "wah" - extra = TRUE - -/datum/sprite_accessory/mam_tails/axolotl +/datum/sprite_accessory/tails/mam_tails/axolotl name = "Axolotl" icon_state = "axolotl" -/datum/sprite_accessory/mam_tails_animated/axolotl +/datum/sprite_accessory/tails_animated/mam_tails_animated/axolotl name = "Axolotl" icon_state = "axolotl" -/datum/sprite_accessory/mam_tails/batl +/datum/sprite_accessory/tails/mam_tails/batl name = "Bat (Long)" icon_state = "batl" -/datum/sprite_accessory/mam_tails_animated/batl +/datum/sprite_accessory/tails_animated/mam_tails_animated/batl name = "Bat (Long)" icon_state = "batl" -/datum/sprite_accessory/mam_tails/bats +/datum/sprite_accessory/tails/mam_tails/bats name = "Bat (Short)" icon_state = "bats" -/datum/sprite_accessory/mam_tails_animated/bats +/datum/sprite_accessory/tails_animated/mam_tails_animated/bats name = "Bat (Short)" icon_state = "bats" -/datum/sprite_accessory/mam_tails/bee +/datum/sprite_accessory/tails/mam_tails/bee name = "Bee" icon_state = "bee" -/datum/sprite_accessory/mam_tails_animated/bee +/datum/sprite_accessory/tails_animated/mam_tails_animated/bee name = "Bee" icon_state = "bee" -/datum/sprite_accessory/mam_tails/cat +/datum/sprite_accessory/tails/mam_tails/cat name = "Cat" icon_state = "cat" color_src = HAIR -/datum/sprite_accessory/mam_tails_animated/cat +/datum/sprite_accessory/tails_animated/mam_tails_animated/cat name = "Cat" icon_state = "cat" color_src = HAIR -/datum/sprite_accessory/mam_tails/catbig +/datum/sprite_accessory/tails/mam_tails/catbig name = "Cat, Big" icon_state = "catbig" -/datum/sprite_accessory/mam_tails_animated/catbig +/datum/sprite_accessory/tails_animated/mam_tails_animated/catbig name = "Cat, Big" icon_state = "catbig" -/datum/sprite_accessory/mam_tails/twocat +/datum/sprite_accessory/tails/mam_tails/twocat name = "Cat, Double" icon_state = "twocat" -/datum/sprite_accessory/mam_tails_animated/twocat +/datum/sprite_accessory/tails_animated/mam_tails_animated/twocat name = "Cat, Double" icon_state = "twocat" -/datum/sprite_accessory/mam_tails/corvid +/datum/sprite_accessory/tails/mam_tails/corvid name = "Corvid" icon_state = "crow" -/datum/sprite_accessory/mam_tails_animated/corvid +/datum/sprite_accessory/tails_animated/mam_tails_animated/corvid name = "Corvid" icon_state = "crow" -/datum/sprite_accessory/mam_tail/cow +/datum/sprite_accessory/tails/mam_tail/cow name = "Cow" icon_state = "cow" -/datum/sprite_accessory/mam_tails_animated/cow +/datum/sprite_accessory/tails_animated/mam_tails_animated/cow name = "Cow" icon_state = "cow" -/datum/sprite_accessory/mam_tails/eevee - name = "Eevee" - icon_state = "eevee" - -/datum/sprite_accessory/mam_tails_animated/eevee - name = "Eevee" - icon_state = "eevee" - -/datum/sprite_accessory/mam_tails/fennec - name = "Fennec" - icon_state = "fennec" - -/datum/sprite_accessory/mam_tails_animated/fennec - name = "Fennec" - icon_state = "fennec" - -/datum/sprite_accessory/mam_tails/human/fish - name = "Fish" - icon_state = "fish" - -/datum/sprite_accessory/mam_tails_animated/human/fish - name = "Fish" - icon_state = "fish" - -/datum/sprite_accessory/mam_tails/fox - name = "Fox" - icon_state = "fox" - -/datum/sprite_accessory/mam_tails_animated/fox - name = "Fox" - icon_state = "fox" - -/datum/sprite_accessory/mam_tails/hawk - name = "Hawk" - icon_state = "hawk" - -/datum/sprite_accessory/mam_tails_animated/hawk - name = "Hawk" - icon_state = "hawk" - -/datum/sprite_accessory/mam_tails/horse - name = "Horse" - icon_state = "horse" - color_src = HAIR - -/datum/sprite_accessory/mam_tails_animated/horse - name = "Horse" - icon_state = "horse" - color_src = HAIR - -/datum/sprite_accessory/mam_tails/husky - name = "Husky" - icon_state = "husky" - -/datum/sprite_accessory/mam_tails_animated/husky - name = "Husky" - icon_state = "husky" - -datum/sprite_accessory/mam_tails/insect - name = "Insect" - icon_state = "insect" - -/datum/sprite_accessory/mam_tails_animated/insect - name = "Insect" - icon_state = "insect" - -/datum/sprite_accessory/mam_tails/kangaroo - name = "kangaroo" - icon_state = "kangaroo" - -/datum/sprite_accessory/mam_tails_animated/kangaroo - name = "kangaroo" - icon_state = "kangaroo" - -/datum/sprite_accessory/mam_tails/kitsune - name = "Kitsune" - icon_state = "kitsune" - -/datum/sprite_accessory/mam_tails_animated/kitsune - name = "Kitsune" - icon_state = "kitsune" - -/datum/sprite_accessory/mam_tails/lab - name = "Lab" - icon_state = "lab" - -/datum/sprite_accessory/mam_tails_animated/lab - name = "Lab" - icon_state = "lab" - -/datum/sprite_accessory/mam_tails/murid - name = "Murid" - icon_state = "murid" - -/datum/sprite_accessory/mam_tails_animated/murid - name = "Murid" - icon_state = "murid" - -/datum/sprite_accessory/mam_tails/otie - name = "Otusian" - icon_state = "otie" - -/datum/sprite_accessory/mam_tails_animated/otie - name = "Otusian" - icon_state = "otie" - -/datum/sprite_accessory/mam_tails/orca - name = "Orca" - icon_state = "orca" - -/datum/sprite_accessory/mam_tails_animated/orca - name = "Orca" - icon_state = "orca" - -/datum/sprite_accessory/mam_tails/pede - name = "Scolipede" - icon_state = "pede" - -/datum/sprite_accessory/mam_tails_animated/pede - name = "Scolipede" - icon_state = "pede" - -/datum/sprite_accessory/mam_tails/rabbit - name = "Rabbit" - icon_state = "rabbit" - -/datum/sprite_accessory/mam_tails_animated/rabbit - name = "Rabbit" - icon_state = "rabbit" - -/datum/sprite_accessory/mam_tails/sergal - name = "Sergal" - icon_state = "sergal" - -/datum/sprite_accessory/mam_tails_animated/sergal - name = "Sergal" - icon_state = "sergal" - -/datum/sprite_accessory/mam_tails/skunk - name = "Skunk" - icon_state = "skunk" - -/datum/sprite_accessory/mam_tails_animated/skunk - name = "Skunk" - icon_state = "skunk" - -/datum/sprite_accessory/mam_tails/smooth - name = "Smooth" - icon_state = "smooth" - color_src = MUTCOLORS - icon = 'icons/mob/mutant_bodyparts.dmi' - -/datum/sprite_accessory/mam_tails_animated/smooth - name = "Smooth" - icon_state = "smooth" - color_src = MUTCOLORS - icon = 'icons/mob/mutant_bodyparts.dmi' - -/datum/sprite_accessory/mam_tails_animated/spikes - name = "Spikes" - icon_state = "spikes" - color_src = MUTCOLORS - icon = 'icons/mob/mutant_bodyparts.dmi' - -/datum/sprite_accessory/mam_tails/spikes - name = "Spikes" - icon_state = "spikes" - color_src = MUTCOLORS - icon = 'icons/mob/mutant_bodyparts.dmi' - -/datum/sprite_accessory/mam_tails/shark - name = "Shark" - icon_state = "shark" - -/datum/sprite_accessory/mam_tails_animated/shark - name = "Shark" - icon_state = "shark" - -/datum/sprite_accessory/mam_tails/shepherd - name = "Shepherd" - icon_state = "shepherd" - -/datum/sprite_accessory/mam_tails_animated/shepherd - name = "Shepherd" - icon_state = "shepherd" - -/datum/sprite_accessory/mam_tails/straighttail - name = "Straight Tail" - icon_state = "straighttail" - -/datum/sprite_accessory/mam_tails_animated/straighttail - name = "Straight Tail" - icon_state = "straighttail" - -/datum/sprite_accessory/mam_tails/squirrel - name = "Squirrel" - icon_state = "squirrel" - -/datum/sprite_accessory/mam_tails_animated/squirrel - 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" - -/datum/sprite_accessory/mam_tails_animated/tentacle - name = "Tentacle" - icon_state = "tentacle" - -/datum/sprite_accessory/mam_tails/tiger - name = "Tiger" - icon_state = "tiger" - -/datum/sprite_accessory/mam_tails_animated/tiger - name = "Tiger" - icon_state = "tiger" - -/datum/sprite_accessory/mam_tails/dtiger +/datum/sprite_accessory/tails/mam_tails/dtiger name = "Dark Tiger" icon_state = "dtiger" color_src = MUTCOLORS icon = 'icons/mob/mutant_bodyparts.dmi' -/datum/sprite_accessory/mam_tails_animated/dtiger +/datum/sprite_accessory/tails_animated/mam_tails_animated/dtiger name = "Dark Tiger" icon_state = "dtiger" color_src = MUTCOLORS icon = 'icons/mob/mutant_bodyparts.dmi' -/datum/sprite_accessory/mam_tails/ltiger +/datum/sprite_accessory/tails/mam_tails/eevee + name = "Eevee" + icon_state = "eevee" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/eevee + name = "Eevee" + icon_state = "eevee" + +/datum/sprite_accessory/tails/mam_tails/fennec + name = "Fennec" + icon_state = "fennec" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/fennec + name = "Fennec" + icon_state = "fennec" + +/datum/sprite_accessory/tails/mam_tails/human/fish + name = "Fish" + icon_state = "fish" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/human/fish + name = "Fish" + icon_state = "fish" + +/datum/sprite_accessory/tails/mam_tails/fox + name = "Fox" + icon_state = "fox" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/fox + name = "Fox" + icon_state = "fox" + +/datum/sprite_accessory/tails/mam_tails/hawk + name = "Hawk" + icon_state = "hawk" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/hawk + name = "Hawk" + icon_state = "hawk" + +/datum/sprite_accessory/tails/mam_tails/horse + name = "Horse" + icon_state = "horse" + color_src = HAIR + +/datum/sprite_accessory/tails_animated/mam_tails_animated/horse + name = "Horse" + icon_state = "horse" + color_src = HAIR + +/datum/sprite_accessory/tails/mam_tails/husky + name = "Husky" + icon_state = "husky" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/husky + name = "Husky" + icon_state = "husky" + +datum/sprite_accessory/tails/mam_tails/insect + name = "Insect" + icon_state = "insect" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/insect + name = "Insect" + icon_state = "insect" + +/datum/sprite_accessory/tails/mam_tails/kangaroo + name = "kangaroo" + icon_state = "kangaroo" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/kangaroo + name = "kangaroo" + icon_state = "kangaroo" + +/datum/sprite_accessory/tails/mam_tails/kitsune + name = "Kitsune" + icon_state = "kitsune" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/kitsune + name = "Kitsune" + icon_state = "kitsune" + +/datum/sprite_accessory/tails/mam_tails/lab + name = "Lab" + icon_state = "lab" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/lab + name = "Lab" + icon_state = "lab" + +/datum/sprite_accessory/tails/mam_tails/ltiger name = "Light Tiger" icon_state = "ltiger" color_src = MUTCOLORS icon = 'icons/mob/mutant_bodyparts.dmi' -/datum/sprite_accessory/mam_tails_animated/ltiger +/datum/sprite_accessory/tails_animated/mam_tails_animated/ltiger name = "Light Tiger" icon_state = "ltiger" color_src = MUTCOLORS icon = 'icons/mob/mutant_bodyparts.dmi' -/datum/sprite_accessory/mam_tails/wolf +/datum/sprite_accessory/tails/mam_tails/murid + name = "Murid" + icon_state = "murid" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/murid + name = "Murid" + icon_state = "murid" + +/datum/sprite_accessory/tails/mam_tails/orca + name = "Orca" + icon_state = "orca" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/orca + name = "Orca" + icon_state = "orca" + +/datum/sprite_accessory/tails/mam_tails/otie + name = "Otusian" + icon_state = "otie" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/otie + name = "Otusian" + icon_state = "otie" + +/datum/sprite_accessory/tails/mam_tails/rabbit + name = "Rabbit" + icon_state = "rabbit" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/rabbit + name = "Rabbit" + icon_state = "rabbit" + +/datum/sprite_accessory/tails/mam_tails/ailurus + name = "Red Panda" + icon_state = "wah" + extra = TRUE + +/datum/sprite_accessory/tails_animated/mam_tails_animated/ailurus + name = "Red Panda" + icon_state = "wah" + extra = TRUE + +/datum/sprite_accessory/tails/mam_tails/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/pede + name = "Scolipede" + icon_state = "pede" + +/datum/sprite_accessory/tails/mam_tails/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/sergal + name = "Sergal" + icon_state = "sergal" + +/datum/sprite_accessory/tails/mam_tails/shark + name = "Shark" + icon_state = "shark" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/shark + name = "Shark" + icon_state = "shark" + +/datum/sprite_accessory/tails/mam_tails/shepherd + name = "Shepherd" + icon_state = "shepherd" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/shepherd + name = "Shepherd" + icon_state = "shepherd" + +/datum/sprite_accessory/tails/mam_tails/skunk + name = "Skunk" + icon_state = "skunk" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/skunk + name = "Skunk" + icon_state = "skunk" + +/datum/sprite_accessory/tails/mam_tails/smooth + name = "Smooth" + icon_state = "smooth" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/tails_animated/mam_tails_animated/smooth + name = "Smooth" + icon_state = "smooth" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/tails_animated/mam_tails_animated/spikes + name = "Spikes" + icon_state = "spikes" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/tails/mam_tails/spikes + name = "Spikes" + icon_state = "spikes" + color_src = MUTCOLORS + icon = 'icons/mob/mutant_bodyparts.dmi' + +/datum/sprite_accessory/tails/mam_tails/straighttail + name = "Straight Tail" + icon_state = "straighttail" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/straighttail + name = "Straight Tail" + icon_state = "straighttail" + +/datum/sprite_accessory/tails/mam_tails/squirrel + name = "Squirrel" + icon_state = "squirrel" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/squirrel + name = "Squirrel" + icon_state = "squirrel" + +/datum/sprite_accessory/tails/mam_tails/tamamo_kitsune + name = "Tamamo Kitsune Tails" + icon_state = "9sune" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/tamamo_kitsune + name = "Tamamo Kitsune Tails" + icon_state = "9sune" + +/datum/sprite_accessory/tails/mam_tails/tentacle + name = "Tentacle" + icon_state = "tentacle" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/tentacle + name = "Tentacle" + icon_state = "tentacle" + +/datum/sprite_accessory/tails/mam_tails/tiger + name = "Tiger" + icon_state = "tiger" + +/datum/sprite_accessory/tails_animated/mam_tails_animated/tiger + name = "Tiger" + icon_state = "tiger" + +/datum/sprite_accessory/tails/mam_tails/wolf name = "Wolf" icon_state = "wolf" -/datum/sprite_accessory/mam_tails_animated/wolf +/datum/sprite_accessory/tails_animated/mam_tails_animated/wolf name = "Wolf" icon_state = "wolf" diff --git a/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm b/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm index 73233f3e09..1be02c207e 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/undershirt.dm @@ -12,6 +12,38 @@ // please make sure they're sorted alphabetically and categorized +/datum/sprite_accessory/underwear/top/cowboyshirt + name = "Cowboy Shirt Black" + icon_state = "cowboyshirt" + +/datum/sprite_accessory/underwear/top/cowboyshirt/red + name = "Cowboy Shirt Red" + icon_state = "cowboyshirt_red" + +/datum/sprite_accessory/underwear/top/cowboyshirt/navy + name = "Cowboy Shirt Navy" + icon_state = "cowboyshirt_navy" + +/datum/sprite_accessory/underwear/top/cowboyshirt/white + name = "Cowboy Shirt White" + icon_state = "cowboyshirt_white" + +/datum/sprite_accessory/underwear/top/cowboyshirt/s + name = "Cowboy Shirt Shortsleeved Black" + icon_state = "cowboyshirt_s" + +/datum/sprite_accessory/underwear/top/cowboyshirt/red/s + name = "Cowboy Shirt Shortsleeved Red" + icon_state = "cowboyshirt_reds" + +/datum/sprite_accessory/underwear/top/cowboyshirt/navy/s + name = "Cowboy Shirt Shortsleeved Navy" + icon_state = "cowboyshirt_navys" + +/datum/sprite_accessory/underwear/top/cowboyshirt/white/s + name = "Cowboy Shirt Shortsleeved White" + icon_state = "cowboyshirt_whites" + /datum/sprite_accessory/underwear/top/longjon name = "Long John Shirt" icon_state = "ljont" @@ -30,36 +62,6 @@ icon_state = "undershirt" has_color = TRUE -/datum/sprite_accessory/underwear/top/bowlingw - name = "Shirt - Bowling" - icon_state = "bowlingw" - has_color = TRUE - -/datum/sprite_accessory/underwear/top/bowling - name = "Shirt, Bowling - Red" - icon_state = "bowling" - -/datum/sprite_accessory/underwear/top/bowlingp - name = "Shirt, Bowling - Pink" - icon_state = "bowlingp" - -/datum/sprite_accessory/underwear/top/bowlinga - name = "Shirt, Bowling - Aqua" - icon_state = "bowlinga" - -/datum/sprite_accessory/underwear/top/bluejersey - name = "Shirt, Jersey - Blue" - icon_state = "shirt_bluejersey" - -/datum/sprite_accessory/underwear/top/redjersey - name = "Shirt, Jersey - Red" - icon_state = "shirt_redjersey" - -/datum/sprite_accessory/underwear/top/polo - name = "Shirt - Polo" - icon_state = "polo" - has_color = TRUE - /datum/sprite_accessory/underwear/top/alienshirt name = "Shirt - Alien" icon_state = "shirt_alien" @@ -72,6 +74,23 @@ name = "Shirt - Bee" icon_state = "bee_shirt" +/datum/sprite_accessory/underwear/top/bowlingw + name = "Shirt - Bowling" + icon_state = "bowlingw" + has_color = TRUE + +/datum/sprite_accessory/underwear/top/bowlinga + name = "Shirt, Bowling - Aqua" + icon_state = "bowlinga" + +/datum/sprite_accessory/underwear/top/bowling + name = "Shirt, Bowling - Red" + icon_state = "bowling" + +/datum/sprite_accessory/underwear/top/bowlingp + name = "Shirt, Bowling - Pink" + icon_state = "bowlingp" + /datum/sprite_accessory/underwear/top/clownshirt name = "Shirt - Clown" icon_state = "shirt_clown" @@ -88,6 +107,14 @@ name = "Shirt - I Love NT" icon_state = "ilovent" +/datum/sprite_accessory/underwear/top/bluejersey + name = "Shirt, Jersey - Blue" + icon_state = "shirt_bluejersey" + +/datum/sprite_accessory/underwear/top/redjersey + name = "Shirt, Jersey - Red" + icon_state = "shirt_redjersey" + /datum/sprite_accessory/underwear/top/lover name = "Shirt - Lover" icon_state = "lover" @@ -112,6 +139,11 @@ name = "Shirt - Pogoman" icon_state = "pogoman" +/datum/sprite_accessory/underwear/top/polo + name = "Shirt - Polo" + icon_state = "polo" + has_color = TRUE + /datum/sprite_accessory/underwear/top/question name = "Shirt - Question" icon_state = "shirt_question" @@ -120,6 +152,23 @@ name = "Shirt - Skull" icon_state = "shirt_skull" +/datum/sprite_accessory/underwear/top/shortsleeve + name = "Shirt - Short Sleeved" + icon_state = "shortsleeve" + has_color = TRUE + +/datum/sprite_accessory/underwear/top/blueshirtsport + name = "Shirt, Sports - Blue" + icon_state = "blueshirtsport" + +/datum/sprite_accessory/underwear/top/greenshirtsport + name = "Shirt, Sports - Green" + icon_state = "greenshirtsport" + +/datum/sprite_accessory/underwear/top/redshirtsport + name = "Shirt, Sports - Red" + icon_state = "redshirtsport" + /datum/sprite_accessory/underwear/top/ss13 name = "Shirt - SS13" icon_state = "shirt_ss13" @@ -141,27 +190,6 @@ name = "Shirt - USA" icon_state = "shirt_assblastusa" -/datum/sprite_accessory/underwear/top/shortsleeve - name = "Shirt - Short Sleeved" - icon_state = "shortsleeve" - has_color = TRUE - -/datum/sprite_accessory/underwear/top/blueshirtsport - name = "Shirt, Sports - Blue" - icon_state = "blueshirtsport" - -/datum/sprite_accessory/underwear/top/greenshirtsport - name = "Shirt, Sports - Green" - icon_state = "greenshirtsport" - -/datum/sprite_accessory/underwear/top/redshirtsport - name = "Shirt, Sports - Red" - icon_state = "redshirtsport" - -/datum/sprite_accessory/underwear/top/tankfire - name = "Tank Top - Fire" - icon_state = "tank_fire" - /datum/sprite_accessory/underwear/top/tanktop name = "Tank Top" icon_state = "tanktop" @@ -172,6 +200,10 @@ icon_state = "tanktop_alt" has_color = TRUE +/datum/sprite_accessory/underwear/top/tankfire + name = "Tank Top - Fire" + icon_state = "tank_fire" + /datum/sprite_accessory/underwear/top/tanktop_midriff name = "Tank Top - Midriff" icon_state = "tank_midriff" @@ -192,6 +224,8 @@ name = "Tank top - Sun" icon_state = "tank_sun" +//feminine accessories from here on + /datum/sprite_accessory/underwear/top/babydoll name = "Baby-Doll" icon_state = "babydoll" @@ -210,15 +244,25 @@ has_color = TRUE gender = FEMALE -/datum/sprite_accessory/underwear/top/bra_thin - name = "Bra - Thin" - icon_state = "bra_thin" - has_color = TRUE +/datum/sprite_accessory/underwear/top/bra_beekini + name = "Bra - Bee-kini" + icon_state = "bra_bee-kini" gender = FEMALE -/datum/sprite_accessory/underwear/top/bra_kinky - name = "Bra - Kinky Black" - icon_state = "bra_kinky" +/datum/sprite_accessory/underwear/top/bra_binder + name = "Bra (binder)" + icon_state = "bra_binder" + has_color = TRUE + +/datum/sprite_accessory/underwear/top/bra_binder_strapless + name = "Bra (binder, strapless)" + icon_state = "bra_binder_strapless" + has_color = TRUE + + +/datum/sprite_accessory/underwear/top/bra_commie + name = "Bra - Commie" + icon_state = "bra_commie" gender = FEMALE /datum/sprite_accessory/underwear/top/bra_freedom @@ -226,33 +270,17 @@ icon_state = "bra_assblastusa" gender = FEMALE -/datum/sprite_accessory/underwear/top/bra_commie - name = "Bra - Commie" - icon_state = "bra_commie" - gender = FEMALE - -/datum/sprite_accessory/underwear/top/bra_beekini - name = "Bra - Bee-kini" - icon_state = "bra_bee-kini" - gender = FEMALE - -/datum/sprite_accessory/underwear/top/bra_uk - name = "Bra - UK" - icon_state = "bra_uk" - gender = FEMALE - -/datum/sprite_accessory/underwear/top/bra_neko - name = "Bra - Neko" - icon_state = "bra_neko" - has_color = TRUE - gender = FEMALE - /datum/sprite_accessory/underwear/top/halterneck_bra name = "Bra - Halterneck" icon_state = "halterneck_bra" has_color = TRUE gender = FEMALE +/datum/sprite_accessory/underwear/top/bra_kinky + name = "Bra - Kinky Black" + icon_state = "bra_kinky" + gender = FEMALE + /datum/sprite_accessory/underwear/top/sports_bra name = "Bra, Sports" icon_state = "sports_bra" @@ -283,9 +311,21 @@ has_color = TRUE gender = FEMALE -/datum/sprite_accessory/underwear/top/fishnet_sleeves - name = "Fishnet - sleeves" - icon_state = "fishnet_sleeves" +/datum/sprite_accessory/underwear/top/bra_thin + name = "Bra - Thin" + icon_state = "bra_thin" + has_color = TRUE + gender = FEMALE + +/datum/sprite_accessory/underwear/top/bra_neko + name = "Bra - Neko" + icon_state = "bra_neko" + has_color = TRUE + gender = FEMALE + +/datum/sprite_accessory/underwear/top/bra_uk + name = "Bra - UK" + icon_state = "bra_uk" gender = FEMALE /datum/sprite_accessory/underwear/top/fishnet_gloves @@ -293,6 +333,11 @@ icon_state = "fishnet_gloves" gender = FEMALE +/datum/sprite_accessory/underwear/top/fishnet_sleeves + name = "Fishnet - sleeves" + icon_state = "fishnet_sleeves" + gender = FEMALE + /datum/sprite_accessory/underwear/top/fishnet_base name = "Fishnet - top" icon_state = "fishnet_body" @@ -315,39 +360,3 @@ icon_state = "tubetop" has_color = TRUE gender = FEMALE - -/datum/sprite_accessory/underwear/top/cowboyshirt - name = "Cowboy Shirt Black" - icon_state = "cowboyshirt" - -/datum/sprite_accessory/underwear/top/cowboyshirt/s - name = "Cowboy Shirt Shortsleeved Black" - icon_state = "cowboyshirt_s" - -/datum/sprite_accessory/underwear/top/cowboyshirt/white - name = "Cowboy Shirt White" - icon_state = "cowboyshirt_white" - -/datum/sprite_accessory/underwear/top/cowboyshirt/white/s - name = "Cowboy Shirt Shortsleeved White" - icon_state = "cowboyshirt_whites" - -/datum/sprite_accessory/underwear/top/cowboyshirt/navy - name = "Cowboy Shirt Navy" - icon_state = "cowboyshirt_navy" - -/datum/sprite_accessory/underwear/top/cowboyshirt/navy/s - name = "Cowboy Shirt Shortsleeved Navy" - icon_state = "cowboyshirt_navys" - -/datum/sprite_accessory/underwear/top/cowboyshirt/red - name = "Cowboy Shirt Red" - icon_state = "cowboyshirt_red" - -/datum/sprite_accessory/underwear/top/cowboyshirt/red/s - name = "Cowboy Shirt Shortsleeved Red" - icon_state = "cowboyshirt_reds" - - - - diff --git a/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm b/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm index 58d5e1ba88..edfeba79f1 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/underwear.dm @@ -10,18 +10,6 @@ icon_state = null covers_groin = FALSE -/datum/sprite_accessory/underwear/bottom/mankini - name = "Mankini" - icon_state = "mankini" - has_color = TRUE - gender = MALE - -/datum/sprite_accessory/underwear/bottom/male_kinky - name = "Jockstrap" - icon_state = "jockstrap" - has_color = TRUE - gender = MALE - /datum/sprite_accessory/underwear/bottom/briefs name = "Briefs" icon_state = "briefs" @@ -77,6 +65,26 @@ has_digitigrade = TRUE has_color = TRUE +/datum/sprite_accessory/underwear/bottom/male_kinky + name = "Jockstrap" + icon_state = "jockstrap" + has_color = TRUE + gender = MALE + +/datum/sprite_accessory/underwear/bottom/longjon + name = "Long John Bottoms" + icon_state = "ljonb" + has_digitigrade = TRUE + has_color = TRUE + +/datum/sprite_accessory/underwear/bottom/mankini + name = "Mankini" + icon_state = "mankini" + has_color = TRUE + gender = MALE + +//feminine underwear from here on + /datum/sprite_accessory/underwear/bottom/panties name = "Panties" icon_state = "panties" @@ -89,11 +97,6 @@ has_color = TRUE gender = FEMALE -/datum/sprite_accessory/underwear/bottom/fishnet_lower - name = "Panties - Fishnet" - icon_state = "fishnet_lower" - gender = FEMALE - /datum/sprite_accessory/underwear/bottom/female_beekini name = "Panties - Bee-kini" icon_state = "panties_bee-kini" @@ -104,6 +107,11 @@ icon_state = "panties_commie" gender = FEMALE +/datum/sprite_accessory/underwear/bottom/fishnet_lower + name = "Panties - Fishnet" + icon_state = "fishnet_lower" + gender = FEMALE + /datum/sprite_accessory/underwear/bottom/female_usastripe name = "Panties - Freedom" icon_state = "panties_assblastusa" @@ -114,11 +122,6 @@ icon_state = "panties_kinky" gender = FEMALE -/datum/sprite_accessory/underwear/bottom/panties_uk - name = "Panties - UK" - icon_state = "panties_uk" - gender = FEMALE - /datum/sprite_accessory/underwear/bottom/panties_neko name = "Panties - Neko" icon_state = "panties_neko" @@ -149,17 +152,10 @@ has_color = TRUE gender = FEMALE -/datum/sprite_accessory/underwear/bottom/longjon - name = "Long John Bottoms" - icon_state = "ljonb" - has_digitigrade = TRUE - has_color = TRUE - -/datum/sprite_accessory/underwear/bottom/swimsuit_red - name = "Swimsuit, One Piece - Red" - icon_state = "swimming_red" +/datum/sprite_accessory/underwear/bottom/panties_uk + name = "Panties - UK" + icon_state = "panties_uk" gender = FEMALE - covers_chest = TRUE /datum/sprite_accessory/underwear/bottom/swimsuit name = "Swimsuit, One Piece - Black" @@ -173,6 +169,12 @@ gender = FEMALE covers_chest = TRUE +/datum/sprite_accessory/underwear/bottom/swimsuit_red + name = "Swimsuit, One Piece - Red" + icon_state = "swimming_red" + gender = FEMALE + covers_chest = TRUE + /datum/sprite_accessory/underwear/bottom/thong name = "Thong" icon_state = "thong" @@ -184,5 +186,3 @@ icon_state = "thong_babydoll" has_color = TRUE gender = FEMALE - - diff --git a/code/modules/mob/dead/new_player/sprite_accessories/wings.dm b/code/modules/mob/dead/new_player/sprite_accessories/wings.dm index 34767a10f1..fb71bb483d 100644 --- a/code/modules/mob/dead/new_player/sprite_accessories/wings.dm +++ b/code/modules/mob/dead/new_player/sprite_accessories/wings.dm @@ -5,10 +5,16 @@ icon_state = "none" relevant_layers = null +/datum/sprite_accessory/wings/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (!H.dna.features["wings"] || H.dna.features["wings"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) + /datum/sprite_accessory/wings_open icon = 'icons/mob/wings.dmi' relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/wings_open/is_not_visible(var/mob/living/carbon/human/H, var/tauric) + return (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)) || H.dna.species.mutant_bodyparts["wings"]) + /datum/sprite_accessory/wings_open/angel name = "Angel" icon_state = "angel" @@ -52,6 +58,10 @@ dimension_y = 34 relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER) +/datum/sprite_accessory/deco_wings/atlas + name = "Atlas" + icon_state = "atlas" + /datum/sprite_accessory/deco_wings/bat name = "Bat" icon_state = "bat" @@ -60,6 +70,10 @@ name = "Bee" icon_state = "bee" +/datum/sprite_accessory/deco_wings/deathhead + name = "Deathshead" + icon_state = "deathhead" + /datum/sprite_accessory/deco_wings/fairy name = "Fairy" icon_state = "fairy" @@ -68,14 +82,6 @@ name = "Feathery" icon_state = "feathery" -/datum/sprite_accessory/deco_wings/atlas - name = "Atlas" - icon_state = "atlas" - -/datum/sprite_accessory/deco_wings/deathhead - name = "Deathshead" - icon_state = "deathhead" - /datum/sprite_accessory/deco_wings/firewatch name = "Firewatch" icon_state = "firewatch" @@ -144,6 +150,10 @@ icon_state = "none" relevant_layers = null +/datum/sprite_accessory/insect_wings/atlas + name = "Atlas" + icon_state = "atlas" + /datum/sprite_accessory/insect_wings/bat name = "Bat" icon_state = "bat" @@ -152,6 +162,10 @@ name = "Bee" icon_state = "bee" +/datum/sprite_accessory/insect_wings/deathhead + name = "Deathshead" + icon_state = "deathhead" + /datum/sprite_accessory/insect_wings/fairy name = "Fairy" icon_state = "fairy" @@ -160,14 +174,6 @@ name = "Feathery" icon_state = "feathery" -/datum/sprite_accessory/insect_wings/atlas - name = "Atlas" - icon_state = "atlas" - -/datum/sprite_accessory/insect_wings/deathhead - name = "Deathshead" - icon_state = "deathhead" - /datum/sprite_accessory/insect_wings/firewatch name = "Firewatch" icon_state = "firewatch" @@ -176,6 +182,10 @@ name = "Gothic" icon_state = "gothic" +/datum/sprite_accessory/insect_wings/jungle + name = "Jungle" + icon_state = "jungle" + /datum/sprite_accessory/insect_wings/lovers name = "Lovers" icon_state = "lovers" @@ -192,6 +202,10 @@ name = "Moon Fly" icon_state = "moonfly" +/datum/sprite_accessory/insect_wings/oakworm + name = "Oak Worm" + icon_state = "oakworm" + /datum/sprite_accessory/insect_wings/plain name = "Plain" icon_state = "plain" @@ -224,14 +238,6 @@ name = "White Fly" icon_state = "whitefly" -/datum/sprite_accessory/insect_wings/oakworm - name = "Oak Worm" - icon_state = "oakworm" - -/datum/sprite_accessory/insect_wings/jungle - name = "Jungle" - icon_state = "jungle" - /datum/sprite_accessory/insect_wings/witchwing name = "Witch Wing" icon_state = "witchwing" diff --git a/code/modules/mob/dead/observer/notificationprefs.dm b/code/modules/mob/dead/observer/notificationprefs.dm index 6c1d76eaf3..524ff80d5d 100644 --- a/code/modules/mob/dead/observer/notificationprefs.dm +++ b/code/modules/mob/dead/observer/notificationprefs.dm @@ -3,12 +3,10 @@ set name = "Notification preferences" set desc = "Notification preferences" - var/datum/notificationpanel/panel = new(usr) + var/datum/notificationpanel/panel = new(usr) panel.ui_interact(usr) - - /datum/notificationpanel var/client/user @@ -21,10 +19,13 @@ else src.user = user -/datum/notificationpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/notificationpanel/ui_state(mob/user) + return GLOB.observer_state + +/datum/notificationpanel/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 270, 360, master_ui, state) + ui = new(user, src, "NotificationPreferences") ui.open() /datum/notificationpanel/ui_data(mob/user) @@ -35,8 +36,7 @@ "key" = key, "enabled" = (user.ckey in GLOB.poll_ignore[key]), "desc" = GLOB.poll_ignore_desc[key] - )) - + )) /datum/notificationpanel/ui_act(action, params) if(..()) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 397af1b9d0..a0df1ee938 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -54,6 +54,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) // Used for displaying in ghost chat, without changing the actual name // of the mob var/deadchat_name + var/datum/orbit_menu/orbit_menu var/datum/spawners_menu/spawners_menu /mob/dead/observer/Initialize(mapload, mob/body) @@ -161,6 +162,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) updateallghostimages() + QDEL_NULL(orbit_menu) QDEL_NULL(spawners_menu) return ..() @@ -490,10 +492,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Orbit" // "Haunt" set desc = "Follow and orbit a mob." - var/list/mobs = getpois(skip_mindless=1) - var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs - var/mob/target = mobs[input] - ManualFollow(target) + if(!orbit_menu) + orbit_menu = new(src) + + orbit_menu.ui_interact(src) // This is the ghost's follow verb with an argument /mob/dead/observer/proc/ManualFollow(atom/movable/target) @@ -837,13 +839,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/vv_edit_var(var_name, var_value) . = ..() switch(var_name) - if("icon") + if(NAMEOF(src, icon)) ghostimage_default.icon = icon ghostimage_simple.icon = icon - if("icon_state") + if(NAMEOF(src, icon_state)) ghostimage_default.icon_state = icon_state ghostimage_simple.icon_state = icon_state - if("fun_verbs") + if(NAMEOF(src, fun_verbs)) if(fun_verbs) verbs += /mob/dead/observer/verb/boo verbs += /mob/dead/observer/verb/possess @@ -903,6 +905,22 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp else to_chat(usr, "Can't become a pAI candidate while not dead!") +/mob/dead/observer/verb/mafia_game_signup() + set category = "Ghost" + set name = "Signup for Mafia" + set desc = "Sign up for a game of Mafia to pass the time while dead." + mafia_signup() +/mob/dead/observer/proc/mafia_signup() + if(!client) + return + if(!isobserver(src)) + to_chat(usr, "You must be a ghost to join mafia!") + return + var/datum/mafia_controller/game = GLOB.mafia_game //this needs to change if you want multiple mafia games up at once. + if(!game) + game = create_mafia_game("mafia") + game.ui_interact(usr) + /mob/dead/observer/CtrlShiftClick(mob/user) if(isobserver(user) && check_rights(R_SPAWN)) change_mob_type( /mob/living/carbon/human , null, null, TRUE) //always delmob, ghosts shouldn't be left lingering @@ -925,7 +943,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/vv_edit_var(var_name, var_value) . = ..() - if(var_name == "invisibility") + if(var_name == NAMEOF(src, invisibility)) set_invisibility(invisibility) // updates light /proc/set_observer_default_invisibility(amount, message=null) diff --git a/code/modules/mob/dead/observer/orbit.dm b/code/modules/mob/dead/observer/orbit.dm new file mode 100644 index 0000000000..b81172afad --- /dev/null +++ b/code/modules/mob/dead/observer/orbit.dm @@ -0,0 +1,82 @@ +/datum/orbit_menu + var/mob/dead/observer/owner + +/datum/orbit_menu/New(mob/dead/observer/new_owner) + if(!istype(new_owner)) + qdel(src) + owner = new_owner + +/datum/orbit_menu/ui_state(mob/user) + return GLOB.observer_state + +/datum/orbit_menu/ui_interact(mob/user, datum/tgui/ui) + if (!ui) + ui = new(user, src, "Orbit") + ui.open() + +/datum/orbit_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + if (..()) + return + + if (action == "orbit") + var/ref = params["ref"] + var/atom/movable/poi = (locate(ref) in GLOB.mob_list) || (locate(ref) in GLOB.poi_list) + if (poi != null) + owner.ManualFollow(poi) + +/datum/orbit_menu/ui_data(mob/user) + var/list/data = list() + + var/list/alive = list() + var/list/antagonists = list() + var/list/dead = list() + var/list/ghosts = list() + var/list/misc = list() + var/list/npcs = list() + + var/list/pois = getpois(skip_mindless = 1) + for (var/name in pois) + var/list/serialized = list() + serialized["name"] = name + + var/poi = pois[name] + + serialized["ref"] = REF(poi) + + var/mob/M = poi + if (istype(M)) + if (isobserver(M)) + ghosts += list(serialized) + else if (M.stat == DEAD) + dead += list(serialized) + else if (M.mind == null) + npcs += list(serialized) + else + var/number_of_orbiters = M.orbiters?.orbiters?.len + if (number_of_orbiters) + serialized["orbiters"] = number_of_orbiters + + var/datum/mind/mind = M.mind + var/was_antagonist = FALSE + + for (var/_A in mind.antag_datums) + var/datum/antagonist/A = _A + if (A.show_to_ghosts) + was_antagonist = TRUE + serialized["antag"] = A.name + antagonists += list(serialized) + break + + if (!was_antagonist) + alive += list(serialized) + else + misc += list(serialized) + + data["alive"] = alive + data["antagonists"] = antagonists + data["dead"] = dead + data["ghosts"] = ghosts + data["misc"] = misc + data["npcs"] = npcs + + return data diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 74775203b1..9ac270bf34 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -5,13 +5,11 @@ /mob/proc/get_active_held_item() return get_item_for_held_index(active_hand_index) - //Finds the opposite limb for the active one (eg: upper left arm will find the item in upper right arm) //So we're treating each "pair" of limbs as a team, so "both" refers to them /mob/proc/get_inactive_held_item() return get_item_for_held_index(get_inactive_hand_index()) - //Finds the opposite index for the active one (eg: upper left arm will find the item in upper right arm) //So we're treating each "pair" of limbs as a team, so "both" refers to them /mob/proc/get_inactive_hand_index() @@ -24,12 +22,9 @@ other_hand = 0 return other_hand - /mob/proc/get_item_for_held_index(i) if(i > 0 && i <= held_items.len) return held_items[i] - return FALSE - //Odd = left. Even = right /mob/proc/held_index_to_dir(i) @@ -37,17 +32,14 @@ return "r" return "l" - //Check we have an organ for this hand slot (Dismemberment), Only relevant for humans /mob/proc/has_hand_for_held_index(i) return TRUE - //Check we have an organ for our active hand slot (Dismemberment),Only relevant for humans /mob/proc/has_active_hand() return has_hand_for_held_index(active_hand_index) - //Finds the first available (null) index OR all available (null) indexes in held_items based on a side. //Lefts: 1, 3, 5, 7... //Rights:2, 4, 6, 8... @@ -158,7 +150,7 @@ //Returns if a certain item can be equipped to a certain slot. // Currently invalid for two-handed items - call obj/item/mob_can_equip() instead. -/mob/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) +/mob/proc/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) return FALSE /mob/proc/can_put_in_hand(I, hand_index) @@ -338,48 +330,71 @@ return FALSE return TRUE -//Outdated but still in use apparently. This should at least be a human proc. -//Daily reminder to murder this - Remie. -/mob/living/proc/get_equipped_items(include_pockets = FALSE) +//This is a SAFE proc. Use this instead of equip_to_slot()! +//set qdel_on_fail to have it delete W if it fails to equip +//set disable_warning to disable the 'you are unable to equip that' warning. +//unset redraw_mob to prevent the mob from being redrawn at the end. +/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, qdel_on_fail = FALSE, disable_warning = FALSE, redraw_mob = TRUE, bypass_equip_delay_self = FALSE, clothing_check = FALSE) + if(!istype(W)) + return FALSE + var/list/warning = list("You are unable to equip that!") + if(!W.mob_can_equip(src, null, slot, disable_warning, bypass_equip_delay_self, clothing_check, warning)) + if(qdel_on_fail) + qdel(W) + else if(!disable_warning) + to_chat(src, warning[1]) + return FALSE + equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. + return TRUE + +//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't equip need to be done before! Use mob_can_equip() for that task. +//In most cases you will want to use equip_to_slot_if_possible() +/mob/proc/equip_to_slot(obj/item/W, slot) return -/mob/living/carbon/get_equipped_items(include_pockets = FALSE) - var/list/items = list() - if(back) - items += back - if(head) - items += head - if(wear_mask) - items += wear_mask - if(wear_neck) - items += wear_neck - return items +//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the round starts and when events happen and such. +//Also bypasses equip delay checks, since the mob isn't actually putting it on. +/mob/proc/equip_to_slot_or_del(obj/item/W, slot) + return equip_to_slot_if_possible(W, slot, TRUE, TRUE, FALSE, TRUE) -/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE) - var/list/items = ..() - if(belt) - items += belt - if(ears) - items += ears - if(glasses) - items += glasses - if(gloves) - items += gloves - if(shoes) - items += shoes - if(wear_id) - items += wear_id - if(wear_suit) - items += wear_suit - if(w_uniform) - items += w_uniform - if(include_pockets) - if(l_store) - items += l_store - if(r_store) - items += r_store - if(s_store) - items += s_store +//puts the item "W" into an appropriate slot in a human's inventory +//returns 0 if it cannot, 1 if successful +/mob/proc/equip_to_appropriate_slot(obj/item/W, clothing_check = FALSE) + if(!istype(W)) + return 0 + var/slot_priority = W.slot_equipment_priority + + if(!slot_priority) + slot_priority = list( \ + SLOT_BACK, SLOT_WEAR_ID,\ + SLOT_W_UNIFORM, SLOT_WEAR_SUIT,\ + SLOT_WEAR_MASK, SLOT_HEAD, SLOT_NECK,\ + SLOT_SHOES, SLOT_GLOVES,\ + SLOT_EARS, SLOT_GLASSES,\ + SLOT_BELT, SLOT_S_STORE,\ + SLOT_L_STORE, SLOT_R_STORE,\ + SLOT_GENERC_DEXTROUS_STORAGE\ + ) + + for(var/slot in slot_priority) + if(equip_to_slot_if_possible(W, slot, FALSE, TRUE, TRUE, FALSE, clothing_check)) //qdel_on_fail = 0; disable_warning = 1; redraw_mob = 1 + return 1 + + return 0 + +/** + * Used to return a list of equipped items on a mob; does not include held items (use get_all_gear) + * + * Argument(s): + * * Optional - include_pockets (TRUE/FALSE), whether or not to include the pockets and suit storage in the returned list + */ + +/mob/living/proc/get_equipped_items(include_pockets = FALSE) + var/list/items = list() + for(var/obj/item/I in contents) + if(I.item_flags & IN_INVENTORY) + items += I + items -= held_items return items /mob/living/proc/unequip_everything() @@ -394,7 +409,7 @@ to_chat(M, "You are not holding anything to equip!") return FALSE - if(M.equip_to_appropriate_slot(src)) + if(M.equip_to_appropriate_slot(src, TRUE)) M.update_inv_hands() return TRUE else @@ -471,5 +486,19 @@ hand_bodyparts[i] = BP ..() //Don't redraw hands until we have organs for them + +//GetAllContents that is reasonable and not stupid +/mob/living/carbon/proc/get_all_gear() + var/list/processing_list = get_equipped_items(include_pockets = TRUE) + held_items + listclearnulls(processing_list) // handles empty hands + var/i = 0 + while(i < length(processing_list) ) + var/atom/A = processing_list[++i] + if(SEND_SIGNAL(A, COMSIG_CONTAINS_STORAGE)) + var/list/item_stuff = list() + SEND_SIGNAL(A, COMSIG_TRY_STORAGE_RETURN_INVENTORY, item_stuff) + processing_list += item_stuff + return processing_list + /mob/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool) return ..() && (user == src) diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 612358e802..cf1a158fc5 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -5,44 +5,43 @@ #define EXOTIC_BLEED_MULTIPLIER 4 //Multiplies the actually bled amount by this number for the purposes of turf reaction calculations. -/mob/living/carbon/human/proc/suppress_bloodloss(amount) - if(bleedsuppress) +/mob/living/carbon/monkey/handle_blood() + if(bodytemperature <= TCRYO || (HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood. return - else - bleedsuppress = TRUE - addtimer(CALLBACK(src, .proc/resume_bleeding), amount) + + var/temp_bleed = 0 + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + temp_bleed += BP.get_bleed_rate() + BP.generic_bleedstacks = max(0, BP.generic_bleedstacks - 1) + if(temp_bleed) + bleed(temp_bleed) + + //Blood regeneration if there is some space + if(blood_volume < BLOOD_VOLUME_NORMAL) + blood_volume += 0.1 // regenerate blood VERY slowly + if(blood_volume < BLOOD_VOLUME_OKAY) + adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1)) /mob/living/carbon/human/proc/resume_bleeding() bleedsuppress = 0 - if(stat != DEAD && bleed_rate) + if(stat != DEAD && is_bleeding()) to_chat(src, "The blood soaks through your bandage.") -/mob/living/carbon/monkey/handle_blood() - if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood. - //Blood regeneration if there is some space - if(blood_volume < (BLOOD_VOLUME_NORMAL * blood_ratio)) - blood_volume += 0.1 // regenerate blood VERY slowly - if(blood_volume < (BLOOD_VOLUME_OKAY * blood_ratio)) - adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.02, 1)) - // Takes care blood loss and regeneration /mob/living/carbon/human/handle_blood() - if(NOBLOOD in dna.species.species_traits) - bleed_rate = 0 + if(NOBLOOD in dna.species.species_traits || bleedsuppress || (HAS_TRAIT(src, TRAIT_FAKEDEATH))) return - if(bleed_rate < 0) - bleed_rate = 0 - if(HAS_TRAIT(src, TRAIT_NOMARROW)) //Bloodsuckers don't need to be here. return - if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood. + if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_HUSK))) //cryosleep or husked people do not pump the blood. //Blood regeneration if there is some space - if(blood_volume < (BLOOD_VOLUME_NORMAL * blood_ratio) && !HAS_TRAIT(src, TRAIT_NOHUNGER)) + if(blood_volume < BLOOD_VOLUME_NORMAL && !HAS_TRAIT(src, TRAIT_NOHUNGER)) var/nutrition_ratio = 0 switch(nutrition) if(0 to NUTRITION_LEVEL_STARVING) @@ -55,22 +54,23 @@ nutrition_ratio = 0.8 else nutrition_ratio = 1 - if(HAS_TRAIT(src, TRAIT_HIGH_BLOOD)) - nutrition_ratio *= 1.2 if(satiety > 80) nutrition_ratio *= 1.25 adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR) - blood_volume = min((BLOOD_VOLUME_NORMAL * blood_ratio), blood_volume + 0.5 * nutrition_ratio) + blood_volume = min(BLOOD_VOLUME_NORMAL, blood_volume + 0.5 * nutrition_ratio) //Effects of bloodloss var/word = pick("dizzy","woozy","faint") - switch(blood_volume * INVERSE(blood_ratio)) + switch(blood_volume) + if(BLOOD_VOLUME_MAXIMUM to BLOOD_VOLUME_EXCESS) + if(prob(10)) + to_chat(src, "You feel terribly bloated.") if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) if(prob(5)) to_chat(src, "You feel [word].") - adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.01, 1)) + adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.01, 1)) if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) - adjustOxyLoss(round(((BLOOD_VOLUME_NORMAL * blood_ratio) - blood_volume) * 0.02, 1)) + adjustOxyLoss(round((BLOOD_VOLUME_NORMAL - blood_volume) * 0.02, 1)) if(prob(5)) blur_eyes(6) to_chat(src, "You feel very [word].") @@ -87,24 +87,11 @@ //Bleeding out for(var/X in bodyparts) var/obj/item/bodypart/BP = X - var/brutedamage = BP.brute_dam + temp_bleed += BP.get_bleed_rate() + BP.generic_bleedstacks = max(0, BP.generic_bleedstacks - 1) - if(BP.status == BODYPART_ROBOTIC) //for the moment, synth limbs won't bleed, but soon, my pretty. - continue - - //We want an accurate reading of .len - listclearnulls(BP.embedded_objects) - for(var/obj/item/embeddies in BP.embedded_objects) - if(!embeddies.isEmbedHarmless()) - temp_bleed += 0.5 - - if(brutedamage >= 20) - temp_bleed += (brutedamage * 0.013) - - bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases - - if(bleed_rate && !bleedsuppress && !(HAS_TRAIT(src, TRAIT_FAKEDEATH))) - bleed(bleed_rate) + if(temp_bleed) + bleed(temp_bleed) //Makes a blood drop, leaking amt units of blood from the mob /mob/living/carbon/proc/bleed(amt) @@ -128,9 +115,11 @@ /mob/living/proc/restore_blood() blood_volume = initial(blood_volume) -/mob/living/carbon/human/restore_blood() +/mob/living/carbon/restore_blood() blood_volume = (BLOOD_VOLUME_NORMAL * blood_ratio) - bleed_rate = 0 + for(var/i in bodyparts) + var/obj/item/bodypart/BP = i + BP.generic_bleedstacks = 0 /**************************************************** BLOOD TRANSFERS @@ -188,7 +177,7 @@ blood_data["viruses"] += D.Copy() blood_data["blood_DNA"] = dna.unique_enzymes - blood_data["bloodcolor"] = bloodtype_to_color(dna.blood_type) + blood_data["bloodcolor"] = dna.species.exotic_blood_color if(disease_resistances && disease_resistances.len) blood_data["resistances"] = disease_resistances.Copy() var/list/temp_chem = list() diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index 3547d5f846..24d456bf8f 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -37,10 +37,10 @@ C.put_in_hands(B1) C.put_in_hands(B2) C.regenerate_icons() - src.notransform = TRUE + src.mob_transforming = TRUE spawn(0) bloodpool_sink(B) - src.notransform = FALSE + src.mob_transforming = FALSE return 1 /mob/living/proc/bloodpool_sink(obj/effect/decal/cleanable/B) @@ -73,7 +73,7 @@ if(victim.stat == CONSCIOUS) src.visible_message("[victim] kicks free of the blood pool just before entering it!", null, "You hear splashing and struggling.") - else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/demonsblood)) + else if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/demonsblood)) visible_message("Something prevents [victim] from entering the pool!", "A strange force is blocking [victim] from entering!", "You hear a splash and a thud.") else victim.forceMove(src) @@ -104,7 +104,7 @@ if(!victim) return FALSE - if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/devilskiss)) + if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/devilskiss)) to_chat(src, "AAH! THEIR FLESH! IT BURNS!") adjustBruteLoss(25) //I can't use adjustHealth() here because bloodcrawl affects /mob/living and adjustHealth() only affects simple mobs var/found_bloodpool = FALSE @@ -155,7 +155,7 @@ addtimer(CALLBACK(src, /atom/.proc/remove_atom_colour, TEMPORARY_COLOUR_PRIORITY, newcolor), 6 SECONDS) /mob/living/proc/phasein(obj/effect/decal/cleanable/B) - if(src.notransform) + if(src.mob_transforming) to_chat(src, "Finish eating first!") return 0 B.visible_message("[B] starts to bubble...") diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm index d1258ce6e4..891243496a 100644 --- a/code/modules/mob/living/brain/MMI.dm +++ b/code/modules/mob/living/brain/MMI.dm @@ -39,7 +39,9 @@ laws.set_laws_config() /obj/item/mmi/attackby(obj/item/O, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) + if(!user.CheckActionCooldown(CLICK_CD_MELEE)) + return + user.DelayNextAction() if(istype(O, /obj/item/organ/brain)) //Time to stick a brain in it --NEO var/obj/item/organ/brain/newbrain = O if(brain) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 08d415fc3c..be03827695 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -100,3 +100,9 @@ client.mouse_pointer_icon = M.mouse_pointer if (client && ranged_ability && ranged_ability.ranged_mousepointer) client.mouse_pointer_icon = ranged_ability.ranged_mousepointer + +/mob/living/brain/proc/get_traumas() + . = list() + if(istype(loc, /obj/item/organ/brain)) + var/obj/item/organ/brain/B = loc + . = B.traumas diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index 5655aaa074..59a119a89a 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -76,9 +76,6 @@ REMOVE_SKILL_MODIFIER_BODY(/datum/skill_modifier/heavy_brain_damage, null, C) C.update_hair() -/obj/item/organ/brain/prepare_eat() - return // Too important to eat. - /obj/item/organ/brain/proc/transfer_identity(mob/living/L) name = "[L.name]'s brain" if(brainmob) @@ -105,7 +102,7 @@ to_chat(brainmob, "You feel slightly disoriented. That's normal when you're just a brain.") /obj/item/organ/brain/attackby(obj/item/O, mob/user, params) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) if(brainmob) O.attack(brainmob, user) //Oh noooeeeee @@ -342,6 +339,8 @@ max_traumas = TRAUMA_LIMIT_BASIC if(TRAUMA_RESILIENCE_SURGERY) max_traumas = TRAUMA_LIMIT_SURGERY + if(TRAUMA_RESILIENCE_WOUND) + max_traumas = TRAUMA_LIMIT_WOUND if(TRAUMA_RESILIENCE_LOBOTOMY) max_traumas = TRAUMA_LIMIT_LOBOTOMY if(TRAUMA_RESILIENCE_MAGIC) @@ -400,7 +399,7 @@ return var/trauma_type = pick(possible_traumas) - gain_trauma(trauma_type, resilience) + return gain_trauma(trauma_type, resilience) //Cure a random trauma of a certain resilience level /obj/item/organ/brain/proc/cure_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience = TRAUMA_RESILIENCE_BASIC) diff --git a/code/modules/mob/living/brain/life.dm b/code/modules/mob/living/brain/life.dm index 51be1f6971..6d06da41ae 100644 --- a/code/modules/mob/living/brain/life.dm +++ b/code/modules/mob/living/brain/life.dm @@ -1,11 +1,7 @@ -/mob/living/brain/Life() - set invisibility = 0 - if (notransform) +/mob/living/brain/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return - if(!loc) - return - . = ..() handle_emp_damage() /mob/living/brain/update_stat() diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 442bcf8027..951185ee92 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -25,7 +25,7 @@ status_flags = CANUNCONSCIOUS|CANPUSH - var/heat_protection = 0.5 + heat_protection = 0.5 var/leaping = 0 gib_type = /obj/effect/decal/cleanable/blood/gibs/xeno unique_name = 1 diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 042451b7dd..5081fd8a14 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -8,9 +8,6 @@ /mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) return ..(AM, skipcatch = TRUE, hitpush = FALSE) -/mob/living/carbon/alien/can_embed(obj/item/I) - return FALSE - /*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other. As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble. In all, this is a lot like the monkey code. /N @@ -48,7 +45,7 @@ In all, this is a lot like the monkey code. /N return attack_alien(L) -/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M) +/mob/living/carbon/alien/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) //To allow surgery to return properly. return @@ -77,7 +74,6 @@ In all, this is a lot like the monkey code. /N var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) apply_damage(rand(1, 3), BRUTE, affecting) - /mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M) . = ..() if(.) diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index 727a22f844..d0addbab21 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -57,8 +57,17 @@ /mob/living/carbon/alien/humanoid/Topic(href, href_list) ..() - //strip panel + //strip panel & embeds if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) + if(href_list["embedded_object"]) + var/obj/item/bodypart/L = locate(href_list["embedded_limb"]) in bodyparts + if(!L) + return + var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects + if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the alien anymore + return + SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L) + return if(href_list["pouches"]) visible_message("[usr] tries to empty [src]'s pouches.", \ "[usr] tries to empty [src]'s pouches.") diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm index 5ebf6210d0..8177360d4a 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid_defense.dm @@ -21,7 +21,7 @@ "[user] has [hitverb] [src]!", null, COMBAT_MESSAGE_RANGE) return 1 -/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M) +/mob/living/carbon/alien/humanoid/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) //To allow surgery to return properly. return diff --git a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm b/code/modules/mob/living/carbon/alien/humanoid/inventory.dm deleted file mode 100644 index e2537f0f4f..0000000000 --- a/code/modules/mob/living/carbon/alien/humanoid/inventory.dm +++ /dev/null @@ -1,5 +0,0 @@ -/mob/living/carbon/alien/humanoid/doUnEquip(obj/item/I) - . = ..() - if(!. || !I) - return - diff --git a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm index 7dabcf5abf..5832996a2c 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva_defense.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva_defense.dm @@ -1,6 +1,6 @@ -/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M) +/mob/living/carbon/alien/larva/on_attack_hand(mob/living/carbon/human/M) . = ..() if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB) return diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index a4da38c4da..f0004b5ed9 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -1,14 +1,10 @@ - - -/mob/living/carbon/alien/larva/Life() - set invisibility = 0 - if (notransform) +/mob/living/carbon/alien/larva/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return - if(..()) //not dead - // GROW! - if(amount_grown < max_grown) - amount_grown++ - update_icons() + // GROW! + if(amount_grown < max_grown) + amount_grown++ + update_icons() /mob/living/carbon/alien/larva/update_stat() diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index 75aadd69c9..d63686691d 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -1,6 +1,7 @@ -/mob/living/carbon/alien/Life() +/mob/living/carbon/alien/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return findQueen() - return..() /mob/living/carbon/alien/check_breath(datum/gas_mixture/breath) if(status_flags & GODMODE) @@ -12,26 +13,23 @@ var/toxins_used = 0 var/tox_detect_threshold = 0.02 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - var/list/breath_gases = breath.gases + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath_gases[/datum/gas/plasma]/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure if(Toxins_pp > tox_detect_threshold) // Detect toxins in air - adjustPlasma(breath_gases[/datum/gas/plasma]*250) + adjustPlasma(breath.get_moles(/datum/gas/plasma)*250) throw_alert("alien_tox", /obj/screen/alert/alien_tox) - toxins_used = breath_gases[/datum/gas/plasma] + toxins_used = breath.get_moles(/datum/gas/plasma) else clear_alert("alien_tox") //Breathe in toxins and out oxygen - breath_gases[/datum/gas/plasma] -= toxins_used - breath_gases[/datum/gas/oxygen] += toxins_used - - GAS_GARBAGE_COLLECT(breath.gases) + breath.adjust_moles(/datum/gas/plasma, -toxins_used) + breath.adjust_moles(/datum/gas/oxygen, toxins_used) //BREATH TEMPERATURE handle_breath_temperature(breath) diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm index 8485fece85..8e3966eb03 100644 --- a/code/modules/mob/living/carbon/alien/organs.dm +++ b/code/modules/mob/living/carbon/alien/organs.dm @@ -1,7 +1,8 @@ /obj/item/organ/alien icon_state = "xgibmid2" + food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/toxin/acid = 10) var/list/alien_powers = list() - organ_flags = ORGAN_NO_SPOIL + organ_flags = ORGAN_NO_SPOIL|ORGAN_EDIBLE /obj/item/organ/alien/Initialize() . = ..() @@ -26,12 +27,6 @@ owner.RemoveAbility(P) ..() -/obj/item/organ/alien/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent(/datum/reagent/toxin/acid, 10) - return S - - /obj/item/organ/alien/plasmavessel name = "plasma vessel" icon_state = "plasma" @@ -39,17 +34,13 @@ zone = BODY_ZONE_CHEST slot = "plasmavessel" alien_powers = list(/obj/effect/proc_holder/alien/plant, /obj/effect/proc_holder/alien/transfer) + food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/toxin/plasma = 10) var/storedPlasma = 100 var/max_plasma = 250 var/heal_rate = 5 var/plasma_rate = 10 -/obj/item/organ/alien/plasmavessel/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent(/datum/reagent/toxin/plasma, storedPlasma/10) - return S - /obj/item/organ/alien/plasmavessel/large name = "large plasma vessel" icon_state = "plasma_large" diff --git a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm index 0e8764a372..bb92eb79bd 100644 --- a/code/modules/mob/living/carbon/alien/special/alien_embryo.dm +++ b/code/modules/mob/living/carbon/alien/special/alien_embryo.dm @@ -4,6 +4,7 @@ name = "alien embryo" icon = 'icons/mob/alien.dmi' icon_state = "larva0_dead" + food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/toxin/acid = 10) var/stage = 0 var/bursting = FALSE @@ -16,11 +17,6 @@ if(prob(10)) AttemptGrow(0) -/obj/item/organ/body_egg/alien_embryo/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent(/datum/reagent/toxin/acid, 10) - return S - /obj/item/organ/body_egg/alien_embryo/on_life() . = ..() if(!owner) @@ -92,7 +88,7 @@ ghost.transfer_ckey(new_xeno, FALSE) SEND_SOUND(new_xeno, sound('sound/voice/hiss5.ogg',0,0,0,100)) //To get the player's attention new_xeno.Paralyze(6) - new_xeno.notransform = TRUE + new_xeno.mob_transforming = TRUE new_xeno.invisibility = INVISIBILITY_MAXIMUM sleep(6) @@ -102,7 +98,7 @@ if(new_xeno) new_xeno.SetParalyzed(0) - new_xeno.notransform = FALSE + new_xeno.mob_transforming = FALSE new_xeno.invisibility = 0 var/mob/living/carbon/old_owner = owner diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index eb1b38b9ff..ad8828572c 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -58,8 +58,7 @@ /obj/item/clothing/mask/facehugger/attack_alien(mob/user) //can be picked up by aliens return attack_hand(user) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/clothing/mask/facehugger/attack_hand(mob/user) +/obj/item/clothing/mask/facehugger/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if((stat == CONSCIOUS && !sterile) && !isalien(user)) if(Leap(user)) return @@ -88,6 +87,7 @@ Die() /obj/item/clothing/mask/facehugger/equipped(mob/M) + . = ..() Attach(M) /obj/item/clothing/mask/facehugger/Crossed(atom/target) @@ -254,7 +254,7 @@ return FALSE if(AmBloodsucker(M)) return FALSE - + if(ismonkey(M)) return 1 diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 7b201e7492..b7d67e49a6 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -47,16 +47,13 @@ /mob/living/carbon/swap_hand(held_index) + . = ..() + if(!.) + var/obj/item/held_item = get_active_held_item() + to_chat(usr, "Your other hand is too busy holding [held_item].") + return if(!held_index) held_index = (active_hand_index % held_items.len)+1 - - var/obj/item/item_in_hand = src.get_active_held_item() - if(item_in_hand) //this segment checks if the item in your hand is twohanded. - var/obj/item/twohanded/TH = item_in_hand - if(istype(TH)) - if(TH.wielded == 1) - to_chat(usr, "Your other hand is too busy holding [TH]") - return var/oindex = active_hand_index active_hand_index = held_index if(hud_used) @@ -90,12 +87,24 @@ if(user != src && (user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)) for(var/datum/surgery/S in surgeries) if(S.next_step(user,user.a_intent)) - return 1 + return STOP_ATTACK_PROC_CHAIN + + if(!all_wounds || !(user.a_intent == INTENT_HELP || user == src)) + return ..() + + for(var/i in shuffle(all_wounds)) + var/datum/wound/W = i + if(W.try_treating(I, user)) + return STOP_ATTACK_PROC_CHAIN + return ..() /mob/living/carbon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() var/hurt = TRUE + var/extra_speed = 0 + if(throwingdatum.thrower != src) + extra_speed = min(max(0, throwingdatum.speed - initial(throw_speed)), 3) if(GetComponent(/datum/component/tackler)) return if(throwingdatum?.thrower && iscyborg(throwingdatum.thrower)) @@ -105,18 +114,18 @@ if(hit_atom.density && isturf(hit_atom)) if(hurt) DefaultCombatKnockdown(20) - take_bodypart_damage(10) + take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5) if(iscarbon(hit_atom) && hit_atom != src) var/mob/living/carbon/victim = hit_atom if(victim.movement_type & FLYING) return if(hurt) - victim.take_bodypart_damage(10) - take_bodypart_damage(10) + victim.take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5) + take_bodypart_damage(10 + 5 * extra_speed, check_armor = TRUE, wound_bonus = extra_speed * 5) victim.DefaultCombatKnockdown(20) DefaultCombatKnockdown(20) - visible_message("[src] crashes into [victim], knocking them both over!",\ - "You violently crash into [victim]!") + visible_message("[src] crashes into [victim] [extra_speed ? "really hard" : ""], knocking them both over!",\ + "You violently crash into [victim] [extra_speed ? "extra hard" : ""]!") playsound(src,'sound/weapons/punch1.ogg',50,1) @@ -156,6 +165,7 @@ if(IS_STAMCRIT(src)) to_chat(src, "You're too exhausted.") return + var/random_turn = a_intent == INTENT_HARM //END OF CIT CHANGES @@ -182,7 +192,7 @@ to_chat(src, "You gently let go of [throwable_mob].") return - adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring + adjustStaminaLossBuffered(STAM_COST_THROW_MOB * ((throwable_mob.mob_size+1)**2))// throwing an entire person shall be very tiring var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors var/turf/end_T = get_turf(target) if(start_T && end_T) @@ -199,12 +209,18 @@ adjustStaminaLossBuffered(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST)) if(thrown_thing) - visible_message("[src] has thrown [thrown_thing].") - log_message("has thrown [thrown_thing]", LOG_ATTACK) + var/power_throw = 0 + if(HAS_TRAIT(src, TRAIT_HULK)) + power_throw++ + if(pulling && grab_state >= GRAB_NECK) + power_throw++ + visible_message("[src] throws [thrown_thing][power_throw ? " really hard!" : "."]", \ + "You throw [thrown_thing][power_throw ? " really hard!" : "."]") + log_message("has thrown [thrown_thing] [power_throw ? "really hard" : ""]", LOG_ATTACK) do_attack_animation(target, no_effect = 1) playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) newtonian_move(get_dir(target, src)) - thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force, random_turn) + thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed + power_throw, src, null, null, null, move_force, random_turn) /mob/living/carbon/restrained(ignore_grab) . = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE)) @@ -295,14 +311,11 @@ return if(restrained()) // too soon. - if(last_special > world.time) - return var/buckle_cd = 600 if(handcuffed) var/obj/item/restraints/O = src.get_item_by_slot(SLOT_HANDCUFFED) buckle_cd = O.breakouttime - changeNext_move(min(CLICK_CD_BREAKOUT, buckle_cd)) - last_special = world.time + min(CLICK_CD_BREAKOUT, buckle_cd) + MarkResistTime() visible_message("[src] attempts to unbuckle [p_them()]self!", \ "You attempt to unbuckle yourself... (This will take around [round(buckle_cd/600,1)] minute\s, and you need to stay still.)") if(do_after(src, buckle_cd, 0, target = src, required_mobility_flags = MOBILITY_RESIST)) @@ -316,39 +329,26 @@ buckled.user_unbuckle_mob(src,src) /mob/living/carbon/resist_fire() - if(last_special > world.time) - return fire_stacks -= 5 DefaultCombatKnockdown(60, TRUE, TRUE) spin(32,2) visible_message("[src] rolls on the floor, trying to put [p_them()]self out!", \ "You stop, drop, and roll!") - last_special = world.time + 30 + MarkResistTime(30) sleep(30) if(fire_stacks <= 0) visible_message("[src] has successfully extinguished [p_them()]self!", \ "You extinguish yourself.") ExtinguishMob() -/mob/living/carbon/resist_restraints(ignore_delay = FALSE) +/mob/living/carbon/resist_restraints() var/obj/item/I = null - var/type = 0 - if(!ignore_delay && (last_special > world.time)) - to_chat(src, "You don't have the energy to resist your restraints that fast!") - return if(handcuffed) I = handcuffed - type = 1 else if(legcuffed) I = legcuffed - type = 2 if(I) - if(type == 1) - changeNext_move(min(CLICK_CD_BREAKOUT, I.breakouttime)) - last_special = world.time + CLICK_CD_BREAKOUT - if(type == 2) - changeNext_move(min(CLICK_CD_RANGE, I.breakouttime)) - last_special = world.time + CLICK_CD_RANGE + MarkResistTime() cuff_resist(I) /mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) @@ -393,7 +393,7 @@ if (W) W.layer = initial(W.layer) W.plane = initial(W.plane) - changeNext_move(0) + SetNextAction(0) if (legcuffed) var/obj/item/W = legcuffed legcuffed = null @@ -406,7 +406,7 @@ if (W) W.layer = initial(W.layer) W.plane = initial(W.plane) - changeNext_move(0) + SetNextAction(0) update_equipment_speed_mods() // In case cuffs ever change speed /mob/living/carbon/proc/clear_cuffs(obj/item/I, cuff_break) @@ -895,6 +895,9 @@ var/datum/disease/D = thing if(D.severity != DISEASE_SEVERITY_POSITIVE) D.cure(FALSE) + for(var/thing in all_wounds) + var/datum/wound/W = thing + W.remove_wound() if(admin_revive) regenerate_limbs() regenerate_organs() @@ -985,6 +988,10 @@ if(SANITY_NEUTRAL to SANITY_GREAT) . *= 0.90 + for(var/i in status_effects) + var/datum/status_effect/S = i + . *= S.interact_speed_modifier() + /mob/living/carbon/proc/create_internal_organs() for(var/X in internal_organs) @@ -1160,3 +1167,68 @@ dna.features["body_model"] = MALE if(update_icon) update_body() + +/mob/living/carbon/check_obscured_slots() + if(head) + if(head.flags_inv & HIDEMASK) + LAZYOR(., SLOT_WEAR_MASK) + if(head.flags_inv & HIDEEYES) + LAZYOR(., SLOT_GLASSES) + if(head.flags_inv & HIDEEARS) + LAZYOR(., SLOT_EARS) + + if(wear_mask) + if(wear_mask.flags_inv & HIDEEYES) + LAZYOR(., SLOT_GLASSES) + +// if any of our bodyparts are bleeding +/mob/living/carbon/proc/is_bleeding() + for(var/i in bodyparts) + var/obj/item/bodypart/BP = i + if(BP.get_bleed_rate()) + return TRUE + +// get our total bleedrate +/mob/living/carbon/proc/get_total_bleed_rate() + var/total_bleed_rate = 0 + for(var/i in bodyparts) + var/obj/item/bodypart/BP = i + total_bleed_rate += BP.get_bleed_rate() + + return total_bleed_rate + +/** + * generate_fake_scars()- for when you want to scar someone, but you don't want to hurt them first. These scars don't count for temporal scarring (hence, fake) + * + * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_SLASH to generate a random cut scar. + * + * Arguments: + * * num_scars- A number for how many scars you want to add + * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types + */ +/mob/living/carbon/proc/generate_fake_scars(num_scars, forced_type) + for(var/i in 1 to num_scars) + var/datum/scar/scaries = new + var/obj/item/bodypart/scar_part = pick(bodyparts) + + var/wound_type + if(forced_type) + if(islist(forced_type)) + wound_type = pick(forced_type) + else + wound_type = forced_type + else + wound_type = pick(GLOB.global_all_wound_types) + + var/datum/wound/phantom_wound = new wound_type + scaries.generate(scar_part, phantom_wound) + scaries.fake = TRUE + QDEL_NULL(phantom_wound) + +/** + * get_biological_state is a helper used to see what kind of wounds we roll for. By default we just assume carbons (read:monkeys) are flesh and bone, but humans rely on their species datums + * + * go look at the species def for more info [/datum/species/proc/get_biological_state] + */ +/mob/living/carbon/proc/get_biological_state() + return BIO_FLESH_BONE diff --git a/code/modules/mob/living/carbon/carbon_active_parry.dm b/code/modules/mob/living/carbon/carbon_active_parry.dm new file mode 100644 index 0000000000..2683b6db6b --- /dev/null +++ b/code/modules/mob/living/carbon/carbon_active_parry.dm @@ -0,0 +1,2 @@ +/mob/living/carbon/check_unarmed_parry_activation_special() + return ..() && length(get_empty_held_indexes()) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 41a034ecd8..566c004142 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -65,32 +65,21 @@ throw_mode_off() return TRUE -/mob/living/carbon/embed_item(obj/item/I) - throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) - var/obj/item/bodypart/L = pick(bodyparts) - L.embedded_objects |= I - I.add_mob_blood(src)//it embedded itself in you, of course it's bloody! - I.forceMove(src) - I.embedded() - L.receive_damage(I.w_class*I.embedding["impact_pain_mult"]) - visible_message("[I] embeds itself in [src]'s [L.name]!","[I] embeds itself in your [L.name]!") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) - /mob/living/carbon/attacked_by(obj/item/I, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) var/totitemdamage = pre_attacked_by(I, user) * damage_multiplier var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected) var/list/block_return = list() - if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone, block_return) & BLOCK_SUCCESS)) + if((user != src) && (mob_run_block(I, totitemdamage, "the [I]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | 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) if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest) affecting = bodyparts[1] SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting) - send_item_attack_message(I, user, affecting.name) + send_item_attack_message(I, user, affecting.name, affecting, totitemdamage) I.do_stagger_action(src, user, totitemdamage) if(I.force) - apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage + apply_damage(totitemdamage, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) //CIT CHANGE - replaces I.force with totitemdamage if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC) var/basebloodychance = affecting.brute_dam + totitemdamage if(prob(basebloodychance)) @@ -111,19 +100,12 @@ head.add_mob_blood(src) update_inv_head() - //dismemberment - var/probability = I.get_dismemberment_chance(affecting) - if(prob(probability)) - if(affecting.dismember(I.damtype)) - I.add_mob_blood(src) - playsound(get_turf(src), I.get_dismember_sound(), 80, 1) return TRUE //successful attack /mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user) return //so we don't call the carbon's attack_hand(). -//ATTACK HAND IGNORING PARENT RETURN VALUE -/mob/living/carbon/attack_hand(mob/living/carbon/human/user) +/mob/living/carbon/on_attack_hand(mob/living/carbon/human/user, act_intent, unarmed_attack_flags) . = ..() if(.) //was the attack blocked? return @@ -138,11 +120,15 @@ ContactContractDisease(D) if(lying && surgeries.len) - if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM) + if(act_intent == INTENT_HELP || act_intent == INTENT_DISARM) for(var/datum/surgery/S in surgeries) - if(S.next_step(user, user.a_intent)) + if(S.next_step(user, act_intent)) return TRUE + for(var/i in all_wounds) + var/datum/wound/W = i + if(W.try_handling(user)) + return TRUE /mob/living/carbon/attack_paw(mob/living/carbon/monkey/M) @@ -159,15 +145,14 @@ if(M.a_intent == INTENT_HELP) help_shake_act(M) - return 0 + return TRUE . = ..() if(.) //successful monkey bite. for(var/thing in M.diseases) var/datum/disease/D = thing ForceContractDisease(D) - return 1 - + return TRUE /mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M) . = ..() @@ -306,12 +291,12 @@ 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()) - var/static/list/many_tails = list("tail_human", "tail_lizard", "mam_tail") - for(var/T in many_tails) - if(S.mutant_bodyparts[T] && dna.features[T] != "None") - emote("wag") - break + if(!(client?.prefs.cit_toggles & NO_AUTO_WAG)) + if(S?.can_wag_tail(src) && !dna.species.is_wagging_tail()) + var/static/list/many_tails = list("tail_human", "tail_lizard", "mam_tail") + for(var/T in many_tails) + if(S.mutant_bodyparts[T] && dna.features[T] != "None") + emote("wag") else if(check_zone(M.zone_selected) == BODY_ZONE_R_ARM || check_zone(M.zone_selected) == BODY_ZONE_L_ARM) M.visible_message( \ @@ -408,7 +393,7 @@ to_chat(src, "Your eyes are really starting to hurt. This can't be good for you!") if(has_bane(BANE_LIGHT)) mind.disrupt_spells(-500) - return 1 + return TRUE else if(damage == 0) // just enough protection if(prob(20)) to_chat(src, "Something bright flashes in the corner of your vision!") @@ -478,3 +463,40 @@ if (BP.status < 2) amount += BP.burn_dam return amount + +/mob/living/carbon/proc/get_interaction_efficiency(zone) + var/obj/item/bodypart/limb = get_bodypart(zone) + if(!limb) + return + +/mob/living/carbon/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart, totitemdamage) + var/message_verb = "attacked" + if(length(I.attack_verb)) + message_verb = "[pick(I.attack_verb)]" + else if(!I.force) + return + + var/extra_wound_details = "" + if(I.damtype == BRUTE && hit_bodypart.can_dismember()) + var/mangled_state = hit_bodypart.get_mangled_state() + var/bio_state = get_biological_state() + if(mangled_state == BODYPART_MANGLED_BOTH) + extra_wound_details = ", threatening to sever it entirely" + else if((mangled_state == BODYPART_MANGLED_FLESH && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_BONE && bio_state == BIO_JUST_BONE)) + extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] through to the bone" + else if((mangled_state == BODYPART_MANGLED_BONE && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_FLESH && bio_state == BIO_JUST_FLESH)) + extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] at the remaining tissue" + + var/message_hit_area = "" + if(hit_area) + message_hit_area = " in the [hit_area]" + var/attack_message = "[src] is [message_verb][message_hit_area] with [I][extra_wound_details]!" + var/attack_message_local = "You're [message_verb][message_hit_area] with [I][extra_wound_details]!" + if(user in viewers(src, null)) + attack_message = "[user] [message_verb] [src][message_hit_area] with [I][extra_wound_details]!" + attack_message_local = "[user] [message_verb] you[message_hit_area] with [I][extra_wound_details]!" + if(user == src) + attack_message_local = "You [message_verb] yourself[message_hit_area] with [I][extra_wound_details]" + visible_message("[attack_message]",\ + "[attack_message_local]", null, COMBAT_MESSAGE_RANGE) + return TRUE diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 15413f76d4..2ce59fb790 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -24,7 +24,7 @@ var/obj/item/head = null var/obj/item/gloves = null //only used by humans - var/obj/item/shoes = null //only used by humans. + var/obj/item/clothing/shoes/shoes = null //only used by humans. var/obj/item/clothing/glasses/glasses = null //only used by humans. var/obj/item/ears = null //only used by humans. @@ -64,3 +64,17 @@ var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects var/tackling = FALSE //Whether or not we are tackling, this will prevent the knock into effects for carbons + + /// All of the wounds a carbon has afflicted throughout their limbs + var/list/all_wounds + /// All of the scars a carbon has afflicted throughout their limbs + var/list/all_scars + + /// Protection (insulation) from the heat, Value 0-1 corresponding to the percentage of protection + var/heat_protection = 0 // No heat protection + /// Protection (insulation) from the cold, Value 0-1 corresponding to the percentage of protection + var/cold_protection = 0 // No cold protection + + /// Timer id of any transformation + var/transformation_timer + diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 5528669afa..5c5a1d6d52 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -1,32 +1,33 @@ -/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE) +/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) var/hit_percent = (100-blocked)/100 if(!forced && hit_percent <= 0) return 0 var/obj/item/bodypart/BP = null - if(isbodypart(def_zone)) //we specified a bodypart object - BP = def_zone - else - if(!def_zone) - def_zone = ran_zone(def_zone) - BP = get_bodypart(check_zone(def_zone)) - if(!BP) - BP = bodyparts[1] + if(!spread_damage) + if(isbodypart(def_zone)) //we specified a bodypart object + BP = def_zone + else + if(!def_zone) + def_zone = ran_zone(def_zone) + BP = get_bodypart(check_zone(def_zone)) + if(!BP) + BP = bodyparts[1] var/damage_amount = forced ? damage : damage * hit_percent switch(damagetype) if(BRUTE) if(BP) - if(damage > 0 ? BP.receive_damage(damage_amount) : BP.heal_damage(abs(damage_amount), 0)) + if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness)) update_damage_overlays() else //no bodypart, we deal damage with a more general method. adjustBruteLoss(damage_amount, forced = forced) if(BURN) if(BP) - if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount))) + if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness)) update_damage_overlays() else adjustFireLoss(damage_amount, forced = forced) @@ -201,12 +202,12 @@ //Damages ONE bodypart randomly selected from damagable ones. //It automatically updates damage overlays if necessary //It automatically updates health status -/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0) +/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) var/list/obj/item/bodypart/parts = get_damageable_bodyparts() if(!parts.len) return var/obj/item/bodypart/picked = pick(parts) - if(picked.receive_damage(brute, burn, stamina)) + if(picked.receive_damage(brute, burn, stamina,check_armor ? run_armor_check(picked, (brute ? "melee" : burn ? "fire" : stamina ? "bullet" : null)) : FALSE, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness)) update_damage_overlays() //Heal MANY bodyparts, in random order @@ -234,12 +235,12 @@ update_damage_overlays() update_stamina() //CIT CHANGE - makes sure update_stamina() always gets called after a health update -// damage MANY bodyparts, in random order -/mob/living/carbon/take_overall_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE) +/// damage MANY bodyparts, in random order +/mob/living/carbon/take_overall_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status) if(status_flags & GODMODE) return //godmode - var/list/obj/item/bodypart/parts = get_damageable_bodyparts() + var/list/obj/item/bodypart/parts = get_damageable_bodyparts(required_status) var/update = 0 while(parts.len && (brute > 0 || burn > 0 || stamina > 0)) var/obj/item/bodypart/picked = pick(parts) @@ -252,7 +253,7 @@ var/stamina_was = picked.stamina_dam - update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE) + update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE, required_status, wound_bonus = CANT_WOUND) // disabling wounds from these for now cuz your entire body snapping cause your heart stopped would suck brute = round(brute - (picked.brute_dam - brute_was), DAMAGE_PRECISION) burn = round(burn - (picked.burn_dam - burn_was), DAMAGE_PRECISION) @@ -265,45 +266,11 @@ update_damage_overlays() update_stamina() -/* TO_REMOVE -/mob/living/carbon/getOrganLoss(ORGAN_SLOT_BRAIN) - . = 0 - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(B) - . = B.get_brain_damage() - -//Some sources of brain damage shouldn't be deadly -/mob/living/carbon/adjustOrganLoss(ORGAN_SLOT_BRAIN, amount, maximum = BRAIN_DAMAGE_DEATH) - if(status_flags & GODMODE) - return FALSE - var/prev_brainloss = getOrganLoss(ORGAN_SLOT_BRAIN) - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(!B) - return - B.adjust_brain_damage(amount, maximum) - if(amount <= 0) //cut this early - return - var/brainloss = getOrganLoss(ORGAN_SLOT_BRAIN) - if(brainloss > BRAIN_DAMAGE_MILD) - if(prob(amount * ((2 * (100 + brainloss - BRAIN_DAMAGE_MILD)) / 100))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 2% - gain_trauma_type(BRAIN_TRAUMA_MILD) - if(brainloss > BRAIN_DAMAGE_SEVERE) - if(prob(amount * ((2 * (100 + brainloss - BRAIN_DAMAGE_SEVERE)) / 100))) //Base chance is the hit damage; for every point of damage past the threshold the chance is increased by 2% - if(prob(20)) - gain_trauma_type(BRAIN_TRAUMA_SPECIAL) - else - gain_trauma_type(BRAIN_TRAUMA_SEVERE) - - if(prev_brainloss < BRAIN_DAMAGE_MILD && brainloss >= BRAIN_DAMAGE_MILD) - to_chat(src, "You feel lightheaded.") - else if(prev_brainloss < BRAIN_DAMAGE_SEVERE && brainloss >= BRAIN_DAMAGE_SEVERE) - to_chat(src, "You feel less in control of your thoughts.") - else if(prev_brainloss < (BRAIN_DAMAGE_DEATH - 20) && brainloss >= (BRAIN_DAMAGE_DEATH - 20)) - to_chat(src, "You can feel your mind flickering on and off...") - -/mob/living/carbon/setBrainLoss(amount) - var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN) - if(B) - var/adjusted_amount = amount - B.get_brain_damage() - B.adjust_brain_damage(adjusted_amount, null) -*/ +///Returns a list of bodyparts with wounds (in case someone has a wound on an otherwise fully healed limb) +/mob/living/carbon/proc/get_wounded_bodyparts(brute = FALSE, burn = FALSE, stamina = FALSE, status) + var/list/obj/item/bodypart/parts = list() + for(var/X in bodyparts) + var/obj/item/bodypart/BP = X + if(LAZYLEN(BP.wounds)) + parts += BP + return parts diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index b07aab30d1..5eabae16f7 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -44,6 +44,9 @@ msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n" else msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n" + for(var/i in BP.wounds) + var/datum/wound/W = i + msg += "[W.get_examine_description(user)]\n" for(var/X in disabled) var/obj/item/bodypart/BP = X @@ -99,6 +102,22 @@ if(pulledby && pulledby.grab_state) msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n" + var/scar_severity = 0 + for(var/i in all_scars) + var/datum/scar/S = i + if(S.is_visible(user)) + scar_severity += S.severity + + switch(scar_severity) + if(1 to 2) + msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n" + if(3 to 4) + msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n" + if(5 to 6) + msg += "[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...\n" + if(7 to INFINITY) + msg += "[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...\n" + if(msg.len) . += "[msg.Join("")]" @@ -135,3 +154,25 @@ . += "[t_He] look[p_s()] ecstatic." SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .) . += "*---------*" + +/mob/living/carbon/examine_more(mob/user) + if(!all_scars) + return ..() + + var/list/visible_scars + for(var/i in all_scars) + var/datum/scar/S = i + if(S.is_visible(user)) + LAZYADD(visible_scars, S) + + if(!visible_scars) + return ..() + + var/msg = list("You examine [src] closer, and note the following...") + for(var/i in visible_scars) + var/datum/scar/S = i + var/scar_text = S.get_examine_description(user) + if(scar_text) + msg += "[scar_text]" + + return msg diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm index 9f6a572fc8..04ec1196fd 100644 --- a/code/modules/mob/living/carbon/human/damage_procs.dm +++ b/code/modules/mob/living/carbon/human/damage_procs.dm @@ -1,5 +1,5 @@ +// depending on the species, it will run the corresponding apply_damage code there +/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) + return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness) -/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE) - // depending on the species, it will run the corresponding apply_damage code there - return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced) diff --git a/code/modules/mob/living/carbon/human/dummy.dm b/code/modules/mob/living/carbon/human/dummy.dm index 24eb5d7234..2f5c94b784 100644 --- a/code/modules/mob/living/carbon/human/dummy.dm +++ b/code/modules/mob/living/carbon/human/dummy.dm @@ -4,6 +4,10 @@ status_flags = GODMODE|CANPUSH mouse_drag_pointer = MOUSE_INACTIVE_POINTER var/in_use = FALSE + vore_flags = NO_VORE + +/mob/living/carbon/human/vore + vore_flags = DEVOURABLE | DIGESTABLE | FEEDING INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) @@ -17,7 +21,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy) /mob/living/carbon/human/dummy/proc/wipe_state() delete_equipment() icon_render_key = null - cut_overlays(TRUE) + cut_overlays() //Inefficient pooling/caching way. GLOBAL_LIST_EMPTY(human_dummy_list) @@ -43,6 +47,5 @@ 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/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index cb0dbef332..04747ffcb4 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -7,6 +7,11 @@ message = "cries." emote_type = EMOTE_AUDIBLE +/datum/emote/living/carbon/human/cry/run_emote(mob/user, params) + . = ..() + if(. && isipcperson(user)) + do_fake_sparks(5,FALSE,user) + /datum/emote/living/carbon/human/dap key = "dap" key_third_person = "daps" @@ -187,3 +192,71 @@ key_third_person = "chimes" message = "chimes." sound = 'sound/machines/chime.ogg' + +//rock paper scissors emote handling +/mob/living/carbon/human/proc/beginRockPaperScissors(var/chosen_move) + GLOB.rockpaperscissors_players[src] = list(chosen_move, ROCKPAPERSCISSORS_NOT_DECIDED) + do_after_advanced(src, ROCKPAPERSCISSORS_TIME_LIMIT, src, DO_AFTER_REQUIRES_USER_ON_TURF|DO_AFTER_NO_COEFFICIENT|DO_AFTER_NO_PROGRESSBAR|DO_AFTER_DISALLOW_MOVING_ABSOLUTE_USER, CALLBACK(src, .proc/rockpaperscissors_tick)) + var/new_entry = GLOB.rockpaperscissors_players[src] + if(new_entry[2] == ROCKPAPERSCISSORS_NOT_DECIDED) + to_chat(src, "You put your hand back down.") + GLOB.rockpaperscissors_players -= src + +/mob/living/carbon/human/proc/rockpaperscissors_tick() //called every cycle of the progress bar for rock paper scissors while waiting for an opponent + var/mob/living/carbon/human/opponent + for(var/mob/living/carbon/human/potential_opponent in (GLOB.rockpaperscissors_players - src)) //dont play against yourself + if(get_dist(src, potential_opponent) <= ROCKPAPERSCISSORS_RANGE) + opponent = potential_opponent + break + if(opponent) + //we found an opponent before they found us + var/move_to_number = list("rock" = 0, "paper" = 1, "scissors" = 2) + var/our_move = move_to_number[GLOB.rockpaperscissors_players[src][1]] + var/their_move = move_to_number[GLOB.rockpaperscissors_players[opponent][1]] + var/result_us = ROCKPAPERSCISSORS_WIN + var/result_them = ROCKPAPERSCISSORS_LOSE + if(our_move == their_move) + result_us = ROCKPAPERSCISSORS_TIE + result_them = ROCKPAPERSCISSORS_TIE + else + if(((our_move + 1) % 3) == their_move) + result_us = ROCKPAPERSCISSORS_LOSE + result_them = ROCKPAPERSCISSORS_WIN + //we decided our results so set them in the list + GLOB.rockpaperscissors_players[src][2] = result_us + GLOB.rockpaperscissors_players[opponent][2] = result_them + + //show what happened + src.visible_message("[src] makes [GLOB.rockpaperscissors_players[src][1]] with their hand!") + opponent.visible_message("[opponent] makes [GLOB.rockpaperscissors_players[opponent][1]] with their hands!") + switch(result_us) + if(ROCKPAPERSCISSORS_TIE) + src.visible_message("It was a tie!") + if(ROCKPAPERSCISSORS_WIN) + src.visible_message("[src] wins!") + if(ROCKPAPERSCISSORS_LOSE) + src.visible_message("[opponent] wins!") + + //make the progress bar end so that each player can handle the result + return DO_AFTER_STOP + + //no opponent was found, so keep searching + return DO_AFTER_PROCEED + +//the actual emotes +/datum/emote/living/carbon/human/rockpaperscissors + message = "is attempting to play rock paper scissors!" + +/datum/emote/living/carbon/human/rockpaperscissors/rock + key = "rock" + +/datum/emote/living/carbon/human/rockpaperscissors/paper + key = "paper" + +/datum/emote/living/carbon/human/rockpaperscissors/scissors + key = "scissors" + +/datum/emote/living/carbon/human/rockpaperscissors/run_emote(mob/living/carbon/human/user, params) + if(!(user in GLOB.rockpaperscissors_players)) //no using the emote again while already playing! + . = ..() + user.beginRockPaperScissors(key) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index d32184edb5..65b2931e08 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -163,16 +163,19 @@ msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n" else msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n" + for(var/i in BP.wounds) + var/datum/wound/iter_wound = i + msg += "[iter_wound.get_examine_description(user)]\n" for(var/X in disabled) var/obj/item/bodypart/BP = X var/damage_text - if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //Stamina is disabling the limb - damage_text = "limp and lifeless" - else - damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg - msg += "[capitalize(t_his)] [BP.name] is [damage_text]!\n" - + if(BP.is_disabled() != BODYPART_DISABLED_WOUND) // skip if it's disabled by a wound (cuz we'll be able to see the bone sticking out!) + if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //we don't care if it's stamcritted + damage_text = "limp and lifeless" + else + damage_text = (BP.brute_dam >= BP.burn_dam) ? BP.heavy_brute_msg : BP.heavy_burn_msg + msg += "[capitalize(t_his)] [BP.name] is [damage_text]!\n" //stores missing limbs var/l_limbs_missing = 0 var/r_limbs_missing = 0 @@ -246,16 +249,52 @@ if(DISGUST_LEVEL_DISGUSTED to INFINITY) msg += "[t_He] look[p_s()] extremely disgusted.\n" - if(ShowAsPaleExamine()) - msg += "[t_He] [t_has] pale skin.\n" + var/apparent_blood_volume = blood_volume + if(dna.species.use_skintones && skin_tone == "albino") + apparent_blood_volume -= 150 // enough to knock you down one tier + switch(apparent_blood_volume) + if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) + msg += "[t_He] [t_has] pale skin.\n" + if(BLOOD_VOLUME_BAD to BLOOD_VOLUME_OKAY) + msg += "[t_He] look[p_s()] like pale death.\n" + if(-INFINITY to BLOOD_VOLUME_BAD) + msg += "[t_He] resemble[p_s()] a crushed, empty juice pouch.\n" if(bleedsuppress) - msg += "[t_He] [t_is] bandaged with something.\n" - else if(bleed_rate) - if(bleed_rate >= 8) //8 is the rate at which heparin causes you to bleed - msg += "[t_He] [t_is] bleeding uncontrollably!\n" + msg += "[t_He] [t_is] embued with a power that defies bleeding.\n" // only statues and highlander sword can cause this so whatever + else if(is_bleeding()) + var/list/obj/item/bodypart/bleeding_limbs = list() + + for(var/i in bodyparts) + var/obj/item/bodypart/BP = i + if(BP.get_bleed_rate()) + bleeding_limbs += BP + + var/num_bleeds = LAZYLEN(bleeding_limbs) + var/list/bleed_text + if(appears_dead) + bleed_text = list("Blood is visible in [t_his] open") else - msg += "[t_He] [t_is] bleeding!\n" + bleed_text = list("[t_He] [t_is] bleeding from [t_his]") + + switch(num_bleeds) + if(1 to 2) + bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]" + if(3 to INFINITY) + for(var/i in 1 to (num_bleeds - 1)) + var/obj/item/bodypart/BP = bleeding_limbs[i] + bleed_text += " [BP.name]," + bleed_text += " and [bleeding_limbs[num_bleeds].name]" + + + if(appears_dead) + bleed_text += ", but it has pooled and is not flowing.\n" + else + if(reagents.has_reagent(/datum/reagent/toxin/heparin)) + bleed_text += " incredibly quickly" + + bleed_text += "!\n" + msg += bleed_text.Join() if(reagents.has_reagent(/datum/reagent/teslium)) msg += "[t_He] [t_is] emitting a gentle blue glow!\n" @@ -331,6 +370,21 @@ if(digitalcamo) msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n" + var/scar_severity = 0 + for(var/i in all_scars) + var/datum/scar/S = i + if(S.is_visible(user)) + scar_severity += S.severity + + switch(scar_severity) + if(1 to 2) + msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n" + if(3 to 4) + msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n" + if(5 to 6) + msg += "[t_He] [t_has] significantly disfiguring scarring, you can look again to take a closer look...\n" + if(7 to INFINITY) + msg += "[t_He] [t_is] just absolutely fucked up, you can look again to take a closer look...\n" if (length(msg)) . += "[msg.Join("")]" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 4421c383e6..38b420aaba 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -33,6 +33,7 @@ enable_intentional_sprint_mode() RegisterSignal(src, COMSIG_COMPONENT_CLEAN_ACT, /atom.proc/clean_blood) + GLOB.human_list += src /mob/living/carbon/human/ComponentInitialize() @@ -47,6 +48,7 @@ /mob/living/carbon/human/Destroy() QDEL_NULL(physiology) QDEL_NULL_LIST(vore_organs) // CITADEL EDIT belly stuff + GLOB.human_list -= src return ..() /mob/living/carbon/human/prepare_data_huds() @@ -152,8 +154,12 @@ dat += " " - dat += "Exosuit:[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "Empty"]" + dat += "Exosuit:[(wear_suit && !(wear_suit.item_flags & ABSTRACT)) ? wear_suit : "Empty"]" if(wear_suit) + if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit)) + var/hardsuit_head = head && istype(head, /obj/item/clothing/head/helmet/space/hardsuit) + dat += " [hardsuit_head ? "Retract Helmet" : "Extend Helmet"]" + dat += "" dat += " ↳Suit Storage:[(s_store && !(s_store.item_flags & ABSTRACT)) ? s_store : "Empty"]" if(has_breathable_mask && istype(s_store, /obj/item/tank)) dat += " [internal ? "Disable Internals" : "Set Internals"]" @@ -164,7 +170,11 @@ if(SLOT_SHOES in obscured) dat += "Shoes:Obscured" else - dat += "Shoes:[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "Empty"]" + dat += "Shoes:[(shoes && !(shoes.item_flags & ABSTRACT)) ? shoes : "Empty"]" + if(shoes && shoes.can_be_tied && shoes.tied != SHOES_KNOTTED) + dat += " [shoes.tied ? "Untie shoes" : "Knot shoes"]" + + dat += "" if(SLOT_GLOVES in obscured) dat += "Gloves:Obscured" @@ -222,13 +232,28 @@ return SEND_SIGNAL(src, COMSIG_CARBON_EMBED_RIP, I, L) return - + if(href_list["toggle_helmet"]) + if(!istype(head, /obj/item/clothing/head/helmet/space/hardsuit)) + return + var/obj/item/clothing/head/helmet/space/hardsuit/hardsuit_head = head + visible_message("[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.", \ + "[usr] tries to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.", \ + target = usr, target_message = "You try to [hardsuit_head ? "retract" : "extend"] [src]'s helmet.") + if(!do_mob(usr, src, hardsuit_head ? head.strip_delay : POCKET_STRIP_DELAY)) + return + if(!istype(wear_suit, /obj/item/clothing/suit/space/hardsuit) || (hardsuit_head ? (!head || head != hardsuit_head) : head)) + return + var/obj/item/clothing/suit/space/hardsuit/hardsuit = wear_suit //This should be an hardsuit given all our checks + if(hardsuit.ToggleHelmet(FALSE)) + visible_message("[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet", \ + "[usr] [hardsuit_head ? "retract" : "extend"] [src]'s helmet", \ + target = usr, target_message = "You [hardsuit_head ? "retract" : "extend"] [src]'s helmet.") + return if(href_list["item"]) var/slot = text2num(href_list["item"]) if(slot in check_obscured_slots()) to_chat(usr, "You can't reach that! Something is covering it.") return - if(href_list["pockets"]) var/strip_mod = 1 var/strip_silence = FALSE @@ -273,6 +298,12 @@ if (!strip_silence) to_chat(src, "You feel your [pocket_side] pocket being fumbled with!") + if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY, null, FALSE)) + // separate from first canusetopic + var/mob/living/user = usr + if(istype(user) && href_list["shoes"] && (user.mobility_flags & MOBILITY_USE)) // we need to be on the ground, so we'll be a bit looser + shoes.handle_tying(usr) + ..() //CITADEL CHANGE - removes a tab from behind this ..() so that flavortext can actually be examined @@ -369,7 +400,7 @@ // Checks the user has security clearence before allowing them to change arrest status via hud, comment out to enable all access var/allowed_access = null var/obj/item/clothing/glasses/G = H.glasses - if (!(G.obj_flags |= EMAGGED)) + if (!(G.obj_flags & EMAGGED)) if(H.wear_id) var/list/access = H.wear_id.GetAccess() if(ACCESS_SEC_DOORS in access) @@ -511,33 +542,15 @@ // Might need re-wording. to_chat(user, "There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"].") -/mob/living/carbon/human/proc/check_obscured_slots() - var/list/obscured = list() - +/mob/living/carbon/human/check_obscured_slots() + . = ..() if(wear_suit) if(wear_suit.flags_inv & HIDEGLOVES) - obscured |= SLOT_GLOVES + LAZYOR(., SLOT_GLOVES) if(wear_suit.flags_inv & HIDEJUMPSUIT) - obscured |= SLOT_W_UNIFORM + LAZYOR(., SLOT_W_UNIFORM) if(wear_suit.flags_inv & HIDESHOES) - obscured |= SLOT_SHOES - - if(head) - if(head.flags_inv & HIDEMASK) - obscured |= SLOT_WEAR_MASK - if(head.flags_inv & HIDEEYES) - obscured |= SLOT_GLASSES - if(head.flags_inv & HIDEEARS) - obscured |= SLOT_EARS - - if(wear_mask) - if(wear_mask.flags_inv & HIDEEYES) - obscured |= SLOT_GLASSES - - if(obscured.len) - return obscured - else - return null + LAZYOR(., SLOT_SHOES) /mob/living/carbon/human/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null) if(judgement_criteria & JUDGE_EMAGGED) @@ -732,8 +745,7 @@ /mob/living/carbon/human/resist_restraints() if(wear_suit && wear_suit.breakouttime) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT + MarkResistTime() cuff_resist(wear_suit) else ..() @@ -982,7 +994,7 @@ if(target.incapacitated(FALSE, TRUE) || incapacitated(FALSE, TRUE)) target.visible_message("[target] can't hang onto [src]!") return - buckle_mob(target, TRUE, TRUE, FALSE, 0, 2, FALSE) + buckle_mob(target, TRUE, TRUE, FALSE, 1, 2, FALSE) else visible_message("[target] fails to climb onto [src]!") else @@ -1028,15 +1040,9 @@ return TRUE return FALSE -/mob/living/carbon/human/proc/clear_shove_slowdown() - remove_movespeed_modifier(/datum/movespeed_modifier/shove) - var/active_item = get_active_held_item() - if(is_type_in_typecache(active_item, GLOB.shove_disarming_types)) - visible_message("[src.name] regains their grip on \the [active_item]!", "You regain your grip on \the [active_item]", null, COMBAT_MESSAGE_RANGE) - /mob/living/carbon/human/updatehealth() . = ..() - + dna?.species.spec_updatehealth(src) if(HAS_TRAIT(src, TRAIT_IGNORESLOWDOWN)) //if we want to ignore slowdown from damage and equipment remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) @@ -1054,10 +1060,21 @@ remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown) remove_movespeed_modifier(/datum/movespeed_modifier/damage_slowdown_flying) + /mob/living/carbon/human/do_after_coefficent() . = ..() . *= physiology.do_after_speed +/mob/living/carbon/human/is_bleeding() + if(NOBLOOD in dna.species.species_traits || bleedsuppress) + return FALSE + return ..() + +/mob/living/carbon/human/get_total_bleed_rate() + if(NOBLOOD in dna.species.species_traits) + return FALSE + return ..() + /mob/living/carbon/human/species var/race = null @@ -1182,6 +1199,9 @@ /mob/living/carbon/human/species/lizard race = /datum/species/lizard +/mob/living/carbon/human/species/ethereal + race = /datum/species/ethereal + /mob/living/carbon/human/species/lizard/ashwalker race = /datum/species/lizard/ashwalker diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index a3705ef53c..b1834da621 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -34,6 +34,19 @@ protection += physiology.armor.getRating(d_type) return protection +///Get all the clothing on a specific body part +/mob/living/carbon/human/proc/clothingonpart(obj/item/bodypart/def_zone) + var/list/covering_part = list() + var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor) + for(var/bp in body_parts) + if(!bp) + continue + if(bp && istype(bp , /obj/item/clothing)) + var/obj/item/clothing/C = bp + if(C.body_parts_covered & def_zone.body_part) + covering_part += C + return covering_part + /mob/living/carbon/human/on_hit(obj/item/projectile/P) if(dna && dna.species) dna.species.on_hit(P, src) @@ -106,18 +119,21 @@ 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) + apply_damage(15, BRUTE, wound_bonus=10) return 1 -/mob/living/carbon/human/attack_hand(mob/user) +/mob/living/carbon/human/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) //To allow surgery to return properly. return if(ishuman(user)) var/mob/living/carbon/human/H = user - dna.species.spec_attack_hand(H, src) + dna.species.spec_attack_hand(H, src, null, act_intent, unarmed_attack_flags) /mob/living/carbon/human/attack_paw(mob/living/carbon/monkey/M) + if(!M.CheckActionCooldown(CLICK_CD_MELEE)) + return + M.DelayNextAction() var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) if(!affecting) @@ -217,16 +233,17 @@ if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration) - apply_damage(damage, M.melee_damage_type, affecting, armor) - + apply_damage(damage, M.melee_damage_type, affecting, armor, wound_bonus = M.wound_bonus, bare_wound_bonus = M.bare_wound_bonus, sharpness = M.sharpness) /mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M) . = ..() if(!.) //unsuccessful slime attack return var/damage = rand(5, 25) + var/wound_mod = -45 // 25^1.4=90, 90-45=45 if(M.is_adult) damage = rand(10, 35) + wound_mod = -90 // 35^1.4=145, 145-90=55 var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) if(!dam_zone) //Dismemberment successful @@ -236,7 +253,7 @@ if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST) var/armor_block = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor_block) + apply_damage(damage, BRUTE, affecting, armor_block, wound_bonus=wound_mod) /mob/living/carbon/human/mech_melee_attack(obj/mecha/M) if(M.occupant.a_intent == INTENT_HARM) @@ -282,10 +299,10 @@ /mob/living/carbon/human/ex_act(severity, target, origin) - if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) + if(TRAIT_BOMBIMMUNE in dna.species.species_traits) return ..() - if (!severity) + if (!severity || QDELETED(src)) return var/brute_loss = 0 var/burn_loss = 0 @@ -319,7 +336,8 @@ if (!istype(ears, /obj/item/clothing/ears/earmuffs)) adjustEarDamage(30, 120) Unconscious(20) //short amount of time for follow up attacks against elusive enemies like wizards - Knockdown(200 - (bomb_armor * 1.6)) //between ~4 and ~20 seconds of knockdown depending on bomb armor + Knockdown((200 - (bomb_armor * 1.6)) / 4) //between ~1 and ~5 seconds of knockdown depending on bomb armor + adjustStaminaLoss(brute_loss) if(EXPLODE_LIGHT) brute_loss = 30 @@ -328,7 +346,8 @@ damage_clothes(max(50 - bomb_armor, 0), BRUTE, "bomb") if (!istype(ears, /obj/item/clothing/ears/earmuffs)) adjustEarDamage(15,60) - Knockdown(160 - (bomb_armor * 1.6)) //100 bomb armor will prevent knockdown altogether + Knockdown((160 - (bomb_armor * 1.6)) / 4) //100 bomb armor will prevent knockdown altogether + adjustStaminaLoss(brute_loss) take_overall_damage(brute_loss,burn_loss) @@ -626,6 +645,20 @@ no_damage = TRUE to_send += "\t Your [LB.name] [HAS_TRAIT(src, TRAIT_SELF_AWARE) ? "has" : "is"] [status].\n" + for(var/thing in LB.wounds) + var/datum/wound/W = thing + var/msg + switch(W.severity) + if(WOUND_SEVERITY_TRIVIAL) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]." + if(WOUND_SEVERITY_MODERATE) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!" + if(WOUND_SEVERITY_SEVERE) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!" + if(WOUND_SEVERITY_CRITICAL) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!" + to_chat(src, msg) + for(var/obj/item/I in LB.embedded_objects) if(I.isEmbedHarmless()) to_chat(src, "\t There is \a [I] stuck to your [LB.name]!") @@ -635,8 +668,25 @@ for(var/t in missing) to_send += "Your [parse_zone(t)] is missing!\n" - if(bleed_rate) - to_send += "You are bleeding!\n" + if(is_bleeding()) + var/list/obj/item/bodypart/bleeding_limbs = list() + for(var/i in bodyparts) + var/obj/item/bodypart/BP = i + if(BP.get_bleed_rate()) + bleeding_limbs += BP + + var/num_bleeds = LAZYLEN(bleeding_limbs) + var/bleed_text = "You are bleeding from your" + switch(num_bleeds) + if(1 to 2) + bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]" + if(3 to INFINITY) + for(var/i in 1 to (num_bleeds - 1)) + var/obj/item/bodypart/BP = bleeding_limbs[i] + bleed_text += " [BP.name]," + bleed_text += " and [bleeding_limbs[num_bleeds].name]" + bleed_text += "!" + to_chat(src, bleed_text) if(getStaminaLoss()) if(getStaminaLoss() > 30) to_send += "You're completely exhausted.\n" @@ -729,6 +779,89 @@ ..() +/mob/living/carbon/human/check_self_for_injuries() + if(stat == DEAD || stat == UNCONSCIOUS) + return + + visible_message("[src] examines [p_them()]self.", \ + "You check yourself for injuries.") + + var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + + for(var/X in bodyparts) + var/obj/item/bodypart/LB = X + missing -= LB.body_zone + if(LB.is_pseudopart) //don't show injury text for fake bodyparts; ie chainsaw arms or synthetic armblades + continue + var/self_aware = FALSE + if(HAS_TRAIT(src, TRAIT_SELF_AWARE)) + self_aware = TRUE + var/limb_max_damage = LB.max_damage + var/status = "" + var/brutedamage = LB.brute_dam + var/burndamage = LB.burn_dam + if(hallucination) + if(prob(30)) + brutedamage += rand(30,40) + if(prob(30)) + burndamage += rand(30,40) + + if(HAS_TRAIT(src, TRAIT_SELF_AWARE)) + status = "[brutedamage] brute damage and [burndamage] burn damage" + if(!brutedamage && !burndamage) + status = "no damage" + + else + if(brutedamage > 0) + status = LB.light_brute_msg + if(brutedamage > (limb_max_damage*0.4)) + status = LB.medium_brute_msg + if(brutedamage > (limb_max_damage*0.8)) + status = LB.heavy_brute_msg + if(brutedamage > 0 && burndamage > 0) + status += " and " + + if(burndamage > (limb_max_damage*0.8)) + status += LB.heavy_burn_msg + else if(burndamage > (limb_max_damage*0.2)) + status += LB.medium_burn_msg + else if(burndamage > 0) + status += LB.light_burn_msg + + if(status == "") + status = "OK" + var/no_damage + if(status == "OK" || status == "no damage") + no_damage = TRUE + var/isdisabled = " " + if(LB.is_disabled()) + isdisabled = " is disabled " + if(no_damage) + isdisabled += " but otherwise " + else + isdisabled += " and " + to_chat(src, "\t Your [LB.name][isdisabled][self_aware ? " has " : " is "][status].") + + for(var/thing in LB.wounds) + var/datum/wound/W = thing + var/msg + switch(W.severity) + if(WOUND_SEVERITY_TRIVIAL) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]." + if(WOUND_SEVERITY_MODERATE) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!" + if(WOUND_SEVERITY_SEVERE) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!" + if(WOUND_SEVERITY_CRITICAL) + msg = "\t Your [LB.name] is suffering [W.a_or_from] [lowertext(W.name)]!!" + to_chat(src, msg) + + for(var/obj/item/I in LB.embedded_objects) + if(I.isEmbedHarmless()) + to_chat(src, "\t There is \a [I] stuck to your [LB.name]!") + else + to_chat(src, "\t There is \a [I] embedded in your [LB.name]!") + /mob/living/carbon/human/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone) if(damage_type != BRUTE && damage_type != BURN) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index e7be540eb9..13456ed61c 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -7,12 +7,14 @@ buckle_lying = FALSE mob_biotypes = MOB_ORGANIC|MOB_HUMANOID /// Enable stamina combat - combat_flags = COMBAT_FLAGS_DEFAULT + combat_flags = COMBAT_FLAGS_DEFAULT | COMBAT_FLAG_UNARMED_PARRY status_flags = CANSTUN|CANKNOCKDOWN|CANUNCONSCIOUS|CANPUSH|CANSTAGGER has_field_of_vision = FALSE //Handled by species. blocks_emissive = EMISSIVE_BLOCK_UNIQUE + block_parry_data = /datum/block_parry_data/unarmed/human + //Hair colour and style var/hair_color = "000" var/hair_style = "Bald" @@ -49,7 +51,6 @@ var/special_voice = "" // For changing our voice. Used by a symptom. - var/bleed_rate = 0 //how much are we bleeding var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding var/blood_state = BLOOD_STATE_NOT_BLOODY @@ -71,3 +72,45 @@ var/lastpuke = 0 var/account_id var/last_fire_update + +/// Unarmed parry data for human +/datum/block_parry_data/unarmed/human + parry_respect_clickdelay = TRUE + parry_stamina_cost = 4 + parry_attack_types = ATTACK_TYPE_UNARMED + parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING + + parry_time_windup = 0 + parry_time_spindown = 1 + parry_time_active = 5 + + parry_time_perfect = 1 + parry_time_perfect_leeway = 1 + parry_imperfect_falloff_percent = 20 + parry_efficiency_perfect = 100 + + parry_efficiency_considered_successful = 0.01 + parry_efficiency_to_counterattack = 0.01 + parry_max_attacks = 3 + parry_cooldown = 30 + parry_failed_stagger_duration = 0 + parry_failed_clickcd_duration = 0.4 + + parry_data = list( // yeah it's snowflake + "HUMAN_PARRY_STAGGER" = 3 SECONDS, + "HUMAN_PARRY_PUNCH" = TRUE, + "HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9 + ) + +/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) + var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data) + if(!owner.Adjacent(attacker)) + return ..() + if(parry_efficiency < D.parry_data["HUMAN_PARRY_MINIMUM_EFFICIENCY"]) + return ..() + visible_message("[src] strikes back perfectly at [attacker], staggering them!") + if(D.parry_data["HUMAN_PARRY_PUNCH"]) + UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING) + var/mob/living/L = attacker + if(istype(L)) + L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"]) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 7c256f5367..af95b9e1b7 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -151,3 +151,32 @@ if(blood_dna.len) last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works last_blood_DNA = blood_dna[blood_dna.len]*/ + +/// For use formatting all of the scars this human has for saving for persistent scarring +/mob/living/carbon/human/proc/format_scars() + var/list/missing_bodyparts = get_missing_limbs() + if(!all_scars && !length(missing_bodyparts)) + return + var/scars = "" + for(var/i in missing_bodyparts) + var/datum/scar/scaries = new + scars += "[scaries.format_amputated(i)]" + for(var/i in all_scars) + var/datum/scar/scaries = i + scars += "[scaries.format()];" + return scars + +/// Takes a single scar from the persistent scar loader and recreates it from the saved data +/mob/living/carbon/human/proc/load_scar(scar_line) + var/list/scar_data = splittext(scar_line, "|") + if(LAZYLEN(scar_data) != SCAR_SAVE_LENGTH) + return // invalid, should delete + var/version = text2num(scar_data[SCAR_SAVE_VERS]) + if(!version || version < SCAR_CURRENT_VERSION) // get rid of old scars + return + var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]") + var/datum/scar/scaries = new + return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY])) + +/mob/living/carbon/human/get_biological_state() + return dna.species.get_biological_state() diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 63ca3f372e..bcb658eab8 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -36,8 +36,9 @@ return FALSE return ..() -/mob/living/carbon/human/experience_pressure_difference() - playsound(src, 'sound/effects/space_wind.ogg', 50, 1) +/mob/living/carbon/human/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0, throw_target) + if(prob(pressure_difference * 2.5)) + playsound(src, 'sound/effects/space_wind.ogg', 50, 1) if(shoes && istype(shoes, /obj/item/clothing)) var/obj/item/clothing/S = shoes if (S.clothing_flags & NOSLIP) @@ -58,7 +59,7 @@ . = ..() for(var/datum/mutation/human/HM in dna.mutations) HM.on_move(NewLoc) - if(. && (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && !(movement_type & FLYING) && CHECK_ALL_MOBILITY(src, MOBILITY_MOVE|MOBILITY_STAND) && m_intent == MOVE_INTENT_RUN && has_gravity(loc) && !pulledby) + if(. && (combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && !(movement_type & FLYING) && CHECK_ALL_MOBILITY(src, MOBILITY_MOVE|MOBILITY_STAND) && m_intent == MOVE_INTENT_RUN && has_gravity(loc) && (!pulledby || (pulledby.pulledby == src))) if(!HAS_TRAIT(src, TRAIT_FREESPRINT)) doSprintLossTiles(1) if((oldpseudoheight - pseudo_z_axis) >= 8) @@ -77,7 +78,7 @@ var/turf/T = get_turf(src) if(S.bloody_shoes && S.bloody_shoes[S.blood_state]) var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T - if(oldFP && (oldFP.blood_state == S.blood_state && oldFP.color == bloodtype_to_color(S.last_bloodtype))) + if(oldFP && (oldFP.blood_state == S.blood_state && oldFP.color == S.last_blood_color)) return S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP) var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T) @@ -85,7 +86,11 @@ FP.entered_dirs |= dir FP.bloodiness = S.bloody_shoes[S.blood_state] if(S.last_bloodtype) - FP.blood_DNA += list(S.last_blood_DNA = S.last_bloodtype) + FP.blood_DNA[S.last_blood_DNA] = S.last_bloodtype + if(!FP.blood_DNA["color"]) + FP.blood_DNA["color"] = S.last_blood_color + else + FP.blood_DNA["color"] = BlendRGB(FP.blood_DNA["color"], S.last_blood_color) FP.update_icon() update_inv_shoes() //End bloody footprints diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 8de143e2bd..523369d10a 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -1,5 +1,18 @@ -/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) - return dna.species.can_equip(I, slot, disable_warning, src, bypass_equip_delay_self) +/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) + return dna.species.can_equip(I, slot, disable_warning, src, bypass_equip_delay_self, clothing_check, return_warning) + +/** + * Used to return a list of equipped items on a human mob; does not include held items (use get_all_gear) + * + * Argument(s): + * * Optional - include_pockets (TRUE/FALSE), whether or not to include the pockets and suit storage in the returned list + */ + +/mob/living/carbon/human/get_equipped_items(include_pockets = FALSE) + var/list/items = ..() + if(!include_pockets) + items -= list(l_store, r_store, s_store) + return items // Return the item currently in the slot ID /mob/living/carbon/human/get_item_by_slot(slot_id) @@ -142,7 +155,7 @@ //Item is handled and in slot, valid to call callback, for this proc should always be true if(!not_handled) I.equipped(src, slot) - + update_genitals() return not_handled //For future deeper overrides /mob/living/carbon/human/equipped_speed_mods() @@ -230,6 +243,7 @@ s_store = null if(!QDELETED(src)) update_inv_s_store() + update_genitals() /mob/living/carbon/human/wear_mask_update(obj/item/clothing/C, toggle_off = 1) if((C.flags_inv & (HIDEHAIR|HIDEFACIALHAIR)) || (initial(C.flags_inv) & (HIDEHAIR|HIDEFACIALHAIR))) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 86b6406081..56ab1f1b10 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -18,32 +18,21 @@ #define THERMAL_PROTECTION_HAND_LEFT 0.025 #define THERMAL_PROTECTION_HAND_RIGHT 0.025 -/mob/living/carbon/human/Life(seconds, times_fired) - set invisibility = 0 - if (notransform) +/mob/living/carbon/human/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return + handle_active_genes() + //heart attack stuff + handle_heart() + dna.species.spec_life(src) // for mutantraces + return (stat != DEAD) && !QDELETED(src) - . = ..() - - if (QDELETED(src)) - return 0 - - if(.) //not dead - handle_active_genes() - - if(stat != DEAD) - //heart attack stuff - handle_heart() - +/mob/living/carbon/human/PhysicalLife(seconds, times_fired) + if(!(. = ..())) + return //Update our name based on whether our face is obscured/disfigured name = get_visible_name() - dna.species.spec_life(src) // for mutantraces - - if(stat != DEAD) - return 1 - - /mob/living/carbon/human/calculate_affecting_pressure(pressure) var/headless = !get_bodypart(BODY_ZONE_HEAD) //should the mob be perennially headless (see dullahans), we only take the suit into account, so they can into space. if (wear_suit && istype(wear_suit, /obj/item/clothing) && (headless || (head && istype(head, /obj/item/clothing)))) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index d703f6a4e2..22cb10026b 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -91,6 +91,7 @@ return " (as [get_id_name("Unknown")])" /mob/living/carbon/human/proc/forcesay(list/append) //this proc is at the bottom of the file because quote fuckery makes notepad++ cri + set waitfor = FALSE // WINGET IS A SLEEP. DO. NOT. SLEEP. if(stat == CONSCIOUS) if(client) var/temp = winget(client, "input", "text") diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index e98931acca..8e3a43007c 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -7,7 +7,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans. var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever - var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race + var/default_color = "#FFFFFF" // 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 @@ -39,6 +39,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/use_skintones = NO_SKINTONES // does it use skintones or not? (spoiler alert this is only used by humans) var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id. var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc) + var/exotic_blood_color = BLOOD_COLOR_HUMAN //assume human as the default blood colour, override this default by species subtypes var/meat = /obj/item/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing var/list/gib_types = list(/obj/effect/gibspawner/human, /obj/effect/gibspawner/human/bodypartless) var/skinned_type @@ -55,6 +56,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 var/armor = 0 // overall defense for the race... or less defense, if it's negative. + var/attack_type = BRUTE // the type of damage unarmed attacks from this species do var/brutemod = 1 // multiplier for brute damage var/burnmod = 1 // multiplier for burn damage var/coldmod = 1 // multiplier for cold damage @@ -72,7 +74,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/datum/outfit/outfit_important_for_life // A path to an outfit that is important for species life e.g. plasmaman outfit // species-only traits. Can be found in DNA.dm - var/list/species_traits = list() + var/list/species_traits = list(HAS_FLESH,HAS_BONE) //by default they can scar and have bones/flesh unless set to something else // generic traits tied to having the species var/list/inherent_traits = list() var/inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID @@ -104,21 +106,31 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/whitelisted = 0 //Is this species restricted to certain players? 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. + var/species_type + + var/tail_type //type of tail i.e. mam_tail + var/wagging_type //type of wagging i.e. waggingtail_lizard /// Our default override for typing indicator state var/typing_indicator_state + //the ids you can use for your species, if empty, it means default only and not changeable + var/list/allowed_limb_ids + /////////// // PROCS // /////////// - /datum/species/New() if(!limbs_id) //if we havent set a limbs id to use, just use our own id - limbs_id = id + mutant_bodyparts["limbs_id"] = id //done this way to be non-intrusive to the existing system + else + mutant_bodyparts["limbs_id"] = limbs_id ..() + //update our mutant bodyparts to include unlocked ones + mutant_bodyparts += GLOB.unlocked_mutant_parts /proc/generate_selectable_species(clear = FALSE) if(clear) @@ -386,7 +398,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) //keep it at the right spot, so we can't have people taking shortcuts var/location = C.dna.mutation_index.Find(inert_mutation) C.dna.mutation_index[location] = new_species.inert_mutation + C.dna.default_mutation_genes[location] = C.dna.mutation_index[location] C.dna.mutation_index[new_species.inert_mutation] = create_sequence(new_species.inert_mutation) + C.dna.default_mutation_genes[new_species.inert_mutation] = C.dna.mutation_index[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) @@ -644,106 +658,19 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!mutant_bodyparts) return - var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD) var/tauric = mutant_bodyparts["taur"] && H.dna.features["taur"] && H.dna.features["taur"] != "None" - if(mutant_bodyparts["tail_lizard"]) - if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) - bodyparts_to_add -= "tail_lizard" - - if(mutant_bodyparts["waggingtail_lizard"]) - if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) - bodyparts_to_add -= "waggingtail_lizard" - else if (mutant_bodyparts["tail_lizard"]) - bodyparts_to_add -= "waggingtail_lizard" - - if(mutant_bodyparts["tail_human"]) - if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) - bodyparts_to_add -= "tail_human" - - if(mutant_bodyparts["waggingtail_human"]) - if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) - bodyparts_to_add -= "waggingtail_human" - else if (mutant_bodyparts["tail_human"]) - bodyparts_to_add -= "waggingtail_human" - - if(mutant_bodyparts["spines"]) - if(!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) - bodyparts_to_add -= "spines" - - if(mutant_bodyparts["waggingspines"]) - if(!H.dna.features["spines"] || H.dna.features["spines"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) - bodyparts_to_add -= "waggingspines" - else if (mutant_bodyparts["tail"]) - bodyparts_to_add -= "waggingspines" - - if(mutant_bodyparts["snout"]) //Take a closer look at that snout! - if((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)) - bodyparts_to_add -= "snout" - - if(mutant_bodyparts["frills"]) - if(!H.dna.features["frills"] || H.dna.features["frills"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || !HD || HD.status == BODYPART_ROBOTIC) - bodyparts_to_add -= "frills" - - if(mutant_bodyparts["horns"]) - if(!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)) - bodyparts_to_add -= "horns" - - if(mutant_bodyparts["ears"]) - if(!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)) - bodyparts_to_add -= "ears" - - if(mutant_bodyparts["wings"]) - if(!H.dna.features["wings"] || H.dna.features["wings"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception)))) - bodyparts_to_add -= "wings" - - if(mutant_bodyparts["wings_open"]) - if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT) && (!H.wear_suit.species_exception || !is_type_in_list(src, H.wear_suit.species_exception))) - bodyparts_to_add -= "wings_open" - else if (mutant_bodyparts["wings"]) - bodyparts_to_add -= "wings_open" - - if(mutant_bodyparts["insect_fluff"]) - if(!H.dna.features["insect_fluff"] || H.dna.features["insect_fluff"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) - bodyparts_to_add -= "insect_fluff" - -//CITADEL EDIT - //Race specific bodyparts: - //Xenos - if(mutant_bodyparts["xenodorsal"]) - if(!H.dna.features["xenodorsal"] || H.dna.features["xenodorsal"] == "None" || (H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))) - bodyparts_to_add -= "xenodorsal" - if(mutant_bodyparts["xenohead"])//This is an overlay for different castes using different head crests - if(!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)) - bodyparts_to_add -= "xenohead" - if(mutant_bodyparts["xenotail"]) - if(!H.dna.features["xenotail"] || H.dna.features["xenotail"] == "None" || H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT)) - bodyparts_to_add -= "xenotail" - - //Other Races - if(mutant_bodyparts["mam_tail"]) - if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) - bodyparts_to_add -= "mam_tail" - - if(mutant_bodyparts["mam_waggingtail"]) - if((H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR)) || tauric) - bodyparts_to_add -= "mam_waggingtail" - else if (mutant_bodyparts["mam_tail"]) - bodyparts_to_add -= "mam_waggingtail" - - if(mutant_bodyparts["mam_ears"]) - if(!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)) - bodyparts_to_add -= "mam_ears" - - if(mutant_bodyparts["mam_snouts"]) //Take a closer look at that snout! - if((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)) - bodyparts_to_add -= "mam_snouts" - - if(mutant_bodyparts["taur"]) - if(!tauric || (H.wear_suit && (H.wear_suit.flags_inv & HIDETAUR))) - bodyparts_to_add -= "taur" - -//END EDIT + for(var/mutant_part in mutant_bodyparts) + var/reference_list = GLOB.mutant_reference_list[mutant_part] + if(reference_list) + var/datum/sprite_accessory/S + var/transformed_part = GLOB.mutant_transform_list[mutant_part] + if(transformed_part) + S = reference_list[H.dna.features[transformed_part]] + else + S = reference_list[H.dna.features[mutant_part]] + if(!S || S.is_not_visible(H, tauric)) + bodyparts_to_add -= mutant_part //Digitigrade legs are stuck in the phantom zone between true limbs and mutant bodyparts. Mainly it just needs more agressive updating than most limbs. var/update_needed = FALSE @@ -780,76 +707,22 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/list/dna_feature_as_text_string = list() for(var/bodypart in bodyparts_to_add) - var/datum/sprite_accessory/S - switch(bodypart) - if("tail_lizard") - S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]] - if("waggingtail_lizard") - S = GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]] - if("tail_human") - S = GLOB.tails_list_human[H.dna.features["tail_human"]] - if("waggingtail_human") - S = GLOB.animated_tails_list_human[H.dna.features["tail_human"]] - if("spines") - S = GLOB.spines_list[H.dna.features["spines"]] - if("waggingspines") - S = GLOB.animated_spines_list[H.dna.features["spines"]] - if("snout") - S = GLOB.snouts_list[H.dna.features["snout"]] - if("frills") - S = GLOB.frills_list[H.dna.features["frills"]] - if("horns") - S = GLOB.horns_list[H.dna.features["horns"]] - if("ears") - S = GLOB.ears_list[H.dna.features["ears"]] - if("body_markings") - S = GLOB.body_markings_list[H.dna.features["body_markings"]] - if("wings") - S = GLOB.wings_list[H.dna.features["wings"]] - if("wingsopen") - S = GLOB.wings_open_list[H.dna.features["wings"]] - if("deco_wings") - S = GLOB.deco_wings_list[H.dna.features["deco_wings"]] - if("legs") - S = GLOB.legs_list[H.dna.features["legs"]] - if("insect_wings") - S = GLOB.insect_wings_list[H.dna.features["insect_wings"]] - if("insect_fluff") - S = GLOB.insect_fluffs_list[H.dna.features["insect_fluff"]] - if("insect_markings") - S = GLOB.insect_markings_list[H.dna.features["insect_markings"]] - if("caps") - S = GLOB.caps_list[H.dna.features["caps"]] - if("ipc_screen") - S = GLOB.ipc_screens_list[H.dna.features["ipc_screen"]] - if("ipc_antenna") - S = GLOB.ipc_antennas_list[H.dna.features["ipc_antenna"]] - if("mam_tail") - S = GLOB.mam_tails_list[H.dna.features["mam_tail"]] - if("mam_waggingtail") - S = GLOB.mam_tails_animated_list[H.dna.features["mam_tail"]] - if("mam_body_markings") - S = GLOB.mam_body_markings_list[H.dna.features["mam_body_markings"]] - if("mam_ears") - S = GLOB.mam_ears_list[H.dna.features["mam_ears"]] - if("mam_snouts") - S = GLOB.mam_snouts_list[H.dna.features["mam_snouts"]] - if("taur") - S = GLOB.taur_list[H.dna.features["taur"]] - if("xenodorsal") - S = GLOB.xeno_dorsal_list[H.dna.features["xenodorsal"]] - if("xenohead") - S = GLOB.xeno_head_list[H.dna.features["xenohead"]] - if("xenotail") - S = GLOB.xeno_tail_list[H.dna.features["xenotail"]] + var/reference_list = GLOB.mutant_reference_list[bodypart] + if(reference_list) + var/datum/sprite_accessory/S + var/transformed_part = GLOB.mutant_transform_list[bodypart] + if(transformed_part) + S = reference_list[H.dna.features[transformed_part]] + else + S = reference_list[H.dna.features[bodypart]] - if(!S || S.icon_state == "none") - continue + if(!S || S.icon_state == "none") + continue - for(var/L in S.relevant_layers) - LAZYADD(relevant_layers["[L]"], S) - if(!S.mutant_part_string) - dna_feature_as_text_string[S] = bodypart + for(var/L in S.relevant_layers) + LAZYADD(relevant_layers["[L]"], S) + if(!S.mutant_part_string) + dna_feature_as_text_string[S] = bodypart var/static/list/layer_text = list( "[BODY_BEHIND_LAYER]" = "BEHIND", @@ -862,10 +735,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/g = (H.dna.features["body_model"] == FEMALE) ? "f" : "m" var/list/colorlist = list() var/husk = HAS_TRAIT(H, TRAIT_HUSK) - colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor"]]0") - colorlist += husk ? ReadRGB("#a3a3a3") :ReadRGB("[H.dna.features["mcolor2"]]0") - colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]0") - colorlist += list(0,0,0, hair_alpha) + colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor"]]00") + colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor2"]]00") + colorlist += husk ? ReadRGB("#a3a3a3") : ReadRGB("[H.dna.features["mcolor3"]]00") + colorlist += husk ? list(0, 0, 0) : list(0, 0, 0, hair_alpha) for(var/index in 1 to colorlist.len) colorlist[index] /= 255 @@ -1039,7 +912,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.apply_overlay(BODY_FRONT_LAYER) H.apply_overlay(HORNS_LAYER) - /* * Equip the outfit required for life. Replaces items currently worn. */ @@ -1070,17 +942,23 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.adjustBruteLoss(1) /datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H) - return + if(H) + stop_wagging_tail(H) /datum/species/proc/auto_equip(mob/living/carbon/human/H) // handles the equipping of species-specific gear return -/datum/species/proc/can_equip(obj/item/I, slot, disable_warning, mob/living/carbon/human/H, bypass_equip_delay_self = FALSE) +/datum/species/proc/can_equip(obj/item/I, slot, disable_warning, mob/living/carbon/human/H, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) if(slot in no_equip) if(!I.species_exception || !is_type_in_list(src, I.species_exception)) return FALSE + if(clothing_check && (slot in H.check_obscured_slots())) + if(return_warning) + return_warning[1] = "You are unable to equip that with your current garments in the way!" + return FALSE + var/num_arms = H.get_num_arms(FALSE) var/num_legs = H.get_num_legs(FALSE) @@ -1142,8 +1020,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!CHECK_BITFIELD(I.item_flags, NO_UNIFORM_REQUIRED)) var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST) if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC)) - if(!disable_warning) - to_chat(H, "You need a jumpsuit before you can attach this [I.name]!") + if(return_warning) + return_warning[1] = "You need a jumpsuit before you can attach this [I.name]!" return FALSE if(!(I.slot_flags & ITEM_SLOT_BELT)) return @@ -1184,8 +1062,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(!CHECK_BITFIELD(I.item_flags, NO_UNIFORM_REQUIRED)) var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_CHEST) if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC)) - if(!disable_warning) - to_chat(H, "You need a jumpsuit before you can attach this [I.name]!") + if(return_warning) + return_warning[1] = "You need a jumpsuit before you can attach this [I.name]!" return FALSE if( !(I.slot_flags & ITEM_SLOT_ID) ) return FALSE @@ -1199,8 +1077,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_L_LEG) if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC)) - if(!disable_warning) - to_chat(H, "You need a jumpsuit before you can attach this [I.name]!") + if(return_warning) + return_warning[1] = "You need a jumpsuit before you can attach this [I.name]!" return FALSE if(I.slot_flags & ITEM_SLOT_DENYPOCKET) return FALSE @@ -1215,8 +1093,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/obj/item/bodypart/O = H.get_bodypart(BODY_ZONE_R_LEG) if(!H.w_uniform && !nojumpsuit && (!O || O.status != BODYPART_ROBOTIC)) - if(!disable_warning) - to_chat(H, "You need a jumpsuit before you can attach this [I.name]!") + if(return_warning) + return_warning[1] = "You need a jumpsuit before you can attach this [I.name]!" return FALSE if(I.slot_flags & ITEM_SLOT_DENYPOCKET) return FALSE @@ -1229,16 +1107,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(H.s_store) return FALSE if(!H.wear_suit) - if(!disable_warning) - to_chat(H, "You need a suit before you can attach this [I.name]!") + if(return_warning) + return_warning[1] = "You need a suit before you can attach this [I.name]!" return FALSE if(!H.wear_suit.allowed) - if(!disable_warning) - to_chat(H, "You somehow have a suit with no defined allowed items for suit storage, stop that.") + if(return_warning) + return_warning[1] = "You somehow have a suit with no defined allowed items for suit storage, stop that." return FALSE if(I.w_class > WEIGHT_CLASS_BULKY) - if(!disable_warning) - to_chat(H, "The [I.name] is too big to attach.") //should be src? + if(return_warning) + return_warning[1] = "The [I.name] is too big to attach." return FALSE if( istype(I, /obj/item/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed) ) return TRUE @@ -1288,9 +1166,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/check_weakness(obj/item, mob/living/attacker) return FALSE -//////// - //LIFE// - //////// +///////////// +////LIFE//// +//////////// /datum/species/proc/handle_digestion(mob/living/carbon/human/H) if(HAS_TRAIT(src, TRAIT_NOHUNGER)) @@ -1365,6 +1243,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/hungry = (500 - H.nutrition) / 5 //So overeat would be 100 and default level would be 80 if(hungry >= 70) H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (hungry / 50)) + else if(isethereal(H)) + var/datum/species/ethereal/E = H.dna.species + if(E.get_charge(H) <= ETHEREAL_CHARGE_NORMAL) + H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (1.5 * (1 - E.get_charge(H) / 100))) else H.remove_movespeed_modifier(/datum/movespeed_modifier/hunger) @@ -1421,6 +1303,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // ATTACK PROCS // ////////////////// +/datum/species/proc/spec_updatehealth(mob/living/carbon/human/H) + return + +/datum/species/proc/spec_fully_heal(mob/living/carbon/human/H) + return + /datum/species/proc/help(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) if(target.health >= 0 && !HAS_TRAIT(target, TRAIT_FAKEDEATH)) target.help_shake_act(user) @@ -1449,7 +1337,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) target.grabbedby(user) return 1 -/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style) +/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style, attackchain_flags = NONE) if(!attacker_style && HAS_TRAIT(user, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm [target]!") return FALSE @@ -1461,10 +1349,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) 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 - user.adjustStaminaLossBuffered(1.5) - else - user.adjustStaminaLossBuffered(3.5) + if(!(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)) + if(HAS_TRAIT(user, TRAIT_PUGILIST))//CITADEL CHANGE - makes punching cause staminaloss but funny martial artist types get a discount + user.adjustStaminaLossBuffered(1.5) + else + user.adjustStaminaLossBuffered(3.5) if(attacker_style && attacker_style.harm_act(user,target)) return TRUE @@ -1492,23 +1381,26 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) //CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) - damage *= 1.5 + damage *= 1.2 if(!CHECK_MOBILITY(user, MOBILITY_STAND)) - damage *= 0.5 + damage *= 0.8 if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) - damage *= 0.25 + damage *= 0.8 //END OF CITADEL CHANGES var/obj/item/bodypart/affecting = target.get_bodypart(ran_zone(user.zone_selected)) var/miss_chance = 100//calculate the odds that a punch misses entirely. considers stamina and brute damage of the puncher. punches miss by default to prevent weird cases - if(user.dna.species.punchdamagelow) - if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance - miss_chance = 10 - if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage) - miss_chance = 0 - else - miss_chance = min(10 + ((puncherstam + puncherbrute)*0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob() + if(attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK) + miss_chance = 0 + else + if(user.dna.species.punchdamagelow) + if(atk_verb == ATTACK_EFFECT_KICK) //kicks never miss (provided your species deals more than 0 damage) + miss_chance = 0 + else if(HAS_TRAIT(user, TRAIT_PUGILIST)) //pugilists have a flat 10% miss chance + miss_chance = 10 + else + miss_chance = min(10 + max(puncherstam * 0.5, puncherbrute * 0.5), 100) //probability of miss has a base of 10, and modified based on half brute total. Capped at max 100 to prevent weirdness in prob() 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) @@ -1535,11 +1427,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) target.dismembering_strike(user, affecting.body_zone) if(atk_verb == ATTACK_EFFECT_KICK)//kicks deal 1.5x raw damage + 0.5x stamina damage - target.apply_damage(damage*1.5, BRUTE, affecting, armor_block) + target.apply_damage(damage*1.5, attack_type, affecting, armor_block) target.apply_damage(damage*0.5, STAMINA, affecting, armor_block) log_combat(user, target, "kicked") else//other attacks deal full raw damage + 2x in stamina damage - target.apply_damage(damage, BRUTE, affecting, armor_block) + target.apply_damage(damage, attack_type, affecting, armor_block) target.apply_damage(damage*2, STAMINA, affecting, armor_block) log_combat(user, target, "punched") @@ -1686,7 +1578,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) return -/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) +/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, attackchain_flags) if(!istype(M)) return CHECK_DNA_AND_SPECIES(M) @@ -1698,7 +1590,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) attacker_style = M.mind.martial_art if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas. attacker_style = null - switch(M.a_intent) + switch(act_intent) if("help") help(M, H, attacker_style) @@ -1706,7 +1598,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) grab(M, H, attacker_style) if("harm") - harm(M, H, attacker_style) + harm(M, H, attacker_style, attackchain_flags) if("disarm") disarm(M, H, attacker_style) @@ -1716,7 +1608,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // Allows you to put in item-specific reactions based on species if(user != H) var/list/block_return = list() - if(H.mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACKCHAIN_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone, block_return) & BLOCK_SUCCESS) + if(H.mob_run_block(I, totitemdamage, "the [I.name]", ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE) | 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()) @@ -1733,24 +1625,23 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/armor_block = H.run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened a hit to your [hit_area].",I.armour_penetration) armor_block = min(90,armor_block) //cap damage reduction at 90% var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords) + var/Iwound_bonus = I.wound_bonus + + // this way, you can't wound with a surgical tool on help intent if they have a surgery active and are laying down, so a misclick with a circular saw on the wrong limb doesn't bleed them dry (they still get hit tho) + if((I.item_flags & SURGICAL_TOOL) && user.a_intent == INTENT_HELP && (H.mobility_flags & ~MOBILITY_STAND) && (LAZYLEN(H.surgeries) > 0)) + Iwound_bonus = CANT_WOUND var/weakness = H.check_weakness(I, user) - apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage + apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) - H.send_item_attack_message(I, user, hit_area) + + H.send_item_attack_message(I, user, hit_area, affecting, totitemdamage) I.do_stagger_action(H, user, totitemdamage) if(!totitemdamage) return 0 //item force is zero - //dismemberment - var/probability = I.get_dismemberment_chance(affecting) - if(prob(probability) || (HAS_TRAIT(H, TRAIT_EASYDISMEMBER) && prob(probability))) //try twice - if(affecting.dismember(I.damtype)) - I.add_mob_blood(H) - playsound(get_turf(H), I.get_dismember_sound(), 80, 1) - var/bloody = 0 if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2)))) if(affecting.status == BODYPART_ORGANIC) @@ -1821,6 +1712,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) return TRUE CHECK_DNA_AND_SPECIES(M) CHECK_DNA_AND_SPECIES(H) + if(!M.CheckActionCooldown()) + return + M.DelayNextAction(CLICK_CD_MELEE) if(!istype(M)) //sanity check for drones. return TRUE @@ -1930,11 +1824,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) target.visible_message("[user.name] shoves [target.name]!", "[user.name] shoves you!", null, COMBAT_MESSAGE_RANGE, null, user, "You shove [target.name]!") + target.Stagger(SHOVE_STAGGER_DURATION) 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 - if(!target.has_movespeed_modifier(/datum/movespeed_modifier/shove)) - target.add_movespeed_modifier(/datum/movespeed_modifier/shove) + if(!target.has_status_effect(STATUS_EFFECT_OFF_BALANCE)) if(target_held_item) if(!HAS_TRAIT(target_held_item, TRAIT_NODROP)) target.visible_message("[target.name]'s grip on \the [target_held_item] loosens!", @@ -1942,43 +1836,43 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) append_message += ", loosening their grip on [target_held_item]" else append_message += ", but couldn't loose their grip on [target_held_item]" - addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH) else if(target_held_item) if(target.dropItemToGround(target_held_item)) target.visible_message("[target.name] drops \the [target_held_item]!!", "You drop \the [target_held_item]!!", null, COMBAT_MESSAGE_RANGE) append_message += ", causing them to drop [target_held_item]" + target.ShoveOffBalance(SHOVE_OFFBALANCE_DURATION) log_combat(user, target, "shoved", append_message) -/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE) - SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) +/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) + SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal var/hit_percent = (100-(blocked+armor))/100 hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 if(!forced && hit_percent <= 0) return 0 var/obj/item/bodypart/BP = null - if(isbodypart(def_zone)) - if(damagetype == STAMINA && istype(def_zone, /obj/item/bodypart/head)) - BP = H.get_bodypart(check_zone(BODY_ZONE_CHEST)) + if(!spread_damage) + if(isbodypart(def_zone)) + if(damagetype == STAMINA && istype(def_zone, /obj/item/bodypart/head)) + BP = H.get_bodypart(check_zone(BODY_ZONE_CHEST)) + else + BP = def_zone else - BP = def_zone - else - if(!def_zone) - def_zone = ran_zone(def_zone) - if(damagetype == STAMINA && def_zone == BODY_ZONE_HEAD) - def_zone = BODY_ZONE_CHEST - BP = H.get_bodypart(check_zone(def_zone)) - - if(!BP) - BP = H.bodyparts[1] + if(!def_zone) + def_zone = ran_zone(def_zone) + if(damagetype == STAMINA && def_zone == BODY_ZONE_HEAD) + def_zone = BODY_ZONE_CHEST + BP = H.get_bodypart(check_zone(def_zone)) + if(!BP) + BP = H.bodyparts[1] switch(damagetype) if(BRUTE) H.damageoverlaytemp = 20 var/damage_amount = forced ? damage : damage * hit_percent * brutemod * H.physiology.brute_mod if(BP) - if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0)) + if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness)) H.update_damage_overlays() if(HAS_TRAIT(H, TRAIT_MASO) && prob(damage_amount)) H.mob_climax(forced_climax=TRUE) @@ -1989,7 +1883,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) H.damageoverlaytemp = 20 var/damage_amount = forced ? damage : damage * hit_percent * burnmod * H.physiology.burn_mod if(BP) - if(damage > 0 ? BP.receive_damage(0, damage_amount) : BP.heal_damage(0, abs(damage_amount))) + if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness)) H.update_damage_overlays() else H.adjustFireLoss(damage_amount) @@ -2026,6 +1920,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // called before a projectile hit return +/** + * The human species version of [/mob/living/carbon/proc/get_biological_state]. Depends on the HAS_FLESH and HAS_BONE species traits, having bones lets you have bone wounds, having flesh lets you have burn, slash, and piercing wounds + */ +/datum/species/proc/get_biological_state(mob/living/carbon/human/H) + . = BIO_INORGANIC + if(HAS_FLESH in species_traits) + . |= BIO_JUST_FLESH + if(HAS_BONE in species_traits) + . |= BIO_JUST_BONE + ///////////// //BREATHING// ///////////// @@ -2034,7 +1938,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(HAS_TRAIT(H, TRAIT_NOBREATH)) return TRUE - /datum/species/proc/handle_environment(datum/gas_mixture/environment, mob/living/carbon/human/H) if(!environment) return @@ -2219,12 +2122,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) /datum/species/proc/ExtinguishMob(mob/living/carbon/human/H) return - //////////// //Stun// //////////// /datum/species/proc/spec_stun(mob/living/carbon/human/H,amount) + if(H) + stop_wagging_tail(H) . = stunmod * H.physiology.stun_mod * amount ////////////// @@ -2242,11 +2146,30 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) //////////////// /datum/species/proc/can_wag_tail(mob/living/carbon/human/H) - return FALSE + if(!tail_type || !wagging_type) + return FALSE + else + return mutant_bodyparts[tail_type] || mutant_bodyparts[wagging_type] /datum/species/proc/is_wagging_tail(mob/living/carbon/human/H) - return FALSE + return mutant_bodyparts[wagging_type] /datum/species/proc/start_wagging_tail(mob/living/carbon/human/H) + if(tail_type && wagging_type) + if(mutant_bodyparts[tail_type]) + mutant_bodyparts[wagging_type] = mutant_bodyparts[tail_type] + mutant_bodyparts -= tail_type + if(tail_type == "tail_lizard") //special lizard thing + mutant_bodyparts["waggingspines"] = mutant_bodyparts["spines"] + mutant_bodyparts -= "spines" + H.update_body() /datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H) + if(tail_type && wagging_type) + if(mutant_bodyparts[wagging_type]) + mutant_bodyparts[tail_type] = mutant_bodyparts[wagging_type] + mutant_bodyparts -= wagging_type + if(tail_type == "tail_lizard") //special lizard thing + mutant_bodyparts["spines"] = mutant_bodyparts["waggingspines"] + mutant_bodyparts -= "waggingspines" + H.update_body() diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index 0899038da4..38e10e8662 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -3,9 +3,10 @@ id = "abductor" say_mod = "gibbers" sexes = FALSE - species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL) + species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_CHUNKYFINGERS,TRAIT_NOHUNGER,TRAIT_NOBREATH) mutanttongue = /obj/item/organ/tongue/abductor + species_type = "alien" /datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() 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 5519545bd2..5d43d18429 100644 --- a/code/modules/mob/living/carbon/human/species_types/android.dm +++ b/code/modules/mob/living/carbon/human/species_types/android.dm @@ -11,3 +11,16 @@ mutanttongue = /obj/item/organ/tongue/robot species_language_holder = /datum/language_holder/synthetic limbs_id = "synth" + species_type = "robotic" + +/datum/species/android/on_species_gain(mob/living/carbon/C) + . = ..() + for(var/X in C.bodyparts) + var/obj/item/bodypart/O = X + O.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE) + +/datum/species/android/on_species_loss(mob/living/carbon/C) + . = ..() + for(var/X in C.bodyparts) + var/obj/item/bodypart/O = X + O.change_bodypart_status(BODYPART_ORGANIC,FALSE, TRUE) diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm index 1a92da3b0a..2cf054c7b9 100644 --- a/code/modules/mob/living/carbon/human/species_types/angel.dm +++ b/code/modules/mob/living/carbon/human/species_types/angel.dm @@ -2,13 +2,14 @@ name = "Angel" id = "angel" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel") use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM no_equip = list(SLOT_BACK) blacklisted = 1 limbs_id = "human" skinned_type = /obj/item/stack/sheet/animalhide/human + species_type = "human" //they're a kind of human var/datum/action/innate/flight/fly diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm index 595a83de9b..16b371c772 100644 --- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm @@ -3,9 +3,9 @@ id = "insect" say_mod = "chitters" default_color = "00FF00" - species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR) + species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG - mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", + mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None") attack_verb = "slash" attack_sound = 'sound/weapons/slash.ogg' @@ -13,35 +13,11 @@ meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect liked_food = MEAT | FRUIT disliked_food = TOXIC - icon_limbs = DEFAULT_BODYPART_ICON_CITADEL exotic_bloodtype = "BUG" + exotic_blood_color = BLOOD_COLOR_BUG -/datum/species/insect/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) + tail_type = "mam_tail" + wagging_type = "mam_waggingtail" + species_type = "insect" -/datum/species/insect/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - -/datum/species/insect/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"] - -/datum/species/insect/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_waggingtail"] - -/datum/species/insect/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_tail"]) - mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"] - mutant_bodyparts -= "mam_tail" - H.update_body() - -/datum/species/insect/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_waggingtail"]) - mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"] - mutant_bodyparts -= "mam_waggingtail" - H.update_body() - -/datum/species/insect/qualifies_for_rank(rank, list/features) - return TRUE + allowed_limb_ids = list("insect","apid","moth","moth_not_greyscale") diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm index e062e1cbf7..a2597ed286 100644 --- a/code/modules/mob/living/carbon/human/species_types/corporate.dm +++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm @@ -17,4 +17,5 @@ species_traits = list(NOBLOOD,EYECOLOR,NOGENITALS) inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER) sexes = 0 - gib_types = /obj/effect/gibspawner/robot \ No newline at end of file + gib_types = /obj/effect/gibspawner/robot + species_type = "robotic" \ No newline at end of file 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 1d19f28aa8..d8dfe63b35 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -2,7 +2,7 @@ name = "Dullahan" id = "dullahan" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None") use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM @@ -14,6 +14,7 @@ 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. + species_type = "undead" var/pumpkin = FALSE var/obj/item/dullahan_relay/myhead 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 bc5f198b4d..a465e7c3a9 100644 --- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm +++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm @@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // name = "Dwarf" id = "dwarf" //Also called Homo sapiens pumilionis default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB) limbs_id = "human" use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM @@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // 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 + species_type = "human" //a kind of human /mob/living/carbon/human/species/dwarf //species admin spawn path race = /datum/species/dwarf //and the race the path is set to. @@ -89,11 +90,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // //These count in on_life ticks which should be 2 seconds per every increment of 1 in a perfect world. var/dwarf_eth_ticker = 0 //Currently set =< 1, that means this will fire the proc around every 2 seconds var/last_alcohol_spam - -/obj/item/organ/dwarfgland/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent(/datum/reagent/consumable/ethanol, stored_alcohol/10) - return S + food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/ethanol = 10) /obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops.. . = ..() diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm new file mode 100644 index 0000000000..cd9b3b80c7 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm @@ -0,0 +1,182 @@ +#define ETHEREAL_COLORS list("#00ffff", "#ffc0cb", "#9400D3", "#4B0082", "#0000FF", "#00FF00", "#FFFF00", "#FF7F00", "#FF0000") + +/datum/species/ethereal + name = "Ethereal" + id = "ethereal" + attack_verb = "burn" + attack_sound = 'sound/weapons/etherealhit.ogg' + miss_sound = 'sound/weapons/etherealmiss.ogg' + meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ethereal + mutantstomach = /obj/item/organ/stomach/ethereal + mutanttongue = /obj/item/organ/tongue/ethereal + exotic_blood = /datum/reagent/consumable/liquidelectricity //Liquid Electricity. fuck you think of something better gamer + siemens_coeff = 0.5 //They thrive on energy + brutemod = 1.25 //They're weak to punches + attack_type = BURN //burn bish + damage_overlay_type = "" //We are too cool for regular damage overlays + species_traits = list(MUTCOLORS, HAIR, HAS_FLESH, HAS_BONE) // i mean i guess they have blood so they can have wounds too + species_language_holder = /datum/language_holder/ethereal + inherent_traits = list(TRAIT_NOHUNGER) + sexes = FALSE + toxic_food = NONE + /* + citadel doesn't have per-species temperatures, yet + // Body temperature for ethereals is much higher then humans as they like hotter environments + bodytemp_normal = (BODYTEMP_NORMAL + 50) + bodytemp_heat_damage_limit = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // about 150C + // Cold temperatures hurt faster as it is harder to move with out the heat energy + bodytemp_cold_damage_limit = (T20C - 10) // about 10c + */ + hair_color = "mutcolor" + hair_alpha = 140 + var/current_color + var/EMPeffect = FALSE + var/emageffect = FALSE + var/r1 + var/g1 + var/b1 + var/static/r2 = 237 + var/static/g2 = 164 + var/static/b2 = 149 + //this is shit but how do i fix it? no clue. + var/drain_time = 0 //used to keep ethereals from spam draining power sources + +/datum/species/ethereal/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) + .=..() + if(ishuman(C)) + var/mob/living/carbon/human/H = C + default_color = "#" + H.dna.features["mcolor"] + r1 = GETREDPART(default_color) + g1 = GETGREENPART(default_color) + b1 = GETBLUEPART(default_color) + spec_updatehealth(H) + RegisterSignal(C, COMSIG_ATOM_EMAG_ACT, .proc/on_emag_act) + RegisterSignal(C, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act) + +/datum/species/ethereal/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + .=..() + C.set_light(0) + UnregisterSignal(C, COMSIG_ATOM_EMAG_ACT) + UnregisterSignal(C, COMSIG_ATOM_EMP_ACT) + +/datum/species/ethereal/random_name(gender,unique,lastname) + if(unique) + return random_unique_ethereal_name() + + var/randname = ethereal_name() + + return randname + +/datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/H) + .=..() + if(H.stat != DEAD && !EMPeffect) + var/healthpercent = max(H.health, 0) / 100 + if(!emageffect) + current_color = rgb(r2 + ((r1-r2)*healthpercent), g2 + ((g1-g2)*healthpercent), b2 + ((b1-b2)*healthpercent)) + H.set_light(1 + (2 * healthpercent), 1 + (1 * healthpercent), current_color) + fixed_mut_color = copytext_char(current_color, 2) + else + H.set_light(0) + fixed_mut_color = rgb(128,128,128) + H.update_body() + +/datum/species/ethereal/proc/on_emp_act(mob/living/carbon/human/H, severity) + EMPeffect = TRUE + spec_updatehealth(H) + to_chat(H, "You feel the light of your body leave you.") + switch(severity) + if(EMP_LIGHT) + addtimer(CALLBACK(src, .proc/stop_emp, H), 10 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 10 seconds + if(EMP_HEAVY) + addtimer(CALLBACK(src, .proc/stop_emp, H), 20 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 20 seconds + +/datum/species/ethereal/proc/on_emag_act(mob/living/carbon/human/H, mob/user) + if(emageffect) + return + emageffect = TRUE + if(user) + to_chat(user, "You tap [H] on the back with your card.") + H.visible_message("[H] starts flickering in an array of colors!") + handle_emag(H) + addtimer(CALLBACK(src, .proc/stop_emag, H), 30 SECONDS) //Disco mode for 30 seconds! This doesn't affect the ethereal at all besides either annoying some players, or making someone look badass. + + +/datum/species/ethereal/spec_life(mob/living/carbon/human/H) + .=..() + handle_charge(H) + + +/datum/species/ethereal/proc/stop_emp(mob/living/carbon/human/H) + EMPeffect = FALSE + spec_updatehealth(H) + to_chat(H, "You feel more energized as your shine comes back.") + + +/datum/species/ethereal/proc/handle_emag(mob/living/carbon/human/H) + if(!emageffect) + return + current_color = pick(ETHEREAL_COLORS) + spec_updatehealth(H) + addtimer(CALLBACK(src, .proc/handle_emag, H), 5) //Call ourselves every 0.5 seconds to change color + +/datum/species/ethereal/proc/stop_emag(mob/living/carbon/human/H) + emageffect = FALSE + spec_updatehealth(H) + H.visible_message("[H] stops flickering and goes back to their normal state!") + +/datum/species/ethereal/proc/handle_charge(mob/living/carbon/human/H) + brutemod = 1.25 + switch(get_charge(H)) + if(ETHEREAL_CHARGE_NONE) + H.throw_alert("ethereal_charge", /obj/screen/alert/etherealcharge, 3) + if(ETHEREAL_CHARGE_NONE to ETHEREAL_CHARGE_LOWPOWER) + H.throw_alert("ethereal_charge", /obj/screen/alert/etherealcharge, 2) + if(H.health > 10.5) + apply_damage(0.65, TOX, null, null, H) + brutemod = 1.75 + if(ETHEREAL_CHARGE_LOWPOWER to ETHEREAL_CHARGE_NORMAL) + H.throw_alert("ethereal_charge", /obj/screen/alert/etherealcharge, 1) + brutemod = 1.5 + if(ETHEREAL_CHARGE_FULL to ETHEREAL_CHARGE_OVERLOAD) + H.throw_alert("ethereal_overcharge", /obj/screen/alert/ethereal_overcharge, 1) + apply_damage(0.2, TOX, null, null, H) + brutemod = 1.5 + if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS) + H.throw_alert("ethereal_overcharge", /obj/screen/alert/ethereal_overcharge, 2) + apply_damage(0.65, TOX, null, null, H) + brutemod = 1.75 + if(prob(10)) //10% each tick for ethereals to explosively release excess energy if it reaches dangerous levels + discharge_process(H) + else + H.clear_alert("ethereal_charge") + H.clear_alert("ethereal_overcharge") + +/datum/species/ethereal/proc/discharge_process(mob/living/carbon/human/H) + to_chat(H, "You begin to lose control over your charge!") + H.visible_message("[H] begins to spark violently!") + var/static/mutable_appearance/overcharge //shameless copycode from lightning spell + overcharge = overcharge || mutable_appearance('icons/effects/effects.dmi', "electricity", EFFECTS_LAYER) + H.add_overlay(overcharge) + if(do_mob(H, H, 50, 1)) + H.flash_lighting_fx(5, 7, current_color) + var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH) + playsound(H, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5) + H.cut_overlay(overcharge) + tesla_zap(H, 2, stomach.crystal_charge*50, ZAP_OBJ_DAMAGE | ZAP_ALLOW_DUPLICATES) + if(istype(stomach)) + stomach.adjust_charge(100 - stomach.crystal_charge) + to_chat(H, "You violently discharge energy!") + H.visible_message("[H] violently discharges energy!") + if(prob(10)) //chance of developing heart disease to dissuade overcharging oneself + var/datum/disease/D = new /datum/disease/heart_failure + H.ForceContractDisease(D) + to_chat(H, "You're pretty sure you just felt your heart stop for a second there..") + H.playsound_local(H, 'sound/effects/singlebeat.ogg', 100, 0) + H.Paralyze(100) + return + +/datum/species/ethereal/proc/get_charge(mob/living/carbon/H) //this feels like it should be somewhere else. Eh? + var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH) + if(istype(stomach)) + return stomach.crystal_charge + return ETHEREAL_CHARGE_NONE diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 2f0595e2c0..b760fd0aee 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -9,37 +9,9 @@ mutantears = /obj/item/organ/ears/cat mutanttail = /obj/item/organ/tail/cat -/datum/species/human/felinid/qualifies_for_rank(rank, list/features) - return TRUE - -//Curiosity killed the cat's wagging tail. -/datum/species/human/felinid/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) - -/datum/species/human/felinid/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - - -/datum/species/human/felinid/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"] - -/datum/species/human/felinid/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_waggingtail"] - -/datum/species/human/felinid/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_tail"]) - mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"] - mutant_bodyparts -= "mam_tail" - H.update_body() - -/datum/species/human/felinid/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_waggingtail"]) - mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"] - mutant_bodyparts -= "mam_waggingtail" - H.update_body() + tail_type = "mam_tail" + wagging_type = "mam_waggingtail" + species_type = "furry" /datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load) if(ishuman(C)) diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index ee4ef83a44..c56adaf1b0 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -2,7 +2,7 @@ name = "Anthromorphic Fly" id = "fly" say_mod = "buzzes" - species_traits = list(NOEYES) + species_traits = list(NOEYES,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG mutanttongue = /obj/item/organ/tongue/fly mutantliver = /obj/item/organ/liver/fly @@ -11,6 +11,8 @@ disliked_food = null liked_food = GROSS exotic_bloodtype = "BUG" + exotic_blood_color = BLOOD_COLOR_BUG + species_type = "insect" /datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H) if(istype(chem, /datum/reagent/toxin/pestkiller)) diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm index b6d56b8e5d..534536d6e7 100644 --- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm @@ -2,10 +2,9 @@ name = "Anthromorph" id = "mammal" default_color = "4B4B4B" - icon_limbs = DEFAULT_BODYPART_ICON_CITADEL - species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR) + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST - mutant_bodyparts = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None", + mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None", "mam_body_markings" = "Husky", "taur" = "None", "horns" = "None", "legs" = "Plantigrade", "meat_type" = "Mammalian") attack_verb = "claw" attack_sound = 'sound/weapons/slash.ogg' @@ -14,67 +13,8 @@ liked_food = MEAT | FRIED disliked_food = TOXIC -//Curiosity killed the cat's wagging tail. -/datum/species/mammal/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) + tail_type = "mam_tail" + wagging_type = "mam_waggingtail" + species_type = "furry" -/datum/species/mammal/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - -/datum/species/mammal/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"] - -/datum/species/mammal/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_waggingtail"] - -/datum/species/mammal/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_tail"]) - mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"] - mutant_bodyparts -= "mam_tail" - H.update_body() - -/datum/species/mammal/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_waggingtail"]) - mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"] - mutant_bodyparts -= "mam_waggingtail" - H.update_body() - - -/datum/species/mammal/qualifies_for_rank(rank, list/features) - return TRUE - - -//Alien// -/datum/species/xeno - // A cloning mistake, crossing human and xenomorph DNA - name = "Xenomorph Hybrid" - id = "xeno" - say_mod = "hisses" - default_color = "00FF00" - icon_limbs = DEFAULT_BODYPART_ICON_CITADEL - species_traits = list(MUTCOLORS,EYECOLOR,LIPS) - mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade") - attack_verb = "slash" - attack_sound = 'sound/weapons/slash.ogg' - miss_sound = 'sound/weapons/slashmiss.ogg' - meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno - gib_types = list(/obj/effect/gibspawner/xeno/xenoperson, /obj/effect/gibspawner/xeno/xenoperson/bodypartless) - skinned_type = /obj/item/stack/sheet/animalhide/xeno - exotic_bloodtype = "X*" - damage_overlay_type = "xeno" - liked_food = MEAT - -//Praise the Omnissiah, A challange worthy of my skills - HS - -//EXOTIC// -//These races will likely include lots of downsides and upsides. Keep them relatively balanced.// - -//misc -/mob/living/carbon/human/dummy - vore_flags = NO_VORE - -/mob/living/carbon/human/vore - vore_flags = DEVOURABLE | DIGESTABLE | FEEDING + allowed_limb_ids = list("mammal","aquatic","avian") \ No newline at end of file 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 958e58a8ad..438eaf1eea 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -32,6 +32,8 @@ var/special_name_chance = 5 var/owner //dobby is a free golem + species_type = "golem" + /datum/species/golem/random_name(gender,unique,lastname) var/golem_surname = pick(GLOB.golem_names) // 3% chance that our golem has a human surname, because @@ -422,9 +424,9 @@ else reactive_teleport(H) -/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) +/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags) ..() - if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP) + if(world.time > last_teleport + teleport_cooldown && M != H && act_intent != INTENT_HELP) reactive_teleport(H) /datum/species/golem/bluespace/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) @@ -519,9 +521,9 @@ var/golem_name = "[uppertext(clown_name)]" return golem_name -/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) +/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags) ..() - if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP) + if(world.time > last_banana + banana_cooldown && M != H && act_intent != INTENT_HELP) new/obj/item/grown/bananapeel/specialpeel(get_turf(H)) last_banana = world.time @@ -830,9 +832,9 @@ if(world.time > last_gong_time + gong_cooldown) gong(H) -/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) +/datum/species/golem/bronze/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style, act_intent, unarmed_attack_flags) ..() - if(world.time > last_gong_time + gong_cooldown && M.a_intent != INTENT_HELP) + if(world.time > last_gong_time + gong_cooldown && act_intent != INTENT_HELP) gong(H) /datum/species/golem/bronze/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 606b7a8bfd..f175ddb921 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -3,15 +3,16 @@ id = "human" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR) - mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None") + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,HAS_FLESH,HAS_BONE) + mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None") use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM skinned_type = /obj/item/stack/sheet/animalhide/human disliked_food = GROSS | RAW liked_food = JUNKFOOD | FRIED -/datum/species/human/qualifies_for_rank(rank, list/features) - return TRUE //Pure humans are always allowed in all roles. + tail_type = "tail_human" + wagging_type = "waggingtail_human" + species_type = "human" /datum/species/human/spec_death(gibbed, mob/living/carbon/human/H) if(H) @@ -21,21 +22,3 @@ if(H) stop_wagging_tail(H) . = ..() - -/datum/species/human/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["tail_human"] || mutant_bodyparts["waggingtail_human"] - -/datum/species/human/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["waggingtail_human"] - -/datum/species/human/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["tail_human"]) - mutant_bodyparts["waggingtail_human"] = mutant_bodyparts["tail_human"] - mutant_bodyparts -= "tail_human" - H.update_body() - -/datum/species/human/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["waggingtail_human"]) - mutant_bodyparts["tail_human"] = mutant_bodyparts["waggingtail_human"] - mutant_bodyparts -= "waggingtail_human" - H.update_body() diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index e520bcec1f..a5ca87327e 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -3,11 +3,11 @@ id = "ipc" say_mod = "beeps" default_color = "00FF00" - icon_limbs = DEFAULT_BODYPART_ICON_CITADEL blacklisted = 0 sexes = 0 - species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,ROBOTIC_LIMBS) + species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD) + inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless) @@ -26,6 +26,8 @@ mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord) exotic_bloodtype = "HF" + exotic_blood_color = BLOOD_COLOR_OIL + species_type = "robotic" var/datum/action/innate/monitor_change/screen 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 b780af6b8a..49c55f70b3 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -4,15 +4,16 @@ id = "jelly" default_color = "00FF90" say_mod = "chirps" - species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR) + species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR,HAS_FLESH) mutantlungs = /obj/item/organ/lungs/slime mutant_heart = /obj/item/organ/heart/slime - mutant_bodyparts = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None") + mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None") inherent_traits = list(TRAIT_TOXINLOVER) meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime gib_types = list(/obj/effect/gibspawner/slime, /obj/effect/gibspawner/slime/bodypartless) exotic_blood = /datum/reagent/blood/jellyblood exotic_bloodtype = "GEL" + exotic_blood_color = "BLOOD_COLOR_SLIME" damage_overlay_type = "" var/datum/action/innate/regenerate_limbs/regenerate_limbs var/datum/action/innate/slime_change/slime_change //CIT CHANGE @@ -22,6 +23,17 @@ heatmod = 0.5 // = 1/4x heat damage burnmod = 0.5 // = 1/2x generic burn damage species_language_holder = /datum/language_holder/jelly + mutant_brain = /obj/item/organ/brain/jelly + + tail_type = "mam_tail" + wagging_type = "mam_waggingtail" + species_type = "jelly" + +/obj/item/organ/brain/jelly + name = "slime nucleus" + desc = "A slimey membranous mass from a slime person" + icon_state = "brain-slime" + /datum/species/jelly/on_species_loss(mob/living/carbon/C) if(regenerate_limbs) @@ -41,6 +53,11 @@ slime_change.Grant(C) //CIT CHANGE C.faction |= "slime" +/datum/species/jelly/handle_body(mob/living/carbon/human/H) + . = ..() + //update blood color to body color + exotic_blood_color = "#" + H.dna.features["mcolor"] + /datum/species/jelly/spec_life(mob/living/carbon/human/H) if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for blooduskers return @@ -115,33 +132,6 @@ return to_chat(H, "...but there is not enough of you to go around! You must attain more mass to heal!") -/datum/species/jelly/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) - -/datum/species/jelly/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - -/datum/species/jelly/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"] - -/datum/species/jelly/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_waggingtail"] - -/datum/species/jelly/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_tail"]) - mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"] - mutant_bodyparts -= "mam_tail" - H.update_body() - -/datum/species/jelly/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_waggingtail"]) - mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"] - mutant_bodyparts -= "mam_waggingtail" - H.update_body() - ////////////////////////////////////////////////////////SLIMEPEOPLE/////////////////////////////////////////////////////////////////// @@ -239,7 +229,7 @@ "You focus intently on moving your body while \ standing perfectly still...") - H.notransform = TRUE + H.mob_transforming = TRUE if(do_after(owner, delay=60, needhand=FALSE, target=owner, progress=TRUE)) if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT) @@ -249,7 +239,7 @@ else to_chat(H, "...but fail to stand perfectly still!") - H.notransform = FALSE + H.mob_transforming = FALSE /datum/action/innate/split_body/proc/make_dupe() var/mob/living/carbon/human/H = owner @@ -267,7 +257,7 @@ spare.Move(get_step(H.loc, pick(NORTH,SOUTH,EAST,WEST))) H.blood_volume *= 0.45 - H.notransform = 0 + H.mob_transforming = 0 var/datum/species/jelly/slime/origin_datum = H.dna.species origin_datum.bodies |= spare @@ -297,11 +287,16 @@ else ui_interact(owner) -/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state) +/datum/action/innate/swap_body/ui_host(mob/user) + return owner - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/action/innate/swap_body/ui_state(mob/user) + return GLOB.not_incapacitated_state + +/datum/action/innate/swap_body/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "slime_swap_body", name, 400, 400, master_ui, state) + ui = new(user, src, "SlimeBodySwapper", name) ui.open() /datum/action/innate/swap_body/ui_data(mob/user) @@ -371,7 +366,8 @@ return switch(action) if("swap") - var/mob/living/carbon/human/selected = locate(params["ref"]) + var/datum/species/jelly/slime/SS = H.dna.species + var/mob/living/carbon/human/selected = locate(params["ref"]) in SS.bodies if(!can_swap(selected)) return SStgui.close_uis(src) @@ -430,7 +426,7 @@ default_color = "00FFFF" species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR) inherent_traits = list(TRAIT_TOXINLOVER) - mutant_bodyparts = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None") + mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None") say_mod = "says" hair_color = "mutcolor" hair_alpha = 160 //a notch brighter so it blends better. @@ -466,8 +462,9 @@ if(new_color) var/temp_hsv = RGBtoHSV(new_color) if(ReadHSV(temp_hsv)[3] >= ReadHSV("#7F7F7F")[3]) // mutantcolors must be bright - H.dna.features["mcolor"] = sanitize_hexcolor(new_color) + H.dna.features["mcolor"] = sanitize_hexcolor(new_color, 6) H.update_body() + H.update_hair() else to_chat(H, "Invalid color. Your color is not bright enough.") else if(select_alteration == "Hair Style") @@ -507,7 +504,7 @@ else if (select_alteration == "Ears") var/list/snowflake_ears_list = list("Normal" = null) for(var/path in GLOB.mam_ears_list) - var/datum/sprite_accessory/mam_ears/instance = GLOB.mam_ears_list[path] + var/datum/sprite_accessory/ears/mam_ears/instance = GLOB.mam_ears_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey))) @@ -521,7 +518,7 @@ else if (select_alteration == "Snout") var/list/snowflake_snouts_list = list("Normal" = null) for(var/path in GLOB.mam_snouts_list) - var/datum/sprite_accessory/mam_snouts/instance = GLOB.mam_snouts_list[path] + var/datum/sprite_accessory/snouts/mam_snouts/instance = GLOB.mam_snouts_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey))) @@ -533,7 +530,7 @@ H.update_body() else if (select_alteration == "Markings") - var/list/snowflake_markings_list = list() + var/list/snowflake_markings_list = list("None") for(var/path in GLOB.mam_body_markings_list) var/datum/sprite_accessory/mam_body_markings/instance = GLOB.mam_body_markings_list[path] if(istype(instance, /datum/sprite_accessory)) @@ -544,8 +541,6 @@ new_mam_body_markings = input(H, "Choose your character's body markings:", "Marking Alteration") as null|anything in snowflake_markings_list if(new_mam_body_markings) H.dna.features["mam_body_markings"] = new_mam_body_markings - if(new_mam_body_markings == "None") - H.dna.features["mam_body_markings"] = "Plain" for(var/X in H.bodyparts) //propagates the markings changes var/obj/item/bodypart/BP = X BP.update_limb(FALSE, H) @@ -554,7 +549,7 @@ else if (select_alteration == "Tail") var/list/snowflake_tails_list = list("Normal" = null) for(var/path in GLOB.mam_tails_list) - var/datum/sprite_accessory/mam_tails/instance = GLOB.mam_tails_list[path] + var/datum/sprite_accessory/tails/mam_tails/instance = GLOB.mam_tails_list[path] if(istype(instance, /datum/sprite_accessory)) var/datum/sprite_accessory/S = instance if((!S.ckeys_allowed) || (S.ckeys_allowed.Find(H.client.ckey))) 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 196073773b..a8e3f89957 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -4,14 +4,13 @@ id = "lizard" say_mod = "hisses" default_color = "00FF00" - species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR) - mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings") + species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE mutanttongue = /obj/item/organ/tongue/lizard mutanttail = /obj/item/organ/tail/lizard coldmod = 1.5 heatmod = 0.67 - mutant_bodyparts = list("mcolor" = "0F0", "mcolor2" = "0F0", "mcolor3" = "0F0", "tail_lizard" = "Smooth", "snout" = "Round", + mutant_bodyparts = list("mcolor" = "0F0", "mcolor2" = "0F0", "mcolor3" = "0F0", "tail_lizard" = "Smooth", "mam_snouts" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "legs" = "Digitigrade", "taur" = "None", "deco_wings" = "None") attack_verb = "slash" @@ -21,11 +20,16 @@ gib_types = list(/obj/effect/gibspawner/lizard, /obj/effect/gibspawner/lizard/bodypartless) skinned_type = /obj/item/stack/sheet/animalhide/lizard exotic_bloodtype = "L" + exotic_blood_color = BLOOD_COLOR_LIZARD disliked_food = GRAIN | DAIRY liked_food = GROSS | MEAT inert_mutation = FIREBREATH species_language_holder = /datum/language_holder/lizard + tail_type = "tail_lizard" + wagging_type = "waggingtail_lizard" + species_type = "lizard" + /datum/species/lizard/random_name(gender,unique,lastname) if(unique) return random_unique_lizard_name(gender) @@ -37,41 +41,6 @@ return randname -/datum/species/lizard/qualifies_for_rank(rank, list/features) - return TRUE - -//I wag in death -/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) - -/datum/species/lizard/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - -/datum/species/lizard/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["tail_lizard"] || mutant_bodyparts["waggingtail_lizard"] - -/datum/species/lizard/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["waggingtail_lizard"] - -/datum/species/lizard/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["tail_lizard"]) - mutant_bodyparts["waggingtail_lizard"] = mutant_bodyparts["tail_lizard"] - mutant_bodyparts["waggingspines"] = mutant_bodyparts["spines"] - mutant_bodyparts -= "tail_lizard" - mutant_bodyparts -= "spines" - H.update_body() - -/datum/species/lizard/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["waggingtail_lizard"]) - mutant_bodyparts["tail_lizard"] = mutant_bodyparts["waggingtail_lizard"] - mutant_bodyparts["spines"] = mutant_bodyparts["waggingspines"] - mutant_bodyparts -= "waggingtail_lizard" - mutant_bodyparts -= "waggingspines" - H.update_body() - /* Lizard subspecies: ASHWALKERS */ @@ -82,6 +51,7 @@ species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE) inherent_traits = list(TRAIT_CHUNKYFINGERS) mutantlungs = /obj/item/organ/lungs/ashwalker + mutanteyes = /obj/item/organ/eyes/night_vision burnmod = 0.9 brutemod = 0.9 species_language_holder = /datum/language_holder/lizard/ash 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 dcb6d868fc..f91c3518a3 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -8,7 +8,7 @@ nojumpsuit = TRUE say_mod = "poofs" //what does a mushroom sound like - species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL) + species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOBREATH) speedmod = 1.5 //faster than golems but not by much @@ -21,6 +21,8 @@ burnmod = 1.25 heatmod = 1.5 + species_type = "plant" + mutanteyes = /obj/item/organ/eyes/night_vision/mushroom var/datum/martial_art/mushpunch/mush species_language_holder = /datum/language_holder/mushroom diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 0383a19764..8c30adb8f9 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -4,7 +4,7 @@ say_mod = "rattles" sexes = 0 meat = /obj/item/stack/sheet/mineral/plasma - species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS) + species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS,HAS_BONE) inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER,TRAIT_CALCIUM_HEALER) inherent_biotypes = MOB_HUMANOID|MOB_MINERAL mutantlungs = /obj/item/organ/lungs/plasmaman @@ -22,6 +22,8 @@ liked_food = VEGETABLES outfit_important_for_life = /datum/outfit/plasmaman + species_type = "skeleton" + /datum/species/plasmaman/spec_life(mob/living/carbon/human/H) var/datum/gas_mixture/environment = H.loc.return_air() var/atmos_sealed = FALSE @@ -33,7 +35,7 @@ if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed) if(environment) if(environment.total_moles()) - if(environment.gases[/datum/gas/oxygen] && (environment.gases[/datum/gas/oxygen]) >= 1) //Same threshhold that extinguishes fire + if(environment.get_moles(/datum/gas/oxygen) >= 1) //Same threshhold that extinguishes fire H.adjust_fire_stacks(0.5) if(!H.on_fire && H.fire_stacks > 0) H.visible_message("[H]'s body reacts with the atmosphere and bursts into flames!","Your body reacts with the atmosphere and bursts into flame!") @@ -55,89 +57,10 @@ ..() /datum/species/plasmaman/before_equip_job(datum/job/J, mob/living/carbon/human/H, visualsOnly = FALSE) - var/current_job = J?.title var/datum/outfit/plasmaman/O = new /datum/outfit/plasmaman - switch(current_job) - if("Chaplain") - O = new /datum/outfit/plasmaman/chaplain - - if("Curator") - O = new /datum/outfit/plasmaman/curator - - if("Janitor") - O = new /datum/outfit/plasmaman/janitor - - if("Botanist") - O = new /datum/outfit/plasmaman/botany - - if("Bartender", "Lawyer") - O = new /datum/outfit/plasmaman/bar - - if("Cook") - O = new /datum/outfit/plasmaman/chef - - if("Security Officer") - O = new /datum/outfit/plasmaman/security - - if("Detective") - O = new /datum/outfit/plasmaman/detective - - if("Warden") - O = new /datum/outfit/plasmaman/warden - - if("Cargo Technician", "Quartermaster") - O = new /datum/outfit/plasmaman/cargo - - if("Shaft Miner") - O = new /datum/outfit/plasmaman/mining - - if("Medical Doctor") - O = new /datum/outfit/plasmaman/medical - - if("Chemist") - O = new /datum/outfit/plasmaman/chemist - - if("Geneticist") - O = new /datum/outfit/plasmaman/genetics - - if("Roboticist") - O = new /datum/outfit/plasmaman/robotics - - if("Virologist") - O = new /datum/outfit/plasmaman/viro - - if("Scientist") - O = new /datum/outfit/plasmaman/science - - if("Station Engineer") - O = new /datum/outfit/plasmaman/engineering - - if("Atmospheric Technician") - O = new /datum/outfit/plasmaman/atmospherics - - if("Captain") - O = new /datum/outfit/plasmaman/captain - - if("Head of Personnel") - O = new /datum/outfit/plasmaman/hop - - if("Head of Security") - O = new /datum/outfit/plasmaman/hos - - if("Chief Engineer") - O = new /datum/outfit/plasmaman/ce - - if("Chief Medical Officer") - O = new /datum/outfit/plasmaman/cmo - - if("Research Director") - O = new /datum/outfit/plasmaman/rd - - if("Mime") - O = new /datum/outfit/plasmaman/mime - - if("Clown") - O = new /datum/outfit/plasmaman/clown + if(J) + if(J.plasma_outfit) + O = new J.plasma_outfit H.equipOutfit(O, visualsOnly) H.internal = H.get_item_for_held_index(2) 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 e79160da06..0f62953e6c 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -3,7 +3,7 @@ name = "Anthromorphic Plant" id = "pod" default_color = "59CE00" - species_traits = list(MUTCOLORS,EYECOLOR) + species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE) attack_verb = "slash" attack_sound = 'sound/weapons/slice.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' @@ -19,6 +19,10 @@ var/light_burnheal = -1 var/light_bruteheal = -1 + species_type = "plant" + + allowed_limb_ids = list("pod","mush") + /datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() C.faction |= "plants" @@ -64,36 +68,12 @@ name = "Anthromorphic Plant" id = "podweak" 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") + mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "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 = 3 light_bruteheal = -0.2 light_burnheal = -0.2 light_toxheal = -0.7 -/datum/species/pod/pseudo_weak/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) - -/datum/species/pod/pseudo_weak/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - -/datum/species/pod/pseudo_weak/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"] - -/datum/species/pod/pseudo_weak/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_waggingtail"] - -/datum/species/pod/pseudo_weak/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_tail"]) - mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"] - mutant_bodyparts -= "mam_tail" - H.update_body() - -/datum/species/pod/pseudo_weak/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_waggingtail"]) - mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"] - mutant_bodyparts -= "mam_waggingtail" - H.update_body() + tail_type = "mam_tail" + wagging_type = "mam_waggingtail" diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index fede67b47a..228a69c30f 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -9,12 +9,14 @@ blacklisted = 1 ignored_by = list(/mob/living/simple_animal/hostile/faithless) meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow - species_traits = list(NOBLOOD,NOEYES) + species_traits = list(NOBLOOD,NOEYES,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH) dangerous_existence = 1 mutanteyes = /obj/item/organ/eyes/night_vision + species_type = "shadow" + /datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() C.AddElement(/datum/element/photosynthesis, 1, 1, 0, 0, 0, 0, SHADOW_SPECIES_LIGHT_THRESHOLD, SHADOW_SPECIES_LIGHT_THRESHOLD) @@ -80,13 +82,11 @@ M.AddSpell(SW) shadowwalk = SW - /obj/item/organ/brain/nightmare/Remove(special = FALSE) if(shadowwalk && owner) owner.RemoveSpell(shadowwalk) return ..() - /obj/item/organ/heart/nightmare name = "heart of darkness" desc = "An alien organ that twists and writhes when exposed to light." @@ -164,7 +164,7 @@ righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' item_flags = ABSTRACT | DROPDEL w_class = WEIGHT_CLASS_HUGE - sharpness = IS_SHARP + sharpness = SHARP_EDGED total_mass = TOTAL_MASS_HAND_REPLACEMENT /obj/item/light_eater/Initialize() @@ -183,6 +183,8 @@ T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR) else if(isliving(AM)) var/mob/living/L = AM + if(isethereal(AM)) + AM.emp_act(EMP_LIGHT) if(iscyborg(AM)) var/mob/living/silicon/robot/borg = AM if(borg.lamp_intensity) diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index 8257238e9c..1b6bef9dc6 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -1,18 +1,28 @@ /datum/species/skeleton - // 2spooky - name = "Spooky Scary Skeleton" + name = "Skeleton" id = "skeleton" say_mod = "rattles" blacklisted = 0 sexes = 0 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton - species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL) - inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER) + species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,HAS_BONE,NOTRANSSTING) + inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_CALCIUM_HEALER) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/tongue/bone damage_overlay_type = ""//let's not show bloody wounds or burns over bones. disliked_food = NONE liked_food = GROSS | MEAT | RAW | DAIRY + brutemod = 1.25 + burnmod = 1.25 + + species_type = "skeleton" //they have their own category that's disassociated from undead, paired with plasmapeople + +/datum/species/skeleton/New() + if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season! + inherent_traits |= list(TRAIT_RESISTHEAT, TRAIT_NOBREATH, TRAIT_PIERCEIMMUNE, TRAIT_FAKEDEATH, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE) + brutemod = 1 + burnmod = 1 + ..() /datum/species/skeleton/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) @@ -27,4 +37,4 @@ inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT, TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER) /datum/species/skeleton/space/check_roundstart_eligible() - return FALSE \ No newline at end of file + return FALSE diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm index 6aaa9b98b1..b446e3796e 100644 --- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm +++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm @@ -1,11 +1,11 @@ /datum/species/synthliz name = "Synthetic Lizardperson" id = "synthliz" - icon_limbs = DEFAULT_BODYPART_ICON_CITADEL say_mod = "beeps" default_color = "00FF00" - species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS) + species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD) + inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless) @@ -23,35 +23,8 @@ mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord) exotic_bloodtype = "S" + exotic_blood_color = BLOOD_COLOR_OIL - -/datum/species/synthliz/qualifies_for_rank(rank, list/features) - return TRUE - -//I wag in death -/datum/species/synthliz/spec_death(gibbed, mob/living/carbon/human/H) - if(H) - stop_wagging_tail(H) - -/datum/species/synthliz/spec_stun(mob/living/carbon/human/H,amount) - if(H) - stop_wagging_tail(H) - . = ..() - -/datum/species/synthliz/can_wag_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_tail"] || mutant_bodyparts["mam_waggingtail"] - -/datum/species/synthliz/is_wagging_tail(mob/living/carbon/human/H) - return mutant_bodyparts["mam_waggingtail"] - -/datum/species/synthliz/start_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_tail"]) - mutant_bodyparts["mam_waggingtail"] = mutant_bodyparts["mam_tail"] - mutant_bodyparts -= "mam_tail" - H.update_body() - -/datum/species/synthliz/stop_wagging_tail(mob/living/carbon/human/H) - if(mutant_bodyparts["mam_waggingtail"]) - mutant_bodyparts["mam_tail"] = mutant_bodyparts["mam_waggingtail"] - mutant_bodyparts -= "mam_waggingtail" - H.update_body() + tail_type = "mam_tail" + wagging_type = "mam_waggingtail" + species_type = "robotic" 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 85f1fbf386..3d55ce1027 100644 --- a/code/modules/mob/living/carbon/human/species_types/synths.dm +++ b/code/modules/mob/living/carbon/human/species_types/synths.dm @@ -17,6 +17,7 @@ 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 + species_type = "robotic" /datum/species/synth/military name = "Military Synth" @@ -43,7 +44,6 @@ return TRUE return ..() - /datum/species/synth/proc/assume_disguise(datum/species/S, mob/living/carbon/human/H) if(S && !istype(S, type)) name = S.name @@ -61,7 +61,7 @@ mutant_organs = S.mutant_organs.Copy() nojumpsuit = S.nojumpsuit no_equip = S.no_equip.Copy() - limbs_id = S.limbs_id + limbs_id = S.mutant_bodyparts["limbs_id"] use_skintones = S.use_skintones fixed_mut_color = S.fixed_mut_color hair_color = S.hair_color @@ -100,14 +100,12 @@ else return ..() - /datum/species/synth/handle_body(mob/living/carbon/human/H) if(fake_species) fake_species.handle_body(H) else return ..() - /datum/species/synth/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour) if(fake_species) fake_species.handle_body(H,forced_colour) diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index f720aa7f8a..723c4848fe 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -2,10 +2,10 @@ name = "Vampire" id = "vampire" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID - mutant_bodyparts = list("mcolor" = "FFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None") + mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None") exotic_bloodtype = "U" use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM mutant_heart = /obj/item/organ/heart/vampire @@ -14,6 +14,7 @@ limbs_id = "human" skinned_type = /obj/item/stack/sheet/animalhide/human var/info_text = "You are a Vampire. You will slowly but constantly lose blood if outside of a coffin. If inside a coffin, you will slowly heal. You may gain more blood by grabbing a live victim and using your drain ability." + species_type = "undead" /datum/species/vampire/check_roundstart_eligible() if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) diff --git a/code/modules/mob/living/carbon/human/species_types/xeno.dm b/code/modules/mob/living/carbon/human/species_types/xeno.dm new file mode 100644 index 0000000000..ddd1c86f0a --- /dev/null +++ b/code/modules/mob/living/carbon/human/species_types/xeno.dm @@ -0,0 +1,18 @@ +/datum/species/xeno + // A cloning mistake, crossing human and xenomorph DNA + name = "Xenomorph Hybrid" + id = "xeno" + say_mod = "hisses" + default_color = "00FF00" + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR) + mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade") + attack_verb = "slash" + attack_sound = 'sound/weapons/slash.ogg' + miss_sound = 'sound/weapons/slashmiss.ogg' + meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno + gib_types = list(/obj/effect/gibspawner/xeno/xenoperson, /obj/effect/gibspawner/xeno/xenoperson/bodypartless) + skinned_type = /obj/item/stack/sheet/animalhide/xeno + exotic_bloodtype = "X*" + damage_overlay_type = "xeno" + liked_food = MEAT + species_type = "alien" diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 26a99dbc2b..8d86ad2fa9 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -8,13 +8,14 @@ sexes = 0 blacklisted = 1 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie - species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING) + species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/tongue/zombie var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg') disliked_food = NONE liked_food = GROSS | MEAT | RAW + species_type = "undead" /datum/species/zombie/notspaceproof id = "notspaceproofzombie" @@ -31,9 +32,10 @@ name = "Infectious Zombie" id = "memezombies" limbs_id = "zombie" + inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_NOSOFTCRIT, TRAIT_FAKEDEATH) mutanthands = /obj/item/zombie_hand armor = 20 // 120 damage to KO a zombie, which kills it - speedmod = 1.6 + speedmod = 1.6 // they're very slow mutanteyes = /obj/item/organ/eyes/night_vision/zombie var/heal_rate = 1 var/regen_cooldown = 0 @@ -41,11 +43,10 @@ /datum/species/zombie/infectious/check_roundstart_eligible() return FALSE - /datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount) . = min(20, amount) -/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE) +/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) . = ..() if(.) regen_cooldown = world.time + REGENERATION_DELAY @@ -62,6 +63,10 @@ heal_amt *= 2 C.heal_overall_damage(heal_amt,heal_amt) C.adjustToxLoss(-heal_amt) + for(var/i in C.all_wounds) + var/datum/wound/iter_wound = i + if(prob(4-iter_wound.severity)) + iter_wound.remove_wound() if(!C.InCritical() && prob(4)) playsound(C, pick(spooks), 50, TRUE, 10) @@ -85,6 +90,11 @@ infection = new() infection.Insert(C) + //make their bodyparts stamina-immune, its a corpse. + var/incoming_stam_mult = 0 + for(var/obj/item/bodypart/part in C.bodyparts) + part.incoming_stam_mult = incoming_stam_mult + //todo: add negative wound resistance to all parts when wounds is merged (zombies are physically weak in terms of limbs) // Your skin falls off /datum/species/krokodil_addict diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index e399ddf872..9b39438563 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -660,7 +660,7 @@ use_mob_overlay_icon: if FALSE, it will always use the default_icon_file even if //produces a key based on the human's limbs /mob/living/carbon/human/generate_icon_render_key() - . = "[dna.species.limbs_id]" + . = "[dna.species.mutant_bodyparts["limbs_id"]]" if(dna.check_mutation(HULK)) . += "-coloured-hulk" diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 4e5b033688..e29c6b9ffe 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -1,29 +1,27 @@ -/mob/living/carbon/Life() - set invisibility = 0 - - if(notransform) - return - - if(damageoverlaytemp) - damageoverlaytemp = 0 - update_damage_hud() - +/mob/living/carbon/BiologicalLife(seconds, times_fired) + //Updates the number of stored chemicals for powers + handle_changeling() + //Handles the unique mentabolism of bloodsuckers, look at /datum/antagonist/bloodsucker/proc/LifeTick() + handle_bloodsucker() //Reagent processing needs to come before breathing, to prevent edge cases. handle_organs() - - . = ..() - - if (QDELETED(src)) + . = ..() // if . is false, we are dead. + if(stat == DEAD) + stop_sound_channel(CHANNEL_HEARTBEAT) + handle_death() + rot() + . = FALSE + if(!.) return - - if(.) //not dead - handle_blood() - + handle_blood() + // handle_blood *could* kill us. + // we should probably have a better system for if we need to check for death or something in the future hmw if(stat != DEAD) var/bprv = handle_bodyparts() if(bprv & BODYPART_LIFE_UPDATE_HEALTH) updatehealth() update_stamina() + doSprintBufferRegen() if(stat != DEAD) handle_brain_damage() @@ -31,16 +29,13 @@ if(stat != DEAD) handle_liver() - if(stat == DEAD) - stop_sound_channel(CHANNEL_HEARTBEAT) - handle_death() - rot() - //Updates the number of stored chemicals for powers - handle_changeling() - - if(stat != DEAD) - return 1 +/mob/living/carbon/PhysicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(damageoverlaytemp) + damageoverlaytemp = 0 + update_damage_hud() //Procs called while dead /mob/living/carbon/proc/handle_death() @@ -169,12 +164,11 @@ var/SA_para_min = 1 var/SA_sleep_min = 5 var/oxygen_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.return_temperature())/BREATH_VOLUME - var/list/breath_gases = breath.gases - var/O2_partialpressure = (breath_gases[/datum/gas/oxygen]/breath.total_moles())*breath_pressure - var/Toxins_partialpressure = (breath_gases[/datum/gas/plasma]/breath.total_moles())*breath_pressure - var/CO2_partialpressure = (breath_gases[/datum/gas/carbon_dioxide]/breath.total_moles())*breath_pressure + var/O2_partialpressure = (breath.get_moles(/datum/gas/oxygen)/breath.total_moles())*breath_pressure + var/Toxins_partialpressure = (breath.get_moles(/datum/gas/plasma)/breath.total_moles())*breath_pressure + var/CO2_partialpressure = (breath.get_moles(/datum/gas/carbon_dioxide)/breath.total_moles())*breath_pressure //OXYGEN @@ -198,7 +192,7 @@ var/ratio = 1 - O2_partialpressure/safe_oxy_min adjustOxyLoss(min(5*ratio, 3)) failed_last_breath = 1 - oxygen_used = breath_gases[/datum/gas/oxygen]*ratio + oxygen_used = breath.get_moles(/datum/gas/oxygen)*ratio else adjustOxyLoss(3) failed_last_breath = 1 @@ -210,12 +204,12 @@ o2overloadtime = 0 //reset our counter for this too if(health >= crit_threshold) adjustOxyLoss(-5) - oxygen_used = breath_gases[/datum/gas/oxygen] + oxygen_used = breath.get_moles(/datum/gas/oxygen) clear_alert("not_enough_oxy") SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "suffocation") - breath_gases[/datum/gas/oxygen] -= oxygen_used - breath_gases[/datum/gas/carbon_dioxide] += oxygen_used + breath.adjust_moles(/datum/gas/oxygen, -oxygen_used) + breath.adjust_moles(/datum/gas/carbon_dioxide, oxygen_used) //CARBON DIOXIDE if(CO2_partialpressure > safe_co2_max) @@ -234,15 +228,15 @@ //TOXINS/PLASMA if(Toxins_partialpressure > safe_tox_max) - var/ratio = (breath_gases[/datum/gas/plasma]/safe_tox_max) * 10 + var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_tox_max) * 10 adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE)) throw_alert("too_much_tox", /obj/screen/alert/too_much_tox) else clear_alert("too_much_tox") //NITROUS OXIDE - if(breath_gases[/datum/gas/nitrous_oxide]) - var/SA_partialpressure = (breath_gases[/datum/gas/nitrous_oxide]/breath.total_moles())*breath_pressure + if(breath.get_moles(/datum/gas/nitrous_oxide)) + var/SA_partialpressure = (breath.get_moles(/datum/gas/nitrous_oxide)/breath.total_moles())*breath_pressure if(SA_partialpressure > SA_para_min) Unconscious(60) if(SA_partialpressure > SA_sleep_min) @@ -255,26 +249,26 @@ SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria") //BZ (Facepunch port of their Agent B) - if(breath_gases[/datum/gas/bz]) - var/bz_partialpressure = (breath_gases[/datum/gas/bz]/breath.total_moles())*breath_pressure + if(breath.get_moles(/datum/gas/bz)) + var/bz_partialpressure = (breath.get_moles(/datum/gas/bz)/breath.total_moles())*breath_pressure if(bz_partialpressure > 1) hallucination += 10 else if(bz_partialpressure > 0.01) hallucination += 5 //TRITIUM - if(breath_gases[/datum/gas/tritium]) - var/tritium_partialpressure = (breath_gases[/datum/gas/tritium]/breath.total_moles())*breath_pressure + if(breath.get_moles(/datum/gas/tritium)) + var/tritium_partialpressure = (breath.get_moles(/datum/gas/tritium)/breath.total_moles())*breath_pressure radiation += tritium_partialpressure/10 //NITRYL - if(breath_gases[/datum/gas/nitryl]) - var/nitryl_partialpressure = (breath_gases[/datum/gas/nitryl]/breath.total_moles())*breath_pressure + if(breath.get_moles(/datum/gas/nitryl)) + var/nitryl_partialpressure = (breath.get_moles(/datum/gas/nitryl)/breath.total_moles())*breath_pressure adjustFireLoss(nitryl_partialpressure/4) //MIASMA - if(breath_gases[/datum/gas/miasma]) - var/miasma_partialpressure = (breath_gases[/datum/gas/miasma]/breath.total_moles())*breath_pressure + if(breath.get_moles(/datum/gas/miasma)) + var/miasma_partialpressure = (breath.get_moles(/datum/gas/miasma)/breath.total_moles())*breath_pressure if(miasma_partialpressure > MINIMUM_MOLES_DELTA_TO_MOVE) if(prob(0.05 * miasma_partialpressure)) @@ -314,11 +308,6 @@ else SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell") - - - - GAS_GARBAGE_COLLECT(breath.gases) - //BREATH TEMPERATURE handle_breath_temperature(breath) @@ -377,9 +366,9 @@ var/datum/gas_mixture/stank = new - stank.gases[/datum/gas/miasma] = 0.1 + stank.set_moles(/datum/gas/miasma,0.1) - stank.temperature = BODYTEMP_NORMAL + stank.set_temperature(BODYTEMP_NORMAL) miasma_turf.assume_air(stank) @@ -417,6 +406,12 @@ if(stat != DEAD || D.process_dead) D.stage_act() +/mob/living/carbon/handle_wounds() + for(var/thing in all_wounds) + var/datum/wound/W = thing + if(W.processes) // meh + W.handle_process() + //todo generalize this and move hud out /mob/living/carbon/proc/handle_changeling() if(mind && hud_used && hud_used.lingchemdisplay) @@ -429,6 +424,12 @@ hud_used.lingchemdisplay.invisibility = INVISIBILITY_ABSTRACT +/mob/living/carbon/proc/handle_bloodsucker() + if(mind && AmBloodsucker(src)) + var/datum/antagonist/bloodsucker/B = mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) + B.LifeTick() + + /mob/living/carbon/handle_mutations_and_radiation() if(dna && dna.temporary_mutations.len) for(var/mut in dna.temporary_mutations) @@ -524,7 +525,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put /mob/living/carbon/handle_status_effects() ..() if(getStaminaLoss() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active - adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? -7.5 : -6) : -3)//CIT CHANGE - decreases adjuststaminaloss to stop stamina damage from being such a joke + adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? STAM_RECOVERY_STAM_CRIT : STAM_RECOVERY_RESTING) : STAM_RECOVERY_NORMAL) if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1) incomingstammult = max(0.01, incomingstammult) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 1b0856bfcd..13d234092c 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -81,7 +81,7 @@ /mob/living/carbon/monkey/proc/pickup_and_wear(obj/item/I) if(QDELETED(I) || I.loc != src) return - equip_to_appropriate_slot(I) + equip_to_appropriate_slot(I, TRUE) /mob/living/carbon/monkey/resist_restraints() var/obj/item/I = null @@ -90,8 +90,7 @@ else if(legcuffed) I = legcuffed if(I) - changeNext_move(CLICK_CD_BREAKOUT) - last_special = world.time + CLICK_CD_BREAKOUT + MarkResistTime() cuff_resist(I) /mob/living/carbon/monkey/proc/should_target(var/mob/living/L) @@ -354,7 +353,7 @@ battle_screech() a_intent = INTENT_HARM -/mob/living/carbon/monkey/attack_hand(mob/living/L) +/mob/living/carbon/monkey/on_attack_hand(mob/living/L) if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) retaliate(L) else if(L.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB)) diff --git a/code/modules/mob/living/carbon/monkey/inventory.dm b/code/modules/mob/living/carbon/monkey/inventory.dm index d5fffc70a2..34599028f7 100644 --- a/code/modules/mob/living/carbon/monkey/inventory.dm +++ b/code/modules/mob/living/carbon/monkey/inventory.dm @@ -1,4 +1,9 @@ -/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) +/mob/living/carbon/monkey/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) + if(clothing_check && (slot in check_obscured_slots())) + if(return_warning) + return_warning[1] = "You are unable to equip that with your current garments in the way!" + return FALSE + switch(slot) if(SLOT_HANDS) if(get_empty_held_indexes()) diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm index edbd1562b3..9e6431985c 100644 --- a/code/modules/mob/living/carbon/monkey/life.dm +++ b/code/modules/mob/living/carbon/monkey/life.dm @@ -3,30 +3,26 @@ /mob/living/carbon/monkey -/mob/living/carbon/monkey/Life() - set invisibility = 0 - - if (notransform) +/mob/living/carbon/monkey/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return - - if(..()) - - if(!client) - if(stat == CONSCIOUS) - if(on_fire || buckled || restrained() || (!CHECK_MOBILITY(src, MOBILITY_STAND) && CHECK_MOBILITY(src, MOBILITY_MOVE))) //CIT CHANGE - makes it so monkeys attempt to resist if they're resting) - if(!resisting && prob(MONKEY_RESIST_PROB)) - resisting = TRUE - walk_to(src,0) - resist() - else if(resisting) - resisting = FALSE - else if((mode == MONKEY_IDLE && !pickupTarget && !prob(MONKEY_SHENANIGAN_PROB)) || !handle_combat()) - if(prob(25) && CHECK_MOBILITY(src, MOBILITY_MOVE) && isturf(loc) && !pulledby) - step(src, pick(GLOB.cardinals)) - else if(prob(1)) - emote(pick("scratch","jump","roll","tail")) - else + if(client) + return + if(stat == CONSCIOUS) + if(on_fire || buckled || restrained() || (!CHECK_MOBILITY(src, MOBILITY_STAND) && CHECK_MOBILITY(src, MOBILITY_MOVE))) //CIT CHANGE - makes it so monkeys attempt to resist if they're resting) + if(!resisting && prob(MONKEY_RESIST_PROB)) + resisting = TRUE walk_to(src,0) + resist() + else if(resisting) + resisting = FALSE + else if((mode == MONKEY_IDLE && !pickupTarget && !prob(MONKEY_SHENANIGAN_PROB)) || !handle_combat()) + if(prob(25) && CHECK_MOBILITY(src, MOBILITY_MOVE) && isturf(loc) && !pulledby) + step(src, pick(GLOB.cardinals)) + else if(prob(1)) + emote(pick("scratch","jump","roll","tail")) + else + walk_to(src,0) /mob/living/carbon/monkey/handle_mutations_and_radiation() if(radiation) @@ -50,8 +46,8 @@ return ..() /mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath) - if(abs(BODYTEMP_NORMAL - breath.temperature) > 50) - switch(breath.temperature) + if(abs(BODYTEMP_NORMAL - breath.return_temperature()) > 50) + switch(breath.return_temperature()) if(-INFINITY to 120) adjustFireLoss(3) if(120 to 200) diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm index 8f862af8fa..16b3c1a79e 100644 --- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm +++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm @@ -42,7 +42,7 @@ adjustBruteLoss(15) return TRUE -/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M) +/mob/living/carbon/monkey/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) //To allow surgery to return properly. return diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm index fbe4bc9900..c59218a8a3 100644 --- a/code/modules/mob/living/carbon/monkey/punpun.dm +++ b/code/modules/mob/living/carbon/monkey/punpun.dm @@ -26,16 +26,19 @@ //These have to be after the parent new to ensure that the monkey //bodyparts are actually created before we try to equip things to //those slots + if(ancestor_chain > 1) + generate_fake_scars(rand(ancestor_chain, ancestor_chain * 4)) if(relic_hat) equip_to_slot_or_del(new relic_hat, SLOT_HEAD) if(relic_mask) equip_to_slot_or_del(new relic_mask, SLOT_WEAR_MASK) -/mob/living/carbon/monkey/punpun/Life() +/mob/living/carbon/monkey/punpun/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) Write_Memory(FALSE, FALSE) memory_saved = TRUE - ..() /mob/living/carbon/monkey/punpun/death(gibbed) if(!memory_saved) diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm index 9a1c6c54b6..1a796fb2bc 100644 --- a/code/modules/mob/living/carbon/update_icons.dm +++ b/code/modules/mob/living/carbon/update_icons.dm @@ -12,7 +12,7 @@ overlays_standing[cache_index] = null /mob/living/carbon/regenerate_icons() - if(notransform) + if(mob_transforming) return 1 update_inv_hands() update_inv_handcuffed() @@ -68,7 +68,7 @@ var/dam_colors = "#E62525" if(ishuman(src)) var/mob/living/carbon/human/H = src - dam_colors = bloodtype_to_color(H.dna.blood_type) + dam_colors = H.dna.species.exotic_blood_color var/mutable_appearance/damage_overlay = mutable_appearance('icons/mob/dam_mob.dmi', "blank", -DAMAGE_LAYER, color = dam_colors) overlays_standing[DAMAGE_LAYER] = damage_overlay diff --git a/code/modules/mob/living/clickdelay.dm b/code/modules/mob/living/clickdelay.dm new file mode 100644 index 0000000000..dfdb9104bf --- /dev/null +++ b/code/modules/mob/living/clickdelay.dm @@ -0,0 +1,4 @@ +/mob/living/GetActionCooldownMod() + . = ..() + for(var/datum/status_effect/S in status_effects) + . *= S.action_cooldown_mod() diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 87d5abb89e..47c9062148 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -1,14 +1,20 @@ -/* - apply_damage(a,b,c) - args - a:damage - How much damage to take - b:damage_type - What type of damage to take, brute, burn - c:def_zone - Where to take the damage if its brute or burn - Returns - standard 0 if fail -*/ -/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE) +/** + * Applies damage to this mob + * + * Sends [COMSIG_MOB_APPLY_DAMGE] + * + * Arguuments: + * * damage - amount of damage + * * damagetype - one of [BRUTE], [BURN], [TOX], [OXY], [CLONE], [STAMINA] + * * def_zone - zone that is being hit if any + * * blocked - armor value applied + * * forced - bypass hit percentage + * * spread_damage - used in overrides + * + * Returns TRUE if damage applied + */ +/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) var/hit_percent = (100-blocked)/100 if(!damage || (hit_percent <= 0)) return 0 @@ -239,7 +245,7 @@ update_stamina() // damage ONE external organ, organ gets randomly selected from damaged ones. -/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE) +/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) adjustBruteLoss(brute, FALSE) //zero as argument for no instant health update adjustFireLoss(burn, FALSE) adjustStaminaLoss(stamina, FALSE) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index ad1a3bc9b9..fe5a78de21 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -8,8 +8,6 @@ spill_organs(no_brain, no_organs, no_bodyparts) - release_vore_contents(silent = TRUE) // return of the bomb safe internals. - if(!no_bodyparts) spread_bodyparts(no_brain, no_organs) @@ -46,7 +44,6 @@ buckled.unbuckle_mob(src, force = TRUE) dust_animation() - release_vore_contents(silent = TRUE) //technically grief protection, I guess? if they're SM'd it doesn't matter seconds after anyway. spawn_dust(just_ash) QDEL_IN(src,5) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes. @@ -103,5 +100,5 @@ for(var/s in sharedSoullinks) var/datum/soullink/S = s S.sharerDies(gibbed) - + release_vore_contents(silent = TRUE) return TRUE diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 7d0a701e8f..a735baceae 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -9,6 +9,11 @@ key_third_person = "blushes" message = "blushes." +/datum/emote/living/blush/run_emote(mob/user, params) + . = ..() + if(. && isipcperson(user)) + do_fake_sparks(5,FALSE,user) + /datum/emote/living/bow key = "bow" key_third_person = "bows" @@ -226,7 +231,7 @@ 'sound/voice/catpeople/nyahehe.ogg'), 50, 1) return - else if(ismoth(C)) + else if(isinsect(C)) playsound(C, 'sound/voice/moth/mothlaugh.ogg', 50, 1) else if(ishumanbasic(C)) if(user.gender == FEMALE) @@ -244,7 +249,7 @@ . = ..() if(. && iscarbon(user)) //Citadel Edit because this is hilarious var/mob/living/carbon/C = user - if(ismoth(C)) + if(isinsect(C)) playsound(C, 'sound/voice/moth/mothchitter.ogg', 50, 1) /datum/emote/living/look @@ -326,6 +331,11 @@ key_third_person = "smiles" message = "smiles." +/datum/emote/living/smirk + key = "smirk" + key_third_person = "smirks" + message = "smirks." + /datum/emote/living/sneeze key = "sneeze" key_third_person = "sneezes" @@ -441,7 +451,7 @@ to_chat(user, "You cannot send IC messages (muted).") return FALSE else if(!params) - var/custom_emote = stripped_multiline_input(user, "Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN) + var/custom_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN) if(custom_emote && !check_invalid(user, custom_emote)) var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable") switch(type) @@ -531,3 +541,29 @@ to_chat(user, "You ready your slapping hand.") else to_chat(user, "You're incapable of slapping in your current state.") + +/datum/emote/living/audio_emote/blorble + key = "blorble" + key_third_person = "blorbles" + message = "blorbles." + message_param = "blorbles at %t." + +/datum/emote/living/audio_emote/blorble/run_emote(mob/user, params) + . = ..() + if(. && iscarbon(user)) + var/mob/living/carbon/C = user + if(isjellyperson(C)) + pick(playsound(C, 'sound/effects/attackblob.ogg', 50, 1),playsound(C, 'sound/effects/blobattack.ogg', 50, 1)) + +/datum/emote/living/audio_emote/blurp + key = "blurp" + key_third_person = "blurps" + message = "blurps." + message_param = "blurps at %t." + +/datum/emote/living/audio_emote/blurp/run_emote(mob/user, params) + . = ..() + if(. && iscarbon(user)) + var/mob/living/carbon/C = user + if(isjellyperson(C)) + pick(playsound(C, 'sound/effects/meatslap.ogg', 50, 1),playsound(C, 'sound/effects/gib_step.ogg', 50, 1)) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 5e04e3ec16..89321082c9 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -1,12 +1,20 @@ +/** + * Called by SSmobs at (hopefully) an interval of 1 second. + * Splits off into PhysicalLife() and BiologicalLife(). Override those instead of this. + */ /mob/living/proc/Life(seconds, times_fired) - set waitfor = FALSE - set invisibility = 0 + SHOULD_NOT_SLEEP(TRUE) + if(mob_transforming) + return - if(digitalinvis) - handle_diginvis() //AI becomes unable to see mob + . = SEND_SIGNAL(src, COMSIG_LIVING_LIFE, seconds, times_fired) + if(!(. & COMPONENT_INTERRUPT_LIFE_PHYSICAL)) + PhysicalLife(seconds, times_fired) + if(!(. & COMPONENT_INTERRUPT_LIFE_BIOLOGICAL)) + BiologicalLife(seconds, times_fired) - if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating - float(on = TRUE) + // CODE BELOW SHOULD ONLY BE THINGS THAT SHOULD HAPPEN NO MATTER WHAT AND CAN NOT BE SUSPENDED! + // Otherwise, it goes into one of the two split Life procs! if (client) var/turf/T = get_turf(src) @@ -30,28 +38,56 @@ log_game("Z-TRACKING: [src] of type [src.type] has a Z-registration despite not having a client.") update_z(null) - if (notransform) - return - if(!loc) - return - var/datum/gas_mixture/environment = loc.return_air() - - if(stat != DEAD) - //Mutations and radiation - handle_mutations_and_radiation() - - if(stat != DEAD) - //Breathing, if applicable - handle_breathing(times_fired) - +/** + * Handles biological life processes like chemical metabolism, breathing, etc + * Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop. + */ +/mob/living/proc/BiologicalLife(seconds, times_fired) handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not. - if (QDELETED(src)) // diseases can qdel the mob via transformations - return + handle_wounds() - if(stat != DEAD) - //Random events (vomiting etc) - handle_random_events() + // Everything after this shouldn't process while dead (as of the time of writing) + if(stat == DEAD) + return FALSE + + //Mutations and radiation + handle_mutations_and_radiation() + + //Breathing, if applicable + handle_breathing(times_fired) + + if (QDELETED(src)) // diseases can qdel the mob via transformations + return FALSE + + //Random events (vomiting etc) + handle_random_events() + + //stuff in the stomach + handle_stomach() + + handle_block_parry(seconds) + + // These two MIGHT need to be moved to base Life() if we get any in the future that's a "physical" effect that needs to fire even while in stasis. + handle_traits() // eye, ear, brain damages + handle_status_effects() //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc + return TRUE + +/** + * Handles physical life processes like being on fire. Don't ask why this is considered "Life". + * Returns TRUE or FALSE based on if we were interrupted. This is used by overridden variants to check if they should stop. + */ +/mob/living/proc/PhysicalLife(seconds, times_fired) + if(digitalinvis) + handle_diginvis() //AI becomes unable to see mob + + if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating + INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE) + + if(!loc) + return FALSE + + var/datum/gas_mixture/environment = loc.return_air() //Handle temperature/pressure differences between body and environment if(environment) @@ -59,23 +95,11 @@ handle_fire() - //stuff in the stomach - handle_stomach() - handle_gravity() - handle_block_parry(seconds) - if(machine) machine.check_eye(src) - - if(stat != DEAD) - handle_traits() // eye, ear, brain damages - if(stat != DEAD) - handle_status_effects() //all special effects, stun, knockdown, jitteryness, hallucination, sleeping, etc - - if(stat != DEAD) - return 1 + return TRUE /mob/living/proc/handle_breathing(times_fired) return @@ -87,6 +111,9 @@ /mob/living/proc/handle_diseases() return +/mob/living/proc/handle_wounds() + return + /mob/living/proc/handle_diginvis() if(!digitaldisguise) src.digitaldisguise = image(loc = src) @@ -112,7 +139,7 @@ ExtinguishMob() return var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment - if(G.gases[/datum/gas/oxygen] < 1) + if(!G.get_moles(/datum/gas/oxygen, 1)) ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire return var/turf/location = get_turf(src) @@ -168,4 +195,4 @@ /mob/living/proc/handle_high_gravity(gravity) if(gravity >= GRAVITY_DAMAGE_TRESHOLD) //Aka gravity values of 3 or more var/grav_stregth = gravity - GRAVITY_DAMAGE_TRESHOLD - adjustBruteLoss(min(grav_stregth,3)) \ No newline at end of file + adjustBruteLoss(min(grav_stregth,3)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 5b21abfb84..2a461b5921 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -57,7 +57,7 @@ /mob/living/Bump(atom/A) if(..()) //we are thrown onto something return - if (buckled || now_pushing) + if(buckled || now_pushing) return if(ismob(A)) var/mob/M = A @@ -273,7 +273,7 @@ return stop_pulling() - changeNext_move(CLICK_CD_GRABBING) + DelayNextAction(CLICK_CD_GRABBING) if(AM.pulledby) if(!supress_message) @@ -605,41 +605,55 @@ SEND_SIGNAL(item, COMSIG_ITEM_WEARERCROSSED, AM) /mob/living/proc/makeTrail(turf/target_turf, turf/start, direction) - if(!has_gravity()) + if(!has_gravity() || !isturf(start) || !blood_volume) return - var/blood_exists = FALSE + var/blood_exists = locate(/obj/effect/decal/cleanable/trail_holder) in start - for(var/obj/effect/decal/cleanable/trail_holder/C in start) //checks for blood splatter already on the floor - blood_exists = TRUE - if(isturf(start)) - var/trail_type = getTrail() - if(trail_type) - var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) - if(blood_volume && blood_volume > max((BLOOD_VOLUME_NORMAL*blood_ratio)*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold - blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage. - var/newdir = get_dir(target_turf, start) - if(newdir != direction) - newdir = newdir | direction - if(newdir == 3) //N + S - newdir = NORTH - else if(newdir == 12) //E + W - newdir = EAST - if((newdir in GLOB.cardinals) && (prob(50))) - newdir = turn(get_dir(target_turf, start), 180) - if(!blood_exists) - new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses()) + var/trail_type = getTrail() + if(!trail_type) + return - for(var/obj/effect/decal/cleanable/trail_holder/TH in start) - if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) - TH.existing_dirs += newdir - TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) - TH.transfer_mob_blood_dna(src) + var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) + if(blood_volume < max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold + return + + var/bleed_amount = bleedDragAmount() + blood_volume = max(blood_volume - bleed_amount, 0) //that depends on our brute damage. + var/newdir = get_dir(target_turf, start) + if(newdir != direction) + newdir = newdir | direction + if(newdir == (NORTH|SOUTH)) + newdir = NORTH + else if(newdir == (EAST|WEST)) + newdir = EAST + if((newdir in GLOB.cardinals) && (prob(50))) + newdir = turn(get_dir(target_turf, start), 180) + if(!blood_exists) + new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses()) + + for(var/obj/effect/decal/cleanable/trail_holder/TH in start) + if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) + TH.existing_dirs += newdir + TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) + TH.transfer_mob_blood_dna(src) /mob/living/carbon/human/makeTrail(turf/T) - if((NOBLOOD in dna.species.species_traits) || !bleed_rate || bleedsuppress) + if((NOBLOOD in dna.species.species_traits) || !is_bleeding() || bleedsuppress) return ..() +///Returns how much blood we're losing from being dragged a tile, from [mob/living/proc/makeTrail] +/mob/living/proc/bleedDragAmount() + var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) + return max(1, brute_ratio * 2) + +/mob/living/carbon/bleedDragAmount() + var/bleed_amount = 0 + for(var/i in all_wounds) + var/datum/wound/iter_wound = i + bleed_amount += iter_wound.drag_bleed_amount() + return bleed_amount + /mob/living/proc/getTrail() if(getBruteLoss() < 300) return pick("ltrails_1", "ltrails_2") @@ -676,7 +690,7 @@ ..(pressure_difference, direction, pressure_resistance_prob_delta) /mob/living/can_resist() - return !((next_move > world.time) || !CHECK_MOBILITY(src, MOBILITY_RESIST)) + return CheckResistCooldown() && CHECK_MOBILITY(src, MOBILITY_RESIST) /// Resist verb for attempting to get out of whatever is restraining your motion. Gives you resist clickdelay if do_resist() returns true. /mob/living/verb/resist() @@ -687,10 +701,12 @@ return if(do_resist()) - changeNext_move(CLICK_CD_RESIST) + MarkResistTime() + DelayNextAction(CLICK_CD_RESIST) -/// The actual proc for resisting. Return TRUE to give clickdelay. +/// The actual proc for resisting. Return TRUE to give CLICK_CD_RESIST clickdelay. /mob/living/proc/do_resist() + set waitfor = FALSE // some of these sleep. SEND_SIGNAL(src, COMSIG_LIVING_RESIST, src) //resisting grabs (as if it helps anyone...) // only works if you're not cuffed. @@ -701,7 +717,7 @@ return old_gs? TRUE : FALSE // unbuckling yourself. stops the chain if you try it. - if(buckled && last_special <= world.time) + if(buckled) log_combat(src, buckled, "resisted buckle") return resist_buckle() @@ -730,13 +746,12 @@ if(CHECK_MOBILITY(src, MOBILITY_USE) && resist_embedded()) //Citadel Change for embedded removal memes - requires being able to use items. // DO NOT GIVE DEFAULT CLICKDELAY - This is a combat action. - changeNext_move(CLICK_CD_MELEE) + DelayNextAction(CLICK_CD_MELEE) return FALSE - if(last_special <= world.time) - resist_restraints() //trying to remove cuffs. - // DO NOT GIVE CLICKDELAY - last_special handles this. - return FALSE + resist_restraints() //trying to remove cuffs. + // DO NOT GIVE CLICKDELAY + return FALSE /// Proc to resist a grab. moving_resist is TRUE if this began by someone attempting to move. Return FALSE if still grabbed/failed to break out. Use this instead of resist_grab() directly. /mob/proc/attempt_resist_grab(moving_resist, forced, log = TRUE) @@ -802,7 +817,7 @@ else throw_alert("gravity", /obj/screen/alert/weightless) if(!override && !is_flying()) - float(!has_gravity) + INVOKE_ASYNC(src, /atom/movable.proc/float, !has_gravity) /mob/living/float(on) if(throwing) @@ -914,7 +929,7 @@ floating_need_update = TRUE /mob/living/proc/get_temperature(datum/gas_mixture/environment) - var/loc_temp = environment ? environment.temperature : T0C + var/loc_temp = environment ? environment.return_temperature() : T0C if(isobj(loc)) var/obj/oloc = loc var/obj_temp = oloc.return_temperature() @@ -1196,30 +1211,29 @@ /mob/living/vv_edit_var(var_name, var_value) switch(var_name) - if ("maxHealth") + if (NAMEOF(src, maxHealth)) if (!isnum(var_value) || var_value <= 0) return FALSE - if("stat") + if(NAMEOF(src, stat)) if((stat == DEAD) && (var_value < DEAD))//Bringing the dead back to life GLOB.dead_mob_list -= src GLOB.alive_mob_list += src if((stat < DEAD) && (var_value == DEAD))//Kill he GLOB.alive_mob_list -= src GLOB.dead_mob_list += src + if(NAMEOF(src, health)) //this doesn't work. gotta use procs instead. + return FALSE . = ..() switch(var_name) - if("eye_blind") + if(NAMEOF(src, eye_blind)) set_blindness(var_value) - if("eye_damage") - var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES) - E?.setOrganDamage(var_value) - if("eye_blurry") + if(NAMEOF(src, eye_blurry)) set_blurriness(var_value) - if("maxHealth") + if(NAMEOF(src, maxHealth)) updatehealth() - if("resize") + if(NAMEOF(src, resize)) update_transform() - if("lighting_alpha") + if(NAMEOF(src, lighting_alpha)) sync_lighting_plane_alpha() /mob/living/proc/do_adrenaline( diff --git a/code/modules/mob/living/living_active_block.dm b/code/modules/mob/living/living_active_block.dm index e1b90716b6..2493509e16 100644 --- a/code/modules/mob/living/living_active_block.dm +++ b/code/modules/mob/living/living_active_block.dm @@ -10,18 +10,17 @@ REMOVE_TRAIT(src, TRAIT_SPRINT_LOCKED, ACTIVE_BLOCK_TRAIT) remove_movespeed_modifier(/datum/movespeed_modifier/active_block) var/datum/block_parry_data/data = I.get_block_parry_data() - if(timeToNextMove() < data.block_end_click_cd_add) - changeNext_move(data.block_end_click_cd_add) + DelayNextAction(data.block_end_click_cd_add) return TRUE -/mob/living/proc/start_active_blocking(obj/item/I) +/mob/living/proc/active_block_start(obj/item/I) if(combat_flags & (COMBAT_FLAG_ACTIVE_BLOCK_STARTING | COMBAT_FLAG_ACTIVE_BLOCKING)) return FALSE if(!(I in held_items)) return FALSE var/datum/block_parry_data/data = I.get_block_parry_data() if(!istype(data)) //Typecheck because if an admin/coder screws up varediting or something we do not want someone being broken forever, the CRASH logs feedback so we know what happened. - CRASH("start_active_blocking called with an item with no valid data: [I] --> [I.block_parry_data]!") + CRASH("ACTIVE_BLOCK_START called with an item with no valid data: [I] --> [I.block_parry_data]!") combat_flags |= COMBAT_FLAG_ACTIVE_BLOCKING active_block_item = I if(data.block_lock_attacking) @@ -83,15 +82,21 @@ return FALSE // QOL: Instead of trying to just block with held item, grab first available item. var/obj/item/I = find_active_block_item() - if(!I) - to_chat(src, "You can't block with your bare hands!") + var/list/other_items = list() + if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_BLOCK_START, I, other_items) & COMPONENT_PREVENT_BLOCK_START) + to_chat(src, "Something is preventing you from blocking!") return + if(!I) + if(!length(other_items)) + to_chat(src, "You can't block with your bare hands!") + return + I = other_items[1] if(!I.can_active_block()) to_chat(src, "[I] is either not capable of being used to actively block, or is not currently in a state that can! (Try wielding it if it's twohanded, for example.)") return // QOL: Attempt to toggle on combat mode if it isn't already SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE) - if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) to_chat(src, "You must be in combat mode to actively block!") return FALSE var/datum/block_parry_data/data = I.get_block_parry_data() @@ -104,7 +109,7 @@ animate(src, pixel_x = get_standard_pixel_x_offset(), pixel_y = get_standard_pixel_y_offset(), time = 2.5, FALSE, SINE_EASING | EASE_IN, ANIMATION_END_NOW) return combat_flags &= ~(COMBAT_FLAG_ACTIVE_BLOCK_STARTING) - start_active_blocking(I) + active_block_start(I) /** * Gets the first item we can that can block, but if that fails, default to active held item.COMSIG_ENABLE_COMBAT_MODE @@ -115,7 +120,8 @@ for(var/obj/item/I in held_items - held) if(I.can_active_block()) return I - return held + else + return held /** * Proc called by keybindings to stop active blocking. @@ -174,6 +180,12 @@ /// Apply the stamina damage to our user, notice how damage argument is stamina_amount. /obj/item/proc/active_block_do_stamina_damage(mob/living/owner, atom/object, stamina_amount, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) + if(istype(object, /obj/item/projectile)) + var/obj/item/projectile/P = object + if(P.stamina) + var/blocked = active_block_calculate_final_damage(owner, object, P.stamina, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return) + var/stam = active_block_stamina_cost(owner, object, blocked, attack_text, ATTACK_TYPE_PROJECTILE, armour_penetration, attacker, def_zone, final_block_chance, block_return) + stamina_amount += stam var/datum/block_parry_data/data = get_block_parry_data() if(iscarbon(owner)) var/mob/living/carbon/C = owner diff --git a/code/modules/mob/living/living_active_parry.dm b/code/modules/mob/living/living_active_parry.dm index 50b51d4d95..b6706d0548 100644 --- a/code/modules/mob/living/living_active_parry.dm +++ b/code/modules/mob/living/living_active_parry.dm @@ -24,35 +24,49 @@ // yanderedev else if time var/obj/item/using_item = get_active_held_item() var/datum/block_parry_data/data + var/datum/tool var/method if(using_item?.can_active_parry()) data = using_item.block_parry_data method = ITEM_PARRY + tool = using_item else if(mind?.martial_art?.can_martial_parry) data = mind.martial_art.block_parry_data method = MARTIAL_PARRY - else if(combat_flags & COMBAT_FLAG_UNARMED_PARRY) + tool = mind.martial_art + else if((combat_flags & COMBAT_FLAG_UNARMED_PARRY) && check_unarmed_parry_activation_special()) data = block_parry_data method = UNARMED_PARRY + tool = src else // QOL: If none of the above work, try to find another item. var/obj/item/backup = find_backup_parry_item() - if(!backup) - to_chat(src, "You have nothing to parry with!") - return FALSE - data = backup.block_parry_data - using_item = backup + if(backup) + tool = backup + data = backup.block_parry_data + using_item = backup + method = ITEM_PARRY + var/list/other_items = list() + if(SEND_SIGNAL(src, COMSIG_LIVING_ACTIVE_PARRY_START, method, tool, other_items) & COMPONENT_PREVENT_PARRY_START) + to_chat(src, "Something is preventing you from parrying!") + return + if(!using_item && !method && length(other_items)) + using_item = other_items[1] method = ITEM_PARRY + data = using_item.block_parry_data + if(!method) + to_chat(src, "You have nothing to parry with!") + return FALSE //QOL: Try to enable combat mode if it isn't already SEND_SIGNAL(src, COMSIG_ENABLE_COMBAT_MODE) - if(!SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) to_chat(src, "You must be in combat mode to parry!") return FALSE data = return_block_parry_datum(data) var/full_parry_duration = data.parry_time_windup + data.parry_time_active + data.parry_time_spindown // no system in place to "fallback" if out of the 3 the top priority one can't parry due to constraints but something else can. // can always implement it later, whatever. - if((data.parry_respect_clickdelay && (next_move > world.time)) || ((parry_end_time_last + data.parry_cooldown) > world.time)) + if((data.parry_respect_clickdelay && !CheckActionCooldown()) || ((parry_end_time_last + data.parry_cooldown) > world.time)) to_chat(src, "You are not ready to parry (again)!") return // Point of no return, make sure everything is set. @@ -79,6 +93,12 @@ if(I.can_active_parry()) return I +/** + * Check if we can unarmed parry + */ +/mob/living/proc/check_unarmed_parry_activation_special() + return TRUE + /** * Called via timer when the parry sequence ends. */ @@ -101,7 +121,7 @@ Stagger(data.parry_failed_stagger_duration) effect_text += "staggering themselves" if(data.parry_failed_clickcd_duration) - changeNext_move(data.parry_failed_clickcd_duration) + DelayNextAction(data.parry_failed_clickcd_duration, flush = TRUE) effect_text += "throwing themselves off balance" handle_parry_ending_effects(data, effect_text) parrying = NOT_PARRYING @@ -140,17 +160,17 @@ /** * Called when an attack is parried using this, whether or not the parry was successful. */ -/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time) +/obj/item/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) /** * Called when an attack is parried innately, whether or not the parry was successful. */ -/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time) +/mob/living/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) /** * Called when an attack is parried using this, whether or not the parry was successful. */ -/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, parry_efficiency, parry_time) +/datum/martial_art/proc/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time) /** * Called when an attack is parried and block_parra_data indicates to use a proc to handle counterattack. @@ -225,7 +245,7 @@ . |= BLOCK_SUCCESS var/list/effect_text if(efficiency >= data.parry_efficiency_to_counterattack) - run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency) + effect_text = run_parry_countereffects(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency) if(data.parry_flags & PARRY_DEFAULT_HANDLE_FEEDBACK) handle_parry_feedback(object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, return_list, efficiency, effect_text) successful_parries += efficiency @@ -234,9 +254,12 @@ /mob/living/proc/handle_parry_feedback(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency, list/effect_text) var/datum/block_parry_data/data = get_parry_data() + var/knockdown_check = FALSE + if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER] && parry_efficiency >= data.parry_efficiency_to_counterattack) + knockdown_check = TRUE if(data.parry_sounds) playsound(src, pick(data.parry_sounds), 75) - visible_message("[src] parries \the [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""]!") + visible_message("[src] parries [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""][length(effect_text) && knockdown_check? " and" : ""][knockdown_check? " knocking them to the ground" : ""]!") /// Run counterattack if any /mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency) @@ -257,7 +280,7 @@ if(data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN]) switch(parrying) if(ITEM_PARRY) - active_parry_item.melee_attack_chain(src, attacker, null, ATTACKCHAIN_PARRY_COUNTERATTACK, data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN]) + active_parry_item.melee_attack_chain(src, attacker, null, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_CLICKDELAY | ATTACK_IGNORE_ACTION | NO_AUTO_CLICKDELAY_HANDLING, data.parry_data[PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN]) effect_text += "reflexively counterattacking with [active_parry_item]" if(UNARMED_PARRY) // WARNING: If you are using these two, the attackchain parry counterattack flags and damage multipliers are unimplemented. Be careful with how you handle this. UnarmedAttack(attacker) @@ -268,15 +291,15 @@ if(data.parry_data[PARRY_DISARM_ATTACKER]) L.drop_all_held_items() effect_text += "disarming" - if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER]) - L.DefaultCombatKnockdown(data.parry_data[PARRY_KNOCKDOWN_ATTACKER]) - effect_text += "knocking them to the ground" if(data.parry_data[PARRY_STAGGER_ATTACKER]) L.Stagger(data.parry_data[PARRY_STAGGER_ATTACKER]) effect_text += "staggering" if(data.parry_data[PARRY_DAZE_ATTACKER]) L.Daze(data.parry_data[PARRY_DAZE_ATTACKER]) effect_text += "dazing" + if(data.parry_data[PARRY_KNOCKDOWN_ATTACKER]) + L.DefaultCombatKnockdown(data.parry_data[PARRY_KNOCKDOWN_ATTACKER]) + // effect_text += "knocking them to the ground" - snowflaked above return effect_text /// Gets the datum/block_parry_data we're going to use to parry. diff --git a/code/modules/mob/living/living_blocking_parrying.dm b/code/modules/mob/living/living_blocking_parrying.dm index 9f1ad1c27a..47dae8849d 100644 --- a/code/modules/mob/living/living_blocking_parrying.dm +++ b/code/modules/mob/living/living_blocking_parrying.dm @@ -126,6 +126,8 @@ GLOBAL_LIST_EMPTY(block_parry_data) var/list/parry_imperfect_falloff_percent_override /// Efficiency in percent on perfect parry. var/parry_efficiency_perfect = 120 + /// Override for attack types, list("[ATTACK_TYPE_DEFINE]" = perecntage) for perfect efficiency. + var/parry_efficiency_perfect_override /// Parry effect data. var/list/parry_data = list( PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 1 @@ -180,7 +182,11 @@ GLOBAL_LIST_EMPTY(block_parry_data) if(isnull(leeway)) leeway = parry_time_perfect_leeway difference -= leeway - . = parry_efficiency_perfect + var/perfect = attack_type_list_scan(parry_efficiency_perfect_override, attack_type) + if(isnull(perfect)) + . = parry_efficiency_perfect + else + . = perfect if(difference <= 0) return var/falloff = attack_type_list_scan(parry_imperfect_falloff_percent_override, attack_type) @@ -276,6 +282,7 @@ GLOBAL_LIST_EMPTY(block_parry_data) RENDER_VARIABLE_SIMPLE(parry_imperfect_falloff_percent, "Linear falloff in percent per decisecond for attacks parried outside of perfect window.") RENDER_OVERRIDE_LIST(parry_imperfect_falloff_percent_override, "Override for the above for each attack type") RENDER_VARIABLE_SIMPLE(parry_efficiency_perfect, "Efficiency in percentage a parry in the perfect window is considered.") + RENDER_OVERRIDE_LIST(parry_efficiency_perfect_override, "Override for the above for each attack type") // parry_data dat += "" RENDER_VARIABLE_SIMPLE(parry_efficiency_considered_successful, "Minimum parry efficiency to be considered a successful parry.") diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index d0aff933b5..19adb7b787 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -1,7 +1,7 @@ /mob/living/proc/run_armor_check(def_zone = null, attack_flag = "melee", absorb_text = "Your armor absorbs the blow!", soften_text = "Your armor softens the blow!", armour_penetration, penetrated_text = "Your armor was penetrated!", silent=FALSE) var/armor = getarmor(def_zone, attack_flag) - + if(silent) return max(0, armor - armour_penetration) @@ -77,6 +77,7 @@ final_percent = returnlist[BLOCK_RETURN_PROJECTILE_BLOCK_PERCENTAGE] if(returned & BLOCK_SHOULD_REDIRECT) handle_projectile_attack_redirection(P, returnlist[BLOCK_RETURN_REDIRECT_METHOD]) + return BULLET_ACT_FORCE_PIERCE if(returned & BLOCK_REDIRECTED) return BULLET_ACT_FORCE_PIERCE if(returned & BLOCK_SUCCESS) @@ -85,7 +86,7 @@ totaldamage = block_calculate_resultant_damage(totaldamage, returnlist) var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null) if(!P.nodamage) - apply_damage(totaldamage, P.damage_type, def_zone, armor) + apply_damage(totaldamage, P.damage_type, def_zone, armor, wound_bonus = P.wound_bonus, bare_wound_bonus = P.bare_wound_bonus, sharpness = P.sharpness) if(P.dismemberment) check_projectile_dismemberment(P, def_zone) var/missing = 100 - final_percent @@ -108,12 +109,6 @@ /mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE) return FALSE -/mob/living/proc/embed_item(obj/item/I) - return - -/mob/living/proc/can_embed(obj/item/I) - return FALSE - /mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) // Throwingdatum can be null if someone had an accident() while slipping with an item in hand. var/obj/item/I @@ -129,37 +124,25 @@ skipcatch = TRUE blocked = TRUE total_damage = block_calculate_resultant_damage(total_damage, block_return) - else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding["embed_chance"]) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && (!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) || incapacitated() || get_active_held_item())) - embed_item(I) - hitpush = FALSE - skipcatch = TRUE //can't catch the now embedded item if(I) + var/nosell_hit = SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone, throwingdatum, FALSE, blocked) + if(nosell_hit) + skipcatch = TRUE + hitpush = FALSE if(!skipcatch && isturf(I.loc) && catch_item(I)) return TRUE var/dtype = BRUTE - var/volume = I.get_volume_by_throwforce_and_or_w_class() - SEND_SIGNAL(I, COMSIG_MOVABLE_IMPACT_ZONE, src, impacting_zone) + dtype = I.damtype - if (I.throwforce > 0) //If the weapon's throwforce is greater than zero... - if (I.throwhitsound) //...and throwhitsound is defined... - playsound(loc, I.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound. - else if(I.hitsound) //Otherwise, if the weapon's hitsound is defined... - playsound(loc, I.hitsound, volume, 1, -1) //...play the weapon's hitsound. - else if(!I.throwhitsound) //Otherwise, if throwhitsound isn't defined... - playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg. - - else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero... - playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg - if(!I.throwforce)// Otherwise, if the item's throwforce is 0... - playsound(loc, 'sound/weapons/throwtap.ogg', 1, volume, -1)//...play throwtap.ogg. if(!blocked) - visible_message("[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) - log_combat(I.thrownby, src, "threw and hit", I) + if(!nosell_hit) + visible_message("[src] is hit by [I]!", \ + "You're hit by [I]!") + if(!I.throwforce) + return + 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(I.throwforce, dtype, impacting_zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND)) else return 1 else @@ -234,8 +217,8 @@ //proc to upgrade a simple pull into a more aggressive grab. /mob/living/proc/grippedby(mob/living/carbon/user, instant = FALSE) if(user.grab_state < GRAB_KILL) - user.changeNext_move(CLICK_CD_GRABBING) - playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + user.DelayNextAction(CLICK_CD_GRABBING, flush = TRUE) + playsound(src, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) if(user.grab_state) //only the first upgrade is instantaneous var/old_grab_state = user.grab_state @@ -289,10 +272,10 @@ user.set_pull_offsets(src, grab_state) return 1 -/mob/living/attack_hand(mob/user) +/mob/living/on_attack_hand(mob/user, act_intent = user.a_intent, attackchain_flags) ..() //Ignoring parent return value here. SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user) - 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)) + if((user != src) && act_intent != INTENT_HELP && (mob_run_block(user, 0, user.name, ATTACK_TYPE_UNARMED | ATTACK_TYPE_MELEE | ((attackchain_flags & ATTACK_IS_PARRY_COUNTERATTACK)? ATTACK_TYPE_PARRY_COUNTERATTACK : NONE), null, user, check_zone(user.zone_selected), null) & BLOCK_SUCCESS)) log_combat(user, src, "attempted to touch") visible_message("[user] attempted to touch [src]!", "[user] attempted to touch you!", target = user, @@ -342,6 +325,9 @@ /mob/living/attack_animal(mob/living/simple_animal/M) M.face_atom(src) + if(!M.CheckActionCooldown(CLICK_CD_MELEE)) + return + M.DelayNextAction() if(M.melee_damage_upper == 0) M.visible_message("\The [M] [M.friendly_verb_continuous] [src]!", "You [M.friendly_verb_simple] [src]!", target = src, @@ -357,7 +343,7 @@ return 0 damage = block_calculate_resultant_damage(damage, return_list) if(M.attack_sound) - playsound(loc, M.attack_sound, 50, 1, 1) + playsound(src, M.attack_sound, 50, 1, 1) M.do_attack_animation(src) visible_message("\The [M] [M.attack_verb_continuous] [src]!", \ "\The [M] [M.attack_verb_continuous] you!", null, COMBAT_MESSAGE_RANGE, null, @@ -366,6 +352,9 @@ return damage /mob/living/attack_paw(mob/living/carbon/monkey/M) + if(!M.CheckActionCooldown(CLICK_CD_MELEE)) + return + M.DelayNextAction() if (M.a_intent == INTENT_HARM) if(HAS_TRAIT(M, TRAIT_PACIFISM)) to_chat(M, "You don't want to hurt anyone!") @@ -387,6 +376,7 @@ visible_message("[M.name] has attempted to bite [src]!", \ "[M.name] has attempted to bite [src]!", null, COMBAT_MESSAGE_RANGE, null, M, "You have attempted to bite [src]!") + return TRUE return FALSE /mob/living/attack_larva(mob/living/carbon/alien/larva/L) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index b037221e2c..5495d37297 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -53,7 +53,6 @@ var/hallucination = 0 //Directly affects how long a mob will hallucinate for - var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out. var/timeofdeath = 0 //Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects. diff --git a/code/modules/mob/living/living_mobility.dm b/code/modules/mob/living/living_mobility.dm index 32038a6102..654a979445 100644 --- a/code/modules/mob/living/living_mobility.dm +++ b/code/modules/mob/living/living_mobility.dm @@ -96,7 +96,13 @@ mobility_flags &= ~MOBILITY_STAND setMovetype(movement_type | CRAWLING) if(!lying) //force them on the ground - lying = pick(90, 270) + switch(dir) + if(NORTH, SOUTH) + lying = pick(90, 270) + if(EAST) + lying = 90 + else //West + lying = 270 if(has_gravity() && !buckled) playsound(src, "bodyfall", 20, 1) else diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 6caf96fedc..66c2cd96c7 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -88,11 +88,22 @@ GLOBAL_LIST_INIT(department_radio_keys, list( var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE) + var/ic_blocked = FALSE + /* + if(client && !forced && config.ic_filter_regex && findtext(message, config.ic_filter_regex)) + //The filter doesn't act on the sanitized message, but the raw message. + ic_blocked = TRUE + */ if(sanitize) message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) if(!message || message == "") return + if(ic_blocked) + //The filter warning message shows the sanitized message though. + to_chat(src, "That message contained a word prohibited in IC chat! Consider reviewing the server rules.\n\"[message]\"") + return + var/datum/saymode/saymode = SSradio.saymodes[talk_key] var/message_mode = get_message_mode(message) var/original_message = message diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 1147042c8c..2cbd1f35ca 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -3,48 +3,48 @@ #define POWER_RESTORATION_SEARCH_APC 2 #define POWER_RESTORATION_APC_FOUND 3 -/mob/living/silicon/ai/Life() - if (stat == DEAD) +/mob/living/silicon/ai/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return - else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist + //I'm not removing that shitton of tabs, unneeded as they are. -- Urist //Being dead doesn't mean your temperature never changes - update_gravity(mob_has_gravity()) + update_gravity(mob_has_gravity()) - handle_status_effects() + handle_status_effects() - if(malfhack && malfhack.aidisabled) - deltimer(malfhacking) - // This proc handles cleanup of screen notifications and - // messenging the client - malfhacked(malfhack) + if(malfhack && malfhack.aidisabled) + deltimer(malfhacking) + // This proc handles cleanup of screen notifications and + // messenging the client + malfhacked(malfhack) - if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc)) - view_core() + if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc)) + view_core() - if(machine) - machine.check_eye(src) + if(machine) + machine.check_eye(src) - // Handle power damage (oxy) - if(aiRestorePowerRoutine) - // Lost power - adjustOxyLoss(1) - else - // Gain Power - if(getOxyLoss()) - adjustOxyLoss(-1) + // Handle power damage (oxy) + if(aiRestorePowerRoutine) + // Lost power + adjustOxyLoss(1) + else + // Gain Power + if(getOxyLoss()) + adjustOxyLoss(-1) - if(!lacks_power()) - var/area/home = get_area(src) - if(home.powered(EQUIP)) - home.use_power(1000, EQUIP) + if(!lacks_power()) + var/area/home = get_area(src) + if(home.powered(EQUIP)) + home.use_power(1000, EQUIP) - if(aiRestorePowerRoutine >= POWER_RESTORATION_SEARCH_APC) - ai_restore_power() - return + if(aiRestorePowerRoutine >= POWER_RESTORATION_SEARCH_APC) + ai_restore_power() + return - else if(!aiRestorePowerRoutine) - ai_lose_power() + else if(!aiRestorePowerRoutine) + ai_lose_power() /mob/living/silicon/ai/proc/lacks_power() var/turf/T = get_turf(src) @@ -151,7 +151,7 @@ to_chat(src, "Receiving control information from APC.") sleep(2) apc_override = 1 - theAPC.ui_interact(src, state = GLOB.conscious_state) + theAPC.ui_interact(src) apc_override = 0 aiRestorePowerRoutine = POWER_RESTORATION_APC_FOUND sleep(50) diff --git a/code/modules/mob/living/silicon/ai/robot_control.dm b/code/modules/mob/living/silicon/ai/robot_control.dm new file mode 100644 index 0000000000..bbfb7604ba --- /dev/null +++ b/code/modules/mob/living/silicon/ai/robot_control.dm @@ -0,0 +1,76 @@ +/datum/robot_control + var/mob/living/silicon/ai/owner + +/datum/robot_control/New(mob/living/silicon/ai/new_owner) + if(!istype(new_owner)) + qdel(src) + owner = new_owner + +/datum/robot_control/proc/is_interactable(mob/user) + if(user != owner || owner.incapacitated()) + return FALSE + if(owner.control_disabled) + to_chat(user, "Wireless control is disabled.") + return FALSE + return TRUE + +/datum/robot_control/ui_status(mob/user) + if(is_interactable(user)) + return ..() + return UI_CLOSE + +/datum/robot_control/ui_state(mob/user) + return GLOB.always_state + +/datum/robot_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "RemoteRobotControl") + ui.open() + +/datum/robot_control/ui_data(mob/user) + if(!owner || user != owner) + return + var/list/data = list() + var/turf/ai_current_turf = get_turf(owner) + var/ai_zlevel = ai_current_turf.z + + data["robots"] = list() + for(var/mob/living/simple_animal/bot/B in GLOB.bots_list) + if(B.z != ai_zlevel || B.remote_disabled) //Only non-emagged bots on the same Z-level are detected! + continue + var/list/robot_data = list( + name = B.name, + model = B.model, + mode = B.get_mode(), + hacked = B.hacked, + location = get_area_name(B, TRUE), + ref = REF(B) + ) + data["robots"] += list(robot_data) + + return data + +/datum/robot_control/ui_act(action, params) + if(..()) + return + if(!is_interactable(usr)) + return + + switch(action) + if("callbot") //Command a bot to move to a selected location. + if(owner.call_bot_cooldown > world.time) + to_chat(usr, "Error: Your last call bot command is still processing, please wait for the bot to finish calculating a route.") + return + owner.Bot = locate(params["ref"]) in GLOB.bots_list + if(!owner.Bot || owner.Bot.remote_disabled || owner.control_disabled) + return + owner.waypoint_mode = TRUE + to_chat(usr, "Set your waypoint by clicking on a valid location free of obstructions.") + . = TRUE + if("interface") //Remotely connect to a bot! + owner.Bot = locate(params["ref"]) in GLOB.bots_list + if(!owner.Bot || owner.Bot.remote_disabled || owner.control_disabled) + return + owner.Bot.attack_ai(usr) + . = TRUE diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index 91a6709bc9..7530630d74 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE) +/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) var/hit_percent = (100-blocked)/100 if(!damage || (!forced && hit_percent <= 0)) return 0 diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index 4b1b108b0e..704a23b8db 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -146,10 +146,11 @@ if(possible_chassis[chassis]) AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', ITEM_SLOT_HEAD) -/mob/living/silicon/pai/Life() +/mob/living/silicon/pai/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(hacking) process_hack() - return ..() /mob/living/silicon/pai/proc/process_hack() @@ -282,17 +283,19 @@ . = ..() . += "A personal AI in holochassis mode. Its master ID string seems to be [master]." -/mob/living/silicon/pai/Life() - if(stat == DEAD) - return +/mob/living/silicon/pai/PhysicalLife() + . = ..() if(cable) if(get_dist(src, cable) > 1) var/turf/T = get_turf(src.loc) T.visible_message("[src.cable] rapidly retracts back into its spool.", "You hear a click and the sound of wire spooling rapidly.") qdel(src.cable) cable = null + +/mob/living/silicon/pai/BiologicalLife() + if(!(. = ..())) + return silent = max(silent - 1, 0) - . = ..() /mob/living/silicon/pai/updatehealth() if(status_flags & GODMODE) diff --git a/code/modules/mob/living/silicon/pai/pai_defense.dm b/code/modules/mob/living/silicon/pai/pai_defense.dm index dcb7ac66c9..64509d2deb 100644 --- a/code/modules/mob/living/silicon/pai/pai_defense.dm +++ b/code/modules/mob/living/silicon/pai/pai_defense.dm @@ -28,8 +28,7 @@ fold_in(force = 1) DefaultCombatKnockdown(200) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user) +/mob/living/silicon/pai/on_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.", diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm index 76ced767e8..92f46e24bc 100644 --- a/code/modules/mob/living/silicon/pai/software.dm +++ b/code/modules/mob/living/silicon/pai/software.dm @@ -565,7 +565,6 @@ dat += "Unable to obtain a reading.
    " else var/datum/gas_mixture/environment = T.return_air() - var/list/env_gases = environment.gases var/pressure = environment.return_pressure() var/total_moles = environment.total_moles() @@ -573,11 +572,11 @@ dat += "Air Pressure: [round(pressure,0.1)] kPa
    " if (total_moles) - for(var/id in env_gases) - var/gas_level = env_gases[id]/total_moles + for(var/id in environment.get_gases()) + var/gas_level = environment.get_moles(id)/total_moles if(gas_level > 0.01) dat += "[GLOB.meta_gas_names[id]]: [round(gas_level*100)]%
    " - dat += "Temperature: [round(environment.temperature-T0C)]°C
    " + dat += "Temperature: [round(environment.return_temperature()-T0C)]°C
    " dat += "Refresh Reading
    " dat += "
    " return dat diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 65e1047cdc..c0fca997f5 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -3,8 +3,14 @@ emote_type = EMOTE_AUDIBLE /datum/emote/sound/silicon - mob_type_allowed_typecache = list(/mob/living/silicon) + mob_type_allowed_typecache = list(/mob/living/silicon, /mob/living/carbon/human) emote_type = EMOTE_AUDIBLE + var/unrestricted = FALSE + +/datum/emote/sound/silicon/run_emote(mob/user, params) + if(!unrestricted && !(issilicon(user) || isipcperson(user))) + return + return ..() /datum/emote/silicon/boop key = "boop" diff --git a/code/modules/mob/living/silicon/robot/inventory.dm b/code/modules/mob/living/silicon/robot/inventory.dm index bb6c37a010..9b964ef188 100644 --- a/code/modules/mob/living/silicon/robot/inventory.dm +++ b/code/modules/mob/living/silicon/robot/inventory.dm @@ -2,11 +2,20 @@ //as they handle all relevant stuff like adding it to the player's screen and such //Returns the thing in our active hand (whatever is in our active module-slot, in this case) +//This proc has been butchered into a proc that overrides borg item holding for the sake of making grippers work. +//I'd be immensely thankful if anyone can figure out a less obtuse way of making grippers work without breaking functionality. /mob/living/silicon/robot/get_active_held_item() + var/item = module_active + if(istype(item, /obj/item/weapon/gripper)) + var/obj/item/weapon/gripper/G = item + if(G.wrapped) + if(G.wrapped.loc != G) + G.wrapped = null + return module_active + item = G.wrapped + return item return module_active - - /mob/living/silicon/robot/proc/uneq_module(obj/item/O) if(!O) return 0 @@ -70,15 +79,15 @@ if(activated(O)) to_chat(src, "That module is already activated.") return - if(!held_items[1]) + if(!held_items[1] && health >= -maxHealth*0.5) held_items[1] = O O.screen_loc = inv1.screen_loc . = TRUE - else if(!held_items[2]) + else if(!held_items[2] && health >= 0) held_items[2] = O O.screen_loc = inv2.screen_loc . = TRUE - else if(!held_items[3]) + else if(!held_items[3] && health >= maxHealth*0.5) held_items[3] = O O.screen_loc = inv3.screen_loc . = TRUE diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index e04943a8c5..0feb8b98b7 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -1,9 +1,6 @@ -/mob/living/silicon/robot/Life() - set invisibility = 0 - if (src.notransform) +/mob/living/silicon/robot/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return - - ..() adjustOxyLoss(-10) //we're a robot! handle_robot_hud_updates() handle_robot_cell() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 633135b3d2..d8299d42ad 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -16,6 +16,8 @@ wires = new /datum/wires/robot(src) AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) + RegisterSignal(src, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/charge) + robot_modules_background = new() robot_modules_background.icon_state = "block" robot_modules_background.layer = HUD_LAYER //Objects that appear on screen are on layer ABOVE_HUD_LAYER, UI should be just below it. @@ -287,50 +289,57 @@ return FALSE return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range) -/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src)) - user.changeNext_move(CLICK_CD_MELEE) - if (!getBruteLoss()) - to_chat(user, "[src] is already in good condition!") +/mob/living/silicon/robot/proc/attempt_welder_repair(obj/item/weldingtool/W, mob/user) + if (!getBruteLoss()) + to_chat(user, "[src] is already in good condition!") + return + if (!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away. + return + user.DelayNextAction(CLICK_CD_MELEE) + if(src == user) + to_chat(user, "You start fixing yourself...") + if(!W.use_tool(src, user, 50)) return - if (!W.tool_start_check(user, amount=0)) //The welder has 1u of fuel consumed by it's afterattack, so we don't need to worry about taking any away. + adjustBruteLoss(-10) + else + to_chat(user, "You start fixing [src]...") + if(!do_after(user, 30, target = src)) return + adjustBruteLoss(-30) + updatehealth() + add_fingerprint(user) + visible_message("[user] has fixed some of the dents on [src].") + +/mob/living/silicon/robot/proc/attempt_cable_repair(obj/item/stack/cable_coil/W, mob/user) + if (getFireLoss() > 0 || getToxLoss() > 0) + user.DelayNextAction(CLICK_CD_MELEE) if(src == user) to_chat(user, "You start fixing yourself...") - if(!W.use_tool(src, user, 50)) + if(!W.use_tool(src, user, 50, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)) + to_chat(user, "You need more cable to repair [src]!") return - adjustBruteLoss(-10) + adjustFireLoss(-10) + adjustToxLoss(-10) 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 - adjustBruteLoss(-30) - updatehealth() - add_fingerprint(user) - visible_message("[user] has fixed some of the dents on [src].") + 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, "The wires seem fine, there's no need to fix them.") + +/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params) + if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src)) + INVOKE_ASYNC(src, .proc/attempt_welder_repair, W, user) return else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed) - user.changeNext_move(CLICK_CD_MELEE) - if (getFireLoss() > 0 || getToxLoss() > 0) - if(src == user) - to_chat(user, "You start fixing yourself...") - 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) - else - to_chat(user, "You start fixing [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, "The wires seem fine, there's no need to fix them.") + INVOKE_ASYNC(src, .proc/attempt_cable_repair, W, user) + return else if(istype(W, /obj/item/crowbar)) // crowbar means open or close the cover if(opened) @@ -1097,6 +1106,15 @@ for(var/i in connected_ai.aicamera.stored) aicamera.stored[i] = TRUE +/mob/living/silicon/robot/proc/charge(datum/source, amount, repairs) + if(module) + var/coeff = amount * 0.005 + module.respawn_consumable(src, coeff) + if(repairs) + heal_bodypart_damage(repairs, repairs - 1) + if(cell) + cell.charge = min(cell.charge + amount, cell.maxcharge) + /mob/living/silicon/robot/proc/rest_style() set name = "Switch Rest Style" set category = "Robot Commands" diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index e337618e4b..746c4f469d 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -62,8 +62,7 @@ return -//ATTACK HAND IGNORING PARENT RETURN VALUE -/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user) +/mob/living/silicon/robot/on_attack_hand(mob/living/carbon/human/user) add_fingerprint(user) if(opened && !wiresexposed && cell && !issilicon(user)) cell.update_icon() diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index bf66556399..6b58988c31 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -128,7 +128,7 @@ S.source = get_or_create_estorage(/datum/robot_energy_storage/wrapping_paper) if(S && S.source) - S.custom_materials = null + S.set_custom_materials(null) S.is_cyborg = 1 if(I.loc != src) @@ -259,7 +259,7 @@ var/prev_locked_down = R.locked_down sleep(1) flick("[cyborg_base_icon]_transform", R) - R.notransform = TRUE + R.mob_transforming = TRUE R.SetLockdown(1) R.anchored = TRUE sleep(1) @@ -270,7 +270,7 @@ R.SetLockdown(0) R.setDir(SOUTH) R.anchored = FALSE - R.notransform = FALSE + R.mob_transforming = FALSE R.update_headlamp() R.notify_ai(NEW_MODULE) if(R.hud_used) @@ -324,7 +324,7 @@ /obj/item/crowbar/cyborg, /obj/item/healthanalyzer, /obj/item/reagent_containers/borghypo, - /obj/item/reagent_containers/glass/beaker/large, + /obj/item/weapon/gripper/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/surgical_drapes, @@ -334,13 +334,15 @@ /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, + /obj/item/bonesetter, /obj/item/roller/robo, /obj/item/borg/cyborghug/medical, /obj/item/stack/medical/gauze/cyborg, + /obj/item/stack/medical/bone_gel/cyborg, /obj/item/organ_storage, /obj/item/borg/lollipop, /obj/item/sensor_device, - /obj/item/twohanded/shockpaddles/cyborg) + /obj/item/shockpaddles/cyborg) emag_modules = list(/obj/item/reagent_containers/borghypo/hacked) ratvar_modules = list( /obj/item/clockwork/slab/cyborg/medical, @@ -360,7 +362,7 @@ "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"), - "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_med") + "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakemedbox") ) var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed") for(var/a in L) @@ -376,8 +378,6 @@ switch(med_borg_icon) if("Default") cyborg_base_icon = "medical" - if("Zoomba") - cyborg_base_icon = "zoomba_med" if("Droid") cyborg_base_icon = "medical" cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' @@ -423,6 +423,13 @@ moduleselect_icon = "medihound" moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi' dogborg = TRUE + if("Drake") + cyborg_base_icon = "drakemed" + cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' + sleeper_overlay = "drakemedsleeper" + moduleselect_icon = "medihound" + moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi' + dogborg = TRUE else return FALSE return ..() @@ -444,7 +451,7 @@ /obj/item/t_scanner, /obj/item/analyzer, /obj/item/storage/part_replacer/cyborg, - /obj/item/holosign_creator/atmos, + /obj/item/holosign_creator/combifan, /obj/item/weapon/gripper, /obj/item/lightreplacer/cyborg, /obj/item/geiger_counter/cyborg, @@ -480,7 +487,7 @@ "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"), - "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_engi") + "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakeengbox") ) var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng") for(var/a in L) @@ -496,8 +503,6 @@ switch(engi_borg_icon) if("Default") cyborg_base_icon = "engineer" - if("Zoomba") - cyborg_base_icon = "zoomba_engi" if("Default - Treads") cyborg_base_icon = "engi-tread" special_light_key = "engineer" @@ -540,6 +545,11 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "alinasleeper" dogborg = TRUE + if("Drake") + cyborg_base_icon = "drakeeng" + cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' + sleeper_overlay = "drakesecsleeper" + dogborg = TRUE else return FALSE return ..() @@ -579,7 +589,7 @@ "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"), - "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_sec") + "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakesecbox") ) var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark") for(var/a in L) @@ -595,8 +605,6 @@ switch(sec_borg_icon) if("Default") cyborg_base_icon = "sec" - if("Zoomba") - cyborg_base_icon = "zoomba_sec" if("Default - Treads") cyborg_base_icon = "sec-tread" special_light_key = "sec" @@ -637,6 +645,11 @@ sleeper_overlay = "valesecsleeper" cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' dogborg = TRUE + if("Drake") + cyborg_base_icon = "drakesec" + cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' + sleeper_overlay = "drakesecsleeper" + dogborg = TRUE else return FALSE return ..() @@ -680,7 +693,8 @@ 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") + "Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "whitespider"), + "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakepeacebox") )) 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) @@ -696,6 +710,11 @@ hat_offset = INFINITY cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi' has_snowflake_deadsprite = TRUE + if("Drake") + cyborg_base_icon = "drakepeace" + cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' + sleeper_overlay = "drakepeacesleeper" + dogborg = TRUE else return FALSE return ..() @@ -779,9 +798,8 @@ /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/instrument/piano_synth, /obj/item/reagent_containers/dropper, /obj/item/lighter, /obj/item/storage/bag/tray, @@ -836,7 +854,7 @@ "(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"), - "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_jani") + "(Janitor) Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakejanitbox") ) var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark", "(Janitor) Scrubpuppy" = "scrubpup") @@ -851,8 +869,6 @@ 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("Zoomba") - cyborg_base_icon = "zoomba_jani" if("(Service) Waitress") cyborg_base_icon = "service_f" special_light_key = "service" @@ -910,6 +926,11 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "jsleeper" dogborg = TRUE + if("(Janitor) Drake") + cyborg_base_icon = "drakejanit" + cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' + sleeper_overlay = "drakesecsleeper" + dogborg = TRUE else return FALSE return ..() @@ -923,7 +944,7 @@ /obj/item/borg/sight/meson, /obj/item/storage/bag/ore/cyborg, /obj/item/pickaxe/drill/cyborg, - /obj/item/twohanded/kinetic_crusher/cyborg, + /obj/item/kinetic_crusher/cyborg, /obj/item/weldingtool/mini, /obj/item/storage/bag/sheetsnatcher/borg, /obj/item/t_scanner/adv_mining_scanner, @@ -956,7 +977,7 @@ "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"), - "Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_miner") + "Drake" = image(icon = 'icons/mob/cyborg/drakemech.dmi', icon_state = "drakeminebox") ) var/list/L = list("Blade" = "blade", "Vale" = "valemine") for(var/a in L) @@ -1000,8 +1021,11 @@ cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi' sleeper_overlay = "valeminesleeper" dogborg = TRUE - if("Zoomba") - cyborg_base_icon = "zoomba_miner" + if("Drake") + cyborg_base_icon = "drakemine" + cyborg_icon_override = 'icons/mob/cyborg/drakemech.dmi' + sleeper_overlay = "drakeminesleeper" + dogborg = TRUE else return FALSE return ..() @@ -1043,7 +1067,7 @@ /obj/item/extinguisher/mini, /obj/item/crowbar/cyborg, /obj/item/reagent_containers/borghypo/syndicate, - /obj/item/twohanded/shockpaddles/syndicate, + /obj/item/shockpaddles/syndicate, /obj/item/healthanalyzer/advanced, /obj/item/surgical_drapes/advanced, /obj/item/retractor, @@ -1051,6 +1075,8 @@ /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, + /obj/item/bonesetter, + /obj/item/stack/medical/bone_gel, /obj/item/melee/transforming/energy/sword/cyborg/saw, /obj/item/roller/robo, /obj/item/card/emag, diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 7a9610fb53..c6aee397e4 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -430,3 +430,6 @@ /mob/living/silicon/handle_high_gravity(gravity) return + +/mob/living/silicon/rust_heretic_act() + adjustBruteLoss(500) diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 0850f0f886..8be2183d3b 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -70,7 +70,7 @@ return TRUE return FALSE -/mob/living/silicon/attack_hand(mob/living/carbon/human/M) +/mob/living/silicon/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) //the attack was blocked return diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 278bb37d0d..b003e066ef 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -1,6 +1,6 @@ -/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M) +/mob/living/simple_animal/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) //the attack was blocked return diff --git a/code/modules/mob/living/simple_animal/astral.dm b/code/modules/mob/living/simple_animal/astral.dm index 4fb9e9273e..f79a2b5b3e 100644 --- a/code/modules/mob/living/simple_animal/astral.dm +++ b/code/modules/mob/living/simple_animal/astral.dm @@ -41,7 +41,11 @@ to_chat(src, "Your astral projection is interrupted and your mind is sent back to your body with a shock!") /mob/living/simple_animal/astral/ClickOn(var/atom/A, var/params) - ..() + . = ..() + attempt_possess(A) + +/mob/living/simple_animal/astral/proc/attempt_possess(atom/A) + set waitfor = FALSE if(pseudo_death == FALSE) if(isliving(A)) if(ishuman(A)) @@ -62,7 +66,7 @@ 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() - if(!mind) - qdel(src) +/mob/living/simple_animal/astral/PhysicalLife(seconds, times_fired) . = ..() + if(!mind && !QDELETED(src)) + qdel(src) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 39eccf9ad4..a1772d9281 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -102,6 +102,10 @@ var/can_salute = TRUE var/salute_delay = 60 SECONDS + //emotes/speech stuff + var/patrol_emote = "Engaging patrol mode." + var/patrol_fail_emote = "Unable to start patrol." + /mob/living/simple_animal/bot/proc/get_mode() if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player. if(paicard) @@ -115,6 +119,19 @@ else return "[mode_name[mode]]" +/** + * Returns a status string about the bot's current status, if it's moving, manually controlled, or idle. + */ +/mob/living/simple_animal/bot/proc/get_mode_ui() + if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player. + return paicard ? "pAI Controlled" : "Autonomous" + else if(!on) + return "Inactive" + else if(!mode) + return "Idle" + else + return "[mode_name[mode]]" + /mob/living/simple_animal/bot/proc/turn_on() if(stat) return FALSE @@ -273,7 +290,7 @@ return TRUE //Successful completion. Used to prevent child process() continuing if this one is ended early. -/mob/living/simple_animal/bot/attack_hand(mob/living/carbon/human/H) +/mob/living/simple_animal/bot/on_attack_hand(mob/living/carbon/human/H) if(H.a_intent == INTENT_HELP) interact(H) else @@ -318,7 +335,6 @@ user.visible_message("[user] uses [W] to pull [paicard] out of [bot_name]!","You pull [paicard] out of [bot_name] with [W].") ejectpai(user) else - user.changeNext_move(CLICK_CD_MELEE) if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) if(health >= maxHealth) to_chat(user, "[src] does not need a repair!") @@ -599,7 +615,7 @@ Pass a positive integer as an argument to override a bot's default speed. if(tries >= BOT_STEP_MAX_RETRIES) //Bot is trapped, so stop trying to patrol. auto_patrol = 0 tries = 0 - speak("Unable to start patrol.") + speak(patrol_fail_emote) return @@ -615,7 +631,7 @@ Pass a positive integer as an argument to override a bot's default speed. return mode = BOT_PATROL else // no patrol target, so need a new one - speak("Engaging patrol mode.") + speak(patrol_emote) find_patrol_target() tries++ return @@ -1042,3 +1058,6 @@ Pass a positive integer as an argument to override a bot's default speed. if(I) I.icon_state = null path.Cut(1, 2) + +/mob/living/silicon/rust_heretic_act() + adjustBruteLoss(500) diff --git a/code/modules/mob/living/simple_animal/bot/cleanbot.dm b/code/modules/mob/living/simple_animal/bot/cleanbot.dm index f6aad5c03f..e7c5644e26 100644 --- a/code/modules/mob/living/simple_animal/bot/cleanbot.dm +++ b/code/modules/mob/living/simple_animal/bot/cleanbot.dm @@ -184,7 +184,7 @@ else to_chat(user, "The [src] already has this mop!") - else if(istype(W, /obj/item/twohanded/broom)) + else if(istype(W, /obj/item/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!") upgrades |= UPGRADE_CLEANER_BROOM @@ -313,7 +313,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/insectguts, /obj/effect/decal/cleanable/semen, - /obj/effect/decal/cleanable/femcum, + /obj/effect/decal/cleanable/semen/femcum, /obj/effect/decal/cleanable/generic, /obj/effect/decal/cleanable/glass,, /obj/effect/decal/cleanable/cobweb, @@ -341,7 +341,7 @@ target_types = typecacheof(target_types) -/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(istype(A, /obj/effect/decal/cleanable)) anchored = TRUE icon_state = "cleanbot-c" diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 6febb942a1..91462a6713 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -177,7 +177,7 @@ Auto Patrol[]"}, target = H mode = BOT_HUNT -/mob/living/simple_animal/bot/ed209/attack_hand(mob/living/carbon/human/H) +/mob/living/simple_animal/bot/ed209/on_attack_hand(mob/living/carbon/human/H) if(H.a_intent == INTENT_HARM) retaliate(H) return ..() @@ -518,7 +518,7 @@ Auto Patrol[]"}, /mob/living/simple_animal/bot/ed209/redtag lasercolor = "r" -/mob/living/simple_animal/bot/ed209/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/ed209/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(!on) return if(iscarbon(A)) @@ -532,8 +532,10 @@ Auto Patrol[]"}, /mob/living/simple_animal/bot/ed209/RangedAttack(atom/A) if(!on) - return + return ..() shootAt(A) + DelayNextAction() + return TRUE /mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C) playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) diff --git a/code/modules/mob/living/simple_animal/bot/firebot.dm b/code/modules/mob/living/simple_animal/bot/firebot.dm index a5ac2e8bca..d0e969dc4e 100644 --- a/code/modules/mob/living/simple_animal/bot/firebot.dm +++ b/code/modules/mob/living/simple_animal/bot/firebot.dm @@ -58,7 +58,7 @@ internal_ext.max_water = INFINITY internal_ext.refill() -/mob/living/simple_animal/bot/firebot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/firebot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(!on) return if(internal_ext) diff --git a/code/modules/mob/living/simple_animal/bot/floorbot.dm b/code/modules/mob/living/simple_animal/bot/floorbot.dm index 0f4608f48c..0ba4023864 100644 --- a/code/modules/mob/living/simple_animal/bot/floorbot.dm +++ b/code/modules/mob/living/simple_animal/bot/floorbot.dm @@ -413,7 +413,7 @@ /obj/machinery/bot_core/floorbot req_one_access = list(ACCESS_CONSTRUCTION, ACCESS_ROBOTICS) -/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(isturf(A)) repair(A) else diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index c3c16d5976..0ee600ed1d 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -112,7 +112,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, target = H mode = BOT_HUNT -/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H) +/mob/living/simple_animal/bot/honkbot/on_attack_hand(mob/living/carbon/human/H) if(H.a_intent == INTENT_HARM) retaliate(H) addtimer(CALLBACK(src, .proc/react_buzz), 5) @@ -141,7 +141,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, retaliate(Proj.firer) return ..() -/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(!on) return if(iscarbon(A)) @@ -367,4 +367,4 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, ..() /obj/machinery/bot_core/honkbot - req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS) \ No newline at end of file + req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index cbb495bf9c..fb5a889d89 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -604,7 +604,7 @@ /mob/living/simple_animal/bot/medbot/proc/get_healchem_toxin(mob/M) return HAS_TRAIT(M, TRAIT_TOXINLOVER)? treatment_tox_toxlover : treatment_tox -/mob/living/simple_animal/bot/medbot/attack_hand(mob/living/carbon/human/H) +/mob/living/simple_animal/bot/medbot/on_attack_hand(mob/living/carbon/human/H) if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED) H.visible_message("[H] begins tipping over [src].", "You begin tipping over [src]...") @@ -625,7 +625,7 @@ else ..() -/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/medbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(iscarbon(A)) var/mob/living/carbon/C = A patient = C @@ -790,4 +790,4 @@ #undef MEDBOT_PANIC_HIGH #undef MEDBOT_PANIC_FUCK #undef MEDBOT_PANIC_ENDING -#undef MEDBOT_PANIC_END \ No newline at end of file +#undef MEDBOT_PANIC_END diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 917fdcf113..d9bf8cc553 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -29,9 +29,6 @@ model = "MULE" bot_core_type = /obj/machinery/bot_core/mulebot - var/ui_x = 350 - var/ui_y = 425 - var/id path_image_color = "#7F5200" @@ -170,11 +167,10 @@ return ui_interact(user) -/mob/living/simple_animal/bot/mulebot/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/mob/living/simple_animal/bot/mulebot/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "mulebot", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "Mule", name) ui.open() /mob/living/simple_animal/bot/mulebot/ui_data(mob/user) @@ -191,8 +187,7 @@ data["modeStatus"] = "average" if(BOT_NO_ROUTE) data["modeStatus"] = "bad" - else - data["load"] = load ? load.name : null + data["load"] = load ? load.name : null //IF YOU CHANGE THE NAME OF THIS, UPDATE MULEBOT/PARANORMAL/UI_DATA. data["destination"] = destination ? destination : null data["home"] = home_destination data["destinations"] = GLOB.deliverybeacontags @@ -206,18 +201,20 @@ return data /mob/living/simple_animal/bot/mulebot/ui_act(action, params) - var/silicon_access = hasSiliconAccessInArea(usr) - if(..() || (locked && silicon_access)) + if(..() || (locked && hasSiliconAccessInArea(usr))) return switch(action) if("lock") - if(silicon_access) + if(hasSiliconAccessInArea(usr)) locked = !locked . = TRUE if("power") if(on) turn_off() - else if(cell && !open) + else if(open) + to_chat(usr, "[name]'s maintenance panel is open!") + return + else if(cell) if(!turn_on()) to_chat(usr, "You can't switch on [src]!") return @@ -752,7 +749,7 @@ if(load) unload() -/mob/living/simple_animal/bot/mulebot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/mulebot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(isturf(A) && isturf(loc) && loc.Adjacent(A) && load) unload(get_dir(loc, A)) else diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index d199bc2ead..cf9698655b 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -33,6 +33,20 @@ var/check_records = TRUE //Does it check security records? var/arrest_type = FALSE //If true, don't handcuff + var/obj/item/clothing/head/bot_accessory + var/datum/beepsky_fashion/stored_fashion + + //emotes (BOT is replaced with bot name, CRIMINAL with criminal name, THREAT_LEVEL with threat level) + var/death_emote = "BOT blows apart!" + var/capture_one = "BOT is trying to put zipties on CRIMINAL!" + var/capture_two = "BOT is trying to put zipties on you!" + var/infraction = "Level THREAT_LEVEL infraction alert!" + var/taunt = "BOT points at CRIMINAL!" + var/attack_one = "BOT has stunned CRIMINAL!" + var/attack_two = "BOT has stunned you!" + var/list/arrest_texts = list("Detaining", "Arresting") + var/arrest_emote = "ARREST_TYPE level THREAT_LEVEL scumbag CRIMINAL in LOCATION." + /mob/living/simple_animal/bot/secbot/beepsky name = "Officer Beep O'sky" desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey." @@ -49,6 +63,103 @@ resize = 0.8 update_transform() +/mob/living/simple_animal/bot/secbot/proc/process_emote(var/emote_type, var/atom/criminal, var/threat, var/arrest = -1, var/location) + var/emote = "The continuity of space itself collapses around [src]. You should probably report that to someone higher up." + switch(emote_type) + if("DEATH") + emote = death_emote + if("CAPTURE_ONE") + emote = capture_one + if("CAPTURE_TWO") + emote = capture_two + if("INFRACTION") + emote = infraction + if("TAUNT") + emote = taunt + if("ATTACK_ONE") + emote = attack_one + if("ATTACK_TWO") + emote = attack_two + if("ARREST") + emote = arrest_emote + + //now replace pieces of the text with the information we have + if(emote_type != "TAUNT" && emote_type != "ARREST") + emote = replacetext(emote, "BOT", name) + else + emote = replacetext(emote, "BOT", "[name]") //needs to be bold if its a taunt or an arrest text + if(criminal) + emote = replacetext(emote, "CRIMINAL", criminal.name) + if(num2text(threat)) //because a threat of 0 will be false + emote = replacetext(emote, "THREAT_LEVEL", threat) + if(arrest > -1) + emote = replacetext(emote, "ARREST_TYPE", arrest_texts[arrest + 1]) + if(location) + emote = replacetext(emote, "LOCATION", location) + return emote + +/mob/living/simple_animal/bot/secbot/proc/apply_fashion(var/datum/beepsky_fashion/fashion) + stored_fashion = new fashion + if(stored_fashion.name) + name = stored_fashion.name + + if(stored_fashion.desc) + desc = stored_fashion.desc + + if(stored_fashion.death_emote) + death_emote = stored_fashion.death_emote + + if(stored_fashion.capture_one) + capture_one = stored_fashion.capture_one + + if(stored_fashion.capture_two) + capture_two = stored_fashion.capture_two + + if(stored_fashion.infraction) + infraction = stored_fashion.infraction + + if(stored_fashion.taunt) + taunt = stored_fashion.taunt + + if(stored_fashion.attack_one) + attack_one = stored_fashion.attack_one + + if(stored_fashion.attack_two) + attack_two = stored_fashion.attack_two + + if(stored_fashion.patrol_emote) + patrol_emote = stored_fashion.patrol_emote + + if(stored_fashion.patrol_fail_emote) + patrol_fail_emote = stored_fashion.patrol_fail_emote + + if(stored_fashion.arrest_texts) + arrest_texts = stored_fashion.arrest_texts + + if(stored_fashion.arrest_emote) + arrest_emote = stored_fashion.arrest_emote + + regenerate_icons() + +/mob/living/simple_animal/bot/secbot/proc/reset_fashion() + bot_accessory.forceMove(get_turf(src)) + //reset all emotes/sounds and name/desc + name = initial(name) + desc = initial(desc) + death_emote = initial(death_emote) + capture_one = initial(capture_one) + capture_two = initial(capture_two) + infraction = initial(infraction) + taunt = initial(taunt) + attack_one = initial(attack_one) + attack_two = initial(attack_two) + arrest_texts = initial(arrest_texts) + arrest_emote = initial(arrest_emote) + patrol_emote = initial(patrol_emote) + arrest_texts = initial(arrest_texts) + arrest_emote = initial(arrest_emote) + bot_accessory = null + regenerate_icons() /mob/living/simple_animal/bot/secbot/beepsky/explode() var/atom/Tsec = drop_location() @@ -173,11 +284,16 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/proc/special_retaliate_after_attack(mob/user) //allows special actions to take place after being attacked. return -/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H) +/mob/living/simple_animal/bot/secbot/on_attack_hand(mob/living/carbon/human/H) if((H.a_intent == INTENT_HARM) || (H.a_intent == INTENT_DISARM)) retaliate(H) if(special_retaliate_after_attack(H)) return + if(H.a_intent == INTENT_HELP && bot_accessory) + + to_chat(H, "You knock [bot_accessory] off of [src]'s head!") + reset_fashion() + return return ..() @@ -185,11 +301,48 @@ Auto Patrol: []"}, ..() if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry. return + if(istype(W, /obj/item/clothing/head)) + attempt_place_on_head(user, W) + return if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass. retaliate(user) if(special_retaliate_after_attack(user)) return +/mob/living/simple_animal/bot/secbot/proc/attempt_place_on_head(mob/user, obj/item/clothing/head/H) + if(user && !user.temporarilyRemoveItemFromInventory(H)) + to_chat(user, "\The [H] is stuck to your hand, you cannot put it on [src]'s head!") + return + if(bot_accessory) + to_chat("\[src] already has an accessory, and the laws of physics disallow him from wearing a second!") + return + + if(H.beepsky_fashion) + to_chat(user, "You set [H] on [src].") + bot_accessory = H + H.forceMove(src) + apply_fashion(H.beepsky_fashion) + else + to_chat(user, "You set [H] on [src]'s head, but it falls off!") + H.forceMove(drop_location()) + +/mob/living/simple_animal/bot/secbot/regenerate_icons() + ..() + if(bot_accessory) + if(!stored_fashion) + stored_fashion = new bot_accessory.beepsky_fashion + if(!stored_fashion.obj_icon_state) + stored_fashion.obj_icon_state = bot_accessory.icon_state + if(!stored_fashion.obj_alpha) + stored_fashion.obj_alpha = bot_accessory.alpha + if(!stored_fashion.obj_color) + stored_fashion.obj_color = bot_accessory.color + add_overlay(stored_fashion.get_overlay()) + else + if(stored_fashion) + cut_overlay(stored_fashion.get_overlay()) + stored_fashion = null + /mob/living/simple_animal/bot/secbot/emag_act(mob/user) . = ..() if(emagged == 2) @@ -208,7 +361,7 @@ Auto Patrol: []"}, return ..() -/mob/living/simple_animal/bot/secbot/UnarmedAttack(atom/A) +/mob/living/simple_animal/bot/secbot/UnarmedAttack(atom/A, proximity, intent = a_intent, flags = NONE) if(!on) return if(iscarbon(A)) @@ -233,8 +386,8 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C) mode = BOT_ARREST playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2) - C.visible_message("[src] is trying to put zipties on [C]!",\ - "[src] is trying to put zipties on you!") + C.visible_message("[process_emote("CAPTURE_ONE", C)]",\ + "[process_emote("CAPTURE_TWO", C)]") if(do_after(src, 60, FALSE, C)) attempt_handcuff(C) @@ -249,16 +402,22 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C) var/judgement_criteria = judgement_criteria() - playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) icon_state = "secbot-c" addtimer(CALLBACK(src, /atom/.proc/update_icon), 2) var/threat = 5 if(ishuman(C)) + if(stored_fashion) + stored_fashion.stun_attack(C) + if(stored_fashion.stun_sounds && !stored_fashion.ignore_sound) + playsound(src, pick(stored_fashion.stun_sounds), 50, TRUE, -1) + else + playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) C.stuttering = 5 C.DefaultCombatKnockdown(100) var/mob/living/carbon/human/H = C threat = H.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons)) else + playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) C.DefaultCombatKnockdown(100) C.stuttering = 5 threat = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons)) @@ -266,9 +425,9 @@ Auto Patrol: []"}, log_combat(src,C,"stunned") if(declare_arrests) var/area/location = get_area(src) - speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag [C] in [location].", radio_channel) - C.visible_message("[src] has stunned [C]!",\ - "[src] has stunned you!") + speak(process_emote("ARREST", C, threat, arrest_type, location), radio_channel) + C.visible_message("[process_emote("ATTACK_ONE", C)]",\ + "[process_emote("ATTACK_TWO", C)]") /mob/living/simple_animal/bot/secbot/handle_automated_action() if(!..()) @@ -355,7 +514,6 @@ Auto Patrol: []"}, look_for_perp() bot_patrol() - return /mob/living/simple_animal/bot/secbot/proc/back_to_idle() @@ -391,9 +549,9 @@ Auto Patrol: []"}, else if(threatlevel >= 4) target = C oldtarget_name = C.name - speak("Level [threatlevel] infraction alert!") + speak(process_emote("INFRACTION", target, threatlevel)) playsound(loc, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE) - visible_message("[src] points at [C.name]!") + visible_message(process_emote("TAUNT", target, threatlevel)) mode = BOT_HUNT INVOKE_ASYNC(src, .proc/handle_automated_action) break @@ -408,7 +566,7 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/explode() walk_to(src,0) - visible_message("[src] blows apart!") + visible_message("[process_emote("DEATH")]") var/atom/Tsec = drop_location() var/obj/item/bot_assembly/secbot/Sa = new (Tsec) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 354bc9ed0f..95bd8d8991 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -11,7 +11,6 @@ response_disarm_simple = "flail at" response_harm_continuous = "punches" response_harm_simple = "punch" - threat = 1 speak_chance = 1 icon = 'icons/mob/mob.dmi' speed = 0 @@ -122,7 +121,6 @@ desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire." icon_state = "behemoth" icon_living = "behemoth" - threat = 3 maxHealth = 150 health = 150 response_harm_continuous = "harmlessly punches" @@ -187,7 +185,6 @@ desc = "A wicked, clawed shell constructed to assassinate enemies and sow chaos behind enemy lines." icon_state = "floating" icon_living = "floating" - threat = 3 maxHealth = 65 health = 65 melee_damage_lower = 20 diff --git a/code/modules/mob/living/simple_animal/eldritch_demons.dm b/code/modules/mob/living/simple_animal/eldritch_demons.dm new file mode 100644 index 0000000000..dbf62be16d --- /dev/null +++ b/code/modules/mob/living/simple_animal/eldritch_demons.dm @@ -0,0 +1,386 @@ +/mob/living/simple_animal/hostile/eldritch + name = "Demon" + real_name = "Demon" + desc = "" + gender = NEUTER + mob_biotypes = NONE + speak_emote = list("screams") + 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 = "reaps" + response_harm_simple = "tears" + speak_chance = 1 + icon = 'icons/mob/eldritch_mobs.dmi' + speed = 0 + a_intent = INTENT_HARM + stop_automated_movement = 1 + AIStatus = AI_OFF + attack_sound = 'sound/weapons/punch1.ogg' + see_in_dark = 7 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) + 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 + healable = 0 + movement_type = GROUND + pressure_resistance = 100 + del_on_death = TRUE + deathmessage = "implodes into itself" + faction = list("heretics") + simple_mob_flags = SILENCE_RANGED_MESSAGE + ///Innate spells that are supposed to be added when a beast is created + var/list/spells_to_add + +/mob/living/simple_animal/hostile/eldritch/Initialize() + . = ..() + add_spells() + +/** + * Add_spells + * + * Goes through spells_to_add and adds each spell to the mind. + */ +/mob/living/simple_animal/hostile/eldritch/proc/add_spells() + for(var/spell in spells_to_add) + AddSpell(new spell()) + +/mob/living/simple_animal/hostile/eldritch/raw_prophet + name = "Raw Prophet" + real_name = "Raw Prophet" + desc = "Abomination made from severed limbs." + icon_state = "raw_prophet" + status_flags = CANPUSH + icon_living = "raw_prophet" + melee_damage_lower = 5 + melee_damage_upper = 10 + maxHealth = 50 + health = 50 + sight = SEE_MOBS|SEE_OBJS|SEE_TURFS + spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash/long,/obj/effect/proc_holder/spell/pointed/manse_link,/obj/effect/proc_holder/spell/targeted/telepathy/eldritch,/obj/effect/proc_holder/spell/pointed/trigger/blind/eldritch) + + var/list/linked_mobs = list() + +/mob/living/simple_animal/hostile/eldritch/raw_prophet/Initialize() + . = ..() + link_mob(src) + +/mob/living/simple_animal/hostile/eldritch/raw_prophet/Login() + . = ..() + client.change_view(10) + +/mob/living/simple_animal/hostile/eldritch/raw_prophet/proc/link_mob(mob/living/mob_linked) + if(QDELETED(mob_linked) || mob_linked.stat == DEAD) + return FALSE + if(HAS_TRAIT(mob_linked, TRAIT_MINDSHIELD)) //mindshield implant, no dice + return FALSE + if(mob_linked.anti_magic_check(FALSE, FALSE, TRUE, 0)) + return FALSE + if(linked_mobs[mob_linked]) + return FALSE + + to_chat(mob_linked, "You feel something new enter your sphere of mind, you hear whispers of people far away, screeches of horror and a humming of welcome to [src]'s Mansus Link.") + var/datum/action/innate/mansus_speech/action = new(src) + linked_mobs[mob_linked] = action + action.Grant(mob_linked) + RegisterSignal(mob_linked, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING) , .proc/unlink_mob) + return TRUE + +/mob/living/simple_animal/hostile/eldritch/raw_prophet/proc/unlink_mob(mob/living/mob_linked) + if(!linked_mobs[mob_linked]) + return + UnregisterSignal(mob_linked, list(COMSIG_MOB_DEATH, COMSIG_PARENT_QDELETING)) + var/datum/action/innate/mansus_speech/action = linked_mobs[mob_linked] + action.Remove(mob_linked) + qdel(action) + to_chat(mob_linked, "Your mind shatters as the [src]'s Mansus Link leaves your mind.") + mob_linked.emote("Scream") + //micro stun + mob_linked.AdjustParalyzed(0.5 SECONDS) + linked_mobs -= mob_linked + +/mob/living/simple_animal/hostile/eldritch/raw_prophet/death(gibbed) + for(var/linked_mob in linked_mobs) + unlink_mob(linked_mob) + return ..() + +/mob/living/simple_animal/hostile/eldritch/armsy + name = "Terror of the Night" + real_name = "Armsy" + desc = "Abomination made from severed limbs." + icon_state = "armsy_start" + icon_living = "armsy_start" + maxHealth = 200 + health = 200 + obj_damage = 80 + melee_damage_lower = 10 + melee_damage_upper = 15 + move_resist = MOVE_FORCE_OVERPOWERING+1 + movement_type = GROUND + environment_smash = ENVIRONMENT_SMASH_RWALLS + sight = SEE_MOBS + spells_to_add = list(/obj/effect/proc_holder/spell/targeted/worm_contract) + ranged = TRUE + ///Previous segment in the chain + var/mob/living/simple_animal/hostile/eldritch/armsy/back + ///Next segment in the chain + var/mob/living/simple_animal/hostile/eldritch/armsy/front + ///Your old location + var/oldloc + ///Allow / disallow pulling + var/allow_pulling = FALSE + ///How many arms do we have to eat to expand? + var/stacks_to_grow = 2 + ///Currently eaten arms + var/current_stacks = 0 + +//I tried Initalize but it didnt work, like at all. This proc just wouldnt fire if it was Initalize instead of New +/mob/living/simple_animal/hostile/eldritch/armsy/Initialize(mapload,spawn_more = TRUE,len = 6) + . = ..() + if(len < 3) + stack_trace("Eldritch Armsy created with invalid len ([len]). Reverting to 3.") + len = 3 //code breaks below 3, let's just not allow it. + oldloc = loc + RegisterSignal(src,COMSIG_MOVABLE_MOVED,.proc/update_chain_links) + if(!spawn_more) + return + allow_pulling = TRUE + ///next link + var/mob/living/simple_animal/hostile/eldritch/armsy/next + ///previous link + var/mob/living/simple_animal/hostile/eldritch/armsy/prev + ///current link + var/mob/living/simple_animal/hostile/eldritch/armsy/current + for(var/i in 0 to len) + prev = current + //i tried using switch, but byond is really fucky and it didnt work as intended. Im sorry + if(i == 0) + current = new type(drop_location(),FALSE) + current.icon_state = "armsy_mid" + current.icon_living = "armsy_mid" + current.front = src + current.AIStatus = AI_OFF + back = current + else if(i < len) + current = new type(drop_location(),FALSE) + prev.back = current + prev.icon_state = "armsy_mid" + prev.icon_living = "armsy_mid" + prev.front = next + prev.AIStatus = AI_OFF + else + prev.icon_state = "armsy_end" + prev.icon_living = "armsy_end" + prev.front = next + prev.AIStatus = AI_OFF + next = prev + +//we are literally a vessel of otherworldly destruction, we bring our own gravity unto this plane +/mob/living/simple_animal/hostile/eldritch/armsy/has_gravity(turf/T) + return TRUE + + +/mob/living/simple_animal/hostile/eldritch/armsy/can_be_pulled() + return FALSE + +///Updates chain links to force move onto a single tile +/mob/living/simple_animal/hostile/eldritch/armsy/proc/contract_next_chain_into_single_tile() + if(back) + back.forceMove(loc) + back.contract_next_chain_into_single_tile() + return + +///Updates the next mob in the chain to move to our last location, fixed the worm if somehow broken. +/mob/living/simple_animal/hostile/eldritch/armsy/proc/update_chain_links() + gib_trail() + if(back && back.loc != oldloc) + back.Move(oldloc) + // self fixing properties if somehow broken + if(front && loc != front.oldloc) + forceMove(front.oldloc) + oldloc = loc + +/mob/living/simple_animal/hostile/eldritch/armsy/proc/gib_trail() + if(front) // head makes gibs + return + var/chosen_decal = pick(typesof(/obj/effect/decal/cleanable/blood/tracks)) + var/obj/effect/decal/cleanable/blood/gibs/decal = new chosen_decal(drop_location()) + decal.setDir(dir) + +/mob/living/simple_animal/hostile/eldritch/armsy/Destroy() + if(front) + front.icon_state = "armsy_end" + front.icon_living = "armsy_end" + front.back = null + if(back) + QDEL_NULL(back) // chain destruction baby + return ..() + +/mob/living/simple_animal/hostile/eldritch/armsy/BiologicalLife(seconds, times_fired) + adjustBruteLoss(-2) + +/mob/living/simple_animal/hostile/eldritch/armsy/proc/heal() + if(health == maxHealth) + if(back) + back.heal() + return + else + current_stacks++ + if(current_stacks >= stacks_to_grow) + var/mob/living/simple_animal/hostile/eldritch/armsy/prev = new type(drop_location(),spawn_more = FALSE) + icon_state = "armsy_mid" + icon_living = "armsy_mid" + back = prev + prev.icon_state = "armsy_end" + prev.icon_living = "armsy_end" + prev.front = src + prev.AIStatus = AI_OFF + current_stacks = 0 + + adjustBruteLoss(-maxHealth * 0.5, FALSE) + adjustFireLoss(-maxHealth * 0.5 ,FALSE) + + +/mob/living/simple_animal/hostile/eldritch/armsy/Shoot(atom/targeted_atom) + target = targeted_atom + AttackingTarget() + + +/mob/living/simple_animal/hostile/eldritch/armsy/AttackingTarget() + if(istype(target,/obj/item/bodypart/r_arm) || istype(target,/obj/item/bodypart/l_arm)) + qdel(target) + heal() + return + if(target == back || target == front) + return + if(back) + back.target = target + back.AttackingTarget() + if(!Adjacent(target)) + return + do_attack_animation(target) + //have fun + //if(istype(target,/turf/closed/wall)) + //var/turf/closed/wall = target + //wall.ScrapeAway() + + + if(iscarbon(target)) + var/mob/living/carbon/C = target + if(HAS_TRAIT(C, TRAIT_NODISMEMBER)) + return + var/list/parts = list() + for(var/X in C.bodyparts) + var/obj/item/bodypart/bodypart = X + if(bodypart.body_part != HEAD && bodypart.body_part != CHEST) + if(bodypart.dismemberable) + parts += bodypart + if(length(parts) && prob(10)) + var/obj/item/bodypart/bodypart = pick(parts) + bodypart.dismember() + + return ..() + +/mob/living/simple_animal/hostile/eldritch/armsy/prime + name = "Lord of the Night" + real_name = "Master of Decay" + maxHealth = 400 + health = 400 + melee_damage_lower = 20 + melee_damage_upper = 25 + +/mob/living/simple_animal/hostile/eldritch/armsy/prime/Initialize(mapload,spawn_more = TRUE,len = 9) + . = ..() + var/matrix/matrix_transformation = matrix() + matrix_transformation.Scale(1.4,1.4) + transform = matrix_transformation + +/mob/living/simple_animal/hostile/eldritch/armsy/primeproc/heal() + if(health == maxHealth) + if(back) + back.heal() + return + else + current_stacks++ + if(current_stacks >= stacks_to_grow) + var/mob/living/simple_animal/hostile/eldritch/armsy/prev = new type(drop_location(),spawn_more = FALSE) + icon_state = "armsy_mid" + icon_living = "armsy_mid" + back = prev + prev.icon_state = "armsy_end" + prev.icon_living = "armsy_end" + prev.front = src + prev.AIStatus = AI_OFF + current_stacks = 0 + var/matrix/matrix_transformation = matrix() + matrix_transformation.Scale(1.4,1.4) + transform = matrix_transformation + + adjustBruteLoss(-maxHealth * 0.5, FALSE) + adjustFireLoss(-maxHealth * 0.5 ,FALSE) + + +/mob/living/simple_animal/hostile/eldritch/rust_spirit + name = "Rust Walker" + real_name = "Rusty" + desc = "Incomprehensible abomination actively seeping life out of it's surrounding." + icon_state = "rust_walker_s" + status_flags = CANPUSH + icon_living = "rust_walker_s" + maxHealth = 75 + health = 75 + melee_damage_lower = 15 + melee_damage_upper = 20 + sight = SEE_TURFS + spells_to_add = list(/obj/effect/proc_holder/spell/aoe_turf/rust_conversion/small,/obj/effect/proc_holder/spell/aimed/rust_wave/short) + +/mob/living/simple_animal/hostile/eldritch/rust_spirit/setDir(newdir, ismousemovement) + . = ..() + if(newdir == NORTH) + icon_state = "rust_walker_n" + else if(newdir == SOUTH) + icon_state = "rust_walker_s" + update_icon() + +/mob/living/simple_animal/hostile/eldritch/rust_spirit/Moved() + . = ..() + playsound(src, 'sound/effects/footstep/rustystep1.ogg', 100, TRUE) + +/mob/living/simple_animal/hostile/eldritch/rust_spirit/Life() + if(stat == DEAD) + return ..() + var/turf/T = get_turf(src) + if(istype(T,/turf/open/floor/plating/rust)) + adjustBruteLoss(-3, FALSE) + adjustFireLoss(-3, FALSE) + return ..() + +/mob/living/simple_animal/hostile/eldritch/ash_spirit + name = "Ash Man" + real_name = "Ashy" + desc = "Incomprehensible abomination actively seeping life out of it's surrounding." + icon_state = "ash_walker" + status_flags = CANPUSH + icon_living = "ash_walker" + maxHealth = 75 + health = 75 + melee_damage_lower = 15 + melee_damage_upper = 20 + sight = SEE_TURFS + spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash,/obj/effect/proc_holder/spell/pointed/cleave/long,/obj/effect/proc_holder/spell/aoe_turf/fire_cascade) + +/mob/living/simple_animal/hostile/eldritch/stalker + name = "Flesh Stalker" + real_name = "Flesh Stalker" + desc = "Abomination made from severed limbs." + icon_state = "stalker" + status_flags = CANPUSH + icon_living = "stalker" + maxHealth = 150 + health = 150 + melee_damage_lower = 15 + melee_damage_upper = 20 + sight = SEE_MOBS + spells_to_add = list(/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/ash,/obj/effect/proc_holder/spell/targeted/shapeshift/eldritch,/obj/effect/proc_holder/spell/targeted/emplosion/eldritch) diff --git a/code/modules/mob/living/simple_animal/friendly/bumbles.dm b/code/modules/mob/living/simple_animal/friendly/bumbles.dm index 2d236a4327..3707aa33f8 100644 --- a/code/modules/mob/living/simple_animal/friendly/bumbles.dm +++ b/code/modules/mob/living/simple_animal/friendly/bumbles.dm @@ -30,6 +30,7 @@ verb_yell = "buzzes intensely" emote_see = list("buzzes.", "makes a loud buzz.", "rolls several times.", "buzzes happily.") speak_chance = 1 + unique_name = TRUE /mob/living/simple_animal/pet/bumbles/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 5f7ff198e2..c21875d1db 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -115,13 +115,14 @@ Read_Memory() . = ..() -/mob/living/simple_animal/pet/cat/Runtime/Life() +/mob/living/simple_animal/pet/cat/Runtime/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!cats_deployed && SSticker.current_state >= GAME_STATE_SETTING_UP) Deploy_The_Cats() if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) Write_Memory() memory_saved = TRUE - ..() /mob/living/simple_animal/pet/cat/Runtime/make_babies() var/mob/baby = ..() @@ -177,7 +178,9 @@ gold_core_spawnable = NO_SPAWN unique_pet = TRUE -/mob/living/simple_animal/pet/cat/Life() +/mob/living/simple_animal/pet/cat/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!stat && !buckled && !client) if(prob(1)) emote("me", EMOTE_VISIBLE, pick("stretches out for a belly rub.", "wags its tail.", "lies down.")) @@ -269,8 +272,9 @@ to_chat(src, "Your name is now \"new_name\"!") name = new_name -/mob/living/simple_animal/pet/cat/cak/Life() - ..() +/mob/living/simple_animal/pet/cat/cak/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(stat) return if(health < maxHealth) @@ -279,7 +283,7 @@ if(!D.is_decorated) D.decorate_donut() -/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L) +/mob/living/simple_animal/pet/cat/cak/on_attack_hand(mob/living/L) . = ..() if(.) //the attack was blocked return diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm index e00e0648b5..7f3693f622 100644 --- a/code/modules/mob/living/simple_animal/friendly/crab.dm +++ b/code/modules/mob/living/simple_animal/friendly/crab.dm @@ -27,8 +27,9 @@ var/obj/item/inventory_mask gold_core_spawnable = FRIENDLY_SPAWN -/mob/living/simple_animal/crab/Life() - ..() +/mob/living/simple_animal/crab/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return //CRAB movement if(!ckey && !stat) if(isturf(loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc. diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 57a4ecc5c9..0584995583 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -366,11 +366,12 @@ RemoveElement(/datum/element/mob_holder, held_icon) AddElement(/datum/element/mob_holder, "old_corgi") -/mob/living/simple_animal/pet/dog/corgi/Ian/Life() +/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) Write_Memory(FALSE) memory_saved = TRUE - ..() /mob/living/simple_animal/pet/dog/corgi/Ian/death() if(!memory_saved) @@ -419,8 +420,9 @@ fdel(json_file) WRITE_FILE(json_file, json_encode(file_data)) -/mob/living/simple_animal/pet/dog/corgi/Ian/Life() - ..() +/mob/living/simple_animal/pet/dog/corgi/Ian/BiologicalLife() + if(!(. = ..())) + return //Feeding, chasing food, FOOOOODDDD if(!stat && CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) && !buckled) @@ -490,8 +492,9 @@ nofur = TRUE unique_pet = TRUE -/mob/living/simple_animal/pet/dog/corgi/narsie/Life() - ..() +/mob/living/simple_animal/pet/dog/corgi/narsie/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return for(var/mob/living/simple_animal/pet/P in range(1, src)) if(P != src && prob(5)) visible_message("[src] devours [P]!", \ @@ -615,8 +618,9 @@ return ..() -/mob/living/simple_animal/pet/dog/corgi/Lisa/Life() - ..() +/mob/living/simple_animal/pet/dog/corgi/Lisa/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return make_babies() @@ -628,8 +632,9 @@ setDir(i) sleep(1) -/mob/living/simple_animal/pet/dog/pug/Life() - ..() +/mob/living/simple_animal/pet/dog/pug/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!stat && CHECK_MULTIPLE_BITFIELDS(mobility_flags, MOBILITY_STAND|MOBILITY_MOVE) && !buckled) if(prob(1)) emote("me", EMOTE_VISIBLE, pick("chases its tail.")) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm index 6e89f045da..8034e3c5e5 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/inventory.dm @@ -19,7 +19,7 @@ return 0 -/mob/living/simple_animal/drone/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) +/mob/living/simple_animal/drone/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) switch(slot) if(SLOT_HEAD) if(head) 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 8c73665b9b..51e7ee6c03 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -46,9 +46,10 @@ udder = null return ..() -/mob/living/simple_animal/hostile/retaliate/goat/Life() - . = ..() - if(.) +/mob/living/simple_animal/hostile/retaliate/goat/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(stat == CONSCIOUS) //chance to go crazy and start wacking stuff if(!enemies.len && prob(1)) Retaliate() @@ -57,7 +58,6 @@ enemies = list() LoseTarget() src.visible_message("[src] calms down.") - if(stat == CONSCIOUS) udder.generateMilk(milk_reagent) eat_plants() if(!pulledby) @@ -160,12 +160,13 @@ else return ..() -/mob/living/simple_animal/cow/Life() - . = ..() +/mob/living/simple_animal/cow/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(stat == CONSCIOUS) udder.generateMilk(milk_reagent) -/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M) +/mob/living/simple_animal/cow/on_attack_hand(mob/living/carbon/M) if(!stat && M.a_intent == INTENT_DISARM && icon_state != icon_dead) M.visible_message("[M] tips over [src].", "You tip over [src].") @@ -191,13 +192,22 @@ else ..() +//a cow that produces a random reagent in its udder +/mob/living/simple_animal/cow/random + name = "strange cow" + desc = "Something seems off about the milk this cow is producing." + +/mob/living/simple_animal/cow/random/Initialize() + milk_reagent = get_random_reagent_id() //this has a blacklist so don't worry about romerol cows, etc + ..() + //Wisdom cow, speaks and bestows great wisdoms /mob/living/simple_animal/cow/wisdom name = "wisdom cow" desc = "Known for its wisdom, shares it with all" butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/wisdomcow = 1) //truly the best meat gold_core_spawnable = FALSE - speak_chance = 30 //the cow is eager to share its wisdom! + speak_chance = 10 //the cow is eager to share its wisdom! //but is wise enough to not lag the server too bad milk_reagent = /datum/reagent/medicine/liquid_wisdom /mob/living/simple_animal/cow/wisdom/Initialize() @@ -244,9 +254,8 @@ pixel_x = rand(-6, 6) pixel_y = rand(0, 10) -/mob/living/simple_animal/chick/Life() - . =..() - if(!.) +/mob/living/simple_animal/chick/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if(!stat && !ckey) amount_grown += rand(1,2) @@ -254,8 +263,9 @@ new /mob/living/simple_animal/chicken(src.loc) qdel(src) -/mob/living/simple_animal/chick/holo/Life() - ..() +/mob/living/simple_animal/chick/holo/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return amount_grown = 0 /mob/living/simple_animal/chicken @@ -328,9 +338,8 @@ else ..() -/mob/living/simple_animal/chicken/Life() - . =..() - if(!.) +/mob/living/simple_animal/chicken/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if((!stat && prob(3) && eggsleft > 0) && egg_type) visible_message("[src] [pick(layMessage)]") @@ -403,9 +412,8 @@ . = ..() ++kiwi_count -/mob/living/simple_animal/kiwi/Life() - . =..() - if(!.) +/mob/living/simple_animal/kiwi/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if((!stat && prob(3) && eggsleft > 0) && egg_type) visible_message("[src] [pick(layMessage)]") @@ -478,9 +486,8 @@ pixel_x = rand(-6, 6) pixel_y = rand(0, 10) -/mob/living/simple_animal/babyKiwi/Life() - . =..() - if(!.) +/mob/living/simple_animal/babyKiwi/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if(!stat && !ckey) amount_grown += rand(1,2) @@ -546,4 +553,4 @@ health = 75 maxHealth = 75 blood_volume = BLOOD_VOLUME_NORMAL - footstep_type = FOOTSTEP_MOB_SHOE \ No newline at end of file + footstep_type = FOOTSTEP_MOB_SHOE diff --git a/code/modules/mob/living/simple_animal/friendly/gondola.dm b/code/modules/mob/living/simple_animal/friendly/gondola.dm index 0cfea3548b..e29cbb8062 100644 --- a/code/modules/mob/living/simple_animal/friendly/gondola.dm +++ b/code/modules/mob/living/simple_animal/friendly/gondola.dm @@ -58,7 +58,7 @@ eyes_overlay.pixel_y = -8 moustache_overlay.pixel_y = -8 - cut_overlays(TRUE) + cut_overlays() add_overlay(body_overlay) add_overlay(eyes_overlay) add_overlay(moustache_overlay) diff --git a/code/modules/mob/living/simple_animal/friendly/panda.dm b/code/modules/mob/living/simple_animal/friendly/panda.dm index 7e523fea83..b3e8c1438f 100644 --- a/code/modules/mob/living/simple_animal/friendly/panda.dm +++ b/code/modules/mob/living/simple_animal/friendly/panda.dm @@ -21,3 +21,6 @@ response_harm_simple = "kick" gold_core_spawnable = FRIENDLY_SPAWN footstep_type = FOOTSTEP_MOB_CLAW + +/mob/living/simple_animal/pet/redpanda/stinky + name = "Stinky" diff --git a/code/modules/mob/living/simple_animal/friendly/plushie.dm b/code/modules/mob/living/simple_animal/friendly/plushie.dm index d992c704f5..ff95e8fe86 100644 --- a/code/modules/mob/living/simple_animal/friendly/plushie.dm +++ b/code/modules/mob/living/simple_animal/friendly/plushie.dm @@ -72,8 +72,8 @@ qdel(src) //low regen over time -/mob/living/simple_animal/pet/plushie/Life() - if(stat) +/mob/living/simple_animal/pet/plushie/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if(health < maxHealth) heal_overall_damage(5) //Decent life regen, they're not able to hurt anyone so this shouldn't be an issue (butterbear for reference has 10 regen) diff --git a/code/modules/mob/living/simple_animal/friendly/possum.dm b/code/modules/mob/living/simple_animal/friendly/possum.dm new file mode 100644 index 0000000000..71fdbd1465 --- /dev/null +++ b/code/modules/mob/living/simple_animal/friendly/possum.dm @@ -0,0 +1,37 @@ +/mob/living/simple_animal/opossum + name = "opossum" + desc = "It's an opossum, a small scavenging marsupial." + icon_state = "possum" + icon_living = "possum" + icon_dead = "possum_dead" + speak = list("Hiss!","HISS!","Hissss?") + speak_emote = list("hisses") + emote_hear = list("hisses.") + emote_see = list("runs in a circle.", "shakes.") + speak_chance = 1 + turns_per_move = 3 + blood_volume = 250 + see_in_dark = 5 + maxHealth = 15 + health = 15 + butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1) + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + response_harm_continuous = "stamps on" + response_harm_simple = "stamp" + density = FALSE + ventcrawler = VENTCRAWLER_ALWAYS + pass_flags = PASSTABLE | PASSMOB + mob_size = MOB_SIZE_TINY + mob_biotypes = MOB_ORGANIC|MOB_BEAST + gold_core_spawnable = FRIENDLY_SPAWN + +/mob/living/simple_animal/opossum/poppy + name = "Poppy the Safety Possum" + desc = "Safety first!" + icon_state = "poppypossum" + icon_living = "poppypossum" + icon_dead = "poppypossum_dead" + butcher_results = list(/obj/item/clothing/head/hardhat = 1) diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 9d94992747..7abecc7c81 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -8,7 +8,6 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians name = "Guardian Spirit" real_name = "Guardian Spirit" desc = "A mysterious being that stands by its charge, ever vigilant." - threat = 5 speak_emote = list("hisses") gender = NEUTER mob_biotypes = NONE @@ -60,11 +59,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/magic_fluff_string = "You draw the Coder, symbolizing bugs and errors. This shouldn't happen! Submit a bug report!" var/tech_fluff_string = "BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!" var/carp_fluff_string = "CARP CARP CARP SOME SORT OF HORRIFIC BUG BLAME THE CODERS CARP CARP CARP" + /// sigh, fine. + var/datum/song/holoparasite/music_datum /mob/living/simple_animal/hostile/guardian/Initialize(mapload, theme) GLOB.parasites += src updatetheme(theme) - + music_datum = new(src, get_allowed_instrument_ids()) . = ..() /mob/living/simple_animal/hostile/guardian/med_hud_set_health() @@ -84,8 +85,16 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians /mob/living/simple_animal/hostile/guardian/Destroy() GLOB.parasites -= src + QDEL_NULL(music_datum) return ..() +/mob/living/simple_animal/hostile/guardian/verb/music_interact() + set name = "Access Internal Synthesizer" + set desc = "Access your internal musical synthesizer" + set category = "IC" + + music_datum.ui_interact(src) + /mob/living/simple_animal/hostile/guardian/proc/updatetheme(theme) //update the guardian's theme if(!theme) theme = pick("magic", "tech", "carp") @@ -160,7 +169,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians to_chat(src, "Your new name [new_name] anchors itself in your mind.") fully_replace_character_name(null, new_name) -/mob/living/simple_animal/hostile/guardian/Life() //Dies if the summoner dies +/mob/living/simple_animal/hostile/guardian/PhysicalLife() //Dies if the summoner dies . = ..() update_health_hud() //we need to update all of our health displays to match our summoner and we can't practically give the summoner a hook to do it med_hud_set_health() @@ -638,6 +647,12 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians /obj/item/guardiancreator/tech/choose/dextrous possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support") +/obj/item/guardiancreator/tech/choose/nukie // lacks support and protector as encouraging nukies to play turtle isnt fun and dextrous is epic + possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Ranged", "Standard") + +/obj/item/guardiancreator/tech/choose/nukie/check_uplink_validity() + return !used + /obj/item/paper/guides/antag/guardian name = "Holoparasite Guide" icon_state = "paper_words" @@ -677,7 +692,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
    Charger: Moves extremely fast, does medium damage on attack, and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding.

    - Dexterous: Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item.
    + Dextrous: Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item.

    Explosive: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.

    @@ -691,6 +706,29 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
    "} +/obj/item/paper/guides/antag/guardian/nukie + name = "Guardian Guide" + info = {"A list of Guardian Types
    + +
    + Assassin: Does medium damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth.
    +
    + Chaos: Ignites enemies on touch and causes them to hallucinate all nearby people as the guardian. Automatically extinguishes the user if they catch on fire.
    +
    + Charger: Moves extremely fast, does medium damage on attack, and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding.
    +
    + Dextrous: Does low damage on attack, but is capable of holding items and storing a single item within it. It will drop items held in its hands when it recalls, but it will retain the stored item.
    +
    + Explosive: High damage resist and medium power attack that may explosively teleport targets. Can turn any object, including objects too large to pick up, into a bomb, dealing explosive damage to the next person to touch it. The object will return to normal after the trap is triggered or after a delay.
    +
    + Lightning: Attacks apply lightning chains to targets. Has a lightning chain to the user. Lightning chains shock everything near them, doing constant damage.
    +
    + Ranged: Has two modes. Ranged; which fires a constant stream of weak, armor-ignoring projectiles. Scout; Cannot attack, but can move through walls and is quite hard to see. Can lay surveillance snares, which alert it when crossed, in either mode.
    +
    + Standard: Devastating close combat attacks and high damage resist. Can smash through weak walls.
    +
    +"} + /obj/item/storage/box/syndie_kit/guardian name = "holoparasite injector kit" @@ -699,6 +737,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians new /obj/item/guardiancreator/tech/choose/traitor(src) new /obj/item/paper/guides/antag/guardian(src) +/obj/item/storage/box/syndie_kit/nukieguardian + name = "holoparasite injector kit" + +/obj/item/storage/box/syndie_kit/nukieguardian/PopulateContents() + new /obj/item/guardiancreator/tech/choose/nukie(src) + new /obj/item/paper/guides/antag/guardian/nukie(src) + /obj/item/guardiancreator/carp name = "holocarp fishsticks" desc = "Using the power of Carp'sie, you can catch a carp from byond the veil of Carpthulu, and bind it to your fleshy flesh form." 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 e82d6cd16a..885f907997 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/assassin.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/assassin.dm @@ -19,8 +19,9 @@ . = ..() stealthcooldown = 0 -/mob/living/simple_animal/hostile/guardian/assassin/Life() - . = ..() +/mob/living/simple_animal/hostile/guardian/assassin/PhysicalLife() + if(!(. = ..())) + return updatestealthalert() if(loc == summoner && toggle) ToggleMode(0) 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 c60e43ff01..0b4952aa9e 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -11,8 +11,9 @@ var/charging = 0 var/obj/screen/alert/chargealert -/mob/living/simple_animal/hostile/guardian/charger/Life() - . = ..() +/mob/living/simple_animal/hostile/guardian/charger/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(ranged_cooldown <= world.time) if(!chargealert) chargealert = throw_alert("charge", /obj/screen/alert/cancharge) diff --git a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm index b4865c4337..a1850fabca 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/dextrous.dm @@ -50,7 +50,7 @@ return 1 return 0 -/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE) +/mob/living/simple_animal/hostile/guardian/dextrous/can_equip(obj/item/I, slot, disable_warning = FALSE, bypass_equip_delay_self = FALSE, clothing_check = FALSE, list/return_warning) switch(slot) if(SLOT_GENERC_DEXTROUS_STORAGE) if(internal_storage) diff --git a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm index f1916b412a..26e5d791f3 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/explosive.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/explosive.dm @@ -36,61 +36,21 @@ return if(isobj(A) && Adjacent(A)) if(bomb_cooldown <= world.time && !stat) - var/obj/guardian_bomb/B = new /obj/guardian_bomb(get_turf(A)) + var/datum/component/killerqueen/K = A.AddComponent(/datum/component/killerqueen, EXPLODE_HEAVY, CALLBACK(src, .proc/on_explode), CALLBACK(src, .proc/on_failure), \ + examine_message = "It glows with a strange light!") + QDEL_IN(K, 1 MINUTES) to_chat(src, "Success! Bomb armed!") bomb_cooldown = world.time + 200 - B.spawner = src - B.disguise(A) else to_chat(src, "Your powers are on cooldown! You must wait 20 seconds between bombs.") -/obj/guardian_bomb - name = "bomb" - desc = "You shouldn't be seeing this!" - var/obj/stored_obj - var/mob/living/simple_animal/hostile/guardian/spawner +/mob/living/simple_animal/hostile/guardian/bomb/proc/on_explode(atom/bomb, atom/victim) + if((victim == src) || (victim == summoner) || (hasmatchingsummoner(victim))) + to_chat(victim, "[src] glows with a strange light, and you don't touch it.") + return FALSE + to_chat(src, "One of your explosive traps caught [victim]!") + to_chat(victim, "[bomb] was boobytrapped!") + return TRUE - -/obj/guardian_bomb/proc/disguise(obj/A) - A.forceMove(src) - stored_obj = A - opacity = A.opacity - anchored = A.anchored - density = A.density - appearance = A.appearance - addtimer(CALLBACK(src, .proc/disable), 600) - -/obj/guardian_bomb/proc/disable() - stored_obj.forceMove(get_turf(src)) - to_chat(spawner, "Failure! Your trap didn't catch anyone this time.") - qdel(src) - -/obj/guardian_bomb/proc/detonate(mob/living/user) - if(isliving(user)) - if(user != spawner && user != spawner.summoner && !spawner.hasmatchingsummoner(user)) - to_chat(user, "[src] was boobytrapped!") - to_chat(spawner, "Success! Your trap caught [user]") - var/turf/T = get_turf(src) - stored_obj.forceMove(T) - playsound(T,'sound/effects/explosion2.ogg', 200, 1) - new /obj/effect/temp_visual/explosion(T) - user.ex_act(EXPLODE_HEAVY) - qdel(src) - else - to_chat(user, "[src] glows with a strange light, and you don't touch it.") - -/obj/guardian_bomb/Bump(atom/A) - detonate(A) - ..() - -/obj/guardian_bomb/attackby(mob/living/user) - detonate(user) - -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/guardian_bomb/attack_hand(mob/living/user) - detonate(user) - -/obj/guardian_bomb/examine(mob/user) - . = stored_obj.examine(user) - if(get_dist(user,src)<=2) - . += "It glows with a strange light!" +/mob/living/simple_animal/hostile/guardian/bomb/proc/on_failure(atom/bomb) + to_chat(src, "Failure! Your trap didn't catch anyone this time.") 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 97003a53e2..a05cd517fb 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm @@ -13,8 +13,9 @@ tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online." carp_fluff_string = "CARP CARP CARP! You caught one! OH GOD, EVERYTHING'S ON FIRE. Except you and the fish." -/mob/living/simple_animal/hostile/guardian/fire/Life() - . = ..() +/mob/living/simple_animal/hostile/guardian/fire/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(summoner) summoner.ExtinguishMob() summoner.adjust_fire_stacks(-20) diff --git a/code/modules/mob/living/simple_animal/guardian/types/standard.dm b/code/modules/mob/living/simple_animal/guardian/types/standard.dm index 2285167df5..d7970daa29 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/standard.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/standard.dm @@ -3,7 +3,7 @@ melee_damage_lower = 20 melee_damage_upper = 20 obj_damage = 80 - next_move_modifier = 0.5 //attacks 50% faster + action_cooldown_mod = 0.5 //attacks 50% faster environment_smash = ENVIRONMENT_SMASH_WALLS playstyle_string = "As a standard type you have no special abilities, but take half damage and have powerful attack capable of smashing through walls." magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated." diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm index 7120ab6d0a..86467624b5 100644 --- a/code/modules/mob/living/simple_animal/hostile/alien.dm +++ b/code/modules/mob/living/simple_animal/hostile/alien.dm @@ -7,7 +7,6 @@ icon_dead = "alienh_dead" icon_gib = "syndicate_gib" gender = FEMALE - threat = 1 response_help_continuous = "pokes" response_help_simple = "poke" response_disarm_continuous = "shoves" @@ -69,7 +68,6 @@ icon_state = "aliens" icon_living = "aliens" icon_dead = "aliens_dead" - threat = 3 health = 150 maxHealth = 150 melee_damage_lower = 15 @@ -87,7 +85,6 @@ icon_living = "alienq" icon_dead = "alienq_dead" pixel_x = -16 - threat = 8 health = 250 maxHealth = 250 melee_damage_lower = 15 @@ -167,7 +164,6 @@ name = "lusty xenomorph maid" melee_damage_lower = 0 melee_damage_upper = 0 - threat = -1 a_intent = INTENT_HELP friendly_verb_continuous = "caresses" friendly_verb_simple = "caress" diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 0e864a1e37..1be90a07f8 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -2,7 +2,6 @@ /mob/living/simple_animal/hostile/bear name = "space bear" desc = "You don't need to be faster than a space bear, you just need to outrun your crewmates." - threat = 1 icon_state = "bear" icon_living = "bear" icon_dead = "bear_dead" @@ -29,8 +28,11 @@ var/armored = FALSE obj_damage = 60 - melee_damage_lower = 20 - melee_damage_upper = 30 + melee_damage_lower = 15 // i know it's like half what it used to be, but bears cause bleeding like crazy now so it works out + melee_damage_upper = 15 + wound_bonus = -5 + bare_wound_bonus = 10 // BEAR wound bonus am i right + sharpness = SHARP_EDGED attack_verb_continuous = "claws" attack_verb_simple = "claw" attack_sound = 'sound/weapons/bladeslice.ogg' @@ -69,8 +71,9 @@ icon_dead = "combatbear_dead" faction = list("russian") butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1, /obj/item/bear_armor = 1) - melee_damage_lower = 25 - melee_damage_upper = 35 + melee_damage_lower = 18 + melee_damage_upper = 20 + wound_bonus = 0 armour_penetration = 20 health = 120 maxHealth = 120 @@ -99,8 +102,9 @@ A.maxHealth += 60 A.health += 60 A.armour_penetration += 20 - A.melee_damage_lower += 5 + A.melee_damage_lower += 3 A.melee_damage_upper += 5 + A.wound_bonus += 5 A.update_icons() to_chat(user, "You strap the armor plating to [A] and sharpen [A.p_their()] claws with the nail filer. This was a great idea.") qdel(src) @@ -125,13 +129,13 @@ mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Seve 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. +/mob/living/simple_animal/hostile/bear/butter/BiologicalLife(seconds, times_fired) //Heals butter bear really fast when he takes damage. if(stat) return if(health < maxHealth) heal_overall_damage(10) //Fast life regen, makes it hard for you to get eaten to death. -/mob/living/simple_animal/hostile/bear/butter/attack_hand(mob/living/L) //Borrowed code from Cak, feeds people if they hit you. More nutriment but less vitamin to represent BUTTER. +/mob/living/simple_animal/hostile/bear/butter/on_attack_hand(mob/living/L) //Borrowed code from Cak, feeds people if they hit you. More nutriment but less vitamin to represent BUTTER. ..() if(L.a_intent == INTENT_HARM && L.reagents && !stat) L.reagents.add_reagent(/datum/reagent/consumable/nutriment, 1) diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 5f3d4f11c1..0a3cde3ef8 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -16,7 +16,6 @@ icon_state = "" icon_living = "" icon = 'icons/mob/bees.dmi' - threat = 0.3 gender = FEMALE speak_emote = list("buzzes") emote_hear = list("buzzes") 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 cde63adffd..b4d60af198 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm @@ -1,7 +1,6 @@ /mob/living/simple_animal/hostile/boss name = "A Perfectly Generic Boss Placeholder" desc = "" - threat = 10 robust_searching = TRUE stat_attack = UNCONSCIOUS status_flags = NONE diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index a56a8dcc29..51a646f668 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -7,7 +7,6 @@ icon_living = "carp" icon_dead = "carp_dead" icon_gib = "carp_gib" - threat = 0.1 mob_biotypes = MOB_ORGANIC|MOB_BEAST speak_chance = 0 turns_per_move = 5 @@ -47,8 +46,9 @@ if(regen_amount) regen_cooldown = world.time + REGENERATION_DELAY -/mob/living/simple_animal/hostile/carp/Life() - . = ..() +/mob/living/simple_animal/hostile/carp/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(regen_amount && regen_cooldown < world.time) heal_overall_damage(regen_amount) @@ -73,7 +73,6 @@ icon_living = "megacarp" icon_dead = "megacarp_dead" icon_gib = "megacarp_gib" - threat = 3 regen_amount = 6 maxHealth = 30 @@ -97,7 +96,6 @@ name = "Cayenne" desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot." gender = FEMALE - threat = 5 regen_amount = 8 speak_emote = list("squeaks") 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 48266e3e76..9b50587b3d 100644 --- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm @@ -1,7 +1,6 @@ /mob/living/simple_animal/hostile/dark_wizard name = "Dark Wizard" desc = "Killing amateurs since the dawn of times." - threat = 3 icon = 'icons/mob/simple_human.dmi' icon_state = "dark_wizard" icon_living = "dark_wizard" diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm index 4f8d2fef6c..b44a2502ef 100644 --- a/code/modules/mob/living/simple_animal/hostile/faithless.dm +++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm @@ -4,7 +4,6 @@ icon_state = "faithless" icon_living = "faithless" icon_dead = "faithless_dead" - threat = 1 mob_biotypes = MOB_ORGANIC|MOB_HUMANOID gender = MALE speak_chance = 0 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 a253ecfd96..a8799f4e8c 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -17,7 +17,6 @@ //basic spider mob, these generally guard nests /mob/living/simple_animal/hostile/poison/giant_spider - threat = 1 name = "giant spider" desc = "Furry and black, it makes you shudder to look at it. This one has deep red eyes." icon_state = "guard" 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 f48eef083b..ec0b7acd07 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -9,7 +9,6 @@ icon_state = "crawling" icon_living = "crawling" icon_dead = "dead" - threat = 0.5 mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 80 maxHealth = 220 diff --git a/code/modules/mob/living/simple_animal/hostile/headcrab.dm b/code/modules/mob/living/simple_animal/hostile/headcrab.dm index 501534237a..ac53ff794b 100644 --- a/code/modules/mob/living/simple_animal/hostile/headcrab.dm +++ b/code/modules/mob/living/simple_animal/hostile/headcrab.dm @@ -6,7 +6,6 @@ icon_state = "headcrab" icon_living = "headcrab" icon_dead = "headcrab_dead" - threat = 1 gender = NEUTER health = 50 maxHealth = 50 diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index e8991df358..186fe36a10 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -3,7 +3,6 @@ stop_automated_movement_when_pulled = 0 obj_damage = 40 environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Bitflags. Set to ENVIRONMENT_SMASH_STRUCTURES to break closets,tables,racks, etc; ENVIRONMENT_SMASH_WALLS for walls; ENVIRONMENT_SMASH_RWALLS for rwalls - var/threat = 0 // for dynamic var/atom/target var/ranged = FALSE var/rapid = 0 //How many shots per volley. @@ -67,11 +66,10 @@ foes = null return ..() -/mob/living/simple_animal/hostile/Life() - . = ..() - if(!.) //dead +/mob/living/simple_animal/hostile/BiologicalLife(seconds, times_fired) + if(!(. = ..())) walk(src, 0) //stops walking - return 0 + return /mob/living/simple_animal/hostile/handle_automated_action() if(AIStatus == AI_OFF) @@ -524,9 +522,9 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega if(ranged && ranged_cooldown <= world.time) target = A OpenFire(A) - ..() - - + DelayNextAction() + . = ..() + return TRUE ////// AI Status /////// /mob/living/simple_animal/hostile/proc/AICanContinue(var/list/possible_targets) @@ -601,6 +599,3 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega . += M else if (M.loc.type in hostile_machines) . += M.loc - -/mob/living/simple_animal/hostile/proc/threat() - return threat diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index cab87010ef..f561f0d43c 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -23,13 +23,12 @@ 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() - ..() +/mob/living/simple_animal/hostile/illusion/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(world.time > life_span) death() - /mob/living/simple_animal/hostile/illusion/proc/Copy_Parent(mob/living/original, life = 50, hp = 100, damage = 0, replicate = 0 ) appearance = original.appearance parent_mob = original 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 574811c968..362432b2af 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -11,7 +11,6 @@ icon_living = "leaper" icon_dead = "leaper_dead" mob_biotypes = MOB_ORGANIC|MOB_BEAST - threat = 2 maxHealth = 300 health = 300 ranged = TRUE @@ -81,7 +80,7 @@ /obj/structure/leaper_bubble/Initialize() . = ..() - float(on = TRUE) + INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE) QDEL_IN(src, 100) /obj/structure/leaper_bubble/Destroy() @@ -136,7 +135,7 @@ target = A if(!isturf(loc)) return - if(next_move > world.time) + if(!CheckActionCooldown()) return if(hopping) return @@ -166,8 +165,9 @@ if(!hopping) Hop() -/mob/living/simple_animal/hostile/jungle/leaper/Life() - . = ..() +/mob/living/simple_animal/hostile/jungle/leaper/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return update_icons() /mob/living/simple_animal/hostile/jungle/leaper/adjustHealth(amount, updating_health = TRUE, forced = FALSE) @@ -197,7 +197,7 @@ hopping = TRUE density = FALSE pass_flags |= PASSMOB - notransform = TRUE + mob_transforming = TRUE var/turf/new_turf = locate((target.x + rand(-3,3)),(target.y + rand(-3,3)),target.z) if(player_hop) new_turf = get_turf(target) @@ -209,7 +209,7 @@ /mob/living/simple_animal/hostile/jungle/leaper/proc/FinishHop() density = TRUE - notransform = FALSE + mob_transforming = FALSE pass_flags &= ~PASSMOB hopping = FALSE playsound(src.loc, 'sound/effects/meteorimpact.ogg', 100, 1) @@ -220,7 +220,7 @@ /mob/living/simple_animal/hostile/jungle/leaper/proc/BellyFlop() var/turf/new_turf = get_turf(target) hopping = TRUE - notransform = TRUE + mob_transforming = TRUE new /obj/effect/temp_visual/leaper_crush(new_turf) addtimer(CALLBACK(src, .proc/BellyFlopHop, new_turf), 30) @@ -231,7 +231,7 @@ /mob/living/simple_animal/hostile/jungle/leaper/proc/Crush() hopping = FALSE density = TRUE - notransform = FALSE + mob_transforming = FALSE playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1) for(var/mob/living/L in orange(1, src)) L.adjustBruteLoss(35) 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 40274c0029..31303bd7f1 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 @@ -8,7 +8,6 @@ icon_living = "arachnid" icon_dead = "arachnid_dead" mob_biotypes = MOB_ORGANIC|MOB_BUG - threat = 2 melee_damage_lower = 30 melee_damage_upper = 30 maxHealth = 300 @@ -27,8 +26,9 @@ footstep_type = FOOTSTEP_MOB_CLAW -/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life() - ..() +/mob/living/simple_animal/hostile/jungle/mega_arachnid/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(target && ranged_cooldown > world.time && iscarbon(target)) var/mob/living/carbon/C = target if(!C.legcuffed && C.health < 50) @@ -40,7 +40,6 @@ minimum_distance = 0 alpha = 255 - /mob/living/simple_animal/hostile/jungle/mega_arachnid/Aggro() ..() alpha = 255 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 6efa0cf468..2d964f5721 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm @@ -14,7 +14,6 @@ icon_living = "mook" icon_dead = "mook_dead" mob_biotypes = MOB_ORGANIC|MOB_HUMANOID - threat = 0.5 pixel_x = -16 maxHealth = 45 health = 45 diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm index 0521afa9e9..7565a686bf 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm @@ -13,7 +13,6 @@ icon_state = "seedling" icon_living = "seedling" icon_dead = "seedling_dead" - threat = 0.5 maxHealth = 100 health = 100 melee_damage_lower = 30 diff --git a/code/modules/mob/living/simple_animal/hostile/killertomato.dm b/code/modules/mob/living/simple_animal/hostile/killertomato.dm index 9cb65d7c30..b86d5d87fc 100644 --- a/code/modules/mob/living/simple_animal/hostile/killertomato.dm +++ b/code/modules/mob/living/simple_animal/hostile/killertomato.dm @@ -5,7 +5,6 @@ icon_living = "tomato" icon_dead = "tomato_dead" gender = NEUTER - threat = 0.3 speak_chance = 0 turns_per_move = 5 maxHealth = 30 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 3ef4ef9be9..2a5f279386 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 @@ -23,7 +23,6 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner name = "blood-drunk miner" desc = "A miner destined to wander forever, engaged in an endless hunt." - threat = 15 health = 900 maxHealth = 900 icon_state = "miner" @@ -70,7 +69,7 @@ Difficulty: Medium /obj/item/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user) target.add_stun_absorption("miner", 10, INFINITY) - ..() + . = ..() target.stun_absorption -= "miner" /obj/item/projectile/kinetic/miner @@ -86,8 +85,8 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE) var/adjustment_amount = amount * 0.1 - if(world.time + adjustment_amount > next_move) - changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly + if(world.time + adjustment_amount > next_action) + DelayNextAction(adjustment_amount, considered_action = FALSE, flush = TRUE) //attacking it interrupts it attacking, but only briefly . = ..() /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/death() @@ -109,7 +108,7 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget() if(QDELETED(target)) return - if(next_move > world.time || !Adjacent(target)) //some cheating + if(!CheckActionCooldown() || !Adjacent(target)) //some cheating INVOKE_ASYNC(src, .proc/quick_attack_loop) return face_atom(target) @@ -125,8 +124,8 @@ Difficulty: Medium adjustHealth(-(L.maxHealth * 0.5)) L.gib() return TRUE - changeNext_move(CLICK_CD_MELEE) - miner_saw.melee_attack_chain(src, target) + miner_saw.melee_attack_chain(src, target, null, ATTACK_IGNORE_CLICKDELAY) + FlushCurrentAction() if(guidance) adjustHealth(-2) transform_weapon() @@ -161,19 +160,19 @@ Difficulty: Medium face_atom(target) new /obj/effect/temp_visual/dir_setting/firing_effect(loc, dir) Shoot(target) - changeNext_move(CLICK_CD_RANGE) + DelayNextAction(CLICK_CD_RANGE, flush = TRUE) //I'm still of the belief that this entire proc needs to be wiped from existence. // do not take my touching of it to be endorsement of it. ~mso /mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop() - while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep. + while(!QDELETED(target) && !CheckActionCooldown()) //this is done this way because next_move can change to be sooner while we sleep. stoplag(1) - sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about + sleep((next_action - world.time) * 1.5) //but don't ask me what the fuck this is about if(QDELETED(target)) return - if(dashing || next_move > world.time || !Adjacent(target)) - if(dashing && next_move <= world.time) - next_move = world.time + 1 + if(dashing || !CheckActionCooldown() || !Adjacent(target)) + if(dashing && next_action <= world.time) + SetNextAction(1, considered_action = FALSE, immediate = FALSE, flush = TRUE) INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again. return AttackingTarget() 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 fe6c2290c4..519d6402e6 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -26,7 +26,6 @@ Difficulty: Hard /mob/living/simple_animal/hostile/megafauna/bubblegum name = "bubblegum" desc = "In what passes for a hierarchy among slaughter demons, this one is king." - threat = 35 health = 2500 maxHealth = 2500 attack_verb_continuous = "rends" @@ -65,8 +64,9 @@ Difficulty: Hard desc = "You're not quite sure how a signal can be bloody." invisibility = 100 -/mob/living/simple_animal/hostile/megafauna/bubblegum/Life() - ..() +/mob/living/simple_animal/hostile/megafauna/bubblegum/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return move_to_delay = clamp(round((health/maxHealth) * 10), 3, 10) /mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire() 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 04ff9413aa..883ad39261 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -24,7 +24,6 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus name = "colossus" desc = "A monstrous creature protected by heavy shielding." - threat = 40 health = 2500 maxHealth = 2500 attack_verb_continuous = "judges" @@ -385,10 +384,7 @@ Difficulty: Very Hard if(isliving(speaker)) ActivationReaction(speaker, ACTIVATE_SPEECH) -/obj/machinery/anomalous_crystal/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/anomalous_crystal/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) ActivationReaction(user, ACTIVATE_TOUCH) /obj/machinery/anomalous_crystal/attackby(obj/item/I, mob/user, params) @@ -606,7 +602,6 @@ Difficulty: Very Hard icon_state = "lightgeist" icon_living = "lightgeist" icon_dead = "butterfly_dead" - threat = -0.7 turns_per_move = 1 response_help_continuous = "waves away" response_help_simple = "wave away" @@ -731,7 +726,7 @@ Difficulty: Very Hard /obj/structure/closet/stasis/Entered(atom/A) if(isliving(A) && holder_animal) var/mob/living/L = A - L.notransform = 1 + L.mob_transforming = 1 ADD_TRAIT(L, TRAIT_MUTE, STASIS_MUTE) L.status_flags |= GODMODE L.mind.transfer_to(holder_animal) @@ -744,7 +739,7 @@ Difficulty: Very Hard for(var/mob/living/L in src) REMOVE_TRAIT(L, TRAIT_MUTE, STASIS_MUTE) L.status_flags &= ~GODMODE - L.notransform = 0 + L.mob_transforming = 0 if(holder_animal) holder_animal.mind.transfer_to(L) L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession) 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 062a4c9a43..4dfd4561d6 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -4,6 +4,11 @@ #define SWOOP_DAMAGEABLE 1 #define SWOOP_INVULNERABLE 2 +///used whenever the drake generates a hotspot +#define DRAKE_FIRE_TEMP 500 +///used whenever the drake generates a hotspot +#define DRAKE_FIRE_EXPOSURE 50 + /* ASH DRAKE @@ -33,7 +38,6 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/dragon name = "ash drake" desc = "Guardians of the necropolis." - threat = 30 health = 2500 maxHealth = 2500 spacewalk = TRUE @@ -148,7 +152,7 @@ Difficulty: Medium break range-- new /obj/effect/hotspot(J) - J.hotspot_expose(700,50,1) + J.hotspot_expose(DRAKE_FIRE_TEMP, DRAKE_FIRE_EXPOSURE, 1) for(var/mob/living/L in J.contents - hit_things) if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon)) continue @@ -404,7 +408,7 @@ Difficulty: Medium if(istype(T, /turf/closed)) break new /obj/effect/hotspot(T) - T.hotspot_expose(700,50,1) + T.hotspot_expose(DRAKE_FIRE_TEMP,DRAKE_FIRE_EXPOSURE,1) for(var/mob/living/L in T.contents) if(L in hit_list || L == source) continue 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 4ade831f95..bd3a6e8232 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -37,7 +37,6 @@ Difficulty: Normal /mob/living/simple_animal/hostile/megafauna/hierophant name = "hierophant" desc = "A massive metal club that hangs in the air as though waiting. It'll make you dance to its beat." - threat = 30 health = 2500 maxHealth = 2500 attack_verb_continuous = "clubs" @@ -88,9 +87,10 @@ Difficulty: Normal /mob/living/simple_animal/hostile/megafauna/hierophant/spawn_crusher_loot() new /obj/item/crusher_trophy/vortex_talisman(get_turf(spawned_beacon)) -/mob/living/simple_animal/hostile/megafauna/hierophant/Life() - . = ..() - if(. && spawned_beacon && !QDELETED(spawned_beacon) && !client) +/mob/living/simple_animal/hostile/megafauna/hierophant/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(spawned_beacon && !QDELETED(spawned_beacon) && !client) if(target || loc == spawned_beacon.loc) timeout_time = initial(timeout_time) else @@ -642,7 +642,7 @@ Difficulty: Normal to_chat(L, "You're struck by a [name]!") var/limb_to_hit = L.get_bodypart(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!") - L.apply_damage(damage, BURN, limb_to_hit, armor) + L.apply_damage(damage, BURN, limb_to_hit, armor, wound_bonus=CANT_WOUND) if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L //mobs find and damage you... if(H.stat == CONSCIOUS && !H.target && H.AIStatus != AI_OFF && !H.client) @@ -661,7 +661,7 @@ Difficulty: Normal continue to_chat(M.occupant, "Your [M.name] is struck by a [name]!") playsound(M,'sound/weapons/sear.ogg', 50, 1, -4) - M.take_damage(damage, BURN, 0, 0) + M.take_damage(damage, BURN, 0, 0, null, 50) /obj/effect/hierophant name = "hierophant beacon" 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 4da8a90b23..795184bad5 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -18,7 +18,6 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/legion name = "Legion" - threat = 30 health = 800 maxHealth = 800 spacewalk = TRUE @@ -52,6 +51,8 @@ Difficulty: Medium elimination = 1 appearance_flags = 0 mouse_opacity = MOUSE_OPACITY_ICON + wound_bonus = -40 + bare_wound_bonus = 20 /mob/living/simple_animal/hostile/megafauna/legion/Initialize() . = ..() 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 02e1b47c95..7009f13f36 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -159,7 +159,7 @@ var/client/C = L.client SSmedals.UnlockMedal("Boss [BOSS_KILL_MEDAL]", C) SSmedals.UnlockMedal("[medaltype] [BOSS_KILL_MEDAL]", C) - if(crusher_kill && istype(L.get_active_held_item(), /obj/item/twohanded/kinetic_crusher)) + if(crusher_kill && istype(L.get_active_held_item(), /obj/item/kinetic_crusher)) SSmedals.UnlockMedal("[medaltype] [BOSS_KILL_MEDAL_CRUSHER]", C) SSmedals.SetScore(BOSS_SCORE, C, 1) SSmedals.SetScore(score_type, C, 1) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index 50c6025378..db6468d1b5 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -73,14 +73,13 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa step(R, ddir) //Step the swarmers, instead of spawning them there, incase the turf is solid -/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/Life() - . = ..() - if(.) - var/createtype = GetUncappedAISwarmerType() - if(createtype && world.time > swarmer_spawn_cooldown && GLOB.AISwarmers.len < (GetTotalAISwarmerCap()*0.5)) - swarmer_spawn_cooldown = world.time + swarmer_spawn_cooldown_amt - new createtype(loc) - +/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + var/createtype = GetUncappedAISwarmerType() + if(createtype && world.time > swarmer_spawn_cooldown && GLOB.AISwarmers.len < (GetTotalAISwarmerCap()*0.5)) + swarmer_spawn_cooldown = world.time + swarmer_spawn_cooldown_amt + new createtype(loc) /mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/adjustHealth(amount, updating_health = TRUE, forced = FALSE) . = ..() 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 ed189f052d..869f29951b 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm @@ -129,7 +129,7 @@ Difficulty: Hard to_chat(L, "[src]'s ground slam shockwave sends you flying!") var/turf/thrownat = get_ranged_target_turf_direct(src, L, 8, rand(-10, 10)) L.throw_at(thrownat, 8, 2, src, TRUE) //, force = MOVE_FORCE_OVERPOWERING, gentle = TRUE) - L.apply_damage(20, BRUTE) + L.apply_damage(20, BRUTE, wound_bonus=CANT_WOUND) shake_camera(L, 2, 1) all_turfs -= T sleep(delay) diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm index 5afe109550..c2d05e43d9 100644 --- a/code/modules/mob/living/simple_animal/hostile/mimic.dm +++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm @@ -118,8 +118,9 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca overlay_googly_eyes = FALSE CopyObject(copy, creator, destroy_original) -/mob/living/simple_animal/hostile/mimic/copy/Life() - ..() +/mob/living/simple_animal/hostile/mimic/copy/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(idledamage && !target && !ckey) //Objects eventually revert to normal if no one is around to terrorize adjustBruteLoss(1) for(var/mob/living/M in contents) //a fix for animated statues from the flesh to stone spell 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 306011dc80..61be1f6287 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 @@ -8,7 +8,6 @@ icon_aggro = "Basilisk_alert" icon_dead = "Basilisk_dead" icon_gib = "syndicate_gib" - threat = 4 mob_biotypes = MOB_ORGANIC|MOB_BEAST move_to_delay = 20 projectiletype = /obj/item/projectile/temp/basilisk @@ -88,8 +87,9 @@ 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() - . = ..() +/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(stat == CONSCIOUS) consume_bait() 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 c4f78b6e26..ed056c2ad9 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 @@ -10,7 +10,6 @@ move_to_delay = 5 vision_range = 20 aggro_vision_range = 20 - threat = 1 maxHealth = 40 //easy to kill, but oh, will you be seeing a lot of them. health = 40 melee_damage_lower = 10 @@ -105,7 +104,7 @@ IGNORE_PROC_IF_NOT_TARGET(attack_slime) /mob/living/simple_animal/hostile/asteroid/curseblob/attacked_by(obj/item/I, mob/living/L, attackchain_flags = NONE, damage_multiplier = 1) if(L != set_target) - L.changeNext_move(I.click_delay) //pre_attacked_by not called + I.ApplyAttackCooldown(L, src) return return ..() 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 81b541dc7b..e3edd171c0 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 @@ -11,7 +11,6 @@ robust_searching = TRUE ranged_ignores_vision = TRUE ranged = TRUE - threat = 5 obj_damage = 5 vision_range = 6 aggro_vision_range = 18 @@ -148,7 +147,7 @@ While using this makes the system rely on OnFire, it still gives options for tim desc = "You're not quite sure how a signal can be menacing." invisibility = 100 -/obj/structure/elite_tumor/attack_hand(mob/user) +/obj/structure/elite_tumor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(ishuman(user)) switch(activity) 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 e662f4e525..d9f3cfba3d 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 @@ -25,7 +25,6 @@ icon_aggro = "broodmother" icon_dead = "egg_sac" icon_gib = "syndicate_gib" - threat = 10 maxHealth = 800 health = 800 melee_damage_lower = 30 @@ -97,9 +96,8 @@ if(CALL_CHILDREN) call_children() -/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Life() - . = ..() - if(!.) //Checks if they are dead as a rock. +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if(health < maxHealth * 0.5 && rand_tent < world.time) rand_tent = world.time + 30 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 78b24acfb0..fce5b636e4 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 @@ -24,7 +24,6 @@ icon_aggro = "herald" icon_dead = "herald_dying" icon_gib = "syndicate_gib" - threat = 10 maxHealth = 800 health = 800 melee_damage_lower = 20 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 31f925fb2b..15ed0135fe 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 @@ -24,7 +24,6 @@ icon_aggro = "legionnaire" icon_dead = "legionnaire_dead" icon_gib = "syndicate_gib" - threat = 10 maxHealth = 800 health = 800 melee_damage_lower = 30 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 ebbf032859..7995e4d20f 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 @@ -24,7 +24,6 @@ icon_aggro = "pandora" icon_dead = "pandora_dead" icon_gib = "syndicate_gib" - threat = 10 maxHealth = 800 health = 800 melee_damage_lower = 15 @@ -95,8 +94,9 @@ if(AOE_SQUARES) aoe_squares(target) -/mob/living/simple_animal/hostile/asteroid/elite/pandora/Life() - . = ..() +/mob/living/simple_animal/hostile/asteroid/elite/pandora/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(health >= maxHealth * 0.5) cooldown_time = 20 return 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 4a3497055a..3845c6f406 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 @@ -8,7 +8,6 @@ icon_aggro = "Goldgrub_alert" icon_dead = "Goldgrub_dead" icon_gib = "syndicate_gib" - threat = 0.2 mob_biotypes = MOB_ORGANIC|MOB_BEAST vision_range = 2 aggro_vision_range = 9 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 a61f1924c8..fa67fd8e3b 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 @@ -10,7 +10,6 @@ icon_gib = "syndicate_gib" mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_OPAQUE - threat = 2 move_to_delay = 10 ranged = 1 ranged_cooldown_time = 60 @@ -39,8 +38,9 @@ footstep_type = FOOTSTEP_MOB_HEAVY -/mob/living/simple_animal/hostile/asteroid/goliath/Life() - . = ..() +/mob/living/simple_animal/hostile/asteroid/goliath/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return handle_preattack() /mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack() @@ -129,9 +129,8 @@ var/turf/last_location var/tentacle_recheck_cooldown = 100 -/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient/Life() - . = ..() - if(!.) // dead +/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return if(isturf(loc)) if(!LAZYLEN(cached_tentacle_turfs) || loc != last_location || tentacle_recheck_cooldown <= world.time) @@ -201,6 +200,8 @@ L.Stun(75) L.adjustBruteLoss(rand(15,20)) // Less stun more harm latched = TRUE + for(var/obj/mecha/M in loc) + M.take_damage(20, BRUTE, null, null, null, 25) if(!latched) retract() else 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 c9e650531c..0ccc4525c7 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 @@ -44,7 +44,7 @@ childtype = list(/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck = 45, /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen = 55) wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/, /obj/item/bodypart, /obj/item/organ/appendix, /obj/item/organ/ears, /obj/item/organ/eyes, /obj/item/organ/heart, /obj/item/organ/liver, \ - /obj/item/organ/lungs, /obj/item/organ/stomach, /obj/item/organ/tongue) // So we dont eat implants or brains. Still can eat robotic stuff thats subtyped of base line but thats a issue for a nother day. + /obj/item/organ/lungs, /obj/item/organ/stomach, /obj/item/organ/tongue) // So we dont eat implants or brains. Still can eat robotic stuff thats subtyped of base line but thats a issue for another day. var/obj/item/udder/gutlunch/udder = null /mob/living/simple_animal/hostile/asteroid/gutlunch/Initialize() @@ -114,8 +114,9 @@ name = "guthen" gender = FEMALE -/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen/Life() - ..() +/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(udder.reagents.total_volume == udder.reagents.maximum_volume) //Only breed when we're full. make_babies() 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 d21e39ef54..11ce4f9214 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 @@ -9,7 +9,6 @@ icon_gib = "syndicate_gib" mob_biotypes = MOB_ORGANIC mouse_opacity = MOUSE_OPACITY_OPAQUE - threat = 4 move_to_delay = 14 ranged = 1 vision_range = 4 @@ -196,12 +195,13 @@ swarming = TRUE var/can_infest_dead = FALSE -/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/Life() +/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(isturf(loc)) for(var/mob/living/carbon/human/H in view(src,1)) //Only for corpse right next to/on same tile if(H.stat == UNCONSCIOUS || (can_infest_dead && H.stat == DEAD)) infest(H) - ..() /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H) visible_message("[name] burrows into the flesh of [H]!") @@ -240,7 +240,6 @@ icon_state = "legion" icon_living = "legion" icon_dead = "legion" - threat = 5 health = 450 maxHealth = 450 melee_damage_lower = 20 @@ -323,7 +322,7 @@ suit = /obj/item/clothing/suit/armor/bone gloves = /obj/item/clothing/gloves/bracer if(prob(5)) - back = pickweight(list(/obj/item/twohanded/bonespear = 3, /obj/item/twohanded/fireaxe/boneaxe = 2)) + back = pickweight(list(/obj/item/spear/bonespear = 3, /obj/item/fireaxe/boneaxe = 2)) if(prob(10)) belt = /obj/item/storage/belt/mining/primitive if(prob(30)) @@ -410,7 +409,7 @@ if(prob(5)) gloves = /obj/item/clothing/gloves/color/yellow if(prob(10)) - back = /obj/item/twohanded/spear + back = /obj/item/spear 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) 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 66241e3d75..d40cd8636c 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 @@ -62,9 +62,10 @@ SLEEP_CHECK_DEATH(8) return ..() -/mob/living/simple_animal/hostile/asteroid/ice_demon/Life() - . = ..() - if(!. || target) +/mob/living/simple_animal/hostile/asteroid/ice_demon/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(target) return adjustHealth(-maxHealth*0.025) 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 b62fb4a665..7214fd71e0 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 @@ -43,9 +43,10 @@ var/list/burn_turfs = getline(src, T) - get_turf(src) dragon_fire_line(src, burn_turfs) -/mob/living/simple_animal/hostile/asteroid/ice_whelp/Life() - . = ..() - if(!. || target) +/mob/living/simple_animal/hostile/asteroid/ice_whelp/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(target) return adjustHealth(-maxHealth*0.025) 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 ac2ce37d3f..de9464cc16 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 @@ -44,9 +44,10 @@ aggressive_message_said = TRUE rapid_melee = 2 -/mob/living/simple_animal/hostile/asteroid/polarbear/Life() - . = ..() - if(!. || target) +/mob/living/simple_animal/hostile/asteroid/polarbear/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(target) return adjustHealth(-maxHealth*0.025) aggressive_message_said = FALSE 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 013a75be75..8c4db48434 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 @@ -51,9 +51,10 @@ retreat_message_said = TRUE retreat_distance = 30 -/mob/living/simple_animal/hostile/asteroid/wolf/Life() - . = ..() - if(!. || target) +/mob/living/simple_animal/hostile/asteroid/wolf/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return + if(target) return adjustHealth(-maxHealth*0.025) retreat_message_said = FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index 1b13200729..9101430ccc 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -48,8 +48,9 @@ else . += "It looks like it's been roughed up." -/mob/living/simple_animal/hostile/mushroom/Life() - ..() +/mob/living/simple_animal/hostile/mushroom/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!stat)//Mushrooms slowly regenerate if conscious, for people who want to save them from being eaten adjustBruteLoss(-2) @@ -169,7 +170,7 @@ Bruise() ..() -/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M) +/mob/living/simple_animal/hostile/mushroom/on_attack_hand(mob/living/carbon/human/M) . = ..() if(.) // the attack was blocked return diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm index ca5d047326..92f331071a 100644 --- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm +++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm @@ -10,7 +10,6 @@ obj_damage = 100 melee_damage_lower = 25 melee_damage_upper = 50 - threat = 2 attack_verb_continuous = "slashes" attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' @@ -46,8 +45,9 @@ var/chosen_sound = pick(migo_sounds) playsound(src, chosen_sound, 100, TRUE) -/mob/living/simple_animal/hostile/netherworld/migo/Life() - ..() +/mob/living/simple_animal/hostile/netherworld/migo/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(stat) return if(prob(10)) @@ -85,7 +85,7 @@ .=..() START_PROCESSING(SSprocessing, src) -/obj/structure/spawner/nether/attack_hand(mob/user) +/obj/structure/spawner/nether/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) user.visible_message("[user] is violently pulled into the link!", \ "Touching the portal, you are quickly pulled through into a world of unimaginable horror!") contents.Add(user) diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm index 0544ddc676..74e37bea21 100644 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm @@ -10,7 +10,6 @@ turns_per_move = 5 response_help_continuous = "pushes" response_help_simple = "push" - threat = 3 speed = 0 maxHealth = 115 health = 115 diff --git a/code/modules/mob/living/simple_animal/hostile/regalrat.dm b/code/modules/mob/living/simple_animal/hostile/regalrat.dm index e21514b37e..77b2d4268a 100644 --- a/code/modules/mob/living/simple_animal/hostile/regalrat.dm +++ b/code/modules/mob/living/simple_animal/hostile/regalrat.dm @@ -184,6 +184,7 @@ /mob/living/simple_animal/hostile/rat/Initialize() . = ..() SSmobs.cheeserats += src + AddComponent(/datum/component/swarming) /mob/living/simple_animal/hostile/rat/Destroy() SSmobs.cheeserats -= src 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 35f2817028..dec2159dc0 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm @@ -37,6 +37,10 @@ var/banana_type = /obj/item/grown/bananapeel var/attack_reagent +/mob/living/simple_animal/hostile/retaliate/clown/Initialize(mapload) + . = ..() + faction |= "clown" + /mob/living/simple_animal/hostile/retaliate/clown/handle_temperature_damage() if(bodytemperature < minbodytemp) adjustBruteLoss(10) @@ -47,12 +51,13 @@ else clear_alert("temp") -/mob/living/simple_animal/hostile/retaliate/clown/attack_hand(mob/living/carbon/human/M) +/mob/living/simple_animal/hostile/retaliate/clown/on_attack_hand(mob/living/carbon/human/M) ..() playsound(src.loc, 'sound/items/bikehorn.ogg', 50, TRUE) -/mob/living/simple_animal/hostile/retaliate/clown/Life() - . = ..() +/mob/living/simple_animal/hostile/retaliate/clown/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(banana_time && banana_time < world.time) var/turf/T = get_turf(src) var/list/adjacent = T.GetAtmosAdjacentTurfs(1) diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm index f7a46658c4..e9879f38ec 100644 --- a/code/modules/mob/living/simple_animal/hostile/russian.dm +++ b/code/modules/mob/living/simple_animal/hostile/russian.dm @@ -10,7 +10,6 @@ speak_chance = 0 turns_per_move = 5 speed = 0 - threat = 1 maxHealth = 100 health = 100 harm_intent_damage = 5 diff --git a/code/modules/mob/living/simple_animal/hostile/sharks.dm b/code/modules/mob/living/simple_animal/hostile/sharks.dm index 1263a23d26..af61149130 100644 --- a/code/modules/mob/living/simple_animal/hostile/sharks.dm +++ b/code/modules/mob/living/simple_animal/hostile/sharks.dm @@ -19,7 +19,6 @@ response_harm_continuous = "kicks" response_harm_simple = "kick" speed = 0 - threat = 1 maxHealth = 75 health = 75 harm_intent_damage = 18 diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm index f3138a773c..ebacf1edef 100644 --- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm +++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm @@ -11,7 +11,6 @@ speak_emote = list("rattles") emote_see = list("rattles") a_intent = INTENT_HARM - threat = 0.5 maxHealth = 40 blood_volume = 0 health = 40 @@ -53,7 +52,7 @@ melee_damage_upper = 20 deathmessage = "collapses into a pile of bones, its gear falling to the floor!" loot = list(/obj/effect/decal/remains/human, - /obj/item/twohanded/spear, + /obj/item/spear, /obj/item/clothing/shoes/winterboots, /obj/item/clothing/suit/hooded/wintercoat) @@ -64,7 +63,6 @@ icon_state = "templar" icon_living = "templar" icon_dead = "templar_dead" - threat = 1.5 maxHealth = 150 health = 150 weather_immunities = list("snow") @@ -98,7 +96,6 @@ icon_state = "plasma_miner" icon_living = "plasma_miner" icon_dead = "plasma_miner" - threat = 2 maxHealth = 150 health = 150 harm_intent_damage = 10 @@ -116,7 +113,6 @@ icon_state = "plasma_miner_tool" icon_living = "plasma_miner_tool" icon_dead = "plasma_miner_tool" - threat = 3 maxHealth = 185 health = 185 harm_intent_damage = 15 diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 23304a2ef3..600d60eb4d 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -10,7 +10,6 @@ gender = NEUTER a_intent = INTENT_HARM mob_biotypes = MOB_HUMANOID - threat = 3 response_help_continuous = "touches" response_help_simple = "touch" response_disarm_continuous = "pushes" @@ -82,8 +81,9 @@ return 0 return ..() -/mob/living/simple_animal/hostile/statue/Life() - ..() +/mob/living/simple_animal/hostile/statue/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!client && target) // If we have a target and we're AI controlled var/mob/watching = can_be_seen() // If they're not our target diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm index 226af952b1..6eeeabc877 100644 --- a/code/modules/mob/living/simple_animal/hostile/stickman.dm +++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm @@ -5,7 +5,6 @@ icon_living = "stickman" icon_dead = "stickman_dead" icon_gib = "syndicate_gib" - threat = 0.5 mob_biotypes = MOB_HUMANOID gender = MALE speak_chance = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 9a362b680d..103868e1d3 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -25,7 +25,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 5 - threat = 1 speed = 0 stat_attack = UNCONSCIOUS robust_searching = 1 @@ -77,6 +76,9 @@ /mob/living/simple_animal/hostile/syndicate/melee melee_damage_lower = 15 melee_damage_upper = 15 + wound_bonus = -10 + bare_wound_bonus = 20 + sharpness = SHARP_EDGED icon_state = "syndicate_knife" icon_living = "syndicate_knife" loot = list(/obj/effect/gibspawner/human) diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm index 3aa3c9e566..46a5a8ec68 100644 --- a/code/modules/mob/living/simple_animal/hostile/tree.dm +++ b/code/modules/mob/living/simple_animal/hostile/tree.dm @@ -7,7 +7,6 @@ icon_dead = "pine_1" icon_gib = "pine_1" gender = NEUTER - threat = 1 speak_chance = 0 turns_per_move = 5 response_help_continuous = "brushes" @@ -44,16 +43,17 @@ gold_core_spawnable = HOSTILE_SPAWN del_on_death = 1 -/mob/living/simple_animal/hostile/tree/Life() - ..() +/mob/living/simple_animal/hostile/tree/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(isopenturf(loc)) var/turf/open/T = src.loc - if(T.air && T.air.gases[/datum/gas/carbon_dioxide]) - var/co2 = T.air.gases[/datum/gas/carbon_dioxide] + if(T.air) + var/co2 = T.air.get_moles(/datum/gas/carbon_dioxide) if(co2 > 0) if(prob(25)) var/amt = min(co2, 9) - T.air.gases[/datum/gas/carbon_dioxide] -= amt + T.air.adjust_moles(/datum/gas/carbon_dioxide, -amt) T.atmos_spawn_air("o2=[amt]") /mob/living/simple_animal/hostile/tree/AttackingTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm index 5111b0b180..fdb088934c 100644 --- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm +++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm @@ -100,8 +100,9 @@ /mob/living/simple_animal/hostile/venus_human_trap/ghost_playable playable_plant = TRUE //For admins that want to buss some harmless plants -/mob/living/simple_animal/hostile/venus_human_trap/Life() - . = ..() +/mob/living/simple_animal/hostile/venus_human_trap/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return pull_vines() /mob/living/simple_animal/hostile/venus_human_trap/AttackingTarget() diff --git a/code/modules/mob/living/simple_animal/hostile/wizard.dm b/code/modules/mob/living/simple_animal/hostile/wizard.dm index 57fb6f829d..b3523fc42c 100644 --- a/code/modules/mob/living/simple_animal/hostile/wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/wizard.dm @@ -8,7 +8,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 turns_per_move = 3 - threat = 3 speed = 0 maxHealth = 100 health = 100 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 5c881a7b0d..bce1a01c8a 100644 --- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm +++ b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm @@ -11,7 +11,6 @@ mob_biotypes = MOB_ORGANIC|MOB_BEAST mouse_opacity = MOUSE_OPACITY_ICON move_to_delay = 5 - threat = 1 friendly_verb_continuous = "floats near" friendly_verb_simple = "float near" speak_emote = list("puffs") @@ -47,12 +46,13 @@ QDEL_NULL(E) return ..() -/mob/living/simple_animal/hostile/asteroid/fugu/Life() +/mob/living/simple_animal/hostile/asteroid/fugu/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!wumbo) inflate_cooldown = max((inflate_cooldown - 1), 0) if(target && AIStatus == AI_ON) E.Activate() - ..() /mob/living/simple_animal/hostile/asteroid/fugu/adjustHealth(amount, updating_health = TRUE, forced = FALSE) if(!forced && wumbo) diff --git a/code/modules/mob/living/simple_animal/hostile/zombie.dm b/code/modules/mob/living/simple_animal/hostile/zombie.dm index 6e4cbac022..1217084ce3 100644 --- a/code/modules/mob/living/simple_animal/hostile/zombie.dm +++ b/code/modules/mob/living/simple_animal/hostile/zombie.dm @@ -7,7 +7,6 @@ mob_biotypes = MOB_ORGANIC|MOB_HUMANOID speak_chance = 0 stat_attack = UNCONSCIOUS //braains - threat = 1 maxHealth = 100 health = 100 harm_intent_damage = 5 diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index e8d6411c01..4fcb1ed5bf 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -271,7 +271,7 @@ * Attack responces */ //Humans, monkeys, aliens -/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M) +/mob/living/simple_animal/parrot/on_attack_hand(mob/living/carbon/M) ..() if(client) return @@ -357,9 +357,9 @@ /* * AI - Not really intelligent, but I'm calling it AI anyway. */ -/mob/living/simple_animal/parrot/Life() - ..() - +/mob/living/simple_animal/parrot/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return //Sprite update for when a parrot gets pulled if(pulledby && !stat && parrot_state != PARROT_WANDER) if(buckled) @@ -369,8 +369,6 @@ parrot_state = PARROT_WANDER pixel_x = initial(pixel_x) pixel_y = initial(pixel_y) - return - //-----SPEECH /* Parrot speech mimickry! @@ -911,11 +909,12 @@ if(. && !client && prob(1) && prob(1)) //Only the one true bird may speak across dimensions. world.TgsTargetedChatBroadcast("A stray squawk is heard... \"[message]\"", FALSE) -/mob/living/simple_animal/parrot/Poly/Life() +/mob/living/simple_animal/parrot/Poly/BiologicalLife(seconds, times_fired) + if(!(. = ..())) + return if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved) Write_Memory(FALSE) memory_saved = TRUE - ..() /mob/living/simple_animal/parrot/Poly/death(gibbed) if(!memory_saved) diff --git a/code/modules/mob/living/simple_animal/pickle.dm b/code/modules/mob/living/simple_animal/pickle.dm new file mode 100644 index 0000000000..78c524fed9 --- /dev/null +++ b/code/modules/mob/living/simple_animal/pickle.dm @@ -0,0 +1,32 @@ +//funniest shit i've ever seen + +/mob/living/simple_animal/pickle + name = "pickle" + desc = "It's a pickle. It might just be the funniest thing you have ever seen." + health = 100 + maxHealth = 100 + icon = 'icons/mob/32x64.dmi' + icon_state = "pickle" + deathmessage = "The pickle implodes into its own existential dread and disappears!" + friendly_verb_continuous = "tickles" + friendly_verb_simple = "tickle" + del_on_death = TRUE + var/mob/living/original_body + +/mob/living/simple_animal/pickle/UnarmedAttack(atom/A) + ..() //we want the tickle emote to go before the laugh + if(ismob(A)) + var/mob/laugher = A + laugher.emote("laugh") + +/mob/living/simple_animal/pickle/death() + if(original_body) + original_body.adjustOrganLoss(ORGAN_SLOT_BRAIN, 200) //to be fair, you have to have a very high iq to understand- + original_body.forceMove(get_turf(src)) + if(mind) + mind.transfer_to(original_body) + ..() + +/mob/living/simple_animal/pickle/wabbajack_act() //restore users name before its used on the new mob + if(original_body) + real_name = original_body.real_name diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 3491fd2f95..be0338a60e 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -140,6 +140,15 @@ ///What kind of footstep this mob should have. Null if it shouldn't have any. var/footstep_type + //How much wounding power it has + var/wound_bonus = CANT_WOUND + //How much bare wounding power it has + var/bare_wound_bonus = 0 + //If the attacks from this are sharp + var/sharpness = SHARP_NONE + //Generic flags + var/simple_mob_flags = NONE + /mob/living/simple_animal/Initialize() . = ..() GLOB.simple_animals[AIStatus] += src @@ -252,14 +261,11 @@ if(isturf(src.loc) && isopenturf(src.loc)) var/turf/open/ST = src.loc if(ST.air) - var/ST_gases = ST.air.gases - var/tox = ST_gases[/datum/gas/plasma] - var/oxy = ST_gases[/datum/gas/oxygen] - var/n2 = ST_gases[/datum/gas/nitrogen] - var/co2 = ST_gases[/datum/gas/carbon_dioxide] - - GAS_GARBAGE_COLLECT(ST.air.gases) + var/tox = ST.air.get_moles(/datum/gas/plasma) + var/oxy = ST.air.get_moles(/datum/gas/oxygen) + var/n2 = ST.air.get_moles(/datum/gas/nitrogen) + var/co2 = ST.air.get_moles(/datum/gas/carbon_dioxide) if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"]) . = FALSE @@ -537,17 +543,13 @@ mode() /mob/living/simple_animal/swap_hand(hand_index) + . = ..() + if(!.) + return if(!dextrous) - return ..() + return if(!hand_index) hand_index = (active_hand_index % held_items.len)+1 - var/obj/item/held_item = get_active_held_item() - if(held_item) - if(istype(held_item, /obj/item/twohanded)) - var/obj/item/twohanded/T = held_item - if(T.wielded == 1) - to_chat(usr, "Your other hand is too busy holding the [T.name].") - return var/oindex = active_hand_index active_hand_index = hand_index if(hud_used) diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 6e8c79c3d0..3513a916f9 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -7,19 +7,17 @@ var/SStun = 0 // stun variable -/mob/living/simple_animal/slime/Life() - set invisibility = 0 - if (notransform) +/mob/living/simple_animal/slime/BiologicalLife(seconds, times_fired) + if(!(. = ..())) return - if(..()) - if(buckled) - handle_feeding() - if(!stat) // Slimes in stasis don't lose nutrition, don't change mood and don't respond to speech - handle_nutrition() - handle_targets() - if (!ckey) - handle_mood() - handle_speech() + if(buckled) + handle_feeding() + if(!stat) // Slimes in stasis don't lose nutrition, don't change mood and don't respond to speech + handle_nutrition() + handle_targets() + if (!ckey) + handle_mood() + handle_speech() // Unlike most of the simple animals, slimes support UNCONSCIOUS /mob/living/simple_animal/slime/update_stat() @@ -130,9 +128,7 @@ Tempstun = 0 if(stat != DEAD) - var/bz_percentage =0 - if(environment.gases[/datum/gas/bz]) - bz_percentage = environment.gases[/datum/gas/bz] / environment.total_moles() + var/bz_percentage = environment.total_moles() ? (environment.get_moles(/datum/gas/bz) / environment.total_moles()) : 0 var/stasis = (bz_percentage >= 0.05 && bodytemperature < (T0C + 100)) || force_stasis if(stat == CONSCIOUS && stasis) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index f7876b3516..1bdd988694 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -296,7 +296,7 @@ discipline_slime(user) return ..() -/mob/living/simple_animal/slime/attack_hand(mob/living/carbon/human/M) +/mob/living/simple_animal/slime/on_attack_hand(mob/living/carbon/human/M) if(buckled) M.do_attack_animation(src, ATTACK_EFFECT_DISARM) if(buckled == M) @@ -356,7 +356,7 @@ attacked += 10 if(prob(25)) user.do_attack_animation(src) - user.changeNext_move(CLICK_CD_MELEE) + W.ApplyAttackCooldown(user, src) to_chat(user, "[W] passes right through [src]!") return if(Discipline && prob(50)) // wow, buddy, why am I getting attacked?? diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 0029300936..87fd0cf609 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -500,6 +500,15 @@ S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) return S +///////////////////////////////// OFF BALANCE/SHOVIES //////////////////////// +/mob/living/proc/ShoveOffBalance(amount) + var/datum/status_effect/off_balance/B = has_status_effect(STATUS_EFFECT_OFF_BALANCE) + if(B) + B.duration = max(world.time + amount, B.duration) + else if(amount > 0) + B = apply_status_effect(STATUS_EFFECT_OFF_BALANCE, amount) + return B + ///////////////////////////////// FROZEN ///////////////////////////////////// /mob/living/proc/IsFrozen() diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm index 36a596f42e..6661d0ccea 100644 --- a/code/modules/mob/living/ventcrawling.dm +++ b/code/modules/mob/living/ventcrawling.dm @@ -19,8 +19,11 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list( to_chat(src, "You can't vent crawl while you're restrained!") return if(has_buckled_mobs()) - to_chat(src, "You can't vent crawl with other creatures on you!") - return + // attempt once + unbuckle_all_mobs() + if(has_buckled_mobs()) + to_chat(src, "You can't vent crawl with other creatures on you!") + return if(buckled) to_chat(src, "You can't vent crawl while buckled!") return diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index b7546becd8..31bfb5621f 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -13,9 +13,7 @@ hud_used.show_hud(hud_used.hud_version) hud_used.update_ui_style(ui_style2icon(client.prefs.UI_style)) - next_move = 1 - - ..() + . = ..() reset_perspective(loc) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 4c692e7175..358eff7a47 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -66,11 +66,10 @@ var/datum/gas_mixture/environment = loc.return_air() var/t = "Coordinates: [x],[y] \n" - t += "Temperature: [environment.temperature] \n" - for(var/id in environment.gases) - var/gas = environment.gases[id] - if(gas) - t+="[GLOB.meta_gas_names[id]]: [gas] \n" + t += "Temperature: [environment.return_temperature()] \n" + for(var/id in environment.get_gases()) + if(environment.get_moles(id)) + t+="[GLOB.meta_gas_names[id]]: [environment.get_moles(id)] \n" to_chat(usr, t) @@ -227,69 +226,24 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA var/obj/item/W = get_active_held_item() if(istype(W)) - if(equip_to_slot_if_possible(W, slot,0,0,0)) - return 1 + if(equip_to_slot_if_possible(W, slot, FALSE, FALSE, FALSE, FALSE, TRUE)) + return TRUE if(!W) // Activate the item var/obj/item/I = get_item_by_slot(slot) if(istype(I)) + if(slot in check_obscured_slots()) + to_chat(src, "You are unable to unequip that while wearing other garments over it!") + return FALSE I.attack_hand(src) - return 0 + return FALSE -//This is a SAFE proc. Use this instead of equip_to_slot()! -//set qdel_on_fail to have it delete W if it fails to equip -//set disable_warning to disable the 'you are unable to equip that' warning. -//unset redraw_mob to prevent the mob from being redrawn at the end. -/mob/proc/equip_to_slot_if_possible(obj/item/W, slot, qdel_on_fail = FALSE, disable_warning = FALSE, redraw_mob = TRUE, bypass_equip_delay_self = FALSE) - if(!istype(W)) - return FALSE - if(!W.mob_can_equip(src, null, slot, disable_warning, bypass_equip_delay_self)) - if(qdel_on_fail) - qdel(W) - else - if(!disable_warning) - to_chat(src, "You are unable to equip that!") - return FALSE - equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. - return TRUE - -//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't equip need to be done before! Use mob_can_equip() for that task. -//In most cases you will want to use equip_to_slot_if_possible() -/mob/proc/equip_to_slot(obj/item/W, slot) +/// Checks for slots that are currently obscured by other garments. +/mob/proc/check_obscured_slots() return -//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the round starts and when events happen and such. -//Also bypasses equip delay checks, since the mob isn't actually putting it on. -/mob/proc/equip_to_slot_or_del(obj/item/W, slot) - return equip_to_slot_if_possible(W, slot, TRUE, TRUE, FALSE, TRUE) - -//puts the item "W" into an appropriate slot in a human's inventory -//returns 0 if it cannot, 1 if successful -/mob/proc/equip_to_appropriate_slot(obj/item/W) - if(!istype(W)) - return 0 - var/slot_priority = W.slot_equipment_priority - - if(!slot_priority) - slot_priority = list( \ - SLOT_BACK, SLOT_WEAR_ID,\ - SLOT_W_UNIFORM, SLOT_WEAR_SUIT,\ - SLOT_WEAR_MASK, SLOT_HEAD, SLOT_NECK,\ - SLOT_SHOES, SLOT_GLOVES,\ - SLOT_EARS, SLOT_GLASSES,\ - SLOT_BELT, SLOT_S_STORE,\ - SLOT_L_STORE, SLOT_R_STORE,\ - SLOT_GENERC_DEXTROUS_STORAGE\ - ) - - for(var/slot in slot_priority) - if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //qdel_on_fail = 0; disable_warning = 1; redraw_mob = 1 - return 1 - - return 0 - // reset_perspective(thing) set the eye to the thing (if it's equal to current default reset to mob perspective) // reset_perspective() set eye to common default : mob on turf, loc otherwise /mob/proc/reset_perspective(atom/A) @@ -333,8 +287,14 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA . = view(dist, src) SEND_SIGNAL(src, COMSIG_MOB_FOV_VIEW, .) -//mob verbs are faster than object verbs. See https://secure.byond.com/forum/?post=1326139&page=2#comment8198716 for why this isn't atom/verb/examine() -/mob/verb/examinate(atom/A as mob|obj|turf in fov_view()) //It used to be oview(12), but I can't really say why +/** + * Examine a mob + * + * mob verbs are faster than object verbs. See + * [this byond forum post](https://secure.byond.com/forum/?post=1326139&page=2#comment8198716) + * for why this isn't atom/verb/examine() + */ +/mob/verb/examinate(atom/A as mob|obj|turf in view()) //It used to be oview(12), but I can't really say why set name = "Examine" set category = "IC" @@ -342,18 +302,63 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA // shift-click catcher may issue examinate() calls for out-of-sight turfs return - if(is_blind(src)) + if(is_blind()) to_chat(src, "Something is there but you can't see it!") return face_atom(A) - var/flags = SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) - if(flags & COMPONENT_DENY_EXAMINATE) - if(flags & COMPONENT_EXAMINATE_BLIND) - to_chat(src, "Something is there but you can't see it!") - return - var/list/result = A.examine(src) + var/list/result + if(client) + LAZYINITLIST(client.recent_examines) + if(isnull(client.recent_examines[A]) || client.recent_examines[A] < world.time) + result = A.examine(src) + client.recent_examines[A] = world.time + EXAMINE_MORE_TIME // set the value to when the examine cooldown ends + RegisterSignal(A, COMSIG_PARENT_QDELETING, .proc/clear_from_recent_examines, override=TRUE) // to flush the value if deleted early + addtimer(CALLBACK(src, .proc/clear_from_recent_examines, A), EXAMINE_MORE_TIME) + handle_eye_contact(A) + else + result = A.examine_more(src) + else + result = A.examine(src) // if a tree is examined but no client is there to see it, did the tree ever really exist? + to_chat(src, result.Join("\n")) + SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) + +/mob/proc/clear_from_recent_examines(atom/A) + if(!client) + return + UnregisterSignal(A, COMSIG_PARENT_QDELETING) + LAZYREMOVE(client.recent_examines, A) + +/** + * handle_eye_contact() is called when we examine() something. If we examine an alive mob with a mind who has examined us in the last second within 5 tiles, we make eye contact! + * + * Note that if either party has their face obscured, the other won't get the notice about the eye contact + * Also note that examine_more() doesn't proc this or extend the timer, just because it's simpler this way and doesn't lose much. + * The nice part about relying on examining is that we don't bother checking visibility, because we already know they were both visible to each other within the last second, and the one who triggers it is currently seeing them + */ +/mob/proc/handle_eye_contact(mob/living/examined_mob) + return + +/mob/living/handle_eye_contact(mob/living/examined_mob) + if(!istype(examined_mob) || src == examined_mob || examined_mob.stat >= UNCONSCIOUS || !client || !examined_mob.client?.recent_examines || !(src in examined_mob.client.recent_examines)) + return + + if(get_dist(src, examined_mob) > EYE_CONTACT_RANGE) + return + + var/mob/living/carbon/examined_carbon = examined_mob + // check to see if their face is blocked (or if they're not a carbon, in which case they can't block their face anyway) + if(!istype(examined_carbon) || (!(examined_carbon.wear_mask && examined_carbon.wear_mask.flags_inv & HIDEFACE) && !(examined_carbon.head && examined_carbon.head.flags_inv & HIDEFACE))) + if(SEND_SIGNAL(src, COMSIG_MOB_EYECONTACT, examined_mob, TRUE) != COMSIG_BLOCK_EYECONTACT) + var/msg = "You make eye contact with [examined_mob]." + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, src, msg), 3) // so the examine signal has time to fire and this will print after + + var/mob/living/carbon/us_as_carbon = src // i know >casting as subtype, but this isn't really an inheritable check + if(!istype(us_as_carbon) || (!(us_as_carbon.wear_mask && us_as_carbon.wear_mask.flags_inv & HIDEFACE) && !(us_as_carbon.head && us_as_carbon.head.flags_inv & HIDEFACE))) + if(SEND_SIGNAL(examined_mob, COMSIG_MOB_EYECONTACT, src, FALSE) != COMSIG_BLOCK_EYECONTACT) + var/msg = "[src] makes eye contact with you." + addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, examined_mob, msg), 3) //same as above //note: ghosts can point, this is intended @@ -584,6 +589,8 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) /mob/Stat() ..() + SSvote?.render_statpanel(src) + //This is only called from client/Stat(), let's assume client exists. if(statpanel("Status")) @@ -642,8 +649,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) continue if(overrides.len && (A in overrides)) continue - if(A.IsObscured()) - continue statpanel(listed_turf.name, null, A) if(mind) add_spells_to_statpanel(mind.spell_list) @@ -678,7 +683,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) return FALSE if(anchored) return FALSE - if(notransform) + if(mob_transforming) return FALSE if(restrained()) return FALSE @@ -755,7 +760,11 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0) return FALSE /mob/proc/swap_hand() - return + var/obj/item/held_item = get_active_held_item() + if(SEND_SIGNAL(src, COMSIG_MOB_SWAP_HANDS, held_item) & COMPONENT_BLOCK_SWAP) + to_chat(src, "Your other hand is too busy holding [held_item].") + return FALSE + return TRUE /mob/proc/activate_hand(selhand) return diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 9dcfb4e99a..03a3ab1001 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -11,6 +11,10 @@ blocks_emissive = EMISSIVE_BLOCK_GENERIC 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. + + attack_hand_is_action = TRUE + attack_hand_unwieldlyness = CLICK_CD_MELEE + attack_hand_speed = 0 /// What receives our keyboard input. src by default. var/datum/focus @@ -35,9 +39,10 @@ var/list/logging = list() var/atom/machine = null - var/next_move = null var/create_area_cooldown - var/notransform = null //Carbon + /// Whether or not the mob is currently being transformed into another mob or into another state of being. This will prevent it from moving or doing realistically anything. + /// Don't you DARE use this for a cheap way to ensure someone is stunned in your code. + var/mob_transforming = FALSE var/eye_blind = 0 //Carbon var/eye_blurry = 0 //Carbon var/real_name = null @@ -121,6 +126,9 @@ var/list/progressbars = null //for stacking do_after bars + ///For storing what do_after's someone has, in case we want to restrict them to only one of a certain do_after at a time + var/list/do_afters + var/list/mousemove_intercept_objects var/datum/click_intercept @@ -153,4 +161,4 @@ /// 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 + var/mutable_appearance/typing_indicator_current diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 28ca97dc2b..52b755d926 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -349,7 +349,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp /mob/proc/reagent_check(datum/reagent/R) // utilized in the species code return 1 -/proc/notify_ghosts(message, ghost_sound, enter_link, atom/source, mutable_appearance/alert_overlay, action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key, ignore_dnr_observers = FALSE) //Easy notification of ghosts. +/proc/notify_ghosts(message, ghost_sound, enter_link, atom/source, mutable_appearance/alert_overlay, action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key, ignore_dnr_observers = FALSE, header) //Easy notification of ghosts. if(ignore_mapload && SSatoms.initialized != INITIALIZATION_INNEW_REGULAR) //don't notify for objects created during a map load return for(var/mob/dead/observer/O in GLOB.player_list) @@ -366,6 +366,8 @@ It's fairly easy to fix if dealing with single letters but not so much with comp if(A) if(O.client.prefs && O.client.prefs.UI_style) A.icon = ui_style2icon(O.client.prefs.UI_style) + if (header) + A.name = header A.desc = message A.action = action A.target = source @@ -556,3 +558,17 @@ It's fairly easy to fix if dealing with single letters but not so much with comp //Can the mob see reagents inside of containers? /mob/proc/can_see_reagents() return stat == DEAD || silicon_privileges //Dead guys and silicons can always see reagents + +/mob/proc/is_blind() + SHOULD_BE_PURE(TRUE) + return eye_blind ? TRUE : HAS_TRAIT(src, TRAIT_BLIND) + +/mob/proc/can_read(obj/O) + if(is_blind()) + to_chat(src, "As you are trying to read [O], you suddenly feel very stupid!") + return + if(!is_literate()) + to_chat(src, "You try to read [O], but can't comprehend any of it.") + return + return TRUE + diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 9867da1ed4..e977c397c9 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -32,7 +32,7 @@ if(!n || !direction || !mob?.loc) return FALSE //GET RID OF THIS SOON AS MOBILITY FLAGS IS DONE - if(mob.notransform) + if(mob.mob_transforming) return FALSE if(mob.control_object) diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index a403845ee2..7d97270808 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -43,6 +43,11 @@ if(GLOB.say_disabled) //This is here to try to identify lag problems to_chat(usr, "Speech is currently admin-disabled.") return + + if(length(message) > MAX_MESSAGE_LEN) + to_chat(usr, message) + to_chat(usr, "^^^----- The preceeding message has been DISCARDED for being over the maximum length of [MAX_MESSAGE_LEN]. It has NOT been sent! -----^^^") + return message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN)) clear_typing_indicator() // clear it immediately! @@ -50,12 +55,22 @@ usr.emote("me",1,message,TRUE) /mob/say_mod(input, message_mode) + if(message_mode == MODE_WHISPER_CRIT) + return ..() + if((input[1] == "!") && (length_char(input) > 1)) + message_mode = MODE_CUSTOM_SAY + return copytext_char(input, 2) var/customsayverb = findtext(input, "*") - if(customsayverb && message_mode != MODE_WHISPER_CRIT) + if(customsayverb) message_mode = MODE_CUSTOM_SAY return lowertext(copytext_char(input, 1, customsayverb)) - else - return ..() + return ..() + +/proc/uncostumize_say(input, message_mode) + . = input + if(message_mode == MODE_CUSTOM_SAY) + var/customsayverb = findtext(input, "*") + return lowertext(copytext_char(input, 1, customsayverb)) /mob/proc/whisper_keybind() var/message = input(src, "", "whisper") as text|null diff --git a/code/modules/mob/say_vr.dm b/code/modules/mob/say_vr.dm index 5ed24af726..5db3ccf216 100644 --- a/code/modules/mob/say_vr.dm +++ b/code/modules/mob/say_vr.dm @@ -37,7 +37,7 @@ proc/get_top_level_mob(var/mob/S) to_chat(user, "You cannot send IC messages (muted).") return FALSE else if(!params) - var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN) + var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN) if(subtle_emote && !check_invalid(user, subtle_emote)) var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable") switch(type) @@ -98,7 +98,7 @@ proc/get_top_level_mob(var/mob/S) to_chat(user, "You cannot send IC messages (muted).") return FALSE else if(!params) - var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN) + var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN) if(subtle_emote && !check_invalid(user, subtle_emote)) var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable") switch(type) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 56ec5bb816..7de30a7095 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -1,26 +1,8 @@ -/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG)) - if (notransform) +#define TRANSFORMATION_DURATION 22 + +/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG)) + if(mob_transforming || transformation_timer) return - //Handle items on mob - - //first implants & organs - var/list/stored_implants = list() - var/list/int_organs = list() - - if (tr_flags & TR_KEEPIMPLANTS) - for(var/X in implants) - var/obj/item/implant/IMP = X - stored_implants += IMP - IMP.removed(src, 1, 1) - - var/list/missing_bodyparts_zones = get_missing_limbs() - - var/obj/item/cavity_object - - var/obj/item/bodypart/chest/CH = get_bodypart(BODY_ZONE_CHEST) - if(CH.cavity_item) - cavity_object = CH.cavity_item - CH.cavity_item = null if(tr_flags & TR_KEEPITEMS) var/Itemlist = get_equipped_items(TRUE) @@ -29,14 +11,37 @@ dropItemToGround(W) //Make mob invisible and spawn animation - notransform = TRUE - Stun(INFINITY, ignore_canstun = TRUE) + mob_transforming = TRUE + Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE) icon = null cut_overlays() invisibility = INVISIBILITY_MAXIMUM new /obj/effect/temp_visual/monkeyify(loc) - sleep(22) + + transformation_timer = addtimer(CALLBACK(src, .proc/finish_monkeyize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE) + +/mob/living/carbon/proc/finish_monkeyize(tr_flags) + transformation_timer = null + + var/list/missing_bodyparts_zones = get_missing_limbs() + + var/list/stored_implants = list() + + if (tr_flags & TR_KEEPIMPLANTS) + for(var/X in implants) + var/obj/item/implant/IMP = X + stored_implants += IMP + IMP.removed(src, 1, 1) + + var/list/int_organs = list() + var/obj/item/cavity_object + + var/obj/item/bodypart/chest/CH = get_bodypart(BODY_ZONE_CHEST) + if(CH.cavity_item) + cavity_object = CH.cavity_item + CH.cavity_item = null + var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc ) // hash the original name? @@ -50,6 +55,7 @@ if(tr_flags & TR_KEEPSE) O.dna.mutation_index = dna.mutation_index + O.dna.default_mutation_genes = dna.default_mutation_genes O.dna.set_se(1, GET_INITIALIZED_MUTATION(RACEMUT)) if(suiciding) @@ -149,12 +155,33 @@ ////////////////////////// Humanize ////////////////////////////// //Could probably be merged with monkeyize but other transformations got their own procs, too -/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG)) - if (notransform) +/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_KEEPSTUNS | TR_KEEPREAGENTS | TR_DEFAULTMSG)) + if (mob_transforming || transformation_timer) return - //Handle items on mob - //first implants & organs + //now the rest + if (tr_flags & TR_KEEPITEMS) + var/Itemlist = get_equipped_items(TRUE) + Itemlist += held_items + for(var/obj/item/W in Itemlist) + dropItemToGround(W, TRUE) + if (client) + client.screen -= W + + //Make mob invisible and spawn animation + mob_transforming = TRUE + Paralyze(TRANSFORMATION_DURATION, ignore_canstun = TRUE) + + icon = null + cut_overlays() + invisibility = INVISIBILITY_MAXIMUM + new /obj/effect/temp_visual/monkeyify/humanify(loc) + + transformation_timer = addtimer(CALLBACK(src, .proc/finish_humanize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE) + +/mob/living/carbon/proc/finish_humanize(tr_flags) + transformation_timer = null + var/list/stored_implants = list() var/list/int_organs = list() @@ -173,25 +200,6 @@ cavity_object = CH.cavity_item CH.cavity_item = null - //now the rest - if (tr_flags & TR_KEEPITEMS) - var/Itemlist = get_equipped_items(TRUE) - Itemlist += held_items - for(var/obj/item/W in Itemlist) - dropItemToGround(W, TRUE) - if (client) - client.screen -= W - - - - //Make mob invisible and spawn animation - notransform = TRUE - Stun(22, ignore_canstun = TRUE) - icon = null - cut_overlays() - invisibility = INVISIBILITY_MAXIMUM - new /obj/effect/temp_visual/monkeyify/humanify(loc) - sleep(22) var/mob/living/carbon/human/O = new( loc ) for(var/obj/item/C in O.loc) O.equip_to_appropriate_slot(C) @@ -208,6 +216,7 @@ if(tr_flags & TR_KEEPSE) O.dna.mutation_index = dna.mutation_index + O.dna.default_mutation_genes = dna.default_mutation_genes O.dna.set_se(0, GET_INITIALIZED_MUTATION(RACEMUT)) O.domutcheck() @@ -304,7 +313,7 @@ qdel(src) /mob/living/carbon/human/AIize() - if (notransform) + if (mob_transforming) return for(var/t in bodyparts) qdel(t) @@ -312,12 +321,12 @@ return ..() /mob/living/carbon/AIize() - if(notransform) + if(mob_transforming) return for(var/obj/item/W in src) dropItemToGround(W) regenerate_icons() - notransform = TRUE + mob_transforming = TRUE Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -353,7 +362,7 @@ qdel(src) /mob/living/carbon/human/proc/Robotize(delete_items = 0, transfer_after = TRUE) - if (notransform) + if(mob_transforming) return for(var/obj/item/W in src) if(delete_items) @@ -361,7 +370,7 @@ else dropItemToGround(W) regenerate_icons() - notransform = TRUE + mob_transforming = TRUE Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -398,12 +407,12 @@ //human -> alien /mob/living/carbon/human/proc/Alienize(mind_transfer = TRUE) - if (notransform) + if (mob_transforming) return for(var/obj/item/W in src) dropItemToGround(W) regenerate_icons() - notransform = 1 + mob_transforming = 1 Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -432,12 +441,12 @@ qdel(src) /mob/living/carbon/human/proc/slimeize(reproduce, mind_transfer = TRUE) - if (notransform) + if (mob_transforming) return for(var/obj/item/W in src) dropItemToGround(W) regenerate_icons() - notransform = 1 + mob_transforming = 1 Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -477,12 +486,12 @@ /mob/living/carbon/human/proc/corgize(mind_transfer = TRUE) - if (notransform) + if (mob_transforming) return for(var/obj/item/W in src) dropItemToGround(W) regenerate_icons() - notransform = TRUE + mob_transforming = TRUE Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -501,7 +510,7 @@ qdel(src) /mob/living/carbon/proc/gorillize(mind_transfer = TRUE) - if(notransform) + if(mob_transforming) return SSblackbox.record_feedback("amount", "gorillas_created", 1) @@ -512,7 +521,7 @@ dropItemToGround(W, TRUE) regenerate_icons() - notransform = TRUE + mob_transforming = TRUE Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -535,13 +544,13 @@ if(mind) mind_transfer = alert("Want to transfer their mind into the new mob", "Mind Transfer", "Yes", "No") == "Yes" ? TRUE : FALSE - if(notransform) + if(mob_transforming) return for(var/obj/item/W in src) dropItemToGround(W) regenerate_icons() - notransform = TRUE + mob_transforming = TRUE Paralyze(INFINITY) icon = null invisibility = INVISIBILITY_MAXIMUM @@ -581,3 +590,68 @@ . = new_mob qdel(src) + + +/* Certain mob types have problems and should not be allowed to be controlled by players. + * + * This proc is here to force coders to manually place their mob in this list, hopefully tested. + * This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them. + */ +/mob/proc/safe_animal(MP) + +//Bad mobs! - Remember to add a comment explaining what's wrong with the mob + if(!MP) + return 0 //Sanity, this should never happen. + + if(ispath(MP, /mob/living/simple_animal/hostile/construct)) + return 0 //Verbs do not appear for players. + +//Good mobs! + if(ispath(MP, /mob/living/simple_animal/pet/cat)) + return 1 + if(ispath(MP, /mob/living/simple_animal/pet/dog/corgi)) + return 1 + if(ispath(MP, /mob/living/simple_animal/crab)) + return 1 + if(ispath(MP, /mob/living/simple_animal/hostile/carp)) + return 1 + if(ispath(MP, /mob/living/simple_animal/hostile/mushroom)) + return 1 + if(ispath(MP, /mob/living/simple_animal/shade)) + return 1 + if(ispath(MP, /mob/living/simple_animal/hostile/killertomato)) + return 1 + if(ispath(MP, /mob/living/simple_animal/mouse)) + return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak) + if(ispath(MP, /mob/living/simple_animal/hostile/bear)) + return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak) + if(ispath(MP, /mob/living/simple_animal/parrot)) + return 1 //Parrots are no longer unfinished! -Nodrak + + //Not in here? Must be untested! + return 0 + +#undef TRANSFORMATION_DURATION + +/mob/living/proc/turn_into_pickle() + //if they're already a pickle, turn them back instead + if(istype(src, /mob/living/simple_animal/pickle)) + //turn them back from being a pickle, but release them alive + var/mob/living/simple_animal/pickle/existing_pickle = src + if(existing_pickle.original_body) + existing_pickle.original_body.forceMove(get_turf(src)) + if(mind) + mind.transfer_to(existing_pickle.original_body) + qdel(src) + else + //make a new pickle on the tile and move their mind into it if possible + var/mob/living/simple_animal/pickle/new_pickle = new /mob/living/simple_animal/pickle(get_turf(src)) + new_pickle.original_body = src + if(mind) + mind.transfer_to(new_pickle) + //give them their old access if any + var/obj/item/card/id/mob_access_card = get_idcard() + if(mob_access_card) + new_pickle.access_card = mob_access_card + //move old body inside the pickle for safekeeping (when they die, we'll return the corpse because we're nice) + src.forceMove(new_pickle) diff --git a/code/modules/mob/typing_indicator.dm b/code/modules/mob/typing_indicator.dm index f28cbe4385..6154828f4d 100644 --- a/code/modules/mob/typing_indicator.dm +++ b/code/modules/mob/typing_indicator.dm @@ -15,13 +15,23 @@ GLOBAL_LIST_EMPTY(typing_indicator_overlays) /mob/proc/get_typing_indicator_icon_state() return typing_indicator_state +/// Generates the mutable appearance for typing indicator. Should prevent stuck overlays. +/mob/proc/generate_typing_indicator() + var/state = get_typing_indicator_icon_state() + if(ispath(state)) + var/atom/thing = new state(null) + var/mutable_appearance/generated = new(thing) + return generated + else + CRASH("Unsupported typing indicator state: [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) +/mob/proc/display_typing_indicator(timeout_override = TYPING_INDICATOR_TIMEOUT, state_override = generate_typing_indicator(), force = FALSE) if((!typing_indicator_enabled && !force) || typing_indicator_current) return typing_indicator_current = state_override diff --git a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm index eeb5212aeb..b5f3bae53d 100644 --- a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm +++ b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm @@ -73,4 +73,4 @@ add_status_message("[client.username] has changed channel title from [title] to [newtitle]") title = newtitle -#undef MAX_CHANNELS \ No newline at end of file +#undef MAX_CHANNELS diff --git a/code/modules/modular_computers/computers/_modular_computer_shared.dm b/code/modules/modular_computers/computers/_modular_computer_shared.dm new file mode 100644 index 0000000000..8ca93e8347 --- /dev/null +++ b/code/modules/modular_computers/computers/_modular_computer_shared.dm @@ -0,0 +1,64 @@ + +/obj/proc/is_modular_computer() + return + +/obj/proc/get_modular_computer_part(part_type) + return null + +/obj/item/modular_computer/is_modular_computer() + return TRUE + +/obj/item/modular_computer/get_modular_computer_part(part_type) + if(!part_type) + stack_trace("get_modular_computer_part() called without a valid part_type") + return null + return all_components[part_type] + + +/obj/machinery/modular_computer/is_modular_computer() + return TRUE + +/obj/machinery/modular_computer/get_modular_computer_part(part_type) + if(!part_type) + stack_trace("get_modular_computer_part() called without a valid part_type") + return null + return cpu?.all_components[part_type] + + +/obj/proc/get_modular_computer_parts_examine(mob/user) + . = list() + if(!is_modular_computer()) + return + + var/user_is_adjacent = Adjacent(user) //don't reveal full details unless they're close enough to see it on the screen anyway. + + var/obj/item/computer_hardware/ai_slot/ai_slot = get_modular_computer_part(MC_AI) + if(ai_slot) + if(ai_slot.stored_card) + if(user_is_adjacent) + . += "It has a slot installed for an intelliCard which contains: [ai_slot.stored_card.name]" + else + . += "It has a slot installed for an intelliCard, which appears to be occupied." + . += "Alt-click to eject the intelliCard." + else + . += "It has a slot installed for an intelliCard." + + var/obj/item/computer_hardware/card_slot/card_slot = get_modular_computer_part(MC_CARD) + if(card_slot) + if(card_slot.stored_card || card_slot.stored_card2) + var/obj/item/card/id/first_ID = card_slot.stored_card + var/obj/item/card/id/second_ID = card_slot.stored_card2 + var/multiple_cards = istype(first_ID) && istype(second_ID) + if(user_is_adjacent) + . += "It has two slots for identification cards installed[multiple_cards ? " which contain [first_ID] and [second_ID]" : ", one of which contains [first_ID ? first_ID : second_ID]"]." + else + . += "It has two slots for identification cards installed, [multiple_cards ? "both of which appear" : "and one of them appears"] to be occupied." + . += "Alt-click [src] to eject the identification card[multiple_cards ? "s":""]." + else + . += "It has two slots installed for identification cards." + + var/obj/item/computer_hardware/printer/printer_slot = get_modular_computer_part(MC_PRINT) + if(printer_slot) + . += "It has a printer installed." + if(user_is_adjacent) + . += "The printer's paper levels are at: [printer_slot.stored_paper]/[printer_slot.max_paper].]" diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index d722197bd9..67c04de13f 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -7,6 +7,7 @@ var/enabled = 0 // Whether the computer is turned on. var/screen_on = 1 // Whether the computer is active/opened/it's screen is on. + var/device_theme = "ntos" // Sets the theme for the main menu, hardware config, and file browser apps. Overridden by certain non-NT devices. var/datum/computer_file/program/active_program = null // A currently active program running on the computer. var/hardware_flag = 0 // A flag that describes this device type var/last_power_usage = 0 @@ -98,7 +99,7 @@ if(issilicon(usr)) return var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] - if(usr.canUseTopic(src)) + if(usr.canUseTopic(src, BE_CLOSE)) card_slot.try_eject(null, usr) // Eject ID card from computer, if it has ID slot with card inside. @@ -109,7 +110,7 @@ if(issilicon(usr)) return var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI] - if(usr.canUseTopic(src)) + if(usr.canUseTopic(src, BE_CLOSE)) ai_slot.try_eject(null, usr,1) @@ -121,17 +122,17 @@ if(issilicon(usr)) return - if(usr.canUseTopic(src)) + if(usr.canUseTopic(src, BE_CLOSE)) var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] if(uninstall_component(portable_drive, usr)) portable_drive.verb_pickup() /obj/item/modular_computer/AltClick(mob/user) - . = ..() + ..() if(issilicon(user)) return - if(user.canUseTopic(src)) + if(user.canUseTopic(src, BE_CLOSE)) var/obj/item/computer_hardware/card_slot/card_slot = all_components[MC_CARD] var/obj/item/computer_hardware/ai_slot/ai_slot = all_components[MC_AI] var/obj/item/computer_hardware/hard_drive/portable/portable_drive = all_components[MC_SDD] @@ -143,7 +144,7 @@ return if(ai_slot) ai_slot.try_eject(null, user) - return TRUE + // Gets IDs/access levels from card slot. Would be useful when/if PDAs would become modular PCs. /obj/item/modular_computer/GetAccess() @@ -175,7 +176,7 @@ /obj/item/modular_computer/MouseDrop(obj/over_object, src_location, over_location) var/mob/M = usr - if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src)) + if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src, BE_CLOSE)) return attack_self(M) return ..() @@ -195,12 +196,22 @@ /obj/item/modular_computer/emag_act(mob/user) . = ..() - if(obj_flags & EMAGGED) - to_chat(user, "\The [src] was already emagged.") - return - obj_flags |= EMAGGED - to_chat(user, "You emag \the [src]. It's screen briefly shows a \"OVERRIDE ACCEPTED: New software downloads available.\" message.") - return TRUE + if(!enabled) + to_chat(user, "You'd need to turn the [src] on first.") + return FALSE + obj_flags |= EMAGGED //Mostly for consistancy purposes; the programs will do their own emag handling + var/newemag = FALSE + var/obj/item/computer_hardware/hard_drive/drive = all_components[MC_HDD] + for(var/datum/computer_file/program/app in drive.stored_files) + if(!istype(app)) + continue + if(app.run_emag()) + newemag = TRUE + if(newemag) + to_chat(user, "You swipe \the [src]. A console window momentarily fills the screen, with white text rapidly scrolling past.") + return TRUE + to_chat(user, "You swipe \the [src]. A console window fills the screen, but it quickly closes itself after only a few lines are written to it.") + return FALSE /obj/item/modular_computer/examine(mob/user) . = ..() @@ -209,13 +220,14 @@ else if(obj_integrity < max_integrity) . += "It is damaged." + . += get_modular_computer_parts_examine(user) + /obj/item/modular_computer/update_icon_state() if(!enabled) icon_state = icon_state_unpowered else icon_state = icon_state_powered - /obj/item/modular_computer/update_overlays() . = ..() if(!display_overlays) @@ -306,6 +318,8 @@ /obj/item/modular_computer/proc/get_header_data() var/list/data = list() + data["PC_device_theme"] = device_theme + var/obj/item/computer_hardware/battery/battery_module = all_components[MC_CELL] var/obj/item/computer_hardware/recharger/recharger = all_components[MC_CHARGE] @@ -407,17 +421,17 @@ if(install_component(W, user)) return - if(istype(W, /obj/item/wrench)) + if(W.tool_behaviour == TOOL_WRENCH) if(all_components.len) to_chat(user, "Remove all components from \the [src] before disassembling it.") return new /obj/item/stack/sheet/metal( get_turf(src.loc), steel_sheet_cost ) - physical.visible_message("\The [src] has been disassembled by [user].") + physical.visible_message("\The [src] is disassembled by [user].") relay_qdel() qdel(src) return - if(istype(W, /obj/item/weldingtool)) + if(W.tool_behaviour == TOOL_WELDER) if(obj_integrity == max_integrity) to_chat(user, "\The [src] does not require repairs.") return @@ -431,7 +445,7 @@ to_chat(user, "You repair \the [src].") return - if(istype(W, /obj/item/screwdriver)) + if(W.tool_behaviour == TOOL_SCREWDRIVER) if(!all_components.len) to_chat(user, "This device doesn't have any components installed.") return @@ -440,7 +454,7 @@ var/obj/item/computer_hardware/H = all_components[h] component_names.Add(H.name) - var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in component_names + var/choice = input(user, "Which component do you want to uninstall?", "Computer maintenance", null) as null|anything in sortList(component_names) if(!choice) return diff --git a/code/modules/modular_computers/computers/item/computer_damage.dm b/code/modules/modular_computers/computers/item/computer_damage.dm index 6664b449bd..b510f8aded 100644 --- a/code/modules/modular_computers/computers/item/computer_damage.dm +++ b/code/modules/modular_computers/computers/item/computer_damage.dm @@ -18,13 +18,13 @@ /obj/item/modular_computer/proc/break_apart() if(!(flags_1 & NODECONSTRUCT_1)) - physical.visible_message("\The [src] breaks apart!") + physical.visible_message("\The [src] breaks apart!") var/turf/newloc = get_turf(src) new /obj/item/stack/sheet/metal(newloc, round(steel_sheet_cost/2)) for(var/C in all_components) var/obj/item/computer_hardware/H = all_components[C] if(QDELETED(H)) - return + continue uninstall_component(H) H.forceMove(newloc) if(prob(25)) diff --git a/code/modules/modular_computers/computers/item/computer_power.dm b/code/modules/modular_computers/computers/item/computer_power.dm index d3c65f86ec..b5188f43d9 100644 --- a/code/modules/modular_computers/computers/item/computer_power.dm +++ b/code/modules/modular_computers/computers/item/computer_power.dm @@ -28,8 +28,7 @@ /obj/item/modular_computer/get_cell() var/obj/item/computer_hardware/battery/battery_module = all_components[MC_CELL] - if(battery_module && battery_module.battery) - return battery_module.battery + return battery_module?.get_cell() // Used in following function to reduce copypaste /obj/item/modular_computer/proc/power_failure() diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 11f5145478..fd017e2b0f 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -3,7 +3,7 @@ ui_interact(user) // Operates TGUI -/obj/item/modular_computer/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) +/obj/item/modular_computer/ui_interact(mob/user, datum/tgui/ui) if(!enabled) if(ui) ui.close() @@ -14,7 +14,7 @@ return 0 // Robots don't really need to see the screen, their wireless connection works as long as computer is on. - if(!screen_on && !hasSiliconAccessInArea(user)) + if(!screen_on && !issilicon(user)) if(ui) ui.close() return 0 @@ -33,19 +33,17 @@ to_chat(user, "\The [src] beeps three times, it's screen displaying a \"DISK ERROR\" warning.") return // No HDD, No HDD files list or no stored files. Something is very broken. - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + ui = SStgui.try_update_ui(user, src, ui) if (!ui) - var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) - assets.send(user) - - ui = new(user, src, ui_key, "ntos_main", "NtOS Main menu", 400, 500, master_ui, state) - ui.set_style("ntos") + ui = new(user, src, "NtosMain") + ui.set_autoupdate(TRUE) ui.open() - ui.set_autoupdate(state = 1) + ui.send_asset(get_asset_datum(/datum/asset/simple/headers)) /obj/item/modular_computer/ui_data(mob/user) var/list/data = get_header_data() + data["device_theme"] = device_theme data["programs"] = list() var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD] for(var/datum/computer_file/program/P in hard_drive.stored_files) @@ -143,6 +141,7 @@ set_light(comp_light_luminosity, 1, comp_light_color) else set_light(0) + return TRUE if("PC_light_color") var/mob/user = usr diff --git a/code/modules/modular_computers/computers/item/laptop.dm b/code/modules/modular_computers/computers/item/laptop.dm index a4d2e74657..5927d57a0b 100644 --- a/code/modules/modular_computers/computers/item/laptop.dm +++ b/code/modules/modular_computers/computers/item/laptop.dm @@ -7,6 +7,7 @@ icon_state_powered = "laptop" icon_state_unpowered = "laptop-off" icon_state_menu = "menu" + display_overlays = FALSE hardware_flag = PROGRAM_LAPTOP max_hardware_size = 2 @@ -18,8 +19,8 @@ screen_on = 0 // Starts closed var/start_open = TRUE // unless this var is set to 1 var/icon_state_closed = "laptop-closed" - display_overlays = FALSE var/w_class_open = WEIGHT_CLASS_BULKY + var/slowdown_open = TRUE /obj/item/modular_computer/laptop/examine(mob/user) . = ..() @@ -38,6 +39,13 @@ else . = ..() +/obj/item/modular_computer/laptop/update_overlays() + if(screen_on) + return ..() + else + cut_overlays() + icon_state = icon_state_closed + /obj/item/modular_computer/laptop/attack_self(mob/user) if(!screen_on) try_toggle_open(user) @@ -64,10 +72,8 @@ return M.put_in_hand(src, H.held_index) -/obj/item/modular_computer/laptop/attack_hand(mob/user) +/obj/item/modular_computer/laptop/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() - if(.) - return if(screen_on && isturf(loc)) return attack_self(user) @@ -76,7 +82,7 @@ return if(!isturf(loc) && !ismob(loc)) // No opening it in backpack. return - if(!user.canUseTopic(src)) + if(!user.canUseTopic(src, BE_CLOSE)) return toggle_open(user) @@ -85,15 +91,17 @@ /obj/item/modular_computer/laptop/AltClick(mob/user) if(screen_on) // Close it. try_toggle_open(user) - return TRUE - return ..() + else + return ..() /obj/item/modular_computer/laptop/proc/toggle_open(mob/living/user=null) if(screen_on) to_chat(user, "You close \the [src].") + slowdown = initial(slowdown) w_class = initial(w_class) else to_chat(user, "You open \the [src].") + slowdown = slowdown_open w_class = w_class_open screen_on = !screen_on diff --git a/code/modules/modular_computers/computers/item/laptop_presets.dm b/code/modules/modular_computers/computers/item/laptop_presets.dm index e50392e3b3..6bc2919bea 100644 --- a/code/modules/modular_computers/computers/item/laptop_presets.dm +++ b/code/modules/modular_computers/computers/item/laptop_presets.dm @@ -20,4 +20,3 @@ /obj/item/modular_computer/laptop/preset/civilian/install_programs() var/obj/item/computer_hardware/hard_drive/hard_drive = all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/chatclient()) - hard_drive.store_file(new/datum/computer_file/program/nttransfer()) diff --git a/code/modules/modular_computers/computers/item/processor.dm b/code/modules/modular_computers/computers/item/processor.dm index 81e2cb95e6..c79d7a9361 100644 --- a/code/modules/modular_computers/computers/item/processor.dm +++ b/code/modules/modular_computers/computers/item/processor.dm @@ -1,4 +1,5 @@ // Held by /obj/machinery/modular_computer to reduce amount of copy-pasted code. +//TODO: REFACTOR THIS SPAGHETTI CODE, MAKE IT A COMPUTER_HARDWARE COMPONENT OR REMOVE IT /obj/item/modular_computer/processor name = "processing unit" desc = "You shouldn't see this. If you do, report it." @@ -11,19 +12,22 @@ var/obj/machinery/modular_computer/machinery_computer = null /obj/item/modular_computer/processor/Destroy() - . = ..() if(machinery_computer && (machinery_computer.cpu == src)) machinery_computer.cpu = null + machinery_computer.UnregisterSignal(src, COMSIG_ATOM_UPDATED_ICON) machinery_computer = null - -/obj/item/modular_computer/processor/Initialize(mapload) . = ..() - if(!loc || !istype(loc, /obj/machinery/modular_computer)) + +/obj/item/modular_computer/processor/New(comp) //intentional new probably + ..() + STOP_PROCESSING(SSobj, src) // Processed by its machine + + if(!comp || !istype(comp, /obj/machinery/modular_computer)) CRASH("Inapropriate type passed to obj/item/modular_computer/processor/New()! Aborting.") // Obtain reference to machinery computer all_components = list() idle_threads = list() - machinery_computer = loc + machinery_computer = comp machinery_computer.cpu = src hardware_flag = machinery_computer.hardware_flag max_hardware_size = machinery_computer.max_hardware_size @@ -39,7 +43,7 @@ qdel(machinery_computer) // This thing is not meant to be used on it's own, get topic data from our machinery owner. -//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE) +//obj/item/modular_computer/processor/canUseTopic(atom/movable/M, be_close=FALSE, no_dexterity=FALSE, no_tk=FALSE) // if(!machinery_computer) // return 0 @@ -69,3 +73,6 @@ machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_disk if(MC_AI) machinery_computer.verbs -= /obj/machinery/modular_computer/proc/eject_card + +/obj/item/modular_computer/processor/attack_ghost(mob/user) + ui_interact(user) diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm index a371e97ec6..41a256467f 100644 --- a/code/modules/modular_computers/computers/item/tablet.dm +++ b/code/modules/modular_computers/computers/item/tablet.dm @@ -5,6 +5,7 @@ icon_state_unpowered = "tablet" icon_state_powered = "tablet" icon_state_menu = "menu" + //worn_icon_state = "tablet" hardware_flag = PROGRAM_TABLET max_hardware_size = 1 w_class = WEIGHT_CLASS_SMALL @@ -32,3 +33,17 @@ slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT comp_light_luminosity = 6.3 has_variants = FALSE + +/// Given to Nuke Ops members. +/obj/item/modular_computer/tablet/nukeops + icon_state = "tablet-syndicate" + comp_light_luminosity = 6.3 + has_variants = FALSE + device_theme = "syndicate" + +/obj/item/modular_computer/tablet/nukeops/emag_act(mob/user) + if(!enabled) + to_chat(user, "You'd need to turn the [src] on first.") + return FALSE + to_chat(user, "You swipe \the [src]. It's screen briefly shows a message reading \"MEMORY CODE INJECTION DETECTED AND SUCCESSFULLY QUARANTINED\".") + return FALSE diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm index f516d3802f..7cca8ea5b4 100644 --- a/code/modules/modular_computers/computers/item/tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/tablet_presets.dm @@ -22,23 +22,38 @@ /obj/item/modular_computer/tablet/preset/cargo/Initialize() . = ..() + var/obj/item/computer_hardware/hard_drive/small/hard_drive = new install_component(new /obj/item/computer_hardware/processor_unit/small) install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer)) - install_component(new /obj/item/computer_hardware/hard_drive/small) + install_component(hard_drive) install_component(new /obj/item/computer_hardware/network_card) install_component(new /obj/item/computer_hardware/printer/mini) + hard_drive.store_file(new /datum/computer_file/program/bounty) + //hard_drive.store_file(new /datum/computer_file/program/shipping) -/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize() // Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink. +/// Given by the syndicate as part of the contract uplink bundle - loads in the Contractor Uplink. +/obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink/Initialize() . = ..() var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = new var/datum/computer_file/program/contract_uplink/uplink = new + active_program = uplink uplink.program_state = PROGRAM_STATE_ACTIVE uplink.computer = src + hard_drive.store_file(uplink) + install_component(new /obj/item/computer_hardware/processor_unit/small) install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer)) install_component(hard_drive) install_component(new /obj/item/computer_hardware/network_card) install_component(new /obj/item/computer_hardware/card_slot) - install_component(new /obj/item/computer_hardware/printer/mini) \ No newline at end of file + install_component(new /obj/item/computer_hardware/printer/mini) + +/// Given to Nuke Ops members. +/obj/item/modular_computer/tablet/nukeops/Initialize() + . = ..() + install_component(new /obj/item/computer_hardware/processor_unit/small) + install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer)) + install_component(new /obj/item/computer_hardware/hard_drive/small/nukeops) + install_component(new /obj/item/computer_hardware/network_card) diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index f83442b137..9d29b23e76 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -46,16 +46,12 @@ desc = "A stationary computer. This one comes preloaded with research programs." _has_ai = TRUE -/obj/machinery/modular_computer/console/preset/research/examine(mob/user) - . = ..() - . += "Alt-click to eject the intelliCard." - /obj/machinery/modular_computer/console/preset/research/install_programs() var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/ntnetmonitor()) - hard_drive.store_file(new/datum/computer_file/program/nttransfer()) hard_drive.store_file(new/datum/computer_file/program/chatclient()) hard_drive.store_file(new/datum/computer_file/program/aidiag()) + hard_drive.store_file(new/datum/computer_file/program/robocontrol()) // ===== COMMAND CONSOLE ===== @@ -66,15 +62,27 @@ _has_id_slot = TRUE _has_printer = TRUE -/obj/machinery/modular_computer/console/preset/command/examine(mob/user) - . = ..() - . += "Alt-click [src] to eject the identification card." - /obj/machinery/modular_computer/console/preset/command/install_programs() var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/chatclient()) hard_drive.store_file(new/datum/computer_file/program/card_mod()) + +// ===== IDENTIFICATION CONSOLE ===== +/obj/machinery/modular_computer/console/preset/id + console_department = "Identification" + name = "identification console" + desc = "A stationary computer. This one comes preloaded with identification modification programs." + _has_id_slot = TRUE + _has_printer = TRUE + +/obj/machinery/modular_computer/console/preset/id/install_programs() + var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] + hard_drive.store_file(new/datum/computer_file/program/chatclient()) + hard_drive.store_file(new/datum/computer_file/program/card_mod()) + hard_drive.store_file(new/datum/computer_file/program/job_management()) + hard_drive.store_file(new/datum/computer_file/program/crew_manifest()) + // ===== CIVILIAN CONSOLE ===== /obj/machinery/modular_computer/console/preset/civilian console_department = "Civilian" @@ -84,4 +92,4 @@ /obj/machinery/modular_computer/console/preset/civilian/install_programs() var/obj/item/computer_hardware/hard_drive/hard_drive = cpu.all_components[MC_HDD] hard_drive.store_file(new/datum/computer_file/program/chatclient()) - hard_drive.store_file(new/datum/computer_file/program/nttransfer()) + hard_drive.store_file(new/datum/computer_file/program/arcade()) diff --git a/code/modules/modular_computers/computers/machinery/modular_computer.dm b/code/modules/modular_computers/computers/machinery/modular_computer.dm index 89c6166a0d..6f016ad147 100644 --- a/code/modules/modular_computers/computers/machinery/modular_computer.dm +++ b/code/modules/modular_computers/computers/machinery/modular_computer.dm @@ -36,6 +36,10 @@ QDEL_NULL(cpu) return ..() +/obj/machinery/modular_computer/examine(mob/user) + . = ..() + . += get_modular_computer_parts_examine(user) + /obj/machinery/modular_computer/attack_ghost(mob/dead/observer/user) . = ..() if(.) @@ -45,31 +49,31 @@ /obj/machinery/modular_computer/emag_act(mob/user) . = ..() - if(cpu) - . |= cpu.emag_act(user) + if(!cpu) + to_chat(user, "You'd need to turn the [src] on first.") + return FALSE + return (cpu.emag_act(user)) -/obj/machinery/modular_computer/update_icon_state() - if(cpu?.enabled) - icon_state = icon_state_powered - else if(stat & NOPOWER || !(cpu?.use_power())) - icon_state = icon_state_unpowered +/obj/machinery/modular_computer/update_icon() + cut_overlays() + icon_state = icon_state_powered -/obj/machinery/modular_computer/update_overlays() - . = ..() if(!cpu || !cpu.enabled) if (!(stat & NOPOWER) && (cpu && cpu.use_power())) - . += screen_icon_screensaver + add_overlay(screen_icon_screensaver) + else + icon_state = icon_state_unpowered set_light(0) else set_light(light_strength) if(cpu.active_program) - . += cpu.active_program.program_icon_state ? cpu.active_program.program_icon_state : screen_icon_state_menu + add_overlay(cpu.active_program.program_icon_state ? cpu.active_program.program_icon_state : screen_icon_state_menu) else - . += screen_icon_state_menu + add_overlay(screen_icon_state_menu) if(cpu && cpu.obj_integrity <= cpu.integrity_failure * cpu.max_integrity) - . += "bsod" - . += "broken" + add_overlay("bsod") + add_overlay("broken") // Eject ID card from computer, if it has ID slot with card inside. /obj/machinery/modular_computer/proc/eject_id() @@ -96,9 +100,8 @@ cpu.eject_card() /obj/machinery/modular_computer/AltClick(mob/user) - . = ..() if(cpu) - return cpu.AltClick(user) + cpu.AltClick(user) //ATTACK HAND IGNORING PARENT RETURN VALUE // On-click handling. Turns on the computer if it's off and opens the GUI. @@ -131,8 +134,7 @@ stat &= ~NOPOWER update_icon() return - ..() - update_icon() + . = ..() /obj/machinery/modular_computer/attackby(var/obj/item/W as obj, mob/user) if(cpu && !(flags_1 & NODECONSTRUCT_1)) @@ -145,6 +147,13 @@ /obj/machinery/modular_computer/ex_act(severity) if(cpu) cpu.ex_act(severity) + // switch(severity) + // if(EXPLODE_DEVASTATE) + // SSexplosions.highobj += cpu + // if(EXPLODE_HEAVY) + // SSexplosions.medobj += cpu + // if(EXPLODE_LIGHT) + // SSexplosions.lowobj += cpu ..() // EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components diff --git a/code/modules/modular_computers/computers/machinery/modular_console.dm b/code/modules/modular_computers/computers/machinery/modular_console.dm index 3d4ec22e89..5d596f98e4 100644 --- a/code/modules/modular_computers/computers/machinery/modular_console.dm +++ b/code/modules/modular_computers/computers/machinery/modular_console.dm @@ -52,4 +52,4 @@ network_card.identification_string = "Unknown Console" if(cpu) cpu.screen_on = 1 - update_icon() \ No newline at end of file + update_icon() diff --git a/code/modules/modular_computers/documentation.md b/code/modules/modular_computers/documentation.md index 246da7c3d9..88d059da7a 100644 --- a/code/modules/modular_computers/documentation.md +++ b/code/modules/modular_computers/documentation.md @@ -1,5 +1,7 @@ # Modular computer programs +How module computer programs work + Ok. so a quick rundown on how to make a program. This is kind of a shitty documentation, but oh well I was asked to. ## Base setup diff --git a/code/modules/modular_computers/file_system/computer_file.dm b/code/modules/modular_computers/file_system/computer_file.dm index 7776fc04d0..4e862c4ae3 100644 --- a/code/modules/modular_computers/file_system/computer_file.dm +++ b/code/modules/modular_computers/file_system/computer_file.dm @@ -3,8 +3,8 @@ var/filetype = "XXX" // File full names are [filename].[filetype] so like NewFile.XXX in this case var/size = 1 // File size in GQ. Integers only! var/obj/item/computer_hardware/hard_drive/holder // Holder that contains this file. - var/unsendable = 0 // Whether the file may be sent to someone via NTNet transfer or other means. - var/undeletable = 0 // Whether the file may be deleted. Setting to 1 prevents deletion/renaming/etc. + var/unsendable = FALSE // Whether the file may be sent to someone via NTNet transfer or other means. + var/undeletable = FALSE // Whether the file may be deleted. Setting to TRUE prevents deletion/renaming/etc. var/uid // UID of this file var/static/file_uid = 0 @@ -24,7 +24,7 @@ return ..() // Returns independent copy of this file. -/datum/computer_file/proc/clone(rename = 0) +/datum/computer_file/proc/clone(rename = FALSE) var/datum/computer_file/temp = new type temp.unsendable = unsendable temp.undeletable = undeletable @@ -34,4 +34,4 @@ else temp.filename = filename temp.filetype = filetype - return temp \ No newline at end of file + return temp diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index b54bc9f2be..12e5ef6e95 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -1,26 +1,40 @@ // /program/ files are executable programs that do things. /datum/computer_file/program filetype = "PRG" - filename = "UnknownProgram" // File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET! - var/required_access = null // List of required accesses to *run* the program. - var/transfer_access = null // List of required access to download or file host the program - var/program_state = PROGRAM_STATE_KILLED// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running. - var/obj/item/modular_computer/computer // Device that runs this program. - var/filedesc = "Unknown Program" // User-friendly name of this program. - var/extended_desc = "N/A" // Short description of this program's function. - var/program_icon_state = null // Program-specific screen icon state - var/requires_ntnet = 0 // Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes. - var/requires_ntnet_feature = 0 // Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION) - var/ntnet_status = 1 // NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc. - var/usage_flags = PROGRAM_ALL // Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL - var/network_destination = null // Optional string that describes what NTNet server/system this program connects to. Used in default logging. - var/available_on_ntnet = 1 // Whether the program can be downloaded from NTNet. Set to 0 to disable. - var/available_on_syndinet = 0 // Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable. - var/tgui_id // ID of TGUI interface - var/ui_style // ID of custom TGUI style (optional) - var/ui_x = 575 // Default size of TGUI window, in pixels - var/ui_y = 700 - var/ui_header = null // Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images! + /// File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NTNET! + filename = "UnknownProgram" + /// List of required accesses to *run* the program. + var/required_access = null + /// List of required access to download or file host the program + var/transfer_access = null + /// PROGRAM_STATE_KILLED or PROGRAM_STATE_BACKGROUND or PROGRAM_STATE_ACTIVE - specifies whether this program is running. + var/program_state = PROGRAM_STATE_KILLED + /// Device that runs this program. + var/obj/item/modular_computer/computer + /// User-friendly name of this program. + var/filedesc = "Unknown Program" + /// Short description of this program's function. + var/extended_desc = "N/A" + /// Program-specific screen icon state + var/program_icon_state = null + /// Set to 1 for program to require nonstop NTNet connection to run. If NTNet connection is lost program crashes. + var/requires_ntnet = FALSE + /// Optional, if above is set to 1 checks for specific function of NTNet (currently NTNET_SOFTWAREDOWNLOAD, NTNET_PEERTOPEER, NTNET_SYSTEMCONTROL and NTNET_COMMUNICATION) + var/requires_ntnet_feature = 0 + /// NTNet status, updated every tick by computer running this program. Don't use this for checks if NTNet works, computers do that. Use this for calculations, etc. + var/ntnet_status = 1 + /// Bitflags (PROGRAM_CONSOLE, PROGRAM_LAPTOP, PROGRAM_TABLET combination) or PROGRAM_ALL + var/usage_flags = PROGRAM_ALL + /// Optional string that describes what NTNet server/system this program connects to. Used in default logging. + var/network_destination = null + /// Whether the program can be downloaded from NTNet. Set to 0 to disable. + var/available_on_ntnet = 1 + /// Whether the program can be downloaded from SyndiNet (accessible via emagging the computer). Set to 1 to enable. + var/available_on_syndinet = 0 + /// Name of the tgui interface + var/tgui_id + /// Example: "something.gif" - a header image that will be rendered in computer's UI when this program is running at background. Images are taken from /icons/program_icons. Be careful not to use too large images! + var/ui_header = null /datum/computer_file/program/New(obj/item/modular_computer/comp = null) ..() @@ -55,7 +69,7 @@ /datum/computer_file/program/proc/is_supported_by_hardware(hardware_flag = 0, loud = 0, mob/user = null) if(!(hardware_flag & usage_flags)) if(loud && computer && user) - to_chat(user, "\The [computer] flashes an \"Hardware Error - Incompatible software\" warning.") + to_chat(user, "\The [computer] flashes a \"Hardware Error - Incompatible software\" warning.") return 0 return 1 @@ -87,7 +101,7 @@ if(IsAdminGhost(user)) return TRUE - if(computer && computer.hasSiliconAccessInArea(user)) + if(issilicon(user)) return TRUE if(ishuman(user)) @@ -98,6 +112,7 @@ D = card_slot.GetID() var/mob/living/carbon/human/h = user var/obj/item/card/id/I = h.get_idcard(TRUE) + if(!I && !D) if(loud) to_chat(user, "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.") @@ -111,7 +126,7 @@ return TRUE if(loud) to_chat(user, "\The [computer] flashes an \"Access Denied\" warning.") - return FALSE + return 0 // This attempts to retrieve header data for UIs. If implementing completely new device of different type than existing ones // always include the device here in this proc. This proc basically relays the request to whatever is running the program. @@ -127,7 +142,21 @@ if(requires_ntnet && network_destination) generate_network_log("Connection opened to [network_destination].") program_state = PROGRAM_STATE_ACTIVE - return TRUE + return 1 + return 0 + +/** + * + *Called by the device when it is emagged. + * + *Emagging the device allows certain programs to unlock new functions. However, the program will + *need to be downloaded first, and then handle the unlock on their own in their run_emag() proc. + *The device will allow an emag to be run multiple times, so the user can re-emag to run the + *override again, should they download something new. The run_emag() proc should return TRUE if + *the emagging affected anything, and FALSE if no change was made (already emagged, or has no + *emag functions). +**/ +/datum/computer_file/program/proc/run_emag() return FALSE // Use this proc to kill the program. Designed to be implemented by each program if it requires on-quit logic, such as the NTNRC client. @@ -135,40 +164,33 @@ program_state = PROGRAM_STATE_KILLED if(network_destination) generate_network_log("Connection to [network_destination] closed.") - return TRUE + return 1 - -/datum/computer_file/program/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/datum/computer_file/program/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui && tgui_id) - var/datum/asset/assets = get_asset_datum(/datum/asset/simple/headers) - assets.send(user) - - ui = new(user, src, ui_key, tgui_id, filedesc, ui_x, ui_y, state = state) - - if(ui_style) - ui.set_style(ui_style) - ui.set_autoupdate(state = 1) + ui = new(user, src, tgui_id, filedesc) ui.open() + ui.send_asset(get_asset_datum(/datum/asset/simple/headers)) // CONVENTIONS, READ THIS WHEN CREATING NEW PROGRAM AND OVERRIDING THIS PROC: // Topic calls are automagically forwarded from NanoModule this program contains. // Calls beginning with "PRG_" are reserved for programs handling. // Calls beginning with "PC_" are reserved for computer handling (by whatever runs the program) // ALWAYS INCLUDE PARENT CALL ..() OR DIE IN FIRE. -/datum/computer_file/program/ui_act(action,params,datum/tgui/ui) +/datum/computer_file/program/ui_act(action,list/params,datum/tgui/ui) if(..()) - return TRUE + return 1 if(computer) switch(action) if("PC_exit") computer.kill_program() ui.close() - return TRUE + return 1 if("PC_shutdown") computer.shutdown_computer() ui.close() - return TRUE + return 1 if("PC_minimize") var/mob/user = usr if(!computer.active_program || !computer.all_components[MC_CPU]) diff --git a/code/modules/modular_computers/file_system/program_events.dm b/code/modules/modular_computers/file_system/program_events.dm index 279d646cfd..3c1daa5af3 100644 --- a/code/modules/modular_computers/file_system/program_events.dm +++ b/code/modules/modular_computers/file_system/program_events.dm @@ -13,6 +13,6 @@ /datum/computer_file/program/proc/event_networkfailure(background) kill_program(forced = TRUE) if(background) - computer.visible_message("\The [computer]'s screen displays an \"Process [filename].[filetype] (PID [rand(100,999)]) terminated - Network Error\" error") + computer.visible_message("\The [computer]'s screen displays a \"Process [filename].[filetype] (PID [rand(100,999)]) terminated - Network Error\" error") else computer.visible_message("\The [computer]'s screen briefly freezes and then shows \"NETWORK ERROR - NTNet connection lost. Please retry. If problem persists contact your system administrator.\" error.") diff --git a/code/modules/modular_computers/file_system/programs/airestorer.dm b/code/modules/modular_computers/file_system/programs/airestorer.dm index 1aa292f247..364ad79737 100644 --- a/code/modules/modular_computers/file_system/programs/airestorer.dm +++ b/code/modules/modular_computers/file_system/programs/airestorer.dm @@ -4,14 +4,12 @@ program_icon_state = "generic" extended_desc = "This program is capable of reconstructing damaged AI systems. Requires direct AI connection via intellicard slot." size = 12 - requires_ntnet = 0 - usage_flags = PROGRAM_CONSOLE + requires_ntnet = FALSE + usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP transfer_access = ACCESS_HEADS - available_on_ntnet = 1 - tgui_id = "ntos_ai_restorer" - ui_x = 600 - ui_y = 400 - + available_on_ntnet = TRUE + tgui_id = "NtosAiRestorer" + /// Variable dictating if we are in the process of restoring the AI in the inserted intellicard var/restoring = FALSE /datum/computer_file/program/aidiag/proc/get_ai(cardcheck) @@ -30,11 +28,11 @@ if(ai_slot.stored_card.AI) return ai_slot.stored_card.AI - return null + return /datum/computer_file/program/aidiag/ui_act(action, params) if(..()) - return TRUE + return var/mob/living/silicon/ai/A = get_ai() if(!A) @@ -44,6 +42,7 @@ if("PRG_beginReconstruction") if(A && A.health < 100) restoring = TRUE + A.notify_ghost_cloning("Your core files are being restored!", source = computer) return TRUE if("PRG_eject") if(computer.all_components[MC_AI]) @@ -53,7 +52,7 @@ return TRUE /datum/computer_file/program/aidiag/process_tick() - ..() + . = ..() if(!restoring) //Put the check here so we don't check for an ai all the time return var/obj/item/aicard/cardhold = get_ai(2) @@ -73,13 +72,13 @@ restoring = FALSE return ai_slot.locked =TRUE - A.adjustOxyLoss(-1, 0) - A.adjustFireLoss(-1, 0) - A.adjustToxLoss(-1, 0) - A.adjustBruteLoss(-1, 0) + A.adjustOxyLoss(-5, 0)//, FALSE) + A.adjustFireLoss(-5, 0)//, FALSE) + A.adjustToxLoss(-5, 0) + A.adjustBruteLoss(-5, 0) A.updatehealth() if(A.health >= 0 && A.stat == DEAD) - A.revive() + A.revive(full_heal = FALSE, admin_revive = FALSE) // Finished restoring if(A.health >= 100) ai_slot.locked = FALSE @@ -90,14 +89,14 @@ /datum/computer_file/program/aidiag/ui_data(mob/user) var/list/data = get_header_data() - var/mob/living/silicon/ai/AI - // A shortcut for getting the AI stored inside the computer. The program already does necessary checks. - AI = get_ai() + var/mob/living/silicon/ai/AI = get_ai() var/obj/item/aicard/aicard = get_ai(2) + data["ejectable"] = TRUE + data["AI_present"] = FALSE + data["error"] = null if(!aicard) - data["nocard"] = TRUE data["error"] = "Please insert an intelliCard." else if(!AI) @@ -107,15 +106,15 @@ if(cardhold.flush) data["error"] = "Flush in progress" else + data["AI_present"] = TRUE data["name"] = AI.name data["restoring"] = restoring - data["laws"] = AI.laws.get_law_list(include_zeroth = 1) data["health"] = (AI.health + 100) / 2 data["isDead"] = AI.stat == DEAD - data["ai_laws"] = AI.laws.get_law_list(include_zeroth = 1) + data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE) return data /datum/computer_file/program/aidiag/kill_program(forced) restoring = FALSE - return ..(forced) \ No newline at end of file + return ..() diff --git a/code/modules/modular_computers/file_system/programs/alarm.dm b/code/modules/modular_computers/file_system/programs/alarm.dm index ca075b51e4..577fad83d0 100644 --- a/code/modules/modular_computers/file_system/programs/alarm.dm +++ b/code/modules/modular_computers/file_system/programs/alarm.dm @@ -7,10 +7,7 @@ requires_ntnet = 1 network_destination = "alarm monitoring network" size = 5 - tgui_id = "ntos_station_alert" - ui_x = 315 - ui_y = 500 - + tgui_id = "NtosStationAlertConsole" var/has_alert = 0 var/alarms = list("Fire" = list(), "Atmosphere" = list(), "Power" = list()) @@ -72,15 +69,23 @@ /datum/computer_file/program/alarm_monitor/proc/cancelAlarm(class, area/A, obj/origin) var/list/L = alarms[class] var/cleared = 0 + var/arealevelalarm = FALSE // set to TRUE for alarms that set/clear whole areas + if (class=="Fire") + arealevelalarm = TRUE for (var/I in L) if (I == A.name) - var/list/alarm = L[I] - var/list/srcs = alarm[3] - if (origin in srcs) - srcs -= origin - if (srcs.len == 0) + if (!arealevelalarm) // the traditional behaviour + var/list/alarm = L[I] + var/list/srcs = alarm[3] + if (origin in srcs) + srcs -= origin + if (srcs.len == 0) + cleared = 1 + L -= I + else + L -= I // wipe the instances entirely cleared = 1 - L -= I + update_alarm_display() return !cleared diff --git a/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm b/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm index 35470cdee9..3accb8e02d 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/contract_uplink.dm @@ -1,6 +1,6 @@ /datum/computer_file/program/contract_uplink filename = "contractor uplink" - filedesc = "Syndicate Contract Uplink" + filedesc = "Syndicate Contractor Uplink" program_icon_state = "assign" extended_desc = "A standard, Syndicate issued system for handling important contracts while on the field." size = 10 @@ -8,91 +8,110 @@ available_on_ntnet = 0 unsendable = 1 undeletable = 1 - tgui_id = "synd_contract" - ui_style = "syndicate" - ui_x = 600 - ui_y = 600 + tgui_id = "SyndContractor" var/error = "" - var/page = CONTRACT_UPLINK_PAGE_CONTRACTS + var/info_screen = TRUE var/assigned = FALSE + var/first_load = TRUE /datum/computer_file/program/contract_uplink/run_program(var/mob/living/user) . = ..(user) /datum/computer_file/program/contract_uplink/ui_act(action, params) if(..()) - return 1 + return TRUE + var/mob/living/user = usr var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD] + switch(action) if("PRG_contract-accept") var/contract_id = text2num(params["contract_id"]) + // Set as the active contract hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ACTIVE hard_drive.traitor_data.contractor_hub.current_contract = hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id] + program_icon_state = "single_contract" - return 1 + return TRUE if("PRG_login") var/datum/antagonist/traitor/traitor_data = user.mind.has_antag_datum(/datum/antagonist/traitor) - if(traitor_data) // Bake their data right into the hard drive, or we don't allow non-antags gaining access to unused contract system. We also create their contracts at this point. - if(!traitor_data.contractor_hub) // Only play greet sound, and handle contractor hub when assigning for the first time. + + // Bake their data right into the hard drive, or we don't allow non-antags gaining access to an unused + // contract system. + // We also create their contracts at this point. + if (traitor_data) + // Only play greet sound, and handle contractor hub when assigning for the first time. + if (!traitor_data.contractor_hub) + user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, FALSE) traitor_data.contractor_hub = new traitor_data.contractor_hub.create_hub_items() - user.playsound_local(user, 'sound/effects/contractstartup.ogg', 100, 0) - // Stops any topic exploits such as logging in multiple times on a single system. - if(!assigned) + + // Stops any topic exploits such as logging in multiple times on a single system. + if (!assigned) traitor_data.contractor_hub.create_contracts(traitor_data.owner) + hard_drive.traitor_data = traitor_data + program_icon_state = "contracts" assigned = TRUE else - error = "Incorrect login details." - return 1 + error = "UNAUTHORIZED USER" + return TRUE if("PRG_call_extraction") - if(hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING) - if(hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user)) - user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, 1) + if (hard_drive.traitor_data.contractor_hub.current_contract.status != CONTRACT_STATUS_EXTRACTING) + if (hard_drive.traitor_data.contractor_hub.current_contract.handle_extraction(user)) + user.playsound_local(user, 'sound/effects/confirmdropoff.ogg', 100, TRUE) hard_drive.traitor_data.contractor_hub.current_contract.status = CONTRACT_STATUS_EXTRACTING + program_icon_state = "extracted" else user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50) error = "Either both you or your target aren't at the dropoff location, or the pod hasn't got a valid place to land. Clear space, or make sure you're both inside." else user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50) - error = "Already extracting... Place the target into the pod. If the pod was destroyed, you will need to cancel this contract." - return 1 + error = "Already extracting... Place the target into the pod. If the pod was destroyed, this contract is no longer possible." + + return TRUE if("PRG_contract_abort") var/contract_id = hard_drive.traitor_data.contractor_hub.current_contract.id + hard_drive.traitor_data.contractor_hub.current_contract = null hard_drive.traitor_data.contractor_hub.assigned_contracts[contract_id].status = CONTRACT_STATUS_ABORTED + program_icon_state = "contracts" - return 1 + + return TRUE if("PRG_redeem_TC") - if(hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem) - var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user), hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem) + if (hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem) + var/obj/item/stack/telecrystal/crystals = new /obj/item/stack/telecrystal(get_turf(user), + hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem) if(ishuman(user)) var/mob/living/carbon/human/H = user if(H.put_in_hands(crystals)) to_chat(H, "Your payment materializes into your hands!") else to_chat(user, "Your payment materializes onto the floor.") + hard_drive.traitor_data.contractor_hub.contract_TC_payed_out += hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem hard_drive.traitor_data.contractor_hub.contract_TC_to_redeem = 0 - return 1 + return TRUE else user.playsound_local(user, 'sound/machines/uplinkerror.ogg', 50) - return 1 - if("PRG_clear_error") + return TRUE + if ("PRG_clear_error") error = "" - if("PRG_contractor_hub") - page = CONTRACT_UPLINK_PAGE_HUB - program_icon_state = "store" - if("PRG_hub_back") - page = CONTRACT_UPLINK_PAGE_CONTRACTS - program_icon_state = "contracts" - if("buy_hub") - if(hard_drive.traitor_data.owner.current == user) + return TRUE + if("PRG_set_first_load_finished") + first_load = FALSE + return TRUE + if("PRG_toggle_info") + info_screen = !info_screen + return TRUE + if ("buy_hub") + if (hard_drive.traitor_data.owner.current == user) var/item = params["item"] + for (var/datum/contractor_item/hub_item in hard_drive.traitor_data.contractor_hub.hub_items) if (hub_item.name == item) hub_item.handle_purchase(hard_drive.traitor_data.contractor_hub, user) @@ -104,23 +123,36 @@ var/obj/item/computer_hardware/hard_drive/small/syndicate/hard_drive = computer.all_components[MC_HDD] var/screen_to_be = null - if(hard_drive && hard_drive.traitor_data != null) + data["first_load"] = first_load + + if (hard_drive && hard_drive.traitor_data != null) var/datum/antagonist/traitor/traitor_data = hard_drive.traitor_data - error = "" - data = get_header_data() - if(traitor_data.contractor_hub.current_contract) + data += get_header_data() + + if (traitor_data.contractor_hub.current_contract) data["ongoing_contract"] = TRUE screen_to_be = "single_contract" - if(traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING) + if (traitor_data.contractor_hub.current_contract.status == CONTRACT_STATUS_EXTRACTING) data["extraction_enroute"] = TRUE screen_to_be = "extracted" + else + data["extraction_enroute"] = FALSE + else + data["ongoing_contract"] = FALSE + data["extraction_enroute"] = FALSE + data["logged_in"] = TRUE data["station_name"] = GLOB.station_name data["redeemable_tc"] = traitor_data.contractor_hub.contract_TC_to_redeem + data["earned_tc"] = traitor_data.contractor_hub.contract_TC_payed_out + data["contracts_completed"] = traitor_data.contractor_hub.contracts_completed data["contract_rep"] = traitor_data.contractor_hub.contract_rep - data["page"] = page + + data["info_screen"] = info_screen + data["error"] = error - for(var/datum/contractor_item/hub_item in traitor_data.contractor_hub.hub_items) + + for (var/datum/contractor_item/hub_item in traitor_data.contractor_hub.hub_items) data["contractor_hub_items"] += list(list( "name" = hub_item.name, "desc" = hub_item.desc, @@ -128,7 +160,8 @@ "limited" = hub_item.limited, "item_icon" = hub_item.item_icon )) - for(var/datum/syndicate_contract/contract in traitor_data.contractor_hub.assigned_contracts) + + for (var/datum/syndicate_contract/contract in traitor_data.contractor_hub.assigned_contracts) data["contracts"] += list(list( "target" = contract.contract.target, "target_rank" = contract.target_rank, @@ -136,33 +169,33 @@ "payout_bonus" = contract.contract.payout_bonus, "dropoff" = contract.contract.dropoff, "id" = contract.id, - "status" = contract.status + "status" = contract.status, + "message" = contract.wanted_message )) var/direction - if(traitor_data.contractor_hub.current_contract) + if (traitor_data.contractor_hub.current_contract) var/turf/curr = get_turf(user) var/turf/dropoff_turf data["current_location"] = "[get_area_name(curr, TRUE)]" - for(var/turf/content in traitor_data.contractor_hub.current_contract.contract.dropoff.contents) - if(isturf(content)) + + for (var/turf/content in traitor_data.contractor_hub.current_contract.contract.dropoff.contents) + if (isturf(content)) dropoff_turf = content break + if(curr.z == dropoff_turf.z) //Direction calculations for same z-level only direction = uppertext(dir2text(get_dir(curr, dropoff_turf))) //Direction text (East, etc). Not as precise, but still helpful. if(get_area(user) == traitor_data.contractor_hub.current_contract.contract.dropoff) direction = "LOCATION CONFIRMED" else direction = "???" + data["dropoff_direction"] = direction - if (page == CONTRACT_UPLINK_PAGE_HUB) - screen_to_be = "store" - if (!screen_to_be) - screen_to_be = "contracts" + else data["logged_in"] = FALSE - if (!screen_to_be) - screen_to_be = "assign" + program_icon_state = screen_to_be update_computer_icon() - return data \ No newline at end of file + return data diff --git a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm index 337e98acaa..803dadc0a0 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/dos.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/dos.dm @@ -4,13 +4,10 @@ program_icon_state = "hostile" extended_desc = "This advanced script can perform denial of service attacks against NTNet quantum relays. The system administrator will probably notice this. Multiple devices can run this program together against same relay for increased effect" size = 20 - requires_ntnet = 1 - available_on_ntnet = 0 - available_on_syndinet = 1 - tgui_id = "ntos_net_dos" - ui_style = "syndicate" - ui_x = 400 - ui_y = 250 + requires_ntnet = TRUE + available_on_ntnet = FALSE + available_on_syndinet = TRUE + tgui_id = "NtosNetDos" var/obj/machinery/ntnet_relay/target = null var/dos_speed = 0 @@ -37,64 +34,55 @@ if(target) target.dos_sources.Remove(src) target = null - executed = 0 + executed = FALSE ..() /datum/computer_file/program/ntnet_dos/ui_act(action, params) if(..()) - return 1 + return switch(action) if("PRG_target_relay") for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays) if("[R.uid]" == params["targid"]) target = R - return 1 + break + return TRUE if("PRG_reset") if(target) target.dos_sources.Remove(src) target = null - executed = 0 + executed = FALSE error = "" - return 1 + return TRUE if("PRG_execute") if(target) - executed = 1 + executed = TRUE target.dos_sources.Add(src) if(SSnetworks.station_network.intrusion_detection_enabled) var/obj/item/computer_hardware/network_card/network_card = computer.all_components[MC_NET] SSnetworks.station_network.add_log("IDS WARNING - Excess traffic flood targeting relay [target.uid] detected from device: [network_card.get_network_tag()]") - SSnetworks.station_network.intrusion_detection_alarm = 1 - return 1 + SSnetworks.station_network.intrusion_detection_alarm = TRUE + return TRUE /datum/computer_file/program/ntnet_dos/ui_data(mob/user) if(!SSnetworks.station_network) return - var/list/data = list() + var/list/data = get_header_data() - data = get_header_data() - - if(error) - data["error"] = error - else if(target && executed) - data["target"] = 1 + data["error"] = error + if(target && executed) + data["target"] = TRUE data["speed"] = dos_speed - // This is mostly visual, generate some strings of 1s and 0s - // Probability of 1 is equal of completion percentage of DoS attack on this relay. - // Combined with UI updates this adds quite nice effect to the UI - var/percentage = target.dos_overload * 100 / target.dos_capacity - data["dos_strings"] = list() - for(var/j, j<10, j++) - var/string = "" - for(var/i, i<20, i++) - string = "[string][prob(percentage)]" - data["dos_strings"] += list(list("nums" = string)) + data["overload"] = target.dos_overload + data["capacity"] = target.dos_capacity else + data["target"] = FALSE data["relays"] = list() for(var/obj/machinery/ntnet_relay/R in SSnetworks.station_network.relays) data["relays"] += list(list("id" = R.uid)) data["focus"] = target ? target.uid : null - return data \ No newline at end of file + return data diff --git a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm index 103b70e496..2ba3d69fe6 100644 --- a/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm +++ b/code/modules/modular_computers/file_system/programs/antagonist/revelation.dm @@ -4,14 +4,10 @@ program_icon_state = "hostile" extended_desc = "This virus can destroy hard drive of system it is executed on. It may be obfuscated to look like another non-malicious program. Once armed, it will destroy the system upon next execution." size = 13 - requires_ntnet = 0 - available_on_ntnet = 0 - available_on_syndinet = 1 - tgui_id = "ntos_revelation" - ui_style = "syndicate" - ui_x = 400 - ui_y = 250 - + requires_ntnet = FALSE + available_on_ntnet = FALSE + available_on_syndinet = TRUE + tgui_id = "NtosRevelation" var/armed = 0 /datum/computer_file/program/revelation/run_program(var/mob/living/user) @@ -22,7 +18,7 @@ /datum/computer_file/program/revelation/proc/activate() if(computer) computer.visible_message("\The [computer]'s screen brightly flashes and loud electrical buzzing is heard.") - computer.enabled = 0 + computer.enabled = FALSE computer.update_icon() var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] var/obj/item/computer_hardware/battery/battery_module = computer.all_components[MC_CELL] @@ -44,18 +40,20 @@ /datum/computer_file/program/revelation/ui_act(action, params) if(..()) - return 1 + return switch(action) if("PRG_arm") armed = !armed + return TRUE if("PRG_activate") activate() + return TRUE if("PRG_obfuscate") - var/mob/living/user = usr - var/newname = sanitize(input(user, "Enter new program name: ")) + var/newname = params["new_name"] if(!newname) return filedesc = newname + return TRUE /datum/computer_file/program/revelation/clone() @@ -68,4 +66,4 @@ data["armed"] = armed - return data \ No newline at end of file + return data diff --git a/code/modules/modular_computers/file_system/programs/arcade.dm b/code/modules/modular_computers/file_system/programs/arcade.dm new file mode 100644 index 0000000000..2503073f9a --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/arcade.dm @@ -0,0 +1,173 @@ +/datum/computer_file/program/arcade + filename = "arcade" + filedesc = "Nanotrasen Micro Arcade" + program_icon_state = "arcade" + extended_desc = "This port of the classic game 'Outbomb Cuban Pete', redesigned to run on tablets, with thrilling graphics and chilling storytelling." + requires_ntnet = FALSE + network_destination = "arcade network" + size = 6 + tgui_id = "NtosArcade" + + ///Returns TRUE if the game is being played. + var/game_active = TRUE + ///This disables buttom actions from having any impact if TRUE. Resets to FALSE when the player is allowed to make an action again. + var/pause_state = FALSE + var/boss_hp = 45 + var/boss_mp = 15 + var/player_hp = 30 + var/player_mp = 10 + var/ticket_count = 0 + ///Shows what text is shown on the app, usually showing the log of combat actions taken by the player. + var/heads_up = "Nanotrasen says, winners make us money." + var/boss_name = "Cuban Pete's Minion" + ///Determines which boss image to use on the UI. + var/boss_id = 1 + +/datum/computer_file/program/arcade/proc/game_check(mob/user) + sleep(5) + //user?.mind?.adjust_experience(/datum/skill/gaming, 1) No gaming(TM) Yet + if(boss_hp <= 0) + heads_up = "You have crushed [boss_name]! Rejoice!" + playsound(computer.loc, 'sound/arcade/win.ogg', 50, TRUE, extrarange = -3, falloff = 10) + game_active = FALSE + program_icon_state = "arcade_off" + if(istype(computer)) + computer.update_icon() + ticket_count += 1 + //user?.mind?.adjust_experience(/datum/skill/gaming, 50) + sleep(10) + else if(player_hp <= 0 || player_mp <= 0) + heads_up = "You have been defeated... how will the station survive?" + playsound(computer.loc, 'sound/arcade/lose.ogg', 50, TRUE, extrarange = -3, falloff = 10) + game_active = FALSE + program_icon_state = "arcade_off" + if(istype(computer)) + computer.update_icon() + //user?.mind?.adjust_experience(/datum/skill/gaming, 10) + sleep(10) + +/datum/computer_file/program/arcade/proc/enemy_check(mob/user) + var/boss_attackamt = 0 //Spam protection from boss attacks as well. + var/boss_mpamt = 0 + var/bossheal = 0 + if(pause_state == TRUE) + boss_attackamt = rand(3,6) + boss_mpamt = rand (2,4) + bossheal = rand (4,6) + if(game_active == FALSE) + return + if (boss_mp <= 5) + heads_up = "[boss_mpamt] magic power has been stolen from you!" + playsound(computer.loc, 'sound/arcade/steal.ogg', 50, TRUE, extrarange = -3, falloff = 10) + player_mp -= boss_mpamt + boss_mp += boss_mpamt + else if(boss_mp > 5 && boss_hp <12) + heads_up = "[boss_name] heals for [bossheal] health!" + playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10) + boss_hp += bossheal + boss_mp -= boss_mpamt + else + heads_up = "[boss_name] attacks you for [boss_attackamt] damage!" + playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10) + player_hp -= boss_attackamt + + pause_state = FALSE + game_check() + +/datum/computer_file/program/arcade/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/simple/arcade), + ) + +/datum/computer_file/program/arcade/ui_data(mob/user) + var/list/data = get_header_data() + data["Hitpoints"] = boss_hp + data["PlayerHitpoints"] = player_hp + data["PlayerMP"] = player_mp + data["TicketCount"] = ticket_count + data["GameActive"] = game_active + data["PauseState"] = pause_state + data["Status"] = heads_up + data["BossID"] = "boss[boss_id].gif" + return data + +/datum/computer_file/program/arcade/ui_act(action, list/params) + if(..()) + return TRUE + var/obj/item/computer_hardware/printer/printer + if(computer) + printer = computer.all_components[MC_PRINT] + + //var/gamerSkillLevel = usr.mind?.get_skill_level(/datum/skill/gaming) + //var/gamerSkill = usr.mind?.get_skill_modifier(/datum/skill/gaming, SKILL_RANDS_MODIFIER) + switch(action) + if("Attack") + var/attackamt = 0 //Spam prevention. + if(pause_state == FALSE) + attackamt = rand(2,6)// + rand(0, gamerSkill) + pause_state = TRUE + heads_up = "You attack for [attackamt] damage." + playsound(computer.loc, 'sound/arcade/hit.ogg', 50, TRUE, extrarange = -3, falloff = 10) + boss_hp -= attackamt + sleep(10) + game_check() + enemy_check() + return TRUE + if("Heal") + var/healamt = 0 //More Spam Prevention. + var/healcost = 0 + if(pause_state == FALSE) + healamt = rand(6,8)// + rand(0, gamerSkill) + var/maxPointCost = 3 + //if(gamerSkillLevel >= SKILL_LEVEL_JOURNEYMAN) + // maxPointCost = 2 + healcost = rand(1, maxPointCost) + pause_state = TRUE + heads_up = "You heal for [healamt] damage." + playsound(computer.loc, 'sound/arcade/heal.ogg', 50, TRUE, extrarange = -3, falloff = 10) + player_hp += healamt + player_mp -= healcost + sleep(10) + game_check() + enemy_check() + return TRUE + if("Recharge_Power") + var/rechargeamt = 0 //As above. + if(pause_state == FALSE) + rechargeamt = rand(4,7)// + rand(0, gamerSkill) + pause_state = TRUE + heads_up = "You regain [rechargeamt] magic power." + playsound(computer.loc, 'sound/arcade/mana.ogg', 50, TRUE, extrarange = -3, falloff = 10) + player_mp += rechargeamt + sleep(10) + game_check() + enemy_check() + return TRUE + if("Dispense_Tickets") + if(!printer) + to_chat(usr, "Hardware error: A printer is required to redeem tickets.") + return + if(printer.stored_paper <= 0) + to_chat(usr, "Hardware error: Printer is out of paper.") + return + else + computer.visible_message("\The [computer] prints out paper.") + if(ticket_count >= 1) + new /obj/item/stack/arcadeticket((get_turf(computer)), 1) + to_chat(usr, "[src] dispenses a ticket!") + ticket_count -= 1 + printer.stored_paper -= 1 + else + to_chat(usr, "You don't have any stored tickets!") + return TRUE + if("Start_Game") + game_active = TRUE + boss_hp = 45 + player_hp = 30 + player_mp = 10 + heads_up = "You stand before [boss_name]! Prepare for battle!" + program_icon_state = "arcade" + boss_id = rand(1,6) + pause_state = FALSE + if(istype(computer)) + computer.update_icon() diff --git a/code/modules/modular_computers/file_system/programs/atmosscan.dm b/code/modules/modular_computers/file_system/programs/atmosscan.dm new file mode 100644 index 0000000000..2df751bebd --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/atmosscan.dm @@ -0,0 +1,31 @@ +/datum/computer_file/program/atmosscan + filename = "atmosscan" + filedesc = "Atmospheric Scanner" + program_icon_state = "air" + extended_desc = "A small built-in sensor reads out the atmospheric conditions around the device." + network_destination = "atmos scan" + size = 4 + tgui_id = "NtosAtmos" + +/datum/computer_file/program/atmosscan/ui_data(mob/user) + var/list/data = get_header_data() + var/list/airlist = list() + var/turf/T = get_turf(ui_host()) + if(T) + var/datum/gas_mixture/environment = T.return_air() + var/list/env_gases = environment.get_gases() + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles() + data["AirPressure"] = round(pressure,0.1) + data["AirTemp"] = round(environment.return_temperature()-T0C) + if (total_moles) + for(var/id in env_gases) + var/gas_level = environment.get_moles(id)/total_moles + if(gas_level > 0) + airlist += list(list("name" = "[GLOB.meta_gas_names[id]]", "percentage" = round(gas_level*100, 0.01))) + data["AirData"] = airlist + return data + +/datum/computer_file/program/atmosscan/ui_act(action, list/params) + if(..()) + return TRUE diff --git a/code/modules/modular_computers/file_system/programs/borg_monitor.dm b/code/modules/modular_computers/file_system/programs/borg_monitor.dm new file mode 100644 index 0000000000..c2160a0e92 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/borg_monitor.dm @@ -0,0 +1,104 @@ +/datum/computer_file/program/borg_monitor + filename = "cyborgmonitor" + filedesc = "Cyborg Remote Monitoring" + ui_header = "borg_mon.gif" + program_icon_state = "generic" + extended_desc = "This program allows for remote monitoring of station cyborgs." + requires_ntnet = TRUE + transfer_access = ACCESS_ROBOTICS + network_destination = "cyborg remote monitoring" + size = 5 + tgui_id = "NtosCyborgRemoteMonitor" + +/datum/computer_file/program/borg_monitor/ui_data(mob/user) + var/list/data = get_header_data() + + data["card"] = FALSE + if(checkID()) + data["card"] = TRUE + + data["cyborgs"] = list() + for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs) + if(!evaluate_borg(R)) + continue + + var/list/upgrade + for(var/obj/item/borg/upgrade/I in R.upgrades) + upgrade += "\[[I.name]\] " + + var/shell = FALSE + if(R.shell && !R.ckey) + shell = TRUE + + var/list/cyborg_data = list( + name = R.name, + locked_down = R.lockcharge, + status = R.stat, + shell_discon = shell, + charge = R.cell ? round(R.cell.percent()) : null, + module = R.module ? "[R.module.name] Module" : "No Module Detected", + upgrades = upgrade, + ref = REF(R) + ) + data["cyborgs"] += list(cyborg_data) + return data + +/datum/computer_file/program/borg_monitor/ui_act(action, params) + if(..()) + return + + switch(action) + if("messagebot") + var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs + if(!istype(R)) + return + var/ID = checkID() + if(!ID) + return + var/message = stripped_input(usr, message = "Enter message to be sent to remote cyborg.", title = "Send Message") + if(!message) + return + to_chat(R, "

    Message from [ID] -- \"[message]\"
    ") + SEND_SOUND(R, 'sound/machines/twobeep_high.ogg') + if(R.connected_ai) + to_chat(R.connected_ai, "

    Message from [ID] to [R] -- \"[message]\"
    ") + SEND_SOUND(R.connected_ai, 'sound/machines/twobeep_high.ogg') + usr.log_talk(message, LOG_PDA, tag="Cyborg Monitor Program: ID name \"[ID]\" to [R]") + +///This proc is used to determin if a borg should be shown in the list (based on the borg's scrambledcodes var). Syndicate version overrides this to show only syndicate borgs. +/datum/computer_file/program/borg_monitor/proc/evaluate_borg(mob/living/silicon/robot/R) + if((get_turf(computer)).z != (get_turf(R)).z) + return FALSE + if(R.scrambledcodes) + return FALSE + return TRUE + +///Gets the ID's name, if one is inserted into the device. This is a seperate proc solely to be overridden by the syndicate version of the app. +/datum/computer_file/program/borg_monitor/proc/checkID() + var/obj/item/card/id/ID = computer.GetID() + if(!ID) + return FALSE + return ID.registered_name + +/datum/computer_file/program/borg_monitor/syndicate + filename = "scyborgmonitor" + filedesc = "Mission-Specific Cyborg Remote Monitoring" + ui_header = "borg_mon.gif" + program_icon_state = "generic" + extended_desc = "This program allows for remote monitoring of mission-assigned cyborgs." + requires_ntnet = FALSE + available_on_ntnet = FALSE + available_on_syndinet = TRUE + transfer_access = null + network_destination = "cyborg remote monitoring" + tgui_id = "NtosCyborgRemoteMonitorSyndicate" + +/datum/computer_file/program/borg_monitor/syndicate/evaluate_borg(mob/living/silicon/robot/R) + if((get_turf(computer)).z != (get_turf(R)).z) + return FALSE + if(!R.scrambledcodes) + return FALSE + return TRUE + +/datum/computer_file/program/borg_monitor/syndicate/checkID() + return "\[CLASSIFIED\]" //no ID is needed for the syndicate version's message function, and the borg will see "[CLASSIFIED]" as the message sender. diff --git a/code/modules/modular_computers/file_system/programs/bounty_board.dm b/code/modules/modular_computers/file_system/programs/bounty_board.dm new file mode 100644 index 0000000000..46fde84f65 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/bounty_board.dm @@ -0,0 +1,120 @@ +/datum/computer_file/program/bounty_board + filename = "bountyboard" + filedesc = "Bounty Board Request Network" + program_icon_state = "bountyboard" + extended_desc = "A multi-platform network for placing requests across the station, with payment across the network being possible.." + requires_ntnet = TRUE + network_destination = "bounty board interface" + size = 10 + tgui_id = "NtosRequestKiosk" + ///Reference to the currently logged in user. + var/datum/bank_account/current_user + ///The station request datum being affected by UI actions. + var/datum/station_request/active_request + ///Value of the currently bounty input + var/bounty_value = 1 + ///Text of the currently written bounty + var/bounty_text = "" + ///Has the app been added to the network yet? + var/networked = FALSE + +/datum/computer_file/program/bounty_board/ui_data(mob/user) + var/list/data = get_header_data() + var/list/formatted_requests = list() + var/list/formatted_applicants = list() + var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] + if(!networked) + GLOB.allbountyboards += computer + networked = TRUE + if(card_slot && card_slot.stored_card && card_slot.stored_card.registered_account) + current_user = card_slot.stored_card.registered_account + for(var/i in GLOB.request_list) + if(!i) + continue + var/datum/station_request/request = i + formatted_requests += list(list("owner" = request.owner, "value" = request.value, "description" = request.description, "acc_number" = request.req_number)) + if(request.applicants) + for(var/datum/bank_account/j in request.applicants) + formatted_applicants += list(list("name" = j.account_holder, "request_id" = request.owner_account.account_id, "requestee_id" = j.account_id)) + if(current_user) + data["accountName"] = current_user.account_holder + data["requests"] = formatted_requests + data["applicants"] = formatted_applicants + data["bountyValue"] = bounty_value + data["bountyText"] = bounty_text + return data + +/datum/computer_file/program/bounty_board/ui_act(action, list/params) + if(..()) + return + var/current_ref_num = params["request"] + var/current_app_num = params["applicant"] + var/datum/bank_account/request_target + if(current_ref_num) + for(var/datum/station_request/i in GLOB.request_list) + if("[i.req_number]" == "[current_ref_num]") + active_request = i + break + if(active_request) + for(var/datum/bank_account/j in active_request.applicants) + if("[j.account_id]" == "[current_app_num]") + request_target = j + break + switch(action) + if("createBounty") + if(!current_user || !bounty_text) + playsound(src, 'sound/machines/buzz-sigh.ogg', 20, TRUE) + return TRUE + for(var/datum/station_request/i in GLOB.request_list) + if("[i.req_number]" == "[current_user.account_id]") + computer.say("Account already has active bounty.") + return + var/datum/station_request/curr_request = new /datum/station_request(current_user.account_holder, bounty_value,bounty_text,current_user.account_id, current_user) + GLOB.request_list += list(curr_request) + for(var/obj/i in GLOB.allbountyboards) + i.say("New bounty has been added!") + playsound(i.loc, 'sound/effects/cashregister.ogg', 30, TRUE) + return TRUE + if("apply") + if(!current_user) + computer.say("Please swipe a valid ID first.") + return TRUE + if(current_user.account_holder == active_request.owner) + playsound(computer, 'sound/machines/buzz-sigh.ogg', 20, TRUE) + return TRUE + active_request.applicants += list(current_user) + if("payApplicant") + if(!current_user) + return + if(!current_user.has_money(active_request.value) || (current_user.account_holder != active_request.owner)) + playsound(computer, 'sound/machines/buzz-sigh.ogg', 30, TRUE) + return + request_target.transfer_money(current_user, active_request.value) + computer.say("Paid out [active_request.value] credits.") + return TRUE + if("clear") + if(current_user) + current_user = null + computer.say("Account Reset.") + return TRUE + if("deleteRequest") + if(!current_user) + playsound(computer, 'sound/machines/buzz-sigh.ogg', 20, TRUE) + return TRUE + if(active_request.owner != current_user.account_holder) + playsound(computer, 'sound/machines/buzz-sigh.ogg', 20, TRUE) + return TRUE + computer.say("Deleted current request.") + GLOB.request_list.Remove(active_request) + return TRUE + if("bountyVal") + bounty_value = text2num(params["bountyval"]) + if(!bounty_value) + bounty_value = 1 + if("bountyText") + bounty_text = (params["bountytext"]) + . = TRUE + +/datum/computer_file/program/bounty_board/Destroy() + GLOB.allbountyboards -= computer + . = ..() diff --git a/code/modules/modular_computers/file_system/programs/card.dm b/code/modules/modular_computers/file_system/programs/card.dm index bf58b120f2..842d6e2588 100644 --- a/code/modules/modular_computers/file_system/programs/card.dm +++ b/code/modules/modular_computers/file_system/programs/card.dm @@ -1,3 +1,11 @@ +#define CARDCON_DEPARTMENT_SERVICE "Service" +#define CARDCON_DEPARTMENT_SECURITY "Security" +#define CARDCON_DEPARTMENT_MEDICAL "Medical" +#define CARDCON_DEPARTMENT_SUPPLY "Supply" +#define CARDCON_DEPARTMENT_SCIENCE "Science" +#define CARDCON_DEPARTMENT_ENGINEERING "Engineering" +#define CARDCON_DEPARTMENT_COMMAND "Command" + /datum/computer_file/program/card_mod filename = "cardmod" filedesc = "ID Card Modification" @@ -6,97 +14,88 @@ transfer_access = ACCESS_HEADS requires_ntnet = 0 size = 8 - tgui_id = "ntos_card" - ui_x = 600 - ui_y = 700 + tgui_id = "NtosCard" - var/mod_mode = 1 - var/is_centcom = 0 - var/show_assignments = 0 - var/minor = 0 - var/authenticated = 0 - var/list/reg_ids = list() - var/list/region_access = null - var/list/head_subordinates = null - var/target_dept = 0 //Which department this computer has access to. 0=all departments - var/change_position_cooldown = 30 - //Jobs you cannot open new positions for - var/list/blacklisted = list( - "AI", - "Assistant", - "Cyborg", - "Captain", - "Head of Personnel", - "Head of Security", - "Chief Engineer", - "Research Director", - "Chief Medical Officer") + var/is_centcom = FALSE + var/minor = FALSE + var/authenticated = FALSE + var/list/region_access + var/list/head_subordinates + ///Which departments this computer has access to. Defined as access regions. null = all departments + var/target_dept - //The scaling factor of max total positions in relation to the total amount of people on board the station in % - var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players + //For some reason everything was exploding if this was static. + var/list/sub_managers - //This is used to keep track of opened positions for jobs to allow instant closing - //Assoc array: "JobName" = (int) - var/list/opened_positions = list(); +/datum/computer_file/program/card_mod/New(obj/item/modular_computer/comp) + . = ..() + sub_managers = list( + "[ACCESS_HOP]" = list( + "department" = list(CARDCON_DEPARTMENT_SERVICE, CARDCON_DEPARTMENT_COMMAND), + "region" = 1, + "head" = "Head of Personnel" + ), + "[ACCESS_HOS]" = list( + "department" = CARDCON_DEPARTMENT_SECURITY, + "region" = 2, + "head" = "Head of Security" + ), + "[ACCESS_CMO]" = list( + "department" = CARDCON_DEPARTMENT_MEDICAL, + "region" = 3, + "head" = "Chief Medical Officer" + ), + "[ACCESS_RD]" = list( + "department" = CARDCON_DEPARTMENT_SCIENCE, + "region" = 4, + "head" = "Research Director" + ), + "[ACCESS_CE]" = list( + "department" = CARDCON_DEPARTMENT_ENGINEERING, + "region" = 5, + "head" = "Chief Engineer" + ) + ) -/datum/computer_file/program/card_mod/New() - ..() - addtimer(CALLBACK(src, .proc/SetConfigCooldown), 0) +/datum/computer_file/program/card_mod/proc/authenticate(mob/user, obj/item/card/id/id_card) + if(!id_card) + return -/datum/computer_file/program/card_mod/proc/SetConfigCooldown() - change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay) + region_access = list() + if(!target_dept && (ACCESS_CHANGE_IDS in id_card.access)) + minor = FALSE + authenticated = TRUE + update_static_data(user) + return TRUE -/datum/computer_file/program/card_mod/event_idremoved(background, slot) - if(!slot || slot == 2)// slot being false means both are removed - minor = 0 - authenticated = 0 - head_subordinates = null - region_access = null + var/list/head_types = list() + for(var/access_text in sub_managers) + var/list/info = sub_managers[access_text] + var/access = text2num(access_text) + if((access in id_card.access) && ((info["region"] in target_dept) || !length(target_dept))) + region_access += info["region"] + //I don't even know what I'm doing anymore + head_types += info["head"] + head_subordinates = list() + if(length(head_types)) + for(var/j in SSjob.occupations) + var/datum/job/job = j + for(var/head in head_types)//god why + if(head in job.department_head) + head_subordinates += job.title -/datum/computer_file/program/card_mod/proc/job_blacklisted(jobtitle) - return (jobtitle in blacklisted) + if(length(region_access)) + minor = TRUE + authenticated = TRUE + update_static_data(user) + return TRUE - -//Logic check for if you can open the job -/datum/computer_file/program/card_mod/proc/can_open_job(datum/job/job) - if(job) - if(!job_blacklisted(job.title)) - if((job.total_positions <= GLOB.player_list.len * (max_relative_positions / 100))) - var/delta = (world.time / 10) - GLOB.time_last_changed_position - if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) - return 1 - return -2 - return 0 - return 0 - -//Logic check for if you can close the job -/datum/computer_file/program/card_mod/proc/can_close_job(datum/job/job) - if(job) - if(!job_blacklisted(job.title)) - if(job.total_positions > job.current_positions) - var/delta = (world.time / 10) - GLOB.time_last_changed_position - if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) - return 1 - return -2 - return 0 - return 0 - -/datum/computer_file/program/card_mod/proc/format_jobs(list/jobs) - var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] - var/obj/item/card/id/id_card = card_slot.stored_card - var/list/formatted = list() - for(var/job in jobs) - formatted.Add(list(list( - "display_name" = replacetext(job, " ", " "), - "target_rank" = id_card && id_card.assignment ? id_card.assignment : "Unassigned", - "job" = job))) - - return formatted + return FALSE /datum/computer_file/program/card_mod/ui_act(action, params) if(..()) - return 1 + return TRUE var/obj/item/computer_hardware/card_slot/card_slot var/obj/item/computer_hardware/printer/printer @@ -106,192 +105,220 @@ if(!card_slot) return - var/obj/item/card/id/user_id_card = null var/mob/user = usr + var/obj/item/card/id/user_id_card = user.get_idcard(FALSE) var/obj/item/card/id/id_card = card_slot.stored_card - var/obj/item/card/id/auth_card = card_slot.stored_card2 - - if(auth_card) - user_id_card = auth_card - else - if(ishuman(user)) - var/mob/living/carbon/human/h = user - user_id_card = h.get_idcard(TRUE) switch(action) - if("PRG_switchm") - if(params["target"] == "mod") - mod_mode = 1 - else if (params["target"] == "manifest") - mod_mode = 0 - else if (params["target"] == "manage") - mod_mode = 2 - if("PRG_togglea") - if(show_assignments) - show_assignments = 0 - else - show_assignments = 1 + if("PRG_authenticate") + if(!computer || !user_id_card) + playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) + return + if(authenticate(user, user_id_card)) + playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE) + return TRUE + if("PRG_logout") + authenticated = FALSE + playsound(computer, 'sound/machines/terminal_off.ogg', 50, FALSE) + return TRUE if("PRG_print") - if(computer && printer) //This option should never be called if there is no printer - if(mod_mode) - if(authorized()) - var/contents = {"

    Access Report

    - Prepared By: [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]
    - For: [id_card.registered_name ? id_card.registered_name : "Unregistered"]
    -
    - Assignment: [id_card.assignment]
    - Access:
    - "} + if(!computer || !printer) + return + if(!authenticated) + return + var/contents = {"

    Access Report

    + Prepared By: [user_id_card && user_id_card.registered_name ? user_id_card.registered_name : "Unknown"]
    + For: [id_card.registered_name ? id_card.registered_name : "Unregistered"]
    +
    + Assignment: [id_card.assignment]
    + Access:
    + "} - var/known_access_rights = get_all_accesses() - for(var/A in id_card.access) - if(A in known_access_rights) - contents += " [get_access_desc(A)]" + var/known_access_rights = get_all_accesses() + for(var/A in id_card.access) + if(A in known_access_rights) + contents += " [get_access_desc(A)]" - if(!printer.print_text(contents,"access report")) - to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.") - return - else - computer.visible_message("\The [computer] prints out paper.") - else - var/contents = {"

    Crew Manifest

    -
    - [GLOB.data_core ? GLOB.data_core.get_manifest(0) : ""] - "} - if(!printer.print_text(contents,text("crew manifest ([])", STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)))) - to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.") - return - else - computer.visible_message("\The [computer] prints out paper.") - if("PRG_eject") - if(computer && card_slot) - var/select = params["target"] - switch(select) - if("id") - if(id_card) - GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment) - card_slot.try_eject(1, user) - else - var/obj/item/I = usr.get_active_held_item() - if (istype(I, /obj/item/card/id)) - if(!usr.transferItemToLoc(I, computer)) - return - card_slot.stored_card = I - if("auth") - if(auth_card) - if(id_card) - GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment) - head_subordinates = null - region_access = null - authenticated = 0 - minor = 0 - card_slot.try_eject(2, user) - else - var/obj/item/I = usr.get_active_held_item() - if (istype(I, /obj/item/card/id)) - if(!usr.transferItemToLoc(I, computer)) - return - card_slot.stored_card2 = I - if("PRG_terminate") - if(computer && ((id_card.assignment in head_subordinates) || id_card.assignment == "Assistant")) - id_card.assignment = "Unassigned" - remove_nt_access(id_card) - - if("PRG_edit") - if(computer && authorized()) - if(params["name"]) - var/temp_name = reject_bad_name(input("Enter name.", "Name", id_card.registered_name)) - if(temp_name) - id_card.registered_name = temp_name - else - computer.visible_message("[computer] buzzes rudely.") - //else if(params["account"]) - // var/account_num = text2num(input("Enter account number.", "Account", id_card.associated_account_number)) - // id_card.associated_account_number = account_num - if("PRG_assign") - if(computer && authorized() && id_card) - var/t1 = params["assign_target"] - if(t1 == "Custom") - var/temp_t = reject_bad_text(input("Enter a custom job assignment.","Assignment", id_card.assignment), 45) - //let custom jobs function as an impromptu alt title, mainly for sechuds - if(temp_t) - id_card.assignment = temp_t - else - var/list/access = list() - if(is_centcom) - access = get_centcom_access(t1) - else - var/datum/job/jobdatum - for(var/jobtype in typesof(/datum/job)) - var/datum/job/J = new jobtype - if(ckey(J.title) == ckey(t1)) - jobdatum = J - break - if(!jobdatum) - to_chat(usr, "No log exists for this job: [t1]") - return - - access = jobdatum.get_access() - - remove_nt_access(id_card) - apply_access(id_card, access) - id_card.assignment = t1 - - if("PRG_access") - if(params["allowed"] && computer && authorized()) - var/access_type = text2num(params["access_target"]) - var/access_allowed = text2num(params["allowed"]) - if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses())) - id_card.access -= access_type - if(!access_allowed) - id_card.access += access_type - if("PRG_open_job") - var/edit_job_target = params["target"] - var/datum/job/j = SSjob.GetJob(edit_job_target) - if(!j) - return 0 - if(can_open_job(j) != 1) - return 0 - if(opened_positions[edit_job_target] >= 0) - GLOB.time_last_changed_position = world.time / 10 - j.total_positions++ - opened_positions[edit_job_target]++ - if("PRG_close_job") - var/edit_job_target = params["target"] - var/datum/job/j = SSjob.GetJob(edit_job_target) - if(!j) - return 0 - if(can_close_job(j) != 1) - return 0 - //Allow instant closing without cooldown if a position has been opened before - if(opened_positions[edit_job_target] <= 0) - GLOB.time_last_changed_position = world.time / 10 - j.total_positions-- - opened_positions[edit_job_target]-- - if("PRG_regsel") - if(!reg_ids) - reg_ids = list() - var/regsel = text2num(params["region"]) - if(regsel in reg_ids) - reg_ids -= regsel + if(!printer.print_text(contents,"access report")) + to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.") + return else - reg_ids += regsel + playsound(computer, 'sound/machines/terminal_on.ogg', 50, FALSE) + computer.visible_message("\The [computer] prints out a paper.") + return TRUE + if("PRG_eject") + if(!computer || !card_slot) + return + if(id_card) + GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment) + card_slot.try_eject(TRUE, user) + else + var/obj/item/I = user.get_active_held_item() + if(istype(I, /obj/item/card/id)) + if(!user.transferItemToLoc(I, computer)) + return + card_slot.stored_card = I + playsound(computer, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + return TRUE + if("PRG_terminate") + if(!computer || !authenticated) + return + if(minor) + if(!(id_card.assignment in head_subordinates) && id_card.assignment != "Assistant") + return - if(id_card) - id_card.name = text("[id_card.registered_name]'s ID Card ([id_card.assignment])") + id_card.access -= get_all_centcom_access() + get_all_accesses() + id_card.assignment = "Unassigned" + id_card.update_label() + playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) + return TRUE + if("PRG_edit") + if(!computer || !authenticated || !id_card) + return + var/new_name = params["name"] + if(!new_name) + return + id_card.registered_name = new_name + id_card.update_label() + playsound(computer, "terminal_type", 50, FALSE) + return TRUE + if("PRG_assign") + if(!computer || !authenticated || !id_card) + return + var/target = params["assign_target"] + if(!target) + return - return 1 + if(target == "Custom") + var/custom_name = params["custom_name"] + if(custom_name) + id_card.assignment = custom_name + id_card.update_label() + else + if(minor && !(target in head_subordinates)) + return + var/list/new_access = list() + if(is_centcom) + new_access = get_centcom_access(target) + else + var/datum/job/job + for(var/jobtype in subtypesof(/datum/job)) + var/datum/job/J = new jobtype + if(J.title == target) + job = J + break + if(!job) + to_chat(user, "No class exists for this job: [target]") + return + new_access = job.get_access() + id_card.access -= get_all_centcom_access() + get_all_accesses() + id_card.access |= new_access + id_card.assignment = target + id_card.update_label() + playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + return TRUE + if("PRG_access") + if(!computer || !authenticated) + return + var/access_type = text2num(params["access_target"]) + if(access_type in (is_centcom ? get_all_centcom_access() : get_all_accesses())) + if(access_type in id_card.access) + id_card.access -= access_type + else + id_card.access |= access_type + playsound(computer, "terminal_type", 50, FALSE) + return TRUE + if("PRG_grantall") + if(!computer || !authenticated || minor) + return + id_card.access |= (is_centcom ? get_all_centcom_access() : get_all_accesses()) + playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + return TRUE + if("PRG_denyall") + if(!computer || !authenticated || minor) + return + id_card.access.Cut() + playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) + return TRUE + if("PRG_grantregion") + if(!computer || !authenticated) + return + var/region = text2num(params["region"]) + if(isnull(region)) + return + id_card.access |= get_region_accesses(region) + playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + return TRUE + if("PRG_denyregion") + if(!computer || !authenticated) + return + var/region = text2num(params["region"]) + if(isnull(region)) + return + id_card.access -= get_region_accesses(region) + playsound(computer, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE) + return TRUE -/datum/computer_file/program/card_mod/proc/remove_nt_access(obj/item/card/id/id_card) - id_card.access -= get_all_accesses() - id_card.access -= get_all_centcom_access() -/datum/computer_file/program/card_mod/proc/apply_access(obj/item/card/id/id_card, list/accesses) - id_card.access |= accesses + +/datum/computer_file/program/card_mod/ui_static_data(mob/user) + var/list/data = list() + data["station_name"] = station_name() + data["centcom_access"] = is_centcom + data["minor"] = target_dept || minor ? TRUE : FALSE + + var/list/departments = target_dept + if(is_centcom) + departments = list("CentCom" = get_all_centcom_jobs()) + else if(isnull(departments)) + departments = list( + CARDCON_DEPARTMENT_COMMAND = list("Captain"),//lol + CARDCON_DEPARTMENT_ENGINEERING = GLOB.engineering_positions, + CARDCON_DEPARTMENT_MEDICAL = GLOB.medical_positions, + CARDCON_DEPARTMENT_SCIENCE = GLOB.science_positions, + CARDCON_DEPARTMENT_SECURITY = GLOB.security_positions, + CARDCON_DEPARTMENT_SUPPLY = GLOB.supply_positions, + CARDCON_DEPARTMENT_SERVICE = GLOB.civilian_positions + ) + data["jobs"] = list() + for(var/department in departments) + var/list/job_list = departments[department] + var/list/department_jobs = list() + for(var/job in job_list) + if(minor && !(job in head_subordinates)) + continue + department_jobs += list(list( + "display_name" = replacetext(job, " ", " "), + "job" = job + )) + if(length(department_jobs)) + data["jobs"][department] = department_jobs + + var/list/regions = list() + for(var/i in 1 to 7) + if((minor || target_dept) && !(i in region_access)) + continue + + var/list/accesses = list() + for(var/access in get_region_accesses(i)) + if (get_access_desc(access)) + accesses += list(list( + "desc" = replacetext(get_access_desc(access), " ", " "), + "ref" = access, + )) + + regions += list(list( + "name" = get_region_accesses_name(i), + "regid" = i, + "accesses" = accesses + )) + + data["regions"] = regions + + return data /datum/computer_file/program/card_mod/ui_data(mob/user) - var/list/data = get_header_data() var/obj/item/computer_hardware/card_slot/card_slot @@ -301,181 +328,34 @@ card_slot = computer.all_components[MC_CARD] printer = computer.all_components[MC_PRINT] - data["mmode"] = mod_mode - - var/authed = 0 - if(computer) - if(card_slot) - var/obj/item/card/id/auth_card = card_slot.stored_card2 - data["auth_name"] = auth_card ? strip_html_simple(auth_card.name) : "-----" - authed = authorized() - - - if(mod_mode == 2) - data["slots"] = list() - var/list/pos = list() - for(var/datum/job/job in SSjob.occupations) - if(job.title in blacklisted) - continue - - var/list/status_open = build_manage(job,1) - var/list/status_close = build_manage(job,0) - - pos.Add(list(list( - "title" = job.title, - "current" = job.current_positions, - "total" = job.total_positions, - "status_open" = (authed && !minor) ? status_open["enable"]: 0, - "status_close" = (authed && !minor) ? status_close["enable"] : 0, - "desc_open" = status_open["desc"], - "desc_close" = status_close["desc"]))) - data["slots"] = pos - - data["src"] = "[REF(src)]" data["station_name"] = station_name() - - if(!mod_mode) - data["manifest"] = list() - var/list/crew = list() - for(var/datum/data/record/t in sortRecord(GLOB.data_core.general)) - crew.Add(list(list( - "name" = t.fields["name"], - "rank" = t.fields["rank"]))) - - data["manifest"] = crew - data["assignments"] = show_assignments if(computer) data["have_id_slot"] = !!card_slot data["have_printer"] = !!printer - if(!card_slot && mod_mode == 1) - mod_mode = 0 //We can't modify IDs when there is no card reader else - data["have_id_slot"] = 0 - data["have_printer"] = 0 + data["have_id_slot"] = FALSE + data["have_printer"] = FALSE - data["centcom_access"] = is_centcom - - - data["authenticated"] = authed - - - if(mod_mode == 1 && computer) - if(card_slot) - var/obj/item/card/id/id_card = card_slot.stored_card - - data["has_id"] = !!id_card - data["id_rank"] = id_card && id_card.assignment ? html_encode(id_card.assignment) : "Unassigned" - data["id_owner"] = id_card && id_card.registered_name ? html_encode(id_card.registered_name) : "-----" - data["id_name"] = id_card ? strip_html_simple(id_card.name) : "-----" - - if(show_assignments) - data["engineering_jobs"] = format_jobs(GLOB.engineering_positions) - data["medical_jobs"] = format_jobs(GLOB.medical_positions) - data["science_jobs"] = format_jobs(GLOB.science_positions) - data["security_jobs"] = format_jobs(GLOB.security_positions) - data["cargo_jobs"] = format_jobs(GLOB.supply_positions) - data["civilian_jobs"] = format_jobs(GLOB.civilian_positions) - data["centcom_jobs"] = format_jobs(get_all_centcom_jobs()) - - - if(card_slot.stored_card) - var/obj/item/card/id/id_card = card_slot.stored_card - if(is_centcom) - var/list/all_centcom_access = list() - for(var/access in get_all_centcom_access()) - all_centcom_access.Add(list(list( - "desc" = replacetext(get_centcom_access_desc(access), " ", " "), - "ref" = access, - "allowed" = (access in id_card.access) ? 1 : 0))) - data["all_centcom_access"] = all_centcom_access - else - var/list/regions = list() - for(var/i = 1; i <= 7; i++) - if((minor || target_dept) && !(i in region_access)) - continue - - var/list/accesses = list() - if(i in reg_ids) - for(var/access in get_region_accesses(i)) - if (get_access_desc(access)) - accesses.Add(list(list( - "desc" = replacetext(get_access_desc(access), " ", " "), - "ref" = access, - "allowed" = (access in id_card.access) ? 1 : 0))) - - regions.Add(list(list( - "name" = get_region_accesses_name(i), - "regid" = i, - "selected" = (i in reg_ids) ? 1 : null, - "accesses" = accesses))) - data["regions"] = regions - - data["minor"] = target_dept || minor ? 1 : 0 + data["authenticated"] = authenticated + if(computer) + var/obj/item/card/id/id_card = card_slot.stored_card + data["has_id"] = !!id_card + data["id_name"] = id_card ? id_card.name : "-----" + if(id_card) + data["id_rank"] = id_card.assignment ? id_card.assignment : "Unassigned" + data["id_owner"] = id_card.registered_name ? id_card.registered_name : "-----" + data["access_on_card"] = id_card.access return data -/datum/computer_file/program/card_mod/proc/build_manage(datum/job,open = FALSE) - var/out = "Denied" - var/can_change= 0 - if(open) - can_change = can_open_job(job) - else - can_change = can_close_job(job) - var/enable = 0 - if(can_change == 1) - out = "[open ? "Open Position" : "Close Position"]" - enable = 1 - else if(can_change == -2) - var/time_to_wait = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) - var/mins = round(time_to_wait / 60) - var/seconds = time_to_wait - (60*mins) - out = "Cooldown ongoing: [mins]:[(seconds < 10) ? "0[seconds]" : "[seconds]"]" - else - out = "Denied" - return list("enable" = enable, "desc" = out) - - -/datum/computer_file/program/card_mod/proc/authorized() - if(!authenticated && computer) - var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] - if(card_slot) - var/obj/item/card/id/auth_card = card_slot.stored_card2 - if(auth_card) - region_access = list() - if(ACCESS_CHANGE_IDS in auth_card.GetAccess()) - minor = 0 - authenticated = 1 - return 1 - else - if((ACCESS_HOP in auth_card.access) && ((target_dept==1) || !target_dept)) - region_access |= 1 - region_access |= 6 - get_subordinates("Head of Personnel") - if((ACCESS_HOS in auth_card.access) && ((target_dept==2) || !target_dept)) - region_access |= 2 - get_subordinates("Head of Security") - if((ACCESS_CMO in auth_card.access) && ((target_dept==3) || !target_dept)) - region_access |= 3 - get_subordinates("Chief Medical Officer") - if((ACCESS_RD in auth_card.access) && ((target_dept==4) || !target_dept)) - region_access |= 4 - get_subordinates("Research Director") - if((ACCESS_CE in auth_card.access) && ((target_dept==5) || !target_dept)) - region_access |= 5 - get_subordinates("Chief Engineer") - if(region_access.len) - minor = 1 - authenticated = 1 - return 1 - else - return authenticated - -/datum/computer_file/program/card_mod/proc/get_subordinates(rank) - head_subordinates = list() - for(var/datum/job/job in SSjob.occupations) - if(rank in job.department_head) - head_subordinates += job.title +#undef CARDCON_DEPARTMENT_SERVICE +#undef CARDCON_DEPARTMENT_SECURITY +#undef CARDCON_DEPARTMENT_MEDICAL +#undef CARDCON_DEPARTMENT_SCIENCE +#undef CARDCON_DEPARTMENT_SUPPLY +#undef CARDCON_DEPARTMENT_ENGINEERING +#undef CARDCON_DEPARTMENT_COMMAND diff --git a/code/modules/modular_computers/file_system/programs/cargobounty.dm b/code/modules/modular_computers/file_system/programs/cargobounty.dm new file mode 100644 index 0000000000..d9bc65c98d --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/cargobounty.dm @@ -0,0 +1,48 @@ +/datum/computer_file/program/bounty + filename = "bounty" + filedesc = "Nanotrasen Bounty Hunter" + program_icon_state = "bounty" + extended_desc = "A basic interface for supply personnel to check and claim bounties." + requires_ntnet = TRUE + transfer_access = ACCESS_CARGO + network_destination = "cargo claims interface" + size = 10 + tgui_id = "NtosBountyConsole" + ///cooldown var for printing paper sheets. + var/printer_ready = 0 + ///The cargo account for grabbing the cargo account's credits. + var/static/datum/bank_account/cargocash + +/datum/computer_file/program/bounty/proc/print_paper() + new /obj/item/paper/bounty_printout(get_turf(computer)) + +/datum/computer_file/program/bounty/ui_interact(mob/user, datum/tgui/ui) + if(!GLOB.bounties_list.len) + setup_bounties() + printer_ready = world.time + PRINTER_TIMEOUT + cargocash = SSeconomy.get_dep_account(ACCOUNT_CAR) + . = ..() + +/datum/computer_file/program/bounty/ui_data(mob/user) + var/list/data = get_header_data() + var/list/bountyinfo = list() + for(var/datum/bounty/B in GLOB.bounties_list) + bountyinfo += list(list("name" = B.name, "description" = B.description, "reward_string" = B.reward_string(), "completion_string" = B.completion_string() , "claimed" = B.claimed, "can_claim" = B.can_claim(), "priority" = B.high_priority, "bounty_ref" = REF(B))) + data["stored_cash"] = cargocash.account_balance + data["bountydata"] = bountyinfo + return data + +/datum/computer_file/program/bounty/ui_act(action,params) + if(..()) + return + switch(action) + if("ClaimBounty") + var/datum/bounty/cashmoney = locate(params["bounty"]) in GLOB.bounties_list + if(cashmoney) + cashmoney.claim() + return TRUE + if("Print") + if(printer_ready < world.time) + printer_ready = world.time + PRINTER_TIMEOUT + print_paper() + return diff --git a/code/modules/modular_computers/file_system/programs/cargoship.dm b/code/modules/modular_computers/file_system/programs/cargoship.dm new file mode 100644 index 0000000000..3ba08a3719 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/cargoship.dm @@ -0,0 +1,72 @@ +/datum/computer_file/program/shipping + filename = "shipping" + filedesc = "Nanotrasen Shipping Scanner" + program_icon_state = "shipping" + extended_desc = "A combination printer/scanner app that enables modular computers to print barcodes for easy scanning and shipping." + network_destination = "ship scanner" + size = 6 + tgui_id = "NtosShipping" + ///Account used for creating barcodes. + var/datum/bank_account/payments_acc + ///The amount which the tagger will receive for the sale. + var/percent_cut = 20 + +/datum/computer_file/program/shipping/ui_data(mob/user) + var/list/data = get_header_data() + + var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] + var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT] + var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null + data["has_id_slot"] = !!card_slot + data["has_printer"] = !!printer + data["paperamt"] = printer ? "[printer.stored_paper] / [printer.max_paper]" : null + data["card_owner"] = card_slot && card_slot.stored_card ? id_card.registered_name : "No Card Inserted." + data["current_user"] = payments_acc ? payments_acc.account_holder : null + data["barcode_split"] = percent_cut + return data + +/datum/computer_file/program/shipping/ui_act(action, list/params) + if(..()) + return TRUE + if(!computer) + return + + // Get components + var/obj/item/computer_hardware/card_slot/card_slot = computer.all_components[MC_CARD] + var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT] + var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null + if(!card_slot || !printer) //We need both to successfully use this app. + return + + switch(action) + if("ejectid") + if(id_card) + card_slot.try_eject(TRUE, usr) + if("selectid") + if(!id_card) + return + if(!id_card.registered_account) + playsound(get_turf(ui_host()), 'sound/machines/buzz-sigh.ogg', 50, TRUE, -1) + return + payments_acc = id_card.registered_account + playsound(get_turf(ui_host()), 'sound/machines/ping.ogg', 50, TRUE, -1) + if("resetid") + payments_acc = null + if("setsplit") + var/potential_cut = input("How much would you like to payout to the registered card?","Percentage Profit") as num|null + percent_cut = potential_cut ? clamp(round(potential_cut, 1), 1, 50) : 20 + if("print") + if(!printer) + to_chat(usr, "Hardware error: A printer is required to print barcodes.") + return + if(printer.stored_paper <= 0) + to_chat(usr, "Hardware error: Printer is out of paper.") + return + if(!payments_acc) + to_chat(usr, "Software error: Please set a current user first.") + return + var/obj/item/barcode/barcode = new /obj/item/barcode(get_turf(ui_host())) + barcode.payments_acc = payments_acc + barcode.percent_cut = percent_cut + printer.stored_paper-- + to_chat(usr, "The computer prints out a barcode.") diff --git a/code/modules/modular_computers/file_system/programs/configurator.dm b/code/modules/modular_computers/file_system/programs/configurator.dm index 2d60323d10..fae06544d5 100644 --- a/code/modules/modular_computers/file_system/programs/configurator.dm +++ b/code/modules/modular_computers/file_system/programs/configurator.dm @@ -10,11 +10,9 @@ unsendable = 1 undeletable = 1 size = 4 - ui_x = 420 - ui_y = 630 available_on_ntnet = 0 requires_ntnet = 0 - tgui_id = "ntos_configuration" + tgui_id = "NtosConfiguration" var/obj/item/modular_computer/movable = null diff --git a/code/modules/modular_computers/file_system/programs/crewmanifest.dm b/code/modules/modular_computers/file_system/programs/crewmanifest.dm new file mode 100644 index 0000000000..a1503ce3a8 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/crewmanifest.dm @@ -0,0 +1,48 @@ +/datum/computer_file/program/crew_manifest + filename = "crewmani" + filedesc = "Crew Manifest" + program_icon_state = "id" + extended_desc = "Program for viewing and printing the current crew manifest" + transfer_access = ACCESS_HEADS + requires_ntnet = FALSE + size = 4 + tgui_id = "NtosCrewManifest" + +/datum/computer_file/program/crew_manifest/ui_static_data(mob/user) + var/list/data = list() + data["manifest"] = GLOB.data_core.get_manifest_tg() + return data + +/datum/computer_file/program/crew_manifest/ui_data(mob/user) + var/list/data = get_header_data() + + var/obj/item/computer_hardware/printer/printer + if(computer) + printer = computer.all_components[MC_PRINT] + + if(computer) + data["have_printer"] = !!printer + else + data["have_printer"] = FALSE + return data + +/datum/computer_file/program/crew_manifest/ui_act(action, params, datum/tgui/ui) + if(..()) + return + + var/obj/item/computer_hardware/printer/printer + if(computer) + printer = computer.all_components[MC_PRINT] + + switch(action) + if("PRG_print") + if(computer && printer) //This option should never be called if there is no printer + var/contents = {"

    Crew Manifest

    +
    + [GLOB.data_core ? GLOB.data_core.get_manifest() : ""] + "} + if(!printer.print_text(contents,text("crew manifest ([])", STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)))) + to_chat(usr, "Hardware error: Printer was unable to print the file. It may be out of paper.") + return + else + computer.visible_message("\The [computer] prints out a paper.") diff --git a/code/modules/modular_computers/file_system/programs/file_browser.dm b/code/modules/modular_computers/file_system/programs/file_browser.dm index cba82eac18..aba826fce8 100644 --- a/code/modules/modular_computers/file_system/programs/file_browser.dm +++ b/code/modules/modular_computers/file_system/programs/file_browser.dm @@ -4,186 +4,67 @@ extended_desc = "This program allows management of files." program_icon_state = "generic" size = 8 - requires_ntnet = 0 - available_on_ntnet = 0 - undeletable = 1 - tgui_id = "ntos_file_manager" + requires_ntnet = FALSE + available_on_ntnet = FALSE + undeletable = TRUE + tgui_id = "NtosFileManager" var/open_file var/error /datum/computer_file/program/filemanager/ui_act(action, params) if(..()) - return 1 + return var/obj/item/computer_hardware/hard_drive/HDD = computer.all_components[MC_HDD] var/obj/item/computer_hardware/hard_drive/RHDD = computer.all_components[MC_SDD] - var/obj/item/computer_hardware/printer/printer = computer.all_components[MC_PRINT] switch(action) - if("PRG_openfile") - . = 1 - open_file = params["name"] - if("PRG_newtextfile") - . = 1 - var/newname = stripped_input(usr, "Enter file name or leave blank to cancel:", "File rename", max_length=50) - if(!newname) - return 1 - if(!HDD) - return 1 - var/datum/computer_file/data/F = new/datum/computer_file/data() - F.filename = newname - F.filetype = "TXT" - HDD.store_file(F) if("PRG_deletefile") - . = 1 if(!HDD) - return 1 + return var/datum/computer_file/file = HDD.find_file_by_name(params["name"]) if(!file || file.undeletable) - return 1 + return HDD.remove_file(file) + return TRUE if("PRG_usbdeletefile") - . = 1 if(!RHDD) - return 1 + return var/datum/computer_file/file = RHDD.find_file_by_name(params["name"]) if(!file || file.undeletable) - return 1 - RHDD.remove_file(file) - if("PRG_closefile") - . = 1 - open_file = null - error = null - if("PRG_clone") - . = 1 - if(!HDD) - return 1 - var/datum/computer_file/F = HDD.find_file_by_name(params["name"]) - if(!F || !istype(F)) - return 1 - var/datum/computer_file/C = F.clone(1) - HDD.store_file(C) - if("PRG_rename") - . = 1 - if(!HDD) - return 1 - var/datum/computer_file/file = HDD.find_file_by_name(params["name"]) - if(!file || !istype(file)) - return 1 - var/newname = stripped_input(usr, "Enter new file name:", "File rename", file.filename, max_length=50) - if(file && newname) - file.filename = newname - if("PRG_edit") - . = 1 - if(!open_file) - return 1 - if(!HDD) - return 1 - var/datum/computer_file/data/F = HDD.find_file_by_name(open_file) - if(!F || !istype(F)) - return 1 - if(F.do_not_edit && (alert("WARNING: This file is not compatible with editor. Editing it may result in permanently corrupted formatting or damaged data consistency. Edit anyway?", "Incompatible File", "No", "Yes") == "No")) - return 1 - // 16384 is the limit for file length in characters. Currently, papers have value of 2048 so this is 8 times as long, since we can't edit parts of the file independently. - var/newtext = stripped_multiline_input(usr, "Editing file [open_file]. You may use most tags used in paper formatting:", "Text Editor", html_decode(F.stored_data), 16384, TRUE) - if(!newtext) return - if(F) - var/datum/computer_file/data/backup = F.clone() - HDD.remove_file(F) - F.stored_data = newtext - F.calculate_size() - // We can't store the updated file, it's probably too large. Print an error and restore backed up version. - // This is mostly intended to prevent people from losing texts they spent lot of time working on due to running out of space. - // They will be able to copy-paste the text from error screen and store it in notepad or something. - if(!HDD.store_file(F)) - error = "I/O error: Unable to overwrite file. Hard drive is probably full. You may want to backup your changes before closing this window:

    [F.stored_data]

    " - HDD.store_file(backup) - if("PRG_printfile") - . = 1 - if(!open_file) - return 1 + RHDD.remove_file(file) + return TRUE + if("PRG_rename") if(!HDD) - return 1 - var/datum/computer_file/data/F = HDD.find_file_by_name(open_file) - if(!F || !istype(F)) - return 1 - if(!printer) - error = "Missing Hardware: Your computer does not have required hardware to complete this operation." - return 1 - if(!printer.print_text("" + prepare_printjob(F.stored_data) + "", open_file)) - error = "Hardware error: Printer was unable to print the file. It may be out of paper." - return 1 + return + var/datum/computer_file/file = HDD.find_file_by_name(params["name"]) + if(!file) + return + var/newname = params["new_name"] + if(!newname) + return + file.filename = newname + return TRUE if("PRG_copytousb") - . = 1 if(!HDD || !RHDD) - return 1 + return var/datum/computer_file/F = HDD.find_file_by_name(params["name"]) - if(!F || !istype(F)) - return 1 - var/datum/computer_file/C = F.clone(0) + if(!F) + return + var/datum/computer_file/C = F.clone(FALSE) RHDD.store_file(C) + return TRUE if("PRG_copyfromusb") - . = 1 if(!HDD || !RHDD) - return 1 + return var/datum/computer_file/F = RHDD.find_file_by_name(params["name"]) if(!F || !istype(F)) - return 1 - var/datum/computer_file/C = F.clone(0) + return + var/datum/computer_file/C = F.clone(FALSE) HDD.store_file(C) - -/datum/computer_file/program/filemanager/proc/parse_tags(t) - t = replacetext(t, "\[center\]", "
    ") - t = replacetext(t, "\[/center\]", "
    ") - t = replacetext(t, "\[br\]", "
    ") - t = replacetext(t, "\n", "
    ") - t = replacetext(t, "\[b\]", "") - t = replacetext(t, "\[/b\]", "") - t = replacetext(t, "\[i\]", "") - t = replacetext(t, "\[/i\]", "") - t = replacetext(t, "\[u\]", "") - t = replacetext(t, "\[/u\]", "") - t = replacetext(t, "\[time\]", "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]") - t = replacetext(t, "\[date\]", "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]") - t = replacetext(t, "\[large\]", "") - t = replacetext(t, "\[/large\]", "") - t = replacetext(t, "\[h1\]", "

    ") - t = replacetext(t, "\[/h1\]", "

    ") - t = replacetext(t, "\[h2\]", "

    ") - t = replacetext(t, "\[/h2\]", "

    ") - t = replacetext(t, "\[h3\]", "

    ") - t = replacetext(t, "\[/h3\]", "

    ") - t = replacetext(t, "\[*\]", "
  • ") - t = replacetext(t, "\[hr\]", "
    ") - t = replacetext(t, "\[small\]", "") - t = replacetext(t, "\[/small\]", "") - t = replacetext(t, "\[list\]", "
      ") - t = replacetext(t, "\[/list\]", "
    ") - t = replacetext(t, "\[table\]", "") - t = replacetext(t, "\[/table\]", "
    ") - t = replacetext(t, "\[grid\]", "") - t = replacetext(t, "\[/grid\]", "
    ") - t = replacetext(t, "\[row\]", "") - t = replacetext(t, "\[tr\]", "") - t = replacetext(t, "\[td\]", "") - t = replacetext(t, "\[cell\]", "") - t = replacetext(t, "\[tab\]", "    ") - - t = parsemarkdown_basic(t) - - return t - -/datum/computer_file/program/filemanager/proc/prepare_printjob(t) // Additional stuff to parse if we want to print it and make a happy Head of Personnel. Forms FTW. - t = replacetext(t, "\[field\]", "") - t = replacetext(t, "\[sign\]", "") - - t = parse_tags(t) - - t = replacetext(t, regex("(?:%s(?:ign)|%f(?:ield))(?=\\s|$)", "ig"), "") - - return t + return TRUE /datum/computer_file/program/filemanager/ui_data(mob/user) var/list/data = get_header_data() @@ -192,41 +73,28 @@ var/obj/item/computer_hardware/hard_drive/portable/RHDD = computer.all_components[MC_SDD] if(error) data["error"] = error - if(open_file) - var/datum/computer_file/data/file - - if(!computer || !HDD) - data["error"] = "I/O ERROR: Unable to access hard drive." - else - file = HDD.find_file_by_name(open_file) - if(!istype(file)) - data["error"] = "I/O ERROR: Unable to open file." - else - data["filedata"] = parse_tags(file.stored_data) - data["filename"] = "[file.filename].[file.filetype]" + if(!computer || !HDD) + data["error"] = "I/O ERROR: Unable to access hard drive." else - if(!computer || !HDD) - data["error"] = "I/O ERROR: Unable to access hard drive." - else - var/list/files[0] - for(var/datum/computer_file/F in HDD.stored_files) - files.Add(list(list( + var/list/files = list() + for(var/datum/computer_file/F in HDD.stored_files) + files += list(list( + "name" = F.filename, + "type" = F.filetype, + "size" = F.size, + "undeletable" = F.undeletable + )) + data["files"] = files + if(RHDD) + data["usbconnected"] = TRUE + var/list/usbfiles = list() + for(var/datum/computer_file/F in RHDD.stored_files) + usbfiles += list(list( "name" = F.filename, "type" = F.filetype, "size" = F.size, "undeletable" = F.undeletable - ))) - data["files"] = files - if(RHDD) - data["usbconnected"] = 1 - var/list/usbfiles[0] - for(var/datum/computer_file/F in RHDD.stored_files) - usbfiles.Add(list(list( - "name" = F.filename, - "type" = F.filetype, - "size" = F.size, - "undeletable" = F.undeletable - ))) - data["usbfiles"] = usbfiles + )) + data["usbfiles"] = usbfiles return data diff --git a/code/modules/modular_computers/file_system/programs/jobmanagement.dm b/code/modules/modular_computers/file_system/programs/jobmanagement.dm new file mode 100644 index 0000000000..bccc6e4dbe --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/jobmanagement.dm @@ -0,0 +1,139 @@ +/datum/computer_file/program/job_management + filename = "job_manage" + filedesc = "Job Manager" + program_icon_state = "id" + extended_desc = "Program for viewing and changing job slot avalibility." + transfer_access = ACCESS_HEADS + requires_ntnet = 0 + size = 4 + tgui_id = "NtosJobManager" + + var/change_position_cooldown = 30 + //Jobs you cannot open new positions for + var/list/blacklisted = list( + "AI", + "Assistant", + "Cyborg", + "Captain", + "Head of Personnel", + "Head of Security", + "Chief Engineer", + "Research Director", + "Chief Medical Officer") + + //The scaling factor of max total positions in relation to the total amount of people on board the station in % + var/max_relative_positions = 30 //30%: Seems reasonable, limit of 6 @ 20 players + + //This is used to keep track of opened positions for jobs to allow instant closing + //Assoc array: "JobName" = (int) + var/list/opened_positions = list() + +/datum/computer_file/program/job_management/New() + ..() + change_position_cooldown = CONFIG_GET(number/id_console_jobslot_delay) + +/datum/computer_file/program/job_management/proc/can_open_job(datum/job/job) + if(!(job?.title in blacklisted)) + if((job.total_positions <= length(GLOB.player_list) * (max_relative_positions / 100))) + var/delta = (world.time / 10) - GLOB.time_last_changed_position + if((change_position_cooldown < delta) || (opened_positions[job.title] < 0)) + return TRUE + return FALSE + +/datum/computer_file/program/job_management/proc/can_close_job(datum/job/job) + if(!(job?.title in blacklisted)) + if(job.total_positions > length(GLOB.player_list) * (max_relative_positions / 100)) + var/delta = (world.time / 10) - GLOB.time_last_changed_position + if((change_position_cooldown < delta) || (opened_positions[job.title] > 0)) + return TRUE + return FALSE + +/datum/computer_file/program/job_management/ui_act(action, params, datum/tgui/ui) + if(..()) + return + + var/authed = FALSE + var/mob/user = usr + var/obj/item/card/id/user_id = user.get_idcard() + if(user_id) + if(ACCESS_CHANGE_IDS in user_id.access) + authed = TRUE + + if(!authed) + return + + switch(action) + if("PRG_open_job") + var/edit_job_target = params["target"] + var/datum/job/j = SSjob.GetJob(edit_job_target) + if(!j || !can_open_job(j)) + return + if(opened_positions[edit_job_target] >= 0) + GLOB.time_last_changed_position = world.time / 10 + j.total_positions++ + opened_positions[edit_job_target]++ + playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + return TRUE + if("PRG_close_job") + var/edit_job_target = params["target"] + var/datum/job/j = SSjob.GetJob(edit_job_target) + if(!j || !can_close_job(j)) + return + //Allow instant closing without cooldown if a position has been opened before + if(opened_positions[edit_job_target] <= 0) + GLOB.time_last_changed_position = world.time / 10 + j.total_positions-- + opened_positions[edit_job_target]-- + playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + return TRUE + if("PRG_priority") + if(length(SSjob.prioritized_jobs) >= 5) + return + var/priority_target = params["target"] + var/datum/job/j = SSjob.GetJob(priority_target) + if(!j) + return + if(j.total_positions <= j.current_positions) + return + if(j in SSjob.prioritized_jobs) + SSjob.prioritized_jobs -= j + else + SSjob.prioritized_jobs += j + playsound(computer, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE) + return TRUE + + +/datum/computer_file/program/job_management/ui_data(mob/user) + var/list/data = get_header_data() + + var/authed = FALSE + var/obj/item/card/id/user_id = user.get_idcard(FALSE) + if(user_id) + if(ACCESS_CHANGE_IDS in user_id.access) + authed = TRUE + + data["authed"] = authed + + var/list/pos = list() + for(var/j in SSjob.occupations) + var/datum/job/job = j + if(job.title in blacklisted) + continue + + pos += list(list( + "title" = job.title, + "current" = job.current_positions, + "total" = job.total_positions, + "status_open" = authed ? can_open_job(job) : FALSE, + "status_close" = authed ? can_close_job(job) : FALSE, + )) + data["slots"] = pos + var/delta = round(change_position_cooldown - ((world.time / 10) - GLOB.time_last_changed_position), 1) + data["cooldown"] = delta < 0 ? 0 : delta + var/list/priority = list() + for(var/j in SSjob.prioritized_jobs) + var/datum/job/job = j + priority += job.title + data["prioritized"] = priority + return data + diff --git a/code/modules/modular_computers/file_system/programs/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/ntdownloader.dm index 92e1453dc6..6401d6207f 100644 --- a/code/modules/modular_computers/file_system/programs/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/ntdownloader.dm @@ -10,7 +10,7 @@ requires_ntnet_feature = NTNET_SOFTWAREDOWNLOAD available_on_ntnet = 0 ui_header = "downloader_finished.gif" - tgui_id = "ntos_net_downloader" + tgui_id = "NtosNetDownloader" var/datum/computer_file/program/downloaded_file = null var/hacked_download = 0 @@ -18,6 +18,21 @@ var/download_netspeed = 0 var/downloaderror = "" var/obj/item/modular_computer/my_computer = null + var/emagged = FALSE + var/list/main_repo + var/list/antag_repo + +/datum/computer_file/program/ntnetdownload/run_program() + . = ..() + main_repo = SSnetworks.station_network.available_station_software + antag_repo = SSnetworks.station_network.available_antag_software + +/datum/computer_file/program/ntnetdownload/run_emag() + if(emagged) + return FALSE + emagged = TRUE + return TRUE + /datum/computer_file/program/ntnetdownload/proc/begin_file_download(filename) if(downloaded_file) @@ -28,8 +43,8 @@ if(!PRG || !istype(PRG)) return 0 - // Attempting to download antag only program, but without having emagged computer. No. - if(PRG.available_on_syndinet && !(computer.obj_flags & EMAGGED)) + // Attempting to download antag only program, but without having emagged/syndicate computer. No. + if(PRG.available_on_syndinet && !emagged) return 0 var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] @@ -39,10 +54,10 @@ ui_header = "downloader_running.gif" - if(PRG in SSnetworks.station_network.available_station_software) + if(PRG in main_repo) generate_network_log("Began downloading file [PRG.filename].[PRG.filetype] from NTNet Software Repository.") hacked_download = 0 - else if(PRG in SSnetworks.station_network.available_antag_software) + else if(PRG in antag_repo) generate_network_log("Began downloading file **ENCRYPTED**.[PRG.filetype] from unspecified server.") hacked_download = 1 else @@ -113,49 +128,50 @@ var/list/data = get_header_data() - // This IF cuts on data transferred to client, so i guess it's worth it. - if(downloaderror) // Download errored. Wait until user resets the program. - data["error"] = downloaderror - else if(downloaded_file) // Download running. Wait please.. + data["downloading"] = !!downloaded_file + data["error"] = downloaderror || FALSE + + // Download running. Wait please.. + if(downloaded_file) data["downloadname"] = downloaded_file.filename data["downloaddesc"] = downloaded_file.filedesc data["downloadsize"] = downloaded_file.size data["downloadspeed"] = download_netspeed data["downloadcompletion"] = round(download_completion, 0.1) - else // No download running, pick file. - var/obj/item/computer_hardware/hard_drive/hard_drive = my_computer.all_components[MC_HDD] - data["disk_size"] = hard_drive.max_capacity - data["disk_used"] = hard_drive.used_capacity - var/list/all_entries[0] - for(var/A in SSnetworks.station_network.available_station_software) - var/datum/computer_file/program/P = A - // Only those programs our user can run will show in the list - if(!P.can_run(user,transfer = 1) || hard_drive.find_file_by_name(P.filename)) - continue - all_entries.Add(list(list( + + var/obj/item/computer_hardware/hard_drive/hard_drive = my_computer.all_components[MC_HDD] + data["disk_size"] = hard_drive.max_capacity + data["disk_used"] = hard_drive.used_capacity + var/list/all_entries[0] + for(var/A in main_repo) + var/datum/computer_file/program/P = A + // Only those programs our user can run will show in the list + if(!P.can_run(user,transfer = 1) || hard_drive.find_file_by_name(P.filename)) + continue + all_entries.Add(list(list( "filename" = P.filename, "filedesc" = P.filedesc, "fileinfo" = P.extended_desc, "compatibility" = check_compatibility(P), - "size" = P.size - ))) - data["hackedavailable"] = 0 - if(computer.obj_flags & EMAGGED) // If we are running on emagged computer we have access to some "bonus" software - var/list/hacked_programs[0] - for(var/S in SSnetworks.station_network.available_antag_software) - var/datum/computer_file/program/P = S - if(hard_drive.find_file_by_name(P.filename)) - continue - data["hackedavailable"] = 1 - hacked_programs.Add(list(list( + "size" = P.size, + ))) + data["hackedavailable"] = FALSE + if(emagged) // If we are running on emagged computer we have access to some "bonus" software + var/list/hacked_programs[0] + for(var/S in antag_repo) + var/datum/computer_file/program/P = S + if(hard_drive.find_file_by_name(P.filename)) + continue + data["hackedavailable"] = TRUE + hacked_programs.Add(list(list( "filename" = P.filename, "filedesc" = P.filedesc, "fileinfo" = P.extended_desc, - "size" = P.size - ))) - data["hacked_programs"] = hacked_programs + "size" = P.size, + ))) + data["hacked_programs"] = hacked_programs - data["downloadable_programs"] = all_entries + data["downloadable_programs"] = all_entries return data @@ -168,4 +184,25 @@ /datum/computer_file/program/ntnetdownload/kill_program(forced) abort_file_download() - return ..(forced) \ No newline at end of file + return ..(forced) + +//////////////////////// +//Syndicate Downloader// +//////////////////////// + +/// This app only lists programs normally found in the emagged section of the normal downloader app + +/datum/computer_file/program/ntnetdownload/syndicate + filename = "syndownloader" + filedesc = "Software Download Tool" + program_icon_state = "generic" + extended_desc = "This program allows downloads of software from shared Syndicate repositories" + requires_ntnet = 0 + ui_header = "downloader_finished.gif" + tgui_id = "NtosNetDownloader" + emagged = TRUE + +/datum/computer_file/program/ntnetdownload/syndicate/run_program() + . = ..() + main_repo = SSnetworks.station_network.available_antag_software + antag_repo = null diff --git a/code/modules/modular_computers/file_system/programs/ntmonitor.dm b/code/modules/modular_computers/file_system/programs/ntmonitor.dm index 2312db7b11..7d6d89f32c 100644 --- a/code/modules/modular_computers/file_system/programs/ntmonitor.dm +++ b/code/modules/modular_computers/file_system/programs/ntmonitor.dm @@ -4,58 +4,48 @@ program_icon_state = "comm_monitor" extended_desc = "This program monitors stationwide NTNet network, provides access to logging systems, and allows for configuration changes" size = 12 - requires_ntnet = 1 + requires_ntnet = TRUE required_access = ACCESS_NETWORK //NETWORK CONTROL IS A MORE SECURE PROGRAM. - available_on_ntnet = 1 - tgui_id = "ntos_net_monitor" + available_on_ntnet = TRUE + tgui_id = "NtosNetMonitor" /datum/computer_file/program/ntnetmonitor/ui_act(action, params) if(..()) - return 1 + return switch(action) if("resetIDS") - . = 1 if(SSnetworks.station_network) SSnetworks.station_network.resetIDS() - return 1 + return TRUE if("toggleIDS") - . = 1 if(SSnetworks.station_network) SSnetworks.station_network.toggleIDS() - return 1 + return TRUE if("toggleWireless") - . = 1 if(!SSnetworks.station_network) - return 1 + return // NTNet is disabled. Enabling can be done without user prompt if(SSnetworks.station_network.setting_disabled) - SSnetworks.station_network.setting_disabled = 0 - return 1 + SSnetworks.station_network.setting_disabled = FALSE + return TRUE - // NTNet is enabled and user is about to shut it down. Let's ask them if they really want to do it, as wirelessly connected computers won't connect without NTNet being enabled (which may prevent people from turning it back on) - var/mob/user = usr - if(!user) - return 1 - var/response = alert(user, "Really disable NTNet wireless? If your computer is connected wirelessly you won't be able to turn it back on! This will affect all connected wireless devices.", "NTNet shutdown", "Yes", "No") - if(response == "Yes") - SSnetworks.station_network.setting_disabled = 1 - return 1 + SSnetworks.station_network.setting_disabled = TRUE + return TRUE if("purgelogs") - . = 1 if(SSnetworks.station_network) SSnetworks.station_network.purge_logs() + return TRUE if("updatemaxlogs") - . = 1 - var/mob/user = usr - var/logcount = text2num(input(user,"Enter amount of logs to keep in memory ([MIN_NTNET_LOGS]-[MAX_NTNET_LOGS]):")) + var/logcount = params["new_number"] if(SSnetworks.station_network) SSnetworks.station_network.update_max_log_count(logcount) + return TRUE if("toggle_function") - . = 1 if(!SSnetworks.station_network) - return 1 + return SSnetworks.station_network.toggle_function(text2num(params["id"])) + return TRUE /datum/computer_file/program/ntnetmonitor/ui_data(mob/user) if(!SSnetworks.station_network) @@ -73,9 +63,11 @@ data["config_systemcontrol"] = SSnetworks.station_network.setting_systemcontrol data["ntnetlogs"] = list() + data["minlogs"] = MIN_NTNET_LOGS + data["maxlogs"] = MAX_NTNET_LOGS for(var/i in SSnetworks.station_network.logs) data["ntnetlogs"] += list(list("entry" = i)) data["ntnetmaxlogs"] = SSnetworks.station_network.setting_maxlogcount - return data \ No newline at end of file + return data diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm index d8b3f96f42..df9b02d8ec 100644 --- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm @@ -9,10 +9,7 @@ network_destination = "NTNRC server" ui_header = "ntnrc_idle.gif" available_on_ntnet = 1 - tgui_id = "ntos_net_chat" - ui_x = 900 - ui_y = 675 - + tgui_id = "NtosNetChat" var/last_message // Used to generate the toolbar icon var/username var/active_channel diff --git a/code/modules/modular_computers/file_system/programs/nttransfer.dm b/code/modules/modular_computers/file_system/programs/nttransfer.dm deleted file mode 100644 index 698e557941..0000000000 --- a/code/modules/modular_computers/file_system/programs/nttransfer.dm +++ /dev/null @@ -1,183 +0,0 @@ -/datum/computer_file/program/nttransfer - filename = "nttransfer" - filedesc = "P2P Transfer Client" - extended_desc = "This program allows for simple file transfer via direct peer to peer connection." - program_icon_state = "comm_logs" - size = 7 - requires_ntnet = 1 - requires_ntnet_feature = NTNET_PEERTOPEER - network_destination = "other device via P2P tunnel" - available_on_ntnet = 1 - tgui_id = "ntos_net_transfer" - - var/error = "" // Error screen - var/server_password = "" // Optional password to download the file. - var/datum/computer_file/provided_file = null // File which is provided to clients. - var/datum/computer_file/downloaded_file = null // File which is being downloaded - var/list/connected_clients = list() // List of connected clients. - var/datum/computer_file/program/nttransfer/remote // Client var, specifies who are we downloading from. - var/download_completion = 0 // Download progress in GQ - var/download_netspeed = 0 // Our connectivity speed in GQ/s - var/actual_netspeed = 0 // Displayed in the UI, this is the actual transfer speed. - var/unique_token // UID of this program - var/upload_menu = 0 // Whether we show the program list and upload menu - var/static/nttransfer_uid = 0 - -/datum/computer_file/program/nttransfer/New() - unique_token = nttransfer_uid++ - ..() - -/datum/computer_file/program/nttransfer/process_tick() - // Server mode - update_netspeed() - if(provided_file) - for(var/datum/computer_file/program/nttransfer/C in connected_clients) - // Transfer speed is limited by device which uses slower connectivity. - // We can have multiple clients downloading at same time, but let's assume we use some sort of multicast transfer - // so they can all run on same speed. - C.actual_netspeed = min(C.download_netspeed, download_netspeed) - C.download_completion += C.actual_netspeed - if(C.download_completion >= provided_file.size) - C.finish_download() - else if(downloaded_file) // Client mode - if(!remote) - crash_download("Connection to remote server lost") - -/datum/computer_file/program/nttransfer/kill_program(forced = FALSE) - if(downloaded_file) // Client mode, clean up variables for next use - finalize_download() - - if(provided_file) // Server mode, disconnect all clients - for(var/datum/computer_file/program/nttransfer/P in connected_clients) - P.crash_download("Connection terminated by remote server") - downloaded_file = null - ..(forced) - -/datum/computer_file/program/nttransfer/proc/update_netspeed() - download_netspeed = 0 - switch(ntnet_status) - if(1) - download_netspeed = NTNETSPEED_LOWSIGNAL - if(2) - download_netspeed = NTNETSPEED_HIGHSIGNAL - if(3) - download_netspeed = NTNETSPEED_ETHERNET - -// Finishes download and attempts to store the file on HDD -/datum/computer_file/program/nttransfer/proc/finish_download() - var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] - if(!computer || !hard_drive || !hard_drive.store_file(downloaded_file)) - error = "I/O Error: Unable to save file. Check your hard drive and try again." - finalize_download() - -// Crashes the download and displays specific error message -/datum/computer_file/program/nttransfer/proc/crash_download(var/message) - error = message ? message : "An unknown error has occurred during download" - finalize_download() - -// Cleans up variables for next use -/datum/computer_file/program/nttransfer/proc/finalize_download() - if(remote) - remote.connected_clients.Remove(src) - downloaded_file = null - remote = null - download_completion = 0 - -/datum/computer_file/program/nttransfer/ui_act(action, params) - if(..()) - return 1 - switch(action) - if("PRG_downloadfile") - for(var/datum/computer_file/program/nttransfer/P in SSnetworks.station_network.fileservers) - if("[P.unique_token]" == params["id"]) - remote = P - break - if(!remote || !remote.provided_file) - return - if(remote.server_password) - var/pass = reject_bad_text(input(usr, "Code 401 Unauthorized. Please enter password:", "Password required")) - if(pass != remote.server_password) - error = "Incorrect Password" - return - downloaded_file = remote.provided_file.clone() - remote.connected_clients.Add(src) - return 1 - if("PRG_reset") - error = "" - upload_menu = 0 - finalize_download() - if(src in SSnetworks.station_network.fileservers) - SSnetworks.station_network.fileservers.Remove(src) - for(var/datum/computer_file/program/nttransfer/T in connected_clients) - T.crash_download("Remote server has forcibly closed the connection") - provided_file = null - return 1 - if("PRG_setpassword") - var/pass = reject_bad_text(input(usr, "Enter new server password. Leave blank to cancel, input 'none' to disable password.", "Server security", "none")) - if(!pass) - return - if(pass == "none") - server_password = "" - return - server_password = pass - return 1 - if("PRG_uploadfile") - var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] - for(var/datum/computer_file/F in hard_drive.stored_files) - if("[F.uid]" == params["id"]) - if(F.unsendable) - error = "I/O Error: File locked." - return - if(istype(F, /datum/computer_file/program)) - var/datum/computer_file/program/P = F - if(!P.can_run(usr,transfer = 1)) - error = "Access Error: Insufficient rights to upload file." - provided_file = F - SSnetworks.station_network.fileservers.Add(src) - return - error = "I/O Error: Unable to locate file on hard drive." - return 1 - if("PRG_uploadmenu") - upload_menu = 1 - - -/datum/computer_file/program/nttransfer/ui_data(mob/user) - - var/list/data = get_header_data() - - if(error) - data["error"] = error - else if(downloaded_file) - data["downloading"] = 1 - data["download_size"] = downloaded_file.size - data["download_progress"] = download_completion - data["download_netspeed"] = actual_netspeed - data["download_name"] = "[downloaded_file.filename].[downloaded_file.filetype]" - else if (provided_file) - data["uploading"] = 1 - data["upload_uid"] = unique_token - data["upload_clients"] = connected_clients.len - data["upload_haspassword"] = server_password ? 1 : 0 - data["upload_filename"] = "[provided_file.filename].[provided_file.filetype]" - else if (upload_menu) - var/list/all_files[0] - var/obj/item/computer_hardware/hard_drive/hard_drive = computer.all_components[MC_HDD] - for(var/datum/computer_file/F in hard_drive.stored_files) - all_files.Add(list(list( - "uid" = F.uid, - "filename" = "[F.filename].[F.filetype]", - "size" = F.size - ))) - data["upload_filelist"] = all_files - else - var/list/all_servers[0] - for(var/datum/computer_file/program/nttransfer/P in SSnetworks.station_network.fileservers) - all_servers.Add(list(list( - "uid" = P.unique_token, - "filename" = "[P.provided_file.filename].[P.provided_file.filetype]", - "size" = P.provided_file.size, - "haspassword" = P.server_password ? 1 : 0 - ))) - data["servers"] = all_servers - - return data \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/powermonitor.dm b/code/modules/modular_computers/file_system/programs/powermonitor.dm index f7c734667b..bd11474858 100644 --- a/code/modules/modular_computers/file_system/programs/powermonitor.dm +++ b/code/modules/modular_computers/file_system/programs/powermonitor.dm @@ -11,10 +11,7 @@ requires_ntnet = 0 network_destination = "power monitoring system" size = 9 - tgui_id = "ntos_power_monitor" - ui_style = "ntos" - ui_x = 550 - ui_y = 700 + tgui_id = "NtosPowerMonitor" var/has_alert = 0 var/obj/structure/cable/attached_wire diff --git a/code/modules/modular_computers/file_system/programs/radar.dm b/code/modules/modular_computers/file_system/programs/radar.dm new file mode 100644 index 0000000000..9b0e09ef99 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/radar.dm @@ -0,0 +1,293 @@ +/datum/computer_file/program/radar //generic parent that handles most of the process + filename = "genericfinder" + filedesc = "debug_finder" + ui_header = "borg_mon.gif" //DEBUG -- new icon before PR + program_icon_state = "radarntos" + requires_ntnet = TRUE + transfer_access = null + available_on_ntnet = FALSE + usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET + network_destination = "tracking program" + size = 5 + tgui_id = "NtosRadar" + ///List of trackable entities. Updated by the scan() proc. + var/list/objects + ///Ref of the last trackable object selected by the user in the tgui window. Updated in the ui_act() proc. + var/atom/selected + ///Used to store when the next scan is available. Updated by the scan() proc. + var/next_scan = 0 + ///Used to keep track of the last value program_icon_state was set to, to prevent constant unnecessary update_icon() calls + var/last_icon_state = "" + ///Used by the tgui interface, themed NT or Syndicate. + var/arrowstyle = "ntosradarpointer.png" + ///Used by the tgui interface, themed for NT or Syndicate colors. + var/pointercolor = "green" + +/datum/computer_file/program/radar/run_program(mob/living/user) + . = ..() + if(.) + START_PROCESSING(SSfastprocess, src) + return + return FALSE + +/datum/computer_file/program/radar/kill_program(forced = FALSE) + objects = list() + selected = null + STOP_PROCESSING(SSfastprocess, src) + return ..() + +/datum/computer_file/program/radar/Destroy() + STOP_PROCESSING(SSfastprocess, src) + return ..() + +/datum/computer_file/program/radar/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/simple/radar_assets), + ) + +/datum/computer_file/program/radar/ui_data(mob/user) + var/list/data = get_header_data() + data["selected"] = selected + data["objects"] = list() + data["scanning"] = (world.time < next_scan) + for(var/list/i in objects) + var/list/objectdata = list( + ref = i["ref"], + name = i["name"], + ) + data["object"] += list(objectdata) + + data["target"] = list() + var/list/trackinfo = track() + if(trackinfo) + data["target"] = trackinfo + return data + +/datum/computer_file/program/radar/ui_act(action, params) + if(..()) + return + + switch(action) + if("selecttarget") + selected = params["ref"] + if("scan") + scan() + +/** + *Updates tracking information of the selected target. + * + *The track() proc updates the entire set of information about the location + *of the target, including whether the Ntos window should use a pinpointer + *crosshair over the up/down arrows, or none in favor of a rotating arrow + *for far away targets. This information is returned in the form of a list. + * +*/ +/datum/computer_file/program/radar/proc/track() + var/atom/movable/signal = find_atom() + if(!trackable(signal)) + return + + var/turf/here_turf = (get_turf(computer)) + var/turf/target_turf = (get_turf(signal)) + var/userot = FALSE + var/rot = 0 + var/pointer="crosshairs" + var/locx = (target_turf.x - here_turf.x) + 24 + var/locy = (here_turf.y - target_turf.y) + 24 + + if(get_dist_euclidian(here_turf, target_turf) > 24) + userot = TRUE + rot = round(Get_Angle(here_turf, target_turf)) + else + if(target_turf.z > here_turf.z) + pointer="caret-up" + else if(target_turf.z < here_turf.z) + pointer="caret-down" + + var/list/trackinfo = list( + "locx" = locx, + "locy" = locy, + "userot" = userot, + "rot" = rot, + "arrowstyle" = arrowstyle, + "color" = pointercolor, + "pointer" = pointer, + ) + return trackinfo + +/** + * + *Checks the trackability of the selected target. + * + *If the target is on the computer's Z level, or both are on station Z + *levels, and the target isn't untrackable, return TRUE. + *Arguments: + **arg1 is the atom being evaluated. +*/ +/datum/computer_file/program/radar/proc/trackable(atom/movable/signal) + if(!signal || !computer) + return FALSE + var/turf/here = get_turf(computer) + var/turf/there = get_turf(signal) + if(!here || !there) + return FALSE //I was still getting a runtime even after the above check while scanning, so fuck it + return (there.z == here.z) || (is_station_level(here.z) && is_station_level(there.z)) + +/** + * + *Runs a scan of all the trackable atoms. + * + *Checks each entry in the GLOB of the specific trackable atoms against + *the track() proc, and fill the objects list with lists containing the + *atoms' names and REFs. The objects list is handed to the tgui screen + *for displaying to, and being selected by, the user. A two second + *sleep is used to delay the scan, both for thematical reasons as well + *as to limit the load players may place on the server using these + *somewhat costly loops. +*/ +/datum/computer_file/program/radar/proc/scan() + return + +/** + * + *Finds the atom in the appropriate list that the `selected` var indicates + * + *The `selected` var holds a REF, which is a string. A mob REF may be + *something like "mob_209". In order to find the actual atom, we need + *to search the appropriate list for the REF string. This is dependant + *on the program (Lifeline uses GLOB.human_list, while Fission360 uses + *GLOB.poi_list), but the result will be the same; evaluate the string and + *return an atom reference. +*/ +/datum/computer_file/program/radar/proc/find_atom() + return + +//We use SSfastprocess for the program icon state because it runs faster than process_tick() does. +/datum/computer_file/program/radar/process() + if(computer.active_program != src) + STOP_PROCESSING(SSfastprocess, src) //We're not the active program, it's time to stop. + return + if(!selected) + return + + var/atom/movable/signal = find_atom() + if(!trackable(signal)) + program_icon_state = "[initial(program_icon_state)]lost" + if(last_icon_state != program_icon_state) + computer.update_icon() + last_icon_state = program_icon_state + return + + var/here_turf = get_turf(computer) + var/target_turf = get_turf(signal) + var/trackdistance = get_dist_euclidian(here_turf, target_turf) + switch(trackdistance) + if(0) + program_icon_state = "[initial(program_icon_state)]direct" + if(1 to 12) + program_icon_state = "[initial(program_icon_state)]close" + if(13 to 24) + program_icon_state = "[initial(program_icon_state)]medium" + if(25 to INFINITY) + program_icon_state = "[initial(program_icon_state)]far" + + if(last_icon_state != program_icon_state) + computer.update_icon() + last_icon_state = program_icon_state + computer.setDir(get_dir(here_turf, target_turf)) + +//We can use process_tick to restart fast processing, since the computer will be running this constantly either way. +/datum/computer_file/program/radar/process_tick() + if(computer.active_program == src) + START_PROCESSING(SSfastprocess, src) + +/////////////////// +//Suit Sensor App// +/////////////////// + +///A program that tracks crew members via suit sensors +/datum/computer_file/program/radar/lifeline + filename = "Lifeline" + filedesc = "Lifeline" + extended_desc = "This program allows for tracking of crew members via their suit sensors." + requires_ntnet = TRUE + transfer_access = ACCESS_MEDICAL + available_on_ntnet = TRUE + +/datum/computer_file/program/radar/lifeline/find_atom() + return locate(selected) in GLOB.human_list + +/datum/computer_file/program/radar/lifeline/scan() + if(world.time < next_scan) + return + next_scan = world.time + (2 SECONDS) + objects = list() + for(var/i in GLOB.human_list) + var/mob/living/carbon/human/humanoid = i + if(!trackable(humanoid)) + continue + var/crewmember_name = "Unknown" + if(humanoid.wear_id) + var/obj/item/card/id/ID = humanoid.wear_id.GetID() + if(ID && ID.registered_name) + crewmember_name = ID.registered_name + var/list/crewinfo = list( + ref = REF(humanoid), + name = crewmember_name, + ) + objects += list(crewinfo) + +/datum/computer_file/program/radar/lifeline/trackable(mob/living/carbon/human/humanoid) + if(!humanoid || !istype(humanoid)) + return FALSE + if(..() && istype(humanoid.w_uniform, /obj/item/clothing/under)) + + var/obj/item/clothing/under/uniform = humanoid.w_uniform + if(!uniform.has_sensor || (uniform.sensor_mode < SENSOR_COORDS)) // Suit sensors must be on maximum. + return FALSE + + return TRUE + +//////////////////////// +//Nuke Disk Finder App// +//////////////////////// + +///A program that tracks crew members via suit sensors +/datum/computer_file/program/radar/fission360 + filename = "Fission360" + filedesc = "Fission360" + program_icon_state = "radarsyndicate" + extended_desc = "This program allows for tracking of nuclear authorization disks and warheads." + requires_ntnet = FALSE + transfer_access = null + available_on_ntnet = FALSE + available_on_syndinet = TRUE + tgui_id = "NtosRadarSyndicate" + arrowstyle = "ntosradarpointerS.png" + pointercolor = "red" + +/datum/computer_file/program/radar/fission360/find_atom() + return locate(selected) in GLOB.poi_list + +/datum/computer_file/program/radar/fission360/scan() + if(world.time < next_scan) + return + next_scan = world.time + (2 SECONDS) + objects = list() + for(var/i in GLOB.nuke_list) + var/obj/machinery/nuclearbomb/nuke = i + if(!trackable(nuke)) + continue + + var/list/nukeinfo = list( + ref = REF(nuke), + name = nuke.name, + ) + objects += list(nukeinfo) + var/obj/item/disk/nuclear/disk = locate() in GLOB.poi_list + if(trackable(disk)) + var/list/nukeinfo = list( + ref = REF(disk), + name = disk.name, + ) + objects += list(nukeinfo) diff --git a/code/modules/modular_computers/file_system/programs/robocontrol.dm b/code/modules/modular_computers/file_system/programs/robocontrol.dm new file mode 100644 index 0000000000..8644ce09b4 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/robocontrol.dm @@ -0,0 +1,84 @@ + +/datum/computer_file/program/robocontrol + filename = "robocontrol" + filedesc = "Bot Remote Controller" + program_icon_state = "robot" + extended_desc = "A remote controller used for giving basic commands to non-sentient robots." + transfer_access = ACCESS_ROBOTICS + requires_ntnet = TRUE + network_destination = "robotics control network" + size = 12 + tgui_id = "NtosRoboControl" + ///Number of simple robots on-station. + var/botcount = 0 + ///Used to find the location of the user for the purposes of summoning robots. + var/mob/current_user + ///Access granted by the used to summon robots. + var/list/current_access = list() + +/datum/computer_file/program/robocontrol/ui_data(mob/user) + var/list/data = get_header_data() + var/turf/current_turf = get_turf(ui_host()) + var/zlevel = current_turf.z + var/list/botlist = list() + var/list/mulelist = list() + + var/obj/item/computer_hardware/card_slot/card_slot = computer ? computer.all_components[MC_CARD] : null + data["have_id_slot"] = !!card_slot + if(computer) + var/obj/item/card/id/id_card = card_slot ? card_slot.stored_card : null + data["has_id"] = !!id_card + data["id_owner"] = id_card ? id_card.registered_name : "No Card Inserted." + data["access_on_card"] = id_card ? id_card.access : null + + botcount = 0 + current_user = user + + for(var/B in GLOB.bots_list) + var/mob/living/simple_animal/bot/Bot = B + if(!Bot.on || Bot.z != zlevel || Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected! + continue //Also, the PDA must have access to the bot type. + var/list/newbot = list("name" = Bot.name, "mode" = Bot.get_mode_ui(), "model" = Bot.model, "locat" = get_area(Bot), "bot_ref" = REF(Bot), "mule_check" = FALSE) + if(Bot.bot_type == MULE_BOT) + var/mob/living/simple_animal/bot/mulebot/MULE = Bot + mulelist += list(list("name" = MULE.name, "dest" = MULE.destination, "power" = MULE.cell ? MULE.cell.percent() : 0, "home" = MULE.home_destination, "autoReturn" = MULE.auto_return, "autoPickup" = MULE.auto_pickup, "reportDelivery" = MULE.report_delivery, "mule_ref" = REF(MULE))) + if(MULE.load) + data["load"] = MULE.load.name + newbot["mule_check"] = TRUE + botlist += list(newbot) + + data["bots"] = botlist + data["mules"] = mulelist + data["botcount"] = botlist.len + + return data + +/datum/computer_file/program/robocontrol/ui_act(action, list/params) + if(..()) + return TRUE + var/obj/item/computer_hardware/card_slot/card_slot + var/obj/item/card/id/id_card + if(computer) + card_slot = computer.all_components[MC_CARD] + if(card_slot) + id_card = card_slot.stored_card + + var/list/standard_actions = list("patroloff", "patrolon", "ejectpai") + var/list/MULE_actions = list("stop", "go", "home", "destination", "setid", "sethome", "unload", "autoret", "autopick", "report", "ejectpai") + var/mob/living/simple_animal/bot/Bot = locate(params["robot"]) in GLOB.bots_list + if (action in standard_actions) + Bot.bot_control(action, current_user, current_access) + if (action in MULE_actions) + Bot.bot_control(action, current_user, current_access, TRUE) + switch(action) + if("summon") + Bot.bot_control(action, current_user, id_card ? id_card.access : current_access) + if("ejectcard") + if(!computer || !card_slot) + return + if(id_card) + GLOB.data_core.manifest_modify(id_card.registered_name, id_card.assignment) + card_slot.try_eject(TRUE, current_user) + else + playsound(get_turf(ui_host()) , 'sound/machines/buzz-sigh.ogg', 25, FALSE) + return diff --git a/code/modules/modular_computers/file_system/programs/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/sm_monitor.dm index dbee59bb3e..32ad102871 100644 --- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm @@ -8,10 +8,7 @@ transfer_access = ACCESS_CONSTRUCTION network_destination = "supermatter monitoring system" size = 5 - tgui_id = "ntos_supermatter_monitor" - ui_style = "ntos" - ui_x = 600 - ui_y = 350 + tgui_id = "NtosSupermatterMonitor" var/last_status = SUPERMATTER_INACTIVE var/list/supermatters var/obj/machinery/power/supermatter_crystal/active // Currently selected supermatter crystal. @@ -73,20 +70,22 @@ data["active"] = TRUE data["SM_integrity"] = active.get_integrity() data["SM_power"] = active.power - data["SM_ambienttemp"] = air.temperature + data["SM_ambienttemp"] = air.return_temperature() data["SM_ambientpressure"] = air.return_pressure() //data["SM_EPR"] = round((air.total_moles / air.group_multiplier) / 23.1, 0.01) var/list/gasdata = list() if(air.total_moles()) - for(var/gasid in air.gases) - gasdata.Add(list(list( - "name"= GLOB.meta_gas_names[gasid], - "amount" = round(100*air.gases[gasid]/air.total_moles(),0.01)))) + for(var/gasid in air.get_gases()) + var/amount = air.get_moles(gasid) + if(amount) + gasdata.Add(list(list( + "name"= GLOB.meta_gas_names[gasid], + "amount" = round(100*amount/air.total_moles(),0.01)))) else - for(var/gasid in air.gases) + for(var/gasid in air.get_gases()) gasdata.Add(list(list( "name"= GLOB.meta_gas_names[gasid], "amount" = 0))) @@ -124,4 +123,4 @@ for(var/obj/machinery/power/supermatter_crystal/S in supermatters) if(S.uid == newuid) active = S - return TRUE \ No newline at end of file + return TRUE diff --git a/code/modules/modular_computers/hardware/CPU.dm b/code/modules/modular_computers/hardware/CPU.dm index d08d65ff8b..f13081e1f3 100644 --- a/code/modules/modular_computers/hardware/CPU.dm +++ b/code/modules/modular_computers/hardware/CPU.dm @@ -37,4 +37,4 @@ icon_state = "cpu_super" w_class = WEIGHT_CLASS_TINY power_usage = 75 - max_idle_programs = 2 \ No newline at end of file + max_idle_programs = 2 diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm index 37f3fc434e..b33442f99b 100644 --- a/code/modules/modular_computers/hardware/_hardware.dm +++ b/code/modules/modular_computers/hardware/_hardware.dm @@ -32,28 +32,29 @@ /obj/item/computer_hardware/attackby(obj/item/I, mob/living/user) - // Multitool. Runs diagnostics - if(istype(I, /obj/item/multitool)) - to_chat(user, "***** DIAGNOSTICS REPORT *****") - diagnostics(user) - to_chat(user, "******************************") - return 1 - // 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(I.use_tool(src, user, 0, 1)) + if(S.use(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 if(try_insert(I, user)) - return 1 + return TRUE return ..() +/obj/item/computer_hardware/multitool_act(mob/living/user, obj/item/I) + ..() + to_chat(user, "***** DIAGNOSTICS REPORT *****") + diagnostics(user) + to_chat(user, "******************************") + return TRUE + // Called on multitool click, prints diagnostic information to the user. /obj/item/computer_hardware/proc/diagnostics(var/mob/user) to_chat(user, "Hardware Integrity Test... (Corruption: [damage]/[max_damage]) [damage > damage_failure ? "FAIL" : damage > damage_malfunction ? "WARN" : "PASS"]") diff --git a/code/modules/modular_computers/hardware/ai_slot.dm b/code/modules/modular_computers/hardware/ai_slot.dm index 8428467a87..0ad157afcb 100644 --- a/code/modules/modular_computers/hardware/ai_slot.dm +++ b/code/modules/modular_computers/hardware/ai_slot.dm @@ -9,6 +9,10 @@ var/obj/item/aicard/stored_card = null var/locked = FALSE +/obj/item/computer_hardware/ai_slot/handle_atom_del(atom/A) + if(A == stored_card) + try_eject(0, null, TRUE) + . = ..() /obj/item/computer_hardware/ai_slot/examine(mob/user) . = ..() @@ -41,13 +45,6 @@ /obj/item/computer_hardware/ai_slot/try_eject(slot=0,mob/living/user = null,forced = 0) - if (get_dist(src,user) > 1) - if (iscarbon(user)) - var/mob/living/carbon/H = user - if (!(H.dna && H.dna.check_mutation(TK) && tkMaxRangeCheck(src,H))) - return FALSE - else - return FALSE if(!stored_card) to_chat(user, "There is no card in \the [src].") return FALSE @@ -57,19 +54,21 @@ return FALSE if(stored_card) - stored_card.forceMove(get_turf(src)) + to_chat(user, "You remove [stored_card] from [src].") locked = FALSE - stored_card.verb_pickup() + if(user) + user.put_in_hands(stored_card) + else + stored_card.forceMove(drop_location()) stored_card = null - to_chat(user, "You remove the card from \the [src].") return TRUE return FALSE /obj/item/computer_hardware/ai_slot/attackby(obj/item/I, mob/living/user) if(..()) return - if(istype(I, /obj/item/screwdriver)) + if(I.tool_behaviour == TOOL_SCREWDRIVER) to_chat(user, "You press down on the manual eject button with \the [I].") try_eject(,user,1) - return \ No newline at end of file + return diff --git a/code/modules/modular_computers/hardware/battery_module.dm b/code/modules/modular_computers/hardware/battery_module.dm index e03427cc9c..6e3193abfd 100644 --- a/code/modules/modular_computers/hardware/battery_module.dm +++ b/code/modules/modular_computers/hardware/battery_module.dm @@ -7,6 +7,9 @@ var/obj/item/stock_parts/cell/battery = null device_type = MC_CELL +/obj/item/computer_hardware/battery/get_cell() + return battery + /obj/item/computer_hardware/battery/New(loc, battery_type = null) if(battery_type) battery = new battery_type(src) @@ -16,6 +19,11 @@ . = ..() QDEL_NULL(battery) +/obj/item/computer_hardware/battery/handle_atom_del(atom/A) + if(A == battery) + try_eject(0, null, TRUE) + . = ..() + /obj/item/computer_hardware/battery/try_insert(obj/item/I, mob/living/user = null) if(!holder) return FALSE @@ -45,7 +53,10 @@ to_chat(user, "There is no power cell connected to \the [src].") return FALSE else - battery.forceMove(get_turf(src)) + if(user) + user.put_in_hands(battery) + else + battery.forceMove(drop_location()) to_chat(user, "You detach \the [battery] from \the [src].") battery = null diff --git a/code/modules/modular_computers/hardware/card_slot.dm b/code/modules/modular_computers/hardware/card_slot.dm index e4bc45dbc5..18b423a42e 100644 --- a/code/modules/modular_computers/hardware/card_slot.dm +++ b/code/modules/modular_computers/hardware/card_slot.dm @@ -9,6 +9,13 @@ var/obj/item/card/id/stored_card = null var/obj/item/card/id/stored_card2 = null +/obj/item/computer_hardware/card_slot/handle_atom_del(atom/A) + if(A == stored_card) + try_eject(1, null, TRUE) + if(A == stored_card2) + try_eject(2, null, TRUE) + . = ..() + /obj/item/computer_hardware/card_slot/Destroy() try_eject() return ..() @@ -67,19 +74,15 @@ else stored_card2 = I to_chat(user, "You insert \the [I] into \the [src].") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.sec_hud_set_ID() return TRUE /obj/item/computer_hardware/card_slot/try_eject(slot=0, mob/living/user = null, forced = 0) - if (get_dist(src,user) > 1) - if (iscarbon(user)) - var/mob/living/carbon/H = user - if (!(H.dna && H.dna.check_mutation(TK) && tkMaxRangeCheck(src,H))) - return FALSE - else - return FALSE if(!stored_card && !stored_card2) to_chat(user, "There are no cards in \the [src].") return FALSE @@ -89,7 +92,7 @@ if(user) user.put_in_hands(stored_card) else - stored_card.forceMove(get_turf(src)) + stored_card.forceMove(drop_location()) stored_card = null ejected++ @@ -97,7 +100,7 @@ if(user) user.put_in_hands(stored_card2) else - stored_card2.forceMove(get_turf(src)) + stored_card2.forceMove(drop_location()) stored_card2 = null ejected++ @@ -109,16 +112,18 @@ for(var/I in holder.idle_threads) var/datum/computer_file/program/P = I P.event_idremoved(1, slot) - + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.sec_hud_set_ID() to_chat(user, "You remove the card[ejected>1 ? "s" : ""] from \the [src].") - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0) + playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) return TRUE return FALSE /obj/item/computer_hardware/card_slot/attackby(obj/item/I, mob/living/user) if(..()) return - if(istype(I, /obj/item/screwdriver)) + if(I.tool_behaviour == TOOL_SCREWDRIVER) to_chat(user, "You press down on the manual eject button with \the [I].") try_eject(0,user) return diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index e27eaa53ae..b8b9624388 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -157,18 +157,30 @@ max_capacity = 64 icon_state = "ssd_mini" w_class = WEIGHT_CLASS_TINY - custom_price = PRICE_ABOVE_NORMAL + custom_price = 150 -/obj/item/computer_hardware/hard_drive/small/syndicate // Syndicate variant - very slight better +// Syndicate variant - very slight better +/obj/item/computer_hardware/hard_drive/small/syndicate desc = "An efficient SSD for portable devices developed by a rival organisation." power_usage = 8 max_capacity = 70 var/datum/antagonist/traitor/traitor_data // Syndicate hard drive has the user's data baked directly into it on creation +/// For tablets given to nuke ops +/obj/item/computer_hardware/hard_drive/small/nukeops + power_usage = 8 + max_capacity = 70 + +/obj/item/computer_hardware/hard_drive/small/nukeops/install_default_programs() + store_file(new/datum/computer_file/program/computerconfig(src)) + store_file(new/datum/computer_file/program/ntnetdownload/syndicate(src)) // Syndicate version; automatic access to syndicate apps and no NT apps + store_file(new/datum/computer_file/program/filemanager(src)) + store_file(new/datum/computer_file/program/radar/fission360(src)) //I am legitimately afraid if I don't do this, Ops players will think they just don't get a pinpointer anymore. + /obj/item/computer_hardware/hard_drive/micro name = "micro solid state drive" desc = "A highly efficient SSD chip for portable devices." power_usage = 2 max_capacity = 32 icon_state = "ssd_micro" - w_class = WEIGHT_CLASS_TINY \ No newline at end of file + w_class = WEIGHT_CLASS_TINY diff --git a/code/modules/modular_computers/hardware/printer.dm b/code/modules/modular_computers/hardware/printer.dm index 44383822cc..ebe40c1922 100644 --- a/code/modules/modular_computers/hardware/printer.dm +++ b/code/modules/modular_computers/hardware/printer.dm @@ -10,14 +10,14 @@ /obj/item/computer_hardware/printer/diagnostics(mob/living/user) ..() - to_chat(user, "Paper level: [stored_paper]/[max_paper].") + to_chat(user, "Paper level: [stored_paper]/[max_paper].") /obj/item/computer_hardware/printer/examine(mob/user) . = ..() . += "Paper level: [stored_paper]/[max_paper]." -/obj/item/computer_hardware/printer/proc/print_text(var/text_to_print, var/paper_title = "") +/obj/item/computer_hardware/printer/proc/print_text(text_to_print, paper_title = "") if(!stored_paper) return FALSE if(!check_functionality()) @@ -33,7 +33,6 @@ if(paper_title) P.name = paper_title P.update_icon() - P.reload_fields() stored_paper-- P = null return TRUE @@ -59,4 +58,4 @@ icon_state = "printer_mini" w_class = WEIGHT_CLASS_TINY stored_paper = 5 - max_paper = 15 \ No newline at end of file + max_paper = 15 diff --git a/code/modules/modular_computers/laptop_vendor.dm b/code/modules/modular_computers/laptop_vendor.dm index 9e0e1c8014..a8d30bad21 100644 --- a/code/modules/modular_computers/laptop_vendor.dm +++ b/code/modules/modular_computers/laptop_vendor.dm @@ -27,9 +27,6 @@ var/dev_printer = 0 // 0: None, 1: Standard var/dev_card = 0 // 0: None, 1: Standard - ui_x = 500 - ui_y = 400 - // Removes all traces of old order and allows you to begin configuration from scratch. /obj/machinery/lapvend/proc/reset_order() state = 0 @@ -224,15 +221,15 @@ return TRUE return FALSE -/obj/machinery/lapvend/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) +/obj/machinery/lapvend/ui_interact(mob/user, datum/tgui/ui) if(stat & (BROKEN | NOPOWER | MAINT)) if(ui) ui.close() return FALSE - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + ui = SStgui.try_update_ui(user, src, ui) if (!ui) - ui = new(user, src, ui_key, "computer_fabricator", "Personal Computer Vendor", ui_x, ui_y, state = state) + ui = new(user, src, "ComputerFabricator") ui.open() /obj/machinery/lapvend/attackby(obj/item/I, mob/user) @@ -241,7 +238,7 @@ if(!user.temporarilyRemoveItemFromInventory(c)) return credits += c.value - visible_message("[user] inserts [c.value] credits into [src].") + visible_message("[user] inserts [c.value] cr into [src].") qdel(c) return else if(istype(I, /obj/item/holochip)) @@ -257,10 +254,10 @@ var/datum/bank_account/account = ID.registered_account var/target_credits = total_price - credits if(!account.adjust_money(-target_credits)) - say("Insufficient money on card to purchase!") + say("Insufficient credits on card to purchase!") return credits += target_credits - say("[target_credits] cr has been desposited from your account.") + say("[target_credits] cr has been deposited from your account.") return return ..() @@ -308,4 +305,4 @@ state = 3 addtimer(CALLBACK(src, .proc/reset_order), 100) return TRUE - return FALSE \ No newline at end of file + return FALSE diff --git a/code/modules/movespeed/_movespeed_modifier.dm b/code/modules/movespeed/_movespeed_modifier.dm index 0976f4d067..3bc4463531 100644 --- a/code/modules/movespeed/_movespeed_modifier.dm +++ b/code/modules/movespeed/_movespeed_modifier.dm @@ -144,6 +144,10 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) /// Handles the special case of editing the movement var /mob/vv_edit_var(var_name, var_value) + if(var_name == NAMEOF(src, control_object)) + var/obj/O = var_name + if(!istype(O) || (O.obj_flags & DANGEROUS_POSSESSION)) + return FALSE var/slowdown_edit = (var_name == NAMEOF(src, cached_multiplicative_slowdown)) var/diff if(slowdown_edit && isnum(cached_multiplicative_slowdown) && isnum(var_value)) @@ -195,7 +199,13 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) else continue . += amt + var/old = cached_multiplicative_slowdown // CITAEDL EDIT - To make things a bit less jarring, when in situations where + // your delay decreases, "give" the delay back to the client cached_multiplicative_slowdown = . + var/diff = old - cached_multiplicative_slowdown + if((diff > 0) && client) + if(client.move_delay > world.time + 1.5) + client.move_delay -= diff /// Get the move speed modifiers list of the mob /mob/proc/get_movespeed_modifiers() diff --git a/code/modules/movespeed/modifiers/mobs.dm b/code/modules/movespeed/modifiers/mobs.dm index a2176ca95e..d17767bb1f 100644 --- a/code/modules/movespeed/modifiers/mobs.dm +++ b/code/modules/movespeed/modifiers/mobs.dm @@ -78,9 +78,6 @@ blacklisted_movetypes = FLOATING variable = TRUE -/datum/movespeed_modifier/shove - multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH - /datum/movespeed_modifier/human_carry variable = TRUE diff --git a/code/modules/newscaster/ghostread.dm b/code/modules/newscaster/ghostread.dm index 77cb1a03c8..ff51f5268c 100644 --- a/code/modules/newscaster/ghostread.dm +++ b/code/modules/newscaster/ghostread.dm @@ -3,7 +3,7 @@ set desc = "Open a list of available news channels" set category = "Ghost" - var/datum/browser/B = new(src, "ghost_news_list", "Chanenl List", 450, 600) + var/datum/browser/B = new(src, "ghost_news_list", "Channel List", 450, 600) B.set_content(render_news_channel_list()) B.open() diff --git a/code/modules/newscaster/newscaster_machine.dm b/code/modules/newscaster/newscaster_machine.dm index cb2d49fc64..470b34e82c 100644 --- a/code/modules/newscaster/newscaster_machine.dm +++ b/code/modules/newscaster/newscaster_machine.dm @@ -95,6 +95,10 @@ GLOBAL_LIST_EMPTY(allCasters) . = ..() update_icon() +/obj/machinery/newscaster/attack_ghost(mob/dead/observer/user) + if(istype(user)) + user.read_news() + /obj/machinery/newscaster/ui_interact(mob/user) . = ..() if(ishuman(user) || issilicon(user)) diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index e6d53d914f..00cfa94893 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -14,7 +14,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 slot_flags = ITEM_SLOT_BELT - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF var/datum/effect_system/spark_spread/spark_system diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm index dbe4c80579..a06b753402 100644 --- a/code/modules/ninja/suit/gloves.dm +++ b/code/modules/ninja/suit/gloves.dm @@ -67,6 +67,7 @@ to_chat(H, "Gained [DisplayEnergy(.)] of energy from [A].") else to_chat(H, "\The [A] has run dry of energy, you must find another source!") + . = INTERRUPT_UNARMED_ATTACK else . = FALSE //as to not cancel attack_hand() diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm index 508722ecf2..57faad9493 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm @@ -14,5 +14,5 @@ /obj/item/throwing_star/ninja name = "ninja throwing star" - throwforce = 30 + throwforce = 20 embedding = list("pain_mult" = 6, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) diff --git a/code/modules/oracle_ui/README.md b/code/modules/oracle_ui/README.md deleted file mode 100644 index bc96eb1f51..0000000000 --- a/code/modules/oracle_ui/README.md +++ /dev/null @@ -1,233 +0,0 @@ -# `/datum/oracle_ui` - -This datum is a replacement for tgui which does not use any Node.js dependencies, and works entirely through raw HTML, JS and CSS. It's designed to be reasonably easy to port something from tgui to oracle_ui. - -### How to create a UI - -For this example, we're going to port the disposals bin from tgui to oracle_ui. - -#### Step 1 - -In order to create a UI, you will first need to create an instance of `/datum/oracle_ui` or one of its subclasses, in this case `/datum/oracle_ui/themed/nano`. - -You need to pass in `src`, the width of the window, the height of the window, and the template to render from. You can optionally set some flags to disallow window resizing and whether to automatically refresh the UI. - -`code/modules/recycling/disposal-unit.dm` -```dm -/obj/machinery/disposal/bin/Initialize(mapload, obj/structure/disposalconstruct/make_from) - . = ..() - ui = new /datum/oracle_ui/themed/nano(src, 330, 190, "disposal_bin") - ui.auto_refresh = TRUE - ui.can_resize = FALSE -``` - -#### Step 2 - -You will now need to make a template in `html/oracle_ui/content/{template_name}`. - -Values defined as `@{value}` will get replaced at runtime by oracle_ui. - -`html/oracle_ui/content/disposal_bin/index.html` -```html -
    -
    - State: -
    @{full_pressure}
    -
    -
    - Pressure: -
    -
    -
    -
    @{per}
    -
    -
    -
    -
    - Handle: -
    @{flush}
    -
    -
    - Eject: -
    @{contents}
    -
    -
    - Compressor: -
    @{pressure_charging}
    -
    -
    -``` - -#### Step 3 - -Now you need to implement the methods that provide data to oracle_ui. `oui_data` can be adapted from the `ui_data` proc that tgui uses. - -The `act` proc generates a hyperlink that will result in `oui_act` getting called on your object when clicked. The `class` argument defines a css class to be added to the hyperlink, and disabled determines whether the hyperlink will be disabled or not. - -Calling `soft_update_fields` will result in the UI being updated on all clients, which is useful when the object changes state. - -`code/modules/recycling/disposal-unit.dm` -```dm -/obj/machinery/disposal/bin/oui_data(mob/user) - var/list/data = list() - data["flush"] = flush ? ui.act("Disengage", user, "handle-0", class="active") : ui.act("Engage", user, "handle-1") - data["full_pressure"] = full_pressure ? "Ready" : (pressure_charging ? "Pressurizing" : "Off") - data["pressure_charging"] = pressure_charging ? ui.act("Turn Off", user, "pump-0", class="active", disabled=full_pressure) : ui.act("Turn On", user, "pump-1", disabled=full_pressure) - var/per = full_pressure ? 100 : Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 99) - data["per"] = "[round(per, 1)]%" - data["contents"] = ui.act("Eject Contents", user, "eject", disabled=contents.len < 1) - data["isai"] = isAI(user) - return data -/obj/machinery/disposal/bin/oui_act(mob/user, action, list/params) - if(..()) - return - switch(action) - if("handle-0") - flush = FALSE - update_icon() - . = TRUE - if("handle-1") - if(!panel_open) - flush = TRUE - update_icon() - . = TRUE - if("pump-0") - if(pressure_charging) - pressure_charging = FALSE - update_icon() - . = TRUE - if("pump-1") - if(!pressure_charging) - pressure_charging = TRUE - update_icon() - . = TRUE - if("eject") - eject() - . = TRUE - ui.soft_update_fields() -``` - -#### Step 4 - -You now need to hook in and ensure oracle_ui is invoked upon clicking. `render` should be used to open the UI for a user, typically on click. - -`code/modules/recycling/disposal-unit.dm` -```dm -/obj/machinery/disposal/bin/ui_interact(mob/user, state) - if(stat & BROKEN) - return - if(user.loc == src) - to_chat(user, "You cannot reach the controls from inside!") - return - ui.render(user) -``` - -#### Done - -![gif](https://user-images.githubusercontent.com/202160/37561879-1bb9179e-2a52-11e8-902c-80e6e6df7204.gif) - -You should have a functional UI at this point. Some additional odds and ends can be discovered throughout `code/modules/recycling/disposal-unit.dm`. For a full diff of the changes made to it, refer to [the original pull request on GitHub](https://github.com/OracleStation/OracleStation/pull/702/files#diff-4b6c20ec7d37222630e7524d9577e230). - -### API Reference - -#### `/datum/oracle_ui` - -The main datum which handles the UI. - -##### `get_content(mob/target)` -Returns the HTML that should be displayed for a specified target mob. Calls `oui_getcontent` on the datasource to get the return value. *This proc is not used in the themed subclass.* - -##### `can_view(mob/target)` -Returns whether the specified target mob can view the UI. Calls `oui_canview` on the datasource to get the return value. - -##### `test_viewer(mob/target, updating)` -Tests whether the client is valid and can view the UI. If updating is TRUE, checks to see if they still have the UI window open. - -##### `render(mob/target, updating = FALSE)` -Opens the UI for a target mob, sending HTML. If updating is TRUE, will only do it to clients which still have the window open. - -##### `render_all()` -Does the above, but for all viewers and with updating set to TRUE. - -##### `close(mob/target)` -Closes the UI for the specified target mob. - -##### `close_all()` -Does the above, but for all viewers. - -##### `check_view(mob/target)` -Checks if the specified target mob can view the UI, and if they can't closes their UI - -##### `check_view_all()` -Does the above, but for all viewers. - -##### `call_js(mob/target, js_func, list/parameters = list())` -Invokes `js_func` in the UI of the specified target mob with the specified parameters. - -##### `call_js_all(js_func, list/parameters = list()))` -Does the above, but for all viewers. - -##### `steal_focus(mob/target)` -Causes the UI to steal focus for the specified target mob. - -##### `steal_focus_all()` -Does the above, but for all viewers. - -##### `flash(mob/target, times = -1)` -Causes the UI to flash for the specified target mob the specified number of times, the default keeps the element flashing until focused. - -##### `flash_all()` -Does the above, but for all viewers. - -##### `href(mob/user, action, list/parameters = list())` -Generates a href for the specified user which will invoke `oui_act` on the datasource with the specified action and parameters. - -#### `/datum/oracle_ui/themed` - -A subclass which supports templating and theming. - -##### `get_file(path)` -Loads a file from disk and returns the contents. Caches files loaded from disk for you. - -##### `get_content_file(filename)` -Loads a file from the current content folder and returns the contents. - -##### `get_themed_file(filename)` -Loads a file from the current theme folder and returns the contents. - -##### `process_template(template, variables)` -Processes a template and populates it with the provided variables. - -##### `get_inner_content(mob/target)` -Returns the templated content to be inserted into the main template for the specified target mob. - -##### `soft_update_fields()` -For all viewers, updates the fields in the template via the `updateFields` javaScript function. - -##### `soft_update_all()` -For all viewers, updates the content body in the template via the `replaceContent` javaScript function. - -##### `change_page(var/newpage)` -Changes the template to use to draw the page and forces an update to all viewers - -##### `act(label, mob/user, action, list/parameters = list(), class = "", disabled = FALSE` -Returns a fully formatted hyperlink for the specified user. `label` will be the hyperlink label, `action` and `parameters` are what will be passed to `oui_act`, `class` is any CSS classes to apply to the hyperlink and `disabled` will disable the hyperlink. - -#### `/datum` - -Functions built into all objects to support oracle_ui. There are default implementations for most major superclasses. - -##### `oui_canview(mob/user)` -Returns whether the specified user view the UI at this time. - -##### `oui_getcontent(mob/user)` -Returns the raw HTML to be sent to the specified user. *This proc is not used in the themed subclass of oracle_ui.* - -##### `oui_data(mob/user)` -Returns templating data for the specified user. *This proc is only used in the themed subclass of oracle_ui.* - -##### `oui_data_debug(mob/user)` -Returns the above, but JSON-encoded and escaped, for copy pasting into the web IDE. *This proc is only used for debugging purposes.* - -##### `oui_act(mob/user, action, list/params)` -Called when a hyperlink is clicked in the UI. diff --git a/code/modules/oracle_ui/assets.dm b/code/modules/oracle_ui/assets.dm deleted file mode 100644 index 5d26d80a81..0000000000 --- a/code/modules/oracle_ui/assets.dm +++ /dev/null @@ -1,8 +0,0 @@ -/datum/asset/simple/oui_theme_nano - assets = list( - // JavaScript - "sui-nano-common.js" = 'html/oracle_ui/themes/nano/sui-nano-common.js', - "sui-nano-jquery.min.js" = 'html/oracle_ui/themes/nano/sui-nano-jquery.min.js', - // Stylesheets - "sui-nano-common.css" = 'html/oracle_ui/themes/nano/sui-nano-common.css', - ) diff --git a/code/modules/oracle_ui/hookup_procs.dm b/code/modules/oracle_ui/hookup_procs.dm deleted file mode 100644 index 30db9d92b9..0000000000 --- a/code/modules/oracle_ui/hookup_procs.dm +++ /dev/null @@ -1,46 +0,0 @@ -/datum/proc/oui_canview(mob/user) - return TRUE - -/datum/proc/oui_getcontent(mob/user) - return "Default Implementation" - -/datum/proc/oui_canuse(mob/user) - if(isobserver(user) && !user.silicon_privileges) - return FALSE - return oui_canview(user) - -/datum/proc/oui_data(mob/user) - return list() - -/datum/proc/oui_data_debug(mob/user) - return html_encode(json_encode(oui_data(user))) - -/datum/proc/oui_act(mob/user, action, list/params) - // No Implementation - -/atom/oui_canview(mob/user) - if(isobserver(user)) - return TRUE - if(user.incapacitated()) - return FALSE - if(isobj(src.loc) && get_dist(src, user) < 2) - return TRUE - if(isturf(src.loc) && Adjacent(user)) - return TRUE - return FALSE - -/obj/item/oui_canview(mob/user) - if(src.loc == user) - return src in user.held_items - return ..() - -/obj/machinery/oui_canview(mob/user) - if(hasSiliconAccessInArea(user, ALL)) - return TRUE - if(!can_interact(user)) - return FALSE - if(iscyborg(user)) - return can_see(user, src, 7) - if(isAI(user)) - return GLOB.cameranet.checkTurfVis(get_turf_pixel(src)) - return ..() diff --git a/code/modules/oracle_ui/oracle_ui.dm b/code/modules/oracle_ui/oracle_ui.dm deleted file mode 100644 index 5e8d6b9c7b..0000000000 --- a/code/modules/oracle_ui/oracle_ui.dm +++ /dev/null @@ -1,134 +0,0 @@ -/datum/oracle_ui - var/width = 512 - var/height = 512 - var/can_close = TRUE - var/can_minimize = FALSE - var/can_resize = TRUE - var/titlebar = TRUE - var/window_id = null - var/viewers[0] - var/auto_check_view = TRUE - var/auto_refresh = FALSE - var/atom/datasource = null - var/datum/asset/assets = null - -/datum/oracle_ui/New(atom/n_datasource, n_width = 512, n_height = 512, n_assets = null) - datasource = n_datasource - window_id = REF(src) - width = n_width - height = n_height - -/datum/oracle_ui/Destroy() - close_all() - if(src.datum_flags & DF_ISPROCESSING) - STOP_PROCESSING(SSobj, src) - return ..() - -/datum/oracle_ui/process() - if(auto_check_view) - check_view_all() - if(auto_refresh) - render_all() - -/datum/oracle_ui/proc/get_content(mob/target) - return call(datasource, "oui_getcontent")(target) - -/datum/oracle_ui/proc/can_view(mob/target) - return call(datasource, "oui_canview")(target) - -/datum/oracle_ui/proc/test_viewer(mob/target, updating) - //If the target is null or does not have a client, remove from viewers and return - if(!target | !target.client | !can_view(target)) - viewers -= target - if(viewers.len < 1 && (src.datum_flags & DF_ISPROCESSING)) - STOP_PROCESSING(SSobj, src) //No more viewers, stop polling - close(target) - return FALSE - //If this is an update, and they have closed the window, remove from viewers and return - if(updating && winget(target, window_id, "is-visible") != "true") - viewers -= target - if(viewers.len < 1 && (src.datum_flags & DF_ISPROCESSING)) - STOP_PROCESSING(SSobj, src) //No more viewers, stop polling - return FALSE - return TRUE - -/datum/oracle_ui/proc/render(mob/target, updating = FALSE) - set waitfor = FALSE //Makes this an async call - if(!can_view(target)) - return - //Check to see if they have the window open still if updating - if(updating && !test_viewer(target, updating)) - return - //Send assets - if(!updating && assets) - assets.send(target) - //Add them to the viewers if they aren't there already - viewers |= target - if(!(src.datum_flags & DF_ISPROCESSING) && (auto_refresh | auto_check_view)) - START_PROCESSING(SSobj, src) //Start processing to poll for viewability - //Send the content - if(updating) - target << output(get_content(target), "[window_id].browser") - else - target << browse(get_content(target), "window=[window_id];size=[width]x[height];can_close=[can_close];can_minimize=[can_minimize];can_resize=[can_resize];titlebar=[titlebar];focus=false;") - steal_focus(target) - -/datum/oracle_ui/proc/render_all() - for(var/viewer in viewers) - render(viewer, TRUE) - -/datum/oracle_ui/proc/close(mob/target) - if(target && target.client) - target << browse(null, "window=[window_id]") - -/datum/oracle_ui/proc/close_all() - for(var/viewer in viewers) - close(viewer) - viewers = list() - -/datum/oracle_ui/proc/check_view_all() - for(var/viewer in viewers) - check_view(viewer) - -/datum/oracle_ui/proc/check_view(mob/target) - set waitfor = FALSE //Makes this an async call - if(!test_viewer(target, TRUE)) - close(target) - -/datum/oracle_ui/proc/call_js(mob/target, js_func, list/parameters = list()) - set waitfor = FALSE //Makes this an async call - if(!test_viewer(target, TRUE)) - return - target << output(list2params(parameters),"[window_id].browser:[js_func]") - -/datum/oracle_ui/proc/call_js_all(js_func, list/parameters = list()) - for(var/viewer in viewers) - call_js(viewer, js_func, parameters) - -/datum/oracle_ui/proc/steal_focus(mob/target) - set waitfor = FALSE //Makes this an async call - winset(target, "[window_id]","focus=true") - -/datum/oracle_ui/proc/steal_focus_all() - for(var/viewer in viewers) - steal_focus(viewer) - -/datum/oracle_ui/proc/flash(mob/target, times = -1) - set waitfor = FALSE //Makes this an async call - winset(target, "[window_id]","flash=[times]") - -/datum/oracle_ui/proc/flash_all(times = -1) - for(var/viewer in viewers) - flash(viewer, times) - -/datum/oracle_ui/proc/href(mob/user, action, list/parameters = list()) - var/params_string = replacetext(list2params(parameters),"&",";") - return "?src=[REF(src)];sui_action=[action];sui_user=[REF(user)];[params_string]" - -/datum/oracle_ui/Topic(href, parameters) - var/action = parameters["sui_action"] - var/mob/current_user = locate(parameters["sui_user"]) - if(!call(datasource, "oui_canuse")(current_user)) - return - if(datasource) - call(datasource, "oui_act")(current_user, action, parameters); diff --git a/code/modules/oracle_ui/themed.dm b/code/modules/oracle_ui/themed.dm deleted file mode 100644 index 56b82c2647..0000000000 --- a/code/modules/oracle_ui/themed.dm +++ /dev/null @@ -1,82 +0,0 @@ -/datum/oracle_ui/themed - var/theme = "" - var/content_root = "" - var/current_page = "index.html" - var/root_template = "" - -/datum/oracle_ui/themed/New(atom/n_datasource, n_width = 512, n_height = 512, n_content_root = "") - root_template = get_themed_file("index.html") - content_root = n_content_root - return ..(n_datasource, n_width, n_height, get_asset_datum(/datum/asset/simple/oui_theme_nano)) - -/datum/oracle_ui/themed/process() - if(auto_check_view) - check_view_all() - if(auto_refresh) - soft_update_fields() - -GLOBAL_LIST_EMPTY(oui_template_variables) -GLOBAL_LIST_EMPTY(oui_file_cache) - -/datum/oracle_ui/themed/proc/get_file(path) - if(GLOB.oui_file_cache[path]) - return GLOB.oui_file_cache[path] - else if(fexists(path)) - var/data = file2text(path) - GLOB.oui_file_cache[path] = data - return data - else - var/errormsg = "MISSING PATH '[path]'" -#ifndef UNIT_TESTS - log_world(errormsg) //Because Travis absolutely hates these procs -#endif - return errormsg - -/datum/oracle_ui/themed/proc/get_content_file(filename) - return get_file("./html/oracle_ui/content/[content_root]/[filename]") - -/datum/oracle_ui/themed/proc/get_themed_file(filename) - return get_file("./html/oracle_ui/themes/[theme]/[filename]") - -/datum/oracle_ui/themed/proc/process_template(template, variables) - var/regex/pattern = regex("\\@\\{(\\w+)\\}","gi") - GLOB.oui_template_variables = variables - var/replaced = pattern.Replace(template, /proc/oui_process_template_replace) - GLOB.oui_template_variables = null - return replaced - -/proc/oui_process_template_replace(match, group1) - var/value = GLOB.oui_template_variables[group1] - return "[value]" - -/datum/oracle_ui/themed/proc/get_inner_content(mob/target) - var/list/data = call(datasource, "oui_data")(target) - return process_template(get_content_file(current_page), data) - -/datum/oracle_ui/themed/get_content(mob/target) - var/list/template_data = list("title" = datasource.name, "body" = get_inner_content(target)) - return process_template(root_template, template_data) - -/datum/oracle_ui/themed/proc/soft_update_fields() - for(var/viewer in viewers) - var/json = json_encode(call(datasource, "oui_data")(viewer)) - call_js(viewer, "updateFields", list(json)) - -/datum/oracle_ui/themed/proc/soft_update_all() - for(var/viewer in viewers) - call_js(viewer, "replaceContent", list(get_inner_content(viewer))) - -/datum/oracle_ui/themed/proc/change_page(newpage) - if(newpage == current_page) - return - current_page = newpage - render_all() - -/datum/oracle_ui/themed/proc/act(label, mob/user, action, list/parameters = list(), class = "", disabled = FALSE) - if(disabled) - return "[label]" - else - return "[label]" - -/datum/oracle_ui/themed/nano - theme = "nano" diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index 5e882eb8d0..b8f2c95762 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -137,7 +137,7 @@ virgin = 0 //tabbing here is correct- it's possible for people to try and use it //before the records have been generated, so we do this inside the loop. -/obj/structure/filingcabinet/security/attack_hand() +/obj/structure/filingcabinet/security/on_attack_hand() populate() . = ..() @@ -170,8 +170,7 @@ virgin = 0 //tabbing here is correct- it's possible for people to try and use it //before the records have been generated, so we do this inside the loop. -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/filingcabinet/medical/attack_hand() +/obj/structure/filingcabinet/medical/on_attack_hand() populate() . = ..() @@ -186,9 +185,8 @@ GLOBAL_LIST_EMPTY(employmentCabinets) /obj/structure/filingcabinet/employment - var/cooldown = 0 icon_state = "employmentcabinet" - var/virgin = 1 + var/virgin = TRUE /obj/structure/filingcabinet/employment/Initialize() . = ..() @@ -213,13 +211,12 @@ GLOBAL_LIST_EMPTY(employmentCabinets) new /obj/item/paper/contract/employment(src, employee) /obj/structure/filingcabinet/employment/interact(mob/user) - if(!cooldown) - if(virgin) - fillCurrent() - virgin = 0 - cooldown = 1 - sleep(100) // prevents the devil from just instantly emptying the cabinet, ensuring an easy win. - cooldown = 0 - else + if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_EMPLOYMENT_CABINET)) to_chat(user, "[src] is jammed, give it a few seconds.") - ..() + return ..() + + TIMER_COOLDOWN_START(src, COOLDOWN_EMPLOYMENT_CABINET, 10 SECONDS) // prevents the devil from just instantly emptying the cabinet, ensuring an easy win. + if(virgin) + fillCurrent() + virgin = FALSE + return ..() diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index a599ec9deb..c32afab342 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -50,6 +50,14 @@ name = "folder - '[inputvalue]'" +/obj/item/folder/Destroy() + for(var/obj/important_thing in contents) + if(!(important_thing.resistance_flags & INDESTRUCTIBLE)) + continue + important_thing.forceMove(drop_location()) //don't destroy round critical content such as objective documents. + return ..() + + /obj/item/folder/attack_self(mob/user) var/dat = "[name]" diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index aed3ff5848..5d842ef11a 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -1,10 +1,57 @@ -/* +/** * Paper * also scraps of paper * * lipstick wiping is in code/game/objects/items/weapons/cosmetics.dm! */ +#define MAX_PAPER_LENGTH 5000 +#define MAX_PAPER_STAMPS 30 // Too low? +#define MAX_PAPER_STAMPS_OVERLAYS 4 +#define MODE_READING 0 +#define MODE_WRITING 1 +#define MODE_STAMPING 2 +/** + * This is a custom ui state. All it really does is keep track of pen + * being used and if they are editing it or not. This way we can keep + * the data with the ui rather than on the paper + */ +/datum/ui_state/default/paper_state + /// What edit mode we are in and who is + /// writing on it right now + var/edit_mode = MODE_READING + /// Setup for writing to a sheet + var/pen_color = "black" + var/pen_font = "" + var/is_crayon = FALSE + /// Setup for stamping a sheet + // Why not the stamp obj? I have no idea + // what happens to states out of scope so + // don't want to put instances in this + var/stamp_icon_state = "" + var/stamp_name = "" + var/stamp_class = "" + +/datum/ui_state/default/paper_state/proc/copy_from(datum/ui_state/default/paper_state/from) + switch(from.edit_mode) + if(MODE_READING) + edit_mode = MODE_READING + if(MODE_WRITING) + edit_mode = MODE_WRITING + pen_color = from.pen_color + pen_font = from.pen_font + is_crayon = from.is_crayon + if(MODE_STAMPING) + edit_mode = MODE_STAMPING + stamp_icon_state = from.stamp_icon_state + stamp_class = from.stamp_class + stamp_name = from.stamp_name + +/** + * Paper is now using markdown (like in github pull notes) for ALL rendering + * so we do loose a bit of functionality but we gain in easy of use of + * paper and getting rid of that crashing bug + */ /obj/item/paper name = "paper" gender = NEUTER @@ -21,19 +68,75 @@ resistance_flags = FLAMMABLE max_integrity = 50 dog_fashion = /datum/dog_fashion/head + // drop_sound = 'sound/items/handling/paper_drop.ogg' + // pickup_sound = 'sound/items/handling/paper_pickup.ogg' + grind_results = list(/datum/reagent/cellulose = 3) + color = "white" + /// What's actually written on the paper. + var/info = "" + var/show_written_words = TRUE - var/info //What's actually written on the paper. - var/info_links //A different version of the paper which includes html links at fields and EOF - var/stamps //The (text for the) stamps on the paper. - var/fields = 0 //Amount of user created fields - var/list/stamped + /// The (text for the) stamps on the paper. + var/list/stamps /// Positioning for the stamp in tgui + var/list/stamped /// Overlay info + + /// This REALLY should be a componenet. Basicly used during, april fools + /// to honk at you var/rigged = 0 var/spam_flag = 0 + var/contact_poison // Reagent ID to transfer on contact var/contact_poison_volume = 0 - var/datum/oracle_ui/ui = null - var/force_stars = FALSE // If we should force the text to get obfuscated with asterisks + // Ok, so WHY are we caching the ui's? + // Since we are not using autoupdate we + // need some way to update the ui's of + // other people looking at it and if + // its been updated. Yes yes, lame + // but canot be helped. However by + // doing it this way, we can see + // live updates and have multipule + // people look at it + var/list/viewing_ui = list() + + /// When the sheet can be "filled out" + /// This is an associated list + var/list/form_fields = list() + var/field_counter = 1 + +/obj/item/paper/Destroy() + close_all_ui() + stamps = null + stamped = null + . = ..() + +/** + * This proc copies this sheet of paper to a new + * sheet, Makes it nice and easy for carbon and + * the copyer machine + */ +/obj/item/paper/proc/copy() + var/obj/item/paper/N = new(arglist(args)) + N.info = info + N.color = color + N.update_icon_state() + N.stamps = stamps + N.stamped = stamped.Copy() + N.form_fields = form_fields.Copy() + N.field_counter = field_counter + copy_overlays(N, TRUE) + return N + +/** + * This proc sets the text of the paper and updates the + * icons. You can modify the pen_color after if need + * be. + */ +/obj/item/paper/proc/setText(text) + info = text + form_fields = null + field_counter = 0 + update_icon_state() /obj/item/paper/pickup(user) if(contact_poison && ishuman(user)) @@ -42,62 +145,17 @@ if(!istype(G) || G.transfer_prints) H.reagents.add_reagent(contact_poison,contact_poison_volume) contact_poison = null - ui.check_view_all() - ..() - -/obj/item/paper/dropped(mob/user) - ui.check_view(user) - return ..() - + . = ..() /obj/item/paper/Initialize() . = ..() pixel_y = rand(-8, 8) pixel_x = rand(-9, 9) - ui = new /datum/oracle_ui(src, 420, 600, get_asset_datum(/datum/asset/spritesheet/simple/paper)) - ui.can_resize = FALSE update_icon() - updateinfolinks() - -/obj/item/paper/oui_getcontent(mob/target) - if(!target.is_literate() || force_stars) - force_stars = FALSE - return "[name][stars(info)]
    [stamps]" - else if(istype(target.get_active_held_item(), /obj/item/pen) | istype(target.get_active_held_item(), /obj/item/toy/crayon)) - return "[name][info_links]
    [stamps]" - else - return "[name][info]
    [stamps]" - -/obj/item/paper/oui_canview(mob/target) - if(check_rights_for(target.client, R_FUN)) //Allows admins to view faxes - return TRUE - if(isAI(target)) - force_stars = TRUE - return TRUE - if(iscyborg(target)) - return get_dist(src, target) < 2 - return ..() /obj/item/paper/update_icon_state() - if(resistance_flags & ON_FIRE) - icon_state = "paper_onfire" - return - if(info) - icon_state = "paper_words" - return - icon_state = "paper" - - -/obj/item/paper/examine(mob/user) - . = ..() - . += "Alt-click to fold it." - if(oui_canview(user)) - ui.render(user) - else - . += "You're too far away to read it!" - -/obj/item/paper/proc/show_content(mob/user) - user.examinate(src) + if(info && show_written_words) + icon_state = "[initial(icon_state)]_words" /obj/item/paper/verb/rename() set name = "Rename paper" @@ -117,258 +175,266 @@ if((loc == usr && usr.stat == CONSCIOUS)) name = "paper[(n_name ? text("- '[n_name]'") : null)]" add_fingerprint(usr) - ui.render_all() /obj/item/paper/suicide_act(mob/user) user.visible_message("[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...") return (BRUTELOSS) +/// ONLY USED FOR APRIL FOOLS /obj/item/paper/proc/reset_spamflag() spam_flag = FALSE /obj/item/paper/attack_self(mob/user) - show_content(user) if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS])) if(!spam_flag) spam_flag = TRUE - playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) + playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE) addtimer(CALLBACK(src, .proc/reset_spamflag), 20) - -/obj/item/paper/attack_ai(mob/living/silicon/ai/user) - show_content(user) - -/obj/item/paper/proc/addtofield(id, text, links = 0) - var/locid = 0 - var/laststart = 1 - var/textindex = 1 - while(locid < 15) //hey whoever decided a while(1) was a good idea here, i hate you - var/istart = 0 - if(links) - istart = findtext(info_links, "", laststart) - else - istart = findtext(info, "", laststart) - - if(istart == 0) - return //No field found with matching id - - if(links) - laststart = istart + length(info_links[istart]) - else - laststart = istart + length(info[istart]) - locid++ - if(locid == id) - var/iend = 1 - if(links) - iend = findtext(info_links, "", istart) - else - iend = findtext(info, "", istart) - - //textindex = istart+26 - textindex = iend - break - - if(links) - var/before = copytext(info_links, 1, textindex) - var/after = copytext(info_links, textindex) - info_links = before + text + after - else - var/before = copytext(info, 1, textindex) - var/after = copytext(info, textindex) - info = before + text + after - updateinfolinks() - - -/obj/item/paper/proc/updateinfolinks() - info_links = info - for(var/i in 1 to min(fields, 15)) - addtofield(i, "write", 1) - info_links = info_links + "write" - ui.render_all() - + . = ..() /obj/item/paper/proc/clearpaper() - info = null + info = "" stamps = null LAZYCLEARLIST(stamped) cut_overlays() - updateinfolinks() - update_icon() + update_icon_state() +/obj/item/paper/examine_more(mob/user) + ui_interact(user) + return list("You try to read [src]...") -/obj/item/paper/proc/parsepencode(t, obj/item/pen/P, mob/user, iscrayon = 0) - if(length(t) < 1) //No input means nothing needs to be parsed - return - - t = parsemarkdown(t, user, iscrayon) - - if(!iscrayon) - t = "[t]" - else - var/obj/item/toy/crayon/C = P - t = "[t]" - - // Count the fields - var/laststart = 1 - while(fields < 15) - var/i = findtext(t, "", laststart) - if(i == 0) - break - laststart = i+1 - fields++ - - return t - -/obj/item/paper/proc/reload_fields() // Useful if you made the paper programicly and want to include fields. Also runs updateinfolinks() for you. - fields = 0 - var/laststart = 1 - while(fields < 15) - var/i = findtext(info, "", laststart) - if(i == 0) - break - laststart = i+1 - fields++ - updateinfolinks() - - -/obj/item/paper/proc/openhelp(mob/user) - user << browse({"Paper Help - - You can use backslash (\\) to escape special characters.
    -
    -
    Crayon&Pen commands

    -
    - # text : Defines a header.
    - |text| : Centers the text.
    - **text** : Makes the text bold.
    - *text* : Makes the text italic.
    - ^text^ : Increases the size of the text.
    - %s : Inserts a signature of your name in a foolproof way.
    - %f : Inserts an invisible field which lets you start type from there. Useful for forms.
    -
    -
    Pen exclusive commands

    - ((text)) : Decreases the size of the text.
    - * item : An unordered list item.
    -   * item: An unordered list child item.
    - --- : Adds a horizontal rule. - "}, "window=paper_help") - - -/obj/item/paper/Topic(href, href_list) - ..() - var/literate = usr.is_literate() - if(!usr.canUseTopic(src, BE_CLOSE, literate)) - return - - if(href_list["help"]) - openhelp(usr) - return - if(href_list["write"]) - var/id = href_list["write"] - var/t = stripped_multiline_input("Enter what you want to write:", "Write", no_trim=TRUE) - if(!t || !usr.canUseTopic(src, BE_CLOSE, literate)) - return - var/obj/item/i = usr.get_active_held_item() //Check to see if he still got that darn pen, also check if he's using a crayon or pen. - var/iscrayon = 0 - if(!istype(i, /obj/item/pen)) - if(!istype(i, /obj/item/toy/crayon)) - return - iscrayon = 1 - - if(!in_range(src, usr) && loc != usr && !istype(loc, /obj/item/clipboard) && loc.loc != usr && usr.get_active_held_item() != i) //Some check to see if he's allowed to write - return - - t = parsepencode(t, i, usr, iscrayon) // Encode everything from pencode to html - - if(t != null) //No input from the user means nothing needs to be added - if(id!="end") - addtofield(text2num(id), t) // He wants to edit a field, let him. - else - info += t // Oh, he wants to edit to the end of the file, let him. - updateinfolinks() - show_content(usr) - update_icon() - - -/obj/item/paper/attackby(obj/item/P, mob/living/carbon/human/user, params) - ..() - +/obj/item/paper/can_interact(mob/user) + if(!..()) + return FALSE + // Are we on fire? Hard ot read if so if(resistance_flags & ON_FIRE) + return FALSE + // Even harder to read if your blind...braile? humm + if(user.is_blind()) + return FALSE + // checks if the user can read. + return user.can_read(src) + +/** + * This creates the ui, since we are using a custom state but not much else + * just makes it easyer to make it. + */ +/obj/item/paper/proc/create_ui(mob/user, datum/ui_state/default/paper_state/state) + ui_interact(user, state = state) + +/obj/item/proc/burn_paper_product_attackby_check(obj/item/I, mob/living/user, bypass_clumsy) + var/ignition_message = I.ignition_effect(src, user) + if(!ignition_message) + return + . = TRUE + if(!bypass_clumsy && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && Adjacent(user)) + user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ + "You miss [src] and accidentally light yourself on fire!") + if(user.is_holding(I)) //checking if they're holding it in case TK is involved + user.dropItemToGround(I) + user.adjust_fire_stacks(1) + user.IgniteMob() return - if(is_blind(user)) + if(user.is_holding(src)) //no TK shit here. + user.dropItemToGround(src) + user.visible_message(ignition_message) + add_fingerprint(user) + fire_act(I.get_temperature()) + +/obj/item/paper/attackby(obj/item/P, mob/living/user, params) + if(burn_paper_product_attackby_check(P, user)) + close_all_ui() return if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon)) - if(user.is_literate()) - show_content(user) - return - else - to_chat(user, "You don't know how to read or write.") + if(length(info) >= MAX_PAPER_LENGTH) // Sheet must have less than 1000 charaters + to_chat(user, "This sheet of paper is full!") return + var/datum/ui_state/default/paper_state/state = new + state.edit_mode = MODE_WRITING + // should a crayon be in the same subtype as a pen? How about a brush or charcoal? + // TODO: Convert all writing stuff to one type, /obj/item/art_tool maybe? + state.is_crayon = istype(P, /obj/item/toy/crayon); + if(state.is_crayon) + var/obj/item/toy/crayon/PEN = P + state.pen_font = CRAYON_FONT + state.pen_color = PEN.paint_color + else + var/obj/item/pen/PEN = P + state.pen_font = PEN.font + state.pen_color = PEN.colour + + create_ui(user, state) + return else if(istype(P, /obj/item/stamp)) - if(!in_range(src, user)) - return + var/datum/ui_state/default/paper_state/state = new + state.edit_mode = MODE_STAMPING // we are read only becausse the sheet is full + state.stamp_icon_state = P.icon_state + state.stamp_name = P.name var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper) - if (isnull(stamps)) - stamps = sheet.css_tag() - stamps += sheet.icon_tag(P.icon_state) - var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[P.icon_state]") - stampoverlay.pixel_x = rand(-2, 2) - stampoverlay.pixel_y = rand(-3, 2) + state.stamp_class = sheet.icon_class_name(P.icon_state) - LAZYADD(stamped, P.icon_state) - add_overlay(stampoverlay) + to_chat(user, "You ready your stamp over the paper! ") - to_chat(user, "You stamp the paper with your rubber stamp.") - ui.render_all() + create_ui(user, state) + return /// Normaly you just stamp, you don't need to read the thing + else + // cut paper? the sky is the limit! + var/datum/ui_state/default/paper_state/state = new + state.edit_mode = MODE_READING + create_ui(user, state) // The other ui will be created with just read mode outside of this - if(P.get_temperature()) - if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10)) - user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ - "You miss the paper and accidentally light yourself on fire!") - user.dropItemToGround(P) - user.adjust_fire_stacks(1) - user.IgniteMob() - return + return ..() - if(!(in_range(user, src))) //to prevent issues as a result of telepathically lighting a paper - return - - user.dropItemToGround(src) - user.visible_message("[user] lights [src] ablaze with [P]!", "You light [src] on fire!") - fire_act() - - - add_fingerprint(user) /obj/item/paper/fire_act(exposed_temperature, exposed_volume) - ..() - if(!(resistance_flags & FIRE_PROOF)) - icon_state = "paper_onfire" + . = ..() + if(.) info = "[stars(info)]" +/obj/item/paper/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/simple/paper), + ) -/obj/item/paper/extinguish() - ..() - update_icon() +/obj/item/paper/ui_interact(mob/user, datum/tgui/ui, + datum/ui_state/default/paper_state/state) + // Update the state + ui = ui || SStgui.get_open_ui(user, src) + if(ui && state) + var/datum/ui_state/default/paper_state/current_state = ui.state + current_state.copy_from(state) + // Update the UI + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PaperSheet", name) + state = new + ui.set_state(state) + ui.set_autoupdate(FALSE) + viewing_ui[user] = ui + ui.open() -/* +/obj/item/paper/ui_close(mob/user) + /// close the editing window and change the mode + viewing_ui[user] = null + . = ..() + +// Again, we have to do this as autoupdate is off +/obj/item/paper/proc/update_all_ui() + for(var/datum/tgui/ui in viewing_ui) + ui.process(force = TRUE) + +// Again, we have to do this as autoupdate is off +/obj/item/paper/proc/close_all_ui() + for(var/datum/tgui/ui in viewing_ui) + ui.close() + viewing_ui = list() + +/obj/item/paper/ui_data(mob/user) + var/list/data = list() + + var/datum/tgui/ui = viewing_ui[user] + var/datum/ui_state/default/paper_state/state = ui.state + + // Should all this go in static data and just do a forced update? + data["text"] = info + data["max_length"] = MAX_PAPER_LENGTH + data["paper_state"] = icon_state /// TODO: show the sheet will bloodied or crinkling? + data["paper_color"] = !color || color == "white" ? "#FFFFFF" : color // color might not be set + data["stamps"] = stamps + + data["edit_mode"] = state.edit_mode + data["edit_usr"] = "[ui.user]"; + + // pen info for editing + data["is_crayon"] = state.is_crayon + data["pen_font"] = state.pen_font + data["pen_color"] = state.pen_color + // stamping info for..stamping + data["stamp_class"] = state.stamp_class + + data["field_counter"] = field_counter + data["form_fields"] = form_fields + + return data + +/obj/item/paper/ui_act(action, params, datum/tgui/ui, datum/ui_state/default/paper_state/state) + if(..()) + return + switch(action) + if("stamp") + var/stamp_x = text2num(params["x"]) + var/stamp_y = text2num(params["y"]) + var/stamp_r = text2num(params["r"]) // rotation in degrees + + if (isnull(stamps)) + stamps = new/list() + if(stamps.len < MAX_PAPER_STAMPS) + // I hate byond when dealing with freaking lists + stamps += list(list(state.stamp_class, stamp_x, stamp_y,stamp_r)) /// WHHHHY + + /// This does the overlay stuff + if (isnull(stamped)) + stamped = new/list() + if(stamped.len < MAX_PAPER_STAMPS_OVERLAYS) + var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[state.stamp_icon_state]") + stampoverlay.pixel_x = rand(-2, 2) + stampoverlay.pixel_y = rand(-3, 2) + add_overlay(stampoverlay) + LAZYADD(stamped, state.stamp_icon_state) + + ui.user.visible_message("[ui.user] stamps [src] with [state.stamp_name]!", "You stamp [src] with [state.stamp_name]!") + else + to_chat(usr, pick("You try to stamp but you miss!", "There is no where else you can stamp!")) + + update_all_ui() + . = TRUE + + if("save") + var/in_paper = params["text"] + var/paper_len = length(in_paper) + var/list/fields = params["form_fields"] + field_counter = params["field_counter"] ? text2num(params["field_counter"]) : field_counter + + if(paper_len > MAX_PAPER_LENGTH) + // Side note, the only way we should get here is if + // the javascript was modified, somehow, outside of + // byond. but right now we are logging it as + // the generated html might get beyond this limit + log_paper("[key_name(ui.user)] writing to paper [name], and overwrote it by [paper_len-MAX_PAPER_LENGTH]") + if(paper_len == 0) + to_chat(ui.user, pick("Writing block strikes again!", "You forgot to write anthing!")) + else + log_paper("[key_name(ui.user)] writing to paper [name]") + if(info != in_paper) + to_chat(ui.user, "You have added to your paper masterpiece!"); + info = in_paper + + for(var/key in fields) + form_fields[key] = fields[key]; + + + update_all_ui() + update_icon() + + . = TRUE + +/** * Construction paper */ - /obj/item/paper/construction /obj/item/paper/construction/Initialize() . = ..() color = pick("FF0000", "#33cc33", "#ffb366", "#551A8B", "#ff80d5", "#4d94ff") -/* +/** * Natural paper */ - /obj/item/paper/natural/Initialize() . = ..() color = "#FFF5ED" @@ -377,13 +443,20 @@ name = "paper scrap" icon_state = "scrap" slot_flags = null + show_written_words = FALSE -/obj/item/paper/crumpled/ComponentInitialize() - . = ..() - AddElement(/datum/element/update_icon_blocker) +/obj/item/paper/crumpled/update_icon_state() + return /obj/item/paper/crumpled/bloody icon_state = "scrap_bloodied" /obj/item/paper/crumpled/muddy icon_state = "scrap_mud" + +#undef MAX_PAPER_LENGTH +#undef MAX_PAPER_STAMPS +#undef MAX_PAPER_STAMPS_OVERLAYS +#undef MODE_READING +#undef MODE_WRITING +#undef MODE_STAMPING diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm index 0a7bf011a7..3937720f74 100644 --- a/code/modules/paperwork/paper_cutter.dm +++ b/code/modules/paperwork/paper_cutter.dm @@ -66,10 +66,7 @@ return ..() -/obj/item/papercutter/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/papercutter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) add_fingerprint(user) if(!storedcutter) to_chat(user, "The cutting blade is gone! You can't use [src] now.") diff --git a/code/modules/paperwork/paper_premade.dm b/code/modules/paperwork/paper_premade.dm index 23c8d47323..392eba5f56 100644 --- a/code/modules/paperwork/paper_premade.dm +++ b/code/modules/paperwork/paper_premade.dm @@ -4,7 +4,49 @@ /obj/item/paper/fluff/sop name = "paper- 'Standard Operating Procedure'" - info = "Alert Levels:
    \nBlue- Emergency
    \n\t1. Caused by fire
    \n\t2. Caused by manual interaction
    \n\tAction:
    \n\t\tClose all fire doors. These can only be opened by resetting the alarm
    \nRed- Ejection/Self Destruct
    \n\t1. Caused by module operating computer.
    \n\tAction:
    \n\t\tAfter the specified time the module will eject completely.
    \n
    \nEngine Maintenance Instructions:
    \n\tShut off ignition systems:
    \n\tActivate internal power
    \n\tActivate orbital balance matrix
    \n\tRemove volatile liquids from area
    \n\tWear a fire suit
    \n
    \n\tAfter
    \n\t\tDecontaminate
    \n\t\tVisit medical examiner
    \n
    \nToxin Laboratory Procedure:
    \n\tWear a gas mask regardless
    \n\tGet an oxygen tank.
    \n\tActivate internal atmosphere
    \n
    \n\tAfter
    \n\t\tDecontaminate
    \n\t\tVisit medical examiner
    \n
    \nDisaster Procedure:
    \n\tFire:
    \n\t\tActivate sector fire alarm.
    \n\t\tMove to a safe area.
    \n\t\tGet a fire suit
    \n\t\tAfter:
    \n\t\t\tAssess Damage
    \n\t\t\tRepair damages
    \n\t\t\tIf needed, Evacuate
    \n\tMeteor Shower:
    \n\t\tActivate fire alarm
    \n\t\tMove to the back of ship
    \n\t\tAfter
    \n\t\t\tRepair damage
    \n\t\t\tIf needed, Evacuate
    \n\tAccidental Reentry:
    \n\t\tActivate fire alarms in front of ship.
    \n\t\tMove volatile matter to a fire proof area!
    \n\t\tGet a fire suit.
    \n\t\tStay secure until an emergency ship arrives.
    \n
    \n\t\tIf ship does not arrive-
    \n\t\t\tEvacuate to a nearby safe area!" + info = {" +Alert Levels: +* Blue - Emergency + * Caused by fire + * Caused by manual interaction + * Action: Close all fire doors. These can only be opened by resetting the alarm +* Red- Ejection/Self Destruct + * Caused by module operating computer. + * Action: After the specified time the module will eject completely. +Engine Maintenance Instructions: +1. Shut off ignition systems: +2. Activate internal power +3. Activate orbital balance matrix +4. Remove volatile liquids from area +5. Wear a fire suit +6. After Decontaminate Visit medical examiner +Toxin Laboratory Procedure: +1. Wear a gas mask regardless +2. Get an oxygen tank. +3. Activate internal atmosphere +4. After Decontaminate Visit medical examiner +Disaster Procedure: +Fire: +1. Activate sector fire alarm. +2. Move to a safe area. +3. Get a fire suit +* After: + 1. Assess Damage + 2. Repair damages + 3. If needed, Evacuate +Meteor Shower: +1. Activate fire alarm +2. Move to the back of ship +* After + 1. Repair damage + 2. If needed, Evacuate +Accidental Reentry: +1. Activate fire alarms in front of ship. +2. Move volatile matter to a fire proof area! +3. Get a fire suit. +4. Stay secure until an emergency ship arrives. +5. If ship does not arrive-Evacuate to a nearby safe area! +"}; /obj/item/paper/fluff/shuttles/daniel info = "i love daniel
    daniel is my best friend

    you are tearing me apart elise" @@ -54,7 +96,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- 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" + info = "To ensure minimal employee downtime, please take note of the following changes to select professions that CogStation specifically requires:
    \n
    \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" @@ -62,7 +104,7 @@ /obj/item/paper/guides/cogstation/disposals name = "Regarding the disposal system:" - info = "As you might have noticed, this station has far more disposal pipes than you may expect from your average Nanotrasen research facility. Part of the reason for this is specialization - mail, trash, even corpses have their own disposal systems. Unfortunately, the convenient color-coding was lost in translocation and we've had to compensate by marking the area around each bin.
    \n
    \n- WHITE/GRAY STRIPES is for DELIVERIES.
    \n- RED STRIPES is for CORPSES.
    \n- EVERYTHING ELSE is for TRASH,
    barring a few exceptions that should be labeled as such.
    \n
    \nIdeally the station won't sustain any heavy structural damage during your time here but if it does, or someone decides to tamper with/sabotage this system, you'll be forgiven if you can't put it back together perfectly.
    \n
    \n-C. Donnelly
    Architectural Analyst" + info = "As you might have noticed, this station has far more disposal pipes than you may expect from your average Nanotrasen research facility. Part of the reason for this is specialization - mail, trash, even corpses have their own disposal systems. Unfortunately, the convenient color-coding was lost in translocation and we've had to compensate by marking the area around each bin.
    \n
    \n- WHITE/GRAY STRIPES are for DELIVERIES.
    \n- RED STRIPES are for CORPSES.
    \n- EVERYTHING ELSE is for TRASH,
    barring a few exceptions that should be labeled as such.
    \n
    \nIdeally the station won't sustain any heavy structural damage during your time here but if it does, or someone decides to tamper with/sabotage this system, you'll be forgiven if you can't put it back together perfectly.
    \n
    \n-C. Donnelly
    Architectural Analyst" /obj/item/paper/guides/cogstation/janitor name = "a quick tip" @@ -86,7 +128,7 @@ /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 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" + 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 protection 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:" @@ -98,15 +140,15 @@ /obj/item/paper/guides/cogstation/letter_hos name = "To the future HoS" - info = "I'm gonna be rather disappointed if CentCom doesn't brief you about this station, but if they don't I wrote up another letter for your department that should cover it pretty well. Make sure your officers read it if they aren't up to speed.
    \n
    \nSomething you in particular should know is that if someone's getting to be too much to handle, the boys and I have constructed a 'discount transfer centre' just behind the router. Use it only as a last resort - the walls may be reinforced but they're still thin, and you'll have big trouble on your hands if the AI or any cyborgs find out about it.
    \n
    -LC" + info = "I'm gonna be rather disappointed if Central Command doesn't brief you about this station, but if they don't I wrote up another letter for your department that should cover it pretty well. Make sure your officers read it if they aren't up to speed.
    \n
    \nSomething you in particular should know is that if someone's getting to be too much to handle, the boys and I have constructed a 'discount transfer centre' just behind the router. Use it only as a last resort - the walls may be reinforced but they're still thin, and you'll have big trouble on your hands if the AI or any cyborgs find out about it.
    \n
    -LC" /obj/item/paper/guides/cogstation/letter_supp name = "To future Supply Staff:" - info = "Cargo, move freight. Miners, don't die. Your jobs are pretty straightforward, which is likely why they originally fell under Engineering on this station as opposed to their own department. Although we've considerably readjusted this part of the station to accommodate you, there are potential differences you should be aware of.
    \n
    \nEngineeringwill have access to some of your department, namely the warehouse and mining dock. Mining operations on this station were originally asteroid-based, hence the catwalk into the great beyond. Although you won't need to worry about being space-worthy due to a newly installed shuttle dock, they might need to get out there.
    \n
    \nYou'll have all your usual means of shipping out goods, but the disposal network is more complex with a separate line for mail and trash. I've left another note that explains this in detail, but know trash is the janitor's responsibility, not yours.
    \n
    \nThe biggest difference has to be this station's router system, which allows departments to ship goods between themselves. Even if the belts aren't working properly they'll still have their own request consoles, so you'll want to check for orders regularly.
    \n
    \n-C. Donnelly
    \nArchitectural Analyst" + info = "Cargo, move freight. Miners, don't die. Your jobs are pretty straightforward, which is likely why they originally fell under Engineering on this station as opposed to their own department. Although we've considerably readjusted this part of the station to accommodate you, there are potential differences you should be aware of.
    \n
    \nEngineeringwill have access to some of your department, namely the warehouse and mining dock. Mining operations on this station were originally asteroid-based, hence the catwalk into the great beyond. Although you won't need to worry about being space-worthy due to a newly installed shuttle dock, they might need to get out there.
    \n
    \nYou'll have all your usual means of shipping out goods, but the disposal network is more complex with a separate line for mail and trash. It also isn't fully space-proofed, meanin it may not be the best choice for livestock, monkey cubes, or clowns. I've left another note that explains this in detail, but know trash is the janitor's responsibility, not yours.
    \n
    \nThe biggest difference has to be this station's router system, which allows departments to ship goods between themselves. Even if the belts aren't working properly they'll still have their own request consoles, so you'll want to check for orders regularly.
    \n
    \n-C. Donnelly
    \nArchitectural Analyst" -/obj/item/paper/fluff/cogstation/sleepers - name = "Re: Sleepers?" - info = "Yes, the sleepers are meant to be publicly accessible. Policies in this station's original location encouraged crew to visit the clinic or treat themselves when it came to minor injuries.
    \n
    \nThis is no excuse for you not to do your jobs. You may wish to keep an eye on the sleepers as to ensure they're being used responsibly. Remember, allowing an overdose to happen under your watch isn't much different from administering that overdose yourself.
    \n
    \n- Dr. Halley" +/obj/item/paper/guides/cogstation/letter_med + name = "Re: Future Medical Staff" + info = "With this station nearing approval for regular use, I've been told to consolidate anything noteworthy about its general medical department into a single document. As you may be able to guess, this is that document.
    \n
    \n- First, you should know a medical clinic is present in the civilian (starboard bow) wing. If you have personnel to spare, it's recommended you have someone staff it - that way people with minor injuries can report there instead of clogging up the research wing.
    \n
    \n- Despite recent renovations to bring this station in line with regional policy, you'll still find the robotics lab directly adjacent to your department. I advise you take full advantage of this, whether it's requesting prosthetics in advance or harvesting organs from those who have undergone more...permanent procedures.
    \n
    \n- Lastly, please make a habit of checking the morgue on a regular basis. Thanks to the Corpse Disposal Network (or CDN for short), you may find the station's deceased delivered directly to you. Some may be employees capable of being revived - more information can be found in the morgue itself.
    \n
    \n- Dr. Halley" /obj/item/paper/fluff/cogstation/cloner name = "Re: Issue with the cloner?" @@ -130,7 +172,7 @@ /obj/item/paper/fluff/cogstation/letter_chap name = "A message from the DHDA" - info = "Regardless of what the name leads you to believe, CogStation is neither Ratvarian in origin nor designed by members of this so-called 'clock cult'. Despite a potential common enemy and instances of exhibiting peaceful behavior, their beliefs have been labeled 'Heretical' by the Department of Higher-Dimensional Affairs and following them is grounds for immediate termination.
    \nAs the station's designated Chaplain, it is advised you correct anyone who claims this station and/or its designers are Ratvarian. While they are most likely misinformed or 'joking around', untruths gain credibility the more they are repeated.
    \n
    \nSoulstone Obelisk
    \n
    \nDepartment of Higher-Dimensional Affairs" + info = "Regardless of what the name leads you to believe, CogStation is neither Ratvarian in origin nor designed by members of this so-called 'clock cult'. Despite a potential common enemy and instances of exhibiting peaceful behavior, their beliefs have been labeled 'Heretical' by the Department of Higher-Dimensional Affairs and following them is grounds for immediate termination.
    \nAs the station's designated Chaplain, it is advised you correct anyone who claims this station and/or its designers are Ratvarian. While they are most likely misinformed or 'joking around', untruths gain credibility the more they are repeated.
    \n
    \nSoulstone Obelisk
    \n
    \nDepartment of Higher-Dimensional Affairs" /obj/item/paper/fluff/cogstation/cluwne name = "Mysterious Note" @@ -142,7 +184,7 @@ /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" + 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
    \nGenerated by Organic Resources Bot #2053" /obj/item/paper/fluff/cogstation/chemists name = "Re: Scientists?!" @@ -150,7 +192,7 @@ /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" + 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" /obj/item/paper/fluff/cogstation/bsrb name = "Message from the NTBSRB" @@ -172,9 +214,9 @@ name = "ROUTER STATUS: LIMITED" info = "Currently, this router cannot receive deliveries from the Airbridge, MedSci, Security, or Service Routers. Cargo and the recycler are the only points currently accepting deliveries from here, although manual input from the routing depot is currently required.
    \n
    \n-C. Donnelly
    \n
    \nArchitectural Analyst" -/obj/item/paper/fluff/cogstation/router_cargo - name = "ROUTER STATUS: VERY LIMITED" - info = "Currently, this router cannot receive deliveries from the Airbridge, MedSci, Security, or Service Routers. It is not yet capable of making deliveries, beyond sending items to the recycler.
    \n
    \n-C. Donnelly
    \n
    \nArchitectural Analyst" +/obj/item/paper/fluff/cogstation/mulebot + name = "MEMO: MULEbots" + info = "As you may know, MULEbots have been coded to minimize travel distance for maximum efficiency. In the case of this station, that may include travelling through depressurized areas exposed to space. Please bear this in mind before using them to transport living tissue.
    \n
    \nGenerated by Organic Resources Bot #2053" /////////// CentCom diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index b8bcbedbbe..28cb5ffae9 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -11,6 +11,8 @@ throw_speed = 3 throw_range = 7 pressure_resistance = 8 + attack_hand_speed = CLICK_CD_RAPID + attack_hand_is_action = TRUE var/papertype = /obj/item/paper var/total_paper = 30 var/list/papers = list() @@ -60,11 +62,9 @@ /obj/item/paper_bin/attack_paw(mob/user) return attack_hand(user) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/paper_bin/attack_hand(mob/user) +/obj/item/paper_bin/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.lying) return - user.changeNext_move(CLICK_CD_MELEE) if(bin_pen) var/obj/item/pen/P = bin_pen P.add_fingerprint(user) @@ -85,9 +85,8 @@ P = new papertype(src) if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS]) if(prob(30)) - P.info = "HONK HONK HONK HONK HONK HONK HONK
    HOOOOOOOOOOOOOOOOOOOOOONK
    APRIL FOOLS
    " + P.info = "*HONK HONK HONK HONK HONK HONK HONK
    HOOOOOOOOOOOOOOOOOOOOOONK*\n*APRIL FOOLS*\n" P.rigged = 1 - P.updateinfolinks() P.add_fingerprint(user) P.forceMove(user.loc) @@ -149,7 +148,7 @@ papertype = /obj/item/paper/natural resistance_flags = FLAMMABLE -/obj/item/paper_bin/bundlenatural/attack_hand(mob/user) +/obj/item/paper_bin/bundlenatural/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) ..() if(total_paper < 1) qdel(src) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index a9baf60c0c..c6a1ee1389 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -123,6 +123,7 @@ H.DefaultCombatKnockdown(40) H.emote("scream") + /obj/item/paper/examine(mob/user) . = ..() . += "Alt-click [src] to fold it into a paper plane." diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 08252d4e05..91b8a6719b 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -28,6 +28,7 @@ var/degrees = 0 var/font = PEN_FONT embedding = list() + sharpness = SHARP_POINTY /obj/item/pen/suicide_act(mob/user) user.visible_message("[user] is scribbling numbers all over [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit sudoku...") @@ -84,7 +85,7 @@ throw_speed = 4 colour = "crimson" custom_materials = list(/datum/material/gold = 750) - sharpness = IS_SHARP + sharpness = SHARP_EDGED resistance_flags = FIRE_PROOF unique_reskin = list("Oak" = "pen-fountain-o", "Gold" = "pen-fountain-g", @@ -146,7 +147,7 @@ log_game("[user] [key_name(user)] has renamed [O] to [input]") if(penchoice == "Change description") - var/input = stripped_input(user,"Describe \the [O.name] here", ,"", 100) + var/input = stripped_input(user,"Describe \the [O.name] here", ,"", 2048) if(QDELETED(O) || !user.canUseTopic(O, BE_CLOSE)) return O.desc = input @@ -180,7 +181,7 @@ */ /obj/item/pen/edagger attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off - sharpness = IS_SHARP + sharpness = SHARP_EDGED var/on = FALSE embedding = list(embed_chance = EMBED_CHANCE) diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 3c4aebdba3..0b1f3bb01d 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -31,7 +31,7 @@ /obj/machinery/photocopier/ui_interact(mob/user) . = ..() - var/dat = "Photocopier

    " + var/list/dat = list("Photocopier

    ") if(copy || photocopy || doccopy || (ass && (ass.loc == src.loc))) dat += "Remove Paper
    " if(toner) @@ -48,7 +48,7 @@ dat += "Current toner level: [toner]" if(!toner) dat +="
    Please insert a new toner cartridge!" - user << browse(dat, "window=copier") + user << browse(dat.Join(""), "window=copier") onclose(user, "copier") /obj/machinery/photocopier/Topic(href, href_list) @@ -77,17 +77,14 @@ c.info += copied c.info += "
    " c.name = copy.name - c.fields = copy.fields c.update_icon() - c.updateinfolinks() c.stamps = copy.stamps if(copy.stamped) c.stamped = copy.stamped.Copy() c.copy_overlays(copy, TRUE) toner-- busy = TRUE - sleep(15) - busy = FALSE + addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) else break updateUsrDialog() @@ -96,8 +93,7 @@ if(toner >= 5 && !busy && photocopy) //Was set to = 0, but if there was say 3 toner left and this ran, you would get -2 which would be weird for ink new /obj/item/photo (loc, photocopy.picture.Copy(greytoggle == "Greyscale"? TRUE : FALSE)) busy = TRUE - sleep(15) - busy = FALSE + addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) else break else if(doccopy) @@ -106,40 +102,35 @@ new /obj/item/documents/photocopy(loc, doccopy) toner-= 6 // the sprite shows 6 papers, yes I checked busy = TRUE - sleep(15) - busy = FALSE + addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) else break updateUsrDialog() else if(ass) //ASS COPY. By Miauw for(var/i = 0, i < copies, i++) var/icon/temp_img - if(ishuman(ass) && (ass.get_item_by_slot(SLOT_W_UNIFORM) || ass.get_item_by_slot(SLOT_WEAR_SUIT))) + if(ishuman(ass) && (ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) || ass.get_item_by_slot(ITEM_SLOT_OCLOTHING))) to_chat(usr, "You feel kind of silly, copying [ass == usr ? "your" : ass][ass == usr ? "" : "\'s"] ass with [ass == usr ? "your" : "[ass.p_their()]"] clothes on." ) break else if(toner >= 5 && !busy && check_ass()) //You have to be sitting on the copier and either be a xeno or a human without clothes on. if(isalienadult(ass) || istype(ass, /mob/living/simple_animal/hostile/alien)) //Xenos have their own asses, thanks to Pybro. temp_img = icon('icons/ass/assalien.png') else if(ishuman(ass)) //Suit checks are in check_ass - var/mob/living/carbon/human/H = ass - if(H.dna.features["body_model"] == FEMALE) - temp_img = icon('icons/ass/assfemale.png') - else - temp_img = icon('icons/ass/assmale.png') + temp_img = icon(ass.gender == FEMALE ? 'icons/ass/assfemale.png' : 'icons/ass/assmale.png') else if(isdrone(ass)) //Drones are hot temp_img = icon('icons/ass/assdrone.png') else break - var/obj/item/photo/p = new /obj/item/photo (loc) - p.pixel_x = rand(-10, 10) - p.pixel_y = rand(-10, 10) - p.picture = new(null, "You see [ass]'s ass on the photo.", temp_img) - p.picture.psize_x = 128 - p.picture.psize_y = 128 - p.update_icon() - toner -= 5 busy = TRUE sleep(15) + var/obj/item/photo/p = new /obj/item/photo (loc) + var/datum/picture/toEmbed = new(name = "[ass]'s Ass", desc = "You see [ass]'s ass on the photo.", image = temp_img) + p.pixel_x = rand(-10, 10) + p.pixel_y = rand(-10, 10) + toEmbed.psize_x = 128 + toEmbed.psize_y = 128 + p.set_picture(toEmbed, TRUE, TRUE) + toner -= 5 busy = FALSE else break @@ -179,8 +170,7 @@ photo.pixel_y = rand(-10, 10) toner -= 5 //AI prints color pictures only, thus they can do it more efficiently busy = TRUE - sleep(15) - busy = FALSE + addtimer(CALLBACK(src, .proc/reset_busy), 1.5 SECONDS) updateUsrDialog() else if(href_list["colortoggle"]) if(greytoggle == "Greyscale") @@ -189,9 +179,13 @@ greytoggle = "Greyscale" updateUsrDialog() +/obj/machinery/photocopier/proc/reset_busy() + busy = FALSE + updateUsrDialog() + /obj/machinery/photocopier/proc/do_insertion(obj/item/O, mob/user) O.forceMove(src) - to_chat(user, "You insert [O] into [src].") + to_chat(user, "You insert [O] into [src].") flick("photocopier1", src) updateUsrDialog() @@ -256,10 +250,10 @@ return ..() /obj/machinery/photocopier/obj_break(damage_flag) - if(!(flags_1 & NODECONSTRUCT_1)) - if(toner > 0) - new /obj/effect/decal/cleanable/oil(get_turf(src)) - toner = 0 + . = ..() + if(. && toner > 0) + new /obj/effect/decal/cleanable/oil(get_turf(src)) + toner = 0 /obj/machinery/photocopier/MouseDrop_T(mob/target, mob/user) check_ass() //Just to make sure that you can re-drag somebody onto it after they moved off. @@ -267,7 +261,7 @@ return src.add_fingerprint(user) if(target == user) - user.visible_message("[user] starts climbing onto the photocopier!", "You start climbing onto the photocopier...") + user.visible_message("[user] starts climbing onto the photocopier!", "You start climbing onto the photocopier...") else user.visible_message("[user] starts putting [target] onto the photocopier!", "You start putting [target] onto the photocopier...") @@ -276,7 +270,7 @@ return if(target == user) - user.visible_message("[user] climbs onto the photocopier!", "You climb onto the photocopier.") + user.visible_message("[user] climbs onto the photocopier!", "You climb onto the photocopier.") else user.visible_message("[user] puts [target] onto the photocopier!", "You put [target] onto the photocopier.") @@ -302,7 +296,7 @@ updateUsrDialog() return 0 else if(ishuman(ass)) - if(!ass.get_item_by_slot(SLOT_W_UNIFORM) && !ass.get_item_by_slot(SLOT_WEAR_SUIT)) + if(!ass.get_item_by_slot(ITEM_SLOT_ICLOTHING) && !ass.get_item_by_slot(ITEM_SLOT_OCLOTHING)) return 1 else return 0 diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm index 3e76fc874a..b925c67940 100644 --- a/code/modules/photography/camera/camera.dm +++ b/code/modules/photography/camera/camera.dm @@ -221,4 +221,4 @@ p.set_picture(picture, TRUE, TRUE) if(CONFIG_GET(flag/picture_logging_camera)) - picture.log_to_file() \ No newline at end of file + picture.log_to_file() diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm index 9e6f827629..d306c46815 100644 --- a/code/modules/photography/photos/frame.dm +++ b/code/modules/photography/photos/frame.dm @@ -21,8 +21,7 @@ to_chat(user, "\The [src] already contains a photo.") ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/wallframe/picture/attack_hand(mob/user) +/obj/item/wallframe/picture/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.get_inactive_held_item() != src) ..() return @@ -141,10 +140,7 @@ ..() -/obj/structure/sign/picture_frame/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/structure/sign/picture_frame/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(framed) framed.show(user) diff --git a/code/modules/photography/photos/photo.dm b/code/modules/photography/photos/photo.dm index 07f765c123..5c78709e9b 100644 --- a/code/modules/photography/photos/photo.dm +++ b/code/modules/photography/photos/photo.dm @@ -51,6 +51,8 @@ user.examinate(src) /obj/item/photo/attackby(obj/item/P, mob/user, params) + if(try_burn(P, user)) + return if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon)) if(!user.is_literate()) to_chat(user, "You scribble illegibly on [src]!") @@ -60,6 +62,26 @@ scribble = txt ..() +/obj/item/photo/proc/try_burn(obj/item/I, mob/living/user) + var/ignition_message = I.ignition_effect(src, user) + if(!ignition_message) + return + . = TRUE + if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10) && Adjacent(user)) + user.visible_message("[user] accidentally ignites [user.p_them()]self!", \ + "You miss [src] and accidentally light yourself on fire!") + if(user.is_holding(I)) //checking if they're holding it in case TK is involved + user.dropItemToGround(I) + user.adjust_fire_stacks(1) + user.IgniteMob() + return + + if(user.is_holding(src)) //no TK shit here. + user.dropItemToGround(src) + user.visible_message(ignition_message) + add_fingerprint(user) + fire_act(I.get_temperature()) + /obj/item/photo/examine(mob/user) . = ..() if(in_range(src, user)) diff --git a/code/modules/plumbing/ducts.dm b/code/modules/plumbing/ducts.dm new file mode 100644 index 0000000000..8a27f2669c --- /dev/null +++ b/code/modules/plumbing/ducts.dm @@ -0,0 +1,433 @@ +/* +All the important duct code: +/code/datums/components/plumbing/plumbing.dm +/code/datums/ductnet.dm +*/ +/obj/machinery/duct + name = "fluid duct" + icon = 'icons/obj/plumbing/fluid_ducts.dmi' + icon_state = "nduct" + + ///bitfield with the directions we're connected in + var/connects + ///set to TRUE to disable smart duct behaviour + var/dumb = FALSE + ///wheter we allow our connects to be changed after initialization or not + var/lock_connects = FALSE + ///our ductnet, wich tracks what we're connected to + var/datum/ductnet/duct + ///amount we can transfer per process. note that the ductnet can carry as much as the lowest capacity duct + var/capacity = 10 + + ///the color of our duct + var/duct_color = null + ///TRUE to ignore colors, so yeah we also connect with other colors without issue + var/ignore_colors = FALSE + ///1,2,4,8,16 + var/duct_layer = DUCT_LAYER_DEFAULT + ///whether we allow our layers to be altered + var/lock_layers = FALSE + ///TRUE to let colors connect when forced with a wrench, false to just not do that at all + var/color_to_color_support = TRUE + ///wheter to even bother with plumbing code or not + var/active = TRUE + ///track ducts we're connected to. Mainly for ducts we connect to that we normally wouldn't, like different layers and colors, for when we regenerate the ducts + var/list/neighbours = list() + ///wheter we just unanchored or drop whatever is in the variable. either is safe + var/drop_on_wrench = /obj/item/stack/ducts + +/obj/machinery/duct/Initialize(mapload, no_anchor, color_of_duct = "#ffffff", layer_of_duct = DUCT_LAYER_DEFAULT, force_connects) + . = ..() + + if(no_anchor) + active = FALSE + set_anchored(FALSE) + else if(!can_anchor()) + qdel(src) + CRASH("Overlapping ducts detected") + + if(force_connects) + connects = force_connects //skip change_connects() because we're still initializing and we need to set our connects at one point + if(!lock_layers) + duct_layer = layer_of_duct + if(!ignore_colors) + duct_color = color_of_duct + if(duct_color) + add_atom_colour(duct_color, FIXED_COLOUR_PRIORITY) + + handle_layer() + + for(var/obj/machinery/duct/D in loc) + if(D == src) + continue + if(D.duct_layer & duct_layer) + disconnect_duct() + + if(active) + attempt_connect() + + +///start looking around us for stuff to connect to +/obj/machinery/duct/proc/attempt_connect() + + for(var/atom/movable/AM in loc) + var/datum/component/plumbing/P = AM.GetComponent(/datum/component/plumbing) + if(P?.active) + disconnect_duct() //let's not built under plumbing machinery + return + for(var/D in GLOB.cardinals) + if(dumb && !(D & connects)) + continue + for(var/atom/movable/AM in get_step(src, D)) + if(connect_network(AM, D)) + add_connects(D) + update_icon() + +///see if whatever we found can be connected to +/obj/machinery/duct/proc/connect_network(atom/movable/AM, direction, ignore_color) + if(istype(AM, /obj/machinery/duct)) + return connect_duct(AM, direction, ignore_color) + + var/plumber = AM.GetComponent(/datum/component/plumbing) + if(!plumber) + return + return connect_plumber(plumber, direction) + +///connect to a duct +/obj/machinery/duct/proc/connect_duct(obj/machinery/duct/D, direction, ignore_color) + var/opposite_dir = turn(direction, 180) + if(!active || !D.active) + return + + if(!dumb && D.dumb && !(opposite_dir & D.connects)) + return + if(dumb && D.dumb && !(connects & D.connects)) //we eliminated a few more scenarios in attempt connect + return + + if((duct == D.duct) && duct)//check if we're not just comparing two null values + add_neighbour(D, direction) + + D.add_connects(opposite_dir) + D.update_icon() + return TRUE //tell the current pipe to also update it's sprite + if(!(D in neighbours)) //we cool + if((duct_color != D.duct_color) && !(ignore_colors || D.ignore_colors)) + return + if(!(duct_layer & D.duct_layer)) + return + + if(D.duct) + if(duct) + duct.assimilate(D.duct) + else + D.duct.add_duct(src) + else + if(duct) + duct.add_duct(D) + else + create_duct() + duct.add_duct(D) + add_neighbour(D, direction) + //tell our buddy its time to pass on the torch of connecting to pipes. This shouldn't ever infinitely loop since it only works on pipes that havent been inductrinated + D.attempt_connect() + + return TRUE + +///connect to a plumbing object +/obj/machinery/duct/proc/connect_plumber(datum/component/plumbing/P, direction) + var/opposite_dir = turn(direction, 180) + if(duct_layer != DUCT_LAYER_DEFAULT) //plumbing devices don't support multilayering. 3 is the default layer so we only use that. We can change this later + return FALSE + + if(!P.active) + return + + var/comp_directions = P.supply_connects + P.demand_connects //they should never, ever have supply and demand connects overlap or catastrophic failure + if(opposite_dir & comp_directions) + if(!duct) + create_duct() + if(duct.add_plumber(P, opposite_dir)) + neighbours[P.parent] = direction + return TRUE + +///we disconnect ourself from our neighbours. we also destroy our ductnet and tell our neighbours to make a new one +/obj/machinery/duct/proc/disconnect_duct(skipanchor) + if(!skipanchor) //since set_anchored calls us too. + set_anchored(FALSE) + active = FALSE + if(duct) + duct.remove_duct(src) + lose_neighbours() + reset_connects(0) + update_icon() + if(ispath(drop_on_wrench) && !QDELING(src)) + new drop_on_wrench(drop_location()) + qdel(src) + +///''''''''''''''''optimized''''''''''''''''' proc for quickly reconnecting after a duct net was destroyed +/obj/machinery/duct/proc/reconnect() + if(neighbours.len && !duct) + create_duct() + for(var/atom/movable/AM in neighbours) + if(istype(AM, /obj/machinery/duct)) + var/obj/machinery/duct/D = AM + if(D.duct) + if(D.duct == duct) //we're already connected + continue + else + duct.assimilate(D.duct) + continue + else + duct.add_duct(D) + D.reconnect() + else + var/datum/component/plumbing/P = AM.GetComponent(/datum/component/plumbing) + if(AM in get_step(src, neighbours[AM])) //did we move? + if(P) + connect_plumber(P, neighbours[AM]) + else + neighbours -= AM //we moved + +///Special proc to draw a new connect frame based on neighbours. not the norm so we can support multiple duct kinds +/obj/machinery/duct/proc/generate_connects() + if(lock_connects) + return + connects = 0 + for(var/A in neighbours) + connects |= neighbours[A] + update_icon() + +///create a new duct datum +/obj/machinery/duct/proc/create_duct() + duct = new() + duct.add_duct(src) + +///add a duct as neighbour. this means we're connected and will connect again if we ever regenerate +/obj/machinery/duct/proc/add_neighbour(obj/machinery/duct/D, direction) + if(!(D in neighbours)) + neighbours[D] = direction + if(!(src in D.neighbours)) + D.neighbours[src] = turn(direction, 180) + +///remove all our neighbours, and remove us from our neighbours aswell +/obj/machinery/duct/proc/lose_neighbours() + for(var/obj/machinery/duct/D in neighbours) + D.neighbours.Remove(src) + neighbours = list() + +///add a connect direction +/obj/machinery/duct/proc/add_connects(new_connects) //make this a define to cut proc calls? + if(!lock_connects) + connects |= new_connects + +///remove a connect direction +/obj/machinery/duct/proc/remove_connects(dead_connects) + if(!lock_connects) + connects &= ~dead_connects + +///remove our connects +/obj/machinery/duct/proc/reset_connects() + if(!lock_connects) + connects = 0 + +///get a list of the ducts we can connect to if we are dumb +/obj/machinery/duct/proc/get_adjacent_ducts() + var/list/adjacents = list() + for(var/A in GLOB.cardinals) + if(A & connects) + for(var/obj/machinery/duct/D in get_step(src, A)) + if((turn(A, 180) & D.connects) && D.active) + adjacents += D + return adjacents + +/obj/machinery/duct/update_icon_state() + var/temp_icon = initial(icon_state) + for(var/D in GLOB.cardinals) + if(D & connects) + if(D == NORTH) + temp_icon += "_n" + if(D == SOUTH) + temp_icon += "_s" + if(D == EAST) + temp_icon += "_e" + if(D == WEST) + temp_icon += "_w" + icon_state = temp_icon + +///update the layer we are on +/obj/machinery/duct/proc/handle_layer() + var/offset + switch(duct_layer)//it's a bitfield, but it's fine because it only works when there's one layer, and multiple layers should be handled differently + if(FIRST_DUCT_LAYER) + offset = -10 + if(SECOND_DUCT_LAYER) + offset = -5 + if(THIRD_DUCT_LAYER) + offset = 0 + if(FOURTH_DUCT_LAYER) + offset = 5 + if(FIFTH_DUCT_LAYER) + offset = 10 + pixel_x = offset + pixel_y = offset + + +/obj/machinery/duct/set_anchored(anchorvalue) + . = ..() + if(isnull(.)) + return + if(anchorvalue) + active = TRUE + attempt_connect() + else + disconnect_duct(TRUE) + +/obj/machinery/duct/wrench_act(mob/living/user, obj/item/I) //I can also be the RPD + ..() + add_fingerprint(user) + I.play_tool_sound(src) + if(anchored || can_anchor()) + set_anchored(!anchored) + user.visible_message( \ + "[user] [anchored ? null : "un"]fastens \the [src].", \ + "You [anchored ? null : "un"]fasten \the [src].", \ + "You hear ratcheting.") + return TRUE +///collection of all the sanity checks to prevent us from stacking ducts that shouldn't be stacked +/obj/machinery/duct/proc/can_anchor(turf/T) + if(!T) + T = get_turf(src) + for(var/obj/machinery/duct/D in T) + if(!anchored || D == src) + continue + for(var/A in GLOB.cardinals) + if(A & connects && A & D.connects) + return FALSE + return TRUE + +/obj/machinery/duct/doMove(destination) + . = ..() + disconnect_duct() + anchored = FALSE + +/obj/machinery/duct/Destroy() + disconnect_duct() + return ..() + +/obj/machinery/duct/MouseDrop_T(atom/A, mob/living/user) + if(!istype(A, /obj/machinery/duct)) + return + var/obj/machinery/duct/D = A + var/obj/item/I = user.get_active_held_item() + if(I?.tool_behaviour != TOOL_WRENCH) + to_chat(user, "You need to be holding a wrench in your active hand to do that!") + return + if(get_dist(src, D) != 1) + return + var/direction = get_dir(src, D) + if(!(direction in GLOB.cardinals)) + return + if(duct_layer != D.duct_layer) + return + + add_connects(direction) //the connect of the other duct is handled in connect_network, but do this here for the parent duct because it's not necessary in normal cases + add_neighbour(D, direction) + connect_network(D, direction, TRUE) + update_icon() + +///has a total of 5 layers and doesnt give a shit about color. its also dumb so doesnt autoconnect. +/obj/machinery/duct/multilayered + name = "duct layer-manifold" + icon = 'icons/obj/2x2.dmi' + icon_state = "multiduct" + pixel_x = -15 + pixel_y = -15 + + color_to_color_support = FALSE + duct_layer = FIRST_DUCT_LAYER | SECOND_DUCT_LAYER | THIRD_DUCT_LAYER | FOURTH_DUCT_LAYER | FIFTH_DUCT_LAYER + drop_on_wrench = null + + lock_connects = TRUE + lock_layers = TRUE + ignore_colors = TRUE + dumb = TRUE + + active = FALSE + anchored = FALSE + +/obj/machinery/duct/multilayered/Initialize(mapload, no_anchor, color_of_duct, layer_of_duct = DUCT_LAYER_DEFAULT, force_connects) + . = ..() + update_connects() + +/obj/machinery/duct/multilayered/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_blocker) + +/obj/machinery/duct/multilayered/wrench_act(mob/living/user, obj/item/I) + . = ..() + update_connects() + +/obj/machinery/duct/multilayered/proc/update_connects() + if(dir & NORTH || dir & SOUTH) + connects = NORTH | SOUTH + else + connects = EAST | WEST + +///don't connect to other multilayered stuff because honestly it shouldn't be done and I dont wanna deal with it +/obj/machinery/duct/multilayered/connect_duct(obj/machinery/duct/D, direction, ignore_color) + if(istype(D, /obj/machinery/duct/multilayered)) + return + return ..() + +/obj/machinery/duct/multilayered/handle_layer() + return + +/obj/item/stack/ducts + name = "stack of duct" + desc = "A stack of fluid ducts." + singular_name = "duct" + icon = 'icons/obj/plumbing/fluid_ducts.dmi' + icon_state = "ducts" + custom_materials = list(/datum/material/iron=500) + w_class = WEIGHT_CLASS_TINY + novariants = FALSE + max_amount = 50 + item_flags = NOBLUDGEON + merge_type = /obj/item/stack/ducts + ///Color of our duct + var/duct_color = "grey" + ///Default layer of our duct + var/duct_layer = "Default Layer" + ///Assoc index with all the available layers. yes five might be a bit much. Colors uses a global by the way + var/list/layers = list("First Layer" = FIRST_DUCT_LAYER, "Second Layer" = SECOND_DUCT_LAYER, "Default Layer" = DUCT_LAYER_DEFAULT, + "Fourth Layer" = FOURTH_DUCT_LAYER, "Fifth Layer" = FIFTH_DUCT_LAYER) + +/obj/item/stack/ducts/examine(mob/user) + . = ..() + . += "It's current color and layer are [duct_color] and [duct_layer]. Use in-hand to change." + +/obj/item/stack/ducts/attack_self(mob/user) + var/new_layer = input("Select a layer", "Layer") as null|anything in layers + if(new_layer) + duct_layer = new_layer + var/new_color = input("Select a color", "Color") as null|anything in GLOB.pipe_paint_colors + if(new_color) + duct_color = new_color + add_atom_colour(GLOB.pipe_paint_colors[new_color], FIXED_COLOUR_PRIORITY) + +/obj/item/stack/ducts/afterattack(atom/A, user, proximity) + . = ..() + if(!proximity) + return + if(istype(A, /obj/machinery/duct)) + var/obj/machinery/duct/D = A + if(!D.anchored) + add(1) + qdel(D) + if(istype(A, /turf/open) && use(1)) + var/turf/open/OT = A + new /obj/machinery/duct(OT, FALSE, GLOB.pipe_paint_colors[duct_color], layers[duct_layer]) + playsound(get_turf(src), 'sound/machines/click.ogg', 50, TRUE) + +/obj/item/stack/ducts/fifty + amount = 50 diff --git a/code/modules/plumbing/plumbers/_plumb_machinery.dm b/code/modules/plumbing/plumbers/_plumb_machinery.dm new file mode 100644 index 0000000000..0566945e3b --- /dev/null +++ b/code/modules/plumbing/plumbers/_plumb_machinery.dm @@ -0,0 +1,98 @@ +/**Basic plumbing object. +* It doesn't really hold anything special, YET. +* Objects that are plumbing but not a subtype are as of writing liquid pumps and the reagent_dispenser tank +* Also please note that the plumbing component is toggled on and off by the component using a signal from default_unfasten_wrench, so dont worry about it +*/ +/obj/machinery/plumbing + name = "pipe thing" + icon = 'icons/obj/plumbing/plumbers.dmi' + icon_state = "pump" + density = TRUE + active_power_usage = 30 + use_power = ACTIVE_POWER_USE + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF + ///Plumbing machinery is always gonna need reagents, so we might aswell put it here + var/buffer = 50 + ///Flags for reagents, like INJECTABLE, TRANSPARENT bla bla everything thats in DEFINES/reagents.dm + var/reagent_flags = TRANSPARENT + ///wheter we partake in rcd construction or not + var/rcd_constructable = TRUE + ///cost of the plumbing rcd construction + var/rcd_cost = 15 + ///delay of constructing it throught the plumbing rcd + var/rcd_delay = 10 + +/obj/machinery/plumbing/Initialize(mapload, bolt = TRUE) + . = ..() + anchored = bolt + create_reagents(buffer, reagent_flags) + AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated)) + +/obj/machinery/plumbing/proc/can_be_rotated(mob/user,rotation_type) + return TRUE + + +/obj/machinery/plumbing/examine(mob/user) + . = ..() + . += "The maximum volume display reads: [reagents.maximum_volume] units." + +/obj/machinery/plumbing/wrench_act(mob/living/user, obj/item/I) + ..() + default_unfasten_wrench(user, I) + return TRUE + +/obj/machinery/plumbing/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) + to_chat(user, "You start furiously plunging [name].") + if(do_after(user, 30, target = src)) + to_chat(user, "You finish plunging the [name].") + reagents.reaction(get_turf(src), TOUCH) //splash on the floor + reagents.clear_reagents() + +/obj/machinery/plumbing/welder_act(mob/living/user, obj/item/I) + . = ..() + if(anchored) + to_chat(user, "The [name] needs to be unbolted to do that!You start slicing the [name] apart.You slice the [name] apart. target_temperature && acclimate_state != COOLING) + acclimate_state = COOLING + update_icon() + if(!emptying) + if(reagents.chem_temp >= target_temperature && target_temperature + allowed_temperature_difference >= reagents.chem_temp) //cooling here + emptying = TRUE + if(reagents.chem_temp <= target_temperature && target_temperature - allowed_temperature_difference <= reagents.chem_temp) //heating here + emptying = TRUE + + reagents.adjust_thermal_energy((target_temperature - reagents.chem_temp) * heater_coefficient * SPECIFIC_HEAT_DEFAULT * reagents.total_volume) //keep constant with chem heater + reagents.handle_reactions() + +/obj/machinery/plumbing/acclimator/update_icon() + icon_state = initial(icon_state) + switch(acclimate_state) + if(COOLING) + icon_state += "_cold" + if(HEATING) + icon_state += "_hot" + +/obj/machinery/plumbing/acclimator/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemAcclimator", name) + ui.open() + +/obj/machinery/plumbing/acclimator/ui_data(mob/user) + var/list/data = list() + + data["enabled"] = enabled + data["chem_temp"] = reagents.chem_temp + data["target_temperature"] = target_temperature + data["allowed_temperature_difference"] = allowed_temperature_difference + data["acclimate_state"] = acclimate_state + data["max_volume"] = reagents.maximum_volume + data["reagent_volume"] = reagents.total_volume + data["emptying"] = emptying + return data + +/obj/machinery/plumbing/acclimator/ui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("set_target_temperature") + var/target = text2num(params["temperature"]) + target_temperature = clamp(target, 0, 1000) + if("set_allowed_temperature_difference") + var/target = text2num(params["temperature"]) + allowed_temperature_difference = clamp(target, 0, 1000) + if("toggle_power") + enabled = !enabled + if("change_volume") + var/target = text2num(params["volume"]) + reagents.maximum_volume = clamp(round(target), 1, buffer) + +#undef COOLING +#undef HEATING +#undef NEUTRAL diff --git a/code/modules/plumbing/plumbers/autohydro.dm b/code/modules/plumbing/plumbers/autohydro.dm new file mode 100644 index 0000000000..dbc70dfcf5 --- /dev/null +++ b/code/modules/plumbing/plumbers/autohydro.dm @@ -0,0 +1,65 @@ +/obj/machinery/hydroponics/constructable/automagic + name = "automated hydroponics system" + desc = "The bane of botanists everywhere. Accepts chemical reagents via plumbing, automatically harvests and removes dead plants." + obj_flags = CAN_BE_HIT | UNIQUE_RENAME + circuit = /obj/item/circuitboard/machine/hydroponics/automagic + self_sufficiency_req = 400 //automating hydroponics makes gaia sad so she needs more drugs to turn they tray godly. + canirrigate = FALSE + + +/obj/machinery/hydroponics/constructable/automagic/attackby(obj/item/O, mob/user, params) + if(istype(O, /obj/item/reagent_containers)) + return FALSE //avoid fucky wuckies + ..() + +/obj/machinery/hydroponics/constructable/automagic/default_unfasten_wrench(mob/user, obj/item/I, time = 20) + . = ..() + if(. == SUCCESSFUL_UNFASTEN) + user.visible_message("[user.name] [anchored ? "fasten" : "unfasten"] [src]", \ + "You [anchored ? "fasten" : "unfasten"] [src]") + var/datum/component/plumbing/CP = GetComponent(/datum/component/plumbing) + if(anchored) + CP.enable() + else + CP.disable() + +/obj/machinery/hydroponics/constructable/automagic/Destroy() + . = ..() + STOP_PROCESSING(SSobj, src) + +/obj/machinery/hydroponics/constructable/automagic/Initialize(mapload) + . = ..() + START_PROCESSING(SSobj, src) + create_reagents(100 , AMOUNT_VISIBLE) + +/obj/machinery/hydroponics/constructable/automagic/ComponentInitialize() + . = ..() + AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated)) + AddComponent(/datum/component/plumbing/simple_demand) + +/obj/machinery/hydroponics/constructable/proc/can_be_rotated(mob/user, rotation_type) + return !anchored + +/obj/machinery/hydroponics/constructable/automagic/process() + if(reagents) + applyChemicals(reagents) + reagents.clear_reagents() + if(dead) + dead = 0 + qdel(myseed) + myseed = null + update_icon() + name = initial(name) + desc = initial(desc) + if(harvest) + myseed.harvest_userless() + harvest = 0 + lastproduce = age + if(!myseed.get_gene(/datum/plant_gene/trait/repeated_harvest)) + qdel(myseed) + myseed = null + dead = 0 + name = initial(name) + desc = initial(desc) + update_icon() + ..() diff --git a/code/modules/plumbing/plumbers/bottler.dm b/code/modules/plumbing/plumbers/bottler.dm new file mode 100644 index 0000000000..396c7cac22 --- /dev/null +++ b/code/modules/plumbing/plumbers/bottler.dm @@ -0,0 +1,79 @@ +/obj/machinery/plumbing/bottler + name = "chemical bottler" + desc = "Puts reagents into containers, like bottles and beakers." + icon_state = "bottler" + layer = ABOVE_ALL_MOB_LAYER + reagent_flags = TRANSPARENT | DRAINABLE + rcd_cost = 50 + rcd_delay = 50 + buffer = 100 + ///how much do we fill + var/wanted_amount = 10 + ///where things are sent + var/turf/goodspot = null + ///where things are taken + var/turf/inputspot = null + ///where beakers that are already full will be sent + var/turf/badspot = null + +/obj/machinery/plumbing/bottler/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_demand, bolt) + setDir(dir) + +/obj/machinery/plumbing/bottler/can_be_rotated(mob/user, rotation_type) + if(anchored) + to_chat(user, "It is fastened to the floor!") + return FALSE + return TRUE + +///changes the tile array +/obj/machinery/plumbing/bottler/setDir(newdir) + . = ..() + switch(dir) + if(NORTH) + goodspot = get_step(get_turf(src), NORTH) + inputspot = get_step(get_turf(src), SOUTH) + badspot = get_step(get_turf(src), EAST) + if(SOUTH) + goodspot = get_step(get_turf(src), SOUTH) + inputspot = get_step(get_turf(src), NORTH) + badspot = get_step(get_turf(src), WEST) + if(WEST) + goodspot = get_step(get_turf(src), WEST) + inputspot = get_step(get_turf(src), EAST) + badspot = get_step(get_turf(src), NORTH) + if(EAST) + goodspot = get_step(get_turf(src), EAST) + inputspot = get_step(get_turf(src), WEST) + badspot = get_step(get_turf(src), SOUTH) + +///changing input ammount with a window +/obj/machinery/plumbing/bottler/interact(mob/user) + . = ..() + wanted_amount = clamp(round(input(user,"maximum is 100u","set ammount to fill with") as num|null, 1), 1, 100) + reagents.clear_reagents() + to_chat(user, " The [src] will now fill for [wanted_amount]u.") + +/obj/machinery/plumbing/bottler/process() + if(stat & NOPOWER) + return + ///see if machine has enough to fill + if(reagents.total_volume >= wanted_amount && anchored) + var/obj/AM = pick(inputspot.contents)///pick a reagent_container that could be used + if(istype(AM, /obj/item/reagent_containers) && (!istype(AM, /obj/item/reagent_containers/hypospray/medipen))) + var/obj/item/reagent_containers/B = AM + ///see if it would overflow else inject + if((B.reagents.total_volume + wanted_amount) <= B.reagents.maximum_volume) + reagents.trans_to(B, wanted_amount) + B.forceMove(goodspot) + return + ///glass was full so we move it away + AM.forceMove(badspot) + if(istype(AM, /obj/item/slime_extract)) ///slime extracts need inject + AM.forceMove(goodspot) + reagents.trans_to(AM, wanted_amount) + return + if(istype(AM, /obj/item/slimecross/industrial)) ///no need to move slimecross industrial things + reagents.trans_to(AM, wanted_amount) + return diff --git a/code/modules/plumbing/plumbers/destroyer.dm b/code/modules/plumbing/plumbers/destroyer.dm new file mode 100644 index 0000000000..b61383ea4a --- /dev/null +++ b/code/modules/plumbing/plumbers/destroyer.dm @@ -0,0 +1,21 @@ +/obj/machinery/plumbing/disposer + name = "chemical disposer" + desc = "Breaks down chemicals and annihilates them." + icon_state = "disposal" + ///we remove 10 reagents per second + var/disposal_rate = 10 + +/obj/machinery/plumbing/disposer/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_demand, bolt) + +/obj/machinery/plumbing/disposer/process() + if(stat & NOPOWER) + return + if(reagents.total_volume) + if(icon_state != initial(icon_state) + "_working") //threw it here instead of update icon since it only has two states + icon_state = initial(icon_state) + "_working" + reagents.remove_any(disposal_rate) + else + if(icon_state != initial(icon_state)) + icon_state = initial(icon_state) diff --git a/code/modules/plumbing/plumbers/fermenter.dm b/code/modules/plumbing/plumbers/fermenter.dm new file mode 100644 index 0000000000..b1e1e4b676 --- /dev/null +++ b/code/modules/plumbing/plumbers/fermenter.dm @@ -0,0 +1,59 @@ +/obj/machinery/plumbing/fermenter //FULLY AUTOMATIC BEER BREWING. TRULY, THE FUTURE. + name = "chemical fermenter" + desc = "Turns plants into various types of booze." + icon_state = "fermenter" + layer = ABOVE_ALL_MOB_LAYER + reagent_flags = TRANSPARENT | DRAINABLE + rcd_cost = 30 + rcd_delay = 30 + buffer = 400 + ///input dir + var/eat_dir = SOUTH + +/obj/machinery/plumbing/fermenter/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_supply, bolt) + +/obj/machinery/plumbing/fermenter/can_be_rotated(mob/user,rotation_type) + if(anchored) + to_chat(user, "It is fastened to the floor!") + return FALSE + switch(eat_dir) + if(WEST) + eat_dir = NORTH + return TRUE + if(EAST) + eat_dir = SOUTH + return TRUE + if(NORTH) + eat_dir = EAST + return TRUE + if(SOUTH) + eat_dir = WEST + return TRUE + +/obj/machinery/plumbing/fermenter/CanPass(atom/movable/AM) + . = ..() + if(!anchored) + return + var/move_dir = get_dir(loc, AM.loc) + if(move_dir == eat_dir) + return TRUE + +/obj/machinery/plumbing/fermenter/Crossed(atom/movable/AM) + . = ..() + ferment(AM) + +/obj/machinery/plumbing/fermenter/proc/ferment(atom/AM) + if(stat & NOPOWER) + return + if(reagents.holder_full()) + return + if(!isitem(AM)) + return + if(istype(AM, /obj/item/reagent_containers/food/snacks/grown)) + var/obj/item/reagent_containers/food/snacks/grown/G = AM + if(G.distill_reagent) + var/amount = G.seed.potency * 0.25 + reagents.add_reagent(G.distill_reagent, amount) + qdel(G) diff --git a/code/modules/plumbing/plumbers/filter.dm b/code/modules/plumbing/plumbers/filter.dm new file mode 100644 index 0000000000..1ffd170507 --- /dev/null +++ b/code/modules/plumbing/plumbers/filter.dm @@ -0,0 +1,65 @@ +///chemical plumbing filter. If it's not filtered by left and right, it goes straight. +/obj/machinery/plumbing/filter + name = "chemical filter" + desc = "A chemical filter for filtering chemicals. The left and right outputs appear to be from the perspective of the input port." + icon_state = "filter" + density = FALSE + + ///whitelist of chems id's that go to the left side. Empty to disable port + var/list/left = list() + ///whitelist of chem id's that go to the right side. Empty to disable port + var/list/right = list() + ///whitelist of chems but their name instead of path + var/list/english_left = list() + ///whitelist of chems but their name instead of path + var/list/english_right = list() + +/obj/machinery/plumbing/filter/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/filter, bolt) + +/obj/machinery/plumbing/filter/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemFilter", name) + ui.open() + +/obj/machinery/plumbing/filter/ui_data(mob/user) + var/list/data = list() + data["left"] = english_left + data["right"] = english_right + return data + +/obj/machinery/plumbing/filter/ui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("add") + var/new_chem_name = params["name"] + var/chem_id = get_chem_id(new_chem_name) + if(chem_id) + switch(params["which"]) + if("left") + if(!left.Find(chem_id)) + english_left += new_chem_name + left += chem_id + if("right") + if(!right.Find(chem_id)) + english_right += new_chem_name + right += chem_id + else + to_chat(usr, "No such known reagent exists!") + + if("remove") + var/chem_name = params["reagent"] + var/chem_id = get_chem_id(chem_name) + switch(params["which"]) + if("left") + if(english_left.Find(chem_name)) + english_left -= chem_name + left -= chem_id + if("right") + if(english_right.Find(chem_name)) + english_right -= chem_name + right -= chem_id diff --git a/code/modules/plumbing/plumbers/grinder_chemical.dm b/code/modules/plumbing/plumbers/grinder_chemical.dm new file mode 100644 index 0000000000..f39c79f906 --- /dev/null +++ b/code/modules/plumbing/plumbers/grinder_chemical.dm @@ -0,0 +1,64 @@ +/obj/machinery/plumbing/grinder_chemical + name = "chemical grinder" + desc = "chemical grinder." + icon_state = "grinder_chemical" + layer = ABOVE_ALL_MOB_LAYER + reagent_flags = TRANSPARENT | DRAINABLE + rcd_cost = 30 + rcd_delay = 30 + buffer = 400 + var/eat_dir = NORTH + +/obj/machinery/plumbing/grinder_chemical/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_supply, bolt) + +/obj/machinery/plumbing/grinder_chemical/can_be_rotated(mob/user,rotation_type) + if(anchored) + to_chat(user, "It is fastened to the floor!") + return FALSE + switch(eat_dir) + if(WEST) + eat_dir = NORTH + return TRUE + if(EAST) + eat_dir = SOUTH + return TRUE + if(NORTH) + eat_dir = EAST + return TRUE + if(SOUTH) + eat_dir = WEST + return TRUE + +/obj/machinery/plumbing/grinder_chemical/CanPass(atom/movable/AM) + . = ..() + if(!anchored) + return + var/move_dir = get_dir(loc, AM.loc) + if(move_dir == eat_dir) + return TRUE + +/obj/machinery/plumbing/grinder_chemical/Crossed(atom/movable/AM) + . = ..() + grind(AM) + +/obj/machinery/plumbing/grinder_chemical/proc/grind(atom/AM) + if(stat & NOPOWER) + return + if(reagents.holder_full()) + return + if(!isitem(AM)) + return + var/obj/item/I = AM + if(I.juice_results || I.grind_results) + if(I.juice_results) + I.on_juice() + reagents.add_reagent_list(I.juice_results) + if(I.reagents) + I.reagents.trans_to(src, I.reagents.total_volume) + qdel(I) + return + I.on_grind() + reagents.add_reagent_list(I.grind_results) + qdel(I) diff --git a/code/modules/plumbing/plumbers/medipenrefill.dm b/code/modules/plumbing/plumbers/medipenrefill.dm new file mode 100644 index 0000000000..fb7553a4d5 --- /dev/null +++ b/code/modules/plumbing/plumbers/medipenrefill.dm @@ -0,0 +1,94 @@ +/obj/machinery/medipen_refiller + name = "Medipen Refiller" + desc = "A machine that refills used medipens with chemicals." + icon = 'icons/obj/machines/medipen_refiller.dmi' + icon_state = "medipen_refiller" + density = TRUE + circuit = /obj/item/circuitboard/machine/medipen_refiller + idle_power_usage = 100 + /// list of medipen subtypes it can refill + var/list/allowed = list(/obj/item/reagent_containers/hypospray/medipen = /datum/reagent/medicine/epinephrine, + /obj/item/reagent_containers/hypospray/medipen/ekit = /datum/reagent/medicine/epinephrine, + /obj/item/reagent_containers/hypospray/medipen/firelocker = /datum/reagent/medicine/oxandrolone, + /obj/item/reagent_containers/hypospray/medipen/stimpack = /datum/reagent/medicine/ephedrine, + /obj/item/reagent_containers/hypospray/medipen/blood_loss = /datum/reagent/medicine/coagulant/weak) + /// var to prevent glitches in the animation + var/busy = FALSE + +/obj/machinery/medipen_refiller/Initialize() + . = ..() + create_reagents(100, TRANSPARENT) + for(var/obj/item/stock_parts/matter_bin/B in component_parts) + reagents.maximum_volume += 100 * B.rating + AddComponent(/datum/component/plumbing/simple_demand) + + +/obj/machinery/medipen_refiller/RefreshParts() + var/new_volume = 100 + for(var/obj/item/stock_parts/matter_bin/B in component_parts) + new_volume += 100 * B.rating + if(!reagents) + create_reagents(new_volume, TRANSPARENT) + reagents.maximum_volume = new_volume + return TRUE + +/// handles the messages and animation, calls refill to end the animation +/obj/machinery/medipen_refiller/attackby(obj/item/I, mob/user, params) + if(busy) + to_chat(user, "The machine is busy.") + return + if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) + var/obj/item/reagent_containers/RC = I + var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this) + if(units) + to_chat(user, "You transfer [units] units of the solution to the [name].") + return + else + to_chat(user, "The [name] is full.") + return + if(istype(I, /obj/item/reagent_containers/hypospray/medipen)) + var/obj/item/reagent_containers/hypospray/medipen/P = I + if(!(LAZYFIND(allowed, P.type))) + to_chat(user, "Error! Unknown schematics.") + return + if(P.reagents?.reagent_list.len) + to_chat(user, "The medipen is already filled.") + return + if(reagents.has_reagent(allowed[P.type], 10)) + busy = TRUE + add_overlay("active") + addtimer(CALLBACK(src, .proc/refill, P, user), 20) + qdel(P) + return + to_chat(user, "There aren't enough reagents to finish this operation.") + return + ..() + +/obj/machinery/medipen_refiller/plunger_act(obj/item/plunger/P, mob/living/user, reinforced) + to_chat(user, "You start furiously plunging [name].") + if(do_after(user, 30, target = src)) + to_chat(user, "You finish plunging the [name].") + reagents.clear_reagents() + +/obj/machinery/medipen_refiller/wrench_act(mob/living/user, obj/item/I) + ..() + default_unfasten_wrench(user, I) + return TRUE + +/obj/machinery/medipen_refiller/crowbar_act(mob/user, obj/item/I) + ..() + default_deconstruction_crowbar(I) + return TRUE + +/obj/machinery/medipen_refiller/screwdriver_act(mob/living/user, obj/item/I) + . = ..() + if(!.) + return default_deconstruction_screwdriver(user, "medipen_refiller_open", "medipen_refiller", I) + +/// refills the medipen +/obj/machinery/medipen_refiller/proc/refill(obj/item/reagent_containers/hypospray/medipen/P, mob/user) + new P.type(loc) + reagents.remove_reagent(allowed[P.type], 10) + cut_overlays() + busy = FALSE + to_chat(user, "Medipen refilled.") diff --git a/code/modules/plumbing/plumbers/pill_press.dm b/code/modules/plumbing/plumbers/pill_press.dm new file mode 100644 index 0000000000..56510fac87 --- /dev/null +++ b/code/modules/plumbing/plumbers/pill_press.dm @@ -0,0 +1,127 @@ +///We take a constant input of reagents, and produce a pill once a set volume is reached +/obj/machinery/plumbing/pill_press + name = "chemical press" + desc = "A press that makes pills, patches and bottles." + icon_state = "pill_press" + ///maximum size of a pill + var/max_pill_volume = 50 + ///maximum size of a patch + var/max_patch_volume = 40 + ///maximum size of a bottle + var/max_bottle_volume = 30 + ///current operating product (pills or patches) + var/product = "pill" + ///the minimum size a pill or patch can be + var/min_volume = 5 + ///the maximum size a pill or patch can be + var/max_volume = 50 + ///selected size of the product + var/current_volume = 10 + ///prefix for the product name + var/product_name = "factory" + ///the icon_state number for the pill. + var/pill_number = RANDOM_PILL_STYLE + ///list of id's and icons for the pill selection of the ui + var/list/pill_styles + ///list of products stored in the machine, so we dont have 610 pills on one tile + var/list/stored_products = list() + ///max amount of pills allowed on our tile before we start storing them instead + var/max_floor_products = 50 //haha massive pill piles + +/obj/machinery/plumbing/pill_press/examine(mob/user) + . = ..() + . += "The [name] currently has [stored_products.len] stored. There needs to be less than [max_floor_products ] on the floor to continue dispensing." + +/obj/machinery/plumbing/pill_press/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_demand, bolt) + + //expertly copypasted from chemmasters + var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills) + pill_styles = list() + for (var/x in 1 to PILL_STYLE_COUNT) + var/list/SL = list() + SL["id"] = x + SL["htmltag"] = assets.icon_tag("pill[x]") + pill_styles += list(SL) + + +/obj/machinery/plumbing/pill_press/process() + if(stat & NOPOWER) + return + if(reagents.total_volume >= current_volume) + if (product == "pill") + var/obj/item/reagent_containers/pill/P = new(src) + reagents.trans_to(P, current_volume) + P.name = trim("[product_name] pill") + stored_products += P + if(pill_number == RANDOM_PILL_STYLE) + P.icon_state = "pill[rand(1,21)]" + else + P.icon_state = "pill[pill_number]" + if(P.icon_state == "pill4") //mirrored from chem masters + P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality." + else if (product == "patch") + var/obj/item/reagent_containers/pill/patch/P = new(src) + reagents.trans_to(P, current_volume) + P.name = trim("[product_name] patch") + stored_products += P + else if (product == "bottle") + var/obj/item/reagent_containers/glass/bottle/P = new(src) + reagents.trans_to(P, current_volume) + P.name = trim("[product_name] bottle") + stored_products += P + if(stored_products.len) + var/pill_amount = 0 + for(var/obj/item/reagent_containers/pill/P in loc) + pill_amount++ + if(pill_amount >= max_floor_products) //too much so just stop + break + if(pill_amount < max_floor_products) + var/atom/movable/AM = stored_products[1] //AM because forceMove is all we need + stored_products -= AM + AM.forceMove(drop_location()) + + +/obj/machinery/plumbing/pill_press/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/simple/pills), + ) + +/obj/machinery/plumbing/pill_press/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemPress", name) + ui.open() + +/obj/machinery/plumbing/pill_press/ui_data(mob/user) + var/list/data = list() + data["pill_style"] = pill_number + data["current_volume"] = current_volume + data["product_name"] = product_name + data["pill_styles"] = pill_styles + data["product"] = product + data["min_volume"] = min_volume + data["max_volume"] = max_volume + return data + +/obj/machinery/plumbing/pill_press/ui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("change_pill_style") + pill_number = clamp(text2num(params["id"]), 1 , PILL_STYLE_COUNT) + if("change_current_volume") + current_volume = clamp(text2num(params["volume"]), min_volume, max_volume) + if("change_product_name") + product_name = html_encode(params["name"]) + if("change_product") + product = params["product"] + if (product == "pill") + max_volume = max_pill_volume + else if (product == "patch") + max_volume = max_patch_volume + else if (product == "bottle") + max_volume = max_bottle_volume + current_volume = clamp(current_volume, min_volume, max_volume) diff --git a/code/modules/plumbing/plumbers/pumps.dm b/code/modules/plumbing/plumbers/pumps.dm new file mode 100644 index 0000000000..c24e48098d --- /dev/null +++ b/code/modules/plumbing/plumbers/pumps.dm @@ -0,0 +1,64 @@ +///We pump liquids from activated(plungerated) geysers to a plumbing outlet. We don't need to be wired. +/obj/machinery/plumbing/liquid_pump + name = "liquid pump" + desc = "Pump up those sweet liquids from under the surface. Uses thermal energy from geysers to power itself." //better than placing 200 cables, because it wasnt fun + icon = 'icons/obj/plumbing/plumbers.dmi' + icon_state = "pump" + anchored = FALSE + density = TRUE + idle_power_usage = 10 + active_power_usage = 1000 + + rcd_cost = 30 + rcd_delay = 40 + + ///units we pump per process (2 seconds) + var/pump_power = 2 + ///set to true if the loop couldnt find a geyser in process, so it remembers and stops checking every loop until moved. more accurate name would be absolutely_no_geyser_under_me_so_dont_try + var/geyserless = FALSE + ///The geyser object + var/obj/structure/geyser/geyser + ///volume of our internal buffer + var/volume = 200 + +/obj/machinery/plumbing/liquid_pump/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_supply, bolt) + +///please note that the component has a hook in the parent call, wich handles activating and deactivating +/obj/machinery/plumbing/liquid_pump/default_unfasten_wrench(mob/user, obj/item/I, time = 20) + . = ..() + if(. == SUCCESSFUL_UNFASTEN) + geyser = null + update_icon() + geyserless = FALSE //we switched state, so lets just set this back aswell + +/obj/machinery/plumbing/liquid_pump/process() + if(!anchored || panel_open || geyserless) + return + + if(!geyser) + for(var/obj/structure/geyser/G in loc.contents) + geyser = G + update_icon() + if(!geyser) //we didnt find one, abort + geyserless = TRUE + visible_message("The [name] makes a sad beep!") + playsound(src, 'sound/machines/buzz-sigh.ogg', 50) + return + + pump() + +///pump up that sweet geyser nectar +/obj/machinery/plumbing/liquid_pump/proc/pump() + if(!geyser || !geyser.reagents) + return + geyser.reagents.trans_to(src, pump_power) + +/obj/machinery/plumbing/liquid_pump/update_icon_state() + if(geyser) + icon_state = initial(icon_state) + "-on" + else if(panel_open) + icon_state = initial(icon_state) + "-open" + else + icon_state = initial(icon_state) diff --git a/code/modules/plumbing/plumbers/reaction_chamber.dm b/code/modules/plumbing/plumbers/reaction_chamber.dm new file mode 100644 index 0000000000..949543c300 --- /dev/null +++ b/code/modules/plumbing/plumbers/reaction_chamber.dm @@ -0,0 +1,63 @@ +///a reaction chamber for plumbing. pretty much everything can react, but this one keeps the reagents seperated and only reacts under your given terms +/obj/machinery/plumbing/reaction_chamber + name = "reaction chamber" + desc = "Keeps chemicals seperated until given conditions are met." + icon_state = "reaction_chamber" + buffer = 200 + reagent_flags = TRANSPARENT | NO_REACT + + /**list of set reagents that the reaction_chamber allows in, and must all be present before mixing is enabled. + * example: list(/datum/reagent/water = 20, /datum/reagent/fuel/oil = 50) + */ + var/list/required_reagents = list() + ///our reagent goal has been reached, so now we lock our inputs and start emptying + var/emptying = FALSE + +/obj/machinery/plumbing/reaction_chamber/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/reaction_chamber, bolt) + +/obj/machinery/plumbing/reaction_chamber/on_reagent_change() + if(reagents.total_volume == 0 && emptying) //we were emptying, but now we aren't + emptying = FALSE + reagent_flags |= NO_REACT + +/obj/machinery/plumbing/reaction_chamber/power_change() + . = ..() + if(use_power != NO_POWER_USE) + icon_state = initial(icon_state) + "_on" + else + icon_state = initial(icon_state) + +/obj/machinery/plumbing/reaction_chamber/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemReactionChamber", name) + ui.open() + +/obj/machinery/plumbing/reaction_chamber/ui_data(mob/user) + var/list/data = list() + var/list/text_reagents = list() + for(var/A in required_reagents) //make a list where the key is text, because that looks alot better in the ui than a typepath + var/datum/reagent/R = A + text_reagents[initial(R.name)] = required_reagents[R] + + data["reagents"] = text_reagents + data["emptying"] = emptying + return data + +/obj/machinery/plumbing/reaction_chamber/ui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("remove") + var/reagent = get_chem_id(params["chem"]) + if(reagent) + required_reagents.Remove(reagent) + if("add") + var/input_reagent = get_chem_id(params["chem"]) + if(input_reagent && !required_reagents.Find(input_reagent)) + var/input_amount = text2num(params["amount"]) + if(input_amount) + required_reagents[input_reagent] = input_amount diff --git a/code/modules/plumbing/plumbers/splitters.dm b/code/modules/plumbing/plumbers/splitters.dm new file mode 100644 index 0000000000..a26813486c --- /dev/null +++ b/code/modules/plumbing/plumbers/splitters.dm @@ -0,0 +1,50 @@ +///it splits the reagents however you want. So you can "every 60 units, 45 goes left and 15 goes straight". The side direction is EAST, you can change this in the component +/obj/machinery/plumbing/splitter + name = "Chemical Splitter" + desc = "A chemical splitter for smart chemical factorization. Waits till a set of conditions is met and then stops all input and splits the buffer evenly or other in two ducts." + icon_state = "splitter" + buffer = 100 + density = FALSE + + ///constantly switches between TRUE and FALSE. TRUE means the batch tick goes straight, FALSE means the next batch goes in the side duct. + var/turn_straight = TRUE + ///how much we must transfer straight. note input can be as high as 10 reagents per process, usually + var/transfer_straight = 5 + ///how much we must transfer to the side + var/transfer_side = 5 + //the maximum you can set the transfer to + var/max_transfer = 9 + + +/obj/machinery/plumbing/splitter/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/splitter, bolt) + +/obj/machinery/plumbing/splitter/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemSplitter", name) + ui.open() + +/obj/machinery/plumbing/splitter/ui_data(mob/user) + var/list/data = list() + data["straight"] = transfer_straight + data["side"] = transfer_side + data["max_transfer"] = max_transfer + return data + +/obj/machinery/plumbing/splitter/ui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("set_amount") + var/direction = params["target"] + var/value = clamp(text2num(params["amount"]), 1, max_transfer) + switch(direction) + if("straight") + transfer_straight = value + if("side") + transfer_side = value + else + return FALSE diff --git a/code/modules/plumbing/plumbers/synthesizer.dm b/code/modules/plumbing/plumbers/synthesizer.dm new file mode 100644 index 0000000000..c2bc3439ff --- /dev/null +++ b/code/modules/plumbing/plumbers/synthesizer.dm @@ -0,0 +1,111 @@ +///A single machine that produces a single chem. Can be placed in unison with others through plumbing to create chemical factories +/obj/machinery/plumbing/synthesizer + name = "chemical synthesizer" + desc = "Produces a single chemical at a given volume. Must be plumbed. Most effective when working in unison with other chemical synthesizers, heaters and filters." + + icon_state = "synthesizer" + icon = 'icons/obj/plumbing/plumbers.dmi' + rcd_cost = 25 + rcd_delay = 15 + + ///Amount we produce for every process. Ideally keep under 5 since thats currently the standard duct capacity + var/amount = 1 + ///The maximum we can produce for every process + buffer = 5 + ///I track them here because I have no idea how I'd make tgui loop like that + var/static/list/possible_amounts = list(0,1,2,3,4,5) + ///The reagent we are producing. We are a typepath, but are also typecast because there's several occations where we need to use initial. + var/datum/reagent/reagent_id = null + ///straight up copied from chem dispenser. Being a subtype would be extremely tedious and making it global would restrict potential subtypes using different dispensable_reagents + var/list/dispensable_reagents = list( + /datum/reagent/aluminium, + /datum/reagent/bromine, + /datum/reagent/carbon, + /datum/reagent/chlorine, + /datum/reagent/copper, + /datum/reagent/consumable/ethanol, + /datum/reagent/fluorine, + /datum/reagent/hydrogen, + /datum/reagent/iodine, + /datum/reagent/iron, + /datum/reagent/lithium, + /datum/reagent/mercury, + /datum/reagent/nitrogen, + /datum/reagent/oxygen, + /datum/reagent/phosphorus, + /datum/reagent/potassium, + /datum/reagent/radium, + /datum/reagent/silicon, + /datum/reagent/silver, + /datum/reagent/sodium, + /datum/reagent/stable_plasma, + /datum/reagent/consumable/sugar, + /datum/reagent/sulfur, + /datum/reagent/toxin/acid, + /datum/reagent/water, + /datum/reagent/fuel, + ) + +/obj/machinery/plumbing/synthesizer/Initialize(mapload, bolt) + . = ..() + AddComponent(/datum/component/plumbing/simple_supply, bolt) + +/obj/machinery/plumbing/synthesizer/process() + if(stat & NOPOWER || !reagent_id || !amount) + return + if(reagents.total_volume >= amount) //otherwise we get leftovers, and we need this to be precise + return + reagents.add_reagent(reagent_id, amount) + +/obj/machinery/plumbing/synthesizer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemSynthesizer", name) + ui.open() + +/obj/machinery/plumbing/synthesizer/ui_data(mob/user) + var/list/data = list() + + var/is_hallucinating = user.hallucinating() + var/list/chemicals = list() + + for(var/A in dispensable_reagents) + var/datum/reagent/R = GLOB.chemical_reagents_list[A] + if(R) + var/chemname = R.name + if(is_hallucinating && prob(5)) + chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" + chemicals.Add(list(list("title" = chemname, "id" = ckey(R.name)))) + data["chemicals"] = chemicals + data["amount"] = amount + data["possible_amounts"] = possible_amounts + + data["current_reagent"] = ckey(initial(reagent_id.name)) + return data + +/obj/machinery/plumbing/synthesizer/ui_act(action, params) + if(..()) + return + . = TRUE + switch(action) + if("amount") + var/new_amount = text2num(params["target"]) + if(new_amount in possible_amounts) + amount = new_amount + . = TRUE + if("select") + var/new_reagent = GLOB.name2reagent[params["reagent"]] + if(new_reagent in dispensable_reagents) + reagent_id = new_reagent + . = TRUE + update_icon() + reagents.clear_reagents() + +/obj/machinery/plumbing/synthesizer/update_overlays() + . = ..() + var/mutable_appearance/r_overlay = mutable_appearance(icon, "[icon_state]_overlay") + if(reagent_id) + r_overlay.color = initial(reagent_id.color) + else + r_overlay.color = "#FFFFFF" + . += r_overlay diff --git a/code/modules/pool/pool_drain.dm b/code/modules/pool/pool_drain.dm index 940f7cd219..527c25b9f0 100644 --- a/code/modules/pool/pool_drain.dm +++ b/code/modules/pool/pool_drain.dm @@ -154,7 +154,7 @@ else new /mob/living/simple_animal/hostile/shark/laser(loc) -/obj/machinery/pool/filter/attack_hand(mob/user) +/obj/machinery/pool/filter/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) to_chat(user, "You search the filter.") for(var/obj/O in contents) O.forceMove(loc) diff --git a/code/modules/pool/pool_main.dm b/code/modules/pool/pool_main.dm index b45c0f36a2..98189cc8a4 100644 --- a/code/modules/pool/pool_main.dm +++ b/code/modules/pool/pool_main.dm @@ -177,7 +177,7 @@ else return ..() -/turf/open/pool/attack_hand(mob/living/user) +/turf/open/pool/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/pool/pool_structures.dm b/code/modules/pool/pool_structures.dm index 4cea485237..ec5d455958 100644 --- a/code/modules/pool/pool_structures.dm +++ b/code/modules/pool/pool_structures.dm @@ -11,7 +11,7 @@ layer = ABOVE_MOB_LAYER dir = EAST -/obj/structure/pool/ladder/attack_hand(mob/living/user) +/obj/structure/pool/ladder/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return @@ -52,7 +52,7 @@ user.pixel_x = initial_px user.pixel_y = initial_py -/obj/structure/pool/Lboard/attack_hand(mob/living/user) +/obj/structure/pool/Lboard/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) var/mob/living/carbon/jumper = user if(jumping) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 6772fe3cf1..2480288484 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -38,6 +38,8 @@ #define APC_CHARGING 1 #define APC_FULLY_CHARGED 2 +#define MAXIMUM_COG_REGAIN 100 //How much charge drained by an integration cog can be priority-recharged in one processing-tick + // the Area Power Controller (APC), formerly Power Distribution Unit (PDU) // one per area, needs wire connection to power network through a terminal @@ -94,6 +96,7 @@ var/mob/living/silicon/ai/occupier = null var/transfer_in_progress = FALSE //Is there an AI being transferred out of us? var/obj/item/clockwork/integration_cog/integration_cog //Is there a cog siphoning power? + var/cog_drained = 0 //How much of the cell's charge was drained by an integration cog, recovering this amount takes priority over the normal APC cell recharge calculations, but comes after powering Essentials. var/longtermpower = 10 var/auto_name = 0 var/failure_timer = 0 @@ -499,6 +502,7 @@ cell.forceMove(T) cell.update_icon() cell = null + cog_drained = 0 //No more cell means no more averting celldrain charging = APC_NOT_CHARGING update_icon() return @@ -701,7 +705,7 @@ START_PROCESSING(SSfastprocess, W) playsound(src, 'sound/machines/clockcult/steam_whoosh.ogg', 50, FALSE) opened = APC_COVER_CLOSED - locked = FALSE + locked = TRUE //Clockies get full APC access on cogged APCs, but they can't lock or unlock em unless they steal some ID to give all of them APC access, soo this is pretty much just QoL for them and makes cogs a tiny bit more stealthy update_icon() return else if(panel_open && !opened && is_wire_tool(W)) @@ -833,10 +837,47 @@ // attack with hand - remove cell (if cover open) or interact with the APC -/obj/machinery/power/apc/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/power/apc/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) + if(isethereal(user)) + var/mob/living/carbon/human/H = user + if(H.a_intent == INTENT_HARM) + if(cell.charge <= (cell.maxcharge / 2)) // if charge is under 50% you shouldnt drain it + to_chat(H, "The APC doesn't have much power, you probably shouldn't drain any.") + return + var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH) + if(stomach.crystal_charge > 145) + to_chat(H, "Your charge is full!") + return + to_chat(H, "You start channeling some power through the APC into your body.") + if(do_after(user, 75, target = src)) + if(cell.charge <= (cell.maxcharge / 2) || (stomach.crystal_charge > 145)) + return + if(istype(stomach)) + to_chat(H, "You receive some charge from the APC.") + stomach.adjust_charge(10) + cell.charge -= 10 + else + to_chat(H, "You can't receive charge from the APC!") + return + if(H.a_intent == INTENT_GRAB) + if(cell.charge == cell.maxcharge) + to_chat(H, "The APC is full!") + return + var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH) + if(stomach.crystal_charge < 10) + to_chat(H, "Your charge is too low!") + return + to_chat(H, "You start channeling power through your body into the APC.") + if(do_after(user, 75, target = src)) + if(cell.charge == cell.maxcharge || (stomach.crystal_charge < 10)) + return + if(istype(stomach)) + to_chat(H, "You transfer some power to the APC.") + stomach.adjust_charge(-10) + cell.charge += 10 + else + to_chat(H, "You can't transfer power to the APC!") + return if(opened && (!issilicon(user))) if(cell) user.visible_message("[user] removes \the [cell] from [src]!","You remove \the [cell].") @@ -849,31 +890,19 @@ if((stat & MAINT) && !opened) //no board; no interface return -/obj/machinery/power/apc/oui_canview(mob/user) - if(area.hasSiliconAccessInArea(user)) //some APCs are mapped outside their assigned area, so this is required. - return TRUE - return ..() - -/obj/machinery/power/apc/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - +/obj/machinery/power/apc/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "apc", name, 450, 460, master_ui, state) + ui = new(user, src, "Apc", name) ui.open() /obj/machinery/power/apc/ui_data(mob/user) - var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack) - var/abilitiesavail = FALSE - if (H && !H.stealthmode && H.toggled) - abilitiesavail = TRUE var/list/data = list( - "locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE), - "lock_nightshift" = nightshift_requires_auth, + "locked" = locked, "failTime" = failure_timer, "isOperating" = operating, "externalPower" = main_status, - "powerCellStatus" = (cell?.percent() || null), + "powerCellStatus" = cell ? cell.percent() : null, "chargeMode" = chargemode, "chargingStatus" = charging, "totalLoad" = DisplayPower(lastused_total), @@ -882,10 +911,7 @@ "malfStatus" = get_malf_status(user), "emergencyLights" = !emergency_lights, "nightshiftLights" = nightshift_lights, - "hijackable" = HAS_TRAIT(user,TRAIT_HIJACKER), - "hijacker" = hijacker == user ? TRUE : FALSE, - "drainavail" = cell && cell.percent() >= 85 && abilitiesavail, - "lockdownavail" = cell && cell.percent() >= 35 && abilitiesavail, + "powerChannels" = list( list( "title" = "Equipment", @@ -940,6 +966,9 @@ return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])" /obj/machinery/power/apc/proc/update() + var/old_light = area.power_light + var/old_equip = area.power_equip + var/old_environ = area.power_environ if(operating && !shorted && !failure_timer) area.power_light = (lighting > 1) area.power_equip = (equipment > 1) @@ -948,7 +977,8 @@ area.power_light = FALSE area.power_equip = FALSE area.power_environ = FALSE - area.power_change() + if(old_light != area.power_light || old_equip != area.power_equip || old_environ != area.power_environ) + area.power_change() /obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic() if(IsAdminGhost(user)) @@ -979,43 +1009,32 @@ . = UI_INTERACTIVE /obj/machinery/power/apc/ui_act(action, params) - if(..() || !can_use(usr, 1)) - return - if(failure_timer) - if(action == "reboot") - failure_timer = 0 - update_icon() - update() - if (action == "hijack" && can_use(usr, 1)) //don't need auth for hijack button - hijack(usr) - return - var/authorized = (!locked || area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) || (integration_cog && (is_servant_of_ratvar(usr)))) - if((action == "toggle_nightshift") && (!nightshift_requires_auth || authorized)) - toggle_nightshift_lights() - return TRUE - if(!authorized) + if(..() || !can_use(usr, 1) || (locked && !area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE) && !failure_timer && action != "toggle_nightshift" && (!integration_cog || !(is_servant_of_ratvar(usr))))) return switch(action) if("lock") if(area.hasSiliconAccessInArea(usr)) if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT))) - to_chat(usr, "The APC does not respond to the command.") + to_chat(usr, "The APC does not respond to the command!") else locked = !locked update_icon() - return TRUE + . = TRUE if("cover") coverlocked = !coverlocked - return TRUE + . = TRUE if("breaker") - toggle_breaker() - return TRUE + toggle_breaker(usr) + . = TRUE + if("toggle_nightshift") + toggle_nightshift_lights() + . = TRUE if("charge") chargemode = !chargemode if(!chargemode) charging = APC_NOT_CHARGING update_icon() - return TRUE + . = TRUE if("channel") if(params["eqp"]) equipment = setsubsystem(text2num(params["eqp"])) @@ -1029,23 +1048,24 @@ environ = setsubsystem(text2num(params["env"])) update_icon() update() - return TRUE + . = TRUE if("overload") - if(area.hasSiliconAccessInArea(usr)) + if(area.hasSiliconAccessInArea(usr, PRIVILEDGES_SILICON|PRIVILEDGES_DRONE)) //usr.has_unlimited_silicon_privilege) overload_lighting() - return TRUE + . = TRUE if("hack") if(get_malf_status(usr)) malfhack(usr) - return TRUE if("occupy") if(get_malf_status(usr)) malfoccupy(usr) - return TRUE if("deoccupy") if(get_malf_status(usr)) malfvacate() - return TRUE + if("reboot") + failure_timer = 0 + update_icon() + update() if("emergency_lighting") emergency_lights = !emergency_lights for(var/obj/machinery/light/L in area) @@ -1053,31 +1073,14 @@ L.no_emergency = emergency_lights INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) CHECK_TICK - if("drain") - cell.use(cell.charge) - hijacker.toggleSiliconAccessArea(area) - hijacker = null - set_hijacked_lighting() - update_icon() - var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack) - H.stealthcooldown = world.time + 2 MINUTES - energy_fail(30 SECONDS * (cell.charge / cell.maxcharge)) - if("lockdown") - var/celluse = rand(20,35) - celluse = celluse /100 - for (var/obj/machinery/door/D in GLOB.airlocks) - if (get_area(D) == area) - INVOKE_ASYNC(D,/obj/machinery/door.proc/hostile_lockdown,usr, FALSE) - addtimer(CALLBACK(D,/obj/machinery/door.proc/disable_lockdown, FALSE), 30 SECONDS) - cell.charge -= cell.maxcharge*celluse - var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack) - H.stealthcooldown = world.time + 3 MINUTES return TRUE -/obj/machinery/power/apc/proc/toggle_breaker() +/obj/machinery/power/apc/proc/toggle_breaker(mob/user) if(!is_operational() || failure_timer) return operating = !operating + add_hiddenprint(user) //delete when runtime + log_game("[key_name(user)] turned [operating ? "on" : "off"] the [src] in [AREACOORD(src)]") update() update_icon() @@ -1122,6 +1125,10 @@ if(malf.malfhacking) to_chat(malf, "You are already hacking an APC.") return + var/area/ourarea = get_area(src) + if(!ourarea.valid_malf_hack) + to_chat(malf, "This APC is not well connected enough to the Exonet to provide any useful processing capabilities.") + return to_chat(malf, "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process.") malf.malfhack = src malf.malfhacking = addtimer(CALLBACK(malf, /mob/living/silicon/ai/.proc/malfhacked, src), 600, TIMER_STOPPABLE) @@ -1141,6 +1148,7 @@ return if(!is_station_level(z)) return + malf.ShutOffDoomsdayDevice() occupier = new /mob/living/silicon/ai(src, malf.laws, malf) //DEAR GOD WHY? //IKR???? occupier.adjustOxyLoss(malf.getOxyLoss()) if(!findtext(occupier.name, "APC Copy")) @@ -1314,6 +1322,11 @@ cur_used -= lastused_light lighting_satisfied = TRUE + //If drained by an integration cog: Forcefully avert as much of the powerdrain as possible, though a maximum of MAXIMUM_COG_REGAIN + if(cur_excess && cog_drained && cell) + var/cog_regain = cell.give(min(min(cog_drained, cur_excess), MAXIMUM_COG_REGAIN)) + cur_excess -= cog_regain + cog_drained = max(0, cog_drained - cog_regain) // next: take from or charge to the cell, depending on how much is left if(cell && !shorted) @@ -1576,6 +1589,8 @@ #undef APC_UPOVERLAY_LOCKED #undef APC_UPOVERLAY_OPERATING +#undef MAXIMUM_COG_REGAIN + /*Power module, used for APC construction*/ /obj/item/electronics/apc name = "power control module" diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index d73f18c32f..3f1e688120 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -171,8 +171,8 @@ By design, d1 is the smallest direction and d2 is the highest return coil.cable_join(src, user) - else if(istype(W, /obj/item/twohanded/rcl)) - var/obj/item/twohanded/rcl/R = W + else if(istype(W, /obj/item/rcl)) + var/obj/item/rcl/R = W if(R.loaded) R.loaded.cable_join(src, user) R.is_empty(user) @@ -569,10 +569,7 @@ By design, d1 is the smallest direction and d2 is the highest icon_state = "[initial(item_state)][amount < 3 ? amount : ""]" name = "cable [amount < 3 ? "piece" : "coil"]" -/obj/item/stack/cable_coil/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/item/stack/cable_coil/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/obj/item/stack/cable_coil/new_cable = ..() if(istype(new_cable)) new_cable.color = color diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm index 0aeda5c949..e9ffc28a98 100644 --- a/code/modules/power/cell.dm +++ b/code/modules/power/cell.dm @@ -45,7 +45,7 @@ /obj/item/stock_parts/cell/vv_edit_var(var_name, var_value) switch(var_name) - if("self_recharge") + if(NAMEOF(src, self_recharge)) if(var_value) START_PROCESSING(SSobj, src) else @@ -151,6 +151,27 @@ if(prob(25)) corrupt() +/obj/item/stock_parts/cell/attack_self(mob/user) + if(isethereal(user)) + var/mob/living/carbon/human/H = user + if(charge < 100) + to_chat(H, "The [src] doesn't have enough power!") + return + var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH) + if(stomach.crystal_charge > 146) + to_chat(H, "Your charge is full!") + return + to_chat(H, "You clumsily channel power through the [src] and into your body, wasting some in the process.") + if(do_after(user, 5, target = src)) + if((charge < 100) || (stomach.crystal_charge > 146)) + return + if(istype(stomach)) + to_chat(H, "You receive some charge from the [src].") + stomach.adjust_charge(3) + charge -= 100 //you waste way more than you receive, so that ethereals cant just steal one cell and forget about hunger + else + to_chat(H, "You can't receive charge from the [src]!") + return /obj/item/stock_parts/cell/blob_act(obj/structure/blob/B) ex_act(EXPLODE_DEVASTATE) diff --git a/code/modules/power/floodlight.dm b/code/modules/power/floodlight.dm index e0b3f5f316..466030b83c 100644 --- a/code/modules/power/floodlight.dm +++ b/code/modules/power/floodlight.dm @@ -92,10 +92,7 @@ else . = ..() -/obj/machinery/power/floodlight/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/power/floodlight/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) var/current = setting if(current == 1) current = light_setting_list.len @@ -113,4 +110,4 @@ qdel(src) /obj/machinery/power/floodlight/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) - playsound(src, 'sound/effects/glasshit.ogg', 75, 1) \ No newline at end of file + playsound(src, 'sound/effects/glasshit.ogg', 75, 1) diff --git a/code/modules/power/generator.dm b/code/modules/power/generator.dm index 6d63a57c88..54b1362518 100644 --- a/code/modules/power/generator.dm +++ b/code/modules/power/generator.dm @@ -57,7 +57,7 @@ var/cold_air_heat_capacity = cold_air.heat_capacity() var/hot_air_heat_capacity = hot_air.heat_capacity() - var/delta_temperature = hot_air.temperature - cold_air.temperature + var/delta_temperature = hot_air.return_temperature() - cold_air.return_temperature() if(delta_temperature > 0 && cold_air_heat_capacity > 0 && hot_air_heat_capacity > 0) @@ -66,10 +66,10 @@ var/energy_transfer = delta_temperature*hot_air_heat_capacity*cold_air_heat_capacity/(hot_air_heat_capacity+cold_air_heat_capacity) var/heat = energy_transfer*(1-efficiency) - lastgen += energy_transfer*efficiency + lastgen += LOGISTIC_FUNCTION(1000000,0.0034,delta_temperature,2000) - hot_air.temperature = hot_air.temperature - energy_transfer/hot_air_heat_capacity - cold_air.temperature = cold_air.temperature + heat/cold_air_heat_capacity + hot_air.set_temperature(hot_air.return_temperature() - energy_transfer/hot_air_heat_capacity) + cold_air.set_temperature(cold_air.return_temperature() + heat/cold_air_heat_capacity) //add_avail(lastgen) This is done in process now // update icon overlays only if displayed level has changed @@ -116,11 +116,11 @@ t += "
    " t += "Cold loop
    " - t += "Temperature Inlet: [round(cold_circ_air2.temperature, 0.1)] K / Outlet: [round(cold_circ_air1.temperature, 0.1)] K
    " + t += "Temperature Inlet: [round(cold_circ_air2.return_temperature(), 0.1)] K / Outlet: [round(cold_circ_air1.return_temperature(), 0.1)] K
    " t += "Pressure Inlet: [round(cold_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(cold_circ_air1.return_pressure(), 0.1)] kPa
    " t += "Hot loop
    " - t += "Temperature Inlet: [round(hot_circ_air2.temperature, 0.1)] K / Outlet: [round(hot_circ_air1.temperature, 0.1)] K
    " + t += "Temperature Inlet: [round(hot_circ_air2.return_temperature(), 0.1)] K / Outlet: [round(hot_circ_air1.return_temperature(), 0.1)] K
    " t += "Pressure Inlet: [round(hot_circ_air2.return_pressure(), 0.1)] kPa / Outlet: [round(hot_circ_air1.return_pressure(), 0.1)] kPa
    " t += "
  • " diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 1644673ece..e37ae56e71 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF var/sprite_number = 0 -/obj/machinery/gravity_generator/safe_throw_at() +/obj/machinery/gravity_generator/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE) return FALSE /obj/machinery/gravity_generator/ex_act(severity, target) @@ -56,7 +56,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne qdel(src) /obj/machinery/gravity_generator/proc/set_broken() - stat |= BROKEN + obj_break() /obj/machinery/gravity_generator/proc/set_fix() stat &= ~BROKEN @@ -80,7 +80,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne /obj/machinery/gravity_generator/part/get_status() return main_part?.get_status() -/obj/machinery/gravity_generator/part/attack_hand(mob/user) +/obj/machinery/gravity_generator/part/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) return main_part.attack_hand(user) /obj/machinery/gravity_generator/part/set_broken() @@ -187,14 +187,14 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne /obj/machinery/gravity_generator/main/attackby(obj/item/I, mob/user, params) switch(broken_state) if(GRAV_NEEDS_SCREWDRIVER) - if(istype(I, /obj/item/screwdriver)) + if(I.tool_behaviour == TOOL_SCREWDRIVER) to_chat(user, "You secure the screws of the framework.") I.play_tool_sound(src) broken_state++ update_icon() return if(GRAV_NEEDS_WELDING) - if(istype(I, /obj/item/weldingtool)) + if(I.tool_behaviour == TOOL_WELDER) if(I.use_tool(src, user, 0, volume=50, amount=1)) to_chat(user, "You mend the damaged framework.") broken_state++ @@ -206,25 +206,24 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne if(PS.get_amount() >= 10) PS.use(10) to_chat(user, "You add the plating to the framework.") - playsound(src.loc, 'sound/machines/click.ogg', 75, 1) + playsound(src.loc, 'sound/machines/click.ogg', 75, TRUE) broken_state++ update_icon() else to_chat(user, "You need 10 sheets of plasteel!") return if(GRAV_NEEDS_WRENCH) - if(istype(I, /obj/item/wrench)) + if(I.tool_behaviour == TOOL_WRENCH) to_chat(user, "You secure the plating to the framework.") I.play_tool_sound(src) set_fix() return return ..() -/obj/machinery/gravity_generator/main/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/gravity_generator/main/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "gravity_generator", name, 400, 200, master_ui, state) + ui = new(user, src, "GravityGenerator", name) ui.open() /obj/machinery/gravity_generator/main/ui_data(mob/user) @@ -241,16 +240,18 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne /obj/machinery/gravity_generator/main/ui_act(action, params) if(..()) return + switch(action) if("gentoggle") breaker = !breaker investigate_log("was toggled [breaker ? "ON" : "OFF"] by [key_name(usr)].", INVESTIGATE_GRAVITY) set_power() + . = TRUE // Power and Icon States /obj/machinery/gravity_generator/main/power_change() - ..() + . = ..() investigate_log("has [stat & NOPOWER ? "lost" : "regained"] power.", INVESTIGATE_GRAVITY) set_power() @@ -313,7 +314,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne charge_count -= 2 if(charge_count % 4 == 0 && prob(75)) // Let them know it is charging/discharging. - playsound(src.loc, 'sound/effects/empulse.ogg', 100, 1) + playsound(src.loc, 'sound/effects/empulse.ogg', 100, TRUE) updateDialog() if(prob(25)) // To help stop "Your clothes feel warm." spam. @@ -390,16 +391,13 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne // Misc /obj/item/paper/guides/jobs/engi/gravity_gen - name = "paper- 'Generate your own gravity!'" - info = {"

    Gravity Generator Instructions For Dummies

    -

    Surprisingly, gravity isn't that hard to make! All you have to do is inject deadly radioactive minerals into a ball of - energy and you have yourself gravity! You can turn the machine on or off when required but you must remember that the generator - will EMIT RADIATION when charging or discharging, you can tell it is charging or discharging by the noise it makes, so please WEAR PROTECTIVE CLOTHING.

    -
    -

    It blew up!

    -

    Don't panic! The gravity generator was designed to be easily repaired. If, somehow, the sturdy framework did not survive then - please proceed to panic; otherwise follow these steps.

      -
    1. Secure the screws of the framework with a screwdriver.
    2. -
    3. Mend the damaged framework with a welding tool.
    4. -
    5. Add additional plasteel plating.
    6. -
    7. Secure the additional plating with a wrench.
    "} + info = {" +# Gravity Generator Instructions For Dummies +Surprisingly, gravity isn't that hard to make! All you have to do is inject deadly radioactive minerals into a ball of energy and you have yourself gravity! You can turn the machine on or off when required but you must remember that the generator will EMIT RADIATION when charging or discharging, you can tell it is charging or discharging by the noise it makes, so please WEAR PROTECTIVE CLOTHING.

    +### It blew up! +Don't panic! The gravity generator was designed to be easily repaired. If, somehow, the sturdy framework did not survive then please proceed to panic; otherwise follow these steps. +1. Secure the screws of the framework with a screwdriver. +2. Mend the damaged framework with a welding tool. +3. Add additional plasteel plating. +4. Secure the additional plating with a wrench. +"} diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index c18eebbb55..4c76c4b5b1 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -118,7 +118,7 @@ return if(istype(W, /obj/item/stack/cable_coil)) - if(W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_TRAINED)) + if(W.use_tool(src, user, 0, 1, skill_gain_mult = TRIVIAL_USE_TOOL_MULT)) icon_state = "[fixture_type]-construct-stage2" stage = 2 user.visible_message("[user.name] adds wires to [src].", \ @@ -595,11 +595,9 @@ // attack with hand - remove tube/bulb // if hands aren't protected and the light is on, burn the player -/obj/machinery/light/attack_hand(mob/living/carbon/human/user) +/obj/machinery/light/on_attack_hand(mob/living/carbon/human/user) . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) add_fingerprint(user) if(status == LIGHT_EMPTY) @@ -612,7 +610,18 @@ var/mob/living/carbon/human/H = user if(istype(H)) - + var/datum/species/ethereal/eth_species = H.dna?.species + if(istype(eth_species)) + to_chat(H, "You start channeling some power through the [fitting] into your body.") + if(do_after(user, 50, target = src)) + var/obj/item/organ/stomach/ethereal/stomach = H.getorganslot(ORGAN_SLOT_STOMACH) + if(istype(stomach)) + to_chat(H, "You receive some charge from the [fitting].") + stomach.adjust_charge(2) + else + to_chat(H, "You can't receive charge from the [fitting]!") + return + if(H.gloves) var/obj/item/clothing/gloves/G = H.gloves if(G.max_heat_protection_temperature) @@ -812,11 +821,11 @@ return /obj/item/light/attack(mob/living/M, mob/living/user, def_zone) - ..() + . = ..() shatter() /obj/item/light/attack_obj(obj/O, mob/living/user) - ..() + . = ..() shatter() /obj/item/light/proc/shatter() diff --git a/code/modules/power/monitor.dm b/code/modules/power/monitor.dm index f4ee102ccc..393d403c4d 100644 --- a/code/modules/power/monitor.dm +++ b/code/modules/power/monitor.dm @@ -10,6 +10,7 @@ idle_power_usage = 20 active_power_usage = 100 circuit = /obj/item/circuitboard/computer/powermonitor + tgui_id = "PowerMonitor" var/obj/structure/cable/attached_wire var/obj/machinery/power/apc/local_apc @@ -19,8 +20,6 @@ var/record_interval = 50 var/next_record = 0 var/is_secret_monitor = FALSE - tgui_id = "power_monitor" - ui_style = "ntos" /obj/machinery/computer/monitor/secret //Hides the power monitor (such as ones on ruins & CentCom) from PDA's to prevent metagaming. name = "outdated power monitoring console" @@ -83,11 +82,10 @@ if(demand.len > record_size) demand.Cut(1, 2) -/obj/machinery/computer/monitor/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/monitor/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, tgui_id, name, 550, 700, master_ui, state) + ui = new(user, src, "PowerMonitor", name) ui.open() /obj/machinery/computer/monitor/ui_data() diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 3c20f2f69c..e2f8c4e58a 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -1,4 +1,3 @@ - //Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power). /obj/machinery/power/port_gen name = "portable generator" @@ -9,9 +8,8 @@ anchored = FALSE use_power = NO_POWER_USE - var/active = 0 + var/active = FALSE var/power_gen = 5000 - var/recent_fault = 0 var/power_output = 1 var/consumption = 0 var/base_icon = "portgen0" @@ -27,8 +25,13 @@ QDEL_NULL(soundloop) return ..() +/obj/machinery/power/port_gen/connect_to_network() + if(!anchored) + return FALSE + . = ..() + /obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check. - return 1 + return TRUE /obj/machinery/power/port_gen/proc/UseFuel() //Placeholder for fuel use. return @@ -39,26 +42,38 @@ /obj/machinery/power/port_gen/proc/handleInactive() return +/obj/machinery/power/port_gen/proc/TogglePower() + if(active) + active = FALSE + update_icon() + soundloop.stop() + else if(HasFuel()) + active = TRUE + START_PROCESSING(SSmachines, src) + update_icon() + soundloop.start() + /obj/machinery/power/port_gen/update_icon_state() icon_state = "[base_icon]_[active]" /obj/machinery/power/port_gen/process() - if(active && HasFuel() && !crit_fail && anchored && powernet) - add_avail(power_gen * power_output) + if(active) + if(!HasFuel() || !anchored) + TogglePower() + return + if(powernet) + add_avail(power_gen * power_output) UseFuel() - src.updateDialog() - soundloop.start() - else - active = 0 handleInactive() - update_icon() - soundloop.stop() /obj/machinery/power/port_gen/examine(mob/user) . = ..() . += "It is[!active?"n't":""] running." +///////////////// +// P.A.C.M.A.N // +///////////////// /obj/machinery/power/port_gen/pacman name = "\improper P.A.C.M.A.N.-type portable generator" circuit = /obj/item/circuitboard/machine/pacman @@ -78,8 +93,8 @@ /obj/machinery/power/port_gen/pacman/Initialize() . = ..() - var/obj/sheet = new sheet_path(null) - sheet_name = sheet.name + var/obj/S = sheet_path + sheet_name = initial(S.name) /obj/machinery/power/port_gen/pacman/Destroy() DropFuel() @@ -100,16 +115,16 @@ /obj/machinery/power/port_gen/pacman/examine(mob/user) . = ..() - . += "The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle." - if(crit_fail) - . += "The generator seems to have broken down." + . += "The generator has [sheets] units of [sheet_name] fuel left, producing [DisplayPower(power_gen)] per cycle." + if(anchored) + . += "It is anchored to the ground." if(in_range(user, src) || isobserver(user)) . += "The status display reads: Fuel efficiency increased by [(consumption*100)-100]%." /obj/machinery/power/port_gen/pacman/HasFuel() if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left) - return 1 - return 0 + return TRUE + return FALSE /obj/machinery/power/port_gen/pacman/DropFuel() if(sheets) @@ -145,13 +160,11 @@ if (current_heat > 300) overheat() qdel(src) - return /obj/machinery/power/port_gen/pacman/handleInactive() - - if (current_heat > 0) - current_heat = max(current_heat - 2, 0) - src.updateDialog() + current_heat = max(current_heat - 2, 0) + if(current_heat == 0) + STOP_PROCESSING(SSmachines, src) /obj/machinery/power/port_gen/pacman/proc/overheat() explosion(src.loc, 2, 5, 2, -1) @@ -166,24 +179,21 @@ to_chat(user, "You add [amount] sheets to the [src.name].") sheets += amount addstack.use(amount) - updateUsrDialog() return else if(!active) - - if(istype(O, /obj/item/wrench)) - + if(O.tool_behaviour == TOOL_WRENCH) if(!anchored && !isinspace()) + anchored = TRUE connect_to_network() to_chat(user, "You secure the generator to the floor.") - anchored = TRUE else if(anchored) + anchored = FALSE disconnect_from_network() to_chat(user, "You unsecure the generator from the floor.") - anchored = FALSE - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) + playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE) return - else if(istype(O, /obj/item/screwdriver)) + else if(O.tool_behaviour == TOOL_SCREWDRIVER) panel_open = !panel_open O.play_tool_sound(src) if(panel_open) @@ -196,12 +206,10 @@ return ..() /obj/machinery/power/port_gen/pacman/emag_act(mob/user) - . = ..() if(obj_flags & EMAGGED) return obj_flags |= EMAGGED emp_act(EMP_HEAVY) - return TRUE /obj/machinery/power/port_gen/pacman/attack_ai(mob/user) interact(user) @@ -209,60 +217,51 @@ /obj/machinery/power/port_gen/pacman/attack_paw(mob/user) interact(user) -/obj/machinery/power/port_gen/pacman/ui_interact(mob/user) - . = ..() - if (get_dist(src, user) > 1 ) - if(!isAI(user)) - user.unset_machine() - user << browse(null, "window=port_gen") - return +/obj/machinery/power/port_gen/pacman/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PortableGenerator", name) + ui.open() - var/dat = text("[name]
    ") - if (active) - dat += text("Generator: On
    ") - else - dat += text("Generator: Off
    ") - dat += text("[capitalize(sheet_name)]: [sheets] - Eject
    ") - var/stack_percent = round(sheet_left * 100, 1) - dat += text("Current stack: [stack_percent]%
    ") - dat += text("Power output: - [power_gen * power_output] +
    ") - dat += text("Power current: [(powernet == null ? "Unconnected" : "[DisplayPower(avail())]")]
    ") - dat += text("Heat: [current_heat]
    ") - dat += "
    Close" - user << browse(dat, "window=port_gen") - onclose(user, "port_gen") +/obj/machinery/power/port_gen/pacman/ui_data() + var/data = list() -/obj/machinery/power/port_gen/pacman/Topic(href, href_list) + data["active"] = active + data["sheet_name"] = capitalize(sheet_name) + data["sheets"] = sheets + data["stack_percent"] = round(sheet_left * 100, 0.1) + + data["anchored"] = anchored + data["connected"] = (powernet == null ? 0 : 1) + data["ready_to_boot"] = anchored && HasFuel() + data["power_generated"] = DisplayPower(power_gen) + data["power_output"] = DisplayPower(power_gen * power_output) + data["power_available"] = (powernet == null ? 0 : DisplayPower(avail())) + data["current_heat"] = current_heat + . = data + +/obj/machinery/power/port_gen/pacman/ui_act(action, params) if(..()) return + switch(action) + if("toggle_power") + TogglePower() + . = TRUE - src.add_fingerprint(usr) - if(href_list["action"]) - if(href_list["action"] == "enable") - if(!active && HasFuel() && !crit_fail) - active = 1 - src.updateUsrDialog() - update_icon() - if(href_list["action"] == "disable") - if (active) - active = 0 - src.updateUsrDialog() - update_icon() - if(href_list["action"] == "eject") + if("eject") if(!active) DropFuel() - src.updateUsrDialog() - if(href_list["action"] == "lower_power") + . = TRUE + + if("lower_power") if (power_output > 1) power_output-- - src.updateUsrDialog() - if (href_list["action"] == "higher_power") + . = TRUE + + if("higher_power") if (power_output < 4 || (obj_flags & EMAGGED)) power_output++ - src.updateUsrDialog() - if (href_list["action"] == "close") - usr << browse(null, "window=port_gen") - usr.unset_machine() + . = TRUE /obj/machinery/power/port_gen/pacman/super name = "\improper S.U.P.E.R.P.A.C.M.A.N.-type portable generator" diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index f84b639d68..9bbdcf4f66 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -299,8 +299,8 @@ //siemens_coeff - layman's terms, conductivity //dist_check - set to only shock mobs within 1 of source (vendors, airlocks, etc.) //No animations will be performed by this proc. -/proc/electrocute_mob(mob/living/carbon/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE) - if(!M || ismecha(M.loc)) +/proc/electrocute_mob(mob/living/M, power_source, obj/source, siemens_coeff = 1, dist_check = FALSE) + if(!istype(M) || ismecha(M.loc)) return 0 //feckin mechs are dumb if(dist_check) if(!in_range(source,M)) @@ -386,4 +386,4 @@ var/target = base_area ? base_area : src for(var/obj/machinery/power/apc/APC in GLOB.apcs_list) if(APC.area == target) - return APC \ No newline at end of file + return APC diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index 651892e5b1..256b13ee72 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -47,31 +47,29 @@ if(!loaded_tank) return if(!bitcoinmining) - if(!loaded_tank.air_contents.gases[/datum/gas/plasma]) + if(loaded_tank.air_contents.get_moles(/datum/gas/plasma) < 0.0001) investigate_log("out of fuel.", INVESTIGATE_SINGULO) playsound(src, 'sound/machines/ding.ogg', 50, 1) Radio.talk_into(src, "Insufficient plasma in [get_area(src)] [src], ejecting \the [loaded_tank].", FREQ_ENGINEERING) eject() else - var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.gases[/datum/gas/plasma]) - loaded_tank.air_contents.gases[/datum/gas/plasma] -= 2.7 * gasdrained - loaded_tank.air_contents.gases[/datum/gas/tritium] += 2.7 * gasdrained - GAS_GARBAGE_COLLECT(loaded_tank.air_contents.gases) + var/gasdrained = min(powerproduction_drain*drainratio,loaded_tank.air_contents.get_moles(/datum/gas/plasma)) + loaded_tank.air_contents.adjust_moles(/datum/gas/plasma, -gasdrained) + loaded_tank.air_contents.adjust_moles(/datum/gas/tritium, gasdrained) var/power_produced = RAD_COLLECTOR_OUTPUT add_avail(power_produced) stored_power-=power_produced else if(is_station_level(z) && SSresearch.science_tech) - if(!loaded_tank.air_contents.gases[/datum/gas/tritium] || !loaded_tank.air_contents.gases[/datum/gas/oxygen]) + if(!loaded_tank.air_contents.get_moles(/datum/gas/tritium) || !loaded_tank.air_contents.get_moles(/datum/gas/oxygen)) playsound(src, 'sound/machines/ding.ogg', 50, 1) Radio.talk_into(src, "Insufficient oxygen and tritium in [get_area(src)] [src] to produce research points, ejecting \the [loaded_tank].", FREQ_ENGINEERING) eject() else var/gasdrained = bitcoinproduction_drain*drainratio - loaded_tank.air_contents.gases[/datum/gas/tritium] -= gasdrained - 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) + loaded_tank.air_contents.adjust_moles(/datum/gas/tritium, -gasdrained) + loaded_tank.air_contents.adjust_moles(/datum/gas/oxygen, -gasdrained) + loaded_tank.air_contents.adjust_moles(/datum/gas/carbon_dioxide, gasdrained*2) var/bitcoins_mined = stored_power*RAD_COLLECTOR_MINING_CONVERSION_RATE var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_ENG) if(D) @@ -86,9 +84,7 @@ toggle_power() user.visible_message("[user.name] turns the [src.name] [active? "on":"off"].", \ "You turn the [src.name] [active? "on":"off"].") - var/fuel - if(loaded_tank) - fuel = loaded_tank.air_contents.gases[/datum/gas/plasma] + var/fuel = loaded_tank.air_contents.get_moles(/datum/gas/plasma) investigate_log("turned [active?"on":"off"] by [key_name(user)]. [loaded_tank?"Fuel: [round(fuel/0.29)]%":"It is empty"].", INVESTIGATE_SINGULO) return else @@ -180,6 +176,7 @@ /obj/machinery/power/rad_collector/analyzer_act(mob/living/user, obj/item/I) if(loaded_tank) loaded_tank.analyzer_act(user, I) + return TRUE /obj/machinery/power/rad_collector/examine(mob/user) . = ..() diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index 89596eb82f..dfb51df9cf 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -21,8 +21,7 @@ FG2.fields -= src return ..() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/machinery/field/containment/attack_hand(mob/user) +/obj/machinery/field/containment/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(get_dist(src, user) > 1) return FALSE else diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 0d182e0a1b..50dae7d6bb 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -315,6 +315,9 @@ /obj/machinery/power/emitter/proc/integrate(obj/item/gun/energy/E,mob/user) if(istype(E, /obj/item/gun/energy)) + if(!E.can_emitter) + to_chat(user, "[E] cannot fit into emitters.") + return if(!user.transferItemToLoc(E, src)) return gun = E diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm index e33116b02c..528a3abb8b 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm @@ -103,7 +103,6 @@ did_something = TRUE if(did_something) - user.changeNext_move(CLICK_CD_MELEE) update_state() update_icon() return diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm index 957ceb986f..96c8d9a263 100644 --- a/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -9,15 +9,15 @@ idle_power_usage = 500 active_power_usage = 10000 dir = NORTH - var/strength_upper_limit = 2 - var/interface_control = 1 - var/list/obj/structure/particle_accelerator/connected_parts - var/assembled = 0 - var/construction_state = PA_CONSTRUCTION_UNSECURED - var/active = 0 - var/strength = 0 - var/powered = 0 mouse_opacity = MOUSE_OPACITY_OPAQUE + var/strength_upper_limit = 2 + var/interface_control = TRUE + var/list/obj/structure/particle_accelerator/connected_parts + var/assembled = FALSE + var/construction_state = PA_CONSTRUCTION_UNSECURED + var/active = FALSE + var/strength = 0 + var/powered = FALSE /obj/machinery/particle_accelerator/control_box/Initialize() . = ..() @@ -34,30 +34,27 @@ QDEL_NULL(wires) return ..() -/obj/machinery/particle_accelerator/control_box/attack_hand(mob/user) +/obj/machinery/particle_accelerator/control_box/multitool_act(mob/living/user, obj/item/I) . = ..() - if(.) - return - if(construction_state == PA_CONSTRUCTION_COMPLETE) - interact(user) - else if(construction_state == PA_CONSTRUCTION_PANEL_OPEN) + if(construction_state == PA_CONSTRUCTION_PANEL_OPEN) wires.interact(user) + return TRUE /obj/machinery/particle_accelerator/control_box/proc/update_state() if(construction_state < PA_CONSTRUCTION_COMPLETE) use_power = NO_POWER_USE - assembled = 0 - active = 0 + assembled = FALSE + active = FALSE for(var/CP in connected_parts) var/obj/structure/particle_accelerator/part = CP part.strength = null - part.powered = 0 + part.powered = FALSE part.update_icon() connected_parts.Cut() return if(!part_scan()) use_power = IDLE_POWER_USE - active = 0 + active = FALSE connected_parts.Cut() /obj/machinery/particle_accelerator/control_box/update_icon_state() @@ -78,36 +75,6 @@ else icon_state = "control_boxc" -/obj/machinery/particle_accelerator/control_box/Topic(href, href_list) - if(..()) - return - - if(!interface_control) - to_chat(usr, "ERROR: Request timed out. Check wire contacts.") - return - - if(href_list["close"]) - usr << browse(null, "window=pacontrol") - usr.unset_machine() - return - if(href_list["togglep"]) - if(!wires.is_cut(WIRE_POWER)) - toggle_power() - - else if(href_list["scan"]) - part_scan() - - else if(href_list["strengthup"]) - if(!wires.is_cut(WIRE_STRENGTH)) - add_strength() - - else if(href_list["strengthdown"]) - if(!wires.is_cut(WIRE_STRENGTH)) - remove_strength() - - updateDialog() - update_icon() - /obj/machinery/particle_accelerator/control_box/proc/strength_change() for(var/CP in connected_parts) var/obj/structure/particle_accelerator/part = CP @@ -123,7 +90,6 @@ log_game("PA Control Computer increased to [strength] by [key_name(usr)] in [AREACOORD(src)]") investigate_log("increased to [strength] by [key_name(usr)] at [AREACOORD(src)]", INVESTIGATE_SINGULO) - /obj/machinery/particle_accelerator/control_box/proc/remove_strength(s) if(assembled && (strength > 0)) strength-- @@ -133,11 +99,10 @@ log_game("PA Control Computer decreased to [strength] by [key_name(usr)] in [AREACOORD(src)]") investigate_log("decreased to [strength] by [key_name(usr)] at [AREACOORD(src)]", INVESTIGATE_SINGULO) - /obj/machinery/particle_accelerator/control_box/power_change() - ..() + . = ..() if(stat & NOPOWER) - active = 0 + active = FALSE use_power = NO_POWER_USE else if(!stat && construction_state == PA_CONSTRUCTION_COMPLETE) use_power = IDLE_POWER_USE @@ -160,49 +125,48 @@ var/odir = turn(dir,180) var/turf/T = loc - assembled = 0 + assembled = FALSE critical_machine = FALSE var/obj/structure/particle_accelerator/fuel_chamber/F = locate() in orange(1,src) if(!F) - return 0 + return FALSE setDir(F.dir) connected_parts.Cut() T = get_step(T,rdir) if(!check_part(T, /obj/structure/particle_accelerator/fuel_chamber)) - return 0 + return FALSE T = get_step(T,odir) if(!check_part(T, /obj/structure/particle_accelerator/end_cap)) - return 0 + return FALSE T = get_step(T,dir) T = get_step(T,dir) if(!check_part(T, /obj/structure/particle_accelerator/power_box)) - return 0 + return FALSE T = get_step(T,dir) if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/center)) - return 0 + return FALSE T = get_step(T,ldir) if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/left)) - return 0 + return FALSE T = get_step(T,rdir) T = get_step(T,rdir) if(!check_part(T, /obj/structure/particle_accelerator/particle_emitter/right)) - return 0 + return FALSE - assembled = 1 + assembled = TRUE critical_machine = TRUE //Only counts if the PA is actually assembled. - return 1 + return TRUE /obj/machinery/particle_accelerator/control_box/proc/check_part(turf/T, type) var/obj/structure/particle_accelerator/PA = locate(/obj/structure/particle_accelerator) in T if(istype(PA, type) && (PA.construction_state == PA_CONSTRUCTION_COMPLETE)) if(PA.connect_master(src)) connected_parts.Add(PA) - return 1 - return 0 - + return TRUE + return FALSE /obj/machinery/particle_accelerator/control_box/proc/toggle_power() active = !active @@ -214,47 +178,16 @@ for(var/CP in connected_parts) var/obj/structure/particle_accelerator/part = CP part.strength = strength - part.powered = 1 + part.powered = TRUE part.update_icon() else use_power = IDLE_POWER_USE for(var/CP in connected_parts) var/obj/structure/particle_accelerator/part = CP part.strength = null - part.powered = 0 + part.powered = FALSE part.update_icon() - return 1 - - -/obj/machinery/particle_accelerator/control_box/ui_interact(mob/user) - . = ..() - if((get_dist(src, user) > 1) || (stat & (BROKEN|NOPOWER))) - if(!issilicon(user)) - user.unset_machine() - user << browse(null, "window=pacontrol") - return - - var/dat = "" - dat += "Close

    " - dat += "

    Status

    " - if(!assembled) - dat += "Unable to detect all parts!
    " - dat += "Run Scan

    " - else - dat += "All parts in place.

    " - dat += "Power:" - if(active) - dat += "On
    " - else - dat += "Off
    " - dat += "Toggle Power

    " - dat += "Particle Strength: [strength] " - dat += "--|++

    " - - var/datum/browser/popup = new(user, "pacontrol", name, 420, 300) - popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) - popup.open() + return TRUE /obj/machinery/particle_accelerator/control_box/examine(mob/user) . = ..() @@ -266,53 +199,51 @@ if(PA_CONSTRUCTION_PANEL_OPEN) . += "The panel is open." - /obj/machinery/particle_accelerator/control_box/attackby(obj/item/W, mob/user, params) var/did_something = FALSE switch(construction_state) if(PA_CONSTRUCTION_UNSECURED) - if(istype(W, /obj/item/wrench) && !isinspace()) + if(W.tool_behaviour == TOOL_WRENCH && !isinspace()) W.play_tool_sound(src, 75) anchored = TRUE - user.visible_message("[user.name] secures the [name] to the floor.", \ - "You secure the external bolts.") + user.visible_message("[user.name] secures the [name] to the floor.", \ + "You secure the external bolts.") construction_state = PA_CONSTRUCTION_UNWIRED did_something = TRUE if(PA_CONSTRUCTION_UNWIRED) - if(istype(W, /obj/item/wrench)) + if(W.tool_behaviour == TOOL_WRENCH) W.play_tool_sound(src, 75) anchored = FALSE - user.visible_message("[user.name] detaches the [name] from the floor.", \ - "You remove the external bolts.") + user.visible_message("[user.name] detaches the [name] from the floor.", \ + "You remove the external bolts.") construction_state = PA_CONSTRUCTION_UNSECURED did_something = TRUE else if(istype(W, /obj/item/stack/cable_coil)) if(W.use_tool(src, user, 0, 1)) - user.visible_message("[user.name] adds wires to the [name].", \ - "You add some wires.") + user.visible_message("[user.name] adds wires to the [name].", \ + "You add some wires.") construction_state = PA_CONSTRUCTION_PANEL_OPEN did_something = TRUE if(PA_CONSTRUCTION_PANEL_OPEN) - if(istype(W, /obj/item/wirecutters))//TODO:Shock user if its on? - user.visible_message("[user.name] removes some wires from the [name].", \ - "You remove some wires.") + if(W.tool_behaviour == TOOL_WIRECUTTER)//TODO:Shock user if its on? + user.visible_message("[user.name] removes some wires from the [name].", \ + "You remove some wires.") construction_state = PA_CONSTRUCTION_UNWIRED did_something = TRUE - else if(istype(W, /obj/item/screwdriver)) - user.visible_message("[user.name] closes the [name]'s access panel.", \ - "You close the access panel.") + else if(W.tool_behaviour == TOOL_SCREWDRIVER) + user.visible_message("[user.name] closes the [name]'s access panel.", \ + "You close the access panel.") construction_state = PA_CONSTRUCTION_COMPLETE did_something = TRUE if(PA_CONSTRUCTION_COMPLETE) - if(istype(W, /obj/item/screwdriver)) - user.visible_message("[user.name] opens the [name]'s access panel.", \ - "You open the access panel.") + if(W.tool_behaviour == TOOL_SCREWDRIVER) + user.visible_message("[user.name] opens the [name]'s access panel.", \ + "You open the access panel.") construction_state = PA_CONSTRUCTION_PANEL_OPEN did_something = TRUE if(did_something) - user.changeNext_move(CLICK_CD_MELEE) update_state() update_icon() return @@ -323,6 +254,64 @@ if(prob(50)) qdel(src) +/obj/machinery/particle_accelerator/control_box/interact(mob/user) + if(construction_state == PA_CONSTRUCTION_PANEL_OPEN) + wires.interact(user) + else + ..() + +/obj/machinery/particle_accelerator/control_box/proc/is_interactive(mob/user) + if(!interface_control) + to_chat(user, "ERROR: Request timed out. Check wire contacts.") + return FALSE + if(construction_state != PA_CONSTRUCTION_COMPLETE) + return FALSE + return TRUE + +/obj/machinery/particle_accelerator/control_box/ui_status(mob/user) + if(is_interactive(user)) + return ..() + return UI_CLOSE + +/obj/machinery/particle_accelerator/control_box/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ParticleAccelerator", name) + ui.open() + +/obj/machinery/particle_accelerator/control_box/ui_data(mob/user) + var/list/data = list() + data["assembled"] = assembled + data["power"] = active + data["strength"] = strength + return data + +/obj/machinery/particle_accelerator/control_box/ui_act(action, params) + if(..()) + return + + switch(action) + if("power") + if(wires.is_cut(WIRE_POWER)) + return + toggle_power() + . = TRUE + if("scan") + part_scan() + . = TRUE + if("add_strength") + if(wires.is_cut(WIRE_STRENGTH)) + return + add_strength() + . = TRUE + if("remove_strength") + if(wires.is_cut(WIRE_STRENGTH)) + return + remove_strength() + . = TRUE + + update_icon() + #undef PA_CONSTRUCTION_UNSECURED #undef PA_CONSTRUCTION_UNWIRED #undef PA_CONSTRUCTION_PANEL_OPEN diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 025784e909..cc3a19cf55 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -59,7 +59,7 @@ last_failed_movement = direct return 0 -/obj/singularity/attack_hand(mob/user) +/obj/singularity/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) consume(user) return TRUE diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 85999707a2..a4fc7d0641 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -21,6 +21,7 @@ density = TRUE use_power = NO_POWER_USE circuit = /obj/item/circuitboard/machine/smes + var/capacity = 5e6 // maximum charge var/charge = 0 // actual charge @@ -54,7 +55,7 @@ break dir_loop if(!terminal) - stat |= BROKEN + obj_break() return terminal.master = src update_icon() @@ -123,22 +124,22 @@ return to_chat(user, "You start building the power terminal...") - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1) + playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE) 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 + if(!terminal) + C.use(10) + user.visible_message("[user.name] builds a power terminal.",\ + "You build the power terminal.") - user.visible_message(\ - "[user.name] has built a power terminal.",\ - "You build the power terminal.") - - //build the terminal and link it to the network - make_terminal(T) - terminal.connect_to_network() - connect_to_network() + //build the terminal and link it to the network + make_terminal(T) + terminal.connect_to_network() + connect_to_network() return //crowbarring it ! @@ -148,13 +149,14 @@ log_game("[src] has been deconstructed by [key_name(user)] at [AREACOORD(src)]") investigate_log("SMES deconstructed by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_SINGULO) return - else if(panel_open && istype(I, /obj/item/crowbar)) + else if(panel_open && I.tool_behaviour == TOOL_CROWBAR) return return ..() /obj/machinery/power/smes/wirecutter_act(mob/living/user, obj/item/I) //disassembling the terminal + . = ..() if(terminal && panel_open) terminal.dismantle(user, I) return TRUE @@ -193,12 +195,15 @@ if(terminal) terminal.master = null terminal = null - stat |= BROKEN + obj_break() /obj/machinery/power/smes/update_overlays() . = ..() - if((stat & BROKEN) || panel_open) + if(stat & BROKEN) + return + + if(panel_open) return if(outputting) @@ -208,14 +213,14 @@ if(inputting) . += "smes-oc1" - else - if(input_attempt) - . += "smes-oc0" + else if(input_attempt) + . += "smes-oc0" var/clevel = chargedisplay() if(clevel>0) . += "smes-og[clevel]" + /obj/machinery/power/smes/proc/chargedisplay() return clamp(round(5.5*charge/capacity),0,5) @@ -228,6 +233,11 @@ var/last_chrg = inputting var/last_onln = outputting + //check for self-recharging cells in stock parts and use them to self-charge + for(var/obj/item/stock_parts/cell/C in component_parts) + if(C.self_recharge) + charge += min(capacity-charge, C.chargerate) // If capacity-charge is smaller than the attempted charge rate, this avoids overcharging + //inputting if(terminal && input_attempt) input_available = terminal.surplus() @@ -306,32 +316,29 @@ return -/obj/machinery/power/smes/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/power/smes/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "smes", name, 340, 440, master_ui, state) + ui = new(user, src, "Smes", name) ui.open() /obj/machinery/power/smes/ui_data() var/list/data = list( - "capacityPercent" = round(100*charge/capacity, 0.1), "capacity" = capacity, + "capacityPercent" = round(100*charge/capacity, 0.1), "charge" = charge, - "inputAttempt" = input_attempt, "inputting" = inputting, "inputLevel" = input_level, "inputLevel_text" = DisplayPower(input_level), "inputLevelMax" = input_level_max, - "inputAvailable" = DisplayPower(input_available), - + "inputAvailable" = input_available, "outputAttempt" = output_attempt, "outputting" = outputting, "outputLevel" = output_level, "outputLevel_text" = DisplayPower(output_level), "outputLevelMax" = output_level_max, - "outputUsed" = DisplayPower(output_used) + "outputUsed" = output_used, ) return data @@ -352,11 +359,7 @@ if("input") var/target = params["target"] var/adjust = text2num(params["adjust"]) - if(target == "input") - target = input("New input target (0-[input_level_max]):", name, input_level) as num|null - if(!isnull(target) && !..()) - . = TRUE - else if(target == "min") + if(target == "min") target = 0 . = TRUE else if(target == "max") @@ -374,11 +377,7 @@ if("output") var/target = params["target"] var/adjust = text2num(params["adjust"]) - if(target == "input") - target = input("New output target (0-[output_level_max]):", name, output_level) as num|null - if(!isnull(target) && !..()) - . = TRUE - else if(target == "min") + if(target == "min") target = 0 . = TRUE else if(target == "max") diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 89452affcb..cf526f083d 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -115,9 +115,6 @@ panel.icon_state = "solar_panel-b" else panel.icon_state = "solar_panel" -#if DM_VERSION <= 512 - . += new /mutable_appearance(panel) -#endif /obj/machinery/power/solar/proc/queue_turn(azimuth) needs_to_turn = TRUE @@ -346,11 +343,10 @@ else . += mutable_appearance(icon, icon_screen) -/obj/machinery/power/solar_control/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/power/solar_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "solar_control", name, 380, 230, master_ui, state) + ui = new(user, src, "SolarControl", name) ui.open() /obj/machinery/power/solar_control/ui_data() @@ -481,8 +477,12 @@ // /obj/item/paper/guides/jobs/engi/solars - name = "paper- 'Going green! Setup your own solar array instructions.'" - info = "

    Welcome

    At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or plasma! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array.

    You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!

    Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the sun's movements and to send commands to the solar panels to change direction with the sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker.

    Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.

    That's all to it, be safe, be green!

    " + info = {" +# Welcome! +At greencorps we love the environment, and space. With this package you are able to help mother nature and produce energy without any usage of fossil fuel or plasma! Singularity energy is dangerous while solar energy is safe, which is why it's better. Now here is how you setup your own solar array. +You can make a solar panel by wrenching the solar assembly onto a cable node. Adding a glass panel, reinforced or regular glass will do, will finish the construction of your solar panel. It is that easy!

    Now after setting up 19 more of these solar panels you will want to create a solar tracker to keep track of our mother nature's gift, the sun. These are the same steps as before except you insert the tracker equipment circuit into the assembly before performing the final step of adding the glass. You now have a tracker! Now the last step is to add a computer to calculate the sun's movements and to send commands to the solar panels to change direction with the sun. Setting up the solar computer is the same as setting up any computer, so you should have no trouble in doing that. You do need to put a wire node under the computer, and the wire needs to be connected to the tracker. +Congratulations, you should have a working solar array. If you are having trouble, here are some tips. Make sure all solar equipment are on a cable node, even the computer. You can always deconstruct your creations if you make a mistake.

    That's all to it, be safe, be green! +"} #undef SOLAR_GEN_RATE #undef OCCLUSION_DISTANCE diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 1350c36348..fd8f900552 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -2,34 +2,54 @@ //Please do not bother them with bugs from this port, however, as it has been modified quite a bit. //Modifications include removing the world-ending full supermatter variation, and leaving only the shard. +//Zap constants, speeds up targeting + +#define BIKE (COIL + 1) +#define COIL (ROD + 1) +#define ROD (LIVING + 1) +#define LIVING (MACHINERY + 1) +#define MACHINERY (OBJECT + 1) +#define OBJECT (LOWEST + 1) +#define LOWEST (1) + #define PLASMA_HEAT_PENALTY 15 // Higher == Bigger heat and waste penalty from having the crystal surrounded by this gas. Negative numbers reduce penalty. #define OXYGEN_HEAT_PENALTY 1 -#define CO2_HEAT_PENALTY 0.1 #define PLUOXIUM_HEAT_PENALTY -1 #define TRITIUM_HEAT_PENALTY 10 +#define CO2_HEAT_PENALTY 0.1 #define NITROGEN_HEAT_PENALTY -1.5 #define BZ_HEAT_PENALTY 5 +#define H2O_HEAT_PENALTY 8 +//#define FREON_HEAT_PENALTY -10 //very good heat absorbtion and less plasma and o2 generation +//#define HYDROGEN_HEAT_PENALTY 10 // similar heat penalty as tritium (dangerous) + +//All of these get divided by 10-bzcomp * 5 before having 1 added and being multiplied with power to determine rads +//Keep the negative values here above -10 and we won't get negative rads #define OXYGEN_TRANSMIT_MODIFIER 1.5 //Higher == Bigger bonus to power generation. #define PLASMA_TRANSMIT_MODIFIER 4 #define BZ_TRANSMIT_MODIFIER -2 +#define TRITIUM_TRANSMIT_MODIFIER 30 //We divide by 10, so this works out to 3 +#define PLUOXIUM_TRANSMIT_MODIFIER -5 //Should halve the power output +#define H2O_TRANSMIT_MODIFIER 2 +//#define HYDROGEN_TRANSMIT_MODIFIER 25 //increase the radiation emission, but less than the trit (2.5) -#define TRITIUM_RADIOACTIVITY_MODIFIER 3 //Higher == Crystal spews out more radiation -#define BZ_RADIOACTIVITY_MODIFIER 5 -#define PLUOXIUM_RADIOACTIVITY_MODIFIER -2 +#define BZ_RADIOACTIVITY_MODIFIER 5 //Improves the effect of transmit modifiers #define N2O_HEAT_RESISTANCE 6 //Higher == Gas makes the crystal more resistant against heat damage. #define PLUOXIUM_HEAT_RESISTANCE 3 +//#define HYDROGEN_HEAT_RESISTANCE 2 // just a bit of heat resistance to spice it up #define POWERLOSS_INHIBITION_GAS_THRESHOLD 0.20 //Higher == Higher percentage of inhibitor gas needed before the charge inertia chain reaction effect starts. #define POWERLOSS_INHIBITION_MOLE_THRESHOLD 20 //Higher == More moles of the gas are needed before the charge inertia chain reaction effect starts. //Scales powerloss inhibition down until this amount of moles is reached #define POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD 500 //bonus powerloss inhibition boost if this amount of moles is reached -#define MOLE_PENALTY_THRESHOLD 1800 //Higher == Shard can absorb more moles before triggering the high mole penalties. +#define MOLE_PENALTY_THRESHOLD 1800 //Above this value we can get lord singulo and independent mol damage, below it we can heal damage #define MOLE_HEAT_PENALTY 350 //Heat damage scales around this. Too hot setups with this amount of moles do regular damage, anything above and below is scaled -#define POWER_PENALTY_THRESHOLD 5000 //Higher == Engine can generate more power before triggering the high power penalties. -#define SEVERE_POWER_PENALTY_THRESHOLD 7000 //Same as above, but causes more dangerous effects -#define CRITICAL_POWER_PENALTY_THRESHOLD 12000 //Even more dangerous effects, threshold for tesla delamination +//Along with damage_penalty_point, makes flux anomalies. +#define POWER_PENALTY_THRESHOLD 5000 //The cutoff on power properly doing damage, pulling shit around, and delamming into a tesla. Low chance of pyro anomalies, +2 bolts of electricity +#define SEVERE_POWER_PENALTY_THRESHOLD 7000 //+1 bolt of electricity, allows for gravitational anomalies, and higher chances of pyro anomalies +#define CRITICAL_POWER_PENALTY_THRESHOLD 9000 //+1 bolt of electricity. #define HEAT_PENALTY_THRESHOLD 40 //Higher == Crystal safe operational temperature is higher. #define DAMAGE_HARDCAP 0.002 #define DAMAGE_INCREASE_MULTIPLIER 0.25 @@ -66,6 +86,13 @@ #define SUPERMATTER_COUNTDOWN_TIME 30 SECONDS +///to prevent accent sounds from layering +#define SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN 2 SECONDS + +#define DEFAULT_ZAP_ICON_STATE "sm_arc" +#define SLIGHTLY_CHARGED_ZAP_ICON_STATE "sm_arc_supercharged" +#define OVER_9000_ZAP_ICON_STATE "sm_arc_dbz_referance" //Witty I know + GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /obj/machinery/power/supermatter_crystal @@ -76,89 +103,183 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) density = TRUE anchored = TRUE flags_1 = PREVENT_CONTENTS_EXPLOSION_1 - var/uid = 1 - var/static/gl_uid = 1 light_range = 4 resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF - critical_machine = TRUE + ///The id of our supermatter + var/uid = 1 + ///The amount of supermatters that have been created this round + var/static/gl_uid = 1 + ///Tracks the bolt color we are using + var/zap_icon = DEFAULT_ZAP_ICON_STATE + ///The portion of the gasmix we're on that we should remove var/gasefficency = 0.15 - + ///Used for changing icon states for diff base sprites var/base_icon_state = "darkmatter" + ///Are we exploding? var/final_countdown = FALSE + ///The amount of damage we have currently var/damage = 0 + ///The damage we had before this cycle. Used to limit the damage we can take each cycle, and for safe_alert var/damage_archived = 0 + ///Our "Shit is no longer fucked" message. We send it when damage is less then damage_archived var/safe_alert = "Crystalline hyperstructure returning to safe operating parameters." + ///The point at which we should start sending messeges about the damage to the engi channels. var/warning_point = 50 + ///The alert we send when we've reached warning_point var/warning_alert = "Danger! Crystal hyperstructure integrity faltering!" - var/damage_penalty_point = 550 + ///The point at which we start sending messages to the common channel var/emergency_point = 700 + ///The alert we send when we've reached emergency_point var/emergency_alert = "CRYSTAL DELAMINATION IMMINENT." + ///The point at which we delam var/explosion_point = 900 + ///When we pass this amount of damage we start shooting bolts + var/damage_penalty_point = 550 - var/emergency_issued = FALSE - + ///A scaling value that affects the severity of explosions. var/explosion_power = 35 - var/temp_factor = 30 - - var/lastwarning = 0 // Time in 1/10th of seconds since the last sent warning + ///Time in 1/10th of seconds since the last sent warning + var/lastwarning = 0 + ///Refered to as eer on the moniter. This value effects gas output, heat, damage, and radiation. var/power = 0 - - var/n2comp = 0 // raw composition of each gas in the chamber, ranges from 0 to 1 - - var/plasmacomp = 0 - var/o2comp = 0 - var/co2comp = 0 - var/n2ocomp = 0 - var/pluoxiumcomp = 0 - var/tritiumcomp = 0 - var/bzcomp = 0 - - var/pluoxiumbonus = 0 - + ///Determines the rate of positve change in gas comp values + var/gas_change_rate = 0.05 + ///The list of gases we will be interacting with in process_atoms() + var/list/gases_we_care_about = list( + /datum/gas/oxygen, + /datum/gas/water_vapor, + /datum/gas/plasma, + /datum/gas/carbon_dioxide, + /datum/gas/nitrous_oxide, + /datum/gas/nitrogen, + /datum/gas/pluoxium, + /datum/gas/tritium, + /datum/gas/bz, +// /datum/gas/freon, +// /datum/gas/hydrogen, + ) + ///The list of gases mapped against their current comp. We use this to calculate different values the supermatter uses, like power or heat resistance. It doesn't perfectly match the air around the sm, instead moving up at a rate determined by gas_change_rate per call. Ranges from 0 to 1 + var/list/gas_comp = list( + /datum/gas/oxygen = 0, + /datum/gas/water_vapor = 0, + /datum/gas/plasma = 0, + /datum/gas/carbon_dioxide = 0, + /datum/gas/nitrous_oxide = 0, + /datum/gas/nitrogen = 0, + /datum/gas/pluoxium = 0, + /datum/gas/tritium = 0, + /datum/gas/bz = 0, +// /datum/gas/freon = 0, +// /datum/gas/hydrogen = 0, + ) + ///The list of gases mapped against their transmit values. We use it to determine the effect different gases have on radiation + var/list/gas_trans = list( + /datum/gas/oxygen = OXYGEN_TRANSMIT_MODIFIER, + /datum/gas/water_vapor = H2O_TRANSMIT_MODIFIER, + /datum/gas/plasma = PLASMA_TRANSMIT_MODIFIER, + /datum/gas/pluoxium = PLUOXIUM_TRANSMIT_MODIFIER, + /datum/gas/tritium = TRITIUM_TRANSMIT_MODIFIER, + /datum/gas/bz = BZ_TRANSMIT_MODIFIER, +// /datum/gas/hydrogen = HYDROGEN_TRANSMIT_MODIFIER, + ) + ///The list of gases mapped against their heat penaltys. We use it to determin molar and heat output + var/list/gas_heat = list( + /datum/gas/oxygen = OXYGEN_HEAT_PENALTY, + /datum/gas/water_vapor = H2O_HEAT_PENALTY, + /datum/gas/plasma = PLASMA_HEAT_PENALTY, + /datum/gas/carbon_dioxide = CO2_HEAT_PENALTY, + /datum/gas/nitrogen = NITROGEN_HEAT_PENALTY, + /datum/gas/pluoxium = PLUOXIUM_HEAT_PENALTY, + /datum/gas/tritium = TRITIUM_HEAT_PENALTY, + /datum/gas/bz = BZ_HEAT_PENALTY, +// /datum/gas/freon = FREON_HEAT_PENALTY, +// /datum/gas/hydrogen = HYDROGEN_HEAT_PENALTY, + ) + ///The list of gases mapped against their heat resistance. We use it to moderate heat damage. + var/list/gas_resist = list( + /datum/gas/nitrous_oxide = N2O_HEAT_RESISTANCE, + /datum/gas/pluoxium = PLUOXIUM_HEAT_RESISTANCE, +// /datum/gas/hydrogen = HYDROGEN_HEAT_RESISTANCE, + ) + ///The list of gases mapped against their powermix ratio + var/list/gas_powermix = list( + /datum/gas/oxygen = 1, + /datum/gas/water_vapor = 1, + /datum/gas/plasma = 1, + /datum/gas/carbon_dioxide = 1, + /datum/gas/nitrogen = -1, + /datum/gas/pluoxium = -1, + /datum/gas/tritium = 1, + /datum/gas/bz = 1, +// /datum/gas/freon = -1, +// /datum/gas/hydrogen = 1, + ) + ///The last air sample's total molar count, will always be above or equal to 0 var/combined_gas = 0 + ///Affects the power gain the sm experiances from heat var/gasmix_power_ratio = 0 + ///Affects the amount of o2 and plasma the sm outputs, along with the heat it makes. var/dynamic_heat_modifier = 1 + ///Affects the amount of damage and minimum point at which the sm takes heat damage var/dynamic_heat_resistance = 1 + ///Uses powerloss_dynamic_scaling and combined_gas to lessen the effects of our powerloss functions var/powerloss_inhibitor = 1 + ///Based on co2 percentage, slowly moves between 0 and 1. We use it to calc the powerloss_inhibitor var/powerloss_dynamic_scaling= 0 + ///Affects the amount of radiation the sm makes. We multiply this with power to find the rads. var/power_transmission_bonus = 0 + ///Used to increase or lessen the amount of damage the sm takes from heat based on molar counts. var/mole_heat_penalty = 0 - - + ///Takes the energy throwing things into the sm generates and slowly turns it into actual power var/matter_power = 0 + ///The cutoff for a bolt jumping, grows with heat, lowers with higher mol count, + var/zap_cutoff = 1500 + ///How much the bullets damage should be multiplied by when it is added to the internal variables + var/bullet_energy = 2 + ///How much hallucination should we produce per unit of power? + var/hallucination_power = 0.1 - //Temporary values so that we can optimize this - //How much the bullets damage should be multiplied by when it is added to the internal variables - var/config_bullet_energy = 2 - //How much of the power is left after processing is finished? -// var/config_power_reduction_per_tick = 0.5 - //How much hallucination should it produce per unit of power? - var/config_hallucination_power = 0.1 - + ///Our internal radio var/obj/item/radio/radio + ///The key our internal radio uses var/radio_key = /obj/item/encryptionkey/headset_eng + ///The engineering channel var/engineering_channel = "Engineering" + ///The common channel var/common_channel = null - //for logging + ///Boolean used for logging if we've been powered var/has_been_powered = FALSE + ///Boolean used for logging if we've passed the emergency point var/has_reached_emergency = FALSE - // For making hugbox supermatter - var/takes_damage = TRUE - var/produces_gas = TRUE + ///An effect we show to admins and ghosts the percentage of delam we're at var/obj/effect/countdown/supermatter/countdown + ///Used along with a global var to track if we can give out the sm sliver stealing objective var/is_main_engine = FALSE - + ///Our soundloop var/datum/looping_sound/supermatter/soundloop - + ///Can it be moved? var/moveable = FALSE + ///cooldown tracker for accent sounds + var/last_accent_sound = 0 + + //For making hugbox supermatters + ///Disables all methods of taking damage + var/takes_damage = TRUE + ///Disables the production of gas, and pretty much any handling of it we do. + var/produces_gas = TRUE + ///Disables power changes + var/power_changes = TRUE + ///Disables the sm's proccessing totally. + var/processes = TRUE + /obj/machinery/power/supermatter_crystal/Initialize() . = ..() uid = gl_uid++ @@ -174,6 +295,9 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(is_main_engine) GLOB.main_supermatter_engine = src + AddElement(/datum/element/bsa_blocker) + RegisterSignal(src, COMSIG_ATOM_BSA_BEAM, .proc/call_explode) + soundloop = new(list(src), TRUE) /obj/machinery/power/supermatter_crystal/Destroy() @@ -184,12 +308,11 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) QDEL_NULL(countdown) if(is_main_engine && GLOB.main_supermatter_engine == src) GLOB.main_supermatter_engine = null - QDEL_NULL(soundloop) return ..() /obj/machinery/power/supermatter_crystal/examine(mob/user) . = ..() - if (iscarbon(user)) + if (istype(user, /mob/living/carbon)) var/mob/living/carbon/C = user if (!istype(C.glasses, /obj/item/clothing/glasses/meson) && (get_dist(user, src) < HALLUCINATION_RANGE(power))) . += "You get headaches just from looking at it." @@ -202,19 +325,20 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(!air) return SUPERMATTER_ERROR - if(get_integrity() < SUPERMATTER_DELAM_PERCENT) + var/integrity = get_integrity() + if(integrity < SUPERMATTER_DELAM_PERCENT) return SUPERMATTER_DELAMINATING - if(get_integrity() < SUPERMATTER_EMERGENCY_PERCENT) + if(integrity < SUPERMATTER_EMERGENCY_PERCENT) return SUPERMATTER_EMERGENCY - if(get_integrity() < SUPERMATTER_DANGER_PERCENT) + if(integrity < SUPERMATTER_DANGER_PERCENT) return SUPERMATTER_DANGER - if((get_integrity() < SUPERMATTER_WARNING_PERCENT) || (air.temperature > CRITICAL_TEMPERATURE)) + if((integrity < SUPERMATTER_WARNING_PERCENT) || (air.return_temperature() > CRITICAL_TEMPERATURE)) return SUPERMATTER_WARNING - if(air.temperature > (CRITICAL_TEMPERATURE * 0.8)) + if(air.return_temperature() > (CRITICAL_TEMPERATURE * 0.8)) return SUPERMATTER_NOTIFY if(power > 5) @@ -238,23 +362,26 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) integrity = integrity < 0 ? 0 : integrity return integrity +/obj/machinery/power/supermatter_crystal/update_overlays() + . = ..() + if(final_countdown) + . += "casuality_field" + /obj/machinery/power/supermatter_crystal/proc/countdown() set waitfor = FALSE if(final_countdown) // We're already doing it go away return final_countdown = TRUE - - var/image/causality_field = image(icon, null, "causality_field") - add_overlay(causality_field, TRUE) + update_icon() 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_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) - cut_overlay(causality_field, TRUE) final_countdown = FALSE + update_icon() return else if((i % 50) != 0 && i > 50) // A message once every 5 seconds until the final 5 seconds which count down individualy sleep(10) @@ -287,48 +414,65 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "delam", /datum/mood_event/delam) if(combined_gas > MOLE_PENALTY_THRESHOLD) investigate_log("has collapsed into a singularity.", INVESTIGATE_SUPERMATTER) - if(T) + if(T) //If something fucks up we blow anyhow. This fix is 4 years old and none ever said why it's here. help. var/obj/singularity/S = new(T) S.energy = 800 S.consume(src) - else - investigate_log("has exploded.", INVESTIGATE_SUPERMATTER) - explosion(get_turf(T), explosion_power * max(gasmix_power_ratio, 0.205) * 0.5 , explosion_power * max(gasmix_power_ratio, 0.205) + 2, explosion_power * max(gasmix_power_ratio, 0.205) + 4 , explosion_power * max(gasmix_power_ratio, 0.205) + 6, 1, 1) - if(power > POWER_PENALTY_THRESHOLD) - investigate_log("has spawned additional energy balls.", INVESTIGATE_SUPERMATTER) + return //No boom for me sir + else if(power > POWER_PENALTY_THRESHOLD) + investigate_log("has spawned additional energy balls.", INVESTIGATE_SUPERMATTER) + if(T) var/obj/singularity/energy_ball/E = new(T) E.energy = power - qdel(src) + investigate_log("has exploded.", INVESTIGATE_SUPERMATTER) + //Dear mappers, balance the sm max explosion radius to 17.5, 37, 39, 41 + explosion(get_turf(T), explosion_power * max(gasmix_power_ratio, 0.205) * 0.5 , explosion_power * max(gasmix_power_ratio, 0.205) + 2, explosion_power * max(gasmix_power_ratio, 0.205) + 4 , explosion_power * max(gasmix_power_ratio, 0.205) + 6, 1, 1) + qdel(src) -/obj/machinery/power/supermatter_crystal/proc/consume_turf(turf/T) - var/oldtype = T.type - var/turf/newT = T.ScrapeAway() - if(newT.type == oldtype) - return - playsound(T, 'sound/effects/supermatter.ogg', 50, 1) - T.visible_message("[T] smacks into [src] and rapidly flashes to ash.",\ - "You hear a loud crack as you are washed with a wave of heat.") - CALCULATE_ADJACENT_TURFS(T) + +//this is here to eat arguments +/obj/machinery/power/supermatter_crystal/proc/call_explode() + explode() /obj/machinery/power/supermatter_crystal/process_atmos() + if(!processes) //Just fuck me up bro + return var/turf/T = loc - if(isnull(T)) // We have a null turf...something is wrong, stop processing this entity. + if(isnull(T))// We have a null turf...something is wrong, stop processing this entity. return PROCESS_KILL - if(!istype(T)) //We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now. + if(!istype(T))//We are in a crate or somewhere that isn't turf, if we return to turf resume processing but for now. return //Yeah just stop. - if(istype(T, /turf/closed)) - consume_turf(T) + if(isclosedturf(T)) + var/turf/did_it_melt = T.Melt() + if(!isclosedturf(did_it_melt)) //In case some joker finds way to place these on indestructible walls + visible_message("[src] melts through [T]!") + return + + //We vary volume by power, and handle OH FUCK FUSION IN COOLING LOOP noises. if(power) - soundloop.volume = min(40, (round(power/100)/50)+1) // 5 +1 volume per 20 power. 2500 power is max + soundloop.volume = clamp((50 + (power / 50)), 50, 100) + if(damage >= 300) + soundloop.mid_sounds = list('sound/machines/sm/loops/delamming.ogg' = 1) + else + soundloop.mid_sounds = list('sound/machines/sm/loops/calm.ogg' = 1) + + //We play delam/neutral sounds at a rate determined by power and damage + if(last_accent_sound < world.time && prob(20)) + var/aggression = min(((damage / 800) * (power / 2500)), 1.0) * 100 + if(damage >= 300) + playsound(src, "smdelam", max(50, aggression), FALSE, 10) + else + playsound(src, "smcalm", max(50, aggression), FALSE, 10) + var/next_sound = round((100 - aggression) * 5) + last_accent_sound = world.time + max(SUPERMATTER_ACCENT_SOUND_MIN_COOLDOWN, next_sound) //Ok, get the air from the turf var/datum/gas_mixture/env = T.return_air() var/datum/gas_mixture/removed - if(produces_gas) //Remove gas from surrounding area removed = env.remove(gasefficency * env.total_moles()) @@ -336,141 +480,240 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) // Pass all the gas related code an empty gas container removed = new() damage_archived = damage + + /******** + EXPERIMENTAL, HUGBOXY AS HELL CITADEL CHANGES: Even in a vaccum, update gas composition and modifiers. + This means that the SM will usually have a very small explosion if it ends up being breached to space, + and CO2 tesla delaminations basically require multiple grounding rods to stabilize it long enough to not have it vent. + *********/ + if(!removed || !removed.total_moles() || isspaceturf(T)) //we're in space or there is no gas to process if(takes_damage) damage += max((power / 1000) * DAMAGE_INCREASE_MULTIPLIER, 0.1) // always does at least some damage + combined_gas = max(0, combined_gas - 0.5) // Slowly wear off. + for(var/gasID in gases_we_care_about) + gas_comp[gasID] = max(0, gas_comp[gasID] - 0.05) //slowly ramp down else if(takes_damage) //causing damage - damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.temperature - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0) + //Due to DAMAGE_INCREASE_MULTIPLIER, we only deal one 4th of the damage the statements otherwise would cause + + //((((some value between 0.5 and 1 * temp - ((273.15 + 40) * some values between 1 and 10)) * some number between 0.25 and knock your socks off / 150) * 0.25 + //Heat and mols account for each other, a lot of hot mols are more damaging then a few + //Mols start to have a positive effect on damage after 350 + damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.return_temperature() - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0) + //Power only starts affecting damage when it is above 5000 damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0) + //Molar count only starts affecting damage when it is above 1800 damage = max(damage + (max(combined_gas - MOLE_PENALTY_THRESHOLD, 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0) + //There might be a way to integrate healing and hurting via heat //healing damage if(combined_gas < MOLE_PENALTY_THRESHOLD) - damage = max(damage + (min(removed.temperature - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150 ), 0) + //Only has a net positive effect when the temp is below 313.15, heals up to 2 damage. Psycologists increase this temp min by up to 45 + damage = max(damage + (min(removed.return_temperature() - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150), 0) - //capping damage - damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point),damage) - if(damage > damage_archived && prob(10)) - playsound(get_turf(src), 'sound/effects/empulse.ogg', 50, 1) + //caps damage rate - //calculating gas related values - combined_gas = max(removed.total_moles(), 0) + //Takes the lower number between archived damage + (1.8) and damage + //This means we can only deal 1.8 damage per function call + damage = min(damage_archived + (DAMAGE_HARDCAP * explosion_point), damage) - plasmacomp = max(removed.gases[/datum/gas/plasma]/combined_gas, 0) - o2comp = max(removed.gases[/datum/gas/oxygen]/combined_gas, 0) - co2comp = max(removed.gases[/datum/gas/carbon_dioxide]/combined_gas, 0) - pluoxiumcomp = max(removed.gases[/datum/gas/pluoxium]/combined_gas, 0) - tritiumcomp = max(removed.gases[/datum/gas/tritium]/combined_gas, 0) - bzcomp = max(removed.gases[/datum/gas/bz]/combined_gas, 0) + //calculating gas related values + //Wanna know a secret? See that max() to zero? it's used for error checking. If we get a mol count in the negative, we'll get a divide by zero error + combined_gas = max(removed.total_moles(), 0) - n2ocomp = max(removed.gases[/datum/gas/nitrous_oxide]/combined_gas, 0) - n2comp = max(removed.gases[/datum/gas/nitrogen]/combined_gas, 0) + //This is more error prevention, according to all known laws of atmos, gas_mix.remove() should never make negative mol values. + //But this is tg - if(pluoxiumcomp >= 0.15) - pluoxiumbonus = 1 //makes pluoxium only work at 15%+ - else - pluoxiumbonus = 0 + //Lets get the proportions of the gasses in the mix and then slowly move our comp to that value + //Can cause an overestimation of mol count, should stabalize things though. + //Prevents huge bursts of gas/heat when a large amount of something is introduced + //They range between 0 and 1 + for(var/gasID in gases_we_care_about) + gas_comp[gasID] += clamp(max(removed.get_moles(gasID)/combined_gas, 0) - gas_comp[gasID], -1, gas_change_rate) - gasmix_power_ratio = min(max(plasmacomp + o2comp + co2comp + tritiumcomp + bzcomp - pluoxiumcomp - n2comp, 0), 1) + var/list/heat_mod = gases_we_care_about.Copy() + var/list/transit_mod = gases_we_care_about.Copy() + var/list/resistance_mod = gases_we_care_about.Copy() - dynamic_heat_modifier = max((plasmacomp * PLASMA_HEAT_PENALTY) + (o2comp * OXYGEN_HEAT_PENALTY) + (co2comp * CO2_HEAT_PENALTY) + (tritiumcomp * TRITIUM_HEAT_PENALTY) + ((pluoxiumcomp * PLUOXIUM_HEAT_PENALTY) * pluoxiumbonus) + (n2comp * NITROGEN_HEAT_PENALTY) + (bzcomp * BZ_HEAT_PENALTY), 0.5) - dynamic_heat_resistance = max((n2ocomp * N2O_HEAT_RESISTANCE) + ((pluoxiumcomp * PLUOXIUM_HEAT_RESISTANCE) * pluoxiumbonus), 1) + //We're concerned about pluoxium being too easy to abuse at low percents, so we make sure there's a substantial amount. + var/pluoxiumbonus = (gas_comp[/datum/gas/pluoxium] >= 0.15) //makes pluoxium only work at 15%+ + var/h2obonus = 1 - (gas_comp[/datum/gas/water_vapor] * 0.25)//At max this value should be 0.75 +// var/freonbonus = (gas_comp[/datum/gas/freon] <= 0.03) //Let's just yeet power output if this shit is high - power_transmission_bonus = max((plasmacomp * PLASMA_TRANSMIT_MODIFIER) + (o2comp * OXYGEN_TRANSMIT_MODIFIER) + (bzcomp * BZ_TRANSMIT_MODIFIER), 0) + heat_mod[/datum/gas/pluoxium] = pluoxiumbonus + transit_mod[/datum/gas/pluoxium] = pluoxiumbonus + resistance_mod[/datum/gas/pluoxium] = pluoxiumbonus - //more moles of gases are harder to heat than fewer, so let's scale heat damage around them - mole_heat_penalty = max(combined_gas / MOLE_HEAT_PENALTY, 0.25) + //No less then zero, and no greater then one, we use this to do explosions and heat to power transfer + //Be very careful with modifing this var by large amounts, and for the love of god do not push it past 1 + gasmix_power_ratio = 0 + for(var/gasID in gas_powermix) + gasmix_power_ratio += gas_comp[gasID] * gas_powermix[gasID] + gasmix_power_ratio = clamp(gasmix_power_ratio, 0, 1) - if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && co2comp > POWERLOSS_INHIBITION_GAS_THRESHOLD) - powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(co2comp - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1) - else - powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05,0, 1) - powerloss_inhibitor = clamp(1-(powerloss_dynamic_scaling * clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD,1 ,1.5)),0 ,1) + //Minimum value of -10, maximum value of 23. Effects plasma and o2 output and the output heat + dynamic_heat_modifier = 0 + for(var/gasID in gas_heat) + dynamic_heat_modifier += gas_comp[gasID] * gas_heat[gasID] * (isnull(heat_mod[gasID]) ? 1 : heat_mod[gasID]) + dynamic_heat_modifier *= h2obonus + dynamic_heat_modifier = max(dynamic_heat_modifier, 0.5) - if(matter_power) - var/removed_matter = max(matter_power/MATTER_POWER_CONVERSION, 40) - power = max(power + removed_matter, 0) - matter_power = max(matter_power - removed_matter, 0) + //Value between 1 and 10. Effects the damage heat does to the crystal + dynamic_heat_resistance = 0 + for(var/gasID in gas_resist) + dynamic_heat_resistance += gas_comp[gasID] * gas_resist[gasID] * (isnull(resistance_mod[gasID]) ? 1 : resistance_mod[gasID]) + dynamic_heat_resistance = max(dynamic_heat_resistance, 1) - var/temp_factor = 50 + //Value between -5 and 30, used to determine radiation output as it concerns things like collectors. + power_transmission_bonus = 0 + for(var/gasID in gas_trans) + power_transmission_bonus += gas_comp[gasID] * gas_trans[gasID] * (isnull(transit_mod[gasID]) ? 1 : transit_mod[gasID]) + power_transmission_bonus *= h2obonus - if(gasmix_power_ratio > 0.8) - // with a perfect gas mix, make the power less based on heat - icon_state = "[base_icon_state]_glow" - else - // in normal mode, base the produced energy around the heat - temp_factor = 30 - icon_state = base_icon_state + //more moles of gases are harder to heat than fewer, so let's scale heat damage around them + mole_heat_penalty = max(combined_gas / MOLE_HEAT_PENALTY, 0.25) - power = max( (removed.temperature * temp_factor / T0C) * gasmix_power_ratio + power, 0) //Total laser power plus an overload + //Ramps up or down in increments of 0.02 up to the proportion of co2 + //Given infinite time, powerloss_dynamic_scaling = co2comp + //Some value between 0 and 1 + if (combined_gas > POWERLOSS_INHIBITION_MOLE_THRESHOLD && gas_comp[/datum/gas/carbon_dioxide] > POWERLOSS_INHIBITION_GAS_THRESHOLD) //If there are more then 20 mols, and more then 20% co2 + powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling + clamp(gas_comp[/datum/gas/carbon_dioxide] - powerloss_dynamic_scaling, -0.02, 0.02), 0, 1) + else + powerloss_dynamic_scaling = clamp(powerloss_dynamic_scaling - 0.05, 0, 1) + //Ranges from 0 to 1(1-(value between 0 and 1 * ranges from 1 to 1.5(mol / 500))) + //We take the mol count, and scale it to be our inhibitor + powerloss_inhibitor = clamp(1-(powerloss_dynamic_scaling * clamp(combined_gas/POWERLOSS_INHIBITION_MOLE_BOOST_THRESHOLD, 1, 1.5)), 0, 1) - if(prob(50)) - radiation_pulse(src, power * (1 + (tritiumcomp * TRITIUM_RADIOACTIVITY_MODIFIER) + ((pluoxiumcomp * PLUOXIUM_RADIOACTIVITY_MODIFIER) * pluoxiumbonus) * (power_transmission_bonus/(10-(bzcomp * BZ_RADIOACTIVITY_MODIFIER))))) // Rad Modifiers BZ(500%), Tritium(300%), and Pluoxium(-200%) - if(bzcomp >= 0.4 && prob(30 * bzcomp)) - fire_nuclear_particle() // Start to emit radballs at a maximum of 30% chance per tick + //Releases stored power into the general pool + //We get this by consuming shit or being scalpeled + if(matter_power && power_changes) + //We base our removed power off one 10th of the matter_power. + var/removed_matter = max(matter_power/MATTER_POWER_CONVERSION, 40) + //Adds at least 40 power + power = max(power + removed_matter, 0) + //Removes at least 40 matter power + matter_power = max(matter_power - removed_matter, 0) - var/device_energy = power * REACTION_POWER_MODIFIER + var/temp_factor = 50 + if(gasmix_power_ratio > 0.8) + //with a perfect gas mix, make the power more based on heat + icon_state = "[base_icon_state]_glow" + else + //in normal mode, power is less effected by heat + temp_factor = 30 + icon_state = base_icon_state - //To figure out how much temperature to add each tick, consider that at one atmosphere's worth - //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature - //that the device energy is around 2140. At that stage, we don't want too much heat to be put out - //Since the core is effectively "cold" + //if there is more pluox and n2 then anything else, we receive no power increase from heat + if(power_changes) + power = max((removed.return_temperature() * temp_factor / T0C) * gasmix_power_ratio + power, 0) - //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock - //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall. - removed.temperature += ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER) + if(prob(50)) + //(1 + (tritRad + pluoxDampen * bzDampen * o2Rad * plasmaRad / (10 - bzrads))) * freonbonus + radiation_pulse(src, power * max(0, (1 + (power_transmission_bonus/(10-(gas_comp[/datum/gas/bz] * BZ_RADIOACTIVITY_MODIFIER)))) * 1))//freonbonus))// RadModBZ(500%) + if(gas_comp[/datum/gas/bz] >= 0.4 && prob(30 * gas_comp[/datum/gas/bz])) + src.fire_nuclear_particle() // Start to emit radballs at a maximum of 30% chance per tick - removed.temperature = max(0, min(removed.temperature, 2500 * dynamic_heat_modifier)) + //Power * 0.55 * a value between 1 and 0.8 + var/device_energy = power * REACTION_POWER_MODIFIER - //Calculate how much gas to release - removed.gases[/datum/gas/plasma] += max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0) + //To figure out how much temperature to add each tick, consider that at one atmosphere's worth + //of pure oxygen, with all four lasers firing at standard energy and no N2 present, at room temperature + //that the device energy is around 2140. At that stage, we don't want too much heat to be put out + //Since the core is effectively "cold" - removed.gases[/datum/gas/oxygen] += max(((device_energy + removed.temperature * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0) + //Also keep in mind we are only adding this temperature to (efficiency)% of the one tile the rock + //is on. An increase of 4*C @ 25% efficiency here results in an increase of 1*C / (#tilesincore) overall. + //Power * 0.55 * (some value between 1.5 and 23) / 5 + removed.set_temperature(removed.return_temperature() + ((device_energy * dynamic_heat_modifier) / THERMAL_RELEASE_MODIFIER)) + //We can only emit so much heat, that being 57500 + removed.set_temperature(max(0, min(removed.return_temperature(), 2500 * dynamic_heat_modifier))) - if(produces_gas) - env.merge(removed) - air_update_turf() + //Calculate how much gas to release + //Varies based on power and gas content + removed.adjust_moles(/datum/gas/plasma, max((device_energy * dynamic_heat_modifier) / PLASMA_RELEASE_MODIFIER, 0)) + //Varies based on power, gas content, and heat + removed.adjust_moles(/datum/gas/oxygen, max(((device_energy + removed.return_temperature() * dynamic_heat_modifier) - T0C) / OXYGEN_RELEASE_MODIFIER, 0)) - 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(produces_gas) + env.merge(removed) + air_update_turf() + + /********* + END CITADEL CHANGES + *********/ + + //Makes em go mad and accumulate rads. + for(var/mob/living/carbon/human/l in fov_viewers(src, HALLUCINATION_RANGE(power))) // 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 - l.hallucination = clamp(0, 200, l.hallucination) - + l.hallucination += power * hallucination_power * D + l.hallucination = clamp(l.hallucination, 0, 200) for(var/mob/living/l in range(src, round((power / 100) ** 0.25))) var/rads = (power / 10) * sqrt( 1 / max(get_dist(l, src),1) ) l.rad_act(rads) - power -= ((power/500)**3) * powerloss_inhibitor + //Transitions between one function and another, one we use for the fast inital startup, the other is used to prevent errors with fusion temperatures. + //Use of the second function improves the power gain imparted by using co2 + if(power_changes) + power = max(power - min(((power/500)**3) * powerloss_inhibitor, power * 0.83 * powerloss_inhibitor),0) + //After this point power is lowered + //This wraps around to the begining of the function + //Handle high power zaps/anomaly generation + if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point) //If the power is above 5000 or if the damage is above 550 + var/range = 4 + zap_cutoff = 1500 + if(removed && removed.return_pressure() > 0 && removed.return_temperature() > 0) + //You may be able to freeze the zapstate of the engine with good planning, we'll see + zap_cutoff = clamp(3000 - (power * (removed.total_moles()) / 10) / removed.return_temperature(), 350, 3000)//If the core is cold, it's easier to jump, ditto if there are a lot of mols + //We should always be able to zap our way out of the default enclosure + //See supermatter_zap() for more details + range = clamp(power / removed.return_pressure() * 10, 2, 7) + var/flags = ZAP_SUPERMATTER_FLAGS + var/zap_count = 0 + //Deal with power zaps + switch(power) + if(POWER_PENALTY_THRESHOLD to SEVERE_POWER_PENALTY_THRESHOLD) + zap_icon = DEFAULT_ZAP_ICON_STATE + zap_count = 2 + if(SEVERE_POWER_PENALTY_THRESHOLD to CRITICAL_POWER_PENALTY_THRESHOLD) + zap_icon = SLIGHTLY_CHARGED_ZAP_ICON_STATE + //Uncaps the zap damage, it's maxed by the input power + //Objects take damage now + flags |= (ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE) + zap_count = 3 + if(CRITICAL_POWER_PENALTY_THRESHOLD to INFINITY) + zap_icon = OVER_9000_ZAP_ICON_STATE + //It'll stun more now, and damage will hit harder, gloves are no garentee. + //Machines go boom + flags |= (ZAP_MOB_STUN | ZAP_MACHINE_EXPLOSIVE | ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE) + zap_count = 4 + //Now we deal with damage shit + if (damage > damage_penalty_point && prob(20)) + zap_count += 1 - if(power > POWER_PENALTY_THRESHOLD || damage > damage_penalty_point) + if(zap_count >= 1) + playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, TRUE, extrarange = 10) + for(var/i in 1 to zap_count) + supermatter_zap(src, range, clamp(power*2, 4000, 20000), flags) - if(power > POWER_PENALTY_THRESHOLD) - playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10) - supermatter_zap(src, 5, min(power*2, 20000)) - supermatter_zap(src, 5, min(power*2, 20000)) - if(power > SEVERE_POWER_PENALTY_THRESHOLD) - supermatter_zap(src, 5, min(power*2, 20000)) - if(power > CRITICAL_POWER_PENALTY_THRESHOLD) - supermatter_zap(src, 5, min(power*2, 20000)) - else if (damage > damage_penalty_point && prob(20)) - playsound(src.loc, 'sound/weapons/emitter2.ogg', 100, 1, extrarange = 10) - supermatter_zap(src, 5, clamp(power*2, 4000, 20000)) - - if(prob(15) && power > POWER_PENALTY_THRESHOLD) - supermatter_pull(src, power/750) if(prob(5)) supermatter_anomaly_gen(src, FLUX_ANOMALY, rand(5, 10)) if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(5) || prob(1)) supermatter_anomaly_gen(src, GRAVITATIONAL_ANOMALY, rand(5, 10)) - if(power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2) || prob(0.3) && power > POWER_PENALTY_THRESHOLD) + if((power > SEVERE_POWER_PENALTY_THRESHOLD && prob(2)) || (prob(0.3) && power > POWER_PENALTY_THRESHOLD)) supermatter_anomaly_gen(src, PYRO_ANOMALY, rand(5, 10)) + + if(prob(15)) + supermatter_pull(loc, min(power/850, 3))//850, 1700, 2550 + + //Tells the engi team to get their butt in gear if(damage > warning_point) // while the core is still damaged and it's still worth noting its status if((REALTIMEOFDAY - lastwarning) / 10 >= WARNING_DELAY) alarm() + //Oh shit it's bad, time to freak out if(damage > emergency_point) radio.talk_into(src, "[emergency_alert] Integrity: [get_integrity()]%", common_channel) lastwarning = REALTIMEOFDAY @@ -493,7 +736,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) if(combined_gas > MOLE_PENALTY_THRESHOLD) radio.talk_into(src, "Warning: Critical coolant mass reached.", engineering_channel) - + //Boom (Mind blown) if(damage > explosion_point) countdown() @@ -503,16 +746,17 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) var/turf/L = loc if(!istype(L)) return FALSE - if(!istype(Proj.firer, /obj/machinery/power/emitter)) + if(!istype(Proj.firer, /obj/machinery/power/emitter) && power_changes) investigate_log("has been hit by [Proj] fired by [key_name(Proj.firer)]", INVESTIGATE_SUPERMATTER) if(Proj.flag != "bullet") - power += Proj.damage * config_bullet_energy - if(!has_been_powered) - investigate_log("has been powered for the first time.", INVESTIGATE_SUPERMATTER) - message_admins("[src] has been powered for the first time [ADMIN_JMP(src)].") - has_been_powered = TRUE + if(power_changes) //This needs to be here I swear + power += Proj.damage * bullet_energy + if(!has_been_powered) + investigate_log("has been powered for the first time.", INVESTIGATE_SUPERMATTER) + message_admins("[src] has been powered for the first time [ADMIN_JMP(src)].") + has_been_powered = TRUE else if(takes_damage) - matter_power += Proj.damage * config_bullet_energy + matter_power += Proj.damage * bullet_energy return BULLET_ACT_HIT /obj/machinery/power/supermatter_crystal/singularity_act() @@ -529,15 +773,15 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /obj/machinery/power/supermatter_crystal/blob_act(obj/structure/blob/B) if(B && !isspaceturf(loc)) //does nothing in space - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE) damage += B.obj_integrity * 0.5 //take damage equal to 50% of remaining blob health before it tried to eat us if(B.obj_integrity > 100) B.visible_message("\The [B] strikes at \the [src] and flinches away!",\ - "You hear a loud crack as you are washed with a wave of heat.") + "You hear a loud crack as you are washed with a wave of heat.") B.take_damage(100, BURN) else B.visible_message("\The [B] strikes at \the [src] and rapidly flashes to ash.",\ - "You hear a loud crack as you are washed with a wave of heat.") + "You hear a loud crack as you are washed with a wave of heat.") Consume(B) /obj/machinery/power/supermatter_crystal/attack_tk(mob/user) @@ -546,11 +790,10 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) log_game("[key_name(C)] has been disintegrated by a telekenetic grab on a supermatter crystal.") to_chat(C, "That was a really dense idea.") C.visible_message("A bright flare of radiation is seen from [C]'s head, shortly before you hear a sickening sizzling!") + C.ghostize() var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs - rip_u.Remove() + rip_u.Remove(C) qdel(rip_u) - return - return ..() /obj/machinery/power/supermatter_crystal/attack_paw(mob/user) dust_mob(user, cause = "monkey attack") @@ -559,9 +802,14 @@ 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_verb_continuous + else + murder = S.attack_verb_continuous dust_mob(S, \ - "[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.", \ + "[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.", \ "simple animal attack") /obj/machinery/power/supermatter_crystal/attack_robot(mob/user) @@ -571,65 +819,103 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) /obj/machinery/power/supermatter_crystal/attack_ai(mob/user) return -/obj/machinery/power/supermatter_crystal/attack_hand(mob/living/user) +/obj/machinery/power/supermatter_crystal/on_attack_hand(mob/living/user) . = ..() - if(.) - return dust_mob(user, cause = "hand") /obj/machinery/power/supermatter_crystal/proc/dust_mob(mob/living/nom, vis_msg, mob_msg, cause) - if(nom.incorporeal_move || nom.status_flags & GODMODE) + if(nom.incorporeal_move || nom.status_flags & GODMODE) //try to keep supermatter sliver's + hemostat's dust conditions in sync with this too return if(!vis_msg) - vis_msg = "[nom] reaches out and touches [src], inducing a resonance... [nom.p_their()] body starts to glow and bursts into flames before flashing into ash" + vis_msg = "[nom] reaches out and touches [src], inducing a resonance... [nom.p_their()] body starts to glow and burst into flames before flashing into dust!" if(!mob_msg) mob_msg = "You reach out and touch [src]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"" if(!cause) cause = "contact" - nom.visible_message(vis_msg, mob_msg, "You hear an unearthly noise as a wave of heat washes over you.") + nom.visible_message(vis_msg, mob_msg, "You hear an unearthly noise as a wave of heat washes over you.") investigate_log("has been attacked ([cause]) by [key_name(nom)]", INVESTIGATE_SUPERMATTER) - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE) Consume(nom) /obj/machinery/power/supermatter_crystal/attackby(obj/item/W, mob/living/user, params) if(!istype(W) || (W.item_flags & ABSTRACT) || !istype(user)) return - if (istype(W, /obj/item/melee/roastingstick)) + if(istype(W, /obj/item/melee/roastingstick)) return ..() + if(istype(W, /obj/item/clothing/mask/cigarette)) + var/obj/item/clothing/mask/cigarette/cig = W + var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY) + if(clumsy) + var/which_hand = BODY_ZONE_L_ARM + if(!(user.active_hand_index % 2)) + which_hand = BODY_ZONE_R_ARM + var/obj/item/bodypart/dust_arm = user.get_bodypart(which_hand) + dust_arm.dismember() + user.visible_message("The [W] flashes out of existence on contact with \the [src], resonating with a horrible sound...",\ + "Oops! The [W] flashes out of existence on contact with \the [src], taking your arm with it! That was clumsy of you!") + playsound(src, 'sound/effects/supermatter.ogg', 150, TRUE) + Consume(dust_arm) + qdel(W) + return + if(cig.lit || user.a_intent != INTENT_HELP) + user.visible_message("A hideous sound echoes as [W] is ashed out on contact with \the [src]. That didn't seem like a good idea...") + playsound(src, 'sound/effects/supermatter.ogg', 150, TRUE) + Consume(W) + radiation_pulse(src, 150, 4) + return ..() + else + cig.light() + user.visible_message("As [user] lights \their [W] on \the [src], silence fills the room...",\ + "Time seems to slow to a crawl as you touch \the [src] with \the [W].\n\The [W] flashes alight with an eerie energy as you nonchalantly lift your hand away from \the [src]. Damn.") + playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE) + radiation_pulse(src, 50, 3) + return if(istype(W, /obj/item/scalpel/supermatter)) + var/obj/item/scalpel/supermatter/scalpel = W to_chat(user, "You carefully begin to scrape \the [src] with \the [W]...") if(W.use_tool(src, user, 60, volume=100)) - to_chat(user, "You extract a sliver from \the [src]. \The [src] begins to react violently!") - new /obj/item/nuke_core/supermatter_sliver(drop_location()) - matter_power += 200 + if (scalpel.usesLeft) + to_chat(user, "You extract a sliver from \the [src]. \The [src] begins to react violently!") + new /obj/item/nuke_core/supermatter_sliver(drop_location()) + matter_power += 800 + scalpel.usesLeft-- + if (!scalpel.usesLeft) + to_chat(user, "A tiny piece of \the [W] falls off, rendering it useless!") + else + to_chat(user, "You fail to extract a sliver from \The [src]! \the [W] isn't sharp enough anymore.") else if(user.dropItemToGround(W)) user.visible_message("As [user] touches \the [src] with \a [W], silence fills the room...",\ "You touch \the [src] with \the [W], and everything suddenly goes silent.\n\The [W] flashes into dust as you flinch away from \the [src].",\ - "Everything suddenly goes silent.") + "Everything suddenly goes silent.") investigate_log("has been attacked ([W]) by [key_name(user)]", INVESTIGATE_SUPERMATTER) Consume(W) - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE) radiation_pulse(src, 150, 4) + else if(Adjacent(user)) //if the item is stuck to the person, kill the person too instead of eating just the item. + var/vis_msg = "[user] reaches out and touches [src] with [W], inducing a resonance... [W] starts to glow briefly before the light continues up to [user]'s body. [user.p_they(TRUE)] bursts into flames before flashing into dust!" + var/mob_msg = "You reach out and touch [src] with [W]. Everything starts burning and all you can hear is ringing. Your last thought is \"That was not a wise decision.\"" + dust_mob(user, vis_msg, mob_msg) + /obj/machinery/power/supermatter_crystal/wrench_act(mob/user, obj/item/tool) + ..() if (moveable) default_unfasten_wrench(user, tool, time = 20) return TRUE /obj/machinery/power/supermatter_crystal/Bumped(atom/movable/AM) if(isliving(AM)) - AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... [AM.p_their()] body starts to glow and catch flame before flashing into ash.",\ + AM.visible_message("\The [AM] slams into \the [src] inducing a resonance... [AM.p_their()] body starts to glow and burst into flames before flashing into dust!",\ "You slam into \the [src] as your ears are filled with unearthly ringing. Your last thought is \"Oh, fuck.\"",\ - "You hear an unearthly noise as a wave of heat washes over you.") + "You hear an unearthly noise as a wave of heat washes over you.") else if(isobj(AM) && !iseffect(AM)) AM.visible_message("\The [AM] smacks into \the [src] and rapidly flashes to ash.", null,\ - "You hear a loud crack as you are washed with a wave of heat.") + "You hear a loud crack as you are washed with a wave of heat.") else return - playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, 1) - + playsound(get_turf(src), 'sound/effects/supermatter.ogg', 50, TRUE) Consume(AM) /obj/machinery/power/supermatter_crystal/intercept_zImpact(atom/movable/AM, levels) @@ -645,7 +931,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) message_admins("[src] has consumed [key_name_admin(user)] [ADMIN_JMP(src)].") investigate_log("has consumed [key_name(user)].", INVESTIGATE_SUPERMATTER) user.dust(force = TRUE) - matter_power += 200 + if(power_changes) + matter_power += 200 else if(istype(AM, /obj/singularity)) return else if(isobj(AM)) @@ -656,19 +943,29 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) message_admins("[src] has consumed [AM], [suspicion] [ADMIN_JMP(src)].") investigate_log("has consumed [AM] - [suspicion].", INVESTIGATE_SUPERMATTER) qdel(AM) - if(!iseffect(AM)) + if(!iseffect(AM) && power_changes) matter_power += 200 //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) + var/list/viewers = fov_viewers(world.view, src) 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 - L.show_message("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns.", MSG_AUDIBLE) + L.show_message("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns.", MSG_AUDIBLE) + +/obj/machinery/power/supermatter_crystal/proc/consume_turf(turf/T) + var/oldtype = T.type + var/turf/newT = T.ScrapeAway() + if(newT.type == oldtype) + return + playsound(T, 'sound/effects/supermatter.ogg', 50, 1) + T.visible_message("[T] smacks into [src] and rapidly flashes to ash.",\ + "You hear a loud crack as you are washed with a wave of heat.") + CALCULATE_ADJACENT_TURFS(T) //Do not blow up our internal radio /obj/machinery/power/supermatter_crystal/contents_explosion(severity, target) @@ -685,6 +982,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) anchored = FALSE gasefficency = 0.125 explosion_power = 12 + layer = ABOVE_MOB_LAYER moveable = TRUE /obj/machinery/power/supermatter_crystal/shard/engine @@ -699,6 +997,8 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) name = "anchored supermatter shard" takes_damage = FALSE produces_gas = FALSE + power_changes = FALSE + processes = FALSE //SHUT IT DOWN moveable = FALSE anchored = TRUE @@ -707,101 +1007,183 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal) base_icon_state = "darkmatter" icon_state = "darkmatter" -/obj/machinery/power/supermatter_crystal/proc/supermatter_pull(turf/center, pull_range = 10) - playsound(src.loc, 'sound/weapons/marauder.ogg', 100, 1, extrarange = 7) - for(var/atom/P in orange(pull_range,center)) - if(ismovable(P)) - var/atom/movable/pulled_object = P - if(ishuman(P)) - var/mob/living/carbon/human/H = P - H.apply_effect(40, EFFECT_KNOCKDOWN, 0) - if(pulled_object && !pulled_object.anchored && !ishuman(P)) - step_towards(pulled_object,center) - step_towards(pulled_object,center) - step_towards(pulled_object,center) - step_towards(pulled_object,center) +/obj/machinery/power/supermatter_crystal/proc/supermatter_pull(turf/center, pull_range = 3) + playsound(center, 'sound/weapons/marauder.ogg', 100, TRUE, extrarange = pull_range - world.view) + for(var/atom/movable/P in orange(pull_range,center)) + if((P.anchored || P.move_resist >= MOVE_FORCE_EXTREMELY_STRONG)) //move resist memes. + if(istype(P, /obj/structure/closet)) + var/obj/structure/closet/toggle = P + toggle.open() + continue + if(ismob(P)) + var/mob/M = P + if(M.mob_negates_gravity()) + continue //You can't pull someone nailed to the deck + step_towards(P,center) /obj/machinery/power/supermatter_crystal/proc/supermatter_anomaly_gen(turf/anomalycenter, type = FLUX_ANOMALY, anomalyrange = 5) var/turf/L = pick(orange(anomalyrange, anomalycenter)) if(L) switch(type) if(FLUX_ANOMALY) - var/obj/effect/anomaly/flux/A = new(L, 300) + var/obj/effect/anomaly/flux/A = new(L, 300, FALSE) A.explosive = FALSE if(GRAVITATIONAL_ANOMALY) - new /obj/effect/anomaly/grav(L, 250) + new /obj/effect/anomaly/grav(L, 250, FALSE) if(PYRO_ANOMALY) - new /obj/effect/anomaly/pyro(L, 200) + new /obj/effect/anomaly/pyro(L, 200, FALSE) -/obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart, range = 3, power) - . = zapstart.dir - if(power < 1000) +/obj/machinery/power/supermatter_crystal/proc/supermatter_zap(atom/zapstart = src, range = 5, zap_str = 4000, zap_flags = ZAP_SUPERMATTER_FLAGS, list/targets_hit = list()) + if(QDELETED(zapstart)) return + . = zapstart.dir + //If the strength of the zap decays past the cutoff, we stop + if(zap_str < zap_cutoff) + return + var/atom/target + var/target_type = LOWEST + var/list/arctargets = list() + //Making a new copy so additons further down the recursion do not mess with other arcs + //Lets put this ourself into the do not hit list, so we don't curve back to hit the same thing twice with one arc + for(var/test in oview(zapstart, range)) + if(!(zap_flags & ZAP_ALLOW_DUPLICATES) && LAZYACCESS(targets_hit, test)) + continue - var/target_atom - var/mob/living/target_mob - var/obj/machinery/target_machine - var/obj/structure/target_structure - var/list/arctargetsmob = list() - var/list/arctargetsmachine = list() - var/list/arctargetsstructure = list() + if(istype(test, /obj/vehicle/ridden/bicycle/)) + var/obj/vehicle/ridden/bicycle/bike = test + if(!(bike.obj_flags & BEING_SHOCKED) && bike.can_buckle)//God's not on our side cause he hates idiots. + if(target_type != BIKE) + arctargets = list() + arctargets += test + target_type = BIKE - if(prob(20)) //let's not hit all the engineers with every beam and/or segment of the arc - for(var/mob/living/Z in oview(zapstart, range+2)) - arctargetsmob += Z - if(arctargetsmob.len) - var/mob/living/H = pick(arctargetsmob) - var/atom/A = H - target_mob = H - target_atom = A + if(target_type > COIL) + continue - else - for(var/obj/machinery/X in oview(zapstart, range+2)) - arctargetsmachine += X - if(arctargetsmachine.len) - var/obj/machinery/M = pick(arctargetsmachine) - var/atom/A = M - target_machine = M - target_atom = A + if(istype(test, /obj/machinery/power/tesla_coil/)) + var/obj/machinery/power/tesla_coil/coil = test + if(coil.anchored && !(coil.obj_flags & BEING_SHOCKED) && !coil.panel_open && prob(70))//Diversity of death + if(target_type != COIL) + arctargets = list() + arctargets += test + target_type = COIL - else - for(var/obj/structure/Y in oview(zapstart, range+2)) - arctargetsstructure += Y - if(arctargetsstructure.len) - var/obj/structure/O = pick(arctargetsstructure) - var/atom/A = O - target_structure = O - target_atom = A + if(target_type > ROD) + continue - if(target_atom) - zapstart.Beam(target_atom, icon_state="nzcrentrs_power", time=5) - var/zapdir = get_dir(zapstart, target_atom) + if(istype(test, /obj/machinery/power/grounding_rod/)) + var/obj/machinery/power/grounding_rod/rod = test + //We're adding machine damaging effects, rods need to be surefire + if(rod.anchored && !rod.panel_open) + if(target_type != ROD) + arctargets = list() + arctargets += test + target_type = ROD + + if(target_type > LIVING) + continue + + if(istype(test, /mob/living/)) + var/mob/living/alive = test + if(!(HAS_TRAIT(alive, TRAIT_TESLA_SHOCKIMMUNE)) && !(alive.flags_1 & SHOCKED_1) && alive.stat != DEAD && prob(20))//let's not hit all the engineers with every beam and/or segment of the arc + if(target_type != LIVING) + arctargets = list() + arctargets += test + target_type = LIVING + + if(target_type > MACHINERY) + continue + + if(istype(test, /obj/machinery/)) + var/obj/machinery/machine = test + if(!(machine.obj_flags & BEING_SHOCKED) && prob(40)) + if(target_type != MACHINERY) + arctargets = list() + arctargets += test + target_type = MACHINERY + + if(target_type > OBJECT) + continue + + if(istype(test, /obj/)) + var/obj/object = test + if(!(object.obj_flags & BEING_SHOCKED)) + if(target_type != OBJECT) + arctargets = list() + arctargets += test + target_type = OBJECT + + if(arctargets.len)//Pick from our pool + target = pick(arctargets) + + if(!QDELETED(target))//If we found something + //Do the animation to zap to it from here + if(!(zap_flags & ZAP_ALLOW_DUPLICATES)) + LAZYSET(targets_hit, target, TRUE) + zapstart.Beam(target, icon_state=zap_icon, time=5) + var/zapdir = get_dir(zapstart, target) if(zapdir) . = zapdir - if(target_mob) - target_mob.electrocute_act(rand(5,10), "Supermatter Discharge Bolt", 1, SHOCK_NOSTUN) - if(prob(15)) - supermatter_zap(target_mob, 5, power / 2) - supermatter_zap(target_mob, 5, power / 2) - else - supermatter_zap(target_mob, 5, power / 1.5) + //Going boom should be rareish + if(prob(80)) + zap_flags &= ~ZAP_MACHINE_EXPLOSIVE + if(target_type == COIL) + //In the best situation we can expect this to grow up to 2120kw before a delam/IT'S GONE TOO FAR FRED SHUT IT DOWN + //The formula for power gen is zap_str * zap_mod / 2 * capacitor rating, between 1 and 4 + var/multi = 10 + switch(power)//Between 7k and 9k it's 20, above that it's 40 + if(SEVERE_POWER_PENALTY_THRESHOLD to CRITICAL_POWER_PENALTY_THRESHOLD) + multi = 20 + if(CRITICAL_POWER_PENALTY_THRESHOLD to INFINITY) + multi = 40 + target.zap_act(zap_str * multi, zap_flags, list()) + zap_str /= 3 //Coils should take a lot out of the power of the zap - else if(target_machine) - if(prob(15)) - supermatter_zap(target_machine, 5, power / 2) - supermatter_zap(target_machine, 5, power / 2) - else - supermatter_zap(target_machine, 5, power / 1.5) + else if(target_type == ROD) + //We can expect this to do very little, maybe shock the poor soul buckled to it, but that's all. + //This is one of our endpoints, if the bolt hits a grounding rod, it stops jumping + target.zap_act(zap_str, zap_flags, list()) + return + + else if(isliving(target))//If we got a fleshbag on our hands + var/mob/living/creature = target + creature.set_shocked() + addtimer(CALLBACK(creature, /mob/living/proc/reset_shocked), 10) + //3 shots a human with no resistance. 2 to crit, one to death. This is at at least 10000 power. + //There's no increase after that because the input power is effectivly capped at 10k + //Does 1.5 damage at the least + var/shock_damage = ((zap_flags & ZAP_MOB_DAMAGE) ? (power / 200) - 10 : rand(5,10)) + creature.electrocute_act(shock_damage, "Supermatter Discharge Bolt", 1, ((zap_flags & ZAP_MOB_STUN) ? SHOCK_TESLA : SHOCK_NOSTUN)) + zap_str /= 1.5 //Meatsacks are conductive, makes working in pairs more destructive - else if(target_structure) - if(prob(15)) - supermatter_zap(target_structure, 5, power / 2) - supermatter_zap(target_structure, 5, power / 2) else - supermatter_zap(target_structure, 5, power / 1.5) + target.zap_act(zap_str, zap_flags, list()) + zap_str /= 2 // worse then living things, better then coils + //This gotdamn variable is a boomer and keeps giving me problems + var/turf/T = get_turf(target) + var/pressure = 1 + if(T && T.return_air()) + pressure = max(1,T.return_air().return_pressure()) + //We get our range with the strength of the zap and the pressure, the higher the former and the lower the latter the better + var/new_range = clamp(zap_str / pressure * 10, 2, 7) + var/zap_count = 1 + if(prob(5)) + zap_str -= (zap_str/10) + zap_count += 1 + for(var/j in 1 to zap_count) + if(zap_count > 1) + targets_hit = targets_hit.Copy() //Pass by ref begone + supermatter_zap(target, new_range, zap_str, zap_flags, targets_hit) #undef HALLUCINATION_RANGE #undef GRAVITATIONAL_ANOMALY #undef FLUX_ANOMALY #undef PYRO_ANOMALY +#undef BIKE +#undef COIL +#undef ROD +#undef LIVING +#undef MACHINERY +#undef OBJECT +#undef LOWEST diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index b40e5c6c41..a9acea719c 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -41,6 +41,11 @@ var/comp_id = 0 var/efficiency +/obj/machinery/power/compressor/Destroy() + if(turbine && turbine.compressor == src) + turbine.compressor = null + turbine = null + return ..() /obj/machinery/power/turbine name = "gas turbine generator" @@ -57,6 +62,12 @@ var/lastgen var/productivity = 1 +/obj/machinery/power/turbine/Destroy() + if(compressor && compressor.turbine == src) + compressor.turbine = null + compressor = null + return ..() + // the inlet stage of the gas turbine electricity generator /obj/machinery/power/compressor/Initialize() @@ -66,12 +77,10 @@ inturf = get_step(src, dir) locate_machinery() if(!turbine) - stat |= BROKEN - + obj_break() #define COMPFRICTION 5e5 - /obj/machinery/power/compressor/locate_machinery() if(turbine) return @@ -103,7 +112,7 @@ stat &= ~BROKEN else to_chat(user, "Turbine not connected.") - stat |= BROKEN + obj_break() return default_deconstruction_crowbar(I) @@ -129,9 +138,9 @@ // RPM function to include compression friction - be advised that too low/high of a compfriction value can make things screwy + rpm = min(rpm, (COMPFRICTION*efficiency)/2) rpm = max(0, rpm - (rpm*rpm)/(COMPFRICTION*efficiency)) - if(starter && !(stat & NOPOWER)) use_power(2800) if(rpm<1000) @@ -140,8 +149,6 @@ if(rpm<1000) rpmtarget = 0 - - if(rpm>50000) add_overlay(mutable_appearance(icon, "comp-o4", FLY_LAYER)) else if(rpm>10000) @@ -164,7 +171,7 @@ outturf = get_step(src, dir) locate_machinery() if(!compressor) - stat |= BROKEN + obj_break() connect_to_network() /obj/machinery/power/turbine/RefreshParts() @@ -205,7 +212,7 @@ // Weird function but it works. Should be something else... - var/newrpm = ((compressor.gas_contained.temperature) * compressor.gas_contained.total_moles())/4 + var/newrpm = ((compressor.gas_contained.return_temperature()) * compressor.gas_contained.total_moles())/4 newrpm = max(0, newrpm) @@ -222,8 +229,6 @@ if(lastgen > 100) add_overlay(mutable_appearance(icon, "turb-o", FLY_LAYER)) - updateDialog() - /obj/machinery/power/turbine/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I)) return @@ -237,53 +242,41 @@ stat &= ~BROKEN else to_chat(user, "Compressor not connected.") - stat |= BROKEN + obj_break() return default_deconstruction_crowbar(I) -/obj/machinery/power/turbine/ui_interact(mob/user) +/obj/machinery/power/turbine/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "TurbineComputer", name) + ui.open() - if(!Adjacent(user) || (stat & (NOPOWER|BROKEN)) && !issilicon(user)) - user.unset_machine(src) - user << browse(null, "window=turbine") - return +/obj/machinery/power/turbine/ui_data(mob/user) + var/list/data = list() + data["compressor"] = compressor ? TRUE : FALSE + data["compressor_broke"] = (!compressor || (compressor.stat & BROKEN)) ? TRUE : FALSE + data["turbine"] = compressor?.turbine ? TRUE : FALSE + data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.stat & BROKEN)) ? TRUE : FALSE + data["online"] = compressor?.starter + data["power"] = DisplayPower(compressor?.turbine?.lastgen) + data["rpm"] = compressor?.rpm + data["temp"] = compressor?.gas_contained.return_temperature() + return data - var/t = "Gas Turbine Generator


    "
    -
    -	t += "Generated power : [DisplayPower(lastgen)]

    " - - t += "Turbine: [round(compressor.rpm)] RPM
    " - - t += "Starter: [ compressor.starter ? "Off On" : "Off On"]" - - t += "

    Close" - - t += "" - var/datum/browser/popup = new(user, "turbine", name) - popup.set_content(t) - popup.open() - - return - -/obj/machinery/power/turbine/Topic(href, href_list) +/obj/machinery/power/turbine/ui_act(action, params) if(..()) return - if( href_list["close"] ) - usr << browse(null, "window=turbine") - usr.unset_machine(src) - return - - else if( href_list["str"] ) - if(compressor) - compressor.starter = !compressor.starter - - updateDialog() - - - - + switch(action) + if("toggle_power") + if(compressor && compressor.turbine) + compressor.starter = !compressor.starter + . = TRUE + if("reconnect") + locate_machinery() + . = TRUE ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -315,31 +308,29 @@ else compressor = locate(/obj/machinery/power/compressor) in range(7, src) -/obj/machinery/computer/turbine_computer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/turbine_computer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "turbine_computer", name, 300, 200, master_ui, state) + ui = new(user, src, "TurbineComputer", name) ui.open() /obj/machinery/computer/turbine_computer/ui_data(mob/user) var/list/data = list() - data["compressor"] = compressor ? TRUE : FALSE data["compressor_broke"] = (!compressor || (compressor.stat & BROKEN)) ? TRUE : FALSE data["turbine"] = compressor?.turbine ? TRUE : FALSE data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.stat & BROKEN)) ? TRUE : FALSE data["online"] = compressor?.starter - data["power"] = DisplayPower(compressor?.turbine?.lastgen) data["rpm"] = compressor?.rpm - data["temp"] = compressor?.gas_contained.temperature + data["temp"] = compressor?.gas_contained.return_temperature() return data /obj/machinery/computer/turbine_computer/ui_act(action, params) if(..()) return + switch(action) if("toggle_power") if(compressor && compressor.turbine) diff --git a/code/modules/procedural_mapping/mapGenerator.dm b/code/modules/procedural_mapping/mapGenerator.dm index f509c409ce..323f74d0ef 100644 --- a/code/modules/procedural_mapping/mapGenerator.dm +++ b/code/modules/procedural_mapping/mapGenerator.dm @@ -147,8 +147,16 @@ set category = "Debug" var/datum/mapGenerator/nature/N = new() - var/startInput = input(usr,"Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text - var/endInput = input(usr,"End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[mob ? mob.z : 1]") as text + var/startInput = input(usr,"Start turf of Map, (X;Y;Z)", "Map Gen Settings", "1;1;1") as text|null + + if (isnull(startInput)) + return + + var/endInput = input(usr,"End turf of Map (X;Y;Z)", "Map Gen Settings", "[world.maxx];[world.maxy];[mob ? mob.z : 1]") as text|null + + if (isnull(endInput)) + return + //maxx maxy and current z so that if you fuck up, you only fuck up one entire z level instead of the entire universe if(!startInput || !endInput) to_chat(src, "Missing Input") diff --git a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm index 3083e7a096..4bd9177373 100644 --- a/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm +++ b/code/modules/procedural_mapping/mapGeneratorModules/helpers.dm @@ -16,7 +16,7 @@ if(T.air) if(T.initial_gas_mix) T.air.parse_gas_string(T.initial_gas_mix) - T.temperature = T.air.temperature + T.temperature = T.air.return_temperature() else T.air.copy_from_turf(T) SSair.add_to_active(T) diff --git a/code/modules/projectiles/ammunition/_ammunition.dm b/code/modules/projectiles/ammunition/_ammunition.dm index ee6a25d8e4..6a73d9a366 100644 --- a/code/modules/projectiles/ammunition/_ammunition.dm +++ b/code/modules/projectiles/ammunition/_ammunition.dm @@ -16,7 +16,8 @@ var/variance = 0 //Variance for inaccuracy fundamental to the casing var/randomspread = 0 //Randomspread for automatics var/delay = 0 //Delay for energy weapons - var/click_cooldown_override = 0 //Override this to make your gun have a faster fire rate, in tenths of a second. 4 is the default gun cooldown. + /// Override this to make the gun check for a different cooldown rather than CLICK_CD_RANGE, which is 4 deciseconds. + var/click_cooldown_override var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the ammo is fired. var/heavy_metal = TRUE var/harmful = TRUE //pacifism check for boolet, set to FALSE if bullet is non-lethal diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm index 340cfc2e98..437b7dcc5a 100644 --- a/code/modules/projectiles/ammunition/_firing.dm +++ b/code/modules/projectiles/ammunition/_firing.dm @@ -16,10 +16,7 @@ AddComponent(/datum/component/pellet_cloud, projectile_type, pellets) SEND_SIGNAL(src, COMSIG_PELLET_CLOUD_INIT, target, user, fired_from, randomspread, spread, zone_override, params, distro) - if(click_cooldown_override) - user.changeNext_move(click_cooldown_override) - else - user.changeNext_move(CLICK_CD_RANGE) + user.DelayNextAction(considered_action = TRUE, immediate = FALSE) user.newtonian_move(get_dir(target, user)) update_icon() return 1 @@ -39,6 +36,14 @@ if(isgun(fired_from)) var/obj/item/gun/G = fired_from BB.damage *= G.projectile_damage_multiplier + if(HAS_TRAIT(user, TRAIT_INSANE_AIM)) + BB.ricochets_max = max(BB.ricochets_max, 10) //bouncy! + BB.ricochet_chance = max(BB.ricochet_chance, 100) //it wont decay so we can leave it at 100 for always bouncing + BB.ricochet_auto_aim_range = max(BB.ricochet_auto_aim_range, 3) + BB.ricochet_auto_aim_angle = max(BB.ricochet_auto_aim_angle, 360) //it can turn full circle and shoot you in the face because our aim? is insane. + BB.ricochet_decay_chance = 0 + BB.ricochet_decay_damage = max(BB.ricochet_decay_damage, 0.1) + BB.ricochet_incidence_leeway = 0 if(reagents && BB.reagents) reagents.trans_to(BB, reagents.total_volume) //For chemical darts/bullets diff --git a/code/modules/projectiles/ammunition/ballistic/pistol.dm b/code/modules/projectiles/ammunition/ballistic/pistol.dm index 2077b108d7..07f3b4c997 100644 --- a/code/modules/projectiles/ammunition/ballistic/pistol.dm +++ b/code/modules/projectiles/ammunition/ballistic/pistol.dm @@ -51,17 +51,3 @@ desc = "A .50AE bullet casing." caliber = ".50" projectile_type = /obj/item/projectile/bullet/a50AE - -// .32 ACP (Improvised Pistol) - -/obj/item/ammo_casing/c32acp - name = ".32 bullet casing" - desc = "A .32 bullet casing." - caliber = "c32acp" - projectile_type = /obj/item/projectile/bullet/c32acp - -/obj/item/ammo_casing/r32acp - name = ".32 rubber bullet casing" - desc = "A .32 rubber bullet casing." - caliber = "c32acp" - projectile_type = /obj/item/projectile/bullet/r32acp diff --git a/code/modules/projectiles/ammunition/ballistic/revolver.dm b/code/modules/projectiles/ammunition/ballistic/revolver.dm index 693b258e3d..c13a3c953d 100644 --- a/code/modules/projectiles/ammunition/ballistic/revolver.dm +++ b/code/modules/projectiles/ammunition/ballistic/revolver.dm @@ -14,9 +14,13 @@ /obj/item/ammo_casing/a357/match name = ".357 match bullet casing" desc = "A .357 bullet casing, manufactured to exceedingly high standards." - caliber = "357" projectile_type = /obj/item/projectile/bullet/a357/match +/obj/item/ammo_casing/a357/dumdum + name = ".357 DumDum bullet casing" + desc = "A .357 bullet casing. Usage of this ammunition will constitute a war crime in your area." + projectile_type = /obj/item/projectile/bullet/a357/dumdum + // 7.62x38mmR (Nagant Revolver) /obj/item/ammo_casing/n762 @@ -68,4 +72,4 @@ /obj/item/ammo_casing/c38/dumdum name = ".38 DumDum bullet casing" desc = "A .38 DumDum bullet casing." - projectile_type = /obj/item/projectile/bullet/c38/dumdum \ No newline at end of file + projectile_type = /obj/item/projectile/bullet/c38/dumdum diff --git a/code/modules/projectiles/ammunition/ballistic/shotgun.dm b/code/modules/projectiles/ammunition/ballistic/shotgun.dm index ea84e23d01..b6fdef69e2 100644 --- a/code/modules/projectiles/ammunition/ballistic/shotgun.dm +++ b/code/modules/projectiles/ammunition/ballistic/shotgun.dm @@ -8,6 +8,18 @@ projectile_type = /obj/item/projectile/bullet/shotgun_slug custom_materials = list(/datum/material/iron=4000) +obj/item/ammo_casing/shotgun/executioner + name = "executioner slug" + desc = "A 12 gauge lead slug purpose built to annihilate flesh on impact." + icon_state = "stunshell" + projectile_type = /obj/item/projectile/bullet/shotgun_slug/executioner + +/obj/item/ammo_casing/shotgun/pulverizer + name = "pulverizer slug" + desc = "A 12 gauge lead slug purpose built to annihilate bones on impact." + icon_state = "stunshell" + projectile_type = /obj/item/projectile/bullet/shotgun_slug/pulverizer + /obj/item/ammo_casing/shotgun/beanbag name = "beanbag slug" desc = "A weak beanbag slug for riot control." diff --git a/code/modules/projectiles/ammunition/energy/laser.dm b/code/modules/projectiles/ammunition/energy/laser.dm index 492b91ec2d..05c47fc3bb 100644 --- a/code/modules/projectiles/ammunition/energy/laser.dm +++ b/code/modules/projectiles/ammunition/energy/laser.dm @@ -12,15 +12,6 @@ e_cost = 200 select_name = "kill" -/obj/item/ammo_casing/energy/lasergun/improvised - projectile_type = /obj/item/projectile/beam/weak/improvised - e_cost = 200 - select_name = "kill" - -/obj/item/ammo_casing/energy/lasergun/improvised/upgraded - projectile_type = /obj/item/projectile/beam/weak - e_cost = 100 - /obj/item/ammo_casing/energy/laser/hos e_cost = 100 @@ -46,6 +37,11 @@ select_name = "anti-vehicle" fire_sound = 'sound/weapons/lasercannonfire.ogg' +/obj/item/ammo_casing/energy/laser/hellfire + projectile_type = /obj/item/projectile/beam/laser/hellfire + e_cost = 130 + select_name = "maim" + /obj/item/ammo_casing/energy/laser/pulse projectile_type = /obj/item/projectile/beam/pulse e_cost = 200 diff --git a/code/modules/projectiles/ammunition/energy/special.dm b/code/modules/projectiles/ammunition/energy/special.dm index 994b0f7f01..ab180cb629 100644 --- a/code/modules/projectiles/ammunition/energy/special.dm +++ b/code/modules/projectiles/ammunition/energy/special.dm @@ -75,4 +75,9 @@ /obj/item/ammo_casing/energy/shrink projectile_type = /obj/item/projectile/beam/shrink select_name = "shrink ray" - e_cost = 200 \ No newline at end of file + e_cost = 200 + +/obj/item/ammo_casing/energy/pickle //ammo for an adminspawn gun + projectile_type = /obj/item/projectile/energy/pickle + select_name = "pickle ray" + e_cost = 0 \ No newline at end of file diff --git a/code/modules/projectiles/boxes_magazines/_box_magazine.dm b/code/modules/projectiles/boxes_magazines/_box_magazine.dm index 8ebddaa24f..78ca6e9280 100644 --- a/code/modules/projectiles/boxes_magazines/_box_magazine.dm +++ b/code/modules/projectiles/boxes_magazines/_box_magazine.dm @@ -20,6 +20,7 @@ var/caliber var/multiload = 1 var/start_empty = 0 + var/load_delay = 0 //how long do we take to load (deciseconds) var/list/bullet_cost var/list/base_cost// override this one as well if you override bullet_cost @@ -75,12 +76,19 @@ return 1 /obj/item/ammo_box/attackby(obj/item/A, mob/user, params, silent = FALSE, replace_spent = 0) + if(INTERACTING_WITH(user, src) || INTERACTING_WITH(user, A)) + to_chat(user, "You're already doing that!") + return FALSE var/num_loaded = 0 if(!can_load(user)) return if(istype(A, /obj/item/ammo_box)) var/obj/item/ammo_box/AM = A for(var/obj/item/ammo_casing/AC in AM.stored_ammo) + if(load_delay || AM.load_delay) + var/loadtime = max(AM.load_delay, load_delay) + if(!do_after(user, loadtime, target = src)) + return FALSE var/did_load = give_round(AC, replace_spent) if(did_load) AM.stored_ammo -= AC @@ -114,11 +122,13 @@ /obj/item/ammo_box/update_icon() . = ..() 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] - custom_materials[material] = material_amount - set_custom_materials(custom_materials)//make sure we setup the correct properties again + if(length(bullet_cost)) + var/temp_materials = custom_materials.Copy() + for (var/material in bullet_cost) + var/material_amount = bullet_cost[material] + material_amount = (material_amount*stored_ammo.len) + base_cost[material] + temp_materials[material] = material_amount + set_custom_materials(temp_materials) /obj/item/ammo_box/update_icon_state() switch(multiple_sprites) diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm index 86d66ec354..8cd49bdf16 100644 --- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm +++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm @@ -16,6 +16,11 @@ name = "speed loader (.357 AP)" ammo_type = /obj/item/ammo_casing/a357/ap +/obj/item/ammo_box/a357/dumdum + name = "speed loader (.357 DumDum)" + desc = "Designed to quickly reload revolvers. Usage of these rounds will constitute a war crime in your area." + ammo_type = /obj/item/ammo_casing/a357/dumdum + /obj/item/ammo_box/c38 name = "speed loader (.38 rubber)" desc = "Designed to quickly reload revolvers." @@ -47,7 +52,7 @@ /obj/item/ammo_box/c38/dumdum name = "speed loader (.38 DumDum)" - desc = "Designed to quickly reload revolvers. DumDum bullets shatter on impact and shred the target's innards, likely getting caught inside." + desc = "Designed to quickly reload revolvers. These rounds expand on impact, allowing them to shred the target and cause massive bleeding. Very weak against armor and distant targets." ammo_type = /obj/item/ammo_casing/c38/dumdum /obj/item/ammo_box/c38/match @@ -55,18 +60,6 @@ desc = "Designed to quickly reload revolvers. These rounds are manufactured within extremely tight tolerances, making them easy to show off trickshots with." ammo_type = /obj/item/ammo_casing/c38/match -/obj/item/ammo_box/c32mm - name = "ammo box (.32 acp)" - desc = "Lethal .32 acp bullets, there's forty in the box." - ammo_type = /obj/item/ammo_casing/c32acp - max_ammo = 40 - -/obj/item/ammo_box/r32mm - name = "ammo box (rubber .32 acp)" - desc = "Non-lethal .32 acp bullets, there's forty in the box." - ammo_type = /obj/item/ammo_casing/r32acp - max_ammo = 40 - /obj/item/ammo_box/c9mm name = "ammo box (9mm)" icon_state = "9mmbox" @@ -156,10 +149,15 @@ icon = 'icons/obj/ammo.dmi' icon_state = "shotgunclip" caliber = "shotgun" // slapped in to allow shell mix n match + slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_POCKET + w_class = WEIGHT_CLASS_NORMAL + w_volume = ITEM_VOLUME_STRIPPER_CLIP ammo_type = /obj/item/ammo_casing/shotgun max_ammo = 4 var/pixeloffsetx = 4 start_empty = TRUE + multiload = FALSE + load_delay = 6 //6ds /obj/item/ammo_box/shotgun/update_overlays() . = ..() diff --git a/code/modules/projectiles/boxes_magazines/external/pistol.dm b/code/modules/projectiles/boxes_magazines/external/pistol.dm index 1852b839f4..63b0483875 100644 --- a/code/modules/projectiles/boxes_magazines/external/pistol.dm +++ b/code/modules/projectiles/boxes_magazines/external/pistol.dm @@ -66,15 +66,3 @@ caliber = ".50" max_ammo = 7 multiple_sprites = 1 - -/obj/item/ammo_box/magazine/m32acp - name = "pistol magazine (.32)" - desc = "A crudely construction pistol magazine that holds .32 ACP rounds. It looks like it can only fit eight bullets." - icon_state = "32acp" - ammo_type = /obj/item/ammo_casing/c32acp - caliber = "c32acp" - max_ammo = 8 - multiple_sprites = 2 - -/obj/item/ammo_box/magazine/m32acp/empty - start_empty = 1 diff --git a/code/modules/projectiles/boxes_magazines/external/shotgun.dm b/code/modules/projectiles/boxes_magazines/external/shotgun.dm index 1001937678..ed41375aee 100644 --- a/code/modules/projectiles/boxes_magazines/external/shotgun.dm +++ b/code/modules/projectiles/boxes_magazines/external/shotgun.dm @@ -1,5 +1,5 @@ /obj/item/ammo_box/magazine/m12g - name = "shotgun magazine (12g buckshot slugs)" + name = "shotgun magazine (12g buckshot)" desc = "A drum magazine." icon_state = "m12gb" ammo_type = /obj/item/ammo_casing/shotgun/buckshot @@ -17,7 +17,7 @@ /obj/item/ammo_box/magazine/m12g/slug name = "shotgun magazine (12g slugs)" - icon_state = "m12gb" //this may need an unique sprite + icon_state = "m12gsl" ammo_type = /obj/item/ammo_casing/shotgun /obj/item/ammo_box/magazine/m12g/dragon diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index b90f0aee0d..8cddd5d02f 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -17,6 +17,7 @@ force = 5 item_flags = NEEDS_PERMIT attack_verb = list("struck", "hit", "bashed") + attack_speed = CLICK_CD_RANGE var/fire_sound = "gunshot" var/suppressed = null //whether or not a message is displayed when fired @@ -29,6 +30,13 @@ var/sawn_desc = null //description change if weapon is sawn-off var/sawn_off = FALSE + /// can we be put into a turret + var/can_turret = TRUE + /// can we be put in a circuit + var/can_circuit = TRUE + /// can we be put in an emitter + var/can_emitter = TRUE + /// Weapon is burst fire if this is above 1 var/burst_size = 1 /// The time between shots in burst. @@ -54,7 +62,8 @@ var/no_pin_required = FALSE //whether the gun can be fired without a pin var/obj/item/flashlight/gun_light - var/can_flashlight = 0 + var/can_flashlight = FALSE + var/gunlight_state = "flight" var/obj/item/kitchen/knife/bayonet var/mutable_appearance/knife_overlay var/can_bayonet = FALSE @@ -166,6 +175,8 @@ /obj/item/gun/afterattack(atom/target, mob/living/user, flag, params) . = ..() + if(!CheckAttackCooldown(user, target)) + return process_afterattack(target, user, flag, params) /obj/item/gun/proc/process_afterattack(atom/target, mob/living/user, flag, params) @@ -174,16 +185,19 @@ if(firing) return var/stamloss = user.getStaminaLoss() - if(stamloss >= STAMINA_NEAR_SOFTCRIT) //The more tired you are, the less damage you do. - var/penalty = (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*STAM_CRIT_GUN_DELAY - user.changeNext_move(CLICK_CD_RANGE+(CLICK_CD_RANGE*penalty)) if(flag) //It's adjacent, is the user, or is on the user's person if(target in user.contents) //can't shoot stuff inside us. return if(!ismob(target) || user.a_intent == INTENT_HARM) //melee attack return - if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH) //so we can't shoot ourselves (unless mouth selected) + if(target == user && user.zone_selected != BODY_ZONE_PRECISE_MOUTH && (user.a_intent != INTENT_DISARM)) //so we can't shoot ourselves (unless mouth selected or disarm intent) return + if(iscarbon(target)) + var/mob/living/carbon/C = target + for(var/i in C.all_wounds) + var/datum/wound/W = i + if(W.try_treating(src, user)) + return // another coward cured! if(istype(user))//Check if the user can use the gun, if the user isn't alive(turrets) assume it can. var/mob/living/L = user @@ -213,6 +227,8 @@ to_chat(user, "You need both hands free to fire \the [src]!") return + user.DelayNextAction() + //DUAL (or more!) WIELDING var/bonus_spread = 0 var/loop_counter = 0 @@ -243,6 +259,17 @@ to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...") return FALSE +/obj/item/gun/CheckAttackCooldown(mob/user, atom/target) + if((user.a_intent == INTENT_HARM) && user.Adjacent(target)) //melee + return user.CheckActionCooldown(CLICK_CD_MELEE) + return user.CheckActionCooldown(get_clickcd()) + +/obj/item/gun/proc/get_clickcd() + return isnull(chambered?.click_cooldown_override)? CLICK_CD_RANGE : chambered.click_cooldown_override + +/obj/item/gun/GetEstimatedAttackSpeed() + return get_clickcd() + /obj/item/gun/proc/handle_pins(mob/living/user) if(no_pin_required) return TRUE @@ -284,8 +311,6 @@ randomized_gun_spread = rand(0, spread) else if(burst_size > 1 && burst_spread) randomized_gun_spread = rand(0, burst_spread) - if(HAS_TRAIT(user, TRAIT_POOR_AIM)) //nice shootin' tex - bonus_spread += 25 var/randomized_bonus_spread = rand(0, bonus_spread) if(burst_size > 1) @@ -357,17 +382,14 @@ if(user.a_intent == INTENT_HARM) //Flogging if(bayonet) M.attackby(bayonet, user) - attack_delay_done = TRUE return else return ..() - attack_delay_done = TRUE //we are firing the gun, not bashing people with its butt. /obj/item/gun/attack_obj(obj/O, mob/user) if(user.a_intent == INTENT_HARM) if(bayonet) - O.attackby(bayonet, user) - return TRUE + return O.attackby(bayonet, user) return ..() /obj/item/gun/attackby(obj/item/I, mob/user, params) @@ -396,14 +418,7 @@ return to_chat(user, "You attach \the [K] to the front of \the [src].") bayonet = K - var/state = "bayonet" //Generic state. - if(bayonet.icon_state in icon_states('icons/obj/guns/bayonets.dmi')) //Snowflake state? - state = bayonet.icon_state - var/icon/bayonet_icons = 'icons/obj/guns/bayonets.dmi' - knife_overlay = mutable_appearance(bayonet_icons, state) - knife_overlay.pixel_x = knife_x_offset - knife_overlay.pixel_y = knife_y_offset - add_overlay(knife_overlay, TRUE) + update_icon() else if(istype(I, /obj/item/screwdriver)) if(gun_light) var/obj/item/flashlight/seclite/S = gun_light @@ -418,8 +433,7 @@ var/obj/item/kitchen/knife/K = bayonet K.forceMove(get_turf(user)) bayonet = null - cut_overlay(knife_overlay, TRUE) - knife_overlay = null + update_icon() else return ..() @@ -447,22 +461,35 @@ set_light(gun_light.brightness_on, gun_light.flashlight_power, gun_light.light_color) else set_light(0) - cut_overlays(flashlight_overlay, TRUE) - var/state = "flight[gun_light.on? "_on":""]" //Generic state. + else + set_light(0) + update_icon() + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + +/obj/item/gun/update_overlays() + . = ..() + if(gun_light) + var/mutable_appearance/flashlight_overlay + var/state = "[gunlight_state][gun_light.on? "_on":""]" //Generic state. if(gun_light.icon_state in icon_states('icons/obj/guns/flashlights.dmi')) //Snowflake state? state = gun_light.icon_state flashlight_overlay = mutable_appearance('icons/obj/guns/flashlights.dmi', state) flashlight_overlay.pixel_x = flight_x_offset flashlight_overlay.pixel_y = flight_y_offset - add_overlay(flashlight_overlay, TRUE) - else - set_light(0) - cut_overlays(flashlight_overlay, TRUE) - flashlight_overlay = null - update_icon(TRUE) - for(var/X in actions) - var/datum/action/A = X - A.UpdateButtonIcon() + . += flashlight_overlay + + if(bayonet) + var/mutable_appearance/knife_overlay + var/state = "bayonet" //Generic state. + if(bayonet.icon_state in icon_states('icons/obj/guns/bayonets.dmi')) //Snowflake state? + state = bayonet.icon_state + var/icon/bayonet_icons = 'icons/obj/guns/bayonets.dmi' + knife_overlay = mutable_appearance(bayonet_icons, state) + knife_overlay.pixel_x = knife_x_offset + knife_overlay.pixel_y = knife_y_offset + . += knife_overlay /obj/item/gun/item_action_slot_check(slot, mob/user, datum/action/A) if(istype(A, /datum/action/item_action/toggle_scope_zoom) && slot != SLOT_HANDS) @@ -580,10 +607,16 @@ var/penalty = (last_fire + GUN_AIMING_TIME + fire_delay) - world.time if(penalty > 0) //Yet we only penalize users firing it multiple times in a haste. fire_delay isn't necessarily cumbersomeness. aiming_delay = penalty - if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //To be removed in favor of something less tactless later. + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) || HAS_TRAIT(user, TRAIT_INSANE_AIM)) //To be removed in favor of something less tactless later. base_inaccuracy /= 1.5 if(stamloss > STAMINA_NEAR_SOFTCRIT) //This can null out the above bonus. base_inaccuracy *= 1 + (stamloss - STAMINA_NEAR_SOFTCRIT)/(STAMINA_NEAR_CRIT - STAMINA_NEAR_SOFTCRIT)*0.5 + if(HAS_TRAIT(user, TRAIT_POOR_AIM)) //nice shootin' tex + if(!HAS_TRAIT(user, TRAIT_INSANE_AIM)) + bonus_spread += 25 + else + //you have both poor aim and insane aim, why? + bonus_spread += rand(0,50) var/mult = max((GUN_AIMING_TIME + aiming_delay + user.last_click_move - world.time)/GUN_AIMING_TIME, -0.5) //Yes, there is a bonus for taking time aiming. if(mult < 0) //accurate weapons should provide a proper bonus with negative inaccuracy. the opposite is true too. mult *= 1/inaccuracy_modifier diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index 4aeefde6d4..1aefa51a51 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -53,6 +53,8 @@ ..() if (istype(A, /obj/item/ammo_box/magazine)) var/obj/item/ammo_box/magazine/AM = A + if(AM.load_delay && !do_after(user, AM.load_delay, target = src)) + return FALSE if (!magazine && istype(AM, mag_type)) if(user.transferItemToLoc(AM, src)) magazine = AM @@ -97,8 +99,7 @@ w_class += S.w_class //so pistols do not fit in pockets when suppressed update_icon() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/gun/ballistic/attack_hand(mob/user) +/obj/item/gun/ballistic/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc == user) if(suppressed && can_unsuppress) var/obj/item/suppressor/S = suppressed @@ -180,13 +181,11 @@ #undef BRAINS_BLOWN_THROW_SPEED #undef BRAINS_BLOWN_THROW_RANGE - - /obj/item/gun/ballistic/proc/sawoff(mob/user) if(sawn_off) to_chat(user, "\The [src] is already shortened!") return - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) user.visible_message("[user] begins to shorten \the [src].", "You begin to shorten \the [src]...") //if there's any live ammo inside the gun, makes it go off diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 39956ef3e8..9210e66f22 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -18,13 +18,15 @@ /obj/item/gun/ballistic/automatic/proto/unrestricted pin = /obj/item/firing_pin -/obj/item/gun/ballistic/automatic/update_icon() - ..() +/obj/item/gun/ballistic/automatic/update_overlays() + . = ..() if(automatic_burst_overlay) if(!select) - add_overlay("[initial(icon_state)]semi") + . += ("[initial(icon_state)]semi") if(select == 1) - add_overlay("[initial(icon_state)]burst") + . += "[initial(icon_state)]burst" + +/obj/item/gun/ballistic/automatic/update_icon_state() icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/gun/ballistic/automatic/attackby(obj/item/A, mob/user, params) @@ -115,8 +117,7 @@ . = ..() empty_alarm() -/obj/item/gun/ballistic/automatic/c20r/update_icon() - ..() +/obj/item/gun/ballistic/automatic/c20r/update_icon_state() icon_state = "c20r[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/gun/ballistic/automatic/wt550 @@ -141,9 +142,8 @@ . = ..() spread = 0 -/obj/item/gun/ballistic/automatic/wt550/update_icon() - ..() - icon_state = "wt550[magazine ? "-[CEILING(( (get_ammo(FALSE) / magazine.max_ammo) * 20) /4, 1)*4]" : "-0"]" //Sprites only support up to 20. +/obj/item/gun/ballistic/automatic/wt550/update_icon_state() + icon_state = "wt550[magazine ? "-[CEILING(((get_ammo(FALSE) / magazine.max_ammo) * 20) /4, 1)*4]" : "-0"]" //Sprites only support up to 20. /obj/item/gun/ballistic/automatic/mini_uzi name = "\improper Type U3 Uzi" @@ -160,6 +160,7 @@ mag_type = /obj/item/ammo_box/magazine/m556 fire_sound = 'sound/weapons/gunshot_smg.ogg' can_suppress = FALSE + automatic_burst_overlay = FALSE var/obj/item/gun/ballistic/revolver/grenadelauncher/underbarrel burst_size = 3 burst_shot_delay = 2 @@ -191,18 +192,19 @@ underbarrel.attackby(A, user, params) else ..() -/obj/item/gun/ballistic/automatic/m90/update_icon() - ..() - cut_overlays() +/obj/item/gun/ballistic/automatic/m90/update_overlays() + . = ..() switch(select) if(0) - add_overlay("[initial(icon_state)]semi") + . += "[initial(icon_state)]semi" if(1) - add_overlay("[initial(icon_state)]burst") + . += "[initial(icon_state)]burst" if(2) - add_overlay("[initial(icon_state)]gren") + . += "[initial(icon_state)]gren" + +/obj/item/gun/ballistic/automatic/m90/update_icon_state() icon_state = "[initial(icon_state)][magazine ? "" : "-e"]" - return + /obj/item/gun/ballistic/automatic/m90/burst_select() var/mob/living/carbon/human/user = usr switch(select) @@ -257,6 +259,7 @@ weapon_weight = WEAPON_MEDIUM mag_type = /obj/item/ammo_box/magazine/m12g fire_sound = 'sound/weapons/gunshot.ogg' + automatic_burst_overlay = FALSE can_suppress = FALSE burst_size = 1 pin = /obj/item/firing_pin/implant/pindicate @@ -269,10 +272,13 @@ . = ..() update_icon() -/obj/item/gun/ballistic/automatic/shotgun/bulldog/update_icon() - cut_overlays() +/obj/item/gun/ballistic/automatic/shotgun/bulldog/update_icon_state() + return + +/obj/item/gun/ballistic/automatic/shotgun/bulldog/update_overlays() + . = ..() if(magazine) - add_overlay("[magazine.icon_state]") + . += "[magazine.icon_state]" icon_state = "bulldog[chambered ? "" : "-e"]" /obj/item/gun/ballistic/automatic/shotgun/bulldog/afterattack() @@ -298,6 +304,7 @@ burst_shot_delay = 1 spread = 7 pin = /obj/item/firing_pin/implant/pindicate + automatic_burst_overlay = FALSE /obj/item/gun/ballistic/automatic/l6_saw/unrestricted pin = /obj/item/firing_pin @@ -316,7 +323,7 @@ playsound(user, 'sound/weapons/sawclose.ogg', 60, 1) update_icon() -/obj/item/gun/ballistic/automatic/l6_saw/update_icon() +/obj/item/gun/ballistic/automatic/l6_saw/update_icon_state() icon_state = "l6[cover_open ? "open" : "closed"][magazine ? CEILING(get_ammo(0)/12.5, 1)*25 : "-empty"][suppressed ? "-suppressed" : ""]" item_state = "l6[cover_open ? "openmag" : "closedmag"]" @@ -327,8 +334,7 @@ . = ..() update_icon() -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/gun/ballistic/automatic/l6_saw/attack_hand(mob/user) +/obj/item/gun/ballistic/automatic/l6_saw/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(loc != user) ..() return //let them pick it up @@ -370,9 +376,10 @@ zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you. zoom_out_amt = 13 slot_flags = ITEM_SLOT_BACK + automatic_burst_overlay = FALSE actions_types = list() -/obj/item/gun/ballistic/automatic/sniper_rifle/update_icon() +/obj/item/gun/ballistic/automatic/sniper_rifle/update_icon_state() if(magazine) icon_state = "sniper-mag" else @@ -398,9 +405,10 @@ can_suppress = TRUE w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BACK + automatic_burst_overlay = FALSE actions_types = list() -/obj/item/gun/ballistic/automatic/surplus/update_icon() +/obj/item/gun/ballistic/automatic/surplus/update_icon_state() if(magazine) icon_state = "surplus" else @@ -414,6 +422,7 @@ icon_state = "oldrifle" item_state = "arg" mag_type = /obj/item/ammo_box/magazine/recharge + automatic_burst_overlay = FALSE fire_delay = 2 can_suppress = FALSE burst_size = 1 @@ -421,7 +430,5 @@ fire_sound = 'sound/weapons/laser.ogg' casing_ejector = FALSE -/obj/item/gun/ballistic/automatic/laser/update_icon() - ..() +/obj/item/gun/ballistic/automatic/laser/update_icon_state() icon_state = "oldrifle[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""]" - return diff --git a/code/modules/projectiles/guns/ballistic/bow.dm b/code/modules/projectiles/guns/ballistic/bow.dm index 4bd7d34fe2..dbf249b3f8 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 durathread string and lots of bending. Used to fire arrows." + desc = "Some sort of pipe-based projectile weapon made of string and lots of bending. Used to fire arrows." icon_state = "pipebow" item_state = "pipebow" - force = 0 + force = 2 diff --git a/code/modules/projectiles/guns/ballistic/laser_gatling.dm b/code/modules/projectiles/guns/ballistic/laser_gatling.dm index c2dd5bb42d..244bc5b124 100644 --- a/code/modules/projectiles/guns/ballistic/laser_gatling.dm +++ b/code/modules/projectiles/guns/ballistic/laser_gatling.dm @@ -29,8 +29,7 @@ /obj/item/minigunpack/process() overheat = max(0, overheat - heat_diffusion) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/item/minigunpack/attack_hand(var/mob/living/carbon/user) +/obj/item/minigunpack/on_attack_hand(var/mob/living/carbon/user) if(src.loc == user) if(!armed) if(user.get_item_by_slot(SLOT_BACK) == src) diff --git a/code/modules/projectiles/guns/ballistic/launchers.dm b/code/modules/projectiles/guns/ballistic/launchers.dm index 34572d609d..9e03207888 100644 --- a/code/modules/projectiles/guns/ballistic/launchers.dm +++ b/code/modules/projectiles/guns/ballistic/launchers.dm @@ -42,8 +42,7 @@ actions_types = list() casing_ejector = FALSE -/obj/item/gun/ballistic/automatic/gyropistol/update_icon() - ..() +/obj/item/gun/ballistic/automatic/gyropistol/update_icon_state() icon_state = "[initial(icon_state)][magazine ? "loaded" : ""]" /obj/item/gun/ballistic/automatic/speargun @@ -54,6 +53,7 @@ w_class = WEIGHT_CLASS_BULKY force = 10 can_suppress = FALSE + automatic_burst_overlay = FALSE mag_type = /obj/item/ammo_box/magazine/internal/speargun fire_sound = 'sound/weapons/grenadelaunch.ogg' burst_size = 1 @@ -62,8 +62,9 @@ actions_types = list() casing_ejector = FALSE -/obj/item/gun/ballistic/automatic/speargun/update_icon() - return +/obj/item/gun/ballistic/automatic/speargun/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_blocker) /obj/item/gun/ballistic/automatic/speargun/attack_self() return @@ -137,20 +138,20 @@ chamber_round() update_icon() -/obj/item/gun/ballistic/rocketlauncher/update_icon() +/obj/item/gun/ballistic/rocketlauncher/update_icon_state() icon_state = "[initial(icon_state)]-[chambered ? "1" : "0"]" /obj/item/gun/ballistic/rocketlauncher/suicide_act(mob/living/user) user.visible_message("[user] aims [src] at the ground! It looks like [user.p_theyre()] performing a sick rocket jump!", \ "You aim [src] at the ground to perform a bisnasty rocket jump...") if(can_shoot()) - user.notransform = TRUE + user.mob_transforming = TRUE playsound(src, 'sound/vehicles/rocketlaunch.ogg', 80, 1, 5) animate(user, pixel_z = 300, time = 30, easing = LINEAR_EASING) sleep(70) animate(user, pixel_z = 0, time = 5, easing = LINEAR_EASING) sleep(5) - user.notransform = FALSE + user.mob_transforming = FALSE process_fire(user, user, TRUE) if(!QDELETED(user)) //if they weren't gibbed by the explosion, take care of them for good. user.gib() diff --git a/code/modules/projectiles/guns/ballistic/magweapon.dm b/code/modules/projectiles/guns/ballistic/magweapon.dm index 74b8b210a7..4e27a73300 100644 --- a/code/modules/projectiles/guns/ballistic/magweapon.dm +++ b/code/modules/projectiles/guns/ballistic/magweapon.dm @@ -75,8 +75,7 @@ recoil = 2 weapon_weight = WEAPON_HEAVY -/obj/item/gun/ballistic/automatic/magrifle/hyperburst/update_icon() - ..() +/obj/item/gun/ballistic/automatic/magrifle/hyperburst/update_icon_state() icon_state = "hyperburst[magazine ? "-[get_ammo()]" : ""][chambered ? "" : "-e"]" ///magpistol/// @@ -92,12 +91,14 @@ fire_delay = 2 inaccuracy_modifier = 0.25 cell_type = /obj/item/stock_parts/cell/magnetic/pistol + automatic_burst_overlay = FALSE -/obj/item/gun/ballistic/automatic/magrifle/pistol/update_icon() - ..() - cut_overlays() +/obj/item/gun/ballistic/automatic/magrifle/pistol/update_overlays() + . = ..() if(magazine) - add_overlay("magpistol-magazine") + . += "magpistol-magazine" + +/obj/item/gun/ballistic/automatic/magrifle/pistol/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" /obj/item/gun/ballistic/automatic/magrifle/pistol/nopin diff --git a/code/modules/projectiles/guns/ballistic/pistol.dm b/code/modules/projectiles/guns/ballistic/pistol.dm index 319ec16345..e775fdc05a 100644 --- a/code/modules/projectiles/guns/ballistic/pistol.dm +++ b/code/modules/projectiles/guns/ballistic/pistol.dm @@ -8,12 +8,12 @@ burst_size = 1 fire_delay = 0 actions_types = list() + automatic_burst_overlay = FALSE /obj/item/gun/ballistic/automatic/pistol/no_mag spawnwithmagazine = FALSE -/obj/item/gun/ballistic/automatic/pistol/update_icon() - ..() +/obj/item/gun/ballistic/automatic/pistol/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/gun/ballistic/automatic/pistol/suppressed/Initialize(mapload) @@ -28,6 +28,7 @@ icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi' icon_state = "cde" can_unsuppress = TRUE + automatic_burst_overlay = FALSE obj_flags = UNIQUE_RENAME unique_reskin = list("Default" = "cde", "N-99" = "n99", @@ -38,20 +39,18 @@ "PX4 Storm" = "px4" ) -/obj/item/gun/ballistic/automatic/pistol/modular/update_icon() - ..() +/obj/item/gun/ballistic/automatic/pistol/modular/update_icon_state() if(current_skin) icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" else icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" + +/obj/item/gun/ballistic/automatic/pistol/modular/update_overlays() + . = ..() if(magazine && suppressed) - cut_overlays() - add_overlay("[unique_reskin[current_skin]]-magazine-sup") //Yes, this means the default iconstate can't have a magazine overlay + . += "[unique_reskin[current_skin]]-magazine-sup" //Yes, this means the default iconstate can't have a magazine overlay else if (magazine) - cut_overlays() - add_overlay("[unique_reskin[current_skin]]-magazine") - else - cut_overlays() + . += "[unique_reskin[current_skin]]-magazine" /obj/item/gun/ballistic/automatic/pistol/m1911 name = "\improper M1911" @@ -77,14 +76,14 @@ force = 14 mag_type = /obj/item/ammo_box/magazine/m50 can_suppress = FALSE + automatic_burst_overlay = FALSE -/obj/item/gun/ballistic/automatic/pistol/deagle/update_icon() - ..() +/obj/item/gun/ballistic/automatic/pistol/deagle/update_overlays() + . = ..() if(magazine) - cut_overlays() - add_overlay("deagle_magazine") - else - cut_overlays() + . += "deagle_magazine" + +/obj/item/gun/ballistic/automatic/pistol/deagle/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" /obj/item/gun/ballistic/automatic/pistol/deagle/gold @@ -142,33 +141,17 @@ actions_types = list() fire_sound = 'sound/weapons/blastcannon.ogg' spread = 20 //damn thing has no rifling. + automatic_burst_overlay = FALSE -/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon() - ..() +/obj/item/gun/ballistic/automatic/pistol/antitank/update_overlays() + . = ..() if(magazine) - cut_overlays() - add_overlay("atp-mag") - else - cut_overlays() + . += "atp-mag" + +/obj/item/gun/ballistic/automatic/pistol/antitank/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate name = "Syndicate Anti Tank Pistol" desc = "A massively impractical and silly monstrosity of a pistol that fires .50 calliber rounds. The recoil is likely to dislocate a variety of joints without proper bracing." pin = /obj/item/firing_pin/implant/pindicate - -////////////Improvised Pistol//////////// - -/obj/item/gun/ballistic/automatic/pistol/improvised - name = "Improvised Pistol" - desc = "An improvised pocket-sized pistol that fires .32 calibre rounds. It looks incredibly flimsy." - icon_state = "ipistol" - item_state = "pistol" - mag_type = /obj/item/ammo_box/magazine/m32acp - fire_delay = 7.5 - can_suppress = FALSE - w_class = WEIGHT_CLASS_SMALL - spread = 15 // Keep the spread between 15 and 20. This hardlocks it into being a mid-range pistol, the magazine size means you're allowed to miss. Fills the mid-range niche that slugs/rifle and buckshot doesn't fill. - -/obj/item/gun/ballistic/automatic/pistol/improvised/nomag - spawnwithmagazine = FALSE // For crafting as you shouldn't get eight bullets for free otherwise people will reaper reload. diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index f34dbc6abc..6f1fb96af5 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -84,6 +84,11 @@ . = ..() . += "[get_ammo(0,0)] of those are live rounds." +/obj/item/gun/ballistic/revolver/syndicate + unique_reskin = list("Default" = "revolver", + "Silver" = "russianrevolver", + "Robust" = "revolvercit") + /obj/item/gun/ballistic/revolver/detective name = "\improper .38 Mars Special" desc = "A cheap Martian knock-off of a classic law enforcement firearm. Uses .38-special rounds." @@ -319,11 +324,11 @@ /obj/item/gun/ballistic/revolver/doublebarrel/improvised name = "improvised shotgun" - desc = "A shoddy break-action breechloaded shotgun. Its lacklustre construction will probably result in it hurting people less than a normal shotgun." + desc = "A shoddy break-action breechloaded shotgun. Its lacklustre construction shows in its lesser effectiveness." icon_state = "ishotgun" item_state = "shotgun" w_class = WEIGHT_CLASS_BULKY - weapon_weight = WEAPON_MEDIUM + weapon_weight = WEAPON_MEDIUM // prevents shooting 2 at once, but doesn't require 2 hands force = 10 slot_flags = null mag_type = /obj/item/ammo_box/magazine/internal/shot/improvised @@ -331,12 +336,11 @@ unique_reskin = null projectile_damage_multiplier = 0.9 var/slung = FALSE - weapon_weight = WEAPON_HEAVY /obj/item/gun/ballistic/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params) ..() if(istype(A, /obj/item/stack/cable_coil) && !sawn_off) - if(A.use_tool(src, user, 0, 10, max_level = JOB_SKILL_BASIC)) + if(A.use_tool(src, user, 0, 10, skill_gain_mult = EASY_USE_TOOL_MULT)) slot_flags = ITEM_SLOT_BACK to_chat(user, "You tie the lengths of cable to the shotgun, making a sling.") slung = TRUE @@ -344,10 +348,10 @@ else to_chat(user, "You need at least ten lengths of cable if you want to make a sling!") -/obj/item/gun/ballistic/revolver/doublebarrel/improvised/update_icon() - ..() +/obj/item/gun/ballistic/revolver/doublebarrel/improvised/update_overlays() + . = ..() if(slung) - icon_state += "sling" + . += "[icon_state]sling" /obj/item/gun/ballistic/revolver/doublebarrel/improvised/sawoff(mob/user) . = ..() @@ -358,7 +362,7 @@ /obj/item/gun/ballistic/revolver/doublebarrel/improvised/sawn name = "sawn-off improvised shotgun" - desc = "The barrel and stock have been sawn and filed down; it can fit in backpacks. You still need two hands to fire this, if you value unbroken wrists." + desc = "The barrel and stock have been sawn and filed down; it can fit in backpacks. You wont want to shoot two of these at once if you value your wrists." icon_state = "ishotgun" item_state = "gun" w_class = WEIGHT_CLASS_NORMAL @@ -487,4 +491,4 @@ for(var/i = 0, i < ratio, i++) var/mutable_appearance/charge_bar = mutable_appearance(icon, "[initial(icon_state)]_charge", color = batt_color) charge_bar.pixel_x = i - . += charge_bar \ No newline at end of file + . += charge_bar diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index a4a4065959..ecf6e538b8 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -156,7 +156,7 @@ /obj/item/gun/ballistic/shotgun/boltaction/improvised/attackby(obj/item/A, mob/user, params) ..() if(istype(A, /obj/item/stack/cable_coil) && !sawn_off) - if(A.use_tool(src, user, 0, 10, max_level = JOB_SKILL_BASIC)) + if(A.use_tool(src, user, 0, 10, skill_gain_mult = EASY_USE_TOOL_MULT)) slot_flags = ITEM_SLOT_BACK to_chat(user, "You tie the lengths of cable to the rifle, making a sling.") slung = TRUE @@ -164,10 +164,10 @@ else to_chat(user, "You need at least ten lengths of cable if you want to make a sling!") -/obj/item/gun/ballistic/shotgun/boltaction/improvised/update_icon() - ..() +/obj/item/gun/ballistic/shotgun/boltaction/improvised/update_overlays() + . = ..() if(slung) - icon_state += "sling" + . += "[icon_state]sling" /obj/item/gun/ballistic/shotgun/boltaction/enchanted name = "enchanted bolt action rifle" @@ -272,7 +272,7 @@ spread = 2 update_icon() -/obj/item/gun/ballistic/shotgun/automatic/combat/compact/update_icon() +/obj/item/gun/ballistic/shotgun/automatic/combat/compact/update_icon_state() icon_state = "[current_skin ? unique_reskin[current_skin] : "cshotgun"][stock ? "" : "c"]" //Dual Feed Shotgun diff --git a/code/modules/projectiles/guns/ballistic/toy.dm b/code/modules/projectiles/guns/ballistic/toy.dm index 5cdd773894..e7f26670d4 100644 --- a/code/modules/projectiles/guns/ballistic/toy.dm +++ b/code/modules/projectiles/guns/ballistic/toy.dm @@ -27,9 +27,9 @@ burst_size = 1 fire_delay = 0 actions_types = list() + automatic_burst_overlay = FALSE -/obj/item/gun/ballistic/automatic/toy/pistol/update_icon() - ..() +/obj/item/gun/ballistic/automatic/toy/pistol/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]" /obj/item/gun/ballistic/automatic/toy/pistol/riot @@ -56,6 +56,7 @@ item_flags = NONE casing_ejector = FALSE can_suppress = FALSE + weapon_weight = WEAPON_MEDIUM /obj/item/gun/ballistic/shotgun/toy/process_chamber(mob/living/user, empty_chamber = 0) ..() diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 8f9e364302..17dcfa96e6 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -29,7 +29,6 @@ var/charge_sections = 4 ammo_x_offset = 2 var/shaded_charge = FALSE //if this gun uses a stateful charge bar for more detail - var/old_ratio = 0 // stores the gun's previous ammo "ratio" to see if it needs an updated icon var/selfcharge = EGUN_NO_SELFCHARGE // EGUN_SELFCHARGE if true, EGUN_SELFCHARGE_BORG drains the cyborg's cell to recharge its own var/charge_tick = 0 var/charge_delay = 4 @@ -64,10 +63,20 @@ START_PROCESSING(SSobj, src) update_icon() +/obj/item/gun/energy/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + /obj/item/gun/energy/Destroy() STOP_PROCESSING(SSobj, src) return ..() +/obj/item/gun/energy/handle_atom_del(atom/A) + if(A == cell) + cell = null + update_icon() + return ..() + /obj/item/gun/energy/examine(mob/user) . = ..() if(!right_click_overridden) @@ -226,46 +235,47 @@ #undef DECREMENT_OR_WRAP #undef IS_VALID_INDEX -/obj/item/gun/energy/update_icon(force_update) - if(QDELETED(src)) +/obj/item/gun/energy/update_icon_state() + if(initial(item_state)) return ..() + var/ratio = get_charge_ratio() + var/new_item_state = "" + new_item_state = initial(icon_state) + if(modifystate) + var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] + new_item_state += "[shot.select_name]" + new_item_state += "[ratio]" + item_state = new_item_state + +/obj/item/gun/energy/update_overlays() + . = ..() + if(QDELETED(src)) + return if(!automatic_charge_overlays) return - var/ratio = can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0 - // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if it's power cell is removed. - // TG issues #5361 & #47908 - if(ratio == old_ratio && !force_update) - return - old_ratio = ratio - cut_overlays() - var/iconState = "[icon_state]_charge" - var/itemState = null - if(!initial(item_state)) - itemState = icon_state + var/overlay_icon_state = "[icon_state]_charge" + var/ratio = get_charge_ratio() if (modifystate) var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] - add_overlay("[icon_state]_[shot.select_name]") - iconState += "_[shot.select_name]" - if(itemState) - itemState += "[shot.select_name]" + . += "[icon_state]_[shot.select_name]" + overlay_icon_state += "_[shot.select_name]" if(ratio == 0) - add_overlay("[icon_state]_empty") + . += "[icon_state]_empty" else if(!shaded_charge) - var/mutable_appearance/charge_overlay = mutable_appearance(icon, iconState) + var/mutable_appearance/charge_overlay = mutable_appearance(icon, overlay_icon_state) for(var/i = ratio, i >= 1, i--) charge_overlay.pixel_x = ammo_x_offset * (i - 1) charge_overlay.pixel_y = ammo_y_offset * (i - 1) - add_overlay(charge_overlay) + . += charge_overlay else - add_overlay("[icon_state]_charge[ratio]") - if(itemState) - itemState += "[ratio]" - item_state = itemState - if(ismob(loc)) //forces inhands to update - var/mob/M = loc - M.update_inv_hands() + . += "[icon_state]_charge[ratio]" + +///Used by update_icon_state() and update_overlays() +/obj/item/gun/energy/proc/get_charge_ratio() + return can_shoot() ? CEILING(clamp(cell.charge / cell.maxcharge, 0, 1) * charge_sections, 1) : 0 + // Sets the ratio to 0 if the gun doesn't have enough charge to fire, or if its power cell is removed. /obj/item/gun/energy/suicide_act(mob/living/user) if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD)) @@ -290,7 +300,7 @@ /obj/item/gun/energy/vv_edit_var(var_name, var_value) switch(var_name) - if("selfcharge") + if(NAMEOF(src, selfcharge)) if(var_value) START_PROCESSING(SSobj, src) else diff --git a/code/modules/projectiles/guns/energy/dueling.dm b/code/modules/projectiles/guns/energy/dueling.dm index 80bb269b21..04eff5afa9 100644 --- a/code/modules/projectiles/guns/energy/dueling.dm +++ b/code/modules/projectiles/guns/energy/dueling.dm @@ -207,12 +207,11 @@ to_chat(user,"You switch [src] setting to [setting] mode.") update_icon() -/obj/item/gun/energy/dueling/update_icon(force_update) +/obj/item/gun/energy/dueling/update_overlays(force_update) . = ..() if(setting_overlay) - cut_overlay(setting_overlay) setting_overlay.icon_state = setting_iconstate() - add_overlay(setting_overlay) + . += setting_overlay /obj/item/gun/energy/dueling/Destroy() if(duel) @@ -363,8 +362,7 @@ STR.max_items = 2 STR.can_hold = typecacheof(/obj/item/gun/energy/dueling) -/obj/item/storage/lockbox/dueling/update_icon() - cut_overlays() +/obj/item/storage/lockbox/dueling/update_icon_state() var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED) if(locked) icon_state = "medalbox+l" diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm index 1b835d35a4..2c9794f391 100644 --- a/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/code/modules/projectiles/guns/energy/energy_gun.dm @@ -19,17 +19,13 @@ cell_type = /obj/item/stock_parts/cell{charge = 600; maxcharge = 600} ammo_x_offset = 2 charge_sections = 3 + gunlight_state = "mini-light" can_flashlight = 0 // Can't attach or detach the flashlight, and override it's icon update /obj/item/gun/energy/e_gun/mini/Initialize() gun_light = new /obj/item/flashlight/seclite(src) return ..() -/obj/item/gun/energy/e_gun/mini/update_icon() - ..() - if(gun_light && gun_light.on) - add_overlay("mini-light") - /obj/item/gun/energy/e_gun/stun name = "tactical energy gun" desc = "Military issue energy gun, is able to fire stun rounds." @@ -138,15 +134,15 @@ return fail_chance = min(fail_chance + round(15/severity), 100) -/obj/item/gun/energy/e_gun/nuclear/update_icon() - ..() +/obj/item/gun/energy/e_gun/nuclear/update_overlays() + . = ..() if(crit_fail) - add_overlay("[icon_state]_fail_3") + . += "[icon_state]_fail_3" else switch(fail_tick) if(0) - add_overlay("[icon_state]_fail_0") + . += "[icon_state]_fail_0" if(1 to 150) - add_overlay("[icon_state]_fail_1") + . += "[icon_state]_fail_1" if(151 to INFINITY) - add_overlay("[icon_state]_fail_2") + . += "[icon_state]_fail_2" diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index 49c069ca62..c1f47ccd1a 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -34,13 +34,6 @@ righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' ammo_type = list(/obj/item/ammo_casing/energy/kinetic/premium) -/obj/item/gun/energy/kinetic_accelerator/premiumka/dropped(mob/user) - . = ..() - if(!QDELING(src) && !holds_charge) - // Put it on a delay because moving item from slot to hand - // calls dropped(). - addtimer(CALLBACK(src, .proc/empty_if_not_held), 1.60) - /obj/item/ammo_casing/energy/kinetic/premium projectile_type = /obj/item/projectile/kinetic/premium @@ -53,13 +46,6 @@ range = 4 log_override = TRUE -/obj/item/gun/energy/kinetic_accelerator/premiumka/update_icon() - ..() - if(!can_shoot()) - add_overlay("[icon_state]_empty") - else - cut_overlays() - /obj/item/gun/energy/kinetic_accelerator/getinaccuracy(mob/living/user, bonus_spread, stamloss) var/old_fire_delay = fire_delay //It's pretty irrelevant tbh but whatever. fire_delay = overheat_time @@ -151,7 +137,7 @@ addtimer(CALLBACK(src, .proc/empty_if_not_held), 2) /obj/item/gun/energy/kinetic_accelerator/proc/empty_if_not_held() - if(!ismob(loc)) + if(!ismob(loc) && !istype(loc, /obj/item/integrated_circuit)) empty() /obj/item/gun/energy/kinetic_accelerator/proc/empty() @@ -193,12 +179,10 @@ update_icon() overheat = FALSE -/obj/item/gun/energy/kinetic_accelerator/update_icon() - ..() +/obj/item/gun/energy/kinetic_accelerator/update_overlays() + . = ..() if(!can_shoot()) - add_overlay("[icon_state]_empty") - else - cut_overlays() + . += "[icon_state]_empty" //Casing /obj/item/ammo_casing/energy/kinetic diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index e64da116f3..8e61221cc8 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -44,6 +44,12 @@ ammo_type = list(/obj/item/ammo_casing/energy/lasergun/old) ammo_x_offset = 3 +/obj/item/gun/energy/laser/hellgun + name ="hellfire laser gun" + desc = "A relic of a weapon, built before NT began installing regulators on its laser weaponry. This pattern of laser gun became infamous for the gruesome burn wounds it caused, and was quietly discontinued once it began to affect NT's reputation." + icon_state = "hellgun" + ammo_type = list(/obj/item/ammo_casing/energy/laser/hellfire) + /obj/item/gun/energy/laser/captain name = "antique laser gun" icon_state = "caplaser" @@ -240,20 +246,3 @@ chambered.BB.damage *= 5 process_fire(target, user, TRUE, params) - -//////////////// -// IMPROVISED // -//////////////// - -/obj/item/gun/energy/e_gun/old/improvised - name = "improvised energy rifle" - desc = "A crude imitation of an energy gun. It works, however the beams are poorly focused and most of the energy is wasted before it reaches the target. Welp, it still burns things." - icon_state = "improvised" - ammo_x_offset = 1 - shaded_charge = 1 - ammo_type = list(/obj/item/ammo_casing/energy/lasergun/improvised) - -/obj/item/gun/energy/e_gun/old/improvised/upgraded - name = "makeshift energy rifle" - desc = "The new lens and upgraded parts gives this a higher capacity and more energy output, however, the shoddy construction still leaves it inferior to Nanotrasen's own energy weapons." - ammo_type = list(/obj/item/ammo_casing/energy/lasergun/improvised/upgraded) diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index b55e26b6a3..19ca42022d 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -34,11 +34,11 @@ pin = null ammo_x_offset = 1 -/obj/item/gun/energy/decloner/update_icon() +/obj/item/gun/energy/decloner/update_overlays() ..() var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] if(!QDELETED(cell) && (cell.charge > shot.e_cost)) - add_overlay("decloner_spin") + . += "decloner_spin" /obj/item/gun/energy/floragun name = "floral somatoray" @@ -125,7 +125,7 @@ flags_1 = CONDUCT_1 attack_verb = list("attacked", "slashed", "cut", "sliced") force = 12 - sharpness = IS_SHARP + sharpness = SHARP_EDGED inaccuracy_modifier = 0.25 can_charge = 0 @@ -134,9 +134,10 @@ tool_behaviour = TOOL_WELDER toolspeed = 0.7 //plasmacutters can be used as welders, and are faster than standard welders -/obj/item/gun/energy/plasmacutter/Initialize() +/obj/item/gun/energy/plasmacutter/ComponentInitialize() . = ..() AddComponent(/datum/component/butchering, 25, 105, 0, 'sound/weapons/plasma_cutter.ogg') + AddElement(/datum/element/update_icon_blocker) /obj/item/gun/energy/plasmacutter/examine(mob/user) . = ..() @@ -166,9 +167,6 @@ /obj/item/gun/energy/plasmacutter/use(amount) return cell.use(amount * 100) -/obj/item/gun/energy/plasmacutter/update_icon() - return - /obj/item/gun/energy/plasmacutter/adv name = "advanced plasma cutter" icon_state = "adv_plasmacutter" @@ -183,11 +181,12 @@ icon_state = "wormhole_projector" pin = null inaccuracy_modifier = 0.25 + automatic_charge_overlays = FALSE var/obj/effect/portal/p_blue var/obj/effect/portal/p_orange var/atmos_link = FALSE -/obj/item/gun/energy/wormhole_projector/update_icon() +/obj/item/gun/energy/wormhole_projector/update_icon_state() icon_state = "[initial(icon_state)][current_firemode_index]" item_state = icon_state @@ -256,8 +255,9 @@ can_charge = 0 use_cyborg_cell = 1 -/obj/item/gun/energy/printer/update_icon() - return +/obj/item/gun/energy/printer/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_blocker) /obj/item/gun/energy/printer/emp_act() return @@ -321,11 +321,19 @@ inaccuracy_modifier = 0.25 cell_type = /obj/item/stock_parts/cell/super ammo_type = list(/obj/item/ammo_casing/energy/emitter) + automatic_charge_overlays = FALSE -/obj/item/gun/energy/emitter/update_icon() - ..() +/obj/item/gun/energy/emitter/update_icon_state() var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] if(!QDELETED(cell) && (cell.charge > shot.e_cost)) - add_overlay("emitter_carbine_empty") + icon_state = "emitter_carbine_empty" else - add_overlay("emitter_carbine") + icon_state = "emitter_carbine" + +//the pickle ray +/obj/item/gun/energy/pickle_gun + name = "pickle ray" + desc = "funniest shit i've ever seen" + icon_state = "decloner" + no_pin_required = TRUE + ammo_type = list(/obj/item/ammo_casing/energy/pickle) \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index d700db817c..6c75ac2d4d 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -24,7 +24,7 @@ ammo_x_offset = 2 // Not enough guns have altfire systems like this yet for this to be a universal framework. var/last_altfire = 0 - var/altfire_delay = 15 + var/altfire_delay = CLICK_CD_RANGE /obj/item/gun/energy/e_gun/advtaser/altafterattack(atom/target, mob/user, proximity_flag, params) . = TRUE diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm index ce87eddc67..ebc4a2f2a4 100644 --- a/code/modules/projectiles/guns/magic.dm +++ b/code/modules/projectiles/guns/magic.dm @@ -9,7 +9,7 @@ fire_sound = 'sound/weapons/emitter.ogg' flags_1 = CONDUCT_1 w_class = WEIGHT_CLASS_HUGE - var/checks_antimagic = FALSE + var/checks_antimagic = TRUE var/max_charges = 6 var/charges = 0 var/recharge_rate = 4 @@ -83,6 +83,6 @@ /obj/item/gun/magic/vv_edit_var(var_name, var_value) . = ..() - switch (var_name) - if ("charges") + switch(var_name) + if(NAMEOF(src, charges)) recharge_newshot() diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index b23b059d89..6ebdc5e7b8 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -83,7 +83,7 @@ force = 20 armour_penetration = 75 block_chance = 50 - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_charges = 4 /obj/item/gun/magic/staff/spellblade/Initialize() diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index bcb074023f..5e250d44e2 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -29,10 +29,13 @@ ammo_type = list(/obj/item/ammo_casing/energy/beam_rifle/hitscan) cell_type = /obj/item/stock_parts/cell/beam_rifle canMouseDown = TRUE + can_turret = FALSE + can_circuit = FALSE //Cit changes: beam rifle stats. slowdown = 1 item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND | NEEDS_PERMIT pin = null + automatic_charge_overlays = FALSE var/aiming = FALSE var/aiming_time = 14 var/aiming_time_fire_threshold = 5 @@ -150,13 +153,13 @@ current_zoom_x = 0 current_zoom_y = 0 -/obj/item/gun/energy/beam_rifle/update_icon() - cut_overlays() +/obj/item/gun/energy/beam_rifle/update_overlays() + . = ..() var/obj/item/ammo_casing/energy/primary_ammo = ammo_type[1] if(!QDELETED(cell) && (cell.charge > primary_ammo.e_cost)) - add_overlay(charged_overlay) + . += charged_overlay else - add_overlay(drained_overlay) + . += drained_overlay /obj/item/gun/energy/beam_rifle/attack_self(mob/user) if(!structure_piercing) @@ -418,10 +421,10 @@ var/wall_devastate = 0 var/aoe_structure_range = 0 var/aoe_structure_damage = 0 - var/aoe_fire_range = 0 - var/aoe_fire_chance = 0 - var/aoe_mob_range = 0 - var/aoe_mob_damage = 0 + var/aoe_fire_range = 2 + var/aoe_fire_chance = 100 + var/aoe_mob_range = 2 + var/aoe_mob_damage = 30 var/impact_structure_damage = 0 var/impact_direct_damage = 0 var/turf/cached diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm index 1c8d519ba8..60b7565333 100644 --- a/code/modules/projectiles/guns/misc/blastcannon.dm +++ b/code/modules/projectiles/guns/misc/blastcannon.dm @@ -41,18 +41,16 @@ user.put_in_hands(bomb) user.visible_message("[user] detaches [bomb] from [src].") bomb = null + name = initial(name) + desc = initial(desc) update_icon() return ..() -/obj/item/gun/blastcannon/update_icon() +/obj/item/gun/blastcannon/update_icon_state() if(bomb) icon_state = icon_state_loaded - name = "blast cannon" - desc = "A makeshift device used to concentrate a bomb's blast energy to a narrow wave." else icon_state = initial(icon_state) - name = initial(name) - desc = initial(desc) /obj/item/gun/blastcannon/attackby(obj/O, mob/user) if(istype(O, /obj/item/transfer_valve)) @@ -65,6 +63,8 @@ return FALSE user.visible_message("[user] attaches [T] to [src]!") bomb = T + name = "blast cannon" + desc = "A makeshift device used to concentrate a bomb's blast energy to a narrow wave." update_icon() return TRUE return ..() diff --git a/code/modules/projectiles/guns/misc/medbeam.dm b/code/modules/projectiles/guns/misc/medbeam.dm index e841422893..6864dad33e 100644 --- a/code/modules/projectiles/guns/misc/medbeam.dm +++ b/code/modules/projectiles/guns/misc/medbeam.dm @@ -47,7 +47,7 @@ if(current_target) LoseTarget() - if(!isliving(target)) + if(!isliving(target) || (user == target)) return current_target = target diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index f279047356..99a0bedc4d 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -49,7 +49,7 @@ var/pixel_move_interrupted = FALSE /// Pixels moved per second. - var/pixels_per_second = TILES_TO_PIXELS(12.5) + var/pixels_per_second = TILES_TO_PIXELS(17.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 @@ -149,15 +149,25 @@ var/temporary_unstoppable_movement = FALSE - ///If defined, on hit we create an item of this type then call hitby() on the hit target with this + ///If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets var/shrapnel_type ///If TRUE, hit mobs even if they're on the floor and not our target var/hit_stunned_targets = FALSE + wound_bonus = CANT_WOUND + ///How much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes + var/wound_falloff_tile + ///How much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes + var/embed_falloff_tile + /// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds + sharpness = SHARP_NONE + /obj/item/projectile/Initialize() . = ..() permutated = list() decayedRange = range + if(embedding) + updateEmbedding() /** * Artificially modified to be called at around every world.icon_size pixels of movement. @@ -165,6 +175,11 @@ */ /obj/item/projectile/proc/Range() range-- + if(wound_bonus != CANT_WOUND) + wound_bonus += wound_falloff_tile + bare_wound_bonus = max(0, bare_wound_bonus + wound_falloff_tile) + if(embedding) + embedding["embed_chance"] += embed_falloff_tile if(range <= 0 && loc) on_range() @@ -239,7 +254,7 @@ else if(ishuman(target)) var/mob/living/carbon/human/H = target - new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color(H.dna.blood_type)) + new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, H.dna.species.exotic_blood_color) else new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color()) @@ -312,16 +327,18 @@ if(!trajectory) return var/turf/T = get_turf(A) - if(check_ricochet(A) && A.handle_ricochet(src)) //if you can ricochet, attempt to ricochet off the object - on_ricochet(A) //if allowed, use autoaim to ricochet into someone, otherwise default to ricocheting off the object from above - var/datum/point/pcache = trajectory.copy_to() - if(hitscan) - store_hitscan_collision(pcache) - decayedRange = max(0, decayedRange - reflect_range_decrease) - ricochet_chance *= ricochet_decay_chance - damage *= ricochet_decay_damage - range = decayedRange - return TRUE + if(check_ricochet_flag(A) && check_ricochet(A)) //if you can ricochet, attempt to ricochet off the object + ricochets++ + if(A.handle_ricochet(src)) + on_ricochet(A) //if allowed, use autoaim to ricochet into someone, otherwise default to ricocheting off the object from above + var/datum/point/pcache = trajectory.copy_to() + if(hitscan) + store_hitscan_collision(pcache) + decayedRange = max(0, decayedRange - reflect_range_decrease) + ricochet_chance *= ricochet_decay_chance + damage *= ricochet_decay_damage + range = decayedRange + return TRUE var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations. if(def_zone && check_zone(def_zone) != BODY_ZONE_CHEST) @@ -619,7 +636,7 @@ pixel_x = trajectory.return_px() pixel_y = trajectory.return_py() else if(T != loc) - var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1 + var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 5 + 1 while(T != loc) if(!--safety) CRASH("[type] took too long (allowed: [CEILING(pixel_increment_amount/world.icon_size,1)*2] moves) to get to its location.") @@ -665,7 +682,8 @@ if(!ignore_source_check && firer) var/mob/M = firer if((target == firer) || ((target == firer.loc) && ismecha(firer.loc)) || (target in firer.buckled_mobs) || (istype(M) && (M.buckled == target))) - return FALSE + if(!ricochets) //if it has ricocheted, it can hit the firer. + return FALSE if(!ignore_loc && (loc != target.loc)) return FALSE if(target in passthrough) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index d95c3b5028..4ba72a1935 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -14,11 +14,25 @@ ricochets_max = 50 //Honk! ricochet_chance = 80 is_reflectable = TRUE + wound_bonus = -20 + bare_wound_bonus = 10 /obj/item/projectile/beam/laser tracer_type = /obj/effect/projectile/tracer/laser muzzle_type = /obj/effect/projectile/muzzle/laser impact_type = /obj/effect/projectile/impact/laser + wound_bonus = -30 + bare_wound_bonus = 40 + +//overclocked laser, does a bit more damage but has much higher wound power (-0 vs -20) +/obj/item/projectile/beam/laser/hellfire + name = "hellfire laser" + wound_bonus = 0 + damage = 25 + +/obj/item/projectile/beam/laser/hellfire/Initialize() + . = ..() + transform *= 2 /obj/item/projectile/beam/laser/heavylaser name = "heavy laser" @@ -39,9 +53,6 @@ /obj/item/projectile/beam/weak damage = 15 -/obj/item/projectile/beam/weak/improvised - damage = 10 - /obj/item/projectile/beam/weak/penetrator armour_penetration = 50 @@ -93,6 +104,7 @@ tracer_type = /obj/effect/projectile/tracer/pulse muzzle_type = /obj/effect/projectile/muzzle/pulse impact_type = /obj/effect/projectile/impact/pulse + wound_bonus = 10 /obj/item/projectile/beam/pulse/on_hit(atom/target, blocked = FALSE) . = ..() @@ -119,6 +131,8 @@ damage = 30 impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser light_color = LIGHT_COLOR_GREEN + wound_bonus = -40 + bare_wound_bonus = 70 /obj/item/projectile/beam/emitter/singularity_pull() return diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 6d03012315..b408957aa7 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -8,3 +8,12 @@ flag = "bullet" hitsound_wall = "ricochet" impact_effect_type = /obj/effect/temp_visual/impact_effect + sharpness = SHARP_POINTY + shrapnel_type = /obj/item/shrapnel/bullet + embedding = list(embed_chance=15, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10) + wound_falloff_tile = -5 + embed_falloff_tile = -5 + +/obj/item/projectile/bullet/smite + name = "divine retribution" + damage = 10 diff --git a/code/modules/projectiles/projectile/bullets/lmg.dm b/code/modules/projectiles/projectile/bullets/lmg.dm index 2ea1fe7c9a..e3eff6dcb0 100644 --- a/code/modules/projectiles/projectile/bullets/lmg.dm +++ b/code/modules/projectiles/projectile/bullets/lmg.dm @@ -25,8 +25,10 @@ /obj/item/projectile/bullet/mm195x129 name = "1.95x129mm bullet" - damage = 45 + damage = 40 armour_penetration = 5 + wound_bonus = -50 + wound_falloff_tile = 0 /obj/item/projectile/bullet/mm195x129_ap name = "1.95x129mm armor-piercing bullet" @@ -35,8 +37,12 @@ /obj/item/projectile/bullet/mm195x129_hp name = "1.95x129mm hollow-point bullet" - damage = 60 + damage = 50 armour_penetration = -60 + sharpness = SHARP_EDGED + wound_bonus = -40 + bare_wound_bonus = 30 + wound_falloff_tile = -8 /obj/item/projectile/bullet/incendiary/mm195x129 name = "1.95x129mm incendiary bullet" diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm index 62ff4adb11..23a749415c 100644 --- a/code/modules/projectiles/projectile/bullets/pistol.dm +++ b/code/modules/projectiles/projectile/bullets/pistol.dm @@ -3,11 +3,13 @@ /obj/item/projectile/bullet/c9mm name = "9mm bullet" damage = 20 + embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) /obj/item/projectile/bullet/c9mm_ap name = "9mm armor-piercing bullet" damage = 15 armour_penetration = 40 + embedding = null /obj/item/projectile/bullet/incendiary/c9mm name = "9mm incendiary bullet" @@ -48,15 +50,3 @@ L.Sleeping(300) else L.adjustStaminaLoss(25) - -// .32 ACP (Improvised Pistol) - -/obj/item/projectile/bullet/c32acp - name = ".32 bullet" - damage = 13 - -/obj/item/projectile/bullet/r32acp - name = ".32 rubber bullet" - damage = 3 - eyeblur = 1 - stamina = 20 diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm index 5643804ac1..ec3cadc31a 100644 --- a/code/modules/projectiles/projectile/bullets/revolver.dm +++ b/code/modules/projectiles/projectile/bullets/revolver.dm @@ -19,6 +19,9 @@ ricochet_chance = 50 ricochet_auto_aim_angle = 10 ricochet_auto_aim_range = 3 + wound_bonus = -20 + bare_wound_bonus = 10 + embedding = list(embed_chance=15, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=10) /obj/item/projectile/bullet/c38/match name = ".38 Match bullet" @@ -29,6 +32,7 @@ ricochet_incidence_leeway = 50 ricochet_decay_chance = 1 ricochet_decay_damage = 1 + wound_bonus = 0 /obj/item/projectile/bullet/c38/match/bouncy name = ".38 Rubber bullet" @@ -40,13 +44,21 @@ ricochet_chance = 130 ricochet_decay_damage = 0.8 shrapnel_type = NONE + sharpness = SHARP_NONE + embedding = null +// premium .38 ammo from cargo, weak against armor, lower base damage, but excellent at embedding and causing slice wounds at close range /obj/item/projectile/bullet/c38/dumdum name = ".38 DumDum bullet" damage = 15 armour_penetration = -30 ricochets_max = 0 - shrapnel_type = /obj/item/shrapnel/bullet/c38/dumdum + sharpness = SHARP_EDGED + wound_bonus = 20 + bare_wound_bonus = 20 + embedding = list(embed_chance=75, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) + wound_falloff_tile = -5 + embed_falloff_tile = -15 /obj/item/projectile/bullet/c38/rubber name = ".38 rubber bullet" @@ -99,6 +111,7 @@ /obj/item/projectile/bullet/a357 name = ".357 bullet" damage = 60 + wound_bonus = -70 /obj/item/projectile/bullet/a357/ap name = ".357 armor-piercing bullet" @@ -113,4 +126,15 @@ ricochet_auto_aim_angle = 50 ricochet_auto_aim_range = 6 ricochet_incidence_leeway = 80 - ricochet_decay_chance = 1 \ No newline at end of file + ricochet_decay_chance = 1 + +/obj/item/projectile/bullet/a357/dumdum + name = ".357 DumDum bullet" // the warcrime bullet + damage = 40 + armour_penetration = -20 + wound_bonus = 45 + bare_wound_bonus = 45 + sharpness = SHARP_EDGED + embedding = list(embed_chance=90, fall_chance=2, jostle_chance=5, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) + wound_falloff_tile = -1 + embed_falloff_tile = -5 diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm index ae1611cb00..ce30f5e787 100644 --- a/code/modules/projectiles/projectile/bullets/rifle.dm +++ b/code/modules/projectiles/projectile/bullets/rifle.dm @@ -3,12 +3,15 @@ /obj/item/projectile/bullet/a556 name = "5.56mm bullet" damage = 35 + wound_bonus = -40 // 7.62 (Nagant Rifle) /obj/item/projectile/bullet/a762 name = "7.62 bullet" damage = 60 + wound_bonus = -35 + wound_falloff_tile = 0 /obj/item/projectile/bullet/a762_enchanted name = "enchanted 7.62 bullet" diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index 264df22c76..69f976d213 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -1,11 +1,26 @@ /obj/item/projectile/bullet/shotgun_slug name = "12g shotgun slug" - damage = 60 + damage = 50 + sharpness = SHARP_POINTY + wound_bonus = 0 + +/obj/item/projectile/bullet/shotgun_slug/executioner + name = "executioner slug" // admin only, can dismember limbs + sharpness = SHARP_EDGED + wound_bonus = 80 + +/obj/item/projectile/bullet/shotgun_slug/pulverizer + name = "pulverizer slug" // admin only, can crush bones + sharpness = SHARP_NONE + wound_bonus = 80 /obj/item/projectile/bullet/shotgun_beanbag name = "beanbag slug" - damage = 5 + damage = 10 stamina = 70 + wound_bonus = 20 + sharpness = SHARP_NONE + embedding = null /obj/item/projectile/bullet/incendiary/shotgun name = "incendiary slug" @@ -71,17 +86,22 @@ return BULLET_ACT_HIT /obj/item/projectile/bullet/pellet - var/tile_dropoff = 0.75 + var/tile_dropoff = 0.45 var/tile_dropoff_s = 1.25 /obj/item/projectile/bullet/pellet/shotgun_buckshot name = "buckshot pellet" - damage = 12.5 + damage = 7.5 + wound_bonus = 5 + bare_wound_bonus = 5 + wound_falloff_tile = -2.5 // low damage + additional dropoff will already curb wounding potential anything past point blank /obj/item/projectile/bullet/pellet/shotgun_rubbershot name = "rubbershot pellet" damage = 2 stamina = 15 + sharpness = SHARP_NONE + embedding = null /obj/item/projectile/bullet/pellet/Range() ..() @@ -93,8 +113,10 @@ qdel(src) /obj/item/projectile/bullet/pellet/shotgun_improvised - tile_dropoff = 0.55 //Come on it does 6 damage don't be like that. + tile_dropoff = 0.35 //Come on it does 6 damage don't be like that. damage = 6 + wound_bonus = 0 + bare_wound_bonus = 7.5 /obj/item/projectile/bullet/pellet/shotgun_improvised/Initialize() . = ..() diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm index eb4c8e9776..5c9d5b92a3 100644 --- a/code/modules/projectiles/projectile/bullets/smg.dm +++ b/code/modules/projectiles/projectile/bullets/smg.dm @@ -3,6 +3,8 @@ /obj/item/projectile/bullet/c45 name = ".45 bullet" damage = 30 + wound_bonus = -10 + wound_falloff_tile = -10 /obj/item/projectile/bullet/c45_cleaning name = ".45 bullet" @@ -51,11 +53,15 @@ /obj/item/projectile/bullet/c46x30mm name = "4.6x30mm bullet" damage = 15 + wound_bonus = -5 + bare_wound_bonus = 5 + embed_falloff_tile = -4 /obj/item/projectile/bullet/c46x30mm_ap name = "4.6x30mm armor-piercing bullet" damage = 12.5 armour_penetration = 40 + embedding = null /obj/item/projectile/bullet/incendiary/c46x30mm name = "4.6x30mm incendiary bullet" diff --git a/code/modules/projectiles/projectile/energy/misc.dm b/code/modules/projectiles/projectile/energy/misc.dm index d5346b954d..bfa15e9ef8 100644 --- a/code/modules/projectiles/projectile/energy/misc.dm +++ b/code/modules/projectiles/projectile/energy/misc.dm @@ -13,3 +13,13 @@ damage_type = TOX knockdown = 100 range = 7 + +/obj/item/projectile/energy/pickle //projectile for adminspawn only gun + name = "pickle-izing beam" + icon_state = "declone" + +/obj/item/projectile/energy/pickle/on_hit(atom/target) + //we don't care if they blocked it, they're turning into a pickle + if(isliving(target)) + var/mob/living/living_target = target + living_target.turn_into_pickle() //yes this is a real proc diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm index 493a02d74c..c9ca4e9ba3 100644 --- a/code/modules/projectiles/projectile/magic.dm +++ b/code/modules/projectiles/projectile/magic.dm @@ -121,10 +121,10 @@ qdel(src) /proc/wabbajack(mob/living/M) - if(!istype(M) || M.stat == DEAD || M.notransform || (GODMODE & M.status_flags)) + if(!istype(M) || M.stat == DEAD || M.mob_transforming || (GODMODE & M.status_flags)) return - M.notransform = TRUE + M.mob_transforming = TRUE M.Paralyze(INFINITY) M.icon = null M.cut_overlays() @@ -207,7 +207,8 @@ /mob/living/simple_animal/pet/fox, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/pet/cat/cak, - /mob/living/simple_animal/chick) + /mob/living/simple_animal/chick, + /mob/living/simple_animal/pickle) new_mob = new path(M.loc) if("humanoid") diff --git a/code/modules/projectiles/projectile/special/plasma.dm b/code/modules/projectiles/projectile/special/plasma.dm index 33559fa92c..77509cb574 100644 --- a/code/modules/projectiles/projectile/special/plasma.dm +++ b/code/modules/projectiles/projectile/special/plasma.dm @@ -2,7 +2,7 @@ name = "plasma blast" icon_state = "plasmacutter" damage_type = BRUTE - damage = 20 + damage = 10 range = 4 dismemberment = 20 impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser @@ -32,12 +32,12 @@ return BULLET_ACT_FORCE_PIERCE /obj/item/projectile/plasma/adv - damage = 28 + damage = 14 range = 5 mine_range = 5 /obj/item/projectile/plasma/adv/mech - damage = 40 + damage = 20 range = 9 mine_range = 3 @@ -52,4 +52,4 @@ dismemberment = 0 damage = 10 range = 4 - mine_range = 0 \ No newline at end of file + mine_range = 0 diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 4cf50cd072..c489edf88e 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -463,17 +463,10 @@ if(total_matching_reagents == total_required_reagents && total_matching_catalysts == total_required_catalysts && matching_container && matching_other && meets_temp_requirement && can_special_react) possible_reactions += C + sortTim(possible_reactions, /proc/cmp_chemical_reactions_default, FALSE) + if(possible_reactions.len) var/datum/chemical_reaction/selected_reaction = possible_reactions[1] - //select the reaction with the most extreme temperature requirements - for(var/V in possible_reactions) - var/datum/chemical_reaction/competitor = V - if(selected_reaction.is_cold_recipe) - if(competitor.required_temp <= selected_reaction.required_temp) - selected_reaction = competitor - else - if(competitor.required_temp >= selected_reaction.required_temp) //will return with the hotter reacting first. - selected_reaction = competitor var/list/cached_required_reagents = selected_reaction.required_reagents//update reagents list var/list/cached_results = selected_reaction.results//resultant chemical list var/special_react_result = selected_reaction.check_special_react(src) @@ -1172,3 +1165,9 @@ random_reagents += R var/picked_reagent = pick(random_reagents) return picked_reagent + +/proc/get_chem_id(chem_name) + for(var/X in GLOB.chemical_reagents_list) + var/datum/reagent/R = GLOB.chemical_reagents_list[X] + if(ckey(chem_name) == ckey(lowertext(R.name))) + return X diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index b85d7aefc9..db16a10d1d 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -32,7 +32,6 @@ var/nopower_state = "dispenser_nopower" var/has_panel_overlay = TRUE var/obj/item/reagent_containers/beaker = null - //dispensable_reagents is copypasted in plumbing synthesizers. Please update accordingly. (I didn't make it global because that would limit custom chem dispensers) var/list/dispensable_reagents = list( /datum/reagent/hydrogen, /datum/reagent/lithium, @@ -178,11 +177,10 @@ beaker = null update_icon() -/obj/machinery/chem_dispenser/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/chem_dispenser/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "chem_dispenser", name, 565, 550, master_ui, state) + ui = new(user, src, "ChemDispenser", name) if(user.hallucinating()) ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals ui.open() @@ -217,7 +215,7 @@ data["beakerTransferAmounts"] = null data["beakerCurrentpH"] = null - var/list/chemicals = list() + var/chemicals[0] var/is_hallucinating = FALSE if(user.hallucinating()) is_hallucinating = TRUE @@ -276,7 +274,7 @@ . = TRUE if("eject") replace_beaker(usr) - . = TRUE //no afterattack + . = TRUE if("dispense_recipe") if(!is_operational() || QDELETED(cell)) return @@ -327,9 +325,9 @@ for(var/reagent in recording_recipe) var/reagent_id = GLOB.name2reagent[translate_legacy_chem_id(reagent)] if(!dispensable_reagents.Find(reagent_id)) - visible_message("[src] buzzes.", "You hear a faint buzz.") + visible_message("[src] buzzes.", "You hear a faint buzz.") to_chat(usr, "[src] cannot find [reagent]!") - playsound(src, 'sound/machines/buzz-two.ogg', 50, 1) + playsound(src, 'sound/machines/buzz-two.ogg', 50, TRUE) return saved_recipes[name] = recording_recipe recording_recipe = null diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index 8572d30efe..28f0b2366a 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -7,6 +7,7 @@ idle_power_usage = 40 resistance_flags = FIRE_PROOF | ACID_PROOF circuit = /obj/item/circuitboard/machine/chem_heater + var/obj/item/reagent_containers/beaker = null var/target_temperature = 300 var/heater_coefficient = 0.1 @@ -30,22 +31,20 @@ /obj/machinery/chem_heater/AltClick(mob/living/user) . = ..() - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) + if(!can_interact(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return replace_beaker(user) - return TRUE /obj/machinery/chem_heater/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) + if(!user) + return FALSE if(beaker) - beaker.forceMove(drop_location()) - if(user && Adjacent(user) && user.can_hold_items()) - user.put_in_hands(beaker) + user.put_in_hands(beaker) + beaker = null if(new_beaker) beaker = new_beaker - else - beaker = null - update_icon() - return TRUE + update_icon() + return TRUE /obj/machinery/chem_heater/RefreshParts() heater_coefficient = 0.1 @@ -63,6 +62,7 @@ return if(on) if(beaker && beaker.reagents.total_volume) + //keep constant with the chemical acclimator please beaker.reagents.adjust_thermal_energy((target_temperature - beaker.reagents.chem_temp) * heater_coefficient * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume) beaker.reagents.handle_reactions() @@ -83,27 +83,16 @@ updateUsrDialog() update_icon() return - - if(beaker) - if(istype(I, /obj/item/reagent_containers/dropper)) - var/obj/item/reagent_containers/dropper/D = I - D.afterattack(beaker, user, 1) - - if(istype(I, /obj/item/reagent_containers/syringe)) - var/obj/item/reagent_containers/syringe/S = I - S.afterattack(beaker, user, 1) - return ..() /obj/machinery/chem_heater/on_deconstruction() replace_beaker() return ..() -/obj/machinery/chem_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.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/chem_heater/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "chem_heater", name, 275, 400, master_ui, state) + ui = new(user, src, "ChemHeater", name) ui.open() /obj/machinery/chem_heater/ui_data() @@ -140,14 +129,7 @@ . = TRUE if("temperature") var/target = params["target"] - var/adjust = text2num(params["adjust"]) - if(target == "input") - target = input("New target temperature:", name, target_temperature) as num|null - if(!isnull(target) && !..()) - . = TRUE - else if(adjust) - target = target_temperature + adjust - else if(text2num(target) != null) + if(text2num(target) != null) target = text2num(target) . = TRUE if(.) @@ -155,4 +137,4 @@ if("eject") on = FALSE replace_beaker(usr) - . = TRUE \ No newline at end of file + . = TRUE diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 50e818abe6..32ac7cecba 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -1,5 +1,3 @@ -#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die -#define RANDOM_PILL_STYLE 22 //Dont change this one though /obj/machinery/chem_master name = "ChemMaster 3000" @@ -12,6 +10,7 @@ idle_power_usage = 20 resistance_flags = FIRE_PROOF | ACID_PROOF circuit = /obj/item/circuitboard/machine/chem_master + var/obj/item/reagent_containers/beaker = null var/obj/item/storage/pill_bottle/bottle = null var/mode = 1 @@ -32,7 +31,7 @@ for (var/x in 1 to PILL_STYLE_COUNT) var/list/SL = list() SL["id"] = x - SL["htmltag"] = assets.icon_class_name("pill[x]") + SL["className"] = assets.icon_class_name("pill[x]") pillStyles += list(SL) . = ..() @@ -154,19 +153,16 @@ bottle?.forceMove(A) return ..() -/obj/machinery/chem_master/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills) - assets.send(user) - ui = new(user, src, ui_key, "chem_master", name, 500, 550, master_ui, state) - ui.open() +/obj/machinery/chem_master/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/simple/pills), + ) -//Insert our custom spritesheet css link into the html -/obj/machinery/chem_master/ui_base_html(html) - var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills) - . = replacetext(html, "", assets.css_tag()) +/obj/machinery/chem_master/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ChemMaster", name) + ui.open() /obj/machinery/chem_master/ui_data(mob/user) var/list/data = list() @@ -182,8 +178,8 @@ data["isPillBottleLoaded"] = bottle ? 1 : 0 if(bottle) var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage) - data["pillBotContent"] = bottle.contents.len - data["pillBotMaxContent"] = STRB.max_items + data["pillBottleCurrentAmount"] = bottle.contents.len + data["pillBottleMaxAmount"] = STRB.max_items var/beakerContents[0] if(beaker) @@ -205,216 +201,219 @@ if(..()) return - switch(action) - if("eject") - replace_beaker(usr) - . = TRUE + if(action == "eject") + replace_beaker(usr) + return TRUE - if("ejectPillBottle") - replace_pillbottle(usr) - . = TRUE - - if("transfer") - if(!beaker) - return FALSE - var/reagent = GLOB.name2reagent[params["id"]] - var/amount = text2num(params["amount"]) - var/to_container = params["to"] - // Custom amount - if (amount == -1) - amount = text2num(input( - "Enter the amount you want to transfer:", - name, "")) - if (amount == null || amount <= 0) - return FALSE - if (to_container == "buffer") - end_fermi_reaction() - beaker.reagents.trans_id_to(src, reagent, amount) - return TRUE - if (to_container == "beaker" && mode) - end_fermi_reaction() - reagents.trans_id_to(beaker, reagent, amount) - return TRUE - if (to_container == "beaker" && !mode) - end_fermi_reaction() - reagents.remove_reagent(reagent, amount) - return TRUE + if(action == "ejectPillBottle") + if(!bottle) return FALSE + bottle.forceMove(drop_location()) + adjust_item_drop_location(bottle) + bottle = null + return TRUE - if("toggleMode") - mode = !mode - . = TRUE + if(action == "transfer") + if(!beaker) + return FALSE + var/reagent = GLOB.name2reagent[params["id"]] + var/amount = text2num(params["amount"]) + var/to_container = params["to"] + // Custom amount + if (amount == -1) + amount = text2num(input( + "Enter the amount you want to transfer:", + name, "")) + if (amount == null || amount <= 0) + return FALSE + if (to_container == "buffer") + end_fermi_reaction() + beaker.reagents.trans_id_to(src, reagent, amount) + return TRUE + if (to_container == "beaker" && mode) + end_fermi_reaction() + reagents.trans_id_to(beaker, reagent, amount) + return TRUE + if (to_container == "beaker" && !mode) + end_fermi_reaction() + reagents.remove_reagent(reagent, amount) + return TRUE + return FALSE - if("pillStyle") - var/id = text2num(params["id"]) - chosenPillStyle = id + if(action == "toggleMode") + mode = !mode + return TRUE + + if(action == "pillStyle") + var/id = text2num(params["id"]) + chosenPillStyle = id + return TRUE + + if(action == "create") + if(reagents.total_volume == 0) + return FALSE + var/item_type = params["type"] + // Get amount of items + var/amount = text2num(params["amount"]) + if(amount == null) + amount = text2num(input(usr, + "Max 10. Buffer content will be split evenly.", + "How many to make?", 1)) + amount = clamp(round(amount), 0, 10) + if (amount <= 0) + return FALSE + // Get units per item + var/vol_each = text2num(params["volume"]) + var/vol_each_text = params["volume"] + var/vol_each_max = reagents.total_volume / amount + if (item_type == "pill") + vol_each_max = min(50, vol_each_max) + else if (item_type == "patch") + vol_each_max = min(40, vol_each_max) + else if (item_type == "bottle") + vol_each_max = min(30, vol_each_max) + else if (item_type == "condimentPack") + vol_each_max = min(10, vol_each_max) + else if (item_type == "condimentBottle") + vol_each_max = min(50, vol_each_max) + else if (item_type == "hypoVial") + vol_each_max = min(60, vol_each_max) + else if (item_type == "smartDart") + vol_each_max = min(20, vol_each_max) + else + return FALSE + if(vol_each_text == "auto") + vol_each = vol_each_max + if(vol_each == null) + vol_each = text2num(input(usr, + "Maximum [vol_each_max] units per item.", + "How many units to fill?", + vol_each_max)) + vol_each = clamp(vol_each, 0, vol_each_max) + if(vol_each <= 0) + return FALSE + // Get item name + var/name = params["name"] + var/name_has_units = item_type == "pill" || item_type == "patch" + if(!name) + var/name_default = reagents.get_master_reagent_name() + if (name_has_units) + name_default += " ([vol_each]u)" + name = stripped_input(usr, + "Name:", + "Give it a name!", + name_default, + MAX_NAME_LEN) + if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) + return FALSE + // Start filling + if(item_type == "pill") + var/obj/item/reagent_containers/pill/P + var/target_loc = drop_location() + var/drop_threshold = INFINITY + if(bottle) + var/datum/component/storage/STRB = bottle.GetComponent( + /datum/component/storage) + if(STRB) + drop_threshold = STRB.max_items - bottle.contents.len + for(var/i = 0; i < amount; i++) + if(i < drop_threshold) + P = new/obj/item/reagent_containers/pill(target_loc) + else + P = new/obj/item/reagent_containers/pill(drop_location()) + P.name = trim("[name] pill") + if(chosenPillStyle == RANDOM_PILL_STYLE) + P.icon_state ="pill[rand(1,21)]" + else + P.icon_state = "pill[chosenPillStyle]" + if(P.icon_state == "pill4") + P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality." + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each)//, transfered_by = usr) + return TRUE + if(item_type == "patch") + var/obj/item/reagent_containers/pill/patch/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/pill/patch(drop_location()) + P.name = trim("[name] patch") + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each)//, transfered_by = usr) + return TRUE + if(item_type == "bottle") + var/obj/item/reagent_containers/glass/bottle/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/glass/bottle(drop_location()) + P.name = trim("[name] bottle") + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each)//, transfered_by = usr) + return TRUE + if(item_type == "condimentPack") + var/obj/item/reagent_containers/food/condiment/pack/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/food/condiment/pack(drop_location()) + P.originalname = name + P.name = trim("[name] pack") + P.desc = "A small condiment pack. The label says it contains [name]." + reagents.trans_to(P, vol_each)//, transfered_by = usr) + return TRUE + if(item_type == "condimentBottle") + var/obj/item/reagent_containers/food/condiment/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/food/condiment(drop_location()) + P.originalname = name + P.name = trim("[name] bottle") + reagents.trans_to(P, vol_each)//, transfered_by = usr) + return TRUE + if(item_type == "hypoVial") + var/obj/item/reagent_containers/glass/bottle/vial/small/P + for(var/i = 0; i < amount; i++) + P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location()) + P.name = trim("[name] hypovial") + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each)//, transfered_by = usr) + return TRUE + if(item_type == "smartDart") + var/obj/item/reagent_containers/syringe/dart/P + for(var/i = 0; i < amount; i++) + P = new /obj/item/reagent_containers/syringe/dart(drop_location()) + P.name = trim("[name] SmartDart") + adjust_item_drop_location(P) + reagents.trans_to(P, vol_each)//, transfered_by = usr) + P.mode=!mode + P.update_icon() + return TRUE + return FALSE + + if(action == "analyze") + // var/datum/reagent/R = GLOB.name2reagent[params["id"]] + var/reagent = GLOB.name2reagent[params["id"]] + var/datum/reagent/R = GLOB.chemical_reagents_list[reagent] + if(R) + var/state = "Unknown" + if(initial(R.reagent_state) == 1) + state = "Solid" + else if(initial(R.reagent_state) == 2) + state = "Liquid" + else if(initial(R.reagent_state) == 3) + state = "Gas" + var/const/P = 3 //The number of seconds between life ticks + var/T = initial(R.metabolization_rate) * (60 / P) + if(istype(R, /datum/reagent/fermi)) + fermianalyze = TRUE + var/datum/chemical_reaction/Rcr = get_chemical_reaction(reagent) + var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2 + analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = R.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache) + else + fermianalyze = FALSE + analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold)) + screen = "analyze" return TRUE - if("create") - if(reagents.total_volume == 0) - return FALSE - var/item_type = params["type"] - // Get amount of items - var/amount = text2num(params["amount"]) - if(amount == null) - amount = text2num(input(usr, - "Max 10. Buffer content will be split evenly.", - "How many to make?", 1)) - amount = clamp(round(amount), 0, 10) - if (amount <= 0) - return FALSE - // Get units per item - var/vol_each = text2num(params["volume"]) - var/vol_each_text = params["volume"] - var/vol_each_max = reagents.total_volume / amount - if (item_type == "pill") - vol_each_max = min(50, vol_each_max) - else if (item_type == "patch") - vol_each_max = min(40, vol_each_max) - else if (item_type == "bottle") - vol_each_max = min(30, vol_each_max) - else if (item_type == "condimentPack") - vol_each_max = min(10, vol_each_max) - else if (item_type == "condimentBottle") - vol_each_max = min(50, vol_each_max) - else if (item_type == "hypoVial") - vol_each_max = min(60, vol_each_max) - else if (item_type == "smartDart") - vol_each_max = min(20, vol_each_max) - else - return FALSE - if(vol_each_text == "auto") - vol_each = vol_each_max - if(vol_each == null) - vol_each = text2num(input(usr, - "Maximum [vol_each_max] units per item.", - "How many units to fill?", - vol_each_max)) - vol_each = clamp(vol_each, 0, vol_each_max) - if(vol_each <= 0) - return FALSE - // Get item name - var/name = params["name"] - var/name_has_units = item_type == "pill" || item_type == "patch" - if(!name) - var/name_default = reagents.get_master_reagent_name() - if (name_has_units) - name_default += " ([vol_each]u)" - name = stripped_input(usr, - "Name:", - "Give it a name!", - name_default, - MAX_NAME_LEN) - if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr))) - return FALSE - // Start filling - if(item_type == "pill") - var/obj/item/reagent_containers/pill/P - var/target_loc = drop_location() - var/drop_threshold = INFINITY - if(bottle) - var/datum/component/storage/STRB = bottle.GetComponent( - /datum/component/storage) - if(STRB) - drop_threshold = STRB.max_items - bottle.contents.len - for(var/i = 0; i < amount; i++) - if(i < drop_threshold) - P = new/obj/item/reagent_containers/pill(target_loc) - else - P = new/obj/item/reagent_containers/pill(drop_location()) - P.name = trim("[name] pill") - if(chosenPillStyle == RANDOM_PILL_STYLE) - P.icon_state ="pill[rand(1,21)]" - else - P.icon_state = "pill[chosenPillStyle]" - if(P.icon_state == "pill4") - P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality." - adjust_item_drop_location(P) - reagents.trans_to(P, vol_each) - return TRUE - if(item_type == "patch") - var/obj/item/reagent_containers/pill/patch/P - for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/pill/patch(drop_location()) - P.name = trim("[name] patch") - adjust_item_drop_location(P) - reagents.trans_to(P, vol_each) - return TRUE - if(item_type == "bottle") - var/obj/item/reagent_containers/glass/bottle/P - for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/glass/bottle(drop_location()) - P.name = trim("[name] bottle") - adjust_item_drop_location(P) - reagents.trans_to(P, vol_each) - return TRUE - if(item_type == "condimentPack") - var/obj/item/reagent_containers/food/condiment/pack/P - for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/food/condiment/pack(drop_location()) - P.originalname = name - P.name = trim("[name] pack") - P.desc = "A small condiment pack. The label says it contains [name]." - reagents.trans_to(P, vol_each) - return TRUE - if(item_type == "condimentBottle") - var/obj/item/reagent_containers/food/condiment/P - for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/food/condiment(drop_location()) - P.originalname = name - P.name = trim("[name] bottle") - reagents.trans_to(P, vol_each) - return TRUE - if(item_type == "hypoVial") - var/obj/item/reagent_containers/glass/bottle/vial/small/P - for(var/i = 0; i < amount; i++) - P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location()) - P.name = trim("[name] hypovial") - adjust_item_drop_location(P) - reagents.trans_to(P, vol_each) - return TRUE - if(item_type == "smartDart") - var/obj/item/reagent_containers/syringe/dart/P - for(var/i = 0; i < amount; i++) - P = new /obj/item/reagent_containers/syringe/dart(drop_location()) - P.name = trim("[name] SmartDart") - adjust_item_drop_location(P) - reagents.trans_to(P, vol_each) - P.mode=!mode - P.update_icon() - return TRUE - return FALSE + if(action == "goScreen") + screen = params["screen"] + return TRUE - if("analyze") - var/datum/reagent/R = GLOB.name2reagent[params["id"]] - if(R) - var/state = "Unknown" - if(initial(R.reagent_state) == 1) - state = "Solid" - else if(initial(R.reagent_state) == 2) - state = "Liquid" - else if(initial(R.reagent_state) == 3) - state = "Gas" - var/const/P = 3 //The number of seconds between life ticks - var/T = initial(R.metabolization_rate) * (60 / P) - if(istype(R, /datum/reagent/fermi)) - fermianalyze = TRUE - var/datum/chemical_reaction/Rcr = get_chemical_reaction(R) - var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2 - var/datum/reagent/targetReagent = reagents.has_reagent(R) - - if(!targetReagent) - CRASH("Tried to find a reagent that doesn't exist in the chem_master!") - analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache) - else - fermianalyze = FALSE - analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold)) - screen = "analyze" - return TRUE - - if("goScreen") - screen = params["screen"] - . = TRUE + return FALSE diff --git a/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm b/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm index ed23e7c75c..489f9dd179 100644 --- a/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm +++ b/code/modules/reagents/chemistry/machinery/chem_synthesizer.dm @@ -12,11 +12,10 @@ "tricord" = /datum/reagent/medicine/tricordrazine ) -/obj/machinery/chem_dispenser/chem_synthesizer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/chem_dispenser/chem_synthesizer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "chem_synthesizer", name, 390, 330, master_ui, state) + ui = new(user, src, "ChemDebugSynthesizer", name) ui.open() /obj/machinery/chem_dispenser/chem_synthesizer/ui_act(action, params) @@ -31,7 +30,11 @@ beaker = null . = TRUE if("input") - var/input_reagent = replacetext(lowertext(input("Enter the name of any reagent", "Input") as text), " ", "") //95% of the time, the reagent types is a lowercase, no spaces / underscored version of the name + var/input_reagent = replacetext(lowertext(input("Enter the name of any reagent", "Input") as text|null), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name + + if (isnull(input_reagent)) + return + if(shortcuts[input_reagent]) input_reagent = shortcuts[input_reagent] else @@ -51,7 +54,7 @@ beaker = new /obj/item/reagent_containers/glass/beaker/bluespace(src) visible_message("[src] dispenses a bluespace beaker.") if("amount") - var/input = input("Units to dispense", "Units") as num|null + var/input = text2num(params["amount"]) if(input) amount = input update_icon() diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index 38a05cd541..36e102be72 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -7,10 +7,11 @@ density = TRUE icon = 'icons/obj/chemical.dmi' icon_state = "mixer0" - circuit = /obj/item/circuitboard/computer/pandemic use_power = TRUE idle_power_usage = 20 resistance_flags = ACID_PROOF + circuit = /obj/item/circuitboard/computer/pandemic + var/wait var/datum/symptom/selected_symptom var/obj/item/reagent_containers/beaker @@ -23,11 +24,27 @@ QDEL_NULL(beaker) return ..() -/obj/machinery/computer/pandemic/handle_atom_del(atom/A) +/obj/machinery/computer/pandemic/examine(mob/user) . = ..() + if(beaker) + var/is_close + if(Adjacent(user)) //don't reveal exactly what's inside unless they're close enough to see the UI anyway. + . += "It contains \a [beaker]." + is_close = TRUE + else + . += "It has a beaker inside it." + . += "Alt-click to eject [is_close ? beaker : "the beaker"]." + +/obj/machinery/computer/pandemic/AltClick(mob/user) + . = ..() + if(user.canUseTopic(src, BE_CLOSE)) + eject_beaker() + +/obj/machinery/computer/pandemic/handle_atom_del(atom/A) if(A == beaker) beaker = null update_icon() + return ..() /obj/machinery/computer/pandemic/proc/get_by_index(thing, index) if(!beaker || !beaker.reagents) @@ -107,7 +124,7 @@ /obj/machinery/computer/pandemic/proc/reset_replicator_cooldown() wait = FALSE update_icon() - playsound(loc, 'sound/machines/ping.ogg', 30, 1) + playsound(src, 'sound/machines/ping.ogg', 30, TRUE) /obj/machinery/computer/pandemic/update_icon_state() if(stat & BROKEN) @@ -117,13 +134,19 @@ /obj/machinery/computer/pandemic/update_overlays() . = ..() - if(!(stat & BROKEN) && wait) + if(wait) . += "waitlight" -/obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/pandemic/proc/eject_beaker() + if(beaker) + beaker.forceMove(drop_location()) + beaker = null + update_icon() + +/obj/machinery/computer/pandemic/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "pandemic", name, 520, 550, master_ui, state) + ui = new(user, src, "Pandemic", name) ui.open() /obj/machinery/computer/pandemic/ui_data(mob/user) @@ -135,9 +158,9 @@ var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list if(B) data["has_blood"] = TRUE - data[/datum/reagent/blood] = list() - data[/datum/reagent/blood]["dna"] = B.data["blood_DNA"] || "none" - data[/datum/reagent/blood]["type"] = B.data["blood_type"] || "none" + data["blood"] = list() //wha why the fuck are we sending pathtypes to tgui frontend? + data["blood"]["dna"] = B.data["blood_DNA"] || "none" + data["blood"]["type"] = B.data["blood_type"] || "none" data["viruses"] = get_viruses_data(B) data["resistances"] = get_resistance_data(B) else @@ -153,7 +176,7 @@ return switch(action) if("eject_beaker") - replace_beaker(usr) + eject_beaker() . = TRUE if("empty_beaker") if(beaker) @@ -162,7 +185,7 @@ if("empty_eject_beaker") if(beaker) beaker.reagents.clear_reagents() - replace_beaker(usr) + eject_beaker() . = TRUE if("rename_disease") var/id = get_virus_id_by_index(text2num(params["index"])) @@ -170,75 +193,62 @@ if(!A.mutable) return if(A) - var/new_name = sanitize_name(html_encode(trim(params["name"], 50))) + var/new_name = sanitize_name(html_encode(trim(params["name"], 50)))//, allow_numbers = TRUE) if(!new_name || ..()) return A.AssignName(new_name) . = TRUE if("create_culture_bottle") + if (wait) + return var/id = get_virus_id_by_index(text2num(params["index"])) var/datum/disease/advance/A = SSdisease.archive_diseases[id] if(!istype(A) || !A.mutable) to_chat(usr, "ERROR: Cannot replicate virus strain.") return - wait = TRUE - addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50) A = A.Copy() - var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY", "viruses" = list(A)) + var/list/data = list("viruses" = list(A)) var/obj/item/reagent_containers/glass/bottle/B = new(drop_location()) B.name = "[A.name] culture bottle" B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium." B.reagents.add_reagent(/datum/reagent/blood/synthetics, 10, data) + wait = TRUE update_icon() var/turf/source_turf = get_turf(src) log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]") - + addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50) . = TRUE if("create_vaccine_bottle") - wait = TRUE - addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 400) + if (wait) + return var/id = params["index"] var/datum/disease/D = SSdisease.archive_diseases[id] var/obj/item/reagent_containers/glass/bottle/B = new(drop_location()) B.name = "[D.name] vaccine bottle" B.reagents.add_reagent(/datum/reagent/vaccine, 15, list(id)) - + wait = TRUE update_icon() - + addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 200) . = TRUE + /obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container()) . = TRUE //no afterattack if(stat & (NOPOWER|BROKEN)) return - var/obj/item/reagent_containers/B = I - if(!user.transferItemToLoc(B, src)) + if(beaker) + to_chat(user, "A container is already loaded into [src]!") return - replace_beaker(user, B) + if(!user.transferItemToLoc(I, src)) + return + + beaker = I to_chat(user, "You insert [I] into [src].") + update_icon() else return ..() -/obj/machinery/computer/pandemic/AltClick(mob/living/user) - . = ..() - if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) - return - replace_beaker(user) - return TRUE - -/obj/machinery/computer/pandemic/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker) - if(beaker) - if(user && Adjacent(user) && user.can_hold_items()) - if(!user.put_in_hands(beaker)) - beaker.forceMove(drop_location()) - if(new_beaker) - beaker = new_beaker - else - beaker = null - update_icon() - return TRUE - /obj/machinery/computer/pandemic/on_deconstruction() - replace_beaker(usr) + eject_beaker() . = ..() diff --git a/code/modules/reagents/chemistry/machinery/smoke_machine.dm b/code/modules/reagents/chemistry/machinery/smoke_machine.dm index 0a08395c1b..d22523c4b8 100644 --- a/code/modules/reagents/chemistry/machinery/smoke_machine.dm +++ b/code/modules/reagents/chemistry/machinery/smoke_machine.dm @@ -7,6 +7,7 @@ icon_state = "smoke0" density = TRUE circuit = /obj/item/circuitboard/machine/smoke_machine + var/efficiency = 10 var/on = FALSE var/cooldown = 0 @@ -31,9 +32,18 @@ /obj/machinery/smoke_machine/Initialize() . = ..() create_reagents(REAGENTS_BASE_VOLUME) + // AddComponent(/datum/component/plumbing/simple_demand) for(var/obj/item/stock_parts/matter_bin/B in component_parts) reagents.maximum_volume += REAGENTS_BASE_VOLUME * B.rating +/obj/machinery/smoke_machine/ComponentInitialize() + . = ..() + AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated)) + AddComponent(/datum/component/plumbing/simple_demand) //this SURELY CANT' LEAD TO BAD THINGS HAPPENING. + +/obj/machinery/smoke_machine/proc/can_be_rotated(mob/user, rotation_type) + return !anchored + /obj/machinery/smoke_machine/update_icon_state() if((!is_operational()) || (!on) || (reagents.total_volume == 0)) if (panel_open) @@ -81,10 +91,9 @@ add_fingerprint(user) if(istype(I, /obj/item/reagent_containers) && I.is_open_container()) var/obj/item/reagent_containers/RC = I - var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this) + var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this) //, transfered_by = user) if(units) to_chat(user, "You transfer [units] units of the solution to [src].") - log_combat(usr, src, "has added [english_list(RC.reagents.reagent_list)] to [src]") return if(default_unfasten_wrench(user, I, 40)) on = FALSE @@ -100,11 +109,10 @@ reagents.clear_reagents() return ..() -/obj/machinery/smoke_machine/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/smoke_machine/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "smoke_machine", name, 350, 350, master_ui, state) + ui = new(user, src, "SmokeMachine", name) ui.open() /obj/machinery/smoke_machine/ui_data(mob/user) diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index a85ac8b085..672127cb11 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -8,6 +8,7 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) if (length(initial(R.name))) .[ckey(initial(R.name))] = t + //Various reagents //Toxin & acid reagents //Hydroponics stuff @@ -52,6 +53,14 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) var/metabolizing = FALSE var/chemical_flags // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME var/value = REAGENT_VALUE_NONE //How much does it sell for in cargo? + var/datum/material/material //are we made of material? + +/datum/reagent/New() + . = ..() + + if(material) + material = SSmaterials.GetMaterialRef(material) + /datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references . = ..() @@ -220,4 +229,3 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent()) bloodsuckerdatum.handle_eat_human_food(disgust, blood_puke, force) if(blood_change) bloodsuckerdatum.AddBloodVolume(blood_change) - diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index b22f34091f..4034759c72 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1962,12 +1962,12 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/bug_spray/on_mob_life(mob/living/carbon/M) //Bugs should not drink Bug spray. - if(ismoth(M) || isflyperson(M)) + if(isinsect(M) || isflyperson(M)) M.adjustToxLoss(1,0) return ..() /datum/reagent/consumable/ethanol/bug_spray/on_mob_add(mob/living/carbon/M) - if(ismoth(M) || isflyperson(M)) + if(isinsect(M) || isflyperson(M)) M.emote("scream") return ..() @@ -2270,59 +2270,52 @@ All effects don't start immediately, but rather get worse over time; the rate is //////////////////// //Race-Base-Drinks// //////////////////// +/datum/reagent/consumable/ethanol/species_drink + var/species_required + var/disgust = 25 + boozepwr = 50 -/datum/reagent/consumable/ethanol/coldscales +/datum/reagent/consumable/ethanol/species_drink/on_mob_life(mob/living/carbon/C) + if(C.dna.species && C.dna.species.species_type == species_required) //species have a species_type variable that refers to one of the drinks + quality = RACE_DRINK + else + C.adjust_disgust(disgust) + +/datum/reagent/consumable/ethanol/species_drink/coldscales name = "Coldscales" color = "#5AEB52" //(90, 235, 82) description = "A cold looking drink made for people with scales." - boozepwr = 50 //strong! taste_description = "dead flies" glass_icon_state = "coldscales" glass_name = "glass of Coldscales" glass_desc = "A soft green drink that looks inviting!" -/datum/reagent/consumable/ethanol/coldscales/on_mob_life(mob/living/carbon/M) - if(islizard(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "lizard" -/datum/reagent/consumable/ethanol/oil_drum +/datum/reagent/consumable/ethanol/species_drink/oil_drum name = "Oil Drum" color = "#000000" //(0, 0, 0) - description = "Industeral grade oil mixed with some ethanol to make it a drink. Somehow not known to be toxic." + description = "Industrial grade oil mixed with some ethanol to make it a drink. Somehow not known to be toxic." boozepwr = 45 taste_description = "oil spill" glass_icon_state = "oil_drum" glass_name = "Drum of oil" glass_desc = "A gray can of booze and oil..." -/datum/reagent/consumable/ethanol/oil_drum/on_mob_life(mob/living/carbon/M) - if(isipcperson(M) || issynthliz(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "robot" -/datum/reagent/consumable/ethanol/nord_king +/datum/reagent/consumable/ethanol/species_drink/nord_king name = "Nord King" color = "#EB1010" //(235, 16, 16) - description = "Strong mead mixed with more honey and ethanol. Known to beloved by most palettes." - boozepwr = 50 //strong! + description = "Strong mead mixed with more honey and ethanol. Beloved by its human patrons." taste_description = "honey and red wine" glass_icon_state = "nord_king" glass_name = "Keg of Nord King" glass_desc = "A dripping keg of red mead." -/datum/reagent/consumable/ethanol/nord_king/on_mob_life(mob/living/carbon/M) - if(ishumanbasic(M) || isdwarf(M) || isangel(M)) //Humans and angel races are rare - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "basic" -/datum/reagent/consumable/ethanol/velvet_kiss +/datum/reagent/consumable/ethanol/species_drink/velvet_kiss name = "Velvet Kiss" color = "#EB1010" //(235, 16, 16) description = "A bloody drink mixed with wine." @@ -2332,14 +2325,9 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_name = "glass of Velvet Kiss" glass_desc = "Red and white drink for the upper classes or undead." -/datum/reagent/consumable/ethanol/velvet_kiss/on_mob_life(mob/living/carbon/M) - if(iszombie(M) || isvampire(M) || isdullahan(M)) //Rare races! - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "undead" -/datum/reagent/consumable/ethanol/abduction_fruit +/datum/reagent/consumable/ethanol/species_drink/abduction_fruit name = "Abduction Fruit" color = "#DEFACD" //(222, 250, 205) description = "Mixing of juices to make an alien taste." @@ -2347,33 +2335,23 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "grass and lime" glass_icon_state = "abduction_fruit" glass_name = "glass of Abduction Fruit" - glass_desc = "Mixed fruits that were never ment to be mixed..." + glass_desc = "Mixed fruits that were never meant to be mixed..." -/datum/reagent/consumable/ethanol/abduction_fruit/on_mob_life(mob/living/carbon/M) - if(isabductor(M) || isxenoperson(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "alien" -/datum/reagent/consumable/ethanol/bug_zapper +/datum/reagent/consumable/ethanol/species_drink/bug_zapper name = "Bug Zapper" color = "#F5882A" //(222, 250, 205) - description = "Metals and lemon juice. Hardly even a drink." + description = "Copper and lemon juice. Hardly even a drink." boozepwr = 5 //No booze really taste_description = "copper and AC power" glass_icon_state = "bug_zapper" glass_name = "glass of Bug Zapper" glass_desc = "An odd mix of copper, lemon juice and power meant for non-human consumption." -/datum/reagent/consumable/ethanol/bug_zapper/on_mob_life(mob/living/carbon/M) - if(isinsect(M) || isflyperson(M) || ismoth(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "bug" -/datum/reagent/consumable/ethanol/mush_crush +/datum/reagent/consumable/ethanol/species_drink/mush_crush name = "Mush Crush" color = "#F5882A" //(222, 250, 205) description = "Soil in a glass." @@ -2381,16 +2359,11 @@ All effects don't start immediately, but rather get worse over time; the rate is taste_description = "dirt and iron" glass_icon_state = "mush_crush" glass_name = "glass of Mush Crush" - glass_desc = "Popular among people that want to grow their own food rather then drink the soil." + glass_desc = "Popular among people that want to grow their own food rather than drink the soil." -/datum/reagent/consumable/ethanol/mush_crush/on_mob_life(mob/living/carbon/M) - if(ispodperson(M) || ismush(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "plant" -/datum/reagent/consumable/ethanol/darkbrew +/datum/reagent/consumable/ethanol/species_drink/darkbrew name = "Darkbrew" color = "#000000" //(0, 0, 0) description = "Contained dark matter mixed with coffee." @@ -2400,31 +2373,21 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_name = "glass of Darkbrew" glass_desc = "A pitch black drink that's commonly confused with a type of coffee." -/datum/reagent/consumable/ethanol/darkbrew/on_mob_life(mob/living/carbon/M) - if(isshadow(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "shadow" -/datum/reagent/consumable/ethanol/hollow_bone +/datum/reagent/consumable/ethanol/species_drink/hollow_bone name = "Hollow Bone" color = "#FCF7D4" //(252, 247, 212) - description = "Shockingly none-harmful mix of toxins and milk." + description = "Shockingly non-harmful mix of toxins and milk." boozepwr = 15 taste_description = "Milk and salt" glass_icon_state = "hollow_bone" glass_name = "skull of Hollow Bone" - glass_desc = "Mixing of milk and bone hurting juice for enjoyment for rather skinny people." + glass_desc = "Mixing of milk and bone hurting juice for the enjoyment of rather skinny people." -/datum/reagent/consumable/ethanol/hollow_bone/on_mob_life(mob/living/carbon/M) - if(isplasmaman(M) || isskeleton(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "skeleton" -/datum/reagent/consumable/ethanol/frisky_kitty +/datum/reagent/consumable/ethanol/species_drink/frisky_kitty name = "Frisky Kitty" color = "#FCF7D4" //(252, 247, 212) description = "Warm milk mixed with a catnip." @@ -2434,14 +2397,9 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_name = "cup of Drisky Kitty" glass_desc = "Warm milk and some catnip." -/datum/reagent/consumable/ethanol/frisky_kitty/on_mob_life(mob/living/carbon/M) - if(ismammal(M) || iscatperson(M)) //well its not to bad for mammals - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "furry" -/datum/reagent/consumable/ethanol/jell_wyrm +/datum/reagent/consumable/ethanol/species_drink/jell_wyrm name = "Jell Wyrm" color = "#FF6200" //(255, 98, 0) description = "Horrible mix of Co2, toxins and heat. Meant for slime based life." @@ -2451,15 +2409,9 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_name = "glass of Jell Wyrm" glass_desc = "A bubbly drink that is rather inviting to those that don't know who it's meant for." -/datum/reagent/consumable/ethanol/jell_wyrm/on_mob_life(mob/living/carbon/M) - if(isjellyperson(M) || isstartjelly(M) || isslimeperson(M) || isluminescent(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - M.adjustToxLoss(1, 0) //Low tox do to being carp + jell toxins. - return ..() + species_required = "jelly" -/datum/reagent/consumable/ethanol/laval_spit //Yes Laval +/datum/reagent/consumable/ethanol/species_drink/laval_spit //Yes Laval name = "Laval Spit" color = "#DE3009" //(222, 48, 9) description = "Heat minerals and some mauna loa. Meant for rock based life." @@ -2469,15 +2421,10 @@ All effects don't start immediately, but rather get worse over time; the rate is glass_name = "glass of Laval Spit" glass_desc = "Piping hot drink for those who can stomach the heat of lava." -/datum/reagent/consumable/ethanol/laval_spit/on_mob_life(mob/living/carbon/M) - if(isgolem(M)) - quality = RACE_DRINK - else - M.adjust_disgust(25) - return ..() + species_required = "golem" /////////////// -//Barrle Wine// +//Barrel Wine// /////////////// /datum/reagent/consumable/ethanol/fruit_wine diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index b157f328c5..e1433eb64e 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -217,6 +217,9 @@ /datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M) if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) M.heal_bodypart_damage(1.5,0, 0) + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_xadone(2) . = 1 else if(M.getBruteLoss() && prob(20)) @@ -320,6 +323,83 @@ ..() . = 1 +/datum/reagent/consumable/tea/red + name = "Red Tea" + description = "Tasty red tea, helps the body digest food. Drink in moderation!" + color = "#101000" // rgb: 16, 16, 0 + nutriment_factor = 0 + taste_description = "sweet red tea" + glass_icon_state = "teaglass" + glass_name = "glass of red tea" + glass_desc = "A piping hot tea that helps with the digestion of food." + +/datum/reagent/consumable/tea/red/on_mob_life(mob/living/carbon/M) + if(M.nutrition > NUTRITION_LEVEL_HUNGRY) + M.adjust_nutrition(-3) + M.dizziness = max(0,M.dizziness-2) + M.drowsyness = max(0,M.drowsyness-1) + M.jitteriness = max(0,M.jitteriness-3) + M.adjust_bodytemperature(23 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) + . = 1 + +/datum/reagent/consumable/tea/green + name = "Green Tea" + description = "Tasty green tea, known to heal livers, it's good for you!" + color = "#101000" // rgb: 16, 16, 0 + nutriment_factor = 0 + taste_description = "tart green tea" + glass_icon_state = "teaglass" + glass_name = "glass of tea" + glass_desc = "A calming glass of green tea to help get you through the day." + +/datum/reagent/consumable/tea/green/on_mob_life(mob/living/carbon/M) + M.adjustOrganLoss(ORGAN_SLOT_LIVER, -0.5) //Detox! + M.dizziness = max(0,M.dizziness-2) + M.drowsyness = max(0,M.drowsyness-1) + M.jitteriness = max(0,M.jitteriness-3) + M.adjust_bodytemperature(15 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) + . = 1 + +/datum/reagent/consumable/tea/forest + name = "Forest Tea" + description = "Tea mixed with honey, has both antitoxins and sweetness in one!" + color = "#101000" // rgb: 16, 16, 0 + nutriment_factor = 0 + quality = DRINK_NICE + taste_description = "sweet tea" + glass_icon_state = "teaglass" + glass_name = "glass of forest tea" + glass_desc = "A lovely glass of tea and honey." + +/datum/reagent/consumable/tea/forest/on_mob_life(mob/living/carbon/M) + if(M.getToxLoss() && prob(40))//Two anti-toxins working here + M.adjustToxLoss(-1, 0, TRUE) //heals TOXINLOVERs + //Reminder that honey heals toxin lovers + M.dizziness = max(0,M.dizziness-2) + M.drowsyness = max(0,M.drowsyness-1) + M.jitteriness = max(0,M.jitteriness-3) + M.adjust_bodytemperature(15 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL) + . = 1 + +/datum/reagent/consumable/tea/mush + name = "Mush Tea" + description = "Tea mixed with mushroom hallucinogen, used for fun rides or self reflection." + color = "#101000" // rgb: 16, 16, 0 + nutriment_factor = 0 + quality = DRINK_NICE + taste_description = "fungal infections" + glass_icon_state = "teaglass" + glass_name = "glass of mush tea" + glass_desc = "A cold merky brown tea." + +/datum/reagent/consumable/tea/mush/on_mob_life(mob/living/carbon/M) + M.set_drugginess(20) //Little better then space drugs + if(prob(20)) + M.Dizzy(10) + if(prob(10)) + M.disgust = 0 + . = 1 + /datum/reagent/consumable/lemonade name = "Lemonade" description = "Sweet, tangy lemonade. Good for the soul." @@ -964,12 +1044,6 @@ M.emote("nya") if(prob(20)) to_chat(M, "[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/adjusted = H.adjust_arousal(5,aphro = TRUE) - for(var/g in adjusted) - var/obj/item/organ/genital/G = g - to_chat(M, "You feel like playing with your [G.name]!") ..() /datum/reagent/consumable/monkey_energy @@ -999,3 +1073,37 @@ glass_name = "glass of bungo juice" glass_desc = "Exotic! You feel like you are on vacation already." value = REAGENT_VALUE_COMMON + +/datum/reagent/consumable/aloejuice + name = "Aloe Juice" + color = "#A3C48B" + description = "A healthy and refreshing juice." + taste_description = "vegetable" + glass_icon_state = "glass_yellow" + glass_name = "glass of aloe juice" + glass_desc = "A healthy and refreshing juice." + +/datum/reagent/consumable/aloejuice/on_mob_life(mob/living/M) + if(M.getToxLoss() && prob(30)) + M.adjustToxLoss(-1, 0) + ..() + . = TRUE + +// i googled "natural coagulant" and a couple of results came up for banana peels, so after precisely 30 more seconds of research, i now dub grinding banana peels good for your blood +/datum/reagent/consumable/banana_peel + name = "Pulped Banana Peel" + description = "Okay, so you put a banana peel in a grinder... Why, exactly?" + color = "#863333" // rgb: 175, 175, 0 + reagent_state = SOLID + taste_description = "stringy, bitter pulp" + glass_name = "glass of banana peel pulp" + glass_desc = "Okay, so you put a banana peel in a grinder... Why, exactly?" + +/datum/reagent/consumable/baked_banana_peel + name = "Baked Banana Peel Powder" + description = "You took a banana peel... pulped it... baked it... Where are you going with this?" + color = "#863333" // rgb: 175, 175, 0 + reagent_state = SOLID + taste_description = "bitter powder" + glass_name = "glass of banana peel powder" + description = "You took a banana peel... pulped it... baked it... Where are you going with this?" diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm index f1e45d0717..44b6e85f47 100644 --- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm @@ -467,7 +467,7 @@ /datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L) . = ..() L.add_movespeed_modifier(/datum/movespeed_modifier/reagent/skooma) - L.next_move_modifier *= 2 + L.action_cooldown_mod *= 2 if(ishuman(L)) var/mob/living/carbon/human/H = L if(H.physiology) @@ -480,7 +480,7 @@ /datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L) . = ..() L.remove_movespeed_modifier(/datum/movespeed_modifier/reagent/skooma) - L.next_move_modifier *= 0.5 + L.action_cooldown_mod *= 0.5 if(ishuman(L)) var/mob/living/carbon/human/H = L if(H.physiology) @@ -542,13 +542,13 @@ /datum/reagent/syndicateadrenals/on_mob_metabolize(mob/living/M) . = ..() if(istype(M)) - M.next_move_modifier *= 0.5 + M.action_cooldown_mod *= 0.5 to_chat(M, "You feel an intense surge of energy rushing through your veins.") /datum/reagent/syndicateadrenals/on_mob_end_metabolize(mob/living/M) . = ..() if(istype(M)) - M.next_move_modifier *= 2 + M.action_cooldown_mod *= 2 to_chat(M, "You feel as though the world around you is going faster.") /datum/reagent/syndicateadrenals/overdose_start(mob/living/M) @@ -559,128 +559,3 @@ 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 94a22853f6..5287df094f 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -117,11 +117,11 @@ /datum/reagent/consumable/cooking_oil/reaction_obj(obj/O, reac_volume) if(holder && holder.chem_temp >= fry_temperature) - if(isitem(O) && !istype(O, /obj/item/reagent_containers/food/snacks/deepfryholder) && !(O.resistance_flags & (FIRE_PROOF|INDESTRUCTIBLE))) + if(isitem(O) && !O.GetComponent(/datum/component/fried) && !(O.resistance_flags & (FIRE_PROOF|INDESTRUCTIBLE)) && (!O.reagents || isfood(O))) //don't fry stuff we shouldn't O.loc.visible_message("[O] rapidly fries as it's splashed with hot oil! Somehow.") - var/obj/item/reagent_containers/food/snacks/deepfryholder/F = new(O.drop_location(), O) - F.fry(volume) - F.reagents.add_reagent(/datum/reagent/consumable/cooking_oil, reac_volume) + O.fry(volume) + if(O.reagents) + O.reagents.add_reagent(/datum/reagent/consumable/cooking_oil, reac_volume) /datum/reagent/consumable/cooking_oil/reaction_mob(mob/living/M, method = TOUCH, reac_volume, show_message = 1, touch_protection = 0) if(!istype(M)) @@ -134,8 +134,8 @@ "You're covered in boiling oil!") M.emote("scream") playsound(M, 'sound/machines/fryer/deep_fryer_emerge.ogg', 25, TRUE) - var/oil_damage = (holder.chem_temp / fry_temperature) * 0.33 //Damage taken per unit - M.adjustFireLoss(min(35, oil_damage * reac_volume)) //Damage caps at 35 + var/oil_damage = min((holder.chem_temp / fry_temperature) * 0.33,1) //Damage taken per unit + M.adjustFireLoss(oil_damage * min(reac_volume,20)) //Damage caps at 20 else ..() return TRUE @@ -143,10 +143,9 @@ /datum/reagent/consumable/cooking_oil/reaction_turf(turf/open/T, reac_volume) if(!istype(T) || isgroundlessturf(T)) return - if(reac_volume >= 5) + if(reac_volume >= 5 && holder && holder.chem_temp >= fry_temperature) T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume * 1.5 SECONDS) - T.name = "deep-fried [initial(T.name)]" - T.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY) + T.fry(reac_volume/4) /datum/reagent/consumable/sugar name = "Sugar" @@ -273,7 +272,7 @@ if(isopenturf(T)) var/turf/open/OT = T OT.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure. - OT.air.temperature -= MOLES_CELLSTANDARD*100*reac_volume/OT.air.heat_capacity() // reduces environment temperature by 5K per unit. + OT.air.set_temperature(OT.air.return_temperature() - MOLES_CELLSTANDARD*100*reac_volume/OT.air.heat_capacity()) // reduces environment temperature by 5K per unit. /datum/reagent/consumable/condensedcapsaicin name = "Condensed Capsaicin" @@ -508,7 +507,7 @@ var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) if(hotspot) var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles()) - lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0) + lowertemp.set_temperature(max( min(lowertemp.return_temperature()-2000,lowertemp.return_temperature() / 2) ,0)) lowertemp.react(src) T.assume_air(lowertemp) qdel(hotspot) @@ -771,7 +770,6 @@ color = "#97ee63" taste_description = "pure electricity" -/* //We don't have ethereals here, so I'll just comment it out. /datum/reagent/consumable/liquidelectricity/reaction_mob(mob/living/M, method=TOUCH, reac_volume) //can't be on life because of the way blood works. if((method == INGEST || method == INJECT || method == PATCH) && iscarbon(M)) @@ -779,10 +777,9 @@ var/obj/item/organ/stomach/ethereal/stomach = C.getorganslot(ORGAN_SLOT_STOMACH) if(istype(stomach)) stomach.adjust_charge(reac_volume * REM) -*/ /datum/reagent/consumable/liquidelectricity/on_mob_life(mob/living/carbon/M) - if(prob(25)) // && !isethereal(M)) + if(prob(25) && !isethereal(M)) M.electrocute_act(rand(10,15), "Liquid Electricity in their body", 1) //lmao at the newbs who eat energy bars playsound(M, "sparks", 50, TRUE) return ..() @@ -868,4 +865,4 @@ taste_mult = 2 taste_description = "fizzy sweetness" value = REAGENT_VALUE_COMMON - \ No newline at end of file + diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 0f53add567..37010cbbb5 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -144,6 +144,9 @@ M.adjustFireLoss(-power, 0) M.adjustToxLoss(-power, 0, TRUE) //heals TOXINLOVERs M.adjustCloneLoss(-power, 0) + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_xadone(power) REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) //fixes common causes for disfiguration . = 1 metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5) @@ -192,6 +195,9 @@ M.adjustFireLoss(-1.5 * power, 0) M.adjustToxLoss(-power, 0, TRUE) M.adjustCloneLoss(-power, 0) + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_xadone(power) REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) . = 1 ..() @@ -231,7 +237,7 @@ /datum/reagent/medicine/spaceacillin name = "Spaceacillin" - description = "Spaceacillin will prevent a patient from conventionally spreading any diseases they are currently infected with." + description = "Spaceacillin will prevent a patient from conventionally spreading any diseases they are currently infected with. Also reduces infection in serious burns." color = "#f2f2f2" metabolization_rate = 0.1 * REAGENTS_METABOLISM pH = 8.1 @@ -359,7 +365,7 @@ /datum/reagent/medicine/salglu_solution name = "Saline-Glucose Solution" - description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute." + description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute, as well as slowly speeding blood regeneration." reagent_state = LIQUID color = "#DCDCDC" metabolization_rate = 0.5 * REAGENTS_METABOLISM @@ -367,6 +373,7 @@ taste_description = "sweetness and salt" var/last_added = 0 var/maximum_reachable = BLOOD_VOLUME_NORMAL - 10 //So that normal blood regeneration can continue with salglu active + var/extra_regen = 0.25 // in addition to acting as temporary blood, also add this much to their actual blood per tick pH = 5.5 /datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/carbon/M) @@ -379,7 +386,7 @@ var/amount_to_add = min(M.blood_volume, volume*5) var/new_blood_level = min(M.blood_volume + amount_to_add, maximum_reachable) last_added = new_blood_level - M.blood_volume - M.blood_volume = new_blood_level + M.blood_volume = new_blood_level + extra_regen if(prob(33)) M.adjustBruteLoss(-0.5*REM, 0) M.adjustFireLoss(-0.5*REM, 0) @@ -403,7 +410,7 @@ /datum/reagent/medicine/mine_salve name = "Miner's Salve" - description = "A powerful painkiller. Restores bruising and burns in addition to making the patient believe they are fully healed." + description = "A powerful painkiller. Restores bruising and burns in addition to making the patient believe they are fully healed. Also great for treating severe burn wounds in a pinch." reagent_state = LIQUID color = "#6D6374" metabolization_rate = 0.4 * REAGENTS_METABOLISM @@ -432,7 +439,7 @@ // +10% success propability on each step, useful while operating in less-than-perfect conditions if(show_message) - to_chat(M, "You feel your wounds fade away to nothing!" ) + to_chat(M, "You feel your injuries fade away to nothing!" ) ..() /datum/reagent/medicine/mine_salve/on_mob_end_metabolize(mob/living/M) @@ -453,10 +460,10 @@ /datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1) if(iscarbon(M)) - if (M.stat == DEAD) + var/mob/living/carbon/C = M + if(M.stat == DEAD) show_message = 0 if(method in list(INGEST, VAPOR)) - var/mob/living/carbon/C = M C.losebreath++ C.emote("cough") to_chat(M, "You feel your throat closing up!") @@ -465,6 +472,9 @@ else if(method in list(PATCH, TOUCH)) M.adjustBruteLoss(-1 * reac_volume) M.adjustFireLoss(-1 * reac_volume) + for(var/i in C.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_synthflesh(reac_volume) if(show_message) to_chat(M, "You feel your burns and bruises healing! It stings like hell!") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine) @@ -505,12 +515,13 @@ overdose_threshold = 30 pH = 2 value = REAGENT_VALUE_UNCOMMON + var/healing = 0.5 /datum/reagent/medicine/omnizine/on_mob_life(mob/living/carbon/M) - M.adjustToxLoss(-0.5*REM, 0) - M.adjustOxyLoss(-0.5*REM, 0) - M.adjustBruteLoss(-0.5*REM, 0) - M.adjustFireLoss(-0.5*REM, 0) + M.adjustToxLoss(-healing*REM, 0) + M.adjustOxyLoss(-healing*REM, 0) + M.adjustBruteLoss(-healing*REM, 0) + M.adjustFireLoss(-healing*REM, 0) ..() . = 1 @@ -522,6 +533,12 @@ ..() . = 1 +/datum/reagent/medicine/omnizine/protozine + name = "Protozine" + description = "A less environmentally friendly and somewhat weaker variant of omnizine." + color = "#d8c7b7" + healing = 0.2 + /datum/reagent/medicine/calomel name = "Calomel" description = "Quickly purges the body of all chemicals. Toxin damage is dealt if the patient is in good condition." @@ -928,10 +945,18 @@ M.adjustOxyLoss(-20, 0) M.adjustToxLoss(-20, 0) M.updatehealth() + var/tplus = world.time - M.timeofdeath if(M.revive()) M.grab_ghost() M.emote("gasp") log_combat(M, M, "revived", src) + var/list/policies = CONFIG_GET(keyed_list/policyconfig) + var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) + var/late = timelimit && (tplus > timelimit) + var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT] + if(policy) + to_chat(M, policy) + M.log_message("revived using strange reagent, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME) ..() @@ -1544,10 +1569,6 @@ /datum/reagent/medicine/polypyr/on_mob_life(mob/living/carbon/M) //I wanted a collection of small positive effects, this is as hard to obtain as coniine after all. M.adjustOrganLoss(ORGAN_SLOT_LUNGS, -0.25) M.adjustBruteLoss(-0.35, 0) - if(prob(50)) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.bleed_rate = max(H.bleed_rate - 1, 0) ..() . = 1 @@ -1580,3 +1601,56 @@ to_chat(C, "[pick(GLOB.wisdoms)]") //give them a random wisdom ..() +// helps bleeding wounds clot faster +/datum/reagent/medicine/coagulant + name = "Sanguirite" + description = "A proprietary coagulant used to help bleeding wounds clot faster." + reagent_state = LIQUID + color = "#bb2424" + metabolization_rate = 0.25 * REAGENTS_METABOLISM + overdose_threshold = 20 + /// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound + var/clot_rate = 0.25 + /// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting) + var/clot_coeff_per_wound = 0.9 + +/datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/M) + . = ..() + if(!M.blood_volume || !M.all_wounds) + return + + var/effective_clot_rate = clot_rate + + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + if(iter_wound.blood_flow) + effective_clot_rate *= clot_coeff_per_wound + + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.blood_flow = max(0, iter_wound.blood_flow - effective_clot_rate) + +/datum/reagent/medicine/coagulant/overdose_process(mob/living/M) + . = ..() + if(!M.blood_volume) + return + + if(prob(15)) + M.losebreath += rand(2,4) + M.adjustOxyLoss(rand(1,3)) + if(prob(30)) + to_chat(M, "You can feel your blood clotting up in your veins!") + else if(prob(10)) + to_chat(M, "You feel like your blood has stopped moving!") + if(prob(50)) + var/obj/item/organ/lungs/our_lungs = M.getorganslot(ORGAN_SLOT_LUNGS) + our_lungs.applyOrganDamage(1) + else + var/obj/item/organ/heart/our_heart = M.getorganslot(ORGAN_SLOT_HEART) + our_heart.applyOrganDamage(1) + +// can be synthesized on station rather than bought. made by grinding a banana peel, heating it up, then mixing the banana peel powder with salglu +/datum/reagent/medicine/coagulant/weak + name = "Synthi-Sanguirite" + description = "A synthetic coagulant used to help bleeding wounds clot faster. Not quite as effective as name brand Sanguirite, especially on patients with lots of cuts." + clot_coeff_per_wound = 0.8 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 117748afc0..5c01fd8cf6 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -70,6 +70,10 @@ B = new(T) if(data["blood_DNA"]) B.blood_DNA[data["blood_DNA"]] = data["blood_type"] + if(!B.blood_DNA["color"]) + B.blood_DNA["color"] = data["bloodcolor"] + else + B.blood_DNA["color"] = BlendRGB(B.blood_DNA["color"], data["bloodcolor"]) if(B.reagents) B.reagents.add_reagent(type, reac_volume) B.update_icon() @@ -77,7 +81,7 @@ /datum/reagent/blood/on_new(list/data) if(istype(data)) SetViruses(src, data) - color = bloodtype_to_color(data["blood_type"]) + color = data["bloodcolor"] if(data["blood_type"] == "SY") name = "Synthetic Blood" taste_description = "oil" @@ -240,6 +244,11 @@ glass_desc = "The father of all refreshments." shot_glass_icon_state = "shotglassclear" +/datum/reagent/water/on_mob_life(mob/living/carbon/M) + . = ..() + if(M.blood_volume) + M.blood_volume += 0.1 // water is good for you! + /* * Water reaction to turf */ @@ -259,7 +268,7 @@ if(hotspot && !isspaceturf(T)) if(T.air) var/datum/gas_mixture/G = T.air - G.temperature = max(min(G.temperature-(CT*1000),G.temperature/CT),TCMB) + G.set_temperature(max(min(G.return_temperature()-(CT*1000),G.return_temperature()/CT),TCMB)) G.react(src) qdel(hotspot) var/obj/effect/acid/A = (locate(/obj/effect/acid) in T) @@ -304,6 +313,13 @@ metabolization_rate = 45 * REAGENTS_METABOLISM . = 1 +/datum/reagent/water/hollowwater + name = "Hollow Water" + description = "An ubiquitous chemical substance that is composed of hydrogen and oxygen, but it looks kinda hollow." + color = "#88878777" + taste_description = "emptyiness" + + /datum/reagent/water/holywater name = "Holy Water" description = "Water blessed by some deity." @@ -330,6 +346,8 @@ return ..() /datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M) + if(M.blood_volume) + M.blood_volume += 0.1 // water is good for you! if(!data) data = list("misc" = 1) data["misc"]++ @@ -872,7 +890,7 @@ if(istype(O, /obj/item/stack/sheet/metal)) var/obj/item/stack/sheet/metal/M = O reac_volume = min(reac_volume, M.amount) - new/obj/item/stack/tile/bronze(get_turf(M), reac_volume) + new/obj/item/stack/sheet/bronze(get_turf(M), reac_volume) M.use(reac_volume) /datum/reagent/nitrogen @@ -939,6 +957,7 @@ color = "#1C1300" // rgb: 30, 20, 0 taste_description = "sour chalk" pH = 5 + material = /datum/material/diamond /datum/reagent/carbon/reaction_turf(turf/T, reac_volume) if(!isspaceturf(T)) @@ -1061,6 +1080,7 @@ pH = 6 overdose_threshold = 30 color = "#c2391d" + material = /datum/material/iron /datum/reagent/iron/on_mob_life(mob/living/carbon/C) if((HAS_TRAIT(C, TRAIT_NOMARROW))) @@ -1092,6 +1112,7 @@ reagent_state = SOLID color = "#F7C430" // rgb: 247, 196, 48 taste_description = "expensive metal" + material = /datum/material/gold /datum/reagent/silver name = "Silver" @@ -1099,6 +1120,7 @@ reagent_state = SOLID color = "#D0D0D0" // rgb: 208, 208, 208 taste_description = "expensive yet reasonable metal" + material = /datum/material/silver /datum/reagent/silver/reaction_mob(mob/living/M, method=TOUCH, reac_volume) if(M.has_bane(BANE_SILVER)) @@ -1112,6 +1134,7 @@ color = "#B8B8C0" // rgb: 184, 184, 192 taste_description = "the inside of a reactor" pH = 4 + material = /datum/material/uranium /datum/reagent/uranium/on_mob_life(mob/living/carbon/M) M.apply_effect(1/M.metabolism_efficiency,EFFECT_IRRADIATE,0) @@ -1133,6 +1156,7 @@ taste_description = "fizzling blue" pH = 12 value = REAGENT_VALUE_RARE + material = /datum/material/bluespace /datum/reagent/bluespace/reaction_mob(mob/living/M, method=TOUCH, reac_volume) if(method == TOUCH || method == VAPOR) @@ -1150,6 +1174,13 @@ /mob/living/proc/bluespace_shuffle() do_teleport(src, get_turf(src), 5, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) +/datum/reagent/telecrystal + name = "Telecrystal Dust" + description = "A blood-red dust comprised of something that was much more useful when it was intact." + reagent_state = SOLID + color = "#660000" // rgb: 102, 0, 0. + taste_description = "contraband" + /datum/reagent/aluminium name = "Aluminium" description = "A silvery white and ductile member of the boron group of chemical elements." @@ -1164,6 +1195,7 @@ color = "#A8A8A8" // rgb: 168, 168, 168 taste_mult = 0 pH = 10 + material = /datum/material/glass /datum/reagent/fuel name = "Welding fuel" @@ -2179,13 +2211,6 @@ M.emote("nya") if(prob(20)) to_chat(M, "[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]") - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/list/adjusted = H.adjust_arousal(2,aphro = TRUE) - for(var/g in adjusted) - var/obj/item/organ/genital/G = g - to_chat(M, "You feel like playing with your [G.name]!") - ..() /datum/reagent/preservahyde @@ -2195,6 +2220,66 @@ color = "#f7685e" metabolization_rate = REAGENTS_METABOLISM * 0.25 +/datum/reagent/wittel + name = "Wittel" + description = "An extremely rare metallic-white substance only found on demon-class planets." + color = "#FFFFFF" // rgb: 255, 255, 255 + taste_mult = 0 // oderless and tasteless + +/datum/reagent/metalgen + name = "Metalgen" + data = list("material"=null) + description = "A purple metal morphic liquid, said to impose it's metallic properties on whatever it touches." + color = "#b000aa" + taste_mult = 0 // oderless and tasteless + var/applied_material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + var/minumum_material_amount = 100 + +/datum/reagent/metalgen/reaction_obj(obj/O, volume) + metal_morph(O) + return + +/datum/reagent/metalgen/reaction_turf(turf/T, volume) + metal_morph(T) + return + +///turn an object into a special material +/datum/reagent/metalgen/proc/metal_morph(atom/A) + var/metal_ref = data["material"] + if(!metal_ref) + return + var/metal_amount = 0 + + for(var/B in A.custom_materials) //list with what they're made of + metal_amount += A.custom_materials[B] + + if(!metal_amount) + metal_amount = minumum_material_amount //some stuff doesn't have materials at all. To still give them properties, we give them a material. Basically doesnt exist + + var/list/metal_dat = list() + metal_dat[metal_ref] = metal_amount //if we pass the list directly, byond turns metal_ref into "metal_ref" kjewrg8fwcyvf + + A.material_flags = applied_material_flags + A.set_custom_materials(metal_dat) + +/datum/reagent/gravitum + name = "Gravitum" + description = "A rare kind of null fluid, capable of temporalily removing all weight of whatever it touches." //i dont even + color = "#050096" // rgb: 5, 0, 150 + taste_mult = 0 // oderless and tasteless + metabolization_rate = 0.1 * REAGENTS_METABOLISM //20 times as long, so it's actually viable to use + var/time_multiplier = 1 MINUTES //1 minute per unit of gravitum on objects. Seems overpowered, but the whole thing is very niche + +/datum/reagent/gravitum/reaction_obj(obj/O, volume) + O.AddElement(/datum/element/forced_gravity, 0) + + addtimer(CALLBACK(O, .proc/_RemoveElement, /datum/element/forced_gravity, 0), volume * time_multiplier) + +/datum/reagent/gravitum/on_mob_add(mob/living/L) + L.AddElement(/datum/element/forced_gravity, 0) //0 is the gravity, and in this case weightless + +/datum/reagent/gravitum/on_mob_end_metabolize(mob/living/L) + L.RemoveElement(/datum/element/forced_gravity, 0) //body bluids /datum/reagent/consumable/semen @@ -2207,6 +2292,7 @@ color = "#FFFFFF" // rgb: 255, 255, 255 can_synth = FALSE nutriment_factor = 0.5 * REAGENTS_METABOLISM + var/decal_path = /obj/effect/decal/cleanable/semen /datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) if(!istype(T)) @@ -2216,7 +2302,7 @@ var/obj/effect/decal/cleanable/semen/S = locate() in T if(!S) - S = new(T) + S = new decal_path(T) if(data["blood_DNA"]) S.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"])) @@ -2240,48 +2326,134 @@ blood_DNA |= S.blood_DNA return ..() -/datum/reagent/consumable/femcum +/datum/reagent/consumable/semen/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 + decal_path = /obj/effect/decal/cleanable/semen/femcum -/obj/effect/decal/cleanable/femcum +/obj/effect/decal/cleanable/semen/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+")) +/datum/reagent/determination + name = "Determination" + description = "For when you need to push on a little more. Do NOT allow near plants." + reagent_state = LIQUID + color = "#D2FFFA" + metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~17 ticks + /// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound + var/significant = FALSE + self_consuming = TRUE -/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/determination/on_mob_end_metabolize(mob/living/carbon/M) + if(significant) + var/stam_crash = 0 + for(var/thing in M.all_wounds) + var/datum/wound/W = thing + stam_crash += (W.severity + 1) * 3 // spike of 3 stam damage per wound severity (moderate = 6, severe = 9, critical = 12) when the determination wears off if it was a combat rush + M.adjustStaminaLoss(stam_crash) + M.remove_status_effect(STATUS_EFFECT_DETERMINED) + ..() -/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) - if(!istype(T)) - return - if(reac_volume < 10) - return +/datum/reagent/determination/on_mob_life(mob/living/carbon/M) + if(!significant && volume >= WOUND_DETERMINATION_SEVERE) + significant = TRUE + M.apply_status_effect(STATUS_EFFECT_DETERMINED) // in addition to the slight healing, limping cooldowns are divided by 4 during the combat high - 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"])) + volume = min(volume, WOUND_DETERMINATION_MAX) + + for(var/thing in M.all_wounds) + var/datum/wound/W = thing + var/obj/item/bodypart/wounded_part = W.limb + if(wounded_part) + wounded_part.heal_damage(0.25, 0.25) + M.adjustStaminaLoss(-0.25*REM) // the more wounds, the more stamina regen + ..() + +datum/reagent/eldritch + name = "Eldritch Essence" + description = "Strange liquid that defies the laws of physics" + taste_description = "Ag'hsj'saje'sh" + color = "#1f8016" + +/datum/reagent/eldritch/on_mob_life(mob/living/carbon/M) + if(IS_HERETIC(M)) + M.drowsyness = max(M.drowsyness-5, 0) + M.AdjustAllImmobility(-40, FALSE) + M.adjustStaminaLoss(-15, FALSE) + M.adjustToxLoss(-3, FALSE) + M.adjustOxyLoss(-3, FALSE) + M.adjustBruteLoss(-3, FALSE) + M.adjustFireLoss(-3, FALSE) + if(ishuman(M) && M.blood_volume < BLOOD_VOLUME_NORMAL) + M.blood_volume += 3 + else + M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3, 150) + M.adjustToxLoss(2, FALSE) + M.adjustFireLoss(2, FALSE) + M.adjustOxyLoss(2, FALSE) + M.adjustBruteLoss(2, FALSE) + holder.remove_reagent(type, 1) + return TRUE + +/datum/reagent/cellulose + name = "Cellulose Fibers" + description = "A crystaline polydextrose polymer, plants swear by this stuff." + reagent_state = SOLID + color = "#E6E6DA" + taste_mult = 0 + + +/datum/reagent/hairball + name = "Hairball" + description = "A bundle of keratinous bits and fibers, not easily digestible." + reagent_state = SOLID + can_synth = FALSE + metabolization_rate = 0.05 * REAGENTS_METABOLISM + taste_description = "wet hair" + var/amount = 0 + var/knotted = FALSE + +/datum/reagent/hairball/on_mob_life(mob/living/carbon/M) + amount = M.reagents.get_reagent_amount(/datum/reagent/hairball) + + if(amount < 10) + if(prob(10)) + M.losebreath += 1 + M.emote("cough") + to_chat(M, "You clear your throat.") + else + if(!knotted) + to_chat(M, "You feel a knot in your stomach.") + knotted = TRUE + + if(prob(5 + amount * 0.5)) // don't want this to cause too much damage + M.losebreath += 2 + to_chat(M, "You feel a knot in your throat.") + M.emote("cough") + + else if(prob(amount - 4)) + to_chat(M, "Your stomach feels awfully bloated.") + playsound(M,'sound/voice/catpeople/distressed.ogg', 50, FALSE) + M.visible_message("[M] seems distressed!.", ignored_mobs=M) + + else if(prob(amount - 8)) + knotted = FALSE + playsound(M,'sound/voice/catpeople/puking.ogg', 110, FALSE) + M.Immobilize(30) + sleep(30) //snowflake but it works, don't wanna proc this + if(QDELETED(M) || QDELETED(src)) //this handles race conditions about m or src not existing. + return + M.visible_message("[M] throws up a hairball! Disgusting!", ignored_mobs=M) + new /obj/item/toy/plush/hairball(get_turf(M)) + to_chat(M, "Aaaah that's better!") + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "cleared_stomach", /datum/mood_event/cleared_stomach, name) + M.reagents.del_reagent(/datum/reagent/hairball) + return + ..() diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm index 50d94a637e..3f0ebcb3e3 100644 --- a/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm @@ -281,8 +281,8 @@ if(hotspot && !isspaceturf(T)) if(T.air) var/datum/gas_mixture/G = T.air - if(G.temperature > T20C) - G.temperature = max(G.temperature/2,T20C) + if(G.return_temperature() > T20C) + G.set_temperature(max(G.return_temperature()/2,T20C)) G.react(src) qdel(hotspot) diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index 02e4a89e1d..07934d9880 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -64,6 +64,7 @@ toxpwr = 3 pH = 4 value = REAGENT_VALUE_RARE //sheets are worth more + material = /datum/material/plasma /datum/reagent/toxin/plasma/on_mob_life(mob/living/carbon/C) if(holder.has_reagent(/datum/reagent/medicine/epinephrine)) @@ -154,6 +155,11 @@ pH = 12 value = REAGENT_VALUE_RARE +/datum/reagent/toxin/carpotoxin/on_mob_life(mob/living/carbon/M) + . = ..() + for(var/i in M.all_scars) + qdel(i) + /datum/reagent/toxin/zombiepowder name = "Zombie Powder" description = "A strong neurotoxin that puts the subject into a death-like state." @@ -368,6 +374,14 @@ pH = 4.9 value = REAGENT_VALUE_VERY_COMMON +/datum/reagent/toxin/teapowder/red + name = "Ground Red Tea Leaves" + toxpwr = 0.4 + +/datum/reagent/toxin/teapowder/green + name = "Ground Green Tea Leaves" + toxpwr = 0.6 + /datum/reagent/toxin/mutetoxin //the new zombie powder. name = "Mute Toxin" description = "A nonlethal poison that inhibits speech in its victim." @@ -520,25 +534,6 @@ taste_description = "bad cooking" value = REAGENT_VALUE_NONE -/datum/reagent/toxin/condensed_cooking_oil - name = "Condensed Cooking Oil" - description = "Taste the consequences of your mistakes." - reagent_state = LIQUID - color = "#d6d6d8" - metabolization_rate = 0.25 * REAGENTS_METABOLISM - toxpwr = 0 - taste_mult = -2 - taste_description = "awful cooking" - value = REAGENT_VALUE_NONE - -/datum/reagent/toxin/condensed_cooking_oil/on_mob_life(mob/living/carbon/M) - if(prob(5)) - M.vomit() - else - if(prob(40)) - M.adjustOrganLoss(ORGAN_SLOT_HEART, 0.5) //For reference, bungotoxin does 3 - ..() - /datum/reagent/toxin/itching_powder name = "Itching Powder" description = "A powder that induces itching upon contact with the skin. Causes the victim to scratch at their itches and has a very low chance to decay into Histamine." @@ -736,22 +731,13 @@ /datum/reagent/toxin/heparin //Based on a real-life anticoagulant. I'm not a doctor, so this won't be realistic. name = "Heparin" - description = "A powerful anticoagulant. Victims will bleed uncontrollably and suffer scaling bruising." + description = "A powerful anticoagulant. All open cut wounds on the victim will open up and bleed much faster" reagent_state = LIQUID color = "#C8C8C8" //RGB: 200, 200, 200 metabolization_rate = 0.2 * REAGENTS_METABOLISM toxpwr = 0 value = REAGENT_VALUE_VERY_RARE -/datum/reagent/toxin/heparin/on_mob_life(mob/living/carbon/M) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - H.bleed_rate = min(H.bleed_rate + 2, 8) - H.adjustBruteLoss(1, 0) //Brute damage increases with the amount they're bleeding - . = 1 - return ..() || . - - /datum/reagent/toxin/rotatium //Rotatium. Fucks up your rotation and is hilarious name = "Rotatium" description = "A constantly swirling, oddly colourful fluid. Causes the consumer's sense of direction and hand-eye coordination to become wild." diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm index 98d66a2b1b..7df061c8aa 100644 --- a/code/modules/reagents/chemistry/recipes.dm +++ b/code/modules/reagents/chemistry/recipes.dm @@ -5,6 +5,9 @@ var/list/required_reagents = new/list() var/list/required_catalysts = new/list() + /// Higher is higher priority, determines which order reactions are checked. + var/priority = CHEMICAL_REACTION_PRIORITY_DEFAULT + // Both of these variables are mostly going to be used with slime cores - but if you want to, you can use them for other things var/required_container = null // the exact container path required for the reaction to happen var/required_other = 0 // an integer required for the reaction to happen diff --git a/code/modules/reagents/chemistry/recipes/drugs.dm b/code/modules/reagents/chemistry/recipes/drugs.dm index a2b8c27552..468d29c052 100644 --- a/code/modules/reagents/chemistry/recipes/drugs.dm +++ b/code/modules/reagents/chemistry/recipes/drugs.dm @@ -62,34 +62,3 @@ 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/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index 9cf9acb424..9e0c78d2e6 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -50,6 +50,18 @@ results = list(/datum/reagent/medicine/salglu_solution = 3) required_reagents = list(/datum/reagent/consumable/sodiumchloride = 1, /datum/reagent/water = 1, /datum/reagent/consumable/sugar = 1) +/datum/chemical_reaction/baked_banana_peel + results = list(/datum/reagent/consumable/baked_banana_peel = 1) + required_temp = 413.15 // if it's good enough for caramel it's good enough for this + required_reagents = list(/datum/reagent/consumable/banana_peel = 1) + mix_message = "The pulp dries up and takes on a powdery state!" + mob_react = FALSE + +/datum/chemical_reaction/coagulant_weak + results = list(/datum/reagent/medicine/coagulant/weak = 3) + required_reagents = list(/datum/reagent/medicine/salglu_solution = 2, /datum/reagent/consumable/baked_banana_peel = 1) + mob_react = FALSE + /datum/chemical_reaction/mine_salve name = "Miner's Salve" id = /datum/reagent/medicine/mine_salve @@ -207,6 +219,12 @@ results = list(/datum/reagent/medicine/strange_reagent = 3) required_reagents = list(/datum/reagent/medicine/omnizine = 1, /datum/reagent/water/holywater = 1, /datum/reagent/toxin/mutagen = 1) +/datum/chemical_reaction/strange_reagent/alt + name = "Strange Reagent" + id = /datum/reagent/medicine/strange_reagent + results = list(/datum/reagent/medicine/strange_reagent = 2) + required_reagents = list(/datum/reagent/medicine/omnizine/protozine = 1, /datum/reagent/water/holywater = 1, /datum/reagent/toxin/mutagen = 1) + /datum/chemical_reaction/mannitol name = "Mannitol" id = /datum/reagent/medicine/mannitol @@ -318,3 +336,35 @@ id = /datum/reagent/medicine/psicodine results = list(/datum/reagent/medicine/psicodine = 5) required_reagents = list( /datum/reagent/medicine/mannitol = 2, /datum/reagent/water = 2, /datum/reagent/impedrezene = 1) + +/datum/chemical_reaction/medsuture + required_reagents = list(/datum/reagent/cellulose = 10, /datum/reagent/toxin/formaldehyde = 20, /datum/reagent/medicine/polypyr = 15) //This might be a bit much, reagent cost should be reviewed after implementation. + +/datum/chemical_reaction/medsuture/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + for(var/i = 1, i <= created_volume, i++) + new /obj/item/stack/medical/suture/medicated(location) + +/datum/chemical_reaction/medmesh + required_reagents = list(/datum/reagent/cellulose = 20, /datum/reagent/consumable/aloejuice = 20, /datum/reagent/space_cleaner/sterilizine = 10) + +/datum/chemical_reaction/medmesh/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + for(var/i = 1, i <= created_volume, i++) + new /obj/item/stack/medical/mesh/advanced(location) + +/datum/chemical_reaction/suture + required_reagents = list(/datum/reagent/cellulose = 2, /datum/reagent/medicine/styptic_powder = 2) + +/datum/chemical_reaction/suture/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + for(var/i = 1, i <= created_volume, i++) + new /obj/item/stack/medical/suture/(location) + +/datum/chemical_reaction/mesh + required_reagents = list(/datum/reagent/cellulose = 2, /datum/reagent/medicine/silver_sulfadiazine = 2) + +/datum/chemical_reaction/mesh/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + for(var/i = 1, i <= created_volume, i++) + new /obj/item/stack/medical/mesh/(location) diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index df1b57c20b..92861a94ed 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -1,3 +1,34 @@ +/datum/chemical_reaction/metalgen + name = "metalgen" + id = /datum/reagent/metalgen + required_reagents = list(/datum/reagent/wittel = 1, /datum/reagent/bluespace = 1, /datum/reagent/toxin/mutagen = 1) + results = list(/datum/reagent/metalgen = 1) + +/datum/chemical_reaction/metalgen_imprint + name = "metalgen imprint" + id = /datum/reagent/metalgen + required_reagents = list(/datum/reagent/metalgen = 1, /datum/reagent/liquid_dark_matter = 1) + results = list(/datum/reagent/metalgen = 1) + +/datum/chemical_reaction/holywater + name = "Holy Water" + id = /datum/reagent/water/holywater + results = list(/datum/reagent/water/holywater = 1) + required_reagents = list(/datum/reagent/water/hollowwater = 1) + required_catalysts = list(/datum/reagent/water/holywater = 1) + +/datum/chemical_reaction/metalgen_imprint/on_reaction(datum/reagents/holder, created_volume) + var/datum/reagent/metalgen/MM = holder.get_reagent(/datum/reagent/metalgen) + for(var/datum/reagent/R in holder.reagent_list) + if(R.material && R.volume >= 40) + MM.data["material"] = R.material + holder.remove_reagent(R.type, 40) + +/datum/chemical_reaction/gravitum + name = "gravitum" + id = /datum/reagent/gravitum + required_reagents = list(/datum/reagent/wittel = 1, /datum/reagent/sorium = 10) + results = list(/datum/reagent/gravitum = 10) /datum/chemical_reaction/sterilizine name = "Sterilizine" @@ -87,7 +118,7 @@ new /obj/item/stack/sheet/mineral/uranium(location) /datum/chemical_reaction/bluespacecrystalifaction - name = "Crystal Bluespace" + name = "Crystallized Bluespace" id = "crystalbluespace" required_reagents = list(/datum/reagent/consumable/frostoil = 5, /datum/reagent/bluespace = 20, /datum/reagent/iron = 1) mob_react = FALSE @@ -684,10 +715,10 @@ required_reagents = list(/datum/reagent/toxin/mindbreaker = 1, /datum/reagent/medicine/synaptizine = 1, /datum/reagent/water = 1) /datum/chemical_reaction/cat - name = "felined mutation toxic" + name = "felinid mutation toxic" id = /datum/reagent/mutationtoxin/felinid results = list(/datum/reagent/mutationtoxin/felinid = 1) - required_reagents = list(/datum/reagent/toxin/mindbreaker = 1, /datum/reagent/ammonia = 1, /datum/reagent/water = 1, /datum/reagent/drug/aphrodisiac = 10, /datum/reagent/mutationtoxin = 1) // Maybe aphro+ if it becomes a shitty meme + required_reagents = list(/datum/reagent/toxin/mindbreaker = 1, /datum/reagent/ammonia = 1, /datum/reagent/water = 1, /datum/reagent/pax/catnip = 1, /datum/reagent/mutationtoxin = 1) required_temp = 450 /datum/chemical_reaction/moff @@ -704,6 +735,14 @@ required_reagents = list(/datum/reagent/liquid_dark_matter = 5, /datum/reagent/medicine/synaptizine = 10, /datum/reagent/medicine/oculine = 10, /datum/reagent/mutationtoxin = 1) required_temp = 600 +/datum/chemical_reaction/slime_extractification + required_reagents = list(/datum/reagent/toxin/slimejelly = 30, /datum/reagent/consumable/frostoil = 5, /datum/reagent/toxin/plasma = 5) + mix_message = "The mixture condenses into a ball." + +/datum/chemical_reaction/slime_extractification/on_reaction(datum/reagents/holder, created_volume) + var/location = get_turf(holder.my_atom) + new /obj/item/slime_extract/grey(location) + // Liquid Carpets /datum/chemical_reaction/carpet @@ -825,3 +864,8 @@ required_reagents = list(/datum/reagent/medicine/salglu_solution = 1, /datum/reagent/iron = 1, /datum/reagent/stable_plasma = 1) mix_message = "The mixture congeals and gives off a faint copper scent." required_temp = 350 + +/datum/chemical_reaction/cellulose_carbonization + results = list(/datum/reagent/carbon = 1) + required_reagents = list(/datum/reagent/cellulose = 1) + required_temp = 512 diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm index 1d06aaacde..efa92ef7d6 100644 --- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm +++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm @@ -280,6 +280,7 @@ /datum/chemical_reaction/smoke_powder name = "smoke_powder" id = /datum/reagent/smoke_powder + priority = CHEMICAL_REACTION_PRIORITY_SMOKE results = list(/datum/reagent/smoke_powder = 3) required_reagents = list(/datum/reagent/potassium = 1, /datum/reagent/consumable/sugar = 1, /datum/reagent/phosphorus = 1) diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index ead47e2a42..2c3f25e73a 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -165,10 +165,7 @@ var/chosen = getbork() var/obj/B = new chosen(T) if(prob(5))//Fry it! - var/obj/item/reagent_containers/food/snacks/deepfryholder/fried - fried = new(T, B) - fried.fry() // actually set the name and colour it - B = fried + B.fry() // actually set the name and colour it if(prob(50)) for(var/j in 1 to rand(1, 3)) step(B, pick(NORTH,SOUTH,EAST,WEST)) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index fbdbb5f656..b71584982c 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -69,7 +69,8 @@ to_chat(user, "[src]'s transfer amount is now [amount_per_transfer_from_this] units.") return -/obj/item/reagent_containers/attack(mob/M, mob/user, def_zone) +/obj/item/reagent_containers/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) + . = ..() if(user.a_intent == INTENT_HARM) return ..() diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index 6be2e658c1..98a117ea69 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -13,7 +13,7 @@ /obj/item/reagent_containers/blood/Initialize() . = ..() if(blood_type != null) - reagents.add_reagent(/datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_colour"=color, "blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) + reagents.add_reagent(/datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"bloodcolor"=bloodtype_to_color(blood_type), "blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) update_icon() /obj/item/reagent_containers/blood/on_reagent_change(changetype) diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm index ad8d722b61..20abcf847f 100644 --- a/code/modules/reagents/reagent_containers/bottle.dm +++ b/code/modules/reagents/reagent_containers/bottle.dm @@ -416,25 +416,3 @@ /obj/item/reagent_containers/glass/bottle/bromine name = "bromine bottle" list_reagents = list(/datum/reagent/bromine = 30) - -//Lewd Stuff - -/obj/item/reagent_containers/glass/bottle/crocin - name = "Crocin bottle" - desc = "A bottle of mild aphrodisiac. Increases libido." - list_reagents = list(/datum/reagent/drug/aphrodisiac = 30) - -/obj/item/reagent_containers/glass/bottle/hexacrocin - name = "Hexacrocin bottle" - desc = "A bottle of strong aphrodisiac. Increases libido." - list_reagents = list(/datum/reagent/drug/aphrodisiacplus = 30) - -/obj/item/reagent_containers/glass/bottle/camphor - name = "Camphor bottle" - desc = "A bottle of mild anaphrodisiac. Reduces libido." - list_reagents = list(/datum/reagent/drug/anaphrodisiac = 30) - -/obj/item/reagent_containers/glass/bottle/hexacamphor - name = "Hexacamphor bottle" - desc = "A bottle of strong anaphrodisiac. Reduces libido." - list_reagents = list(/datum/reagent/drug/anaphrodisiacplus = 30) diff --git a/code/modules/reagents/reagent_containers/chem_pack.dm b/code/modules/reagents/reagent_containers/chem_pack.dm new file mode 100644 index 0000000000..35ec588ec5 --- /dev/null +++ b/code/modules/reagents/reagent_containers/chem_pack.dm @@ -0,0 +1,51 @@ +/obj/item/reagent_containers/chem_pack + name = "intravenous medicine bag" + desc = "A plastic pressure bag, or 'chem pack', for IV administration of drugs. It is fitted with a thermosealing strip." + icon = 'icons/obj/bloodpack.dmi' + icon_state = "chempack" + volume = 100 + reagent_flags = OPENCONTAINER + spillable = TRUE + obj_flags = UNIQUE_RENAME + resistance_flags = ACID_PROOF + var/sealed = FALSE + +/obj/item/reagent_containers/chem_pack/on_reagent_change(changetype) + update_icon() + +/obj/item/reagent_containers/chem_pack/update_icon() + cut_overlays() + + var/v = min(round(reagents.total_volume / volume * 10), 10) + if(v > 0) + var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "chempack1") + filling.icon_state = "chempack[v]" + filling.color = mix_color_from_reagents(reagents.reagent_list) + add_overlay(filling) + +/obj/item/reagent_containers/chem_pack/AltClick(mob/living/user) + if(user.canUseTopic(src, BE_CLOSE, NO_DEXTERY) && !sealed) + if(iscarbon(user) && (HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))) + to_chat(user, "Uh... whoops! You accidentally spill the content of the bag onto yourself.") + SplashReagents(user) + return + else + DISABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER) + ENABLE_BITFIELD(reagents.reagents_holder_flags, DRAWABLE |INJECTABLE ) + spillable = FALSE + sealed = TRUE + to_chat(user, "You seal the bag.") + + +/obj/item/reagent_containers/chem_pack/examine() + . = ..() + if(sealed) + . += "The bag is sealed shut." + else + . += "Alt-click to seal it." + + +obj/item/reagent_containers/chem_pack/attack_self(mob/user) + if(sealed) + return + ..() \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 328b30d092..ec26182813 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -9,6 +9,11 @@ container_HP = 2 /obj/item/reagent_containers/glass/attack(mob/M, mob/user, obj/target) + // WARNING: This entire section is shitcode and prone to breaking at any time. + INVOKE_ASYNC(src, .proc/attempt_feed, M, user, target) // for example, the arguments in this proc are wrong + // but i don't have time to properly fix it right now. + +/obj/item/reagent_containers/glass/proc/attempt_feed(mob/M, mob/user, obj/target) if(!canconsume(M, user)) return @@ -386,6 +391,20 @@ /obj/item/reagent_containers/glass/beaker/waterbottle/large/empty list_reagents = list() +/obj/item/reagent_containers/glass/beaker/waterbottle/wataur + name = "Bottled Wataur" + desc = "Finally, a bottle as proportionate as you." + icon = 'icons/obj/drinks.dmi' + icon_state = "wataur" + custom_materials = list(/datum/material/plastic=0) + list_reagents = list(/datum/reagent/water = 100) + volume = 100 + amount_per_transfer_from_this = 20 + possible_transfer_amounts = list(5,10,15,20,25,30,50, 100) + container_flags = TEMP_WEAK|APTFT_ALTCLICK|APTFT_VERB + container_HP = 1 + cached_icon = "wataur" + /obj/item/reagent_containers/glass/get_belt_overlay() return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "bottle") diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 799a6db9f5..835ffe2d89 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -90,12 +90,12 @@ item_state = "medipen" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' - amount_per_transfer_from_this = 13 - volume = 13 + amount_per_transfer_from_this = 15 + volume = 15 ignore_flags = 1 //so you can medipen through hardsuits reagent_flags = DRAWABLE flags_1 = null - list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3) + list_reagents = list(/datum/reagent/medicine/epinephrine = 10, /datum/reagent/preservahyde = 3, /datum/reagent/medicine/coagulant = 2) custom_premium_price = PRICE_ALMOST_EXPENSIVE /obj/item/reagent_containers/hypospray/medipen/suicide_act(mob/living/carbon/user) @@ -133,6 +133,20 @@ else . += "It is spent." +/obj/item/reagent_containers/hypospray/medipen/ekit + name = "emergency first-aid autoinjector" + desc = "An epinephrine medipen with extra coagulant and antibiotics to help stabilize bad cuts and burns." + volume = 15 + amount_per_transfer_from_this = 15 + list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5) + +/obj/item/reagent_containers/hypospray/medipen/blood_loss + name = "hypovolemic-response autoinjector" + desc = "A medipen designed to stabilize and rapidly reverse severe bloodloss." + volume = 15 + amount_per_transfer_from_this = 15 + list_reagents = list(/datum/reagent/medicine/epinephrine = 5, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/iron = 3.5, /datum/reagent/medicine/salglu_solution = 4) + /obj/item/reagent_containers/hypospray/medipen/stimulants name = "illegal stimpack medipen" desc = "A highly illegal medipen due to its load and small injections, allow for five uses before being drained" @@ -354,13 +368,17 @@ obj_flags |= EMAGGED return TRUE -/obj/item/hypospray/mkii/attack_hand(mob/user) +/obj/item/hypospray/mkii/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() //Don't bother changing this or removing it from containers will break. /obj/item/hypospray/mkii/attack(obj/item/I, mob/user, params) return /obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity) + . = ..() + INVOKE_ASYNC(src, .proc/attempt_inject, target, user, proximity) + +/obj/item/hypospray/mkii/proc/attempt_inject(atom/target, mob/user, proximity) if(!vial || !proximity || !isliving(target)) return var/mob/living/L = target diff --git a/code/modules/reagents/reagent_containers/maunamug.dm b/code/modules/reagents/reagent_containers/maunamug.dm index 18e6cfa847..3dfac8a631 100644 --- a/code/modules/reagents/reagent_containers/maunamug.dm +++ b/code/modules/reagents/reagent_containers/maunamug.dm @@ -88,7 +88,7 @@ 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) +/obj/item/reagent_containers/glass/maunamug/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) if(cell && open) cell.update_icon() user.put_in_hands(cell) diff --git a/code/modules/reagents/reagent_containers/medspray.dm b/code/modules/reagents/reagent_containers/medspray.dm index 02a3f987bc..40ad167531 100644 --- a/code/modules/reagents/reagent_containers/medspray.dm +++ b/code/modules/reagents/reagent_containers/medspray.dm @@ -32,6 +32,9 @@ to_chat(user, "You will now apply the medspray's contents in [squirt_mode ? "short bursts":"extended sprays"]. You'll now use [amount_per_transfer_from_this] units per use.") /obj/item/reagent_containers/medspray/attack(mob/living/L, mob/user, def_zone) + INVOKE_ASYNC(src, .proc/attempt_spray, L, user, def_zone) // this is shitcode because the params for attack aren't even right but i'm not in the mood to refactor right now. + +/obj/item/reagent_containers/medspray/proc/attempt_spray(mob/living/L, mob/user, def_zone) if(!reagents || !reagents.total_volume) to_chat(user, "[src] is empty!") return diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index fca04f239e..3c23794e5a 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -11,8 +11,8 @@ grind_results = list() var/apply_type = INGEST var/apply_method = "swallow" - var/roundstart = 0 - var/self_delay = 0 //pills are instant, this is because patches inheret their aplication from pills + var/roundstart = FALSE + var/self_delay = FALSE //pills are instant, this is because patches inheret their aplication from pills var/dissolvable = TRUE /obj/item/reagent_containers/pill/Initialize() @@ -28,22 +28,24 @@ /obj/item/reagent_containers/pill/get_w_volume() // DEFAULT_VOLUME_TINY at 25u, DEFAULT_VOLUME_SMALL at 50u return DEFAULT_VOLUME_TINY/2 + reagents.total_volume / reagents.maximum_volume * DEFAULT_VOLUME_TINY -/obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone) +/obj/item/reagent_containers/pill/attack(mob/living/M, mob/living/user, attackchain_flags = NONE, damage_multiplier = 1) + INVOKE_ASYNC(src, .proc/attempt_feed, M, user) + +/obj/item/reagent_containers/pill/proc/attempt_feed(mob/living/M, mob/living/user) if(!canconsume(M, user)) - return 0 + return FALSE if(M == user) M.visible_message("[user] attempts to [apply_method] [src].") if(self_delay) if(!do_mob(user, M, self_delay)) - return 0 + return FALSE to_chat(M, "You [apply_method] [src].") - else M.visible_message("[user] attempts to force [M] to [apply_method] [src].", \ "[user] attempts to force [M] to [apply_method] [src].") if(!do_mob(user, M)) - return 0 + return FALSE M.visible_message("[user] forces [M] to [apply_method] [src].", \ "[user] forces [M] to [apply_method] [src].") @@ -56,8 +58,7 @@ reagents.reaction(M, apply_type) reagents.trans_to(M, reagents.total_volume) qdel(src) - return 1 - + return TRUE /obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity) . = ..() @@ -77,125 +78,133 @@ "You dissolve [src] in [target].", vision_distance = 2) reagents.trans_to(target, reagents.total_volume) qdel(src) + return STOP_ATTACK_PROC_CHAIN /obj/item/reagent_containers/pill/tox name = "toxins pill" desc = "Highly toxic." icon_state = "pill5" list_reagents = list(/datum/reagent/toxin = 50) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/cyanide name = "cyanide pill" desc = "Don't swallow this." icon_state = "pill5" list_reagents = list(/datum/reagent/toxin/cyanide = 50) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/adminordrazine name = "adminordrazine pill" desc = "It's magic. We don't have to explain it." icon_state = "pill16" list_reagents = list(/datum/reagent/medicine/adminordrazine = 50) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/morphine name = "morphine pill" desc = "Commonly used to treat insomnia." icon_state = "pill8" list_reagents = list(/datum/reagent/medicine/morphine = 30) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/stimulant name = "stimulant pill" desc = "Often taken by overworked employees, athletes, and the inebriated. You'll snap to attention immediately!" icon_state = "pill19" list_reagents = list(/datum/reagent/medicine/ephedrine = 10, /datum/reagent/medicine/antihol = 10, /datum/reagent/consumable/coffee = 30) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/salbutamol name = "salbutamol pill" desc = "Used to treat oxygen deprivation." icon_state = "pill16" list_reagents = list(/datum/reagent/medicine/salbutamol = 30) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/charcoal name = "charcoal pill" desc = "Neutralizes many common toxins." icon_state = "pill17" list_reagents = list(/datum/reagent/medicine/charcoal = 10) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/epinephrine name = "epinephrine pill" desc = "Used to stabilize patients." icon_state = "pill5" list_reagents = list(/datum/reagent/medicine/epinephrine = 15) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/mannitol name = "mannitol pill" desc = "Used to treat brain damage." icon_state = "pill17" list_reagents = list(/datum/reagent/medicine/mannitol = 25) - roundstart = 1 + roundstart = TRUE /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 = 25) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/salicyclic name = "salicylic acid pill" desc = "Used to dull pain." icon_state = "pill9" list_reagents = list(/datum/reagent/medicine/sal_acid = 24) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/oxandrolone name = "oxandrolone pill" desc = "Used to stimulate burn healing." icon_state = "pill11" list_reagents = list(/datum/reagent/medicine/oxandrolone = 24) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/insulin name = "insulin pill" desc = "Handles hyperglycaemic coma." icon_state = "pill18" list_reagents = list(/datum/reagent/medicine/insulin = 50) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/psicodine name = "psicodine pill" - desc = "Used to treat mental instability and traumas." + desc = "Used to treat mental instability and phobias." list_reagents = list(/datum/reagent/medicine/psicodine = 10) icon_state = "pill22" - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/antirad name = "potassium iodide pill" desc = "Used to treat radition used to counter radiation poisoning." icon_state = "pill18" list_reagents = list(/datum/reagent/medicine/potass_iodide = 50) - roundstart = 1 + roundstart = TRUE /obj/item/reagent_containers/pill/antirad_plus name = "prussian blue pill" desc = "Used to treat heavy radition poisoning." icon_state = "prussian_blue" list_reagents = list(/datum/reagent/medicine/prussian_blue = 25) - roundstart = 1 + roundstart = TRUE /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 = 10, /datum/reagent/medicine/potass_iodide = 10, /datum/reagent/medicine/mutadone = 5) - roundstart = 1 + roundstart = TRUE + +/obj/item/reagent_containers/pill/neurine + name = "neurine pill" + desc = "Used to treat non-severe mental traumas." + list_reagents = list("neurine" = 10) + icon_state = "pill22" + roundstart = TRUE ///////////////////////////////////////// this pill is used only in a legion mob drop /obj/item/reagent_containers/pill/shadowtoxin diff --git a/code/modules/reagents/reagent_containers/rags.dm b/code/modules/reagents/reagent_containers/rags.dm index c6903ff7b4..469a8ef907 100644 --- a/code/modules/reagents/reagent_containers/rags.dm +++ b/code/modules/reagents/reagent_containers/rags.dm @@ -36,26 +36,29 @@ var/reagentlist = pretty_string_from_reagent_list(reagents) var/log_object = "a damp rag containing [reagentlist]" if(user.a_intent == INTENT_HARM && !C.is_mouth_covered()) - reagents.reaction(C, INGEST) - reagents.trans_to(C, 5) - C.visible_message("[user] has smothered \the [C] with \the [src]!", "[user] has smothered you with \the [src]!", "You hear some struggling and muffled cries of surprise.") - log_combat(user, C, "smothered", log_object) + C.visible_message("[user] is trying to smother \the [C] with \the [src]!", "[user] is trying to smother you with \the [src]!", "You hear some struggling and muffled cries of surprise.") + if(do_after(user, 20, target = C)) + reagents.reaction(C, INGEST) + reagents.trans_to(C, 5) + C.visible_message("[user] has smothered \the [C] with \the [src]!", "[user] has smothered you with \the [src]!", "You hear some struggling and a heavy breath taken.") + log_combat(user, C, "smothered", log_object) else - reagents.reaction(C, TOUCH) - reagents.remove_all(5) - C.visible_message("[user] has touched \the [C] with \the [src].") - log_combat(user, C, "touched", log_object) + C.visible_message("[user] is trying to wipe \the [C] with \the [src].") + if(do_after(user, 20, target = C)) + reagents.reaction(C, TOUCH) + reagents.remove_all(5) + C.visible_message("[user] has wiped \the [C] with \the [src].") + log_combat(user, C, "touched", log_object) else if(istype(A) && (src in user)) user.visible_message("[user] starts to wipe down [A] with [src]!", "You start to wipe down [A] with [src]...") if(do_after(user, action_speed, target = A)) user.visible_message("[user] finishes wiping off [A]!", "You finish wiping off [A].") SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM) - return /obj/item/reagent_containers/rag/alt_pre_attack(mob/living/M, mob/living/user, params) if(istype(M) && user.a_intent == INTENT_HELP) - user.changeNext_move(CLICK_CD_MELEE) + user.DelayNextAction(CLICK_CD_MELEE) if(M.on_fire) user.visible_message("\The [user] uses \the [src] to pat out [M == user ? "[user.p_their()]" : "\the [M]'s"] flames!") if(hitsound) @@ -189,4 +192,4 @@ extinguish_efficiency = 5 action_speed = 15 damp_threshold = 0.8 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 50, "acid" = 50) //items don't provide armor to wearers unlike clothing yet. \ No newline at end of file + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 20, "bio" = 20, "rad" = 20, "fire" = 50, "acid" = 50) //items don't provide armor to wearers unlike clothing yet. diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 7fea8250d9..926ed27854 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -19,6 +19,10 @@ var/stream_range = 1 //the range of tiles the sprayer will reach when in stream mode. var/stream_amount = 10 //the amount of reagents transfered when in stream mode. var/spray_delay = 3 //The amount of sleep() delay between each chempuff step. + /// Last world.time of spray + var/last_spray = 0 + /// Spray cooldown + var/spray_cooldown = CLICK_CD_MELEE var/can_fill_from_container = TRUE amount_per_transfer_from_this = 5 volume = 250 @@ -47,10 +51,11 @@ to_chat(user, "[src] is empty!") return - spray(A) + if(!spray(A)) + return playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6) - user.changeNext_move(CLICK_CD_RANGE*2) + user.last_action = world.time user.newtonian_move(get_dir(A, user)) var/turf/T = get_turf(src) if(reagents.has_reagent(/datum/reagent/toxin/acid)) @@ -62,10 +67,10 @@ if(reagents.has_reagent(/datum/reagent/lube)) message_admins("[ADMIN_LOOKUPFLW(user)] fired Space lube from \a [src] at [ADMIN_VERBOSEJMP(T)].") log_game("[key_name(user)] fired Space lube from \a [src] at [AREACOORD(T)].") - return - /obj/item/reagent_containers/spray/proc/spray(atom/A) + if((last_spray + spray_cooldown) > world.time) + return var/range = clamp(get_dist(src, A), 1, current_range) var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src)) D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE) @@ -77,10 +82,11 @@ reagents.trans_to(D, amount_per_transfer_from_this, 1/range) D.color = mix_color_from_reagents(D.reagents.reagent_list) var/wait_step = max(round(2+ spray_delay * INVERSE(range)), 2) - do_spray(A, wait_step, D, range, puff_reagent_left) + last_spray = world.time + INVOKE_ASYNC(src, .proc/do_spray, A, wait_step, D, range, puff_reagent_left) + return TRUE /obj/item/reagent_containers/spray/proc/do_spray(atom/A, wait_step, obj/effect/decal/chempuff/D, range, puff_reagent_left) - set waitfor = FALSE var/range_left = range for(var/i=0, i[user.name] [anchored ? "fasten" : "unfasten"] [src]", \ + "You [anchored ? "fasten" : "unfasten"] [src]") + var/datum/component/plumbing/CP = GetComponent(/datum/component/plumbing) + if(anchored) + CP.enable() + else + CP.disable() + +/obj/structure/reagent_dispensers/plumbed/ComponentInitialize() + AddComponent(/datum/component/plumbing/simple_supply) + +/obj/structure/reagent_dispensers/plumbed/storage + name = "stationairy storage tank" + icon_state = "tank_stationairy" + reagent_id = null //start empty + +/obj/structure/reagent_dispensers/plumbed/storage/ComponentInitialize() + AddComponent(/datum/component/plumbing/tank) + ////////////// //Fuel Tanks// ////////////// @@ -222,19 +255,6 @@ icon_state = "orangekeg" reagent_id = /datum/reagent/consumable/ethanol/mead -/obj/structure/reagent_dispensers/keg/aphro - name = "keg of aphrodisiac" - desc = "A keg of aphrodisiac." - icon_state = "pinkkeg" - reagent_id = /datum/reagent/drug/aphrodisiac - tank_volume = 150 - -/obj/structure/reagent_dispensers/keg/aphro/strong - name = "keg of strong aphrodisiac" - desc = "A keg of strong and addictive aphrodisiac." - reagent_id = /datum/reagent/drug/aphrodisiacplus - tank_volume = 120 - /obj/structure/reagent_dispensers/keg/milk name = "keg of milk" desc = "A keg of pasteurised, homogenised, filtered and semi-skimmed space milk." @@ -247,3 +267,40 @@ icon_state = "bluekeg" reagent_id = /datum/reagent/consumable/ethanol/gargle_blaster tank_volume = 100 + +//kegs given by the travelling trader's bartender subtype + +/obj/structure/reagent_dispensers/keg/quintuple_sec + name = "keg of quintuple sec" + desc = "A keg of pure justice." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/ethanol/quintuple_sec + tank_volume = 250 + +/obj/structure/reagent_dispensers/keg/narsour + name = "keg of narsour" + desc = "A keg of eldritch terrors." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/ethanol/narsour + tank_volume = 250 + +/obj/structure/reagent_dispensers/keg/red_queen + name = "keg of red queen" + desc = "A strange keg, filled with a kind of tea." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/red_queen + tank_volume = 250 + +/obj/structure/reagent_dispensers/keg/hearty_punch + name = "keg of hearty punch" + desc = "A keg that will get you right back on your feet." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/ethanol/hearty_punch + tank_volume = 100 //this usually has a 15:1 ratio when being made, so we provide less of it + +/obj/structure/reagent_dispensers/keg/neurotoxin + name = "keg of neurotoxin" + desc = "A keg of the sickly substance known as 'neurotoxin'." + icon_state = "bluekeg" + reagent_id = /datum/reagent/consumable/ethanol/neurotoxin + tank_volume = 100 //2.5x less than the other kegs because it's harder to get diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index cadd9ba04f..b81c3b88f8 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -68,7 +68,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) . = ..() /obj/machinery/conveyor/vv_edit_var(var_name, var_value) - if (var_name == "id") + if (var_name == NAMEOF(src, id)) // if "id" is varedited, update our list membership LAZYREMOVE(GLOB.conveyors_by_id[id], src) . = ..() @@ -174,10 +174,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) return ..() // attack with hand, move pulled object onto conveyor -/obj/machinery/conveyor/attack_hand(mob/user) - . = ..() - if(.) - return +/obj/machinery/conveyor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) user.Move_Pulled(src) // make the conveyor broken @@ -243,7 +240,7 @@ GLOBAL_LIST_EMPTY(conveyors_by_id) . = ..() /obj/machinery/conveyor_switch/vv_edit_var(var_name, var_value) - if (var_name == "id") + if (var_name == NAMEOF(src, id)) // if "id" is varedited, update our list membership LAZYREMOVE(GLOB.conveyors_by_id[id], src) . = ..() diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 65bfa1d98f..c8da9ab5e3 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -40,7 +40,7 @@ trunk_check() air_contents = new /datum/gas_mixture() - //gas.volume = 1.05 * CELLSTANDARD + //air_contents.set_volume(1.05 * CELLSTANDARD) update_icon() return INITIALIZE_HINT_LATELOAD //we need turfs to have air @@ -299,13 +299,15 @@ // handle machine interaction -/obj/machinery/disposal/bin/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) +/obj/machinery/disposal/bin/ui_state(mob/user) + return GLOB.notcontained_state + +/obj/machinery/disposal/bin/ui_interact(mob/user, datum/tgui/ui) if(stat & BROKEN) return - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "disposal_unit", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "DisposalUnit", name) ui.open() /obj/machinery/disposal/bin/ui_data(mob/user) @@ -375,7 +377,6 @@ log_combat(user, target, "shoved", "into [src] (disposal bin)") return TRUE - /obj/machinery/disposal/bin/flush() ..() full_pressure = FALSE @@ -443,8 +444,8 @@ var/datum/gas_mixture/env = L.return_air() var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure() - if(env.temperature > 0) - var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION) + if(env.return_temperature() > 0) + var/transfer_moles = 0.1 * pressure_delta*air_contents.return_volume()/(env.return_temperature() * R_IDEAL_GAS_EQUATION) //Actually transfer the gas var/datum/gas_mixture/removed = env.remove(transfer_moles) diff --git a/code/modules/research/anomaly/anomaly_core.dm b/code/modules/research/anomaly/anomaly_core.dm new file mode 100644 index 0000000000..7aeb7b3a9b --- /dev/null +++ b/code/modules/research/anomaly/anomaly_core.dm @@ -0,0 +1,63 @@ +// Embedded signaller used in anomalies. +/obj/item/assembly/signaler/anomaly + name = "anomaly core" + desc = "The neutralized core of an anomaly. It'd probably be valuable for research." + icon_state = "anomaly_core" + //inhand_icon_state = "electronic" + lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' + righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' + resistance_flags = FIRE_PROOF + var/anomaly_type = /obj/effect/anomaly + +/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal) + if(!signal) + return FALSE + if(signal.data["code"] != code) + return FALSE + if(suicider) + manual_suicide(suicider) + for(var/obj/effect/anomaly/A in get_turf(src)) + A.anomalyNeutralize() + return TRUE + +/obj/item/assembly/signaler/anomaly/manual_suicide(mob/living/carbon/user) + user.visible_message("[user]'s [src] is reacting to the radio signal, warping [user.p_their()] body!") + //user.set_suicide(TRUE) + user.suicide_log() + user.gib() + +/obj/item/assembly/signaler/anomaly/attackby(obj/item/I, mob/user, params) + if(I.tool_behaviour == TOOL_ANALYZER) + to_chat(user, "Analyzing... [src]'s stabilized field is fluctuating along frequency [format_frequency(frequency)], code [code].") + return ..() + +//Anomaly cores +/obj/item/assembly/signaler/anomaly/pyro + name = "\improper pyroclastic anomaly core" + desc = "The neutralized core of a pyroclastic anomaly. It feels warm to the touch. It'd probably be valuable for research." + icon_state = "pyro_core" + anomaly_type = /obj/effect/anomaly/pyro + +/obj/item/assembly/signaler/anomaly/grav + name = "\improper gravitational anomaly core" + desc = "The neutralized core of a gravitational anomaly. It feels much heavier than it looks. It'd probably be valuable for research." + icon_state = "grav_core" + anomaly_type = /obj/effect/anomaly/grav + +/obj/item/assembly/signaler/anomaly/flux + name = "\improper flux anomaly core" + desc = "The neutralized core of a flux anomaly. Touching it makes your skin tingle. It'd probably be valuable for research." + icon_state = "flux_core" + anomaly_type = /obj/effect/anomaly/flux + +/obj/item/assembly/signaler/anomaly/bluespace + name = "\improper bluespace anomaly core" + desc = "The neutralized core of a bluespace anomaly. It keeps phasing in and out of view. It'd probably be valuable for research." + icon_state = "anomaly_core" + anomaly_type = /obj/effect/anomaly/bluespace + +/obj/item/assembly/signaler/anomaly/vortex + name = "\improper vortex anomaly core" + desc = "The neutralized core of a vortex anomaly. It won't sit still, as if some invisible force is acting on it. It'd probably be valuable for research." + icon_state = "vortex_core" + anomaly_type = /obj/effect/anomaly/bhole diff --git a/code/modules/research/bepis.dm b/code/modules/research/bepis.dm index 20ca7987d5..7b36a614a7 100644 --- a/code/modules/research/bepis.dm +++ b/code/modules/research/bepis.dm @@ -33,11 +33,13 @@ 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/flashlight/flashdark, - /obj/item/pen/survival, - /obj/item/circuitboard/machine/sleeper/party, - /obj/item/toy/sprayoncan) + var/list/minor_rewards = list( + //To add a new minor reward, add it here. + /obj/item/stack/circuit_stack/full, + /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) @@ -101,6 +103,7 @@ return account.adjust_money(-deposit_value) //The money vanishes, not paid to any accounts. SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value) + //log_econ("[deposit_value] credits were inserted into [src] by [account.account_holder]") banked_cash += deposit_value use_power(1000 * power_saver) say("Cash deposit successful. There is [banked_cash] in the chamber.") @@ -179,10 +182,10 @@ 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) +/obj/machinery/rnd/bepis/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "bepis", name, 500, 480, master_ui, state) + ui = new(user, src, "Bepis", name) ui.open() RefreshParts() 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 76ec6224b8..574c7c9282 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 @@ -119,6 +119,24 @@ category = list("initial", "Medical","Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE +/datum/design/bonesetter + name = "Bonesetter" + id = "bonesetter" + build_type = AUTOLATHE | PROTOLATHE + materials = list(/datum/material/iron = 1000) + build_path = /obj/item/bonesetter + category = list("initial", "Medical", "Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/sticky_tape/surgical + name = "Surgical Tape" + id = "surgical_tape" + build_type = PROTOLATHE + materials = list(/datum/material/plastic = 500) + build_path = /obj/item/stack/sticky_tape/surgical + category = list("initial", "Medical") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + /datum/design/beaker name = "Beaker" id = "beaker" 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 9768d80a59..61d0594d3b 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 @@ -30,14 +30,6 @@ build_path = /obj/item/ammo_box/c38 category = list("initial", "Security") -/datum/design/r32acp - name = "Rubber Pistol Bullet (.32)" - id = "r32acp" - build_type = AUTOLATHE - materials = list(/datum/material/iron = 250) - build_path = /obj/item/ammo_casing/r32acp - category = list("initial", "Security") - ///////////////// ///Hacked Gear // ///////////////// @@ -206,22 +198,3 @@ build_path = /obj/item/clothing/head/foilhat category = list("hacked", "Misc") -/datum/design/c32acp - name = "Pistol Bullet (.32)" - id = "c32acp" - build_type = AUTOLATHE - materials = list(/datum/material/iron = 500) - build_path = /obj/item/ammo_casing/c32acp - category = list("hacked", "Security") - -///////////////// -// Magazines // -///////////////// - -/datum/design/m32acp - name = "Empty .32 Magazine" - id = "m32acp" - build_type = AUTOLATHE - materials = list(/datum/material/iron = 10000) - build_path = /obj/item/ammo_box/magazine/m32acp/empty - category = list("hacked", "Security") 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 320f856b35..539232bbcd 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 @@ -81,7 +81,16 @@ materials = list(/datum/material/iron = 50, /datum/material/glass = 50) build_path = /obj/item/airlock_painter category = list("initial", "Misc","Tool Designs") - departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SERVICE + +/datum/design/airlock_painter/decal + name = "Decal Painter" + id = "decal_painter" + build_type = AUTOLATHE | PROTOLATHE + materials = list(/datum/material/iron = 50, /datum/material/glass = 50) + build_path = /obj/item/airlock_painter/decal + category = list("initial","Tools","Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SERVICE /datum/design/cultivator name = "Cultivator" @@ -280,11 +289,3 @@ materials = list(/datum/material/iron = 6500, /datum/material/glass = 50) build_path = /obj/item/weaponcrafting/improvised_parts/trigger_assembly category = list("initial", "Misc") - -/datum/design/focusing_lens - name = "Makeshift Lens" - id = "makeshift_lens" - build_type = AUTOLATHE - materials = list(/datum/material/iron = 2000, /datum/material/glass = 4000) - build_path = /obj/item/weaponcrafting/improvised_parts/makeshift_lens - category = list("initial", "Misc") 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 516c91d426..bebf836ce0 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_tools.dm @@ -148,7 +148,8 @@ build_type = AUTOLATHE materials = list(/datum/material/iron = 100, /datum/material/glass = 100) build_path = /obj/item/toy/crayon/spraycan - category = list("initial", "Tools") + category = list("initial", "Tools", "Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE /datum/design/geiger name = "Geiger Counter" @@ -157,11 +158,3 @@ materials = list(/datum/material/iron = 150, /datum/material/glass = 150) build_path = /obj/item/geiger_counter category = list("initial", "Tools") - -/datum/design/saw - name = "Hand Saw" - id = "handsaw" - build_type = AUTOLATHE - materials = list(/datum/material/iron = 500) - build_path = /obj/item/hatchet/saw - category = list("initial", "Tools") diff --git a/code/modules/research/designs/autoylathe_designs.dm b/code/modules/research/designs/autoylathe_designs.dm index c2076db121..6db9755585 100644 --- a/code/modules/research/designs/autoylathe_designs.dm +++ b/code/modules/research/designs/autoylathe_designs.dm @@ -63,7 +63,7 @@ name = "Double-Bladed Toy Sword" id = "dbtoysword" materials = list(/datum/material/plastic = 1000) - build_path = /obj/item/twohanded/dualsaber/toy + build_path = /obj/item/dualsaber/toy category = list("initial", "Melee") /datum/design/autoylathe/toykatana diff --git a/code/modules/research/designs/bluespace_designs.dm b/code/modules/research/designs/bluespace_designs.dm index 0d11b8e887..336dc4ec8e 100644 --- a/code/modules/research/designs/bluespace_designs.dm +++ b/code/modules/research/designs/bluespace_designs.dm @@ -95,3 +95,23 @@ build_path = /obj/item/storage/bag/ore/holding category = list("Bluespace Designs") departmental_flags = DEPARTMENTAL_FLAG_CARGO + +/datum/design/bluespace_tray + name = "Bluespace Tray" + desc = "A tray created using bluespace technology to fit more food on it." + id = "bluespace_tray" + build_type = PROTOLATHE + build_path = /obj/item/storage/bag/tray/bluespace + materials = list(/datum/material/iron = 2000, /datum/material/bluespace = 500) + category = list("Bluespace Designs") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE + +/datum/design/bluespace_carrier + name = "Bluespace Jar" + desc = "A jar used to contain creatures, using the power of bluespace." + id = "bluespace_carrier" + build_type = PROTOLATHE + build_path = /obj/item/pet_carrier/bluespace + materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600) + category = list("Bluespace Designs") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE \ No newline at end of file diff --git a/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm b/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm index 27560f29a1..99caa5b480 100644 --- a/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm +++ b/code/modules/research/designs/comp_board_designs/comp_board_designs_all_misc.dm @@ -43,4 +43,20 @@ id = "libraryconsole" build_path = /obj/item/circuitboard/computer/libraryconsole category = list("Computer Boards") - departmental_flags = DEPARTMENTAL_FLAG_ALL \ No newline at end of file + departmental_flags = DEPARTMENTAL_FLAG_ALL + +/datum/design/board/flight_control + name = "Computer Design (Shuttle Flight Controls)" + desc = "Allows for the construction of circuit boards used to build a console that enables shuttle flight" + id = "shuttle_control" + build_path = /obj/item/circuitboard/computer/shuttle/flight_control + category = list("Computer Boards", "Shuttle Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + +/datum/design/board/shuttle_docker + name = "Computer Design (Private Navigation Computer)" + desc = "Allows for the construction of circuit boards used to build a console that enables the targetting of custom flight locations" + id = "shuttle_docker" + build_path = /obj/item/circuitboard/computer/shuttle/docker + category = list("Computer Boards", "Shuttle Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm index 806e2ef75c..7e5bedaf0e 100644 --- a/code/modules/research/designs/electronics_designs.dm +++ b/code/modules/research/designs/electronics_designs.dm @@ -166,35 +166,3 @@ desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk." id = "xenobio_slimeadv" build_path = /obj/item/disk/xenobio_console_upgrade/slimeadv - -/datum/design/board/shuttle/engine/plasma - name = "Machine Design (Plasma Thruster Board)" - desc = "The circuit board for a plasma thruster." - id = "engine_plasma" - build_path = /obj/item/circuitboard/machine/shuttle/engine/plasma - category = list ("Shuttle Machinery") - departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE - -/datum/design/board/shuttle/engine/void - name = "Machine Design (Void Thruster Board)" - desc = "The circuit board for a void thruster." - id = "engine_void" - build_path = /obj/item/circuitboard/machine/shuttle/engine/void - category = list ("Shuttle Machinery") - departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE - -/datum/design/board/shuttle/engine/heater - name = "Machine Design (Engine Heater Board)" - desc = "The circuit board for an engine heater." - id = "engine_heater" - build_path = /obj/item/circuitboard/machine/shuttle/heater - category = list ("Shuttle Machinery") - departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE - -/obj/item/circuitboard/computer/shuttle/flight_control - name = "Shuttle Flight Control (Computer Board)" - build_path = /obj/machinery/computer/custom_shuttle - -/obj/item/circuitboard/computer/shuttle/docker - name = "Shuttle Navigation Computer (Computer Board)" - build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom 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 d12099f7ff..e0702be689 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 @@ -130,3 +130,36 @@ departmental_flags = DEPARTMENTAL_FLAG_SECURITY build_path = /obj/item/circuitboard/machine/hypnochair category = list("Misc. Machinery") + +/datum/design/board/engine_plasma + name = "Machine Design (Plasma Thruster Board)" + desc = "The circuit board for a plasma thruster." + id = "engine_plasma" + build_path = /obj/item/circuitboard/machine/shuttle/engine/plasma + category = list ("Shuttle Machinery") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/board/engine_void + name = "Machine Design (Void Thruster Board)" + desc = "The circuit board for a void thruster." + id = "engine_void" + build_path = /obj/item/circuitboard/machine/shuttle/engine/void + category = list ("Shuttle Machinery") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/board/engine_heater + name = "Machine Design (Engine Heater Board)" + desc = "The circuit board for an engine heater." + id = "engine_heater" + build_path = /obj/item/circuitboard/machine/shuttle/heater + category = list ("Shuttle Machinery") + departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/board/sheetifier + name = "Sheetifier" + desc = "This machine turns weird things into sheets." + id = "sheetifier" + build_path = /obj/item/circuitboard/machine/sheetifier + category = list ("Misc. Machinery") + departmental_flags = DEPARTMENTAL_FLAG_ALL + diff --git a/code/modules/research/designs/machine_desings/machine_designs_medical.dm b/code/modules/research/designs/machine_desings/machine_designs_medical.dm index 329fb7bf6e..84a3ed10d5 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_medical.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_medical.dm @@ -105,3 +105,11 @@ build_path = /obj/item/circuitboard/machine/bloodbankgen departmental_flags = DEPARTMENTAL_FLAG_MEDICAL category = list ("Medical Machinery") + +/datum/design/board/medipen_refiller + name = "Machine Design (Medipen Refiller)" + desc = "The circuit board for a Medipen Refiller." + id = "medipen_refiller" + build_path = /obj/item/circuitboard/machine/medipen_refiller + category = list ("Medical Machinery") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL diff --git a/code/modules/research/designs/machine_desings/machine_designs_service.dm b/code/modules/research/designs/machine_desings/machine_designs_service.dm index 5cbff1c66a..af4f650793 100644 --- a/code/modules/research/designs/machine_desings/machine_designs_service.dm +++ b/code/modules/research/designs/machine_desings/machine_designs_service.dm @@ -81,6 +81,14 @@ category = list ("Hydroponics Machinery") departmental_flags = DEPARTMENTAL_FLAG_SERVICE +/datum/design/board/hydroponics/auto + name = "Machine Design (Automatic Hydroponics Tray Board)" + desc = "The circuit board for an automatic hydroponics tray. GIVE ME THE PLANT, CAPTAIN." + id = "autohydrotray" + build_path = /obj/machinery/hydroponics/constructable/automagic + category = list ("Hydroponics Machinery") + departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_MEDICAL + /datum/design/board/monkey_recycler name = "Machine Design (Monkey Recycler Board)" desc = "The circuit board for a monkey recycler." diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 02d16b8c2e..4efcad97ba 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -264,6 +264,79 @@ construction_time = 600 category = list("Gygax") +//Medical Gygax +/datum/design/medigax_chassis + name = "Exosuit Chassis (\"Medical Gygax\")" + id = "medigax_chassis" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/chassis/medigax + materials = list(/datum/material/iron=20000) + construction_time = 100 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_torso + name = "Exosuit Torso (\"Medical Gygax\")" + id = "medigax_torso" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_torso + materials = list(/datum/material/iron=20000,/datum/material/glass=10000,/datum/material/diamond=2000) + construction_time = 300 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_head + name = "Exosuit Head (\"Medical Gygax\")" + id = "medigax_head" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_head + materials = list(/datum/material/iron=10000,/datum/material/glass=5000, /datum/material/diamond=2000) + construction_time = 200 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_left_arm + name = "Exosuit Left Arm (\"Medical Gygax\")" + id = "medigax_left_arm" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_left_arm + materials = list(/datum/material/iron=15000, /datum/material/diamond=1000) + construction_time = 200 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_right_arm + name = "Exosuit Right Arm (\"Medical Gygax\")" + id = "medigax_right_arm" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_right_arm + materials = list(/datum/material/iron=15000, /datum/material/diamond=1000) + construction_time = 200 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_left_leg + name = "Exosuit Left Leg (\"Medical Gygax\")" + id = "medigax_left_leg" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_left_leg + materials = list(/datum/material/iron=15000, /datum/material/diamond=2000) + construction_time = 200 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_right_leg + name = "Exosuit Right Leg (\"Medical Gygax\")" + id = "medigax_right_leg" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_right_leg + materials = list(/datum/material/iron=15000, /datum/material/diamond=2000) + construction_time = 200 + category = list("Medical-Spec Gygax") + +/datum/design/medigax_armor + name = "Exosuit Armor (\"Medical Gygax\")" + id = "medigax_armor" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/part/medigax_armor + materials = list(/datum/material/iron=15000,/datum/material/diamond=10000,/datum/material/titanium=10000) + construction_time = 600 + category = list("Medical-Spec Gygax") + //Durand /datum/design/durand_chassis name = "Exosuit Chassis (\"Durand\")" diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 69bf039428..0a9fce2e67 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -212,6 +212,16 @@ category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL +/datum/design/chem_pack + name = "Intravenous Medicine Bag" + desc = "A plastic pressure bag for IV administration of drugs." + id = "chem_pack" + build_type = PROTOLATHE + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + materials = list(/datum/material/plastic = 1500) + build_path = /obj/item/reagent_containers/chem_pack + category = list("Medical Designs") + /datum/design/cloning_disk name = "Cloning Data Disk" desc = "Produce additional disks for storing genetic data." @@ -951,3 +961,158 @@ build_path = /obj/item/bodypart/r_arm/robot/surplus_upgraded category = list("Medical Designs") departmental_flags = DEPARTMENTAL_FLAG_MEDICAL + + +/datum/design/acclimator + name = "Plumbing Acclimator" + desc = "A heating and cooling device for pipes!" + id = "acclimator" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 500) + construction_time = 15 + build_path = /obj/machinery/plumbing/acclimator + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/disposer + name = "Plumbing Disposer" + desc = "Using the power of Science, dissolves reagents into nothing (almost)." + id = "disposer" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 500, /datum/material/glass = 100) + construction_time = 15 + build_path = /obj/machinery/plumbing/disposer + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_filter + name = "Plumbing Filter" + desc = "Filters out chemicals by their NTDB ID." + id = "plumb_filter" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 500) + construction_time = 15 + build_path = /obj/machinery/plumbing/filter + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_synth + name = "Plumbing Synthesizer" + desc = "Using standard mass-energy dynamic autoconverters, generates reagents from power and puts them in a pipe." + id = "plumb_synth" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 5000, /datum/material/glass = 1000, /datum/material/plastic = 1000) + construction_time = 15 + build_path = /obj/machinery/plumbing/synthesizer + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_grinder + name = "Plumbing-Linked Autogrinder" + desc = "Automatically extracts reagents from an item by grinding it. Think of the possibilities! Note: does not grind people." + id = "plumb_grinder" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 2000, /datum/material/glass = 1500) + construction_time = 15 + build_path = /obj/machinery/plumbing/grinder_chemical + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/reaction_chamber + name = "Plumbing Reaction Chamber" + desc = "You can set a list of allowed reagents and amounts. Once the chamber has these reagents, will let the products through." + id = "reaction_chamber" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 500) + construction_time = 15 + build_path = /obj/machinery/plumbing/reaction_chamber + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/duct_print + name = "Plumbing Ducts" + desc = "Ducts for plumbing! Now lathed for efficiency." + id = "duct_print" + build_type = PROTOLATHE + materials = list(/datum/material/plastic = 400) + construction_time = 1 + build_path = /obj/item/stack/ducts + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_splitter + name = "Plumbing Chemical Splitter" + desc = "A splitter. Has 2 outputs. Can be configured to allow a certain amount through each side." + id = "plumb_splitter" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 750, /datum/material/glass = 250) + construction_time = 15 + build_path = /obj/machinery/plumbing/splitter + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/pill_press + name = "Plumbing Automatic Pill Former" + desc = "Automatically forms pills to the required parameters with piped reagents! A good replacement for those lazy, useless chemists." + id = "pill_press" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 500) + construction_time = 15 + build_path = /obj/machinery/plumbing/pill_press + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_pump + name = "Liquid Extraction Pump" + desc = "Use it for extracting liquids from lavaland's geysers!" + id = "plumb_pump" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 1000, /datum/material/glass = 500) + construction_time = 15 + build_path = /obj/machinery/plumbing/liquid_pump + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_in + name = "Plumbing Input Device" + desc = "A big piped funnel for putting stuff in the pipe network." + id = "plumb_in" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 400, /datum/material/glass = 400) + construction_time = 15 + build_path = /obj/machinery/plumbing/input + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_out + name = "Plumbing Output Device" + desc = "A big piped funnel for taking stuff out of the pipe network." + id = "plumb_out" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 400, /datum/material/glass = 400) + construction_time = 15 + build_path = /obj/machinery/plumbing/output + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_tank + name = "Plumbed Storage Tank" + desc = "A tank for storing plumbed reagents." + id = "plumb_tank" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 10000, /datum/material/glass = 10000, /datum/material/plastic = 4000) + construction_time = 15 + build_path = /obj/machinery/plumbing/tank + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE + +/datum/design/plumb_rcd + name = "Plumbed Autoconstruction Device" + desc = "A RCD for plumbing machines! Cannot make ducts." + id = "plumb_rcd" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 20000, /datum/material/glass = 10000, /datum/material/plastic = 20000, /datum/material/titanium = 2000, /datum/material/diamond = 800, /datum/material/gold = 2000, /datum/material/silver = 2000) + construction_time = 150 + build_path = /obj/item/construction/plumbing + category = list("Misc","Medical Designs") + departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE diff --git a/code/modules/research/designs/misc_designs.dm b/code/modules/research/designs/misc_designs.dm index 0a1fde30c2..1b608060ce 100644 --- a/code/modules/research/designs/misc_designs.dm +++ b/code/modules/research/designs/misc_designs.dm @@ -343,7 +343,7 @@ id = "broom" build_type = PROTOLATHE | AUTOLATHE materials = list(/datum/material/iron = 1000, /datum/material/glass = 600) - build_path = /obj/item/twohanded/broom + build_path = /obj/item/broom category = list("initial", "Equipment", "Misc") departmental_flags = DEPARTMENTAL_FLAG_SERVICE diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm index 551d6fa0e3..4fe07cb02f 100644 --- a/code/modules/research/designs/tool_designs.dm +++ b/code/modules/research/designs/tool_designs.dm @@ -92,6 +92,16 @@ category = list("Tool Designs") departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_CARGO +/datum/design/ranged_analyzer + name = "Long-range Analyzer" + desc = "A new advanced atmospheric analyzer design, capable of performing scans at long range." + id = "ranged_analyzer" + build_type = PROTOLATHE + materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/plastic = 200) + build_path = /obj/item/analyzer/ranged + category = list("Tool Designs") + departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING + ///////////////////////////////////////// //////////////Alien Tools//////////////// ///////////////////////////////////////// diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index 3d4bf2b4c9..9667830dbc 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -368,7 +368,7 @@ var/heat_capacity = removed.heat_capacity() if(heat_capacity == 0 || heat_capacity == null) heat_capacity = 1 - removed.temperature = min((removed.temperature*heat_capacity + 100000)/heat_capacity, 1000) + removed.set_temperature(min((removed.return_temperature()*heat_capacity + 100000)/heat_capacity, 1000)) env.merge(removed) air_update_turf() investigate_log("Experimentor has released hot air.", INVESTIGATE_EXPERIMENTOR) @@ -414,7 +414,7 @@ var/heat_capacity = removed.heat_capacity() if(heat_capacity == 0 || heat_capacity == null) heat_capacity = 1 - removed.temperature = (removed.temperature*heat_capacity - 75000)/heat_capacity + removed.set_temperature((removed.return_temperature()*heat_capacity - 75000)/heat_capacity) env.merge(removed) air_update_turf() investigate_log("Experimentor has released cold air.", INVESTIGATE_EXPERIMENTOR) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index a5df3f4d12..5a50120833 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -96,7 +96,7 @@ for(var/i in 1 to amount) var/obj/O = new path(get_turf(src)) if(efficient_with(O.type)) - O.set_custom_materials(matlist.Copy()) + O.set_custom_materials(matlist) O.rnd_crafted(src) SSblackbox.record_feedback("nested tally", "item_printed", amount, list("[type]", "[path]")) investigate_log("[key_name(user)] built [amount] of [path] at [src]([type]).", INVESTIGATE_RESEARCH) diff --git a/code/modules/research/nanites/extra_settings/text.dm b/code/modules/research/nanites/extra_settings/text.dm index 56aa3dd07f..d3cad27bcf 100644 --- a/code/modules/research/nanites/extra_settings/text.dm +++ b/code/modules/research/nanites/extra_settings/text.dm @@ -10,6 +10,9 @@ /datum/nanite_extra_setting/text/get_copy() return new /datum/nanite_extra_setting/text(value) +/datum/nanite_extra_setting/text/get_value() + return html_encode(value) + /datum/nanite_extra_setting/text/get_frontend_list(name) return list(list( "name" = name, diff --git a/code/modules/research/nanites/nanite_chamber.dm b/code/modules/research/nanites/nanite_chamber.dm index 4a980a0436..01513a0b41 100644 --- a/code/modules/research/nanites/nanite_chamber.dm +++ b/code/modules/research/nanites/nanite_chamber.dm @@ -150,8 +150,6 @@ return if(busy) return - 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(breakout_time)].)", \ "You hear a metallic creaking from [src].") diff --git a/code/modules/research/nanites/nanite_chamber_computer.dm b/code/modules/research/nanites/nanite_chamber_computer.dm index 4650af5c80..70e4d05590 100644 --- a/code/modules/research/nanites/nanite_chamber_computer.dm +++ b/code/modules/research/nanites/nanite_chamber_computer.dm @@ -3,10 +3,8 @@ desc = "Controls a connected nanite chamber. Can inoculate nanites, load programs, and analyze existing nanite swarms." var/obj/machinery/nanite_chamber/chamber var/obj/item/disk/nanite_program/disk - circuit = /obj/item/circuitboard/computer/nanite_chamber_control icon_screen = "nanite_chamber_control" - ui_x = 380 - ui_y = 570 + circuit = /obj/item/circuitboard/computer/nanite_chamber_control /obj/machinery/computer/nanite_chamber_control/Initialize() . = ..() @@ -25,10 +23,10 @@ find_chamber() ..() -/obj/machinery/computer/nanite_chamber_control/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/nanite_chamber_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "nanite_chamber_control", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "NaniteChamberControl", name) ui.open() /obj/machinery/computer/nanite_chamber_control/ui_data() diff --git a/code/modules/research/nanites/nanite_cloud_controller.dm b/code/modules/research/nanites/nanite_cloud_controller.dm index f9d4d71b01..44ebe11c29 100644 --- a/code/modules/research/nanites/nanite_cloud_controller.dm +++ b/code/modules/research/nanites/nanite_cloud_controller.dm @@ -1,11 +1,9 @@ /obj/machinery/computer/nanite_cloud_controller name = "nanite cloud controller" desc = "Stores and controls nanite cloud backups." - circuit = /obj/item/circuitboard/computer/nanite_cloud_controller icon = 'icons/obj/machines/research.dmi' icon_state = "nanite_cloud_controller" - ui_x = 375 - ui_y = 700 + circuit = /obj/item/circuitboard/computer/nanite_cloud_controller var/obj/item/disk/nanite_program/disk var/list/datum/nanite_cloud_backup/cloud_backups = list() @@ -20,20 +18,27 @@ /obj/machinery/computer/nanite_cloud_controller/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/disk/nanite_program)) var/obj/item/disk/nanite_program/N = I - if(disk) - eject(user) - if(user.transferItemToLoc(N, src)) + if (user.transferItemToLoc(N, src)) to_chat(user, "You insert [N] into [src].") playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + if(disk) + eject(user) disk = N else ..() +/obj/machinery/computer/nanite_cloud_controller/AltClick(mob/user) + if(disk && user.canUseTopic(src, !issilicon(user))) + to_chat(user, "You take out [disk] from [src].") + eject(user) + return + /obj/machinery/computer/nanite_cloud_controller/proc/eject(mob/living/user) if(!disk) return - if(!istype(user) || !Adjacent(user) ||!user.put_in_active_hand(disk)) - disk.forceMove(drop_location()) + disk.forceMove(drop_location()) + if(istype(user) && user.Adjacent(src)) + user.put_in_active_hand(disk) disk = null /obj/machinery/computer/nanite_cloud_controller/proc/get_backup(cloud_id) @@ -53,10 +58,10 @@ backup.nanites = cloud_copy investigate_log("[key_name(user)] created a new nanite cloud backup with id #[cloud_id]", INVESTIGATE_NANITES) -/obj/machinery/computer/nanite_cloud_controller/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/nanite_cloud_controller/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "nanite_cloud_control", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "NaniteCloudControl", name) ui.open() /obj/machinery/computer/nanite_cloud_controller/ui_data() diff --git a/code/modules/research/nanites/nanite_program_hub.dm b/code/modules/research/nanites/nanite_program_hub.dm index 47ee2447d2..495c788845 100644 --- a/code/modules/research/nanites/nanite_program_hub.dm +++ b/code/modules/research/nanites/nanite_program_hub.dm @@ -3,26 +3,24 @@ desc = "Compiles nanite programs from the techweb servers and downloads them into disks." icon = 'icons/obj/machines/research.dmi' icon_state = "nanite_program_hub" - circuit = /obj/item/circuitboard/machine/nanite_program_hub use_power = IDLE_POWER_USE anchored = TRUE density = TRUE - ui_x = 500 - ui_y = 700 + circuit = /obj/item/circuitboard/machine/nanite_program_hub var/obj/item/disk/nanite_program/disk var/datum/techweb/linked_techweb var/current_category = "Main" var/detail_view = TRUE var/categories = list( - list(name = "Utility Nanites"), - list(name = "Medical Nanites"), - list(name = "Sensor Nanites"), - list(name = "Augmentation Nanites"), - list(name = "Suppression Nanites"), - list(name = "Weaponized Nanites"), - list(name = "Protocols") //Moved to default techweb from B.E.P.I.S. research, for now - ) + list(name = "Utility Nanites"), + list(name = "Medical Nanites"), + list(name = "Sensor Nanites"), + list(name = "Augmentation Nanites"), + list(name = "Suppression Nanites"), + list(name = "Weaponized Nanites"), + list(name = "Protocols"), + ) /obj/machinery/nanite_program_hub/Initialize() . = ..() @@ -31,26 +29,45 @@ /obj/machinery/nanite_program_hub/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/disk/nanite_program)) var/obj/item/disk/nanite_program/N = I - if(disk) - eject(user) if(user.transferItemToLoc(N, src)) to_chat(user, "You insert [N] into [src].") playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + if(disk) + eject(user) disk = N else ..() +/obj/machinery/nanite_program_hub/screwdriver_act(mob/living/user, obj/item/I) //remove when runtimed + if(..()) + return TRUE + + return default_deconstruction_screwdriver(user, "nanite_program_hub_t", "nanite_program_hub", I) + +/obj/machinery/nanite_program_hub/crowbar_act(mob/living/user, obj/item/I) + if(..()) + return TRUE + + return default_deconstruction_crowbar(I) + /obj/machinery/nanite_program_hub/proc/eject(mob/living/user) if(!disk) return - if(!istype(user) || !Adjacent(user) || !user.put_in_active_hand(disk)) - disk.forceMove(drop_location()) + disk.forceMove(drop_location()) + if(istype(user) && Adjacent(user)) + user.put_in_active_hand(disk) disk = null -/obj/machinery/nanite_program_hub/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/nanite_program_hub/AltClick(mob/user) + if(disk && user.canUseTopic(src, !issilicon(user))) + to_chat(user, "You take out [disk] from [src].") + eject(user) + return + +/obj/machinery/nanite_program_hub/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "nanite_program_hub", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "NaniteProgramHub", name) ui.open() /obj/machinery/nanite_program_hub/ui_data() @@ -123,9 +140,3 @@ disk.program = null disk.name = initial(disk.name) . = TRUE - - -/obj/machinery/nanite_program_hub/admin/Initialize() - . = ..() - linked_techweb = SSresearch.admin_tech - diff --git a/code/modules/research/nanites/nanite_programmer.dm b/code/modules/research/nanites/nanite_programmer.dm index 5315a7a507..b6a2c8b28b 100644 --- a/code/modules/research/nanites/nanite_programmer.dm +++ b/code/modules/research/nanites/nanite_programmer.dm @@ -3,41 +3,58 @@ desc = "A device that can edit nanite program disks to adjust their functionality." var/obj/item/disk/nanite_program/disk var/datum/nanite_program/program - circuit = /obj/item/circuitboard/machine/nanite_programmer icon = 'icons/obj/machines/research.dmi' icon_state = "nanite_programmer" use_power = IDLE_POWER_USE anchored = TRUE density = TRUE flags_1 = HEAR_1 - ui_x = 420 - ui_y = 550 + circuit = /obj/item/circuitboard/machine/nanite_programmer /obj/machinery/nanite_programmer/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/disk/nanite_program)) var/obj/item/disk/nanite_program/N = I - if(disk) - eject(user) if(user.transferItemToLoc(N, src)) to_chat(user, "You insert [N] into [src]") playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) + if(disk) + eject(user) disk = N program = N.program else ..() +/obj/machinery/nanite_programmer/screwdriver_act(mob/living/user, obj/item/I) + if(..()) + return TRUE + + return default_deconstruction_screwdriver(user, "nanite_programmer_t", "nanite_programmer", I) + +/obj/machinery/nanite_programmer/crowbar_act(mob/living/user, obj/item/I) + if(..()) + return TRUE + + return default_deconstruction_crowbar(I) + /obj/machinery/nanite_programmer/proc/eject(mob/living/user) if(!disk) return - if(!istype(user) || !Adjacent(user) || !user.put_in_active_hand(disk)) - disk.forceMove(drop_location()) + disk.forceMove(drop_location()) + if(istype(user) && user.Adjacent(src)) + user.put_in_active_hand(disk) disk = null program = null -/obj/machinery/nanite_programmer/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/nanite_programmer/AltClick(mob/user) + if(disk && user.canUseTopic(src, !issilicon(user))) + to_chat(user, "You take out [disk] from [src].") + eject(user) + return + +/obj/machinery/nanite_programmer/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "nanite_programmer", name, ui_x, ui_y, master_ui, state) + ui = new(user, src, "NaniteProgrammer", name) ui.open() /obj/machinery/nanite_programmer/ui_data() @@ -131,7 +148,7 @@ program.timer_trigger_delay = timer . = TRUE -/obj/machinery/nanite_programmer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) +/obj/machinery/nanite_programmer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods = list()) . = ..() var/static/regex/when = regex("(?:^\\W*when|when\\W*$)", "i") //starts or ends with when if(findtext(raw_message, when) && !istype(speaker, /obj/machinery/nanite_programmer)) diff --git a/code/modules/research/nanites/nanite_programs/suppression.dm b/code/modules/research/nanites/nanite_programs/suppression.dm index 3b0d6d0d06..d2aa243fee 100644 --- a/code/modules/research/nanites/nanite_programs/suppression.dm +++ b/code/modules/research/nanites/nanite_programs/suppression.dm @@ -176,7 +176,7 @@ sent_message = message_setting.get_value() if(host_mob.stat == DEAD) return - to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[sent_message]\"") + to_chat(host_mob, "You hear a strange, robotic voice in your head... \"[html_encode(sent_message)]\"") /datum/nanite_program/comm/hallucination name = "Hallucination" diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index ebe623d73d..f5372738db 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -51,7 +51,7 @@ rogue_types = list(/datum/nanite_program/toxic) /datum/nanite_program/self_scan/register_extra_settings() - extra_settings[NES_SCAN_TYPE] = new /datum/nanite_extra_setting/type("Medical", list("Medical", "Chemical", "Nanite")) + extra_settings[NES_SCAN_TYPE] = new /datum/nanite_extra_setting/type("Medical", list("Medical", "Chemical", "Wound", "Nanite")) /datum/nanite_program/self_scan/on_trigger(comm_message) if(host_mob.stat == DEAD) @@ -62,6 +62,8 @@ healthscan(host_mob, host_mob) if("Chemical") chemscan(host_mob, host_mob) + if("Wound") + woundscan(host_mob, host_mob) if("Nanite") SEND_SIGNAL(host_mob, COMSIG_NANITE_SCAN, host_mob, TRUE) diff --git a/code/modules/research/nanites/nanite_remote.dm b/code/modules/research/nanites/nanite_remote.dm index 0d9361b534..e3f5a0f286 100644 --- a/code/modules/research/nanites/nanite_remote.dm +++ b/code/modules/research/nanites/nanite_remote.dm @@ -80,10 +80,13 @@ var/datum/nanite_program/relay/N = X N.relay_signal(code, relay_code, source) -/obj/item/nanite_remote/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/item/nanite_remote/ui_state(mob/user) + return GLOB.hands_state + +/obj/item/nanite_remote/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "nanite_remote", name, 420, 500, master_ui, state) + ui = new(user, src, "NaniteRemote", name) ui.open() /obj/item/nanite_remote/ui_data() @@ -94,7 +97,6 @@ data["locked"] = locked data["saved_settings"] = saved_settings data["program_name"] = current_program_name - return data /obj/item/nanite_remote/ui_act(action, params) diff --git a/code/modules/research/nanites/public_chamber.dm b/code/modules/research/nanites/public_chamber.dm index 76392c66e9..b7a8db4080 100644 --- a/code/modules/research/nanites/public_chamber.dm +++ b/code/modules/research/nanites/public_chamber.dm @@ -130,8 +130,6 @@ return if(busy) return - 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(breakout_time)].)", \ "You hear a metallic creaking from [src].") diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index d543468c48..a7b266fc0e 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -1075,6 +1075,9 @@ Nothing else in the console has ID requirements. /obj/machinery/computer/rdconsole/ui_interact(mob/user) . = ..() var/datum/browser/popup = new(user, "rndconsole", name, 900, 600) + var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/research_designs) + + popup.add_head_content("") popup.add_stylesheet("techwebs", 'html/browser/techwebs.css') popup.set_content(generate_ui()) popup.open() diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm index b3e114d2ad..d3b4bb6bac 100644 --- a/code/modules/research/server.dm +++ b/code/modules/research/server.dm @@ -59,14 +59,14 @@ /obj/machinery/rnd/server/proc/get_env_temp() var/datum/gas_mixture/environment = loc.return_air() - return environment.temperature + return environment.return_temperature() /obj/machinery/rnd/server/proc/produce_heat(heat_amt) if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater. var/turf/L = loc if(istype(L)) var/datum/gas_mixture/env = L.return_air() - if(env.temperature < (heat_amt+T0C)) + if(env.return_temperature() < (heat_amt+T0C)) var/transfer_moles = 0.25 * env.total_moles() @@ -77,7 +77,7 @@ var/heat_capacity = removed.heat_capacity() if(heat_capacity == 0 || heat_capacity == null) heat_capacity = 1 - removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000) + removed.set_temperature(min((removed.return_temperature()*heat_capacity + heating_power)/heat_capacity, 1000)) env.merge(removed) air_update_turf() diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index 503bd8bae7..a0f0c651f0 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -24,10 +24,10 @@ var/list/tiers = list() //Assoc list, id = number, 1 is available, 2 is all reqs are 1, so on /datum/techweb/New() + hidden_nodes = SSresearch.techweb_nodes_hidden.Copy() for(var/i in SSresearch.techweb_nodes_starting) var/datum/techweb_node/DN = SSresearch.techweb_node_by_id(i) research_node(DN, TRUE, FALSE) - hidden_nodes = SSresearch.techweb_nodes_hidden.Copy() return ..() /datum/techweb/admin diff --git a/code/modules/research/techweb/nodes/biotech_nodes.dm b/code/modules/research/techweb/nodes/biotech_nodes.dm index 8f7d978a99..977f8685d6 100644 --- a/code/modules/research/techweb/nodes/biotech_nodes.dm +++ b/code/modules/research/techweb/nodes/biotech_nodes.dm @@ -5,7 +5,7 @@ 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") + 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","chem_pack") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) /datum/techweb_node/adv_biotech diff --git a/code/modules/research/techweb/nodes/bluespace_nodes.dm b/code/modules/research/techweb/nodes/bluespace_nodes.dm index 3aacc9fec5..b0705a0b76 100644 --- a/code/modules/research/techweb/nodes/bluespace_nodes.dm +++ b/code/modules/research/techweb/nodes/bluespace_nodes.dm @@ -13,7 +13,7 @@ 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") + design_ids = list("bs_rped","biobag_holding","minerbag_holding", "bluespacebeaker", "bluespacesyringe", "phasic_scanning", "bluespacesmartdart", "xenobio_slimebasic", "bluespace_tray", "bluespace_carrier") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000) /datum/techweb_node/adv_bluespace diff --git a/code/modules/research/techweb/nodes/engineering_nodes.dm b/code/modules/research/techweb/nodes/engineering_nodes.dm index eac8c2faf2..d024823c85 100644 --- a/code/modules/research/techweb/nodes/engineering_nodes.dm +++ b/code/modules/research/techweb/nodes/engineering_nodes.dm @@ -16,7 +16,9 @@ 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") + 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", "sheetifier") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000) /datum/techweb_node/anomaly diff --git a/code/modules/research/techweb/nodes/mecha_nodes.dm b/code/modules/research/techweb/nodes/mecha_nodes.dm index 4d1b703cae..2e77f697da 100644 --- a/code/modules/research/techweb/nodes/mecha_nodes.dm +++ b/code/modules/research/techweb/nodes/mecha_nodes.dm @@ -42,6 +42,14 @@ "gygax_peri", "gygax_targ", "gygax_armor") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/medigax + id = "mech_medigax" + display_name = "EXOSUIT: Medical-Spec Gygax" + description = "Medical-Spec Gygax designs" + prereq_ids = list("mech_gygax", "mecha_odysseus") + design_ids = list("medigax_chassis", "medigax_torso", "medigax_head", "medigax_left_arm", "medigax_right_arm", "medigax_left_leg", "medigax_right_leg", "medigax_armor") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + /datum/techweb_node/durand id = "mech_durand" display_name = "EXOSUIT: Durand" diff --git a/code/modules/research/techweb/nodes/medical_nodes.dm b/code/modules/research/techweb/nodes/medical_nodes.dm index 71dd7c943c..150e420c09 100644 --- a/code/modules/research/techweb/nodes/medical_nodes.dm +++ b/code/modules/research/techweb/nodes/medical_nodes.dm @@ -24,6 +24,23 @@ design_ids = list("defib_decay", "defib_shock", "defib_heal", "defib_speed") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/plumbing + id = "plumbing" + display_name = "Reagent Plumbing Technology" + description = "Plastic tubes, and machinery used for manipulating things in them." + prereq_ids = list("base") + design_ids = list("acclimator", "disposer", "plumb_filter", "plumb_synth", "plumb_grinder", "reaction_chamber", "duct_print", "plumb_splitter", "pill_press", "plumb_pump", "plumb_in", "plumb_out", "plumb_tank", "medipen_refiller") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) + + +/datum/techweb_node/advplumbing + id = "advplumbing" + display_name = "Advanced Plumbing Technology" + description = "Plumbing RCD." + prereq_ids = list("plumbing", "adv_engi") + design_ids = list("plumb_rcd", "autohydrotray") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + //////////////////////Cybernetics///////////////////// /datum/techweb_node/surplus_limbs @@ -104,7 +121,7 @@ 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") + design_ids = list("drapes", "retractor_adv", "surgicaldrill_adv", "scalpel_adv", "bonesetter", "surgical_tape") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) /datum/techweb_node/adv_surgery diff --git a/code/modules/research/techweb/nodes/tools_nodes.dm b/code/modules/research/techweb/nodes/tools_nodes.dm index 5d8d40f10d..180cdb5778 100644 --- a/code/modules/research/techweb/nodes/tools_nodes.dm +++ b/code/modules/research/techweb/nodes/tools_nodes.dm @@ -5,7 +5,7 @@ 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") + design_ids = list("screwdriver", "wrench", "wirecutters", "crowbar", "multitool", "welding_tool", "tscanner", "analyzer", "cable_coil", "pipe_painter", "airlock_painter", "decal_painter", "scalpel", "circular_saw", "surgicaldrill", "retractor", "cautery", "hemostat", "cultivator", "plant_analyzer", "shovel", "spade", "hatchet", "mop", "broom", "normtrash", "spraycan") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 500) /datum/techweb_node/basic_mining @@ -44,7 +44,7 @@ id = "exp_tools" display_name = "Experimental Tools" description = "Highly advanced construction tools." - design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan") + design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan", "ranged_analyzer") prereq_ids = list("adv_engi") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750) diff --git a/code/modules/research/xenobiology/crossbreeding/_clothing.dm b/code/modules/research/xenobiology/crossbreeding/_clothing.dm index 795a57b82c..1ac09652b5 100644 --- a/code/modules/research/xenobiology/crossbreeding/_clothing.dm +++ b/code/modules/research/xenobiology/crossbreeding/_clothing.dm @@ -57,7 +57,7 @@ Slimecrossing Armor light_color = newcolor set_light(5) -/obj/structure/light_prism/attack_hand(mob/user) +/obj/structure/light_prism/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) to_chat(user, "You dispel [src]") qdel(src) @@ -118,7 +118,7 @@ Slimecrossing Armor ..() REMOVE_TRAIT(user, TRAIT_PACIFISM, "peaceflower_[REF(src)]") -/obj/item/clothing/head/peaceflower/attack_hand(mob/user) +/obj/item/clothing/head/peaceflower/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) var/mob/living/carbon/C = user if(src == C.head) diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 7b5004e722..1a8b82232b 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -276,7 +276,7 @@ Burning extracts: /obj/item/slimecross/burning/adamantine/do_effect(mob/user) user.visible_message("[src] crystallizes into a large shield!") - new /obj/item/twohanded/required/adamantineshield(get_turf(user)) + new /obj/item/shield/adamantineshield(get_turf(user)) ..() /obj/item/slimecross/burning/rainbow @@ -440,7 +440,7 @@ Burning extracts: attack_verb = list("irradiated","mutated","maligned") return ..() -/obj/item/twohanded/required/adamantineshield +/obj/item/shield/adamantineshield name = "adamantine shield" desc = "A gigantic shield made of solid adamantium." icon = 'icons/obj/slimecrossing.dmi' @@ -450,12 +450,15 @@ Burning extracts: armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70) slot_flags = ITEM_SLOT_BACK block_chance = 75 + force = 0 throw_range = 1 //How far do you think you're gonna throw a solid crystalline shield...? throw_speed = 2 - force = 15 //Heavy, but hard to wield. attack_verb = list("bashed","pounded","slammed") item_flags = SLOWS_WHILE_IN_HAND +/obj/item/shield/adamantineshield/ComponentInitialize() + . = ..() + AddComponent(/datum/component/two_handed, require_twohands=TRUE, force_wielded=15) /obj/effect/proc_holder/spell/targeted/shapeshift/slimeform name = "Slime Transformation" diff --git a/code/modules/research/xenobiology/crossbreeding/chilling.dm b/code/modules/research/xenobiology/crossbreeding/chilling.dm index 1405bbad51..5325680588 100644 --- a/code/modules/research/xenobiology/crossbreeding/chilling.dm +++ b/code/modules/research/xenobiology/crossbreeding/chilling.dm @@ -100,9 +100,8 @@ Chilling extracts: for(var/turf/open/T in A) var/datum/gas_mixture/G = T.air if(istype(G)) - G.gases[/datum/gas/plasma] = 0 + G.set_moles(/datum/gas/plasma, 0) filtered = TRUE - GAS_GARBAGE_COLLECT(G.gases) T.air_update_turf() if(filtered) user.visible_message("Cracks spread throughout [src], and some air is sucked in!") @@ -308,4 +307,4 @@ Chilling extracts: user.visible_message("[src] reflects an array of dazzling colors and light, energy rushing to nearby doors!") for(var/obj/machinery/door/airlock/door in area) new /obj/effect/forcefield/slimewall/rainbow(door.loc) - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm index 45b6939f42..e572f1ee02 100644 --- a/code/modules/ruins/lavaland_ruin_code.dm +++ b/code/modules/ruins/lavaland_ruin_code.dm @@ -93,7 +93,7 @@ /obj/item/stack/sheet/mineral/adamantine = /datum/species/golem/adamantine, /obj/item/stack/sheet/plastic = /datum/species/golem/plastic, /obj/item/stack/tile/brass = /datum/species/golem/clockwork, - /obj/item/stack/tile/bronze = /datum/species/golem/bronze, + /obj/item/stack/sheet/bronze = /datum/species/golem/bronze, /obj/item/stack/sheet/cardboard = /datum/species/golem/cardboard, /obj/item/stack/sheet/leather = /datum/species/golem/leather, /obj/item/stack/sheet/bone = /datum/species/golem/bone, diff --git a/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm index 65530031c0..088683ccd2 100644 --- a/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm +++ b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm @@ -73,7 +73,7 @@ create_reagents(20) reagents.add_reagent(dispensedreagent, 20) -/obj/structure/sink/oil_well/attack_hand(mob/M) +/obj/structure/sink/oil_well/on_attack_hand(mob/M) flick("puddle-oil-splash",src) reagents.reaction(M, TOUCH, 20) //Covers target in 20u of oil. to_chat(M, "You touch the pool of oil, only to get oil all over yourself. It would be wise to wash this off with water.") diff --git a/code/modules/ruins/lavalandruin_code/puzzle.dm b/code/modules/ruins/lavalandruin_code/puzzle.dm index 70b0545ded..92e24e3bc4 100644 --- a/code/modules/ruins/lavalandruin_code/puzzle.dm +++ b/code/modules/ruins/lavalandruin_code/puzzle.dm @@ -289,7 +289,7 @@ /obj/effect/sliding_puzzle/prison/dispense_reward() prisoner.forceMove(get_turf(src)) - prisoner.notransform = FALSE + prisoner.mob_transforming = FALSE prisoner = null //Some armor so it's harder to kill someone by mistake. @@ -329,7 +329,7 @@ return FALSE //First grab the prisoner and move them temporarily into the generator so they won't get thrown around. - prisoner.notransform = TRUE + prisoner.mob_transforming = TRUE prisoner.forceMove(cube) to_chat(prisoner,"You're trapped by the prison cube! You will remain trapped until someone solves it.") @@ -350,4 +350,4 @@ //Move them into random block var/obj/structure/puzzle_element/E = pick(cube.elements) prisoner.forceMove(E) - return TRUE \ No newline at end of file + return TRUE diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm index c80b4d972c..fd2f4377e7 100644 --- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm +++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm @@ -87,8 +87,7 @@ else return QDEL_HINT_LETMELIVE -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/necropolis_gate/attack_hand(mob/user) +/obj/structure/necropolis_gate/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(locked || uses == 0) to_chat(user, "It's [open ? "stuck open":"locked"].") return @@ -166,8 +165,7 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate) else return QDEL_HINT_LETMELIVE -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/structure/necropolis_gate/legion_gate/attack_hand(mob/user) +/obj/structure/necropolis_gate/legion_gate/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!open && !changing_openness) var/safety = alert(user, "You think this might be a bad idea...", "Knock on the door?", "Proceed", "Abort") if(safety == "Abort" || !in_range(src, user) || !src || open || changing_openness || user.incapacitated()) diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm index 76897b5276..e87382cd6a 100644 --- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm +++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm @@ -57,7 +57,7 @@ canvas rotting away and contents vanishing.") qdel(src) -/obj/structure/cursed_money/attack_hand(mob/living/user) +/obj/structure/cursed_money/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) return diff --git a/code/modules/ruins/spaceruin_code/DJstation.dm b/code/modules/ruins/spaceruin_code/DJstation.dm index 29814d8c1f..ace32b694d 100644 --- a/code/modules/ruins/spaceruin_code/DJstation.dm +++ b/code/modules/ruins/spaceruin_code/DJstation.dm @@ -2,4 +2,20 @@ /obj/item/paper/fluff/ruins/djstation name = "paper - 'DJ Listening Outpost'" - info = "Welcome new owner!

    You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio frequencies. Here is a step by step guide to start listening in on those saucy radio channels:
    1. Equip yourself with a multitool
    2. Use the multitool on the relay.
    3. Turn it on. It has already been configured for you to listen on.
    Simple as that. Now to listen to the private channels, you'll have to configure the intercoms. They are located on the front desk. Here is a list of frequencies for you to listen on.
    • 145.9 - Common Channel
    • 144.7 - Private AI Channel
    • 135.9 - Security Channel
    • 135.7 - Engineering Channel
    • 135.5 - Medical Channel
    • 135.3 - Command Channel
    • 135.1 - Science Channel
    • 134.9 - Service Channel
    • 134.7 - Supply Channel
    • " + info = {" +**Welcome new owner!** +You have purchased the latest in listening equipment. The telecommunication setup we created is the best in listening to common and private radio frequencies. Here is a step by step guide to start listening in on those saucy radio channels: +1. Equip yourself with a multitool +2. Use the multitool on the relay. +3. Turn it on. It has already been configured for you to listen on. +Simple as that. Now to listen to the private channels, you'll have to configure the intercoms. They are located on the front desk. Here is a list of frequencies for you to listen on. +* 145.9 - Common Channel +* 144.7 - Private AI Channel +* 135.9 - Security Channel +* 135.7 - Engineering Channel +* 135.5 - Medical Channel +* 135.3 - Command Channel +* 135.1 - Science Channel +* 134.9 - Service Channel +* 134.7 - Supply Channel +"} diff --git a/code/modules/ruins/spaceruin_code/TheDerelict.dm b/code/modules/ruins/spaceruin_code/TheDerelict.dm index 58e257d587..d26e023df0 100644 --- a/code/modules/ruins/spaceruin_code/TheDerelict.dm +++ b/code/modules/ruins/spaceruin_code/TheDerelict.dm @@ -6,14 +6,186 @@ /obj/item/paper/fluff/ruins/thederelict/syndie_mission name = "Mission Objectives" - info = "The Syndicate have cunningly disguised a Syndicate Uplink as your PDA. Simply enter the code \"678 Bravo\" into the ringtone select to unlock its hidden features.

      Objective #1. Kill the God damn AI in a fire blast that it rocks the station. Success!
      Objective #2. Escape alive. Failed." + info = "The Syndicate have cunningly disguised a Syndicate Uplink as your PDA. Simply enter the code \"678 Bravo\" into the ringtone select to unlock its hidden features.\n \n__Objective #1__. Kill the God damn AI in a fire blast that it rocks the station. __Success!__ \n \n__Objective #2__. Escape alive. __Failed.__" /obj/item/paper/fluff/ruins/thederelict/nukie_objectives name = "Objectives of a Nuclear Operative" - info = "Objective #1: Destroy the station with a nuclear device." + info = "__Objective #1__: Destroy the station with a nuclear device." /obj/item/paper/crumpled/bloody/ruins/thederelict/unfinished name = "unfinished paper scrap" desc = "Looks like someone started shakily writing a will in space common, but were interrupted by something bloody..." - info = "I, Victor Belyakov, do hereby leave my _- " + info = "__Objectives #1__: Find out what is hidden in Kosmicheskaya Stantsiya 13s Vault" +/// Vault controller for use on the derelict/KS13. +/obj/machinery/computer/vaultcontroller + name = "vault controller" + desc = "It seems to be powering and controlling the vault locks." + icon_screen = "power" + icon_keyboard = "power_key" + light_color = LIGHT_COLOR_YELLOW + use_power = NO_POWER_USE + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + + var/obj/structure/cable/attached_cable + var/obj/machinery/door/airlock/vault/derelict/door1 + var/obj/machinery/door/airlock/vault/derelict/door2 + var/locked = TRUE + var/siphoned_power = 0 + var/siphon_max = 1e7 + +/obj/machinery/computer/monitor/examine(mob/user) + . = ..() + . += "It appears to be powered via a cable connector." + +//Checks for cable connection, charges if possible. +/obj/machinery/computer/vaultcontroller/process() + if(siphoned_power >= siphon_max) + return + update_cable() + if(attached_cable) + attempt_siphon() + +///Looks for a cable connection beneath the machine. +/obj/machinery/computer/vaultcontroller/proc/update_cable() + var/turf/T = get_turf(src) + attached_cable = locate(/obj/structure/cable) in T + +///Initializes airlock links. +/obj/machinery/computer/vaultcontroller/proc/find_airlocks() + for(var/obj/machinery/door/airlock/A in GLOB.airlocks) + if(A.id_tag == "derelictvault") + if(!door1) + door1 = A + continue + if(door1 && !door2) + door2 = A + break + +///Tries to charge from powernet excess, no upper limit except max charge. +/obj/machinery/computer/vaultcontroller/proc/attempt_siphon() + var/surpluspower = clamp(attached_cable.surplus(), 0, (siphon_max - siphoned_power)) + if(surpluspower) + attached_cable.add_load(surpluspower) + siphoned_power += surpluspower + +///Handles the doors closing +/obj/machinery/computer/vaultcontroller/proc/cycle_close(obj/machinery/door/airlock/A) + A.safe = FALSE //Make sure its forced closed, always + A.unbolt() + A.close() + A.bolt() + +///Handles the doors opening +/obj/machinery/computer/vaultcontroller/proc/cycle_open(obj/machinery/door/airlock/A) + A.unbolt() + A.open() + A.bolt() + +///Attempts to lock the vault doors +/obj/machinery/computer/vaultcontroller/proc/lock_vault() + if(door1 && !door1.density) + cycle_close(door1) + if(door2 && !door2.density) + cycle_close(door2) + if(door1.density && door1.locked && door2.density && door2.locked) + locked = TRUE + +///Attempts to unlock the vault doors +/obj/machinery/computer/vaultcontroller/proc/unlock_vault() + if(door1 && door1.density) + cycle_open(door1) + if(door2 && door2.density) + cycle_open(door2) + if(!door1.density && door1.locked && !door2.density && door2.locked) + locked = FALSE + +///Attempts to lock/unlock vault doors, if machine is charged. +/obj/machinery/computer/vaultcontroller/proc/activate_lock() + if(siphoned_power < siphon_max) + return + if(!door1 || !door2) + find_airlocks() + if(locked) + unlock_vault() + else + lock_vault() + +/obj/machinery/computer/vaultcontroller/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "VaultController", name) + ui.open() + +/obj/machinery/computer/vaultcontroller/ui_act(action, params) + if(..()) + return + switch(action) + if("togglelock") + activate_lock() + +/obj/machinery/computer/vaultcontroller/ui_data() + var/list/data = list() + data["stored"] = siphoned_power + data["max"] = siphon_max + data["doorstatus"] = locked + return data + +///Airlock that can't be deconstructed, broken or hacked. +/obj/machinery/door/airlock/vault/derelict + locked = TRUE + move_resist = INFINITY + use_power = NO_POWER_USE + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + id_tag = "derelictvault" + +///Overrides screwdriver attack to prevent all deconstruction and hacking. +/obj/machinery/door/airlock/vault/derelict/attackby(obj/item/C, mob/user, params) + if(C.tool_behaviour == TOOL_SCREWDRIVER) + return + ..() + +// So drones can teach borgs and AI dronespeak. For best effect, combine with mother drone lawset. +/obj/item/dronespeak_manual + name = "dronespeak manual" + desc = "The book's cover reads: \"Understanding Dronespeak - An exercise in futility.\"" + icon = 'icons/obj/library.dmi' + icon_state = "book2" + +/obj/item/dronespeak_manual/attack_self(mob/living/user) + ..() + if(isdrone(user) || issilicon(user)) + if(user.has_language(/datum/language/drone)) + to_chat(user, "You start skimming through [src], but you already know dronespeak.") + else + to_chat(user, "You start skimming through [src], and suddenly the drone chittering makes sense.") + user.grant_language(/datum/language/drone, TRUE, TRUE)//, LANGUAGE_MIND) + return + + if(user.has_language(/datum/language/drone)) + to_chat(user, "You start skimming through [src], but you already know dronespeak.") + else + to_chat(user, "You start skimming through [src], but you can't make any sense of the contents.") + +/obj/item/dronespeak_manual/attack(mob/living/M, mob/living/user) + if(!istype(M) || !istype(user)) + return + if(M == user) + attack_self(user) + return + + playsound(loc, "punch", 25, TRUE, -1) + if(isdrone(M) || issilicon(M)) + if(M.has_language(/datum/language/drone)) + 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], chitters resonate in your mind.", "You hear smacking.") + M.grant_language(/datum/language/drone, TRUE, TRUE) //, LANGUAGE_MIND) + return + +/obj/structure/fluff/oldturret + name = "broken turret" + desc = "An obsolete model of turret, long non-functional." + icon = 'icons/obj/turrets.dmi' + icon_state = "turretCover" + density = TRUE diff --git a/code/modules/ruins/spaceruin_code/clericsden.dm b/code/modules/ruins/spaceruin_code/clericsden.dm index 7d1fda6740..3fe4cad794 100644 --- a/code/modules/ruins/spaceruin_code/clericsden.dm +++ b/code/modules/ruins/spaceruin_code/clericsden.dm @@ -21,7 +21,6 @@ desc = "A weaker construct meant to scour ruins for objects of Nar'Sie's affection. Those barbed claws are no joke." icon_state = "proteon" icon_living = "proteon" - threat = 0.4 maxHealth = 35 health = 35 melee_damage_lower = 8 diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index a60d564631..d97eae5766 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -263,7 +263,7 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) /turf/closed/indestructible/hoteldoor/attack_tk(mob/user) return //need to be close. -/turf/closed/indestructible/hoteldoor/attack_hand(mob/user) +/turf/closed/indestructible/hoteldoor/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) promptExit(user) /turf/closed/indestructible/hoteldoor/attack_animal(mob/user) @@ -413,13 +413,13 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) . = ..() if(ismob(AM)) var/mob/M = AM - M.notransform = TRUE + M.mob_transforming = TRUE /obj/item/abstracthotelstorage/Exited(atom/movable/AM, atom/newLoc) . = ..() if(ismob(AM)) var/mob/M = AM - M.notransform = FALSE + M.mob_transforming = FALSE //Space Ruin stuff /area/ruin/space/has_grav/hilbertresearchfacility @@ -474,29 +474,29 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) /obj/item/paper/crumpled/docslogs/Initialize() . = ..() GLOB.hhmysteryRoomNumber = rand(1, SHORT_REAL_LIMIT) - info = {"

      Research Logs

      - I might just be onto something here!
      - The strange space-warping properties of bluespace have been known about for awhile now, but I might be on the verge of discovering a new way of harnessing it.
      - It's too soon to say for sure, but this might be the start of something quite important!
      - I'll be sure to log any major future breakthroughs. This might be a lot more than I can manage on my own, perhaps I should hire that secretary after all...
      -

      Breakthrough!

      - I can't believe it, but I did it! Just when I was certain it couldn't be done, I made the final necessary breakthrough.
      - Exploiting the effects of space dilation caused by specific bluespace structures combined with a precise use of geometric calculus, I've discovered a way to correlate an infinite amount of space within a finite area!
      - While the potential applications are endless, I utilized it in quite a nifty way so far by designing a system that recursively constructs subspace rooms and spatially links them to any of the infinite infinitesimally distinct points on the spheres surface.
      - I call it: Hilbert's Hotel!
      -

      Goodbye

      - I can't take this anymore. I know what happens next, and the fear of what is coming leaves me unable to continue working.
      - Any fool in my field has heard the stories. It's not that I didn't believe them, it's just... I guess I underestimated the importance of my own research...
      - Robert has reported a further increase in frequency of the strange, prying visitors who ask questions they have no business asking. I've requested him to keep everything on strict lockdown and have permanently dismissed all other assistants.
      - I've also instructed him to use the encryption method we discussed for any important quantitative data. The poor lad... I don't think he truly understands what he's gotten himself into...
      - It's clear what happens now. One day they'll show up uninvited, and claim my research as their own, leaving me as nothing more than a bullet ridden corpse floating in space.
      - I can't stick around to the let that happen.
      - I'm escaping into the very thing that brought all this trouble to my doorstep in the first place - my hotel.
      - I'll be in [uppertext(num2hex(GLOB.hhmysteryRoomNumber, 0))] (That will make sense to anyone who should know)
      - I'm sorry that I must go like this. Maybe one day things will be different and it will be safe to return... maybe...
      - Goodbye
      -
      - Doctor Hilbert"} + info = {" +### Research Logs +I might just be onto something here! +The strange space-warping properties of bluespace have been known about for awhile now, but I might be on the verge of discovering a new way of harnessing it. +It's too soon to say for sure, but this might be the start of something quite important! +I'll be sure to log any major future breakthroughs. This might be a lot more than I can manage on my own, perhaps I should hire that secretary after all... +### Breakthrough! +I can't believe it, but I did it! Just when I was certain it couldn't be done, I made the final necessary breakthrough. +Exploiting the effects of space dilation caused by specific bluespace structures combined with a precise use of geometric calculus, I've discovered a way to correlate an infinite amount of space within a finite area! +While the potential applications are endless, I utilized it in quite a nifty way so far by designing a system that recursively constructs subspace rooms and spatially links them to any of the infinite infinitesimally distinct points on the spheres surface. +I call it: Hilbert's Hotel! +

      Goodbye

      +I can't take this anymore. I know what happens next, and the fear of what is coming leaves me unable to continue working. +Any fool in my field has heard the stories. It's not that I didn't believe them, it's just... I guess I underestimated the importance of my own research... +Robert has reported a further increase in frequency of the strange, prying visitors who ask questions they have no business asking. I've requested him to keep everything on strict lockdown and have permanently dismissed all other assistants. +I've also instructed him to use the encryption method we discussed for any important quantitative data. The poor lad... I don't think he truly understands what he's gotten himself into... +It's clear what happens now. One day they'll show up uninvited, and claim my research as their own, leaving me as nothing more than a bullet ridden corpse floating in space. +I can't stick around to the let that happen. +I'm escaping into the very thing that brought all this trouble to my doorstep in the first place - my hotel. +I'll be in [uppertext(num2hex(GLOB.hhmysteryRoomNumber, 0))] (That will make sense to anyone who should know) +I'm sorry that I must go like this. Maybe one day things will be different and it will be safe to return... maybe... +Goodbye + _Doctor Hilbert_"} /obj/item/paper/crumpled/robertsworkjournal name = "Work Journal" @@ -526,16 +526,15 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) /obj/item/paper/crumpled/bloody/docsdeathnote name = "note" - info = {"This is it isn't it?
      - No one's coming to help, that much has become clear.
      - Sure, it's lonely, but do I have much choice? At least I brought the analyzer with me, they shouldn't be able to find me without it.
      - Who knows who's waiting for me out there. Its either die out there in their hands, or die a slower, slightly more comfortable death in here.
      - Everyday I can feel myself slipping away more and more, both physically and mentally. Who knows what happens now...
      - Heh, so it's true then, this must be the inescapable path of all great minds... so be it then.
      -
      -
      -
      - Choose a room, and enter the sphere
      - Lay your head to rest, it soon becomes clear
      - There's always more room around every bend
      - Not all that's countable has an end..."} + info = {" +This is it isn't it? +No one's coming to help, that much has become clear. +Sure, it's lonely, but do I have much choice? At least I brought the analyzer with me, they shouldn't be able to find me without it. +Who knows who's waiting for me out there. Its either die out there in their hands, or die a slower, slightly more comfortable death in here. +Everyday I can feel myself slipping away more and more, both physically and mentally. Who knows what happens now... +Heh, so it's true then, this must be the inescapable path of all great minds... so be it then. +_Choose a room, and enter the sphere +Lay your head to rest, it soon becomes clear +There's always more room around every bend +Not all that's countable has an end..._ +"} diff --git a/code/modules/ruins/spaceruin_code/oldstation.dm b/code/modules/ruins/spaceruin_code/oldstation.dm index e72dbea044..90de7040f4 100644 --- a/code/modules/ruins/spaceruin_code/oldstation.dm +++ b/code/modules/ruins/spaceruin_code/oldstation.dm @@ -38,8 +38,15 @@ /obj/item/paper/fluff/ruins/oldstation/protoinv name = "Laboratory Inventory" - info = "*Inventory*

      (1) Prototype Hardsuit

      (1)Health Analyser

      (1)Prototype Energy Gun

      (1)Singularity Generation Disk

      DO NOT REMOVE WITHOUT \ - THE CAPTAIN AND RESEARCH DIRECTOR'S AUTHORISATION" + info = {" +**Inventory** +* (1) Prototype Hardsuit +* (1)Health Analyser +* (1)Prototype Energy Gun +* (1)Singularity Generation Disk +__DO NOT REMOVE WITHOUT HE CAPTAIN AND RESEARCH DIRECTOR'S AUTHORISATION__ +"} + /obj/item/paper/fluff/ruins/oldstation/report name = "Crew Reawakening Report" diff --git a/code/modules/ruins/spaceruin_code/originalcontent.dm b/code/modules/ruins/spaceruin_code/originalcontent.dm index 5da28af26d..62d9170c2f 100644 --- a/code/modules/ruins/spaceruin_code/originalcontent.dm +++ b/code/modules/ruins/spaceruin_code/originalcontent.dm @@ -1,28 +1,28 @@ /////////// originalcontent items /obj/item/paper/crumpled/ruins/originalcontent - desc = "Various scrawled out drawings and sketches reside on the paper, apparently he didn't much care for these drawings." + desc = "_Various scrawled out drawings and sketches reside on the paper, apparently he didn't much care for these drawings._" /obj/item/paper/pamphlet/ruin/originalcontent icon = 'icons/obj/fluff.dmi' /obj/item/paper/pamphlet/ruin/originalcontent/stickman name = "Painting - 'BANG'" - info = "This picture depicts a crudely-drawn stickman firing a crudely-drawn gun." + info = "_This picture depicts a crudely-drawn stickman firing a crudely-drawn gun._" icon_state = "painting4" /obj/item/paper/pamphlet/ruin/originalcontent/treeside name = "Painting - 'Treeside'" - info = "This picture depicts a sunny day on a lush hillside, set under a shaded tree." + info = "_This picture depicts a sunny day on a lush hillside, set under a shaded tree._" icon_state = "painting1" /obj/item/paper/pamphlet/ruin/originalcontent/pennywise name = "Painting - 'Pennywise'" - info = "This picture depicts a smiling clown. Something doesn't feel right about this.." + info = "_This picture depicts a smiling clown. Something doesn't feel right about this.._" icon_state = "painting3" /obj/item/paper/pamphlet/ruin/originalcontent/yelling name = "Painting - 'Hands-On-Face'" - info = "This picture depicts a man yelling on a bridge for no apparent reason." + info = "_This picture depicts a man yelling on a bridge for no apparent reason._" icon_state = "painting2" diff --git a/code/modules/ruins/spaceruin_code/spacehotel.dm b/code/modules/ruins/spaceruin_code/spacehotel.dm index 69eebd8535..caea851783 100644 --- a/code/modules/ruins/spaceruin_code/spacehotel.dm +++ b/code/modules/ruins/spaceruin_code/spacehotel.dm @@ -3,10 +3,9 @@ /obj/item/paper/fluff/ruins/spacehotel/notice name = "!NOTICE!" - info = "!NOTICE!

      We are expecting arriving guests soon from a nearby station! Stay sharp and make sure guests enjoy their time spent here. Don't think you can sneak off while they're here, either.
      " + info = "__!NOTICE!__\n \nWe are expecting arriving guests soon from a nearby station! Stay sharp and make sure guests enjoy their time spent here. Don't think you can sneak off while they're here, either." /obj/item/paper/pamphlet/ruin/spacehotel name = "hotel pamphlet" - info = "
      The Twin Nexus Hotel

      A place of Sanctuary


      Welcome to The Twin-Nexus Hotel, \[insert name here]! The loyal staff stride to their best effort to cater for the best possible experience for all space(wo)men! If you have any questions or comments, please ask one of our on-board staff for more information.
      " - + info = "__The Twin Nexus Hotel__\n*A place of Sanctuary*\n \nWelcome to The Twin-Nexus Hotel, \[insert name here]! The loyal staff strive to their best effort to cater for the best possible experience for all space(wo)men! If you have any questions or comments, please ask one of our on-board staff for more information." diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm index adf53ff0da..7326cad816 100644 --- a/code/modules/security_levels/keycard_authentication.dm +++ b/code/modules/security_levels/keycard_authentication.dm @@ -16,6 +16,9 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new) power_channel = ENVIRON req_access = list(ACCESS_KEYCARD_AUTH) resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + ui_x = 375 + ui_y = 125 + var/datum/callback/ev var/event = "" var/obj/machinery/keycard_auth/event_source @@ -32,11 +35,13 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new) QDEL_NULL(ev) return ..() -/obj/machinery/keycard_auth/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) +/obj/machinery/keycard_auth/ui_state(mob/user) + return GLOB.physical_state + +/obj/machinery/keycard_auth/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "keycard_auth", name, 375, 125, master_ui, state) + ui = new(user, src, "KeycardAuth", name) ui.open() /obj/machinery/keycard_auth/ui_data() @@ -108,13 +113,13 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new) /obj/machinery/keycard_auth/proc/trigger_event(confirmer) log_game("[key_name(triggerer)] triggered and [key_name(confirmer)] confirmed event [event]") - message_admins("[key_name(triggerer)] triggered and [key_name(confirmer)] confirmed event [event]") + message_admins("[ADMIN_LOOKUPFLW(triggerer)] triggered and [ADMIN_LOOKUPFLW(confirmer)] confirmed event [event]") var/area/A1 = get_area(triggerer) - deadchat_broadcast("[triggerer] triggered [event] at [A1.name].", triggerer) + deadchat_broadcast(" triggered [event] at [A1.name].", "[triggerer]", triggerer) var/area/A2 = get_area(confirmer) - deadchat_broadcast("[confirmer] confirmed [event] at [A2.name].", confirmer) + deadchat_broadcast(" confirmed [event] at [A2.name].", "[confirmer]", confirmer) switch(event) if(KEYCARD_RED_ALERT) set_security_level(SEC_LEVEL_RED) diff --git a/code/modules/shuttle/arrivals.dm b/code/modules/shuttle/arrivals.dm index 190db2c362..8322c6cdd8 100644 --- a/code/modules/shuttle/arrivals.dm +++ b/code/modules/shuttle/arrivals.dm @@ -201,6 +201,6 @@ /obj/docking_port/mobile/arrivals/vv_edit_var(var_name, var_value) switch(var_name) - if("perma_docked") + if(NAMEOF(src, perma_docked)) SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("arrivals shuttle", "[var_value ? "stopped" : "started"]")) return ..() diff --git a/code/modules/shuttle/computer.dm b/code/modules/shuttle/computer.dm index 75bf55a5a3..682a7fa14b 100644 --- a/code/modules/shuttle/computer.dm +++ b/code/modules/shuttle/computer.dm @@ -57,6 +57,7 @@ switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1)) if(0) say("Shuttle departing. Please stand away from the doors.") + log_shuttle("[key_name(usr)] has sent shuttle \"[M]\" towards \"[href_list["move"]]\", using [src].") if(1) to_chat(usr, "Invalid shuttle requested.") else @@ -73,4 +74,4 @@ /obj/machinery/computer/shuttle/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE) if(port && (shuttleId == initial(shuttleId) || override)) - shuttleId = port.id \ No newline at end of file + shuttleId = port.id diff --git a/code/modules/shuttle/custom_shuttle.dm b/code/modules/shuttle/custom_shuttle.dm index 6e06e3fefe..c71b6ba9a8 100644 --- a/code/modules/shuttle/custom_shuttle.dm +++ b/code/modules/shuttle/custom_shuttle.dm @@ -257,7 +257,7 @@ return ..() -/obj/machinery/computer/camera_advanced/shuttle_docker/custom/attack_hand(mob/user) +/obj/machinery/computer/camera_advanced/shuttle_docker/custom/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!shuttleId) to_chat(user, "You must link the console to a shuttle first.") return diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 358fc5ad50..810cadcd2c 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -45,12 +45,14 @@ say("Please equip your ID card into your ID slot to authenticate.") . = ..() -/obj/machinery/computer/emergency_shuttle/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.human_adjacent_state) +/obj/machinery/computer/emergency_shuttle/ui_state(mob/user) + return GLOB.human_adjacent_state - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/emergency_shuttle/ui_interact(mob/user, datum/tgui/ui) + + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "emergency_shuttle_console", name, - 400, 350, master_ui, state) + ui = new(user, src, "EmergencyShuttleConsole", name) ui.open() /obj/machinery/computer/emergency_shuttle/ui_data() @@ -66,8 +68,8 @@ var/job = ID.assignment if(obj_flags & EMAGGED) - name = Gibberish(name, 0) - job = Gibberish(job, 0) + name = Gibberish(name) + job = Gibberish(job) A += list(list("name" = name, "job" = job)) data["authorizations"] = A @@ -145,7 +147,7 @@ authorized += ID message_admins("[ADMIN_LOOKUPFLW(user)] has authorized early shuttle launch") - log_game("[key_name(user)] has authorized early shuttle launch in [COORD(src)]") + log_shuttle("[key_name(user)] has authorized early shuttle launch in [COORD(src)]") // Now check if we're on our way . = TRUE process() @@ -251,7 +253,7 @@ var/time = TIME_LEFT message_admins("[ADMIN_LOOKUPFLW(user.client)] has emagged the emergency shuttle [time] seconds before launch.") - log_game("[key_name(user)] has emagged the emergency shuttle in [COORD(src)] [time] seconds before launch.") + log_shuttle("[key_name(user)] has emagged the emergency shuttle in [COORD(src)] [time] seconds before launch.") obj_flags |= EMAGGED SSshuttle.emergency.movement_force = list("KNOCKDOWN" = 60, "THROW" = 20)//YOUR PUNY SEATBELTS can SAVE YOU NOW, MORTAL var/datum/species/S = new diff --git a/code/modules/shuttle/manipulator.dm b/code/modules/shuttle/manipulator.dm index 8f98a89c36..5f120791cb 100644 --- a/code/modules/shuttle/manipulator.dm +++ b/code/modules/shuttle/manipulator.dm @@ -11,363 +11,13 @@ density = TRUE - // UI state variables - var/datum/map_template/shuttle/selected - - var/obj/docking_port/mobile/existing_shuttle - - var/obj/docking_port/mobile/preview_shuttle - var/datum/map_template/shuttle/preview_template - -/obj/machinery/shuttle_manipulator/Initialize() - . = ..() - update_icon() - SSshuttle.manipulator = src - -/obj/machinery/shuttle_manipulator/Destroy(force) - if(!force) - . = QDEL_HINT_LETMELIVE - else - SSshuttle.manipulator = null - . = ..() - /obj/machinery/shuttle_manipulator/update_overlays() . = ..() var/mutable_appearance/hologram_projection = mutable_appearance(icon, "hologram_on") hologram_projection.pixel_y = 22 var/mutable_appearance/hologram_ship = mutable_appearance(icon, "hologram_whiteship") hologram_ship.pixel_y = 27 + add_overlay(hologram_projection) + add_overlay(hologram_ship) . += hologram_projection . += hologram_ship - -/obj/machinery/shuttle_manipulator/can_interact(mob/user) - // Only admins can use this, but they can use it from anywhere - return user.client && check_rights_for(user.client, R_ADMIN) - -/obj/machinery/shuttle_manipulator/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "shuttle_manipulator", name, 800, 600, master_ui, state) - ui.open() - -/proc/shuttlemode2str(mode) - switch(mode) - if(SHUTTLE_IDLE) - . = "idle" - if(SHUTTLE_IGNITING) - . = "engines charging" - if(SHUTTLE_RECALL) - . = "recalled" - if(SHUTTLE_CALL) - . = "called" - if(SHUTTLE_DOCKED) - . = "docked" - if(SHUTTLE_STRANDED) - . = "stranded" - if(SHUTTLE_ESCAPE) - . = "escape" - if(SHUTTLE_ENDGAME) - . = "endgame" - if(!.) - CRASH("shuttlemode2str(): invalid mode [mode]") - - -/obj/machinery/shuttle_manipulator/ui_data(mob/user) - var/list/data = list() - data["tabs"] = list("Status", "Templates", "Modification") - - // Templates panel - data["templates"] = list() - var/list/templates = data["templates"] - data["templates_tabs"] = list() - data["selected"] = list() - - for(var/shuttle_id in SSmapping.shuttle_templates) - var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id] - - if(!templates[S.port_id]) - data["templates_tabs"] += S.port_id - templates[S.port_id] = list( - "port_id" = S.port_id, - "templates" = list()) - - var/list/L = list() - L["name"] = S.name - L["shuttle_id"] = S.shuttle_id - L["port_id"] = S.port_id - L["description"] = S.description - L["admin_notes"] = S.admin_notes - - if(selected == S) - data["selected"] = L - - templates[S.port_id]["templates"] += list(L) - - data["templates_tabs"] = sortList(data["templates_tabs"]) - - data["existing_shuttle"] = null - - // Status panel - data["shuttles"] = list() - for(var/i in SSshuttle.mobile) - var/obj/docking_port/mobile/M = i - var/timeleft = M.timeLeft(1) - var/list/L = list() - L["name"] = M.name - L["id"] = M.id - L["timer"] = M.timer - L["timeleft"] = M.getTimerStr() - if (timeleft > 1 HOURS) - L["timeleft"] = "Infinity" - L["can_fast_travel"] = M.timer && timeleft >= 50 - L["can_fly"] = TRUE - if(istype(M, /obj/docking_port/mobile/emergency)) - L["can_fly"] = FALSE - else if(!M.destination) - L["can_fast_travel"] = FALSE - if (M.mode != SHUTTLE_IDLE) - L["mode"] = capitalize(shuttlemode2str(M.mode)) - L["status"] = M.getDbgStatusText() - if(M == existing_shuttle) - data["existing_shuttle"] = L - - data["shuttles"] += list(L) - - return data - -/obj/machinery/shuttle_manipulator/ui_act(action, params) - if(..()) - return - - var/mob/user = usr - - // Preload some common parameters - var/shuttle_id = params["shuttle_id"] - var/datum/map_template/shuttle/S = SSmapping.shuttle_templates[shuttle_id] - - switch(action) - if("select_template") - if(S) - existing_shuttle = SSshuttle.getShuttle(S.port_id) - selected = S - . = TRUE - if("jump_to") - if(params["type"] == "mobile") - for(var/i in SSshuttle.mobile) - var/obj/docking_port/mobile/M = i - if(M.id == params["id"]) - user.forceMove(get_turf(M)) - . = TRUE - break - - if("fly") - for(var/i in SSshuttle.mobile) - var/obj/docking_port/mobile/M = i - if(M.id == params["id"]) - . = TRUE - M.admin_fly_shuttle(user) - break - - if("fast_travel") - for(var/i in SSshuttle.mobile) - var/obj/docking_port/mobile/M = i - if(M.id == params["id"] && M.timer && M.timeLeft(1) >= 50) - M.setTimer(50) - . = TRUE - message_admins("[key_name_admin(usr)] fast travelled [M]") - log_admin("[key_name(usr)] fast travelled [M]") - SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[M.name]") - break - - if("preview") - if(S) - . = TRUE - unload_preview() - load_template(S) - if(preview_shuttle) - preview_template = S - user.forceMove(get_turf(preview_shuttle)) - if("load") - if(existing_shuttle == SSshuttle.backup_shuttle) - // TODO make the load button disabled - WARNING("The shuttle that the selected shuttle will replace \ - is the backup shuttle. Backup shuttle is required to be \ - intact for round sanity.") - else if(S) - . = TRUE - // If successful, returns the mobile docking port - var/obj/docking_port/mobile/mdp = action_load(S) - if(mdp) - user.forceMove(get_turf(mdp)) - message_admins("[key_name_admin(usr)] loaded [mdp] with the shuttle manipulator.") - log_admin("[key_name(usr)] loaded [mdp] with the shuttle manipulator.") - SSblackbox.record_feedback("text", "shuttle_manipulator", 1, "[mdp.name]") - - update_icon() - -/obj/machinery/shuttle_manipulator/proc/action_load(datum/map_template/shuttle/loading_template, obj/docking_port/stationary/destination_port) - // Check for an existing preview - if(preview_shuttle && (loading_template != preview_template)) - preview_shuttle.jumpToNullSpace() - preview_shuttle = null - preview_template = null - - if(!preview_shuttle) - if(load_template(loading_template)) - preview_shuttle.linkup(loading_template, destination_port) - preview_template = loading_template - - // get the existing shuttle information, if any - var/timer = 0 - var/mode = SHUTTLE_IDLE - var/obj/docking_port/stationary/D - - if(istype(destination_port)) - D = destination_port - else if(existing_shuttle) - timer = existing_shuttle.timer - mode = existing_shuttle.mode - D = existing_shuttle.get_docked() - - if(!D) - CRASH("No dock found for preview shuttle ([preview_template.name]), aborting.") - - var/result = preview_shuttle.canDock(D) - // truthy value means that it cannot dock for some reason - // but we can ignore the someone else docked error because we'll - // be moving into their place shortly - if((result != SHUTTLE_CAN_DOCK) && (result != SHUTTLE_SOMEONE_ELSE_DOCKED)) - WARNING("Template shuttle [preview_shuttle] cannot dock at [D] ([result]).") - return - - if(existing_shuttle) - existing_shuttle.jumpToNullSpace() - - var/list/force_memory = preview_shuttle.movement_force - preview_shuttle.movement_force = list("KNOCKDOWN" = 0, "THROW" = 0) - preview_shuttle.initiate_docking(D) - preview_shuttle.movement_force = force_memory - - . = preview_shuttle - - // Shuttle state involves a mode and a timer based on world.time, so - // plugging the existing shuttles old values in works fine. - preview_shuttle.timer = timer - preview_shuttle.mode = mode - - preview_shuttle.register() - - // TODO indicate to the user that success happened, rather than just - // blanking the modification tab - preview_shuttle = null - preview_template = null - existing_shuttle = null - selected = null - -/obj/machinery/shuttle_manipulator/proc/load_template(datum/map_template/shuttle/S) - . = FALSE - // load shuttle template, centred at shuttle import landmark, - var/turf/landmark_turf = get_turf(locate(/obj/effect/landmark/shuttle_import) in GLOB.landmarks_list) - S.load(landmark_turf, centered = TRUE, register = FALSE) - - var/affected = S.get_affected_turfs(landmark_turf, centered = TRUE) - - var/found = 0 - // Search the turfs for docking ports - // - We need to find the mobile docking port because that is the heart of - // the shuttle. - // - We need to check that no additional ports have slipped in from the - // template, because that causes unintended behaviour. - for(var/T in affected) - for(var/obj/docking_port/P in T) - if(istype(P, /obj/docking_port/mobile)) - found++ - if(found > 1) - qdel(P, force=TRUE) - log_world("Map warning: Shuttle Template [S.mappath] has multiple mobile docking ports.") - else - preview_shuttle = P - if(istype(P, /obj/docking_port/stationary)) - log_world("Map warning: Shuttle Template [S.mappath] has a stationary docking port.") - if(!found) - var/msg = "load_template(): Shuttle Template [S.mappath] has no mobile docking port. Aborting import." - for(var/T in affected) - var/turf/T0 = T - T0.empty() - - message_admins(msg) - WARNING(msg) - return - //Everything fine - S.on_bought() - return TRUE - -/obj/machinery/shuttle_manipulator/proc/unload_preview() - if(preview_shuttle) - preview_shuttle.jumpToNullSpace() - preview_shuttle = null - -/obj/docking_port/mobile/proc/admin_fly_shuttle(mob/user) - var/list/options = list() - - for(var/port in SSshuttle.stationary) - if (istype(port, /obj/docking_port/stationary/transit)) - continue // please don't do this - var/obj/docking_port/stationary/S = port - if (canDock(S) == SHUTTLE_CAN_DOCK) - options[S.name || S.id] = S - - options += "--------" - options += "Infinite Transit" - options += "Delete Shuttle" - options += "Into The Sunset (delete & greentext 'escape')" - - var/selection = input(user, "Select where to fly [name || id]:", "Fly Shuttle") as null|anything in options - if(!selection) - return - - switch(selection) - if("Infinite Transit") - destination = null - mode = SHUTTLE_IGNITING - setTimer(ignitionTime) - - if("Delete Shuttle") - if(alert(user, "Really delete [name || id]?", "Delete Shuttle", "Cancel", "Really!") != "Really!") - return - jumpToNullSpace() - - if("Into The Sunset (delete & greentext 'escape')") - if(alert(user, "Really delete [name || id] and greentext escape objectives?", "Delete Shuttle", "Cancel", "Really!") != "Really!") - return - intoTheSunset() - - else - if(options[selection]) - request(options[selection]) - -/obj/docking_port/mobile/emergency/admin_fly_shuttle(mob/user) - return // use the existing verbs for this - -/obj/docking_port/mobile/arrivals/admin_fly_shuttle(mob/user) - switch(alert(user, "Would you like to fly the arrivals shuttle once or change its destination?", "Fly Shuttle", "Fly", "Retarget", "Cancel")) - if("Cancel") - return - if("Fly") - return ..() - - var/list/options = list() - - for(var/port in SSshuttle.stationary) - if (istype(port, /obj/docking_port/stationary/transit)) - continue // please don't do this - var/obj/docking_port/stationary/S = port - if (canDock(S) == SHUTTLE_CAN_DOCK) - options[S.name || S.id] = S - - var/selection = input(user, "Select the new arrivals destination:", "Fly Shuttle") as null|anything in options - if(!selection) - return - target_dock = options[selection] - if(!QDELETED(target_dock)) - destination = target_dock diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index 4f53e5d9d0..195e87720c 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -29,7 +29,7 @@ . = ..() GLOB.navigation_computers -= src -/obj/machinery/computer/camera_advanced/shuttle_docker/attack_hand(mob/user) +/obj/machinery/computer/camera_advanced/shuttle_docker/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(jammed) to_chat(user, "The Syndicate is jamming the console!") return diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index b782eccfcc..d7a6d4a583 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -216,10 +216,10 @@ roundstart_template = SSmapping.shuttle_templates[sid] if(!roundstart_template) - CRASH("Invalid path ([roundstart_template]) passed to docking port.") + CRASH("Invalid path ([sid]/[roundstart_template]) passed to docking port.") if(roundstart_template) - SSshuttle.manipulator.action_load(roundstart_template, src) + SSshuttle.action_load(roundstart_template, src) //returns first-found touching shuttleport /obj/docking_port/stationary/get_docked() @@ -507,7 +507,7 @@ if(M.mind && !istype(t, /turf/open/floor/plasteel/shuttle/red) && !istype(t, /turf/open/floor/mineral/plastitanium/red/brig)) M.mind.force_escaped = TRUE // Ghostize them and put them in nullspace stasis (for stat & possession checks) - M.notransform = TRUE + M.mob_transforming = TRUE M.ghostize(FALSE) M.moveToNullspace() diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator.dm index f5a11db60f..b3d99f22ab 100644 --- a/code/modules/shuttle/shuttle_creation/shuttle_creator.dm +++ b/code/modules/shuttle/shuttle_creation/shuttle_creator.dm @@ -43,6 +43,7 @@ GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (He . = ..() internal_shuttle_creator = new() internal_shuttle_creator.owner_rsd = src + desc += " Attention, the max size of the shuttle is [SHUTTLE_CREATOR_MAX_SIZE]." overlay_holder = new() /obj/item/shuttle_creator/Destroy() @@ -237,13 +238,13 @@ GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (He port.register() - icon_state = "rsd_used" + icon_state = "rsd_empty" //Clear highlights overlay_holder.clear_highlights() GLOB.custom_shuttle_count ++ - message_admins("[ADMIN_LOOKUPFLW(user)] created a new shuttle with a [src] at [ADMIN_VERBOSEJMP(user)] ([GLOB.custom_shuttle_count] custom shuttles, limit is [CUSTOM_SHUTTLE_LIMIT])") - log_game("[key_name(user)] created a new shuttle with a [src] at [AREACOORD(user)] ([GLOB.custom_shuttle_count] custom shuttles, limit is [CUSTOM_SHUTTLE_LIMIT])") + message_admins("[ADMIN_LOOKUPFLW(user)] created a new shuttle with a [src] at [ADMIN_VERBOSEJMP(user)] ([GLOB.custom_shuttle_count] custom shuttles)") + log_game("[key_name(user)] created a new shuttle with a [src] at [AREACOORD(user)] ([GLOB.custom_shuttle_count] custom shuttles)") return TRUE /obj/item/shuttle_creator/proc/create_shuttle_area(mob/user) @@ -350,7 +351,7 @@ GLOBAL_LIST_EMPTY(custom_shuttle_machines) //Machines that require updating (He loggedOldArea = get_area(get_turf(user)) loggedTurfs |= turfs overlay_holder.highlight_area(turfs) - //TODO READD THIS SHIT: icon_state = "rsd_used" + //TODO READD THIS SHIT: icon_state = "rsd_empty" to_chat(user, "You add the area into the buffer of the [src], you made add more areas or select an airlock to act as a docking port to complete the shuttle.") return turfs diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm index 6945c93427..314d5e8b80 100644 --- a/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm +++ b/code/modules/shuttle/shuttle_creation/shuttle_creator_console.dm @@ -58,10 +58,10 @@ . = ..() owner_rsd.overlay_holder.remove_client() eyeobj.invisibility = INVISIBILITY_MAXIMUM - if(user.client) + if(user?.client) user.client.images -= eyeobj.user_image -/obj/machinery/computer/camera_advanced/shuttle_creator/attack_hand(mob/user) +/obj/machinery/computer/camera_advanced/shuttle_creator/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(!is_operational()) //you cant use broken machine you chumbis return if(current_user) diff --git a/code/modules/shuttle/shuttle_creation/shuttle_creator_overlay.dm b/code/modules/shuttle/shuttle_creation/shuttle_creator_overlay.dm index 919b1f0221..83c03ed33c 100644 --- a/code/modules/shuttle/shuttle_creation/shuttle_creator_overlay.dm +++ b/code/modules/shuttle/shuttle_creation/shuttle_creator_overlay.dm @@ -12,8 +12,9 @@ holder.images += images /datum/shuttle_creator_overlay_holder/proc/remove_client() - holder.images -= images - holder = null + if(holder) + holder.images -= images + holder = null /datum/shuttle_creator_overlay_holder/proc/clear_highlights() if(holder) diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index a4ef2dfde9..7af0315934 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -101,6 +101,10 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list( if(!SSshuttle.shoppinglist.len) return + var/list/obj/miscboxes = list() //miscboxes are combo boxes that contain all goody orders grouped + var/list/misc_order_num = list() //list of strings of order numbers, so that the manifest can show all orders in a box + var/list/misc_contents = list() //list of lists of items that each box will contain + var/list/empty_turfs = list() for(var/place in shuttle_areas) var/area/shuttle/shuttle_area = place @@ -117,10 +121,13 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list( break var/price = SO.pack.cost + if(SO.applied_coupon) + price *= (1 - SO.applied_coupon.discount_pct_off) 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 + if(!SO.pack.goody) + price *= 1.1 //TODO make this customizable by the quartermaster else D = cargo_budget if(D) @@ -136,14 +143,46 @@ GLOBAL_LIST_INIT(cargo_shuttle_leave_behind_typecache, typecacheof(list( value += SO.pack.cost SSshuttle.shoppinglist -= SO SSshuttle.orderhistory += SO + QDEL_NULL(SO.applied_coupon) + + if(SO.pack.goody) //goody means it gets piled in the miscbox + if(SO.paying_account) + if(!miscboxes.len || !miscboxes[D.account_holder]) //if there's no miscbox for this person + miscboxes[D.account_holder] = new /obj/item/storage/lockbox/order(pick_n_take(empty_turfs)) + var/obj/item/storage/lockbox/order/our_box = miscboxes[D.account_holder] + our_box.buyer_account = SO.paying_account + miscboxes[D.account_holder].name = "small items case - purchased by [D.account_holder]" + misc_contents[D.account_holder] = list() + for (var/item in SO.pack.contains) + misc_contents[D.account_holder] += item + misc_order_num[D.account_holder] = "[misc_order_num[D.account_holder]]#[SO.id] " + else //No private payment, so we just stuff it all into a generic crate + if(!miscboxes.len || !miscboxes["Cargo"]) + miscboxes["Cargo"] = new /obj/structure/closet/secure_closet/goodies(pick_n_take(empty_turfs)) + miscboxes["Cargo"].name = "small items closet" + misc_contents["Cargo"] = list() + miscboxes["Cargo"].req_access = list() + for (var/item in SO.pack.contains) + misc_contents["Cargo"] += item + //new item(miscboxes["Cargo"]) + if(SO.pack.access) + miscboxes["Cargo"].req_access += SO.pack.access + misc_order_num["Cargo"] = "[misc_order_num["Cargo"]]#[SO.id] " + else + SO.generate(pick_n_take(empty_turfs)) - 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)]), 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)], paid by [D.account_holder] has shipped.") purchases++ + for(var/I in miscboxes) + var/datum/supply_order/SO = new/datum/supply_order() + SO.id = misc_order_num[I] + SO.generateCombo(miscboxes[I], I, misc_contents[I]) + qdel(SO) + 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() diff --git a/code/modules/shuttle/syndicate.dm b/code/modules/shuttle/syndicate.dm index 440e6cb03b..0076f584e9 100644 --- a/code/modules/shuttle/syndicate.dm +++ b/code/modules/shuttle/syndicate.dm @@ -1,4 +1,4 @@ -#define SYNDICATE_CHALLENGE_TIMER 12000 //20 minutes +#define SYNDICATE_CHALLENGE_TIMER 9000 // 15 minutes /obj/machinery/computer/shuttle/syndicate name = "syndicate shuttle terminal" @@ -21,8 +21,8 @@ /obj/machinery/computer/shuttle/syndicate/Topic(href, href_list) if(href_list["move"]) var/obj/item/circuitboard/computer/syndicate_shuttle/board = circuit - if(board.challenge && world.time < SYNDICATE_CHALLENGE_TIMER) - to_chat(usr, "You've issued a combat challenge to the station! You've got to give them at least [DisplayTimeText(SYNDICATE_CHALLENGE_TIMER - world.time)] more to allow them to prepare.") + if(board.challenge && ((world.time - SSticker.round_start_time) < SYNDICATE_CHALLENGE_TIMER)) + to_chat(usr, "You've issued a combat challenge to the station! You've got to give them at least [DisplayTimeText(SYNDICATE_CHALLENGE_TIMER - (world.time - SSticker.round_start_time))] more to allow them to prepare.") return 0 board.moved = TRUE ..() diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 143fe508b6..2272a14612 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -56,11 +56,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th to_chat(caller, "[caller.ranged_ability.name] has been disabled.") caller.ranged_ability.remove_ranged_ability() return TRUE //TRUE for failed, FALSE for passed. - if(ranged_clickcd_override >= 0) - ranged_ability_user.next_click = world.time + ranged_clickcd_override - else - ranged_ability_user.next_click = world.time + CLICK_CD_CLICK_ABILITY - ranged_ability_user.face_atom(A) return FALSE /obj/effect/proc_holder/proc/add_ranged_ability(mob/living/user, msg, forced) @@ -120,7 +115,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th var/list/mobs_blacklist //The opposite of the above. var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells var/phase_allowed = 0 // If true, the spell can be cast while phased, eg. blood crawling, ethereal jaunting - var/antimagic_allowed = TRUE // If false, the spell cannot be cast while under the effect of antimagic + var/antimagic_allowed = FALSE // If false, the spell cannot be cast while under the effect of antimagic var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell var/invocation_emote_self = null var/invocation_type = "none" //can be none, whisper, emote and shout @@ -229,7 +224,15 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th /obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf return -/obj/effect/proc_holder/spell/proc/can_target(mob/living/target) +/** + * can_target: Checks if we are allowed to cast the spell on a target. + * + * Arguments: + * * target The atom that is being targeted by the spell. + * * user The mob using the spell. + * * silent If the checks should not give any feedback messages. + */ +/obj/effect/proc_holder/spell/proc/can_target(atom/target, mob/user, silent = FALSE) return TRUE /obj/effect/proc_holder/spell/proc/start_recharge() @@ -301,6 +304,13 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th /obj/effect/proc_holder/spell/proc/cast(list/targets,mob/user = usr) return +/obj/effect/proc_holder/spell/proc/view_or_range(distance = world.view, center=usr, type="view") + switch(type) + if("view") + . = view(distance,center) + if("range") + . = range(distance,center) + /obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge switch(charge_type) if("recharge") @@ -350,7 +360,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th switch(max_targets) if(0) //unlimited for(var/mob/living/target in view_or_range(range, user, selection_type)) - if(!can_target(target)) + if(!can_target(target, user, TRUE)) continue targets += target if(1) //single target can be picked @@ -362,7 +372,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th for(var/mob/living/M in view_or_range(range, user, selection_type)) if(!include_user && user == M) continue - if(!can_target(M)) + if(!can_target(M, user, TRUE)) continue possible_targets += M @@ -370,7 +380,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th //Adds a safety check post-input to make sure those targets are actually in range. var/mob/M if(!random_target) - M = input("Choose the target for the spell.", "Targeting") as null|mob in possible_targets + M = input("Choose the target for the spell.", "Targeting") as null|mob in sortNames(possible_targets) else switch(random_target_priority) if(TARGET_RANDOM) @@ -390,7 +400,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th else var/list/possible_targets = list() for(var/mob/living/target in view_or_range(range, user, selection_type)) - if(!can_target(target)) + if(!can_target(target, user, TRUE)) continue possible_targets += target for(var/i=1,i<=max_targets,i++) @@ -416,7 +426,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th var/list/targets = list() for(var/turf/target in view_or_range(range,user,selection_type)) - if(!can_target(target)) + if(!can_target(target, user, TRUE)) continue if(!(target in view_or_range(inner_radius,user,selection_type))) targets += target diff --git a/code/modules/spells/spell_types/bloodcrawl.dm b/code/modules/spells/spell_types/bloodcrawl.dm index e59fc2049d..39b0f1709e 100644 --- a/code/modules/spells/spell_types/bloodcrawl.dm +++ b/code/modules/spells/spell_types/bloodcrawl.dm @@ -25,6 +25,11 @@ /obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr) if(istype(user)) + if(istype(user, /mob/living/simple_animal/slaughter)) + var/mob/living/simple_animal/slaughter/slaught = user + slaught.current_hitstreak = 0 + slaught.wound_bonus = initial(slaught.wound_bonus) + slaught.bare_wound_bonus = initial(slaught.bare_wound_bonus) if(phased) if(user.phasein(target)) phased = 0 diff --git a/code/modules/spells/spell_types/cone_spells.dm b/code/modules/spells/spell_types/cone_spells.dm new file mode 100644 index 0000000000..63bae4b7cf --- /dev/null +++ b/code/modules/spells/spell_types/cone_spells.dm @@ -0,0 +1,117 @@ +/obj/effect/proc_holder/spell/cone + name = "Cone of Nothing" + desc = "Does nothing in a cone! Wow!" + school = "evocation" + charge_max = 100 + clothes_req = FALSE + invocation = "FUKAN NOTHAN" + invocation_type = "shout" + sound = 'sound/magic/forcewall.ogg' + action_icon_state = "shield" + range = -1 + cooldown_min = 0.5 SECONDS + ///This controls how many levels the cone has, increase this value to make a bigger cone. + var/cone_levels = 3 + ///This value determines if the cone penetrates walls. + var/respect_density = FALSE + +/obj/effect/proc_holder/spell/cone/choose_targets(mob/user = usr) + perform(null, user=user) + +///This proc creates a list of turfs that are hit by the cone +/obj/effect/proc_holder/spell/cone/proc/cone_helper(var/turf/starter_turf, var/dir_to_use, var/cone_levels = 3) + var/list/turfs_to_return = list() + var/turf/turf_to_use = starter_turf + var/turf/left_turf + var/turf/right_turf + var/right_dir + var/left_dir + switch(dir_to_use) + if(NORTH) + left_dir = WEST + right_dir = EAST + if(SOUTH) + left_dir = EAST + right_dir = WEST + if(EAST) + left_dir = NORTH + right_dir = SOUTH + if(WEST) + left_dir = SOUTH + right_dir = NORTH + + + for(var/i in 1 to cone_levels) + var/list/level_turfs = list() + turf_to_use = get_step(turf_to_use, dir_to_use) + level_turfs += turf_to_use + if(i != 1) + left_turf = get_step(turf_to_use, left_dir) + level_turfs += left_turf + right_turf = get_step(turf_to_use, right_dir) + level_turfs += right_turf + for(var/left_i in 1 to i -calculate_cone_shape(i)) + if(left_turf.density && respect_density) + break + left_turf = get_step(left_turf, left_dir) + level_turfs += left_turf + for(var/right_i in 1 to i -calculate_cone_shape(i)) + if(right_turf.density && respect_density) + break + right_turf = get_step(right_turf, right_dir) + level_turfs += right_turf + turfs_to_return += list(level_turfs) + if(i == cone_levels) + continue + if(turf_to_use.density && respect_density) + break + return turfs_to_return + +/obj/effect/proc_holder/spell/cone/cast(list/targets,mob/user = usr) + var/list/cone_turfs = cone_helper(get_turf(user), user.dir, cone_levels) + for(var/list/turf_list in cone_turfs) + do_cone_effects(turf_list) + +///This proc does obj, mob and turf cone effects on all targets in a list +/obj/effect/proc_holder/spell/cone/proc/do_cone_effects(list/target_turf_list, level) + for(var/target_turf in target_turf_list) + if(!target_turf) //if turf is no longer there + continue + do_turf_cone_effect(target_turf, level) + if(isopenturf(target_turf)) + var/turf/open/open_turf = target_turf + for(var/movable_content in open_turf) + if(isobj(movable_content)) + do_obj_cone_effect(movable_content, level) + else if(isliving(movable_content)) + do_mob_cone_effect(movable_content, level) + +///This proc deterimines how the spell will affect turfs. +/obj/effect/proc_holder/spell/cone/proc/do_turf_cone_effect(turf/target_turf, level) + return + +///This proc deterimines how the spell will affect objects. +/obj/effect/proc_holder/spell/cone/proc/do_obj_cone_effect(obj/target_obj, level) + return + +///This proc deterimines how the spell will affect mobs. +/obj/effect/proc_holder/spell/cone/proc/do_mob_cone_effect(mob/living/target_mob, level) + return + +///This proc adjusts the cones width depending on the level. +/obj/effect/proc_holder/spell/cone/proc/calculate_cone_shape(current_level) + var/end_taper_start = round(cone_levels * 0.8) + if(current_level > end_taper_start) + return (current_level % end_taper_start) * 2 //someone more talented and probably come up with a better formula. + else + return 2 + +///This type of cone gradually affects each level of the cone instead of affecting the entire area at once. +/obj/effect/proc_holder/spell/cone/staggered + +/obj/effect/proc_holder/spell/cone/staggered/cast(list/targets,mob/user = usr) + var/level_counter = 0 + var/list/cone_turfs = cone_helper(get_turf(user), user.dir, cone_levels) + for(var/list/turf_list in cone_turfs) + level_counter++ + addtimer(CALLBACK(src, .proc/do_cone_effects, turf_list, level_counter), 2 * level_counter) diff --git a/code/modules/spells/spell_types/curse.dm b/code/modules/spells/spell_types/curse.dm new file mode 100644 index 0000000000..9449e4a5d0 --- /dev/null +++ b/code/modules/spells/spell_types/curse.dm @@ -0,0 +1,37 @@ +GLOBAL_VAR_INIT(curse_of_madness_triggered, FALSE) + +/proc/curse_of_madness(mob/user, message) + if(user) //in this case either someone holding a spellbook or a badmin + to_chat(user, "You sent a curse of madness with the message \"[message]\"!") + message_admins("[ADMIN_LOOKUPFLW(user)] sent a curse of madness with the message \"[message]\"!") + log_game("[key_name(user)] sent a curse of madness with the message \"[message]\"!") + + GLOB.curse_of_madness_triggered = message // So latejoiners are also afflicted. + + deadchat_broadcast("A Curse of Madness has stricken the station, shattering their minds with the awful secret: \"[message]\"") + + for(var/mob/living/carbon/human/H in GLOB.player_list) + if(H.stat == DEAD) + continue + var/turf/T = get_turf(H) + if(T && !is_station_level(T.z)) + continue + if(H.anti_magic_check(TRUE, FALSE, TRUE)) + to_chat(H, "You have a strange feeling for a moment, but then it passes.") + continue + give_madness(H, message) + +/proc/give_madness(mob/living/carbon/human/H, message) + H.playsound_local(H,'sound/magic/curse.ogg',40,1) + to_chat(H, "[message]") + to_chat(H, "Your mind shatters!") + switch(rand(1,10)) + if(1 to 3) + H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY) + H.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_LOBOTOMY) + if(4 to 6) + H.gain_trauma_type(BRAIN_TRAUMA_SEVERE, TRAUMA_RESILIENCE_LOBOTOMY) + if(7 to 8) + H.gain_trauma_type(BRAIN_TRAUMA_MAGIC, TRAUMA_RESILIENCE_LOBOTOMY) + if(9 to 10) + H.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, TRAUMA_RESILIENCE_LOBOTOMY) diff --git a/code/modules/spells/spell_types/devil.dm b/code/modules/spells/spell_types/devil.dm index 34b033fd17..3b76107905 100644 --- a/code/modules/spells/spell_types/devil.dm +++ b/code/modules/spells/spell_types/devil.dm @@ -5,7 +5,7 @@ include_user = 1 range = -1 clothes_req = NONE - item_type = /obj/item/twohanded/pitchfork/demonic + item_type = /obj/item/pitchfork/demonic school = "conjuration" charge_max = 150 @@ -15,10 +15,10 @@ action_background_icon_state = "bg_demon" /obj/effect/proc_holder/spell/targeted/conjure_item/summon_pitchfork/greater - item_type = /obj/item/twohanded/pitchfork/demonic/greater + item_type = /obj/item/pitchfork/demonic/greater /obj/effect/proc_holder/spell/targeted/conjure_item/summon_pitchfork/ascended - item_type = /obj/item/twohanded/pitchfork/demonic/ascended + item_type = /obj/item/pitchfork/demonic/ascended /obj/effect/proc_holder/spell/targeted/conjure_item/violin item_type = /obj/item/instrument/violin/golden @@ -118,14 +118,14 @@ revert_cast() return ..() else - user.notransform = TRUE + user.mob_transforming = TRUE user.fakefire() to_chat(src, "You begin to phase back into sinful flames.") if(do_mob(user,user,150)) user.infernalphaseout() else to_chat(user, "You must remain still while exiting.") - user.notransform = FALSE + user.mob_transforming = FALSE user.fakefireextinguish() start_recharge() return @@ -149,11 +149,11 @@ ExtinguishMob() forceMove(holder) holder = holder - notransform = 0 + mob_transforming = 0 fakefireextinguish() /mob/living/proc/infernalphasein() - if(notransform) + if(mob_transforming) to_chat(src, "You're too busy to jaunt in.") return FALSE fakefire() diff --git a/code/modules/spells/spell_types/dumbfire.dm b/code/modules/spells/spell_types/dumbfire.dm index 6931b4ac31..424c702a31 100644 --- a/code/modules/spells/spell_types/dumbfire.dm +++ b/code/modules/spells/spell_types/dumbfire.dm @@ -49,8 +49,8 @@ var/projectile_type = text2path(proj_type) projectile = new projectile_type(user) else if(istype(proj_type, /obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile + projectile = new /obj/effect/proc_holder/spell/pointed/trigger(user) + var/obj/effect/proc_holder/spell/pointed/trigger/T = projectile T.linked_spells += proj_type else projectile = new proj_type(user) diff --git a/code/modules/spells/spell_types/ethereal_jaunt.dm b/code/modules/spells/spell_types/ethereal_jaunt.dm index f485ae578f..9d91b6534d 100644 --- a/code/modules/spells/spell_types/ethereal_jaunt.dm +++ b/code/modules/spells/spell_types/ethereal_jaunt.dm @@ -17,19 +17,19 @@ action_icon_state = "jaunt" /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded - playsound(get_turf(user), 'sound/magic/ethereal_enter.ogg', 50, 1, -1) + play_sound("enter",user) for(var/mob/living/target in targets) INVOKE_ASYNC(src, .proc/do_jaunt, target) /obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/do_jaunt(mob/living/target) - target.notransform = 1 + target.mob_transforming = 1 var/turf/mobloc = get_turf(target) var/obj/effect/dummy/phased_mob/spell_jaunt/holder = new /obj/effect/dummy/phased_mob/spell_jaunt(mobloc) new jaunt_out_type(mobloc, target.dir) target.ExtinguishMob() target.forceMove(holder) target.reset_perspective(holder) - target.notransform=0 //mob is safely inside holder now, no need for protection. + target.mob_transforming=0 //mob is safely inside holder now, no need for protection. jaunt_steam(mobloc) sleep(jaunt_duration) @@ -42,7 +42,7 @@ ADD_TRAIT(target, TRAIT_MOBILITY_NOMOVE, src) target.update_mobility() holder.reappearing = 1 - playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 50, 1, -1) + play_sound("exit",target) sleep(25 - jaunt_in_time) new jaunt_in_type(mobloc, holder.dir) target.setDir(holder.dir) @@ -63,6 +63,13 @@ steam.set_up(10, 0, mobloc) steam.start() +/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/play_sound(type,mob/living/target) + switch(type) + if("enter") + playsound(get_turf(target), 'sound/magic/ethereal_enter.ogg', 50, TRUE, -1) + if("exit") + playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 50, TRUE, -1) + /obj/effect/dummy/phased_mob/spell_jaunt name = "water" icon = 'icons/effects/effects.dmi' @@ -102,4 +109,4 @@ return /obj/effect/dummy/phased_mob/spell_jaunt/bullet_act(blah) - return BULLET_ACT_FORCE_PIERCE \ No newline at end of file + return BULLET_ACT_FORCE_PIERCE diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm index f6f56c049a..11518b236f 100644 --- a/code/modules/spells/spell_types/lichdom.dm +++ b/code/modules/spells/spell_types/lichdom.dm @@ -132,7 +132,7 @@ lich.real_name = mind.name mind.transfer_to(lich) mind.grab_ghost(force=TRUE) - lich.hardset_dna(null,null,lich.real_name,null, new /datum/species/skeleton/space) + lich.hardset_dna(null,null,null,lich.real_name,null, new /datum/species/skeleton) to_chat(lich, "Your bones clatter and shudder as you are pulled back into this world!") var/turf/body_turf = get_turf(old_body) lich.DefaultCombatKnockdown(200 + 200*resurrections) diff --git a/code/modules/spells/spell_types/mime.dm b/code/modules/spells/spell_types/mime.dm index 8f39da5031..26a6b57b25 100644 --- a/code/modules/spells/spell_types/mime.dm +++ b/code/modules/spells/spell_types/mime.dm @@ -12,6 +12,7 @@ range = 0 cast_sound = null mobs_whitelist = list(/mob/living/carbon/human) + antimagic_allowed = TRUE action_icon_state = "mime" action_background_icon_state = "bg_mime" @@ -40,6 +41,7 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" + antimagic_allowed = TRUE /obj/effect/proc_holder/spell/targeted/mime/speak/Trigger(mob/user, skip_can_cast = TRUE) if(user.mind?.miming) @@ -76,6 +78,7 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" + antimagic_allowed = TRUE /obj/effect/proc_holder/spell/targeted/forcewall/mime/Trigger(mob/user, skip_can_cast = TRUE) if(user.mind) @@ -107,6 +110,7 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" base_icon_state = "mime" + antimagic_allowed = TRUE /obj/effect/proc_holder/spell/aimed/finger_guns/Trigger(mob/user, skip_can_cast = TRUE) @@ -137,6 +141,7 @@ action_icon_state = "mime" action_background_icon_state = "bg_mime" hand_path = /obj/item/melee/touch_attack/mimerope + antimagic_allowed = TRUE /obj/effect/proc_holder/spell/targeted/touch/mimerope/Trigger(mob/user, skip_can_cast = TRUE) if(user.mind) diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm deleted file mode 100644 index d2ef015d1d..0000000000 --- a/code/modules/spells/spell_types/mind_transfer.dm +++ /dev/null @@ -1,88 +0,0 @@ -/obj/effect/proc_holder/spell/targeted/mind_transfer - name = "Mind Transfer" - desc = "This spell allows the user to switch bodies with a target." - - school = "transmutation" - charge_max = 600 - clothes_req = NONE - invocation = "GIN'YU CAPAN" - invocation_type = "whisper" - range = 1 - cooldown_min = 200 //100 deciseconds reduction per rank - var/unconscious_amount_caster = 400 //how much the caster is stunned for after the spell - var/unconscious_amount_victim = 400 //how much the victim is stunned for after the spell - - action_icon_state = "mindswap" - -/* -Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do. -Make sure spells that are removed from spell_list are actually removed and deleted when mind transferring. -Also, you never added distance checking after target is selected. I've went ahead and did that. -*/ -/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/living/user = usr, distanceoverride, silent = FALSE) - if(!targets.len) - if(!silent) - to_chat(user, "No mind found!") - return - - if(targets.len > 1) - if(!silent) - to_chat(user, "Too many minds! You're not a hive damnit!") - return - - var/mob/living/target = targets[1] - - var/t_He = target.p_they(TRUE) - var/t_is = target.p_are() - - if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it. - if(!silent) - to_chat(user, "[t_He] [t_is] too far away!") - return - - if(ismegafauna(target)) - if(!silent) - to_chat(user, "This creature is too powerful to control!") - return - - if(target.stat == DEAD) - if(!silent) - to_chat(user, "You don't particularly want to be dead!") - return - - if(!target.key || !target.mind) - if(!silent) - to_chat(user, "[t_He] appear[target.p_s()] to be catatonic! Not even magic can affect [target.p_their()] vacant mind.") - return - - if(user.suiciding) - if(!silent) - to_chat(user, "You're killing yourself! You can't concentrate enough to do this!") - return - - var/datum/mind/TM = target.mind - if(target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev) || target.key[1] == "@") - if(!silent) - to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!") - return - - var/mob/living/victim = target//The target of the spell whos body will be transferred to. - var/mob/living/caster = user//The wizard/whomever doing the body transferring. - - //MIND TRANSFER BEGIN - var/mob/dead/observer/ghost = victim.ghostize(FALSE, TRUE) - caster.mind.transfer_to(victim) - - ghost.mind.transfer_to(caster) - if(ghost.key) - ghost.transfer_ckey(caster) //have to transfer the key since the mind was not active - qdel(ghost) - - //MIND TRANSFER END - - //Here we knock both mobs out for a time. - caster.Unconscious(unconscious_amount_caster) - victim.Unconscious(unconscious_amount_victim) - SEND_SOUND(caster, sound('sound/magic/mandswap.ogg')) - SEND_SOUND(victim, sound('sound/magic/mandswap.ogg'))// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened - return TRUE diff --git a/code/modules/spells/spell_types/barnyard.dm b/code/modules/spells/spell_types/pointed/barnyard.dm similarity index 52% rename from code/modules/spells/spell_types/barnyard.dm rename to code/modules/spells/spell_types/pointed/barnyard.dm index 4b972e8030..61e3cf7127 100644 --- a/code/modules/spells/spell_types/barnyard.dm +++ b/code/modules/spells/spell_types/pointed/barnyard.dm @@ -1,51 +1,54 @@ -/obj/effect/proc_holder/spell/targeted/barnyardcurse +/obj/effect/proc_holder/spell/pointed/barnyardcurse name = "Curse of the Barnyard" desc = "This spell dooms an unlucky soul to possess the speech and facial attributes of a barnyard animal." school = "transmutation" charge_type = "recharge" charge_max = 150 charge_counter = 0 - clothes_req = NONE - stat_allowed = 0 + clothes_req = FALSE + stat_allowed = FALSE invocation = "KN'A FTAGHU, PUCK 'BTHNK!" invocation_type = "shout" range = 7 cooldown_min = 30 - selection_type = "range" - var/list/compatible_mobs = list(/mob/living/carbon/human, /mob/living/carbon/monkey) - + ranged_mousepointer = 'icons/effects/mouse_pointers/barn_target.dmi' action_icon_state = "barn" + active_msg = "You prepare to curse a target..." + deactive_msg = "You dispel the curse..." + /// List of mobs which are allowed to be a target of the spell + var/static/list/compatible_mobs_typecache = typecacheof(list(/mob/living/carbon/human, /mob/living/carbon/monkey)) -/obj/effect/proc_holder/spell/targeted/barnyardcurse/cast(list/targets, mob/user = usr) +/obj/effect/proc_holder/spell/pointed/barnyardcurse/cast(list/targets, mob/user) if(!targets.len) - to_chat(user, "No target found in range.") - return + to_chat(user, "No target found in range!") + return FALSE + if(!can_target(targets[1], user)) + return FALSE var/mob/living/carbon/target = targets[1] - - if(!(target.type in compatible_mobs)) - to_chat(user, "You are unable to curse [target]'s head!") - return - - if(!(target in oview(range))) - to_chat(user, "[target.p_theyre(TRUE)] too far away!") - return - if(target.anti_magic_check()) to_chat(user, "The spell had no effect!") target.visible_message("[target]'s face bursts into flames, which instantly burst outward, leaving [target] unharmed!", \ - "Your face starts burning up, but the flames are repulsed by your anti-magic protection!") - return + "Your face starts burning up, but the flames are repulsed by your anti-magic protection!") + return FALSE var/list/masks = list(/obj/item/clothing/mask/pig/cursed, /obj/item/clothing/mask/cowmask/cursed, /obj/item/clothing/mask/horsehead/cursed) - var/choice = pick(masks) var/obj/item/clothing/mask/magichead = new choice(get_turf(target)) - magichead.flags_inv = null + target.visible_message("[target]'s face bursts into flames, and a barnyard animal's head takes its place!", \ "Your face burns up, and shortly after the fire you realise you have the face of a barnyard animal!") if(!target.dropItemToGround(target.wear_mask)) qdel(target.wear_mask) - target.equip_to_slot_if_possible(magichead, SLOT_WEAR_MASK, 1, 1) - + target.equip_to_slot_if_possible(magichead, ITEM_SLOT_MASK, 1, 1) target.flash_act() + +/obj/effect/proc_holder/spell/pointed/barnyardcurse/can_target(atom/target, mob/user, silent) + . = ..() + if(!.) + return FALSE + if(!is_type_in_typecache(target, compatible_mobs_typecache)) + if(!silent) + to_chat(user, "You are unable to curse [target]!") + return FALSE + return TRUE diff --git a/code/modules/spells/spell_types/pointed/blind.dm b/code/modules/spells/spell_types/pointed/blind.dm new file mode 100644 index 0000000000..a773c5ad8d --- /dev/null +++ b/code/modules/spells/spell_types/pointed/blind.dm @@ -0,0 +1,35 @@ +/obj/effect/proc_holder/spell/pointed/trigger/blind + name = "Blind" + desc = "This spell temporarily blinds a single target." + school = "transmutation" + charge_max = 300 + clothes_req = FALSE + invocation = "STI KALY" + invocation_type = "whisper" + message = "Your eyes cry out in pain!" + cooldown_min = 50 //12 deciseconds reduction per rank + starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind", "/obj/effect/proc_holder/spell/targeted/genetic/blind") + ranged_mousepointer = 'icons/effects/mouse_pointers/blind_target.dmi' + action_icon_state = "blind" + active_msg = "You prepare to blind a target..." + +/obj/effect/proc_holder/spell/targeted/inflict_handler/blind + amt_eye_blind = 10 + amt_eye_blurry = 20 + sound = 'sound/magic/blind.ogg' + +/obj/effect/proc_holder/spell/targeted/genetic/blind + mutations = list(BLINDMUT) + duration = 300 + charge_max = 400 // needs to be higher than the duration or it'll be permanent + sound = 'sound/magic/blind.ogg' + +/obj/effect/proc_holder/spell/pointed/trigger/blind/can_target(atom/target, mob/user, silent) + . = ..() + if(!.) + return FALSE + if(!isliving(target)) + if(!silent) + to_chat(user, "You can only blind living beings!") + return FALSE + return TRUE diff --git a/code/modules/spells/spell_types/pointed/mind_transfer.dm b/code/modules/spells/spell_types/pointed/mind_transfer.dm new file mode 100644 index 0000000000..28d646f6b6 --- /dev/null +++ b/code/modules/spells/spell_types/pointed/mind_transfer.dm @@ -0,0 +1,103 @@ +/obj/effect/proc_holder/spell/pointed/mind_transfer + name = "Mind Transfer" + desc = "This spell allows the user to switch bodies with a target next to him." + school = "transmutation" + charge_max = 600 + clothes_req = FALSE + invocation = "GIN'YU CAPAN" + invocation_type = "whisper" + range = 1 + cooldown_min = 200 //100 deciseconds reduction per rank + ranged_mousepointer = 'icons/effects/mouse_pointers/mindswap_target.dmi' + action_icon_state = "mindswap" + active_msg = "You prepare to swap minds with a target..." + /// For how long is the caster stunned for after the spell + var/unconscious_amount_caster = 40 SECONDS + /// For how long is the victim stunned for after the spell + var/unconscious_amount_victim = 40 SECONDS + +/obj/effect/proc_holder/spell/pointed/mind_transfer/cast(list/targets, mob/living/user, silent = FALSE) + if(!targets.len) + if(!silent) + to_chat(user, "No mind found!") + return FALSE + if(targets.len > 1) + if(!silent) + to_chat(user, "Too many minds! You're not a hive damnit!") + return FALSE + if(!can_target(targets[1], user, silent)) + return FALSE + + var/mob/living/victim = targets[1] //The target of the spell whos body will be transferred to. + var/datum/mind/VM = victim.mind + if(victim.anti_magic_check(TRUE, FALSE) || VM.has_antag_datum(/datum/antagonist/wizard) || VM.has_antag_datum(/datum/antagonist/cult) || VM.has_antag_datum(/datum/antagonist/changeling) || VM.has_antag_datum(/datum/antagonist/rev) || victim.key[1] == "@") + if(!silent) + to_chat(user, "[victim.p_their(TRUE)] mind is resisting your spell!") + return FALSE + if(istype(victim, /mob/living/simple_animal/hostile/guardian)) + var/mob/living/simple_animal/hostile/guardian/stand = victim + if(stand.summoner) + victim = stand.summoner + + //You should not be able to enter one of the most powerful side-antags as a fucking wizard. + if(istype(victim,/mob/living/simple_animal/slaughter)) + to_chat(user, "The devilish contract doesn't include the 'mind swappable' package, please try again another lifetime.") + return + + //MIND TRANSFER BEGIN + var/mob/dead/observer/ghost = victim.ghostize() + user.mind.transfer_to(victim) + + ghost.mind.transfer_to(user) + if(ghost.key) + user.key = ghost.key //have to transfer the key since the mind was not active + qdel(ghost) + //MIND TRANSFER END + + //Here we knock both mobs out for a time. + user.Unconscious(unconscious_amount_caster) + victim.Unconscious(unconscious_amount_victim) + SEND_SOUND(user, sound('sound/magic/mandswap.ogg')) + SEND_SOUND(victim, sound('sound/magic/mandswap.ogg')) // only the caster and victim hear the sounds, that way no one knows for sure if the swap happened + return TRUE + +/obj/effect/proc_holder/spell/pointed/mind_transfer/can_target(atom/target, mob/user, silent) + . = ..() + if(!.) + return FALSE + if(!isliving(target)) + if(!silent) + to_chat(user, "You can only swap minds with living beings!") + return FALSE + if(user == target) + if(!silent) + to_chat(user, "You can't swap minds with yourself!") + return FALSE + + var/mob/living/victim = target + var/t_He = victim.p_they(TRUE) + + if(ismegafauna(victim)) + if(!silent) + to_chat(user, "This creature is too powerful to control!") + return FALSE + if(victim.stat == DEAD) + if(!silent) + to_chat(user, "You don't particularly want to be dead!") + return FALSE + if(!victim.key || !victim.mind) + if(!silent) + to_chat(user, "[t_He] appear[victim.p_s()] to be catatonic! Not even magic can affect [victim.p_their()] vacant mind.") + return FALSE + if(user.suiciding) + if(!silent) + to_chat(user, "You're killing yourself! You can't concentrate enough to do this!") + return FALSE + if(istype(victim, /mob/living/simple_animal/hostile/guardian)) + var/mob/living/simple_animal/hostile/guardian/stand = victim + if(stand.summoner) + if(stand.summoner == user) + if(!silent) + to_chat(user, "Swapping minds with your own guardian would just put you back into your own head!") + return FALSE + return TRUE diff --git a/code/modules/spells/spell_types/pointed/pointed.dm b/code/modules/spells/spell_types/pointed/pointed.dm new file mode 100644 index 0000000000..7b942dee27 --- /dev/null +++ b/code/modules/spells/spell_types/pointed/pointed.dm @@ -0,0 +1,105 @@ +/obj/effect/proc_holder/spell/pointed + name = "pointed spell" + ranged_mousepointer = 'icons/effects/mouse_pointers/throw_target.dmi' + action_icon_state = "projectile" + /// Message showing to the spell owner upon deactivating pointed spell. + var/deactive_msg = "You dispel the magic..." + /// Message showing to the spell owner upon activating pointed spell. + var/active_msg = "You prepare to use the spell on a target..." + /// Variable dictating if the user is allowed to cast a spell on himself. + var/self_castable = FALSE + /// Variable dictating if the spell will use turf based aim assist + var/aim_assist = TRUE + +/obj/effect/proc_holder/spell/pointed/Trigger(mob/user, skip_can_cast = TRUE) + if(!istype(user)) + return + var/msg + if(!can_cast(user)) + msg = "You can no longer cast [name]!" + remove_ranged_ability(msg) + return + if(active) + msg = "[deactive_msg]" + remove_ranged_ability(msg) + else + msg = "[active_msg] Left-click to activate spell on a target!" + add_ranged_ability(user, msg, TRUE) + on_activation(user) + +/obj/effect/proc_holder/spell/pointed/on_lose(mob/living/user) + remove_ranged_ability() + +/obj/effect/proc_holder/spell/pointed/remove_ranged_ability(msg) + . = ..() + on_deactivation(ranged_ability_user) + +/obj/effect/proc_holder/spell/pointed/add_ranged_ability(mob/living/user, msg, forced) + . = ..() + on_activation(user) + +/** + * on_activation: What happens upon pointed spell activation. + * + * Arguments: + * * user The mob interacting owning the spell. + */ +/obj/effect/proc_holder/spell/pointed/proc/on_activation(mob/user) + return + +/** + * on_activation: What happens upon pointed spell deactivation. + * + * Arguments: + * * user The mob interacting owning the spell. + */ +/obj/effect/proc_holder/spell/pointed/proc/on_deactivation(mob/user) + return + +/obj/effect/proc_holder/spell/pointed/update_icon() + if(!action) + return + if(active) + action.button_icon_state = "[action_icon_state]1" + else + action.button_icon_state = "[action_icon_state]" + action.UpdateButtonIcon() + +/obj/effect/proc_holder/spell/pointed/InterceptClickOn(mob/living/caller, params, atom/target) + if(..()) + return TRUE + if(aim_assist && isturf(target)) + var/list/possible_targets = list() + for(var/A in target) + if(intercept_check(caller, A, TRUE)) + possible_targets += A + if(possible_targets.len == 1) + target = possible_targets[1] + if(!intercept_check(caller, target)) + return TRUE + if(!cast_check(FALSE, caller)) + return TRUE + perform(list(target), user = caller) + remove_ranged_ability() + return TRUE // Do not do any underlying actions after the spell cast + +/** + * intercept_check: Specific spell checks for InterceptClickOn() targets. + * + * Arguments: + * * user The mob using the ranged spell via intercept. + * * target The atom that is being targeted by the spell via intercept. + * * silent If the checks should produce not any feedback messages for the user. + */ +/obj/effect/proc_holder/spell/pointed/proc/intercept_check(mob/user, atom/target, silent = FALSE) + if(!self_castable && target == user) + if(!silent) + to_chat(user, "You cannot cast the spell on yourself!") + return FALSE + if(!(target in view_or_range(range, user, selection_type))) + if(!silent) + to_chat(user, "[target.p_theyre(TRUE)] too far away!") + return FALSE + if(!can_target(target, user, silent)) + return FALSE + return TRUE diff --git a/code/modules/spells/spell_types/projectile.dm b/code/modules/spells/spell_types/projectile.dm index be305520a2..3a8f48cf7c 100644 --- a/code/modules/spells/spell_types/projectile.dm +++ b/code/modules/spells/spell_types/projectile.dm @@ -37,8 +37,8 @@ var/projectile_type = text2path(proj_type) projectile = new projectile_type(user) if(istype(proj_type, /obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile + projectile = new /obj/effect/proc_holder/spell/pointed/trigger(user) + var/obj/effect/proc_holder/spell/pointed/trigger/T = projectile T.linked_spells += proj_type projectile.icon = proj_icon projectile.icon_state = proj_icon_state diff --git a/code/modules/spells/spell_types/rod_form.dm b/code/modules/spells/spell_types/rod_form.dm index 7a96d0ac55..6b974608d6 100644 --- a/code/modules/spells/spell_types/rod_form.dm +++ b/code/modules/spells/spell_types/rod_form.dm @@ -18,7 +18,7 @@ W.damage_bonus += spell_level * 20 //You do more damage when you upgrade the spell W.start_turf = start M.forceMove(W) - M.notransform = 1 + M.mob_transforming = 1 M.status_flags |= GODMODE //Wizard Version of the Immovable Rod @@ -37,7 +37,7 @@ /obj/effect/immovablerod/wizard/Destroy() if(wizard) wizard.status_flags &= ~GODMODE - wizard.notransform = 0 + wizard.mob_transforming = 0 wizard.forceMove(get_turf(src)) return ..() diff --git a/code/modules/spells/spell_types/santa.dm b/code/modules/spells/spell_types/santa.dm index 64ed925455..4f6957433b 100644 --- a/code/modules/spells/spell_types/santa.dm +++ b/code/modules/spells/spell_types/santa.dm @@ -13,3 +13,4 @@ summon_type = list("/obj/item/a_gift") summon_lifespan = 0 summon_amt = 5 + antimagic_allowed = TRUE diff --git a/code/modules/spells/spell_types/shadow_walk.dm b/code/modules/spells/spell_types/shadow_walk.dm index 83996b5bfb..1dd949caa0 100644 --- a/code/modules/spells/spell_types/shadow_walk.dm +++ b/code/modules/spells/spell_types/shadow_walk.dm @@ -12,6 +12,7 @@ action_icon = 'icons/mob/actions/actions_minor_antag.dmi' action_icon_state = "ninja_cloak" action_background_icon_state = "bg_alien" + antimagic_allowed = TRUE /obj/effect/proc_holder/spell/targeted/shadowwalk/cast(list/targets,mob/living/user = usr) var/L = user.loc diff --git a/code/modules/spells/spell_types/shapeshift.dm b/code/modules/spells/spell_types/shapeshift.dm index c6966ccee9..e513865246 100644 --- a/code/modules/spells/spell_types/shapeshift.dm +++ b/code/modules/spells/spell_types/shapeshift.dm @@ -100,12 +100,12 @@ if(stored.mind) stored.mind.transfer_to(shape) stored.forceMove(src) - stored.notransform = TRUE + stored.mob_transforming = TRUE if(source.convert_damage) var/damage_percent = (stored.maxHealth - stored.health)/stored.maxHealth; var/damapply = damage_percent * shape.maxHealth; - shape.apply_damage(damapply, source.convert_damage_type, forced = TRUE); + shape.apply_damage(damapply, source.convert_damage_type, forced = TRUE, wound_bonus=CANT_WOUND); slink = soullink(/datum/soullink/shapeshift, stored , shape) slink.source = src @@ -148,7 +148,7 @@ restoring = TRUE qdel(slink) stored.forceMove(get_turf(src)) - stored.notransform = FALSE + stored.mob_transforming = FALSE if(shape.mind) shape.mind.transfer_to(stored) if(death) @@ -158,7 +158,7 @@ var/damage_percent = (shape.maxHealth - shape.health)/shape.maxHealth; var/damapply = stored.maxHealth * damage_percent - stored.apply_damage(damapply, source.convert_damage_type, forced = TRUE) + stored.apply_damage(damapply, source.convert_damage_type, forced = TRUE, wound_bonus=CANT_WOUND) qdel(shape) qdel(src) diff --git a/code/modules/spells/spell_types/spacetime_distortion.dm b/code/modules/spells/spell_types/spacetime_distortion.dm index 3af4d3883f..5797cbf8b7 100644 --- a/code/modules/spells/spell_types/spacetime_distortion.dm +++ b/code/modules/spells/spell_types/spacetime_distortion.dm @@ -110,8 +110,7 @@ else walk_link(user) -//ATTACK HAND IGNORING PARENT RETURN VALUE -/obj/effect/cross_action/spacetime_dist/attack_hand(mob/user) +/obj/effect/cross_action/spacetime_dist/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) walk_link(user) /obj/effect/cross_action/spacetime_dist/attack_paw(mob/user) diff --git a/code/modules/spells/spell_types/taeclowndo.dm b/code/modules/spells/spell_types/taeclowndo.dm index 5b1e09565b..9d6d71a89f 100644 --- a/code/modules/spells/spell_types/taeclowndo.dm +++ b/code/modules/spells/spell_types/taeclowndo.dm @@ -10,6 +10,7 @@ cooldown_min = 30 action_icon = 'icons/obj/food/piecake.dmi' action_icon_state = "pie" + antimagic_allowed = TRUE ////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -24,6 +25,7 @@ range = 7 selection_type = "view" projectile_type = null + antimagic_allowed = TRUE active_msg = "You focus, your mind reaching to the clown dimension, ready to make a peel matrialize wherever you want!" deactive_msg = "You relax, the peel remaining right in the \"thin air\" it would appear out of." @@ -40,6 +42,8 @@ return . = ..() + if(!.) + return new /obj/item/grown/bananapeel(target) /obj/effect/proc_holder/spell/aimed/banana_peel/update_icon() @@ -62,6 +66,7 @@ charge_max = 100 clothes_req = NONE cooldown_min = 100 + antimagic_allowed = TRUE action_icon = 'icons/mecha/mecha_equipment.dmi' action_icon_state = "mecha_honker" @@ -76,6 +81,7 @@ charge_max = 450 clothes_req = NONE cooldown_min = 450 + antimagic_allowed = TRUE action_icon = 'icons/obj/food/piecake.dmi' action_icon_state = "frostypie" diff --git a/code/modules/spells/spell_types/telepathy.dm b/code/modules/spells/spell_types/telepathy.dm index 4b4f91eb18..caf9ec79c6 100644 --- a/code/modules/spells/spell_types/telepathy.dm +++ b/code/modules/spells/spell_types/telepathy.dm @@ -8,6 +8,7 @@ action_icon = 'icons/mob/actions/actions_revenant.dmi' action_icon_state = "r_transmit" action_background_icon_state = "bg_spell" + antimagic_allowed = TRUE var/notice = "notice" var/boldnotice = "boldnotice" var/magic_check = FALSE diff --git a/code/modules/spells/spell_types/trigger.dm b/code/modules/spells/spell_types/trigger.dm index 39cff63d98..df579d9243 100644 --- a/code/modules/spells/spell_types/trigger.dm +++ b/code/modules/spells/spell_types/trigger.dm @@ -1,30 +1,26 @@ -/obj/effect/proc_holder/spell/targeted/trigger +/obj/effect/proc_holder/spell/pointed/trigger name = "Trigger" desc = "This spell triggers another spell or a few." - var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks -/obj/effect/proc_holder/spell/targeted/trigger/Initialize() +/obj/effect/proc_holder/spell/pointed/trigger/Initialize() . = ..() - for(var/spell in starting_spells) var/spell_to_add = text2path(spell) new spell_to_add(src) //should result in adding to contents, needs testing -/obj/effect/proc_holder/spell/targeted/trigger/Destroy() +/obj/effect/proc_holder/spell/pointed/trigger/Destroy() for(var/spell in contents) qdel(spell) linked_spells = null starting_spells = null return ..() -/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets,mob/user = usr) +/obj/effect/proc_holder/spell/pointed/trigger/cast(list/targets,mob/user = usr) playMagSound() for(var/mob/living/target in targets) for(var/obj/effect/proc_holder/spell/spell in contents) spell.perform(list(target),0) for(var/obj/effect/proc_holder/spell/spell in linked_spells) spell.perform(list(target),0) - - return \ No newline at end of file diff --git a/code/modules/spells/spell_types/voice_of_god.dm b/code/modules/spells/spell_types/voice_of_god.dm index 495681a818..a920344adc 100644 --- a/code/modules/spells/spell_types/voice_of_god.dm +++ b/code/modules/spells/spell_types/voice_of_god.dm @@ -5,6 +5,7 @@ cooldown_min = 0 level_max = 1 clothes_req = NONE + antimagic_allowed = TRUE action_icon = 'icons/mob/actions/actions_items.dmi' action_icon_state = "voice_of_god" var/command diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index e9432e2f58..14f359ef81 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -207,40 +207,12 @@ summon_type = list(/mob/living/simple_animal/hostile/netherworld) cast_sound = 'sound/magic/summonitems_generic.ogg' -/obj/effect/proc_holder/spell/targeted/trigger/blind - name = "Blind" - desc = "This spell temporarily blinds a single person and does not require wizard garb." - - school = "transmutation" - charge_max = 300 - clothes_req = NONE - invocation = "STI KALY" - invocation_type = "whisper" - message = "Your eyes cry out in pain!" - cooldown_min = 50 //12 deciseconds reduction per rank - - starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind") - - action_icon_state = "blind" - /obj/effect/proc_holder/spell/aoe_turf/conjure/creature/cult name = "Summon Creatures (DANGEROUS)" clothes_req = SPELL_CULT_GARB charge_max = 5000 summon_amt = 2 - - -/obj/effect/proc_holder/spell/targeted/inflict_handler/blind - amt_eye_blind = 10 - amt_eye_blurry = 20 - sound = 'sound/magic/blind.ogg' - -/obj/effect/proc_holder/spell/targeted/genetic/blind - mutations = list(BLINDMUT) - duration = 300 - sound = 'sound/magic/blind.ogg' - /obj/effect/proc_holder/spell/aoe_turf/repulse name = "Repulse" desc = "This spell throws everything around the user away." @@ -306,6 +278,7 @@ sound = 'sound/magic/tail_swing.ogg' charge_max = 150 clothes_req = NONE + antimagic_allowed = TRUE range = 2 cooldown_min = 150 invocation_type = "none" @@ -370,7 +343,7 @@ if(isliving(hit_atom)) var/mob/living/M = hit_atom if(!M.anti_magic_check()) - M.electrocute_act(80, src, SHOCK_ILLUSION) + M.electrocute_act(80, src, null, SHOCK_ILLUSION) qdel(src) /obj/item/spellpacket/lightningbolt/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) diff --git a/code/modules/station_goals/bsa.dm b/code/modules/station_goals/bsa.dm index 183462a8f7..472734b74b 100644 --- a/code/modules/station_goals/bsa.dm +++ b/code/modules/station_goals/bsa.dm @@ -180,16 +180,37 @@ reload() /obj/machinery/bsa/full/proc/fire(mob/user, turf/bullseye) - var/turf/point = get_front_turf() - for(var/turf/T in getline(get_step(point,dir),get_target_turf())) - T.ex_act(EXPLODE_DEVASTATE) - point.Beam(get_target_turf(),icon_state="bsa_beam",time=50,maxdistance = world.maxx) //ZZZAP - - message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike.") - explosion(bullseye,ex_power,ex_power*2,ex_power*4) - reload() + var/turf/point = get_front_turf() + var/turf/target = get_target_turf() + var/atom/movable/blocker + for(var/T in getline(get_step(point, dir), target)) + var/turf/tile = T + if(SEND_SIGNAL(tile, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM) + blocker = tile + else + for(var/AM in tile) + var/atom/movable/stuff = AM + if(SEND_SIGNAL(stuff, COMSIG_ATOM_BSA_BEAM) & COMSIG_ATOM_BLOCKS_BSA_BEAM) + blocker = stuff + break + if(blocker) + target = tile + break + else + tile.ex_act(EXPLODE_DEVASTATE) + point.Beam(target, icon_state = "bsa_beam", time = 50, maxdistance = world.maxx) //ZZZAP + new /obj/effect/temp_visual/bsa_splash(point, dir) + + if(!blocker) + message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)].") + log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)].") + explosion(bullseye, ex_power, ex_power*2, ex_power*4) + else + message_admins("[ADMIN_LOOKUPFLW(user)] has launched an artillery strike targeting [ADMIN_VERBOSEJMP(bullseye)] but it was blocked by [blocker] at [ADMIN_VERBOSEJMP(target)].") + log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)] but it was blocked by [blocker] at [AREACOORD(target)].") + /obj/machinery/bsa/full/proc/reload() ready = FALSE use_power(power_used_per_shot) @@ -210,20 +231,23 @@ /obj/machinery/computer/bsa_control name = "bluespace artillery control" - var/obj/machinery/bsa/full/cannon - var/notice - var/target use_power = NO_POWER_USE circuit = /obj/item/circuitboard/computer/bsa_control icon = 'icons/obj/machines/particle_accelerator.dmi' icon_state = "control_boxp" + + var/obj/machinery/bsa/full/cannon + var/notice + var/target var/area_aim = FALSE //should also show areas for targeting -/obj/machinery/computer/bsa_control/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) +/obj/machinery/computer/bsa_control/ui_state(mob/user) + return GLOB.physical_state + +/obj/machinery/computer/bsa_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "bsa", name, 400, 220, master_ui, state) + ui = new(user, src, "BluespaceArtillery", name) ui.open() /obj/machinery/computer/bsa_control/ui_data() @@ -255,7 +279,7 @@ if(!GLOB.bsa_unlock) return var/list/gps_locators = list() - for(var/obj/item/gps/G in GLOB.GPS_list) //nulls on the list somehow + for(var/datum/component/gps/G in GLOB.GPS_list) //nulls on the list somehow if(G.tracking) gps_locators[G.gpstag] = G diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm index 6c21456e63..4ac3777a41 100644 --- a/code/modules/station_goals/dna_vault.dm +++ b/code/modules/station_goals/dna_vault.dm @@ -174,14 +174,13 @@ . = ..() -/obj/machinery/dna_vault/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) +/obj/machinery/dna_vault/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) roll_powers(user) - ui = new(user, src, ui_key, "dna_vault", name, 350, 400, master_ui, state) + ui = new(user, src, "DnaVault", name) ui.open() - /obj/machinery/dna_vault/proc/roll_powers(mob/user) if(user in power_lottery) return @@ -279,5 +278,5 @@ H.add_movespeed_modifier(/datum/movespeed_modifier/dna_vault_speedup) if(VAULT_QUICK) to_chat(H, "Your arms move as fast as lightning.") - H.next_move_modifier = 0.5 + H.action_cooldown_mod = 0.5 power_lottery[H] = list() diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index cf0d79c742..c8fbda8988 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -42,10 +42,10 @@ circuit = /obj/item/circuitboard/computer/sat_control var/notice -/obj/machinery/computer/sat_control/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) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/computer/sat_control/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "sat_control", name, 400, 305, master_ui, state) + ui = new(user, src, "SatelliteControl", name) ui.open() /obj/machinery/computer/sat_control/ui_act(action, params) diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm index cf3a218d80..c61ee330e6 100644 --- a/code/modules/surgery/advanced/revival.dm +++ b/code/modules/surgery/advanced/revival.dm @@ -25,12 +25,12 @@ return TRUE /datum/surgery_step/revive name = "electrically stimulate brain" - implements = list(/obj/item/twohanded/shockpaddles = 100, /obj/item/abductor/gizmo = 100, /obj/item/melee/baton = 75, /obj/item/organ/cyberimp/arm/baton = 75, /obj/item/organ/cyberimp/arm/gun/taser = 60, /obj/item/gun/energy/e_gun/advtaser = 60, /obj/item/gun/energy/taser = 60) + implements = list(/obj/item/shockpaddles = 100, /obj/item/abductor/gizmo = 100, /obj/item/melee/baton = 75, /obj/item/organ/cyberimp/arm/baton = 75, /obj/item/organ/cyberimp/arm/gun/taser = 60, /obj/item/gun/energy/e_gun/advtaser = 60, /obj/item/gun/energy/taser = 60) time = 120 /datum/surgery_step/revive/tool_check(mob/user, obj/item/tool) . = TRUE - if(istype(tool, /obj/item/twohanded/shockpaddles)) - var/obj/item/twohanded/shockpaddles/S = tool + if(istype(tool, /obj/item/shockpaddles)) + var/obj/item/shockpaddles/S = tool if((S.req_defib && !S.defib.powered) || !S.wielded || S.cooldown || S.busy) to_chat(user, "You need to wield both paddles, and [S.defib] must be powered!") return FALSE @@ -60,6 +60,7 @@ playsound(get_turf(target), 'sound/magic/lightningbolt.ogg', 50, 1) target.adjustOxyLoss(-50, 0) target.updatehealth() + var/tplus = world.time - target.timeofdeath if(target.revive()) user.visible_message("...[target] wakes up, alive and aware!", "IT'S ALIVE!") target.visible_message("...[target] wakes up, alive and aware!") @@ -68,6 +69,13 @@ for(var/obj/item/organ/O in target.internal_organs)//zap those buggers back to life! if(O.organ_flags & ORGAN_FAILING) O.applyOrganDamage(-5) + var/list/policies = CONFIG_GET(keyed_list/policyconfig) + var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) + var/late = timelimit && (tplus > timelimit) + var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT] + if(policy) + to_chat(target, policy) + target.log_message("revived using surgical revival, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME) return TRUE else user.visible_message("...[target.p_they()] convulses, then lies still.") diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index 5c77532188..e00ff66ee7 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -6,7 +6,7 @@ requires_bodypart_type = 0 /datum/surgery_step/sever_limb name = "sever limb" - implements = list(TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/transforming/energy/sword/cyborg/saw = 100, /obj/item/melee/arm_blade = 80, /obj/item/twohanded/required/chainsaw = 80, /obj/item/mounted_chainsaw = 80, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25) + implements = list(TOOL_SCALPEL = 100, TOOL_SAW = 100, /obj/item/melee/transforming/energy/sword/cyborg/saw = 100, /obj/item/melee/arm_blade = 80, /obj/item/chainsaw = 80, /obj/item/mounted_chainsaw = 80, /obj/item/fireaxe = 50, /obj/item/hatchet = 40, /obj/item/kitchen/knife/butcher = 25) time = 64 /datum/surgery_step/sever_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm similarity index 52% rename from code/modules/surgery/bodyparts/bodyparts.dm rename to code/modules/surgery/bodyparts/_bodyparts.dm index b8b0afa2a2..2bd02160ef 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -73,6 +73,28 @@ var/render_like_organic = FALSE // forces limb to render as if it were an organic limb + /// The wounds currently afflicting this body part + var/list/wounds + + /// The scars currently afflicting this body part + var/list/scars + /// Our current stored wound damage multiplier + var/wound_damage_multiplier = 1 + + /// This number is subtracted from all wound rolls on this bodypart, higher numbers mean more defense, negative means easier to wound + var/wound_resistance = 0 + /// When this bodypart hits max damage, this number is added to all wound rolls. Obviously only relevant for bodyparts that have damage caps. + var/disabled_wound_penalty = 15 + + /// A hat won't cover your face, but a shirt covering your chest will cover your... you know, chest + var/scars_covered_by_clothes = TRUE + /// So we know if we need to scream if this limb hits max damage + var/last_maxed + /// How much generic bleedstacks we have on this bodypart + var/generic_bleedstacks + /// If we have a gauze wrapping currently applied (not including splints) + var/obj/item/stack/current_gauze + /obj/item/bodypart/examine(mob/user) . = ..() if(brute_dam > DAMAGE_PRECISION) @@ -131,8 +153,20 @@ var/turf/T = get_turf(src) if(status != BODYPART_ROBOTIC) playsound(T, 'sound/misc/splort.ogg', 50, 1, -1) - for(var/obj/item/I in src) - I.forceMove(T) + if(current_gauze) + QDEL_NULL(current_gauze) + for(var/obj/item/organ/drop_organ in get_organs()) + drop_organ.transfer_to_limb(src, owner) + +///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have +/obj/item/bodypart/proc/get_organs() + if(!owner) + return + . = list() + for(var/i in owner.internal_organs) //internal organs inside the dismembered limb are dropped. + var/obj/item/organ/organ_check = i + if(check_zone(organ_check.zone) == body_zone) + . += organ_check /obj/item/bodypart/proc/consider_processing() if(stamina_dam > DAMAGE_PRECISION) @@ -151,7 +185,7 @@ //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. //Damage will not exceed max_damage using this proc //Cannot apply negative damage -/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE) +/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm if(owner && (owner.status_flags & GODMODE)) return FALSE //godmode var/dmg_mlt = CONFIG_GET(number/damage_multiplier) @@ -165,20 +199,82 @@ if(!brute && !burn && !stamina) return FALSE + brute *= wound_damage_multiplier + burn *= wound_damage_multiplier + switch(animal_origin) if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around burn *= 1.2 + /* + // START WOUND HANDLING + */ + + // what kind of wounds we're gonna roll for, take the greater between brute and burn, then if it's brute, we subdivide based on sharpness + var/wounding_type = (brute > burn ? WOUND_BLUNT : WOUND_BURN) + var/wounding_dmg = max(brute, burn) + var/mangled_state = get_mangled_state() + var/bio_state = owner.get_biological_state() + var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%) + + if(wounding_type == WOUND_BLUNT) + if(sharpness == SHARP_EDGED) + wounding_type = WOUND_SLASH + else if(sharpness == SHARP_POINTY) + wounding_type = WOUND_PIERCE + + //Handling for bone only/flesh only(none right now)/flesh and bone targets + switch(bio_state) + // if we're bone only, all cutting attacks go straight to the bone + if(BIO_JUST_BONE) + if(wounding_type == WOUND_SLASH) + wounding_type = WOUND_BLUNT + wounding_dmg *= (easy_dismember ? 1 : 0.5) + else if(wounding_type == WOUND_PIERCE) + wounding_type = WOUND_BLUNT + wounding_dmg *= (easy_dismember ? 1 : 0.75) + if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) + return + // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday) + // standard humanoids + if(BIO_FLESH_BONE) + // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate + // So a big sharp weapon is still all you need to destroy a limb + if(mangled_state == BODYPART_MANGLED_FLESH && sharpness) + playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) + if(wounding_type == WOUND_SLASH && !easy_dismember) + wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area + if(wounding_type == WOUND_PIERCE && !easy_dismember) + wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated + wounding_type = WOUND_BLUNT + else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) + return + + // now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage + if(owner && wounding_dmg >= WOUND_MINIMUM_DAMAGE && wound_bonus != CANT_WOUND) + check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus) + + for(var/i in wounds) + var/datum/wound/iter_wound = i + iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus) + + /* + // END WOUND HANDLING + */ + + //back to our regularly scheduled program, we now actually apply damage if there's room below limb damage cap + var/can_inflict = max_damage - get_damage() - if(can_inflict <= 0) - return FALSE var/total_damage = brute + burn - if(total_damage > can_inflict) + if(total_damage > can_inflict && total_damage > 0) // TODO: the second part of this check should be removed once disabling is all done brute = round(brute * (max_damage / total_damage),DAMAGE_PRECISION) burn = round(burn * (max_damage / total_damage),DAMAGE_PRECISION) + if(can_inflict <= 0) + return FALSE + brute_dam += brute burn_dam += burn @@ -198,6 +294,165 @@ update_disabled() return update_bodypart_damage_state() +/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds +/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=SHARP_NONE) + if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND) + return + + var/mangled_state = get_mangled_state() + var/bio_state = owner.get_biological_state() + var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%) + + if(wounding_type == WOUND_BLUNT) + if(sharpness == SHARP_EDGED) + wounding_type = WOUND_SLASH + else if(sharpness == SHARP_POINTY) + wounding_type = WOUND_PIERCE + + //Handling for bone only/flesh only(none right now)/flesh and bone targets + switch(bio_state) + // if we're bone only, all cutting attacks go straight to the bone + if(BIO_JUST_BONE) + if(wounding_type == WOUND_SLASH) + wounding_type = WOUND_BLUNT + phantom_wounding_dmg *= (easy_dismember ? 1 : 0.5) + else if(wounding_type == WOUND_PIERCE) + wounding_type = WOUND_BLUNT + phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75) + if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) + return + // note that there's no handling for BIO_JUST_FLESH since we don't have any that are that right now (slimepeople maybe someday) + // standard humanoids + if(BIO_FLESH_BONE) + // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate + // So a big sharp weapon is still all you need to destroy a limb + if(mangled_state == BODYPART_MANGLED_FLESH && sharpness) + playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) + if(wounding_type == WOUND_SLASH && !easy_dismember) + phantom_wounding_dmg *= 0.5 // edged weapons pass along 50% of their wounding damage to the bone since the power is spread out over a larger area + if(wounding_type == WOUND_PIERCE && !easy_dismember) + phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated + wounding_type = WOUND_BLUNT + else if(mangled_state == BODYPART_MANGLED_BOTH && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) + return + + check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus) + +/** + * check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria + * + * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_wounding_mods], then go down the list from most severe to least severe wounds in that category. + * We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades + * + * Arguments: + * * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type. + * * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT) + * * wound_bonus- The wound_bonus of an attack + * * bare_wound_bonus- The bare_wound_bonus of an attack + */ +/obj/item/bodypart/proc/check_wounding(woundtype, damage, wound_bonus, bare_wound_bonus) + // actually roll wounds if applicable + if(HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE)) + damage *= 1.5 + else + damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE) + + var/base_roll = rand(max(damage/1.5,25), round(damage ** WOUND_DAMAGE_EXPONENT)) + var/injury_roll = base_roll + injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus) + var/list/wounds_checking = GLOB.global_wound_types[woundtype] + + // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow + if(ishuman(owner)) + var/mob/living/carbon/human/human_wearer = owner + var/list/clothing = human_wearer.clothingonpart(src) + for(var/i in clothing) + var/obj/item/clothing/clothes_check = i + // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary + if(clothes_check.armor.getRating("wound")) + bare_wound_bonus = 0 + break + + //cycle through the wounds of the relevant category from the most severe down + for(var/PW in wounds_checking) + var/datum/wound/possible_wound = PW + var/datum/wound/replaced_wound + for(var/i in wounds) + var/datum/wound/existing_wound = i + if(existing_wound.type in wounds_checking) + if(existing_wound.severity >= initial(possible_wound.severity)) + return + else + replaced_wound = existing_wound + + if(initial(possible_wound.threshold_minimum) < injury_roll) + var/datum/wound/new_wound + if(replaced_wound) + new_wound = replaced_wound.replace_wound(possible_wound) + log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned + else + new_wound = new possible_wound + new_wound.apply_wound(src) + log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) + return new_wound + +// try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart +/obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE) + var/datum/wound/potential_wound = specific_woundtype + for(var/i in wounds) + var/datum/wound/existing_wound = i + if(existing_wound.wound_type == initial(potential_wound.wound_type)) + if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force + existing_wound.replace_wound(potential_wound, smited) + return + + var/datum/wound/new_wound = new potential_wound + new_wound.apply_wound(src, smited = smited) + +/** + * check_wounding_mods() is where we handle the various modifiers of a wound roll + * + * A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus + * We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse + * Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled + * + * Arguments: + * * It's the same ones on [receive_damage] + */ +/obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus) + var/armor_ablation = 0 + var/injury_mod = 0 + + if(owner && ishuman(owner)) + var/mob/living/carbon/human/H = owner + var/list/clothing = H.clothingonpart(src) + for(var/c in clothing) + var/obj/item/clothing/C = c + // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary + armor_ablation += C.armor.getRating("wound") + if(wounding_type == WOUND_SLASH) + C.take_damage_zone(body_zone, damage, BRUTE, armour_penetration) + else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage() + C.take_damage_zone(body_zone, damage, BURN, armour_penetration) + + if(!armor_ablation) + injury_mod += bare_wound_bonus + + injury_mod -= armor_ablation + injury_mod += wound_bonus + + for(var/thing in wounds) + var/datum/wound/W = thing + injury_mod += W.threshold_penalty + + var/part_mod = -wound_resistance + if(get_damage(TRUE) >= max_damage) + part_mod += disabled_wound_penalty + + injury_mod += part_mod + + return injury_mod + //Heals brute and burn damage for the organ. Returns 1 if the damage-icon states changed at all. //Damage cannot go below zero. //Cannot remove negative damage (i.e. apply damage) @@ -229,16 +484,29 @@ //Checks disabled status thresholds /obj/item/bodypart/proc/update_disabled() + if(!owner) + return set_disabled(is_disabled()) /obj/item/bodypart/proc/is_disabled() + if(!owner) + return if(HAS_TRAIT(owner, TRAIT_PARALYSIS)) return BODYPART_DISABLED_PARALYSIS + for(var/i in wounds) + var/datum/wound/W = i + if(W.disabling) + return BODYPART_DISABLED_WOUND if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER)) . = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled - if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0% - return BODYPART_DISABLED_DAMAGE - if(disabled && (get_damage(TRUE) <= (max_damage * 0.5))) + if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0% + if(!last_maxed) + owner.emote("scream") + last_maxed = TRUE + if(!is_organic_limb() || stamina_dam >= max_damage) + return BODYPART_DISABLED_DAMAGE + else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update + last_maxed = FALSE return BODYPART_NOT_DISABLED else return BODYPART_NOT_DISABLED @@ -253,9 +521,11 @@ /obj/item/bodypart/proc/set_disabled(new_disabled) - if(disabled == new_disabled) + if(disabled == new_disabled || !owner) return FALSE disabled = new_disabled + if(disabled && owner.get_item_for_held_index(held_index)) + owner.dropItemToGround(owner.get_item_for_held_index(held_index)) owner.update_health_hud() //update the healthdoll owner.update_body() owner.update_mobility() @@ -330,22 +600,21 @@ var/datum/species/S = H.dna.species base_bp_icon = S?.icon_limbs || DEFAULT_BODYPART_ICON - species_id = S.limbs_id + species_id = S.mutant_bodyparts["limbs_id"] species_flags_list = H.dna.species.species_traits //body marking memes var/list/colorlist = list() colorlist.Cut() - colorlist += ReadRGB("[H.dna.features["mcolor"]]0") - colorlist += ReadRGB("[H.dna.features["mcolor2"]]0") - colorlist += ReadRGB("[H.dna.features["mcolor3"]]0") + colorlist += ReadRGB("[H.dna.features["mcolor"]]00") + colorlist += ReadRGB("[H.dna.features["mcolor2"]]00") + colorlist += ReadRGB("[H.dna.features["mcolor3"]]00") colorlist += list(0,0,0, S.hair_alpha) for(var/index=1, index<=colorlist.len, index++) colorlist[index] = colorlist[index]/255 if(S.use_skintones) skin_tone = H.skin_tone - base_bp_icon = (base_bp_icon == DEFAULT_BODYPART_ICON) ? DEFAULT_BODYPART_ICON_ORGANIC : base_bp_icon else skin_tone = "" @@ -358,13 +627,9 @@ species_color = S.fixed_mut_color else species_color = H.dna.features["mcolor"] - base_bp_icon = (base_bp_icon == DEFAULT_BODYPART_ICON) ? DEFAULT_BODYPART_ICON_ORGANIC : base_bp_icon else species_color = "" - if(base_bp_icon != DEFAULT_BODYPART_ICON) - color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE) - if(S.mutant_bodyparts["legs"]) if(body_zone == BODY_ZONE_L_LEG || body_zone == BODY_ZONE_R_LEG) if(DIGITIGRADE in S.species_traits) @@ -384,11 +649,16 @@ body_markings = "plain" aux_marking = "plain" markings_color = list(colorlist) - else body_markings = null aux_marking = null + if(species_id in GLOB.greyscale_limb_types) //should they have greyscales? + base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC + + if(base_bp_icon != DEFAULT_BODYPART_ICON) + color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE) + if(!dropping_limb && H.dna.check_mutation(HULK)) mutation_color = "00aa00" else @@ -584,293 +854,86 @@ drop_organs() qdel(src) -/obj/item/bodypart/chest - name = BODY_ZONE_CHEST - desc = "It's impolite to stare at a person's chest." - icon_state = "default_human_chest" - max_damage = 200 - body_zone = BODY_ZONE_CHEST - body_part = CHEST - px_x = 0 - px_y = 0 - stam_damage_coeff = 1 - max_stamina_damage = 200 - var/obj/item/cavity_item - -/obj/item/bodypart/chest/can_dismember(obj/item/I) - if(!((owner.stat == DEAD) || owner.InFullCritical())) - return FALSE - return ..() - -/obj/item/bodypart/chest/Destroy() - if(cavity_item) - qdel(cavity_item) - return ..() - -/obj/item/bodypart/chest/drop_organs(mob/user) - if(cavity_item) - cavity_item.forceMove(user.loc) - cavity_item = null - ..() - -/obj/item/bodypart/chest/monkey - icon = 'icons/mob/animal_parts.dmi' - icon_state = "default_monkey_chest" - animal_origin = MONKEY_BODYPART - -/obj/item/bodypart/chest/alien - icon = 'icons/mob/animal_parts.dmi' - icon_state = "alien_chest" - dismemberable = 0 - max_damage = 500 - animal_origin = ALIEN_BODYPART - -/obj/item/bodypart/chest/devil - dismemberable = 0 - max_damage = 5000 - animal_origin = DEVIL_BODYPART - -/obj/item/bodypart/chest/larva - icon = 'icons/mob/animal_parts.dmi' - icon_state = "larva_chest" - dismemberable = 0 - max_damage = 50 - animal_origin = LARVA_BODYPART - -/obj/item/bodypart/l_arm - name = "left arm" - desc = "Did you know that the word 'sinister' stems originally from the \ - Latin 'sinestra' (left hand), because the left hand was supposed to \ - be possessed by the devil? This arm appears to be possessed by no \ - one though." - icon_state = "default_human_l_arm" - attack_verb = list("slapped", "punched") - max_damage = 50 - max_stamina_damage = 50 - body_zone = BODY_ZONE_L_ARM - body_part = ARM_LEFT - aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER) - body_damage_coeff = 0.75 - held_index = 1 - px_x = -6 - px_y = 0 - stam_heal_tick = 4 - -/obj/item/bodypart/l_arm/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) - return BODYPART_DISABLED_PARALYSIS - return ..() - -/obj/item/bodypart/l_arm/set_disabled(new_disabled) - . = ..() - if(!.) +/// Get whatever wound of the given type is currently attached to this limb, if any +/obj/item/bodypart/proc/get_wound_type(checking_type) + if(isnull(wounds)) return - if(owner.stat < UNCONSCIOUS) - switch(disabled) - if(BODYPART_DISABLED_DAMAGE) - owner.emote("scream") - to_chat(owner, "Your [name] is too damaged to function!") - if(BODYPART_DISABLED_PARALYSIS) - to_chat(owner, "You can't feel your [name]!") - if(held_index) - owner.dropItemToGround(owner.get_item_for_held_index(held_index)) - if(owner.hud_used) - var/obj/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"] - if(L) - L.update_icon() + for(var/i in wounds) + if(istype(i, checking_type)) + return i -/obj/item/bodypart/l_arm/monkey - icon = 'icons/mob/animal_parts.dmi' - icon_state = "default_monkey_l_arm" - animal_origin = MONKEY_BODYPART - px_x = -5 - px_y = -3 +/** + * update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status + * + * Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging + * + * Arguments: + * * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet + */ +/obj/item/bodypart/proc/update_wounds(replaced = FALSE) + var/dam_mul = 1 //initial(wound_damage_multiplier) + // we can only have one wound per type, but remember there's multiple types + // we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb) + for(var/i in wounds) + var/datum/wound/iter_wound = i + dam_mul *= iter_wound.damage_mulitplier_penalty -/obj/item/bodypart/l_arm/alien - icon = 'icons/mob/animal_parts.dmi' - icon_state = "alien_l_arm" - px_x = 0 - px_y = 0 - dismemberable = 0 - max_damage = 100 - animal_origin = ALIEN_BODYPART + if(!LAZYLEN(wounds) && current_gauze && !replaced) + owner.visible_message("\The [current_gauze] on [owner]'s [name] fall away.", "The [current_gauze] on your [name] fall away.") + QDEL_NULL(current_gauze) + wound_damage_multiplier = dam_mul + update_disabled() -/obj/item/bodypart/l_arm/devil - dismemberable = 0 - max_damage = 5000 - animal_origin = DEVIL_BODYPART - -/obj/item/bodypart/r_arm - name = "right arm" - desc = "Over 87% of humans are right handed. That figure is much lower \ - among humans missing their right arm." - icon_state = "default_human_r_arm" - attack_verb = list("slapped", "punched") - max_damage = 50 - body_zone = BODY_ZONE_R_ARM - body_part = ARM_RIGHT - aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER) - body_damage_coeff = 0.75 - held_index = 2 - px_x = 6 - px_y = 0 - stam_heal_tick = 4 - max_stamina_damage = 50 - -/obj/item/bodypart/r_arm/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) - return BODYPART_DISABLED_PARALYSIS - return ..() - -/obj/item/bodypart/r_arm/set_disabled(new_disabled) - . = ..() - if(!.) +/obj/item/bodypart/proc/get_bleed_rate() + if(status != BODYPART_ORGANIC) // maybe in the future we can bleed oil from aug parts, but not now return - if(owner.stat < UNCONSCIOUS) - switch(disabled) - if(BODYPART_DISABLED_DAMAGE) - owner.emote("scream") - to_chat(owner, "Your [name] is too damaged to function!") - if(BODYPART_DISABLED_PARALYSIS) - to_chat(owner, "You can't feel your [name]!") - if(held_index) - owner.dropItemToGround(owner.get_item_for_held_index(held_index)) - if(owner.hud_used) - var/obj/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"] - if(R) - R.update_icon() + var/bleed_rate = 0 + if(generic_bleedstacks > 0) + bleed_rate++ + //We want an accurate reading of .len + listclearnulls(embedded_objects) + for(var/obj/item/embeddies in embedded_objects) + if(!embeddies.isEmbedHarmless()) + bleed_rate += 0.5 -/obj/item/bodypart/r_arm/monkey - icon = 'icons/mob/animal_parts.dmi' - icon_state = "default_monkey_r_arm" - animal_origin = MONKEY_BODYPART - px_x = 5 - px_y = -3 + for(var/thing in wounds) + var/datum/wound/W = thing + bleed_rate += W.blood_flow + if(owner.mobility_flags & ~MOBILITY_STAND) + bleed_rate *= 0.75 + return bleed_rate -/obj/item/bodypart/r_arm/alien - icon = 'icons/mob/animal_parts.dmi' - icon_state = "alien_r_arm" - px_x = 0 - px_y = 0 - dismemberable = 0 - max_damage = 100 - animal_origin = ALIEN_BODYPART - -/obj/item/bodypart/r_arm/devil - dismemberable = 0 - max_damage = 5000 - animal_origin = DEVIL_BODYPART - -/obj/item/bodypart/l_leg - name = "left leg" - desc = "Some athletes prefer to tie their left shoelaces first for good \ - luck. In this instance, it probably would not have helped." - icon_state = "default_human_l_leg" - attack_verb = list("kicked", "stomped") - max_damage = 50 - body_zone = BODY_ZONE_L_LEG - body_part = LEG_LEFT - body_damage_coeff = 0.75 - px_x = -2 - px_y = 12 - stam_heal_tick = 4 - max_stamina_damage = 50 - -/obj/item/bodypart/l_leg/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) - return BODYPART_DISABLED_PARALYSIS - return ..() - -/obj/item/bodypart/l_leg/set_disabled(new_disabled) - . = ..() - if(!. || owner.stat >= UNCONSCIOUS) +/** + * apply_gauze() is used to- well, apply gauze to a bodypart + * + * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons). + * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze + * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared, + * the gauze falls off. + * + * Arguments: + * * gauze- Just the gauze stack we're taking a sheet from to apply here + */ +/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze) + if(!istype(gauze) || !gauze.absorption_capacity) return - switch(disabled) - if(BODYPART_DISABLED_DAMAGE) - owner.emote("scream") - to_chat(owner, "Your [name] is too damaged to function!") - if(BODYPART_DISABLED_PARALYSIS) - to_chat(owner, "You can't feel your [name]!") + QDEL_NULL(current_gauze) + current_gauze = new gauze.type(src, 1) + gauze.use(1) - -/obj/item/bodypart/l_leg/digitigrade - name = "left digitigrade leg" - use_digitigrade = FULL_DIGITIGRADE - -/obj/item/bodypart/l_leg/monkey - icon = 'icons/mob/animal_parts.dmi' - icon_state = "default_monkey_l_leg" - animal_origin = MONKEY_BODYPART - px_y = 4 - -/obj/item/bodypart/l_leg/alien - icon = 'icons/mob/animal_parts.dmi' - icon_state = "alien_l_leg" - px_x = 0 - px_y = 0 - dismemberable = 0 - max_damage = 100 - animal_origin = ALIEN_BODYPART - -/obj/item/bodypart/l_leg/devil - dismemberable = 0 - max_damage = 5000 - animal_origin = DEVIL_BODYPART - -/obj/item/bodypart/r_leg - name = "right leg" - desc = "You put your right leg in, your right leg out. In, out, in, out, \ - shake it all about. And apparently then it detaches.\n\ - The hokey pokey has certainly changed a lot since space colonisation." - // alternative spellings of 'pokey' are availible - icon_state = "default_human_r_leg" - attack_verb = list("kicked", "stomped") - max_damage = 50 - body_zone = BODY_ZONE_R_LEG - body_part = LEG_RIGHT - body_damage_coeff = 0.75 - px_x = 2 - px_y = 12 - max_stamina_damage = 50 - stam_heal_tick = 4 - -/obj/item/bodypart/r_leg/is_disabled() - if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) - return BODYPART_DISABLED_PARALYSIS - return ..() - -/obj/item/bodypart/r_leg/set_disabled(new_disabled) - . = ..() - if(!. || owner.stat >= UNCONSCIOUS) +/** + * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity. + * + * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandages fall off and we're left with nothing. + * + * Arguments: + * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?) + */ +/obj/item/bodypart/proc/seep_gauze(seep_amt = 0) + if(!current_gauze) return - switch(disabled) - if(BODYPART_DISABLED_DAMAGE) - owner.emote("scream") - to_chat(owner, "Your [name] is too damaged to function!") - if(BODYPART_DISABLED_PARALYSIS) - to_chat(owner, "You can't feel your [name]!") - -/obj/item/bodypart/r_leg/digitigrade - name = "right digitigrade leg" - use_digitigrade = FULL_DIGITIGRADE - -/obj/item/bodypart/r_leg/monkey - icon = 'icons/mob/animal_parts.dmi' - icon_state = "default_monkey_r_leg" - animal_origin = MONKEY_BODYPART - px_y = 4 - -/obj/item/bodypart/r_leg/alien - icon = 'icons/mob/animal_parts.dmi' - icon_state = "alien_r_leg" - px_x = 0 - px_y = 0 - dismemberable = 0 - max_damage = 100 - animal_origin = ALIEN_BODYPART - -/obj/item/bodypart/r_leg/devil - dismemberable = 0 - max_damage = 5000 - animal_origin = DEVIL_BODYPART + current_gauze.absorption_capacity -= seep_amt + if(current_gauze.absorption_capacity < 0) + owner.visible_message("\The [current_gauze] on [owner]'s [name] fall away in rags.", "\The [current_gauze] on your [name] fall away in rags.", vision_distance=COMBAT_MESSAGE_RANGE) + QDEL_NULL(current_gauze) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index f654270df7..fa003e3f3c 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -4,7 +4,7 @@ return TRUE //Dismember a limb -/obj/item/bodypart/proc/dismember(dam_type = BRUTE) +/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE) if(!owner) return FALSE var/mob/living/carbon/C = owner @@ -15,8 +15,9 @@ 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!") + affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50), wound_bonus=CANT_WOUND) //Damage the chest based on limb's existing damage + if(!silent) + C.visible_message("[C]'s [name] is violently dismembered!") C.emote("scream") SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered) drop_limb() @@ -30,6 +31,7 @@ burn() return TRUE add_mob_blood(C) + C.bleed(rand(20, 40)) var/direction = pick(GLOB.cardinals) var/t_range = rand(2,max(throw_range/2, 2)) var/turf/target_turf = get_turf(src) @@ -80,14 +82,13 @@ if(organ_spilled) C.visible_message("[C]'s internal organs spill out onto the floor!") - - //limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in. -/obj/item/bodypart/proc/drop_limb(special) +/obj/item/bodypart/proc/drop_limb(special, dismembered) if(!owner) return var/atom/Tsec = owner.drop_location() var/mob/living/carbon/C = owner + SEND_SIGNAL(C, COMSIG_CARBON_REMOVE_LIMB, src, dismembered) update_limb(1) C.bodyparts -= src @@ -95,6 +96,15 @@ C.dropItemToGround(owner.get_item_for_held_index(held_index), 1) C.hand_bodyparts[held_index] = null + for(var/thing in scars) + var/datum/scar/S = thing + S.victim = null + LAZYREMOVE(owner.all_scars, S) + + for(var/thing in wounds) + var/datum/wound/W = thing + W.remove_wound(TRUE) + owner = null for(var/X in C.surgeries) //if we had an ongoing surgery on that limb, we stop it. @@ -143,7 +153,52 @@ forceMove(Tsec) +/** + * get_mangled_state() is relevant for flesh and bone bodyparts, and returns whether this bodypart has mangled skin, mangled bone, or both (or neither i guess) + * + * Dismemberment for flesh and bone requires the victim to have the skin on their bodypart destroyed (either a critical cut or piercing wound), and at least a hairline fracture + * (severe bone), at which point we can start rolling for dismembering. The attack must also deal at least 10 damage, and must be a brute attack of some kind (sorry for now, cakehat, maybe later) + * + * Returns: BODYPART_MANGLED_NONE if we're fine, BODYPART_MANGLED_FLESH if our skin is broken, BODYPART_MANGLED_BONE if our bone is broken, or BODYPART_MANGLED_BOTH if both are broken and we're up for dismembering + */ +/obj/item/bodypart/proc/get_mangled_state() + . = BODYPART_MANGLED_NONE + for(var/i in wounds) + var/datum/wound/iter_wound = i + if((iter_wound.wound_flags & MANGLES_BONE)) + . |= BODYPART_MANGLED_BONE + if((iter_wound.wound_flags & MANGLES_FLESH)) + . |= BODYPART_MANGLED_FLESH + +/** + * try_dismember() is used, once we've confirmed that a flesh and bone bodypart has both the skin and bone mangled, to actually roll for it + * + * Mangling is described in the above proc, [/obj/item/bodypart/proc/get_mangled_state()]. This simply makes the roll for whether we actually dismember or not + * using how damaged the limb already is, and how much damage this blow was for. If we have a critical bone wound instead of just a severe, we add +10% to the roll. + * Lastly, we choose which kind of dismember we want based on the wounding type we hit with. Note we don't care about all the normal mods or armor for this + * + * Arguments: + * * wounding_type: Either WOUND_BLUNT, WOUND_SLASH, or WOUND_PIERCE, basically only matters for the dismember message + * * wounding_dmg: The damage of the strike that prompted this roll, higher damage = higher chance + * * wound_bonus: Not actually used right now, but maybe someday + * * bare_wound_bonus: ditto above + */ +/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus) + if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE) + return + + var/base_chance = wounding_dmg + (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart + if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 10% more + base_chance += 10 + + if(!prob(base_chance)) + return + + var/datum/wound/loss/dismembering = new + dismembering.apply_dismember(src, wounding_type) + + return TRUE //when a limb is dropped, the internal organs are removed from the mob and put into the limb /obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C) @@ -298,6 +353,15 @@ for(var/obj/item/organ/O in contents) O.Insert(C) + for(var/thing in scars) + var/datum/scar/S = thing + S.victim = C + LAZYADD(C.all_scars, thing) + + for(var/i in wounds) + var/datum/wound/W = i + W.apply_wound(src, TRUE) + update_bodypart_damage_state() update_disabled() @@ -359,7 +423,7 @@ /mob/living/carbon/regenerate_limb(limb_zone, noheal) var/obj/item/bodypart/L if(get_bodypart(limb_zone)) - return 0 + return FALSE L = newBodyPart(limb_zone, 0, 0) if(L) if(!noheal) @@ -367,6 +431,8 @@ L.burn_dam = 0 L.brutestate = 0 L.burnstate = 0 - + var/datum/scar/scaries = new + var/datum/wound/loss/phantom_loss = new // stolen valor, really + scaries.generate(L, phantom_loss) L.attach_limb(src, 1) - return 1 + return TRUE diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index a74b1dad28..13b1140527 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -35,8 +35,11 @@ //If the head is a special sprite var/custom_head + wound_resistance = 10 + scars_covered_by_clothes = FALSE + /obj/item/bodypart/head/can_dismember(obj/item/I) - if(!((owner.stat == DEAD) || owner.InFullCritical())) + if(owner && !((owner.stat == DEAD) || owner.InFullCritical())) return FALSE return ..() diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 29aca7166f..3161419449 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -10,6 +10,16 @@ if(L.body_zone == zone) return L +///Get the bodypart for whatever hand we have active, Only relevant for carbons +/mob/proc/get_active_hand() + return FALSE + +/mob/living/carbon/get_active_hand() + var/which_hand = BODY_ZONE_PRECISE_L_HAND + if(!(active_hand_index % 2)) + which_hand = BODY_ZONE_PRECISE_R_HAND + return get_bodypart(check_zone(which_hand)) + /mob/living/carbon/has_hand_for_held_index(i) if(i) var/obj/item/bodypart/L = hand_bodyparts[i] diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm new file mode 100644 index 0000000000..5a887ee6b7 --- /dev/null +++ b/code/modules/surgery/bodyparts/parts.dm @@ -0,0 +1,289 @@ +/obj/item/bodypart/chest + name = BODY_ZONE_CHEST + desc = "It's impolite to stare at a person's chest." + icon_state = "default_human_chest" + max_damage = 200 + body_zone = BODY_ZONE_CHEST + body_part = CHEST + px_x = 0 + px_y = 0 + stam_damage_coeff = 1 + max_stamina_damage = 200 + var/obj/item/cavity_item + +/obj/item/bodypart/chest/can_dismember(obj/item/I) + if(!((owner.stat == DEAD) || owner.InFullCritical()) || !get_organs()) + return FALSE + return ..() + +/obj/item/bodypart/chest/Destroy() + if(cavity_item) + qdel(cavity_item) + return ..() + +/obj/item/bodypart/chest/drop_organs(mob/user) + if(cavity_item) + cavity_item.forceMove(user.loc) + cavity_item = null + ..() + +/obj/item/bodypart/chest/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_chest" + animal_origin = MONKEY_BODYPART + +/obj/item/bodypart/chest/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_chest" + dismemberable = 0 + max_damage = 500 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/chest/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + +/obj/item/bodypart/chest/larva + icon = 'icons/mob/animal_parts.dmi' + icon_state = "larva_chest" + dismemberable = 0 + max_damage = 50 + animal_origin = LARVA_BODYPART + +/obj/item/bodypart/l_arm + name = "left arm" + desc = "Did you know that the word 'sinister' stems originally from the \ + Latin 'sinestra' (left hand), because the left hand was supposed to \ + be possessed by the devil? This arm appears to be possessed by no \ + one though." + icon_state = "default_human_l_arm" + attack_verb = list("slapped", "punched") + max_damage = 50 + max_stamina_damage = 50 + body_zone = BODY_ZONE_L_ARM + body_part = ARM_LEFT + aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER) + body_damage_coeff = 0.75 + held_index = 1 + px_x = -6 + px_y = 0 + stam_heal_tick = STAM_RECOVERY_LIMB + +/obj/item/bodypart/l_arm/is_disabled() + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) + return BODYPART_DISABLED_PARALYSIS + return ..() + +/obj/item/bodypart/l_arm/set_disabled(new_disabled) + . = ..() + if(!.) + return + if(owner.stat < UNCONSCIOUS) + switch(disabled) + if(BODYPART_DISABLED_DAMAGE) + owner.emote("scream") + to_chat(owner, "Your [name] is too damaged to function!") + if(BODYPART_DISABLED_PARALYSIS) + to_chat(owner, "You can't feel your [name]!") + if(held_index) + owner.dropItemToGround(owner.get_item_for_held_index(held_index)) + if(owner.hud_used) + var/obj/screen/inventory/hand/L = owner.hud_used.hand_slots["[held_index]"] + if(L) + L.update_icon() + +/obj/item/bodypart/l_arm/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_l_arm" + animal_origin = MONKEY_BODYPART + px_x = -5 + px_y = -3 + +/obj/item/bodypart/l_arm/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_l_arm" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/l_arm/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + +/obj/item/bodypart/r_arm + name = "right arm" + desc = "Over 87% of humans are right handed. That figure is much lower \ + among humans missing their right arm." + icon_state = "default_human_r_arm" + attack_verb = list("slapped", "punched") + max_damage = 50 + body_zone = BODY_ZONE_R_ARM + body_part = ARM_RIGHT + aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER) + body_damage_coeff = 0.75 + held_index = 2 + px_x = 6 + px_y = 0 + stam_heal_tick = STAM_RECOVERY_LIMB + max_stamina_damage = 50 + +/obj/item/bodypart/r_arm/is_disabled() + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_ARM)) + return BODYPART_DISABLED_PARALYSIS + return ..() + +/obj/item/bodypart/r_arm/set_disabled(new_disabled) + . = ..() + if(!.) + return + if(owner.stat < UNCONSCIOUS) + switch(disabled) + if(BODYPART_DISABLED_DAMAGE) + owner.emote("scream") + to_chat(owner, "Your [name] is too damaged to function!") + if(BODYPART_DISABLED_PARALYSIS) + to_chat(owner, "You can't feel your [name]!") + if(held_index) + owner.dropItemToGround(owner.get_item_for_held_index(held_index)) + if(owner.hud_used) + var/obj/screen/inventory/hand/R = owner.hud_used.hand_slots["[held_index]"] + if(R) + R.update_icon() + + +/obj/item/bodypart/r_arm/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_r_arm" + animal_origin = MONKEY_BODYPART + px_x = 5 + px_y = -3 + +/obj/item/bodypart/r_arm/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_r_arm" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/r_arm/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + +/obj/item/bodypart/l_leg + name = "left leg" + desc = "Some athletes prefer to tie their left shoelaces first for good \ + luck. In this instance, it probably would not have helped." + icon_state = "default_human_l_leg" + attack_verb = list("kicked", "stomped") + max_damage = 50 + body_zone = BODY_ZONE_L_LEG + body_part = LEG_LEFT + body_damage_coeff = 0.75 + px_x = -2 + px_y = 12 + stam_heal_tick = STAM_RECOVERY_LIMB + max_stamina_damage = 50 + +/obj/item/bodypart/l_leg/is_disabled() + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG)) + return BODYPART_DISABLED_PARALYSIS + return ..() + +/obj/item/bodypart/l_leg/set_disabled(new_disabled) + . = ..() + if(!. || owner.stat >= UNCONSCIOUS) + return + switch(disabled) + if(BODYPART_DISABLED_DAMAGE) + owner.emote("scream") + to_chat(owner, "Your [name] is too damaged to function!") + if(BODYPART_DISABLED_PARALYSIS) + to_chat(owner, "You can't feel your [name]!") + +/obj/item/bodypart/l_leg/digitigrade + name = "left digitigrade leg" + use_digitigrade = FULL_DIGITIGRADE + +/obj/item/bodypart/l_leg/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_l_leg" + animal_origin = MONKEY_BODYPART + px_y = 4 + +/obj/item/bodypart/l_leg/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_l_leg" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/l_leg/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART + +/obj/item/bodypart/r_leg + name = "right leg" + desc = "You put your right leg in, your right leg out. In, out, in, out, \ + shake it all about. And apparently then it detaches.\n\ + The hokey pokey has certainly changed a lot since space colonisation." + // alternative spellings of 'pokey' are availible + icon_state = "default_human_r_leg" + attack_verb = list("kicked", "stomped") + max_damage = 50 + body_zone = BODY_ZONE_R_LEG + body_part = LEG_RIGHT + body_damage_coeff = 0.75 + px_x = 2 + px_y = 12 + max_stamina_damage = 50 + stam_heal_tick = STAM_RECOVERY_LIMB + +/obj/item/bodypart/r_leg/is_disabled() + if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG)) + return BODYPART_DISABLED_PARALYSIS + return ..() + +/obj/item/bodypart/r_leg/set_disabled(new_disabled) + . = ..() + if(!. || owner.stat >= UNCONSCIOUS) + return + switch(disabled) + if(BODYPART_DISABLED_DAMAGE) + owner.emote("scream") + to_chat(owner, "Your [name] is too damaged to function!") + if(BODYPART_DISABLED_PARALYSIS) + to_chat(owner, "You can't feel your [name]!") + +/obj/item/bodypart/r_leg/digitigrade + name = "right digitigrade leg" + use_digitigrade = FULL_DIGITIGRADE + +/obj/item/bodypart/r_leg/monkey + icon = 'icons/mob/animal_parts.dmi' + icon_state = "default_monkey_r_leg" + animal_origin = MONKEY_BODYPART + px_y = 4 + +/obj/item/bodypart/r_leg/alien + icon = 'icons/mob/animal_parts.dmi' + icon_state = "alien_r_leg" + px_x = 0 + px_y = 0 + dismemberable = 0 + max_damage = 100 + animal_origin = ALIEN_BODYPART + +/obj/item/bodypart/r_leg/devil + dismemberable = 0 + max_damage = 5000 + animal_origin = DEVIL_BODYPART diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm new file mode 100644 index 0000000000..0c0083575b --- /dev/null +++ b/code/modules/surgery/bone_mending.dm @@ -0,0 +1,139 @@ + +/////BONE FIXING SURGERIES////// + +///// Repair Hairline Fracture (Severe) +/datum/surgery/repair_bone_hairline + name = "Repair bone fracture (hairline)" + steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_bone_hairline, /datum/surgery_step/close) + target_mobtypes = list(/mob/living/carbon/human) + possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) + requires_real_bodypart = TRUE + targetable_wound = /datum/wound/blunt/severe + +/datum/surgery/repair_bone_hairline/can_start(mob/living/user, mob/living/carbon/target) + if(..()) + var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) + return(targeted_bodypart.get_wound_type(targetable_wound)) + + +///// Repair Compound Fracture (Critical) +/datum/surgery/repair_bone_compound + name = "Repair Compound Fracture" + steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/reset_compound_fracture, /datum/surgery_step/repair_bone_compound, /datum/surgery_step/close) + target_mobtypes = list(/mob/living/carbon/human) + possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) + requires_real_bodypart = TRUE + targetable_wound = /datum/wound/blunt/critical + +/datum/surgery/repair_bone_compound/can_start(mob/living/user, mob/living/carbon/target) + if(..()) + var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) + return(targeted_bodypart.get_wound_type(targetable_wound)) + + + +//SURGERY STEPS + +///// Repair Hairline Fracture (Severe) +/datum/surgery_step/repair_bone_hairline + name = "repair hairline fracture (bonesetter/bone gel/tape)" + implements = list(/obj/item/bonesetter = 100, /obj/item/stack/medical/bone_gel = 100, /obj/item/stack/sticky_tape/surgical = 100, /obj/item/stack/sticky_tape/super = 50, /obj/item/stack/sticky_tape = 30) + time = 40 + +/datum/surgery_step/repair_bone_hairline/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(surgery.operated_wound) + display_results(user, target, "You begin to repair the fracture in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)].") + else + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + +/datum/surgery_step/repair_bone_hairline/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + if(surgery.operated_wound) + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) + display_results(user, target, "You successfully repair the fracture in [target]'s [parse_zone(target_zone)].", + "[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "repaired a hairline fracture in", addition="INTENT: [uppertext(user.a_intent)]") + qdel(surgery.operated_wound) + else + to_chat(user, "[target] has no hairline fracture there!") + return ..() + +/datum/surgery_step/repair_bone_hairline/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + ..() + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) + + + +///// Reset Compound Fracture (Crticial) +/datum/surgery_step/reset_compound_fracture + name = "reset bone" + implements = list(/obj/item/bonesetter = 100, /obj/item/stack/sticky_tape/surgical = 60, /obj/item/stack/sticky_tape/super = 40, /obj/item/stack/sticky_tape = 20) + time = 40 + +/datum/surgery_step/reset_compound_fracture/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(surgery.operated_wound) + display_results(user, target, "You begin to reset the bone in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to reset the bone in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to reset the bone in [target]'s [parse_zone(user.zone_selected)].") + else + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + +/datum/surgery_step/reset_compound_fracture/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + if(surgery.operated_wound) + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) + display_results(user, target, "You successfully reset the bone in [target]'s [parse_zone(target_zone)].", + "[user] successfully resets the bone in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully resets the bone in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "reset a compound fracture in", addition="INTENT: [uppertext(user.a_intent)]") + else + to_chat(user, "[target] has no compound fracture there!") + return ..() + +/datum/surgery_step/reset_compound_fracture/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + ..() + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) + + +///// Repair Compound Fracture (Crticial) +/datum/surgery_step/repair_bone_compound + name = "repair compound fracture (bone gel/tape)" + implements = list(/obj/item/stack/medical/bone_gel = 100, /obj/item/stack/sticky_tape/surgical = 100, /obj/item/stack/sticky_tape/super = 50, /obj/item/stack/sticky_tape = 30) + time = 40 + +/datum/surgery_step/repair_bone_compound/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(surgery.operated_wound) + display_results(user, target, "You begin to repair the fracture in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to repair the fracture in [target]'s [parse_zone(user.zone_selected)].") + else + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + +/datum/surgery_step/repair_bone_compound/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + if(surgery.operated_wound) + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) + display_results(user, target, "You successfully repair the fracture in [target]'s [parse_zone(target_zone)].", + "[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully repairs the fracture in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "repaired a compound fracture in", addition="INTENT: [uppertext(user.a_intent)]") + qdel(surgery.operated_wound) + else + to_chat(user, "[target] has no compound fracture there!") + return ..() + +/datum/surgery_step/repair_bone_compound/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + ..() + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) diff --git a/code/modules/surgery/burn_dressing.dm b/code/modules/surgery/burn_dressing.dm new file mode 100644 index 0000000000..8bfa52d245 --- /dev/null +++ b/code/modules/surgery/burn_dressing.dm @@ -0,0 +1,107 @@ + +/////BURN FIXING SURGERIES////// + +///// Debride burnt flesh +/datum/surgery/debride + name = "Debride infected flesh" + steps = list(/datum/surgery_step/debride, /datum/surgery_step/dress) + target_mobtypes = list(/mob/living/carbon/human) + possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) + requires_real_bodypart = TRUE + targetable_wound = /datum/wound/burn + +/datum/surgery/debride/can_start(mob/living/user, mob/living/carbon/target) + if(..()) + var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) + var/datum/wound/burn/burn_wound = targeted_bodypart.get_wound_type(targetable_wound) + return(burn_wound && burn_wound.infestation > 0) + +//SURGERY STEPS + +///// Debride +/datum/surgery_step/debride + name = "excise infection" + implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_SAW = 60, TOOL_WIRECUTTER = 40) + time = 30 + repeatable = TRUE + +/datum/surgery_step/debride/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + if(surgery.operated_wound) + var/datum/wound/burn/burn_wound = surgery.operated_wound + if(burn_wound.infestation <= 0) + to_chat(user, "[target]'s [parse_zone(user.zone_selected)] has no infected flesh to remove!") + surgery.status++ + repeatable = FALSE + return + display_results(user, target, "You begin to excise infected flesh from [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to excise infected flesh from [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to excise infected flesh from [target]'s [parse_zone(user.zone_selected)].") + else + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + +/datum/surgery_step/debride/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + var/datum/wound/burn/burn_wound = surgery.operated_wound + if(burn_wound) + display_results(user, target, "You successfully excise some of the infected flesh from [target]'s [parse_zone(target_zone)].", + "[user] successfully excises some of the infected flesh from [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully excises some of the infected flesh from [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]") + surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND) + burn_wound.infestation -= 0.5 + burn_wound.sanitization += 0.5 + if(burn_wound.infestation <= 0) + repeatable = FALSE + else + to_chat(user, "[target] has no infected flesh there!") + return ..() + +/datum/surgery_step/debride/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + ..() + display_results(user, target, "You carve away some of the healthy flesh from [target]'s [parse_zone(target_zone)].", + "[user] carves away some of the healthy flesh from [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] carves away some of the healthy flesh from [target]'s [parse_zone(target_zone)]!") + surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=TRUE) + +/datum/surgery_step/debride/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) + if(!..()) + return + var/datum/wound/burn/burn_wound = surgery.operated_wound + while(burn_wound && burn_wound.infestation > 0.25) + if(!..()) + break + +///// Dressing burns +/datum/surgery_step/dress + name = "bandage burns" + implements = list(/obj/item/stack/medical/gauze = 100, /obj/item/stack/sticky_tape/surgical = 100) + time = 40 + +/datum/surgery_step/dress/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/datum/wound/burn/burn_wound = surgery.operated_wound + if(burn_wound) + display_results(user, target, "You begin to dress the burns on [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to dress the burns on [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to dress the burns on [target]'s [parse_zone(user.zone_selected)].") + else + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + +/datum/surgery_step/dress/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + var/datum/wound/burn/burn_wound = surgery.operated_wound + if(burn_wound) + display_results(user, target, "You successfully wrap [target]'s [parse_zone(target_zone)] with [tool].", + "[user] successfully wraps [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully wraps [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]") + burn_wound.sanitization += 3 + burn_wound.flesh_healing += 5 + var/obj/item/bodypart/the_part = target.get_bodypart(target_zone) + the_part.apply_gauze(tool) + else + to_chat(user, "[target] has no burns there!") + return ..() + +/datum/surgery_step/dress/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + ..() + if(istype(tool, /obj/item/stack)) + var/obj/item/stack/used_stack = tool + used_stack.use(1) diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm index f2baabcef6..69f5062032 100644 --- a/code/modules/surgery/coronary_bypass.dm +++ b/code/modules/surgery/coronary_bypass.dm @@ -32,7 +32,8 @@ display_results(user, target, "Blood pools around the incision in [H]'s heart.", "Blood pools around the incision in [H]'s heart.", "") - H.bleed_rate += 10 + var/obj/item/bodypart/BP = H.get_bodypart(target_zone) + BP.generic_bleedstacks += 10 H.adjustBruteLoss(10) return TRUE @@ -42,7 +43,8 @@ display_results(user, target, "You screw up, cutting too deeply into the heart!", "[user] screws up, causing blood to spurt out of [H]'s chest!", "[user] screws up, causing blood to spurt out of [H]'s chest!") - H.bleed_rate += 20 + var/obj/item/bodypart/BP = H.get_bodypart(target_zone) + BP.generic_bleedstacks += 10 H.adjustOrganLoss(ORGAN_SLOT_HEART, 10) H.adjustBruteLoss(10) @@ -74,5 +76,6 @@ "[user] screws up, causing blood to spurt out of [H]'s chest profusely!", "[user] screws up, causing blood to spurt out of [H]'s chest profusely!") H.adjustOrganLoss(ORGAN_SLOT_HEART, 20) - H.bleed_rate += 30 + var/obj/item/bodypart/BP = H.get_bodypart(target_zone) + BP.generic_bleedstacks += 30 return FALSE diff --git a/code/modules/surgery/emergency_cardioversion_recovery.dm b/code/modules/surgery/emergency_cardioversion_recovery.dm index 05a18e9102..2508bf135f 100644 --- a/code/modules/surgery/emergency_cardioversion_recovery.dm +++ b/code/modules/surgery/emergency_cardioversion_recovery.dm @@ -7,13 +7,13 @@ /datum/surgery_step/ventricular_electrotherapy name = "ventricular electrotherapy" - implements = list(/obj/item/twohanded/shockpaddles = 90, /obj/item/defibrillator = 75, /obj/item/inducer = 55, /obj/item/stock_parts/cell = 25) //Just because the idea of a new player using the whole magine to defib is hillarious to me + implements = list(/obj/item/shockpaddles = 90, /obj/item/defibrillator = 75, /obj/item/inducer = 55, /obj/item/stock_parts/cell = 25) //Just because the idea of a new player using the whole magine to defib is hillarious to me time = 50 repeatable = TRUE //So you can retry /datum/surgery_step/ventricular_electrotherapy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(istype(tool, /obj/item/twohanded/shockpaddles)) - var/obj/item/twohanded/shockpaddles/pads = tool + if(istype(tool, /obj/item/shockpaddles)) + var/obj/item/shockpaddles/pads = tool if(!pads.wielded) to_chat(user, "You need to wield the paddles in both hands before you can use them!") return FALSE @@ -24,8 +24,8 @@ playsound(src, 'sound/machines/defib_charge.ogg', 75, 0) /datum/surgery_step/ventricular_electrotherapy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - if(istype(tool, /obj/item/twohanded/shockpaddles)) - var/obj/item/twohanded/shockpaddles/pads = tool + if(istype(tool, /obj/item/shockpaddles)) + var/obj/item/shockpaddles/pads = tool if(!pads.wielded) return FALSE var/mob/living/carbon/human/H = target @@ -53,7 +53,7 @@ H.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5) H.electrocute_act(0, (tool), 1, SHOCK_ILLUSION) //If we're using a defib, let the defib handle the revive. - if(istype(tool, /obj/item/twohanded/shockpaddles)) + if(istype(tool, /obj/item/shockpaddles)) return //Otherwise, we're ad hocing it if(!(do_after(user, 50, target = target))) diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm index 6110bb6202..b9d877d0c1 100644 --- a/code/modules/surgery/experimental_dissection.dm +++ b/code/modules/surgery/experimental_dissection.dm @@ -78,7 +78,7 @@ "[user] dissects [target]!") SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_earned)) var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) - target.apply_damage(80, BRUTE, L) + target.apply_damage(80, BRUTE, L, wound_bonus=CANT_WOUND) ADD_TRAIT(target, TRAIT_DISSECTED, "[surgery.name]") repeatable = FALSE return TRUE @@ -89,7 +89,7 @@ "[user] dissects [target], but looks a little dissapointed.") SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (round(check_value(target, surgery) * 0.01)))) var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST) - target.apply_damage(80, BRUTE, L) + target.apply_damage(80, BRUTE, L, wound_bonus=CANT_WOUND) return TRUE /datum/surgery/advanced/experimental_dissection/adv diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm index 8753912eb8..f5b23e6087 100644 --- a/code/modules/surgery/healing.dm +++ b/code/modules/surgery/healing.dm @@ -87,7 +87,7 @@ urdamageamt_brute += round((target.getBruteLoss()/ (missinghpbonus*2)),0.1) urdamageamt_burn += round((target.getFireLoss()/ (missinghpbonus*2)),0.1) - target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn) + target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn, wound_bonus=CANT_WOUND) return FALSE /***************************BRUTE***************************/ diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 4650f212c5..85b400d2da 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -62,7 +62,7 @@ time = 64 name = "manipulate organs" repeatable = 1 - implements = list(/obj/item/organ = 100, /obj/item/reagent_containers/food/snacks/organ = 0, /obj/item/organ_storage = 100) + implements = list(/obj/item/organ = 100, /obj/item/organ_storage = 100) var/implements_extract = list(TOOL_HEMOSTAT = 100, TOOL_CROWBAR = 55) var/current_type var/obj/item/organ/I = null @@ -86,6 +86,10 @@ if(target_zone != I.zone || target.getorganslot(I.slot)) to_chat(user, "There is no room for [I] in [target]'s [parse_zone(target_zone)]!") return -1 + var/obj/item/organ/meatslab = tool + if(!meatslab.useable) + to_chat(user, "[I] seems to have been chewed on, you can't use this!") + return -1 display_results(user, target, "You begin to insert [tool] into [target]'s [parse_zone(target_zone)]...", "[user] begins to insert [tool] into [target]'s [parse_zone(target_zone)].", "[user] begins to insert something into [target]'s [parse_zone(target_zone)].") @@ -112,9 +116,6 @@ else return -1 - else if(istype(tool, /obj/item/reagent_containers/food/snacks/organ)) - to_chat(user, "[tool] was bitten by someone! It's too damaged to use!") - return -1 /datum/surgery_step/manipulate_organs/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(current_type == "insert") if(istype(tool, /obj/item/organ_storage)) diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm index 3b05873a0a..8e893875a9 100644 --- a/code/modules/surgery/organic_steps.dm +++ b/code/modules/surgery/organic_steps.dm @@ -21,7 +21,9 @@ display_results(user, target, "Blood pools around the incision in [H]'s [parse_zone(target_zone)].", "Blood pools around the incision in [H]'s [parse_zone(target_zone)].", "") - H.bleed_rate += 3 + var/obj/item/bodypart/BP = target.get_bodypart(target_zone) + if(BP) + BP.generic_bleedstacks += 10 return TRUE /datum/surgery_step/incise/nobleed //silly friendly! @@ -50,7 +52,9 @@ target.heal_bodypart_damage(20,0) if (ishuman(target)) var/mob/living/carbon/human/H = target - H.bleed_rate = max( (H.bleed_rate - 3), 0) + var/obj/item/bodypart/BP = H.get_bodypart(target_zone) + if(BP) + BP.generic_bleedstacks -= 3 return ..() //retract skin /datum/surgery_step/retract_skin @@ -86,12 +90,14 @@ target.heal_bodypart_damage(45,0) if (ishuman(target)) var/mob/living/carbon/human/H = target - H.bleed_rate = max( (H.bleed_rate - 3), 0) + var/obj/item/bodypart/BP = H.get_bodypart(target_zone) + if(BP) + BP.generic_bleedstacks -= 3 return ..() //saw bone /datum/surgery_step/saw name = "saw bone" - implements = list(TOOL_SAW = 100, /obj/item/melee/arm_blade = 75, /obj/item/twohanded/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25) + implements = list(TOOL_SAW = 100, /obj/item/melee/arm_blade = 75, /obj/item/fireaxe = 50, /obj/item/hatchet = 35, /obj/item/kitchen/knife/butcher = 25) time = 54 /datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -100,7 +106,7 @@ "[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].") /datum/surgery_step/saw/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - target.apply_damage(50, BRUTE, "[target_zone]") + target.apply_damage(50, BRUTE, "[target_zone]", wound_bonus=CANT_WOUND) display_results(user, target, "You saw [target]'s [parse_zone(target_zone)] open.", "[user] saws [target]'s [parse_zone(target_zone)] open!", "[user] saws [target]'s [parse_zone(target_zone)] open!") diff --git a/code/modules/surgery/organs/appendix.dm b/code/modules/surgery/organs/appendix.dm index c737e8bc30..782991d79c 100644 --- a/code/modules/surgery/organs/appendix.dm +++ b/code/modules/surgery/organs/appendix.dm @@ -37,9 +37,3 @@ ..() if(inflamed) M.ForceContractDisease(new /datum/disease/appendicitis(), FALSE, TRUE) - -/obj/item/organ/appendix/prepare_eat() - var/obj/S = ..() - if(inflamed) - S.reagents.add_reagent(/datum/reagent/toxin/bad_food, 5) - return S diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index e9eef45228..5ff339691b 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -132,6 +132,7 @@ "You extend [holder] from your [zone == BODY_ZONE_R_ARM ? "right" : "left"] arm.", "You hear a short mechanical noise.") playsound(get_turf(owner), 'sound/mecha/mechmove03.ogg', 50, 1) + return TRUE /obj/item/organ/cyberimp/arm/ui_action_click() if(crit_fail || (organ_flags & ORGAN_FAILING) || (!holder && !contents.len)) @@ -273,12 +274,29 @@ desc = "A deployable riot shield to help deal with civil unrest." contents = newlist(/obj/item/shield/riot/implant) -/obj/item/organ/cyberimp/arm/shield/Extend(obj/item/I) +/obj/item/organ/cyberimp/arm/shield/Extend(obj/item/I, silent = FALSE) if(I.obj_integrity == 0) //that's how the shield recharge works - to_chat(owner, "[I] is still too unstable to extend. Give it some time!") + if(!silent) + to_chat(owner, "[I] is still too unstable to extend. Give it some time!") return FALSE return ..() +/obj/item/organ/cyberimp/arm/shield/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) + . = ..() + if(.) + RegisterSignal(M, COMSIG_LIVING_ACTIVE_BLOCK_START, .proc/on_signal) + +/obj/item/organ/cyberimp/arm/shield/Remove(special = FALSE) + UnregisterSignal(owner, COMSIG_LIVING_ACTIVE_BLOCK_START) + return ..() + +/obj/item/organ/cyberimp/arm/shield/proc/on_signal(datum/source, obj/item/blocking_item, list/other_items) + if(!blocking_item) //if they don't have something + var/obj/item/shield/S = locate() in contents + if(!Extend(S, TRUE)) + return + other_items += S + /obj/item/organ/cyberimp/arm/shield/emag_act() . = ..() if(obj_flags & EMAGGED) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index d988e20637..8b85ddb1f5 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -265,6 +265,10 @@ var/C = input(owner, "Select Color", "Select color", "#ffffff") as color|null if(!C || QDELETED(src) || QDELETED(user) || QDELETED(owner) || owner != user) return + var/list/hsv = ReadHSV(RGBtoHSV(C)) + if(hsv[2] > 125) + to_chat(user, "A color that saturated? Surely not!") + return var/range = input(user, "Enter range (0 - [max_light_beam_distance])", "Range Select", 0) as null|num if(!isnum(range)) return @@ -405,4 +409,4 @@ #undef BLURRY_VISION_ONE #undef BLURRY_VISION_TWO -#undef BLIND_VISION_THREE \ No newline at end of file +#undef BLIND_VISION_THREE diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm index 465c10c4cd..e251abfd35 100644 --- a/code/modules/surgery/organs/heart.dm +++ b/code/modules/surgery/organs/heart.dm @@ -61,10 +61,10 @@ return "a healthy" return "an unstable" -/obj/item/organ/heart/prepare_eat() - var/obj/S = ..() - S.icon_state = "[icon_base]-off" - return S +/obj/item/organ/heart/OnEatFrom(eater, feeder) + . = ..() + beating = FALSE + update_icon() /obj/item/organ/heart/on_life() . = ..() diff --git a/code/modules/surgery/organs/liver.dm b/code/modules/surgery/organs/liver.dm index b24034ca4a..f0f98a5fa5 100755 --- a/code/modules/surgery/organs/liver.dm +++ b/code/modules/surgery/organs/liver.dm @@ -23,6 +23,7 @@ var/toxLethality = LIVER_DEFAULT_TOX_LETHALITY//affects how much damage toxins do to the liver var/filterToxins = TRUE //whether to filter toxins var/cachedmoveCalc = 1 + food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/iron = 5) /obj/item/organ/liver/on_life() . = ..() @@ -44,11 +45,6 @@ if(damage > 10 && prob(damage/3))//the higher the damage the higher the probability to_chat(owner, "You feel a dull pain in your abdomen.") -/obj/item/organ/liver/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent(/datum/reagent/iron, 5) - return S - /obj/item/organ/liver/applyOrganDamage(d, maximum = maxHealth) . = ..() if(!. || QDELETED(owner)) @@ -77,8 +73,8 @@ /obj/item/organ/liver/proc/sizeMoveMod(value, mob/living/carbon/C) if(cachedmoveCalc == value) return - C.next_move_modifier /= cachedmoveCalc - C.next_move_modifier *= value + C.action_cooldown_mod /= cachedmoveCalc + C.action_cooldown_mod *= value cachedmoveCalc = value /obj/item/organ/liver/fly diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 84247d10ee..1864806bed 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -24,6 +24,8 @@ now_fixed = "Your lungs seem to once again be able to hold air." high_threshold_cleared = "The constriction around your chest loosens as your breathing calms down." + food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/medicine/salbutamol = 5) + //Breath damage var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa @@ -131,13 +133,11 @@ var/gas_breathed = 0 - var/list/breath_gases = breath.gases - //Partial pressures in our breath - var/O2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/oxygen])+(8*breath.get_breath_partial_pressure(breath_gases[/datum/gas/pluoxium])) - var/N2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrogen]) - var/Toxins_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/plasma]) - var/CO2_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/carbon_dioxide]) + var/O2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/oxygen))+(8*breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/pluoxium))) + var/N2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrogen)) + var/Toxins_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma)) + var/CO2_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/carbon_dioxide)) //-- OXY --// @@ -145,7 +145,7 @@ //Too much oxygen! //Yes, some species may not like it. if(safe_oxygen_max) if((O2_pp > safe_oxygen_max) && safe_oxygen_max == 0) //I guess plasma men technically need to have a check. - var/ratio = (breath_gases[/datum/gas/oxygen]/safe_oxygen_max) * 10 + var/ratio = (breath.get_moles(/datum/gas/oxygen)/safe_oxygen_max) * 10 H.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type) H.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy) @@ -168,18 +168,18 @@ //Too little oxygen! if(safe_oxygen_min) if(O2_pp < safe_oxygen_min) - gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath_gases[/datum/gas/oxygen]) + gas_breathed = handle_too_little_breath(H, O2_pp, safe_oxygen_min, breath.get_moles(/datum/gas/oxygen)) H.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy) else H.failed_last_breath = FALSE if(H.health >= H.crit_threshold) H.adjustOxyLoss(-breathModifier) //More damaged lungs = slower oxy rate up to a factor of half - gas_breathed = breath_gases[/datum/gas/oxygen] + gas_breathed = breath.get_moles(/datum/gas/oxygen) H.clear_alert("not_enough_oxy") //Exhale - breath_gases[/datum/gas/oxygen] -= gas_breathed - breath_gases[/datum/gas/carbon_dioxide] += gas_breathed + breath.adjust_moles(/datum/gas/oxygen, -gas_breathed) + breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed) gas_breathed = 0 //-- Nitrogen --// @@ -187,7 +187,7 @@ //Too much nitrogen! if(safe_nitro_max) if(N2_pp > safe_nitro_max) - var/ratio = (breath_gases[/datum/gas/nitrogen]/safe_nitro_max) * 10 + var/ratio = (breath.get_moles(/datum/gas/nitrogen)/safe_nitro_max) * 10 H.apply_damage_type(clamp(ratio, nitro_breath_dam_min, nitro_breath_dam_max), nitro_damage_type) H.throw_alert("too_much_nitro", /obj/screen/alert/too_much_nitro) H.losebreath += 2 @@ -197,18 +197,18 @@ //Too little nitrogen! if(safe_nitro_min) if(N2_pp < safe_nitro_min) - gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath_gases[/datum/gas/nitrogen]) + gas_breathed = handle_too_little_breath(H, N2_pp, safe_nitro_min, breath.get_moles(/datum/gas/nitrogen)) H.throw_alert("nitro", /obj/screen/alert/not_enough_nitro) else H.failed_last_breath = FALSE if(H.health >= H.crit_threshold) H.adjustOxyLoss(-breathModifier) - gas_breathed = breath_gases[/datum/gas/nitrogen] + gas_breathed = breath.get_moles(/datum/gas/nitrogen) H.clear_alert("nitro") //Exhale - breath_gases[/datum/gas/nitrogen] -= gas_breathed - breath_gases[/datum/gas/carbon_dioxide] += gas_breathed + breath.adjust_moles(/datum/gas/nitrogen, -gas_breathed) + breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed) gas_breathed = 0 //-- CO2 --// @@ -234,18 +234,18 @@ //Too little CO2! if(safe_co2_min) if(CO2_pp < safe_co2_min) - gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath_gases[/datum/gas/carbon_dioxide]) + gas_breathed = handle_too_little_breath(H, CO2_pp, safe_co2_min, breath.get_moles(/datum/gas/carbon_dioxide)) H.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2) else H.failed_last_breath = FALSE if(H.health >= H.crit_threshold) H.adjustOxyLoss(-breathModifier) - gas_breathed = breath_gases[/datum/gas/carbon_dioxide] + gas_breathed = breath.get_moles(/datum/gas/carbon_dioxide) H.clear_alert("not_enough_co2") //Exhale - breath_gases[/datum/gas/carbon_dioxide] -= gas_breathed - breath_gases[/datum/gas/oxygen] += gas_breathed + breath.adjust_moles(/datum/gas/carbon_dioxide, -gas_breathed) + breath.adjust_moles(/datum/gas/oxygen, gas_breathed) gas_breathed = 0 @@ -254,7 +254,7 @@ //Too much toxins! if(safe_toxins_max) if(Toxins_pp > safe_toxins_max) - var/ratio = (breath_gases[/datum/gas/plasma]/safe_toxins_max) * 10 + var/ratio = (breath.get_moles(/datum/gas/plasma)/safe_toxins_max) * 10 H.apply_damage_type(clamp(ratio, tox_breath_dam_min, tox_breath_dam_max), tox_damage_type) H.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox) else @@ -264,18 +264,18 @@ //Too little toxins! if(safe_toxins_min) if(Toxins_pp < safe_toxins_min) - gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath_gases[/datum/gas/plasma]) + gas_breathed = handle_too_little_breath(H, Toxins_pp, safe_toxins_min, breath.get_moles(/datum/gas/plasma)) H.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox) else H.failed_last_breath = FALSE if(H.health >= H.crit_threshold) H.adjustOxyLoss(-breathModifier) - gas_breathed = breath_gases[/datum/gas/plasma] + gas_breathed = breath.get_moles(/datum/gas/plasma) H.clear_alert("not_enough_tox") //Exhale - breath_gases[/datum/gas/plasma] -= gas_breathed - breath_gases[/datum/gas/carbon_dioxide] += gas_breathed + breath.adjust_moles(/datum/gas/plasma, -gas_breathed) + breath.adjust_moles(/datum/gas/carbon_dioxide, gas_breathed) gas_breathed = 0 @@ -285,7 +285,7 @@ // N2O - var/SA_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitrous_oxide]) + var/SA_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitrous_oxide)) if(SA_pp > SA_para_min) // Enough to make us stunned for a bit H.Unconscious(60) // 60 gives them one second to wake up and run away a bit! if(SA_pp > SA_sleep_min) // Enough to make us sleep as well @@ -299,7 +299,7 @@ // BZ - var/bz_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/bz]) + var/bz_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/bz)) if(bz_pp > BZ_trip_balls_min) H.hallucination += 10 H.reagents.add_reagent(/datum/reagent/bz_metabolites,5) @@ -312,14 +312,14 @@ // Tritium - var/trit_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/tritium]) + var/trit_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/tritium)) if (trit_pp > 50) H.radiation += trit_pp/2 //If you're breathing in half an atmosphere of radioactive gas, you fucked up. else H.radiation += trit_pp/10 // Nitryl - var/nitryl_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/nitryl]) + var/nitryl_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/nitryl)) if (prob(nitryl_pp)) to_chat(H, "Your mouth feels like it's burning!") if (nitryl_pp >40) @@ -330,22 +330,22 @@ H.silent = max(H.silent, 3) else H.adjustFireLoss(nitryl_pp/4) - gas_breathed = breath_gases[/datum/gas/nitryl] + gas_breathed = breath.get_moles(/datum/gas/nitryl) if (gas_breathed > gas_stimulation_min) H.reagents.add_reagent(/datum/reagent/nitryl,1) - breath_gases[/datum/gas/nitryl]-=gas_breathed + breath.adjust_moles(/datum/gas/nitryl, -gas_breathed) // Stimulum - gas_breathed = breath_gases[/datum/gas/stimulum] + gas_breathed = breath.get_moles(/datum/gas/stimulum) if (gas_breathed > gas_stimulation_min) var/existing = H.reagents.get_reagent_amount(/datum/reagent/stimulum) H.reagents.add_reagent(/datum/reagent/stimulum, max(0, 5 - existing)) - breath_gases[/datum/gas/stimulum]-=gas_breathed + breath.adjust_moles(/datum/gas/stimulum, -gas_breathed) // Miasma - if (breath_gases[/datum/gas/miasma]) - var/miasma_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/miasma]) + if (breath.get_moles(/datum/gas/miasma)) + var/miasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/miasma)) if(miasma_pp > MINIMUM_MOLES_DELTA_TO_MOVE) //Miasma sickness @@ -385,14 +385,13 @@ // Then again, this is a purely hypothetical scenario and hardly reachable owner.adjust_disgust(0.1 * miasma_pp) - breath_gases[/datum/gas/miasma]-=gas_breathed + breath.adjust_moles(/datum/gas/miasma, -gas_breathed) // Clear out moods when no miasma at all else SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "smell") handle_breath_temperature(breath, H) - GAS_GARBAGE_COLLECT(breath.gases) return TRUE @@ -414,7 +413,7 @@ /obj/item/organ/lungs/proc/handle_breath_temperature(datum/gas_mixture/breath, mob/living/carbon/human/H) // called by human/life, handles temperatures - var/breath_temperature = breath.temperature + var/breath_temperature = breath.return_temperature() if(!HAS_TRAIT(H, TRAIT_RESISTCOLD)) // COLD DAMAGE var/cold_modifier = H.dna.species.coldmod @@ -458,11 +457,6 @@ else if(!(organ_flags & ORGAN_FAILING)) failed = FALSE -/obj/item/organ/lungs/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent(/datum/reagent/medicine/salbutamol, 5) - return S - /obj/item/organ/lungs/ipc name = "ipc cooling system" icon_state = "lungs-c" @@ -547,8 +541,8 @@ /obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/H) . = ..() - if (breath && breath.gases[/datum/gas/plasma]) - var/plasma_pp = breath.get_breath_partial_pressure(breath.gases[/datum/gas/plasma]) + if (breath) + var/plasma_pp = breath.get_breath_partial_pressure(breath.get_moles(/datum/gas/plasma)) owner.blood_volume += (0.2 * plasma_pp) // 10/s when breathing literally nothing but plasma, which will suffocate you. /obj/item/organ/lungs/yamerol diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index 761ebc17a2..cb4de69fbd 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -8,7 +8,7 @@ var/zone = BODY_ZONE_CHEST var/slot // DO NOT add slots with matching names to different zones - it will break internal_organs_slot list! - var/organ_flags = NONE + var/organ_flags = ORGAN_EDIBLE var/maxHealth = STANDARD_ORGAN_THRESHOLD var/damage = 0 //total damage this organ has sustained ///Healing factor and decay factor function on % of maxhealth, and do not work by applying a static number per tick @@ -25,7 +25,23 @@ var/now_fixed var/high_threshold_cleared var/low_threshold_cleared - rad_flags = RAD_NO_CONTAMINATE + + ///When you take a bite you cant jam it in for surgery anymore. + var/useable = TRUE + var/list/food_reagents = list(/datum/reagent/consumable/nutriment = 5) + +/obj/item/organ/Initialize() + . = ..() + if(organ_flags & ORGAN_EDIBLE) + AddComponent(/datum/component/edible, food_reagents, null, RAW | MEAT | GROSS, null, 10, null, null, null, CALLBACK(src, .proc/OnEatFrom)) + START_PROCESSING(SSobj, src) + +/obj/item/organ/Destroy() + if(owner) + // The special flag is important, because otherwise mobs can die + // while undergoing transformation into different mobs. + Remove(TRUE) + return ..() /obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) if(!iscarbon(M) || owner == M) @@ -106,7 +122,7 @@ if(istype(loc, /turf/))//Only concern is adding an organ to a freezer when the area around it is cold. var/turf/T = loc var/datum/gas_mixture/enviro = T.return_air() - local_temp = enviro.temperature + local_temp = enviro.return_temperature() else if(!owner && ismob(loc)) var/mob/M = loc @@ -116,7 +132,7 @@ return TRUE var/turf/T = M.loc var/datum/gas_mixture/enviro = T.return_air() - local_temp = enviro.temperature + local_temp = enviro.return_temperature() if(owner) //Don't interfere with bodies frozen by structures. @@ -157,47 +173,8 @@ if(damage > high_threshold) . += "[src] is starting to look discolored." - -/obj/item/organ/proc/prepare_eat() - var/obj/item/reagent_containers/food/snacks/organ/S = new - S.name = name - S.desc = desc - S.icon = icon - S.icon_state = icon_state - S.w_class = w_class - - return S - -/obj/item/reagent_containers/food/snacks/organ - name = "appendix" - icon_state = "appendix" - icon = 'icons/obj/surgery.dmi' - list_reagents = list(/datum/reagent/consumable/nutriment = 5) - foodtype = RAW | MEAT | GROSS - - -/obj/item/organ/Initialize() - . = ..() - START_PROCESSING(SSobj, src) - -/obj/item/organ/Destroy() - if(owner) - // The special flag is important, because otherwise mobs can die - // while undergoing transformation into different mobs. - Remove(TRUE) - return ..() - -/obj/item/organ/attack(mob/living/carbon/M, mob/user) - if(M == user && ishuman(user)) - var/mob/living/carbon/human/H = user - if(status == ORGAN_ORGANIC) - var/obj/item/reagent_containers/food/snacks/S = prepare_eat() - if(S) - qdel(src) - if(H.put_in_active_hand(S)) - S.attack(H, H) - else - ..() +/obj/item/organ/proc/OnEatFrom(eater, feeder) + useable = FALSE //You can't use it anymore after eating it you spaztic /obj/item/organ/item_action_slot_check(slot,mob/user) return //so we don't grant the organ's action to mobs who pick up the organ. diff --git a/code/modules/surgery/organs/stomach.dm b/code/modules/surgery/organs/stomach.dm old mode 100755 new mode 100644 index d2ec254ca2..cabe49db25 --- a/code/modules/surgery/organs/stomach.dm +++ b/code/modules/surgery/organs/stomach.dm @@ -103,3 +103,35 @@ if(2) owner.nutrition = min(owner.nutrition - 100, 0) to_chat(owner, "Alert: Minor battery discharge!") + +/obj/item/organ/stomach/ethereal + name = "biological battery" + icon_state = "stomach-p" //Welp. At least it's more unique in functionaliy. + desc = "A crystal-like organ that stores the electric charge of ethereals." + var/crystal_charge = ETHEREAL_CHARGE_FULL + +/obj/item/organ/stomach/ethereal/on_life() + ..() + adjust_charge(-ETHEREAL_CHARGE_FACTOR) + +/obj/item/organ/stomach/ethereal/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) + ..() + RegisterSignal(owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/charge) + RegisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_electrocute) + +/obj/item/organ/stomach/ethereal/Remove(mob/living/carbon/M, special = 0) + UnregisterSignal(owner, COMSIG_PROCESS_BORGCHARGER_OCCUPANT) + UnregisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT) + ..() + +/obj/item/organ/stomach/ethereal/proc/charge(datum/source, amount, repairs) + adjust_charge(amount / 70) + +/obj/item/organ/stomach/ethereal/proc/on_electrocute(datum/source, shock_damage, siemens_coeff = 1, flags = NONE) + if(flags & SHOCK_ILLUSION) + return + adjust_charge(shock_damage * siemens_coeff * 2) + to_chat(owner, "You absorb some of the shock into your body!") + +/obj/item/organ/stomach/ethereal/proc/adjust_charge(amount) + crystal_charge = clamp(crystal_charge + amount, ETHEREAL_CHARGE_NONE, ETHEREAL_CHARGE_DANGEROUS) diff --git a/code/modules/surgery/organs/tails.dm b/code/modules/surgery/organs/tails.dm index 55a656f42d..289e9df9d4 100644 --- a/code/modules/surgery/organs/tails.dm +++ b/code/modules/surgery/organs/tails.dm @@ -45,14 +45,20 @@ /obj/item/organ/tail/lizard/Insert(mob/living/carbon/human/H, special = 0, drop_if_replaced = TRUE) ..() if(istype(H)) - // Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in + // Checks here are necessary so it wouldn't overwrite the tail of a lizard it spawned in //yes, the if checks may cause snowflakes so that you can't insert another person's tail (haven't actually tested it but I assume that's the result of my addition) but it makes it so never again will lizards break their spine if set_species is called twice in a row (hopefully) if(!H.dna.species.mutant_bodyparts["tail_lizard"]) - H.dna.features["tail_lizard"] = tail_type - H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type + if (!H.dna.features["tail_lizard"]) + H.dna.features["tail_lizard"] = tail_type + H.dna.species.mutant_bodyparts["tail_lizard"] = tail_type + else + H.dna.species.mutant_bodyparts["tail_lizard"] = H.dna.features["tail_lizard"] if(!H.dna.species.mutant_bodyparts["spines"]) - H.dna.features["spines"] = spines - H.dna.species.mutant_bodyparts["spines"] = spines + if (!H.dna.features["spines"]) + H.dna.features["spines"] = spines + H.dna.species.mutant_bodyparts["spines"] = spines + else + H.dna.species.mutant_bodyparts["spines"] = H.dna.features["spines"] H.update_body() /obj/item/organ/tail/lizard/Remove(special = FALSE) diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm index f8547dda6e..7090ab62e2 100644 --- a/code/modules/surgery/organs/tongue.dm +++ b/code/modules/surgery/organs/tongue.dm @@ -252,6 +252,7 @@ name = "robotic voicebox" desc = "A voice synthesizer that can interface with organic lifeforms." status = ORGAN_ROBOTIC + organ_flags = ORGAN_NO_SPOIL icon_state = "tonguerobot" say_mod = "states" attack_verb = list("beeped", "booped") @@ -311,3 +312,26 @@ desc = "A voice synthesizer used by IPCs to smoothly interface with organic lifeforms." electronics_magic = FALSE organ_flags = ORGAN_SYNTHETIC + +/obj/item/organ/tongue/ethereal + name = "electric discharger" + desc = "A sophisticated ethereal organ, capable of synthesising speech via electrical discharge." + icon_state = "electrotongue" + say_mod = "crackles" + attack_verb = list("shocked", "jolted", "zapped") + taste_sensitivity = 101 // Not a tongue, they can't taste shit + var/static/list/languages_possible_ethereal = typecacheof(list( + /datum/language/common, + /datum/language/draconic, + /datum/language/codespeak, + /datum/language/monkey, + /datum/language/narsie, + /datum/language/beachbum, + /datum/language/aphasia, + /datum/language/sylvan, + /datum/language/voltaic + )) + +/obj/item/organ/tongue/ethereal/Initialize(mapload) + . = ..() + languages_possible = languages_possible_ethereal diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index 65e53df26f..b6b74efe32 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -254,7 +254,6 @@ var/static/regex/clap_words = regex("clap|applaud") var/static/regex/honk_words = regex("ho+nk") //hooooooonk var/static/regex/multispin_words = regex("like a record baby|right round") - var/static/regex/orgasm_words = regex("cum|orgasm|climax|squirt|heyo") //CITADEL CHANGE var/static/regex/dab_words = regex("dab|mood") //CITADEL CHANGE var/static/regex/snap_words = regex("snap") //CITADEL CHANGE var/static/regex/bwoink_words = regex("what the fuck are you doing|bwoink|hey you got a moment?") //CITADEL CHANGE @@ -319,13 +318,14 @@ cooldown = COOLDOWN_DAMAGE for(var/V in listeners) var/mob/living/L = V - L.apply_damage(15 * power_multiplier, def_zone = BODY_ZONE_CHEST) + L.apply_damage(15 * power_multiplier, def_zone = BODY_ZONE_CHEST, wound_bonus=CANT_WOUND) //BLEED else if((findtext(message, bleed_words))) cooldown = COOLDOWN_DAMAGE for(var/mob/living/carbon/human/H in listeners) - H.bleed_rate += (5 * power_multiplier) + var/obj/item/bodypart/BP = pick(H.bodyparts) + BP.generic_bleedstacks += 5 //FIRE else if((findtext(message, burn_words))) @@ -572,16 +572,6 @@ var/mob/living/L = V L.SpinAnimation(speed = 10, loops = 5) - //CITADEL CHANGES - //ORGASM - else if((findtext(message, orgasm_words))) - cooldown = COOLDOWN_MEME - for(var/V in listeners) - var/mob/living/carbon/human/H = V - - if(H.client && H.client.prefs && H.client.prefs.cit_toggles & HYPNO) // probably a redundant check but for good measure - H.mob_climax(forced_climax=TRUE) - //DAB else if((findtext(message, dab_words))) cooldown = COOLDOWN_DAMAGE @@ -765,7 +755,6 @@ var/static/regex/forget_words = regex("forget|muddled|awake and forget") var/static/regex/attract_words = regex("come here|come to me|get over here|attract") //phase 2 - var/static/regex/orgasm_words = regex("cum|orgasm|climax|squirt|heyo") //wah, lewd var/static/regex/awoo_words = regex("howl|awoo|bark") var/static/regex/nya_words = regex("nya|meow|mewl") var/static/regex/sleep_words = regex("sleep|slumber|rest") @@ -1092,28 +1081,6 @@ addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "You are drawn towards [user]!
      "), 5) to_chat(user, "You draw [L] towards you!") - - //teir 2 - - /* removed for now - //ORGASM - else if((findtext(message, orgasm_words))) - for(var/V in listeners) - var/mob/living/carbon/human/H = V - var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall) - if(E.phase > 1) - if(E.lewd) // probably a redundant check but for good measure - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure."), 5) - H.mob_climax(forced_climax=TRUE) - H.SetStun(20) - E.resistanceTally = 0 //makes resistance 0, but resets arousal, resistance buildup is faster unaroused (massively so). - E.enthrallTally += power_multiplier - E.cooldown += 6 - else - H.throw_at(get_step_towards(user,H), 3 * power_multiplier, 1 * power_multiplier) - */ - - //awoo else if((findtext(message, awoo_words))) for(var/V in listeners) diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm index 62ce16e7e6..8eac5b7895 100644 --- a/code/modules/surgery/prosthetic_replacement.dm +++ b/code/modules/surgery/prosthetic_replacement.dm @@ -13,7 +13,7 @@ return 1 /datum/surgery_step/add_prosthetic name = "add prosthetic" - implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/twohanded/required/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100) + implements = list(/obj/item/bodypart = 100, /obj/item/organ_storage = 100, /obj/item/chainsaw = 100, /obj/item/melee/synthetic_arm_blade = 100) time = 32 var/organ_rejection_dam = 0 /datum/surgery_step/add_prosthetic/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) @@ -79,7 +79,7 @@ "[user] finishes attaching [tool]!", "[user] finishes the attachment procedure!") qdel(tool) - if(istype(tool, /obj/item/twohanded/required/chainsaw)) + if(istype(tool, /obj/item/chainsaw)) var/obj/item/mounted_chainsaw/new_arm = new(target) target_zone == BODY_ZONE_R_ARM ? target.put_in_r_hand(new_arm) : target.put_in_l_hand(new_arm) return 1 diff --git a/code/modules/surgery/repair_puncture.dm b/code/modules/surgery/repair_puncture.dm new file mode 100644 index 0000000000..12aefefc82 --- /dev/null +++ b/code/modules/surgery/repair_puncture.dm @@ -0,0 +1,108 @@ + +/////BURN FIXING SURGERIES////// + +//the step numbers of each of these two, we only currently use the first to switch back and forth due to advancing after finishing steps anyway +#define REALIGN_INNARDS 1 +#define WELD_VEINS 2 + +///// Repair puncture wounds +/datum/surgery/repair_puncture + name = "Repair puncture" + steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_innards, /datum/surgery_step/seal_veins, /datum/surgery_step/close) // repeat between steps 2 and 3 until healed + target_mobtypes = list(/mob/living/carbon) + possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) + requires_real_bodypart = TRUE + targetable_wound = /datum/wound/pierce + +/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target) + . = ..() + if(.) + var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) + var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound) + return(pierce_wound && pierce_wound.blood_flow > 0) + +//SURGERY STEPS + +///// realign the blood vessels so we can reweld them +/datum/surgery_step/repair_innards + name = "realign blood vessels" + implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_WIRECUTTER = 40) + time = 3 SECONDS + +/datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/datum/wound/pierce/pierce_wound = surgery.operated_wound + if(!pierce_wound) + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + return + + if(pierce_wound.blood_flow <= 0) + to_chat(user, "[target]'s [parse_zone(user.zone_selected)] has no puncture to repair!") + surgery.status++ + return + + display_results(user, target, "You begin to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)].") + +/datum/surgery_step/repair_innards/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + var/datum/wound/pierce/pierce_wound = surgery.operated_wound + if(!pierce_wound) + to_chat(user, "[target] has no puncture wound there!") + return ..() + + display_results(user, target, "You successfully realign some of the blood vessels in [target]'s [parse_zone(target_zone)].", + "[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]") + surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND) + pierce_wound.blood_flow -= 0.25 + return ..() + +/datum/surgery_step/repair_innards/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + . = ..() + display_results(user, target, "You jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)].", + "[user] jerks apart some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)]!") + surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=SHARP_EDGED, wound_bonus = 10) + +///// Sealing the vessels back together +/datum/surgery_step/seal_veins + name = "weld veins" // if your doctor says they're going to weld your blood vessels back together, you're either A) on SS13, or B) in grave mortal peril + implements = list(TOOL_CAUTERY = 100, /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30) + time = 4 SECONDS + +/datum/surgery_step/seal_veins/tool_check(mob/user, obj/item/tool) + if(implement_type == TOOL_WELDER || implement_type == /obj/item) + return tool.get_temperature() + + return TRUE + +/datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + var/datum/wound/pierce/pierce_wound = surgery.operated_wound + if(!pierce_wound) + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + return + display_results(user, target, "You begin to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)].") + +/datum/surgery_step/seal_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + var/datum/wound/pierce/pierce_wound = surgery.operated_wound + if(!pierce_wound) + to_chat(user, "[target] has no puncture there!") + return ..() + + display_results(user, target, "You successfully meld some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool].", + "[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]") + pierce_wound.blood_flow -= 0.5 + if(pierce_wound.blood_flow > 0) + surgery.status = REALIGN_INNARDS + to_chat(user, "There still seems to be misaligned blood vessels to finish...") + else + to_chat(user, "You've repaired all the internal damage in [target]'s [parse_zone(target_zone)]!") + return ..() + +#undef REALIGN_INNARDS +#undef WELD_VEINS diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index 51ce2726b0..4d42cb6c23 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -18,6 +18,8 @@ var/lying_required = TRUE //Does the vicitm needs to be lying down. var/requires_tech = FALSE var/replaced_by + var/datum/wound/operated_wound //The actual wound datum instance we're targeting + var/datum/wound/targetable_wound //The wound type this surgery targets /datum/surgery/New(surgery_target, surgery_location, surgery_bodypart) ..() @@ -28,8 +30,13 @@ location = surgery_location if(surgery_bodypart) operated_bodypart = surgery_bodypart + if(targetable_wound) + operated_wound = operated_bodypart.get_wound_type(targetable_wound) + operated_wound.attached_surgery = src /datum/surgery/Destroy() + if(operated_wound) + operated_wound.attached_surgery = null if(target) target.surgeries -= src target = null diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 584a0a189a..c4ded65e9c 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -163,9 +163,10 @@ item_flags = SURGICAL_TOOL attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY tool_behaviour = TOOL_SCALPEL toolspeed = 1 + bare_wound_bonus = 20 /obj/item/scalpel/Initialize() . = ..() @@ -180,7 +181,7 @@ force = 16 toolspeed = 0.7 light_color = LIGHT_COLOR_GREEN - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY /obj/item/scalpel/advanced/Initialize() . = ..() @@ -220,7 +221,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") toolspeed = 0.5 hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY /obj/item/scalpel/suicide_act(mob/user) user.visible_message("[user] is slitting [user.p_their()] [pick("wrists", "throat", "stomach")] with [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -244,9 +245,11 @@ throw_range = 5 custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000) attack_verb = list("attacked", "slashed", "sawed", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED tool_behaviour = TOOL_SAW toolspeed = 1 + wound_bonus = 5 + bare_wound_bonus = 10 /obj/item/circular_saw/Initialize() . = ..() @@ -269,7 +272,7 @@ custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000) toolspeed = 0.5 attack_verb = list("attacked", "slashed", "sawed", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/surgical_drapes name = "surgical drapes" @@ -374,3 +377,18 @@ advanced_surgeries |= OC.advanced_surgeries return TRUE return + +/obj/item/bonesetter + name = "bonesetter" + desc = "For setting things right." + icon = 'icons/obj/surgery.dmi' + icon_state = "bone setter" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + custom_materials = list(/datum/material/iron=5000, /datum/material/glass=2500) + flags_1 = CONDUCT_1 + item_flags = SURGICAL_TOOL + w_class = WEIGHT_CLASS_SMALL + attack_verb = list("corrected", "properly set") + tool_behaviour = TOOL_BONESET + toolspeed = 1 diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm index 38a5a27e0c..46b324e151 100644 --- a/code/modules/tgui/external.dm +++ b/code/modules/tgui/external.dm @@ -1,144 +1,188 @@ - /** - * tgui external - * - * Contains all external tgui declarations. - **/ +/** + * External tgui definitions, such as src_object APIs. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ - /** - * public - * - * Used to open and update UIs. - * If this proc is not implemented properly, the UI will not update correctly. - * - * required user mob The mob who opened/is using the UI. - * optional ui_key string The ui_key of the UI. - * optional ui datum/tgui The UI to be updated, if it exists. - * optional force_open bool If the UI should be re-opened instead of updated. - * optional master_ui datum/tgui The parent UI. - * optional state datum/ui_state The state used to determine status. - **/ -/datum/proc/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) +/** + * public + * + * Used to open and update UIs. + * If this proc is not implemented properly, the UI will not update correctly. + * + * required user mob The mob who opened/is using the UI. + * optional ui datum/tgui The UI to be updated, if it exists. + */ +/datum/proc/ui_interact(mob/user, datum/tgui/ui) return FALSE // Not implemented. - /** - * public - * - * Data to be sent to the UI. - * This must be implemented for a UI to work. - * - * required user mob The mob interacting with the UI. - * - * return list Data to be sent to the UI. - **/ +/** + * public + * + * Data to be sent to the UI. + * This must be implemented for a UI to work. + * + * required user mob The mob interacting with the UI. + * + * return list Data to be sent to the UI. + */ /datum/proc/ui_data(mob/user) return list() // Not implemented. - /** - * public - * - * Static Data to be sent to the UI. - * Static data differs from normal data in that it's large data that should be sent infrequently - * This is implemented optionally for heavy uis that would be sending a lot of redundant data - * frequently. - * Gets squished into one object on the frontend side, but the static part is cached. - * - * required user mob The mob interacting with the UI. - * - * return list Statuic Data to be sent to the UI. - **/ +/** + * public + * + * Static Data to be sent to the UI. + * + * Static data differs from normal data in that it's large data that should be + * sent infrequently. This is implemented optionally for heavy uis that would + * be sending a lot of redundant data frequently. Gets squished into one + * object on the frontend side, but the static part is cached. + * + * required user mob The mob interacting with the UI. + * + * return list Statuic Data to be sent to the UI. + */ /datum/proc/ui_static_data(mob/user) return list() /** - * public - * - * Forces an update on static data. Should be done manually whenever something happens to change static data. - * - * required user the mob currently interacting with the ui - * optional ui ui to be updated - * optional ui_key ui key of ui to be updated - * -**/ -/datum/proc/update_static_data(mob/user, datum/tgui/ui, ui_key = "main") - ui = SStgui.try_update_ui(user, src, ui_key, ui) + * public + * + * Forces an update on static data. Should be done manually whenever something + * happens to change static data. + * + * required user the mob currently interacting with the ui + * optional ui ui to be updated + */ +/datum/proc/update_static_data(mob/user, datum/tgui/ui) if(!ui) - return //If there was no ui to update, there's no static data to update either. - ui.push_data(null, ui_static_data(), TRUE) + ui = SStgui.get_open_ui(user, src) + if(ui) + ui.send_full_update() - /** - * public - * - * Called on a UI when the UI receieves a href. - * Think of this as Topic(). - * - * required action string The action/button that has been invoked by the user. - * required params list A list of parameters attached to the button. - * - * return bool If the UI should be updated or not. - **/ +/** + * public + * + * Called on a UI when the UI receieves a href. + * Think of this as Topic(). + * + * required action string The action/button that has been invoked by the user. + * required params list A list of parameters attached to the button. + * + * return bool If the UI should be updated or not. + */ /datum/proc/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) + // If UI is not interactive or usr calling Topic is not the UI user, bail. if(!ui || ui.status != UI_INTERACTIVE) - return 1 // If UI is not interactive or usr calling Topic is not the UI user, bail. + return 1 - /** - * public - * - * Called on an object when a tgui object is being created, allowing you to customise the html - * For example: inserting a custom stylesheet that you need in the head - * - * For this purpose, some tags are available in the html, to be parsed out with replacetext - * (customheadhtml) - Additions to the head tag - * - * required html the html base text - * - **/ -/datum/proc/ui_base_html(html) - return html +/** + * public + * + * Called on an object when a tgui object is being created, allowing you to + * push various assets to tgui, for examples spritesheets. + * + * return list List of asset datums or file paths. + */ +/datum/proc/ui_assets(mob/user) + return list() - /** - * private - * - * The UI's host object (usually src_object). - * This allows modules/datums to have the UI attached to them, - * and be a part of another object. - **/ +/** + * private + * + * The UI's host object (usually src_object). + * This allows modules/datums to have the UI attached to them, + * and be a part of another object. + */ /datum/proc/ui_host(mob/user) return src // Default src. - /** - * global - * - * Used to track UIs for a mob. - **/ -/mob/var/list/open_uis = list() - /** - * public - * - * Called on a UI's object when the UI is closed, not to be confused with client/verb/uiclose(), which closes the ui window - * - * - **/ -/datum/proc/ui_close() +/** + * private + * + * The UI's state controller to be used for created uis + * This is a proc over a var for memory reasons + */ +/datum/proc/ui_state(mob/user) + return GLOB.default_state - /** - * verb - * - * Called by UIs when they are closed. - * Must be a verb so winset() can call it. - * - * required uiref ref The UI that was closed. - **/ -/client/verb/uiclose(ref as text) +/** + * global + * + * Associative list of JSON-encoded shared states that were set by + * tgui clients. + */ +/datum/var/list/tgui_shared_states + +/** + * global + * + * Tracks open UIs for a user. + */ +/mob/var/list/tgui_open_uis = list() + +/** + * global + * + * Tracks open windows for a user. + */ +/client/var/list/tgui_windows = list() + +/** + * public + * + * Called on a UI's object when the UI is closed, not to be confused with + * client/verb/uiclose(), which closes the ui window + */ +/datum/proc/ui_close(mob/user) + +/** + * verb + * + * Called by UIs when they are closed. + * Must be a verb so winset() can call it. + * + * required uiref ref The UI that was closed. + */ +/client/verb/uiclose(window_id as text) // Name the verb, and hide it from the user panel. set name = "uiclose" - set hidden = 1 + set hidden = TRUE + var/mob/user = src && src.mob + if(!user) + return + // Close all tgui datums based on window_id. + SStgui.force_close_window(user, window_id) - // Get the UI based on the ref. - var/datum/tgui/ui = locate(ref) - - // If we found the UI, close it. - if(istype(ui)) - ui.close() - // Unset machine just to be sure. - if(src && src.mob) - src.mob.unset_machine() +/** + * Middleware for /client/Topic. + * + * return bool Whether the topic is passed (TRUE), or cancelled (FALSE). + */ +/proc/tgui_Topic(href_list) + // Skip non-tgui topics + if(!href_list["tgui"]) + return TRUE + var/type = href_list["type"] + // Unconditionally collect tgui logs + if(type == "log") + log_tgui(usr, href_list["message"]) + // Locate window + var/window_id = href_list["window_id"] + var/datum/tgui_window/window + if(window_id) + window = usr.client.tgui_windows[window_id] + if(!window) + log_tgui(usr, "Error: Couldn't find the window datum, force closing.") + SStgui.force_close_window(usr, window_id) + return FALSE + // Decode payload + var/payload + if(href_list["payload"]) + payload = json_decode(href_list["payload"]) + // Pass message to window + if(window) + window.on_message(type, payload, href_list) + return FALSE diff --git a/code/modules/tgui/states.dm b/code/modules/tgui/states.dm index 723e5f90ed..fa88cc1338 100644 --- a/code/modules/tgui/states.dm +++ b/code/modules/tgui/states.dm @@ -1,19 +1,21 @@ - /** - * tgui states - * - * Base state and helpers for states. Just does some sanity checks, implement a state for in-depth checks. - **/ +/** + * Base state and helpers for states. Just does some sanity checks, + * implement a proper state for in-depth checks. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ - /** - * public - * - * Checks the UI state for a mob. - * - * required user mob The mob who opened/is using the UI. - * required state datum/ui_state The state to check. - * - * return UI_state The state of the UI. - **/ +/** + * public + * + * Checks the UI state for a mob. + * + * required user mob The mob who opened/is using the UI. + * required state datum/ui_state The state to check. + * + * return UI_state The state of the UI. + */ /datum/proc/ui_status(mob/user, datum/ui_state/state) var/src_object = ui_host(user) . = UI_CLOSE @@ -26,92 +28,109 @@ . = max(., UI_INTERACTIVE) // Regular ghosts can always at least view if in range. - var/clientviewlist = getviewsize(user.client.view) - if(get_dist(src_object, user) < max(clientviewlist[1],clientviewlist[2])) - . = max(., UI_UPDATE) + if(user.client) + var/clientviewlist = getviewsize(user.client.view) + if(get_dist(src_object, user) < max(clientviewlist[1], clientviewlist[2])) + . = max(., UI_UPDATE) // Check if the state allows interaction var/result = state.can_use_topic(src_object, user) . = max(., result) - /** - * private - * - * Checks if a user can use src_object's UI, and returns the state. - * Can call a mob proc, which allows overrides for each mob. - * - * required src_object datum The object/datum which owns the UI. - * required user mob The mob who opened/is using the UI. - * - * return UI_state The state of the UI. - **/ +/** + * private + * + * Checks if a user can use src_object's UI, and returns the state. + * Can call a mob proc, which allows overrides for each mob. + * + * required src_object datum The object/datum which owns the UI. + * required user mob The mob who opened/is using the UI. + * + * return UI_state The state of the UI. + */ /datum/ui_state/proc/can_use_topic(src_object, mob/user) - return UI_CLOSE // Don't allow interaction by default. + // Don't allow interaction by default. + return UI_CLOSE - /** - * public - * - * Standard interaction/sanity checks. Different mob types may have overrides. - * - * return UI_state The state of the UI. - **/ +/** + * public + * + * Standard interaction/sanity checks. Different mob types may have overrides. + * + * return UI_state The state of the UI. + */ /mob/proc/shared_ui_interaction(src_object) - if(!client) // Close UIs if mindless. + // Close UIs if mindless. + if(!client) return UI_CLOSE - else if(stat) // Disable UIs if unconcious. + // Disable UIs if unconcious. + else if(stat) return UI_DISABLED - else if(incapacitated() || lying) // Update UIs if incapicitated but concious. + // Update UIs if incapicitated but concious. + else if(incapacitated()) return UI_UPDATE return UI_INTERACTIVE +/mob/living/shared_ui_interaction(src_object) + . = ..() + if(!(mobility_flags & MOBILITY_UI) && . == UI_INTERACTIVE) + return UI_UPDATE + /mob/living/silicon/ai/shared_ui_interaction(src_object) - if(lacks_power()) // Disable UIs if the AI is unpowered. + // Disable UIs if the AI is unpowered. + if(lacks_power()) return UI_DISABLED return ..() /mob/living/silicon/robot/shared_ui_interaction(src_object) - if(!cell || cell.charge <= 0 || locked_down) // Disable UIs if the Borg is unpowered or locked. + // Disable UIs if the Borg is unpowered or locked. + if(!cell || cell.charge <= 0 || locked_down) return UI_DISABLED return ..() /** - * public - * - * Check the distance for a living mob. - * Really only used for checks outside the context of a mob. - * Otherwise, use shared_living_ui_distance(). - * - * required src_object The object which owns the UI. - * required user mob The mob who opened/is using the UI. - * - * return UI_state The state of the UI. - **/ + * public + * + * Check the distance for a living mob. + * Really only used for checks outside the context of a mob. + * Otherwise, use shared_living_ui_distance(). + * + * required src_object The object which owns the UI. + * required user mob The mob who opened/is using the UI. + * + * return UI_state The state of the UI. + */ /atom/proc/contents_ui_distance(src_object, mob/living/user) - return user.shared_living_ui_distance(src_object) // Just call this mob's check. + // Just call this mob's check. + return user.shared_living_ui_distance(src_object) - /** - * public - * - * Distance versus interaction check. - * - * required src_object atom/movable The object which owns the UI. - * - * return UI_state The state of the UI. - **/ -/mob/living/proc/shared_living_ui_distance(atom/movable/src_object) - if(!(src_object in fov_view())) // If the object is obscured, close it. +/** + * public + * + * Distance versus interaction check. + * + * required src_object atom/movable The object which owns the UI. + * + * return UI_state The state of the UI. + */ +/mob/living/proc/shared_living_ui_distance(atom/movable/src_object, viewcheck = TRUE) + // If the object is obscured, close it. + if(viewcheck && !(src_object in view(src))) return UI_CLOSE - var/dist = get_dist(src_object, src) - if(dist <= 1 || src_object.hasSiliconAccessInArea(src)) // Open and interact if 1-0 tiles away. + // Open and interact if 1-0 tiles away. + if(dist <= 1) return UI_INTERACTIVE - else if(dist <= 2) // View only if 2-3 tiles away. + // View only if 2-3 tiles away. + else if(dist <= 2) return UI_UPDATE - else if(dist <= 5) // Disable if 5 tiles away. + // Disable if 5 tiles away. + else if(dist <= 5) return UI_DISABLED - return UI_CLOSE // Otherwise, we got nothing. + // Otherwise, we got nothing. + return UI_CLOSE -/mob/living/carbon/human/shared_living_ui_distance(atom/movable/src_object) +/mob/living/carbon/human/shared_living_ui_distance(atom/movable/src_object, viewcheck = TRUE) if(dna.check_mutation(TK) && tkMaxRangeCheck(src, src_object)) return UI_INTERACTIVE return ..() diff --git a/code/modules/tgui/states/admin.dm b/code/modules/tgui/states/admin.dm index 945a864430..227a294078 100644 --- a/code/modules/tgui/states/admin.dm +++ b/code/modules/tgui/states/admin.dm @@ -1,8 +1,11 @@ - /** - * tgui state: admin_state - * - * Checks that the user is an admin, end-of-story. - **/ +/** + * tgui state: admin_state + * + * Checks that the user is an admin, end-of-story. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(admin_state, /datum/ui_state/admin_state, new) diff --git a/code/modules/tgui/states/always.dm b/code/modules/tgui/states/always.dm index b6c689d5d8..210f0896a2 100644 --- a/code/modules/tgui/states/always.dm +++ b/code/modules/tgui/states/always.dm @@ -1,9 +1,11 @@ - - /** - * tgui state: always_state - * - * Always grants the user UI_INTERACTIVE. Period. - **/ +/** + * tgui state: always_state + * + * Always grants the user UI_INTERACTIVE. Period. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(always_state, /datum/ui_state/always_state, new) diff --git a/code/modules/tgui/states/conscious.dm b/code/modules/tgui/states/conscious.dm index 4323c1391c..670ca7c07e 100644 --- a/code/modules/tgui/states/conscious.dm +++ b/code/modules/tgui/states/conscious.dm @@ -1,8 +1,11 @@ - /** - * tgui state: conscious_state - * - * Only checks if the user is conscious. - **/ +/** + * tgui state: conscious_state + * + * Only checks if the user is conscious. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(conscious_state, /datum/ui_state/conscious_state, new) diff --git a/code/modules/tgui/states/contained.dm b/code/modules/tgui/states/contained.dm index 7387f7e6cb..1eb8edba25 100644 --- a/code/modules/tgui/states/contained.dm +++ b/code/modules/tgui/states/contained.dm @@ -1,8 +1,11 @@ - /** - * tgui state: contained_state - * - * Checks that the user is inside the src_object. - **/ +/** + * tgui state: contained_state + * + * Checks that the user is inside the src_object. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(contained_state, /datum/ui_state/contained_state, new) diff --git a/code/modules/tgui/states/deep_inventory.dm b/code/modules/tgui/states/deep_inventory.dm index 06bdb92f3a..a2b9276a59 100644 --- a/code/modules/tgui/states/deep_inventory.dm +++ b/code/modules/tgui/states/deep_inventory.dm @@ -1,8 +1,12 @@ - /** - * tgui state: deep_inventory_state - * - * Checks that the src_object is in the user's deep (backpack, box, toolbox, etc) inventory. - **/ +/** + * tgui state: deep_inventory_state + * + * Checks that the src_object is in the user's deep + * (backpack, box, toolbox, etc) inventory. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(deep_inventory_state, /datum/ui_state/deep_inventory_state, new) diff --git a/code/modules/tgui/states/default.dm b/code/modules/tgui/states/default.dm index c6741f20b8..367e57beff 100644 --- a/code/modules/tgui/states/default.dm +++ b/code/modules/tgui/states/default.dm @@ -1,8 +1,12 @@ - /** - * tgui state: default_state - * - * Checks a number of things -- mostly physical distance for humans and view for robots. - **/ +/** + * tgui state: default_state + * + * Checks a number of things -- mostly physical distance for humans + * and view for robots. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(default_state, /datum/ui_state/default, new) diff --git a/code/modules/tgui/states/hands.dm b/code/modules/tgui/states/hands.dm index 5da0e5d500..1c885ed414 100644 --- a/code/modules/tgui/states/hands.dm +++ b/code/modules/tgui/states/hands.dm @@ -1,8 +1,11 @@ - /** - * tgui state: hands_state - * - * Checks that the src_object is in the user's hands. - **/ +/** + * tgui state: hands_state + * + * Checks that the src_object is in the user's hands. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(hands_state, /datum/ui_state/hands_state, new) diff --git a/code/modules/tgui/states/human_adjacent.dm b/code/modules/tgui/states/human_adjacent.dm index 0ab20b36ff..2ac7c8637b 100644 --- a/code/modules/tgui/states/human_adjacent.dm +++ b/code/modules/tgui/states/human_adjacent.dm @@ -1,10 +1,12 @@ - - /** - * tgui state: human_adjacent_state - * - * In addition to default checks, only allows interaction for a - * human adjacent user. - **/ +/** + * tgui state: human_adjacent_state + * + * In addition to default checks, only allows interaction for a + * human adjacent user. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(human_adjacent_state, /datum/ui_state/human_adjacent_state, new) diff --git a/code/modules/tgui/states/inventory.dm b/code/modules/tgui/states/inventory.dm index b8b1ad3b6a..dc5dd0d57e 100644 --- a/code/modules/tgui/states/inventory.dm +++ b/code/modules/tgui/states/inventory.dm @@ -1,8 +1,12 @@ - /** - * tgui state: inventory_state - * - * Checks that the src_object is in the user's top-level (hand, ear, pocket, belt, etc) inventory. - **/ +/** + * tgui state: inventory_state + * + * Checks that the src_object is in the user's top-level + * (hand, ear, pocket, belt, etc) inventory. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(inventory_state, /datum/ui_state/inventory_state, new) diff --git a/code/modules/tgui/states/language_menu.dm b/code/modules/tgui/states/language_menu.dm index fedc4320e4..6389b05cd5 100644 --- a/code/modules/tgui/states/language_menu.dm +++ b/code/modules/tgui/states/language_menu.dm @@ -1,6 +1,9 @@ - /** - * tgui state: language_menu_state - */ +/** + * tgui state: language_menu_state + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(language_menu_state, /datum/ui_state/language_menu, new) diff --git a/code/modules/tgui/states/not_incapacitated.dm b/code/modules/tgui/states/not_incapacitated.dm index 12fe266bc5..16dcb7881e 100644 --- a/code/modules/tgui/states/not_incapacitated.dm +++ b/code/modules/tgui/states/not_incapacitated.dm @@ -1,16 +1,19 @@ - /** - * tgui state: not_incapacitated_state - * - * Checks that the user isn't incapacitated - **/ +/** + * tgui state: not_incapacitated_state + * + * Checks that the user isn't incapacitated + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(not_incapacitated_state, /datum/ui_state/not_incapacitated_state, new) - /** - * tgui state: not_incapacitated_turf_state - * - * Checks that the user isn't incapacitated and that their loc is a turf - **/ +/** + * tgui state: not_incapacitated_turf_state + * + * Checks that the user isn't incapacitated and that their loc is a turf + */ GLOBAL_DATUM_INIT(not_incapacitated_turf_state, /datum/ui_state/not_incapacitated_state, new(no_turfs = TRUE)) @@ -24,6 +27,10 @@ GLOBAL_DATUM_INIT(not_incapacitated_turf_state, /datum/ui_state/not_incapacitate /datum/ui_state/not_incapacitated_state/can_use_topic(src_object, mob/user) if(user.stat) return UI_CLOSE - if(user.incapacitated() || user.lying || (turf_check && !isturf(user.loc))) + if(user.incapacitated() || (turf_check && !isturf(user.loc))) return UI_DISABLED - return UI_INTERACTIVE \ No newline at end of file + if(isliving(user)) + var/mob/living/L = user + if(!(L.mobility_flags & MOBILITY_STAND)) + return UI_DISABLED + return UI_INTERACTIVE diff --git a/code/modules/tgui/states/notcontained.dm b/code/modules/tgui/states/notcontained.dm index 77a7fe01b0..1d4e6aec19 100644 --- a/code/modules/tgui/states/notcontained.dm +++ b/code/modules/tgui/states/notcontained.dm @@ -1,8 +1,12 @@ - /** - * tgui state: notcontained_state - * - * Checks that the user is not inside src_object, and then makes the default checks. - **/ +/** + * tgui state: notcontained_state + * + * Checks that the user is not inside src_object, and then makes the + * default checks. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(notcontained_state, /datum/ui_state/notcontained_state, new) diff --git a/code/modules/tgui/states/observer.dm b/code/modules/tgui/states/observer.dm index ade0ce66bb..d105de1c0c 100644 --- a/code/modules/tgui/states/observer.dm +++ b/code/modules/tgui/states/observer.dm @@ -1,8 +1,11 @@ - /** - * tgui state: observer_state - * - * Checks that the user is an observer/ghost. - **/ +/** + * tgui state: observer_state + * + * Checks that the user is an observer/ghost. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(observer_state, /datum/ui_state/observer_state, new) diff --git a/code/modules/tgui/states/physical.dm b/code/modules/tgui/states/physical.dm index 3b13dc5b3d..3073039d14 100644 --- a/code/modules/tgui/states/physical.dm +++ b/code/modules/tgui/states/physical.dm @@ -1,8 +1,11 @@ - /** - * tgui state: physical_state - * - * Short-circuits the default state to only check physical distance. - */ +/** + * tgui state: physical_state + * + * Short-circuits the default state to only check physical distance. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(physical_state, /datum/ui_state/physical, new) @@ -23,6 +26,7 @@ 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 * @@ -40,10 +44,10 @@ GLOBAL_DATUM_INIT(physical_obscured_state, /datum/ui_state/physical_obscured_sta return UI_CLOSE /mob/living/physical_obscured_can_use_topic(src_object) - return shared_living_ui_distance(src_object) + return shared_living_ui_distance(src_object, viewcheck = FALSE) /mob/living/silicon/physical_obscured_can_use_topic(src_object) - return max(UI_UPDATE, shared_living_ui_distance(src_object)) // Silicons can always see. + return max(UI_UPDATE, shared_living_ui_distance(src_object, viewcheck = FALSE)) // 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 + return UI_UPDATE // AIs are not physical. diff --git a/code/modules/tgui/states/self.dm b/code/modules/tgui/states/self.dm index 10849772c6..4b6e3b9fd9 100644 --- a/code/modules/tgui/states/self.dm +++ b/code/modules/tgui/states/self.dm @@ -1,8 +1,11 @@ - /** - * tgui state: self_state - * - * Only checks that the user and src_object are the same. - **/ +/** + * tgui state: self_state + * + * Only checks that the user and src_object are the same. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(self_state, /datum/ui_state/self_state, new) diff --git a/code/modules/tgui/states/zlevel.dm b/code/modules/tgui/states/zlevel.dm index 6ccfd0fe7d..64ea2fa1c0 100644 --- a/code/modules/tgui/states/zlevel.dm +++ b/code/modules/tgui/states/zlevel.dm @@ -1,8 +1,11 @@ - /** - * tgui state: z_state - * - * Only checks that the Z-level of the user and src_object are the same. - **/ +/** + * tgui state: z_state + * + * Only checks that the Z-level of the user and src_object are the same. + * + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ GLOBAL_DATUM_INIT(z_state, /datum/ui_state/z_state, new) diff --git a/code/modules/tgui/subsystem.dm b/code/modules/tgui/subsystem.dm deleted file mode 100644 index 90a00fb607..0000000000 --- a/code/modules/tgui/subsystem.dm +++ /dev/null @@ -1,247 +0,0 @@ - /** - * tgui subsystem - * - * Contains all tgui state and subsystem code. - **/ - - /** - * public - * - * Get a open UI given a user, src_object, and ui_key and try to update it with data. - * - * required user mob The mob who opened/is using the UI. - * required src_object datum The object/datum which owns the UI. - * required ui_key string The ui_key of the UI. - * optional ui datum/tgui The UI to be updated, if it exists. - * optional force_open bool If the UI should be re-opened instead of updated. - * - * return datum/tgui The found UI. - **/ -/datum/controller/subsystem/tgui/proc/try_update_ui(mob/user, datum/src_object, ui_key, datum/tgui/ui, force_open = FALSE) - if(isnull(ui)) // No UI was passed, so look for one. - ui = get_open_ui(user, src_object, ui_key) - - if(!isnull(ui)) - var/data = src_object.ui_data(user) // Get data from the src_object. - if(!force_open) // UI is already open; update it. - ui.push_data(data) - else // Re-open it anyways. - ui.reinitialize(null, data) - return ui // We found the UI, return it. - else - return null // We couldn't find a UI. - - /** - * private - * - * Get a open UI given a user, src_object, and ui_key. - * - * required user mob The mob who opened/is using the UI. - * required src_object datum The object/datum which owns the UI. - * required ui_key string The ui_key of the UI. - * - * return datum/tgui The found UI. - **/ -/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object, ui_key) - var/src_object_key = "[REF(src_object)]" - if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return null // No UIs open. - else if(isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list)) - return null // No UIs open for this object. - - for(var/datum/tgui/ui in open_uis[src_object_key][ui_key]) // Find UIs for this object. - if(ui.user == user) // Make sure we have the right user - return ui - - return null // Couldn't find a UI! - - /** - * private - * - * Update all UIs attached to src_object. - * - * required src_object datum The object/datum which owns the UIs. - * - * return int The number of UIs updated. - **/ -/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object) - var/src_object_key = "[REF(src_object)]" - if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return 0 // Couldn't find any UIs for this object. - - var/update_count = 0 - for(var/ui_key in open_uis[src_object_key]) - for(var/datum/tgui/ui in open_uis[src_object_key][ui_key]) - if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) // Check the UI is valid. - ui.process(force = 1) // Update the UI. - update_count++ // Count each UI we update. - return update_count - - /** - * private - * - * Close all UIs attached to src_object. - * - * required src_object datum The object/datum which owns the UIs. - * - * return int The number of UIs closed. - **/ -/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object) - var/src_object_key = "[REF(src_object)]" - if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return 0 // Couldn't find any UIs for this object. - - var/close_count = 0 - for(var/ui_key in open_uis[src_object_key]) - for(var/datum/tgui/ui in open_uis[src_object_key][ui_key]) - if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) // Check the UI is valid. - ui.close() // Close the UI. - close_count++ // Count each UI we close. - return close_count - - /** - * private - * - * Close *ALL* UIs - * - * return int The number of UIs closed. - **/ -/datum/controller/subsystem/tgui/proc/close_all_uis() - var/close_count = 0 - for(var/src_object_key in open_uis) - for(var/ui_key in open_uis[src_object_key]) - for(var/datum/tgui/ui in open_uis[src_object_key][ui_key]) - if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user)) // Check the UI is valid. - ui.close() // Close the UI. - close_count++ // Count each UI we close. - return close_count - - /** - * private - * - * Update all UIs belonging to a user. - * - * required user mob The mob who opened/is using the UI. - * optional src_object datum If provided, only update UIs belonging this src_object. - * optional ui_key string If provided, only update UIs with this UI key. - * - * return int The number of UIs updated. - **/ -/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object = null, ui_key = null) - if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0) - return 0 // Couldn't find any UIs for this user. - - var/update_count = 0 - for(var/datum/tgui/ui in user.open_uis) - if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key)) - ui.process(force = 1) // Update the UI. - update_count++ // Count each UI we upadte. - return update_count - - /** - * private - * - * Close all UIs belonging to a user. - * - * required user mob The mob who opened/is using the UI. - * optional src_object datum If provided, only close UIs belonging this src_object. - * optional ui_key string If provided, only close UIs with this UI key. - * - * return int The number of UIs closed. - **/ -/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object = null, ui_key = null) - if(isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0) - return 0 // Couldn't find any UIs for this user. - - var/close_count = 0 - for(var/datum/tgui/ui in user.open_uis) - if((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key)) - ui.close() // Close the UI. - close_count++ // Count each UI we close. - return close_count - - /** - * private - * - * Add a UI to the list of open UIs. - * - * required ui datum/tgui The UI to be added. - **/ -/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui) - var/src_object_key = "[REF(ui.src_object)]" - if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - open_uis[src_object_key] = list(ui.ui_key = list()) // Make a list for the ui_key and src_object. - else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list)) - open_uis[src_object_key][ui.ui_key] = list() // Make a list for the ui_key. - - // Append the UI to all the lists. - ui.user.open_uis |= ui - var/list/uis = open_uis[src_object_key][ui.ui_key] - uis |= ui - processing_uis |= ui - - /** - * private - * - * Remove a UI from the list of open UIs. - * - * required ui datum/tgui The UI to be removed. - * - * return bool If the UI was removed or not. - **/ -/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui) - var/src_object_key = "[REF(ui.src_object)]" - if(isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list)) - return 0 // It wasn't open. - else if(isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list)) - return 0 // It wasn't open. - - processing_uis.Remove(ui) // Remove it from the list of processing UIs. - if(ui.user) // If the user exists, remove it from them too. - ui.user.open_uis.Remove(ui) - var/Ukey = ui.ui_key - var/list/uis = open_uis[src_object_key][Ukey] // Remove it from the list of open UIs. - uis.Remove(ui) - if(!uis.len) - var/list/uiobj = open_uis[src_object_key] - uiobj.Remove(Ukey) - if(!uiobj.len) - open_uis.Remove(src_object_key) - - return 1 // Let the caller know we did it. - - /** - * private - * - * Handle client logout, by closing all their UIs. - * - * required user mob The mob which logged out. - * - * return int The number of UIs closed. - **/ -/datum/controller/subsystem/tgui/proc/on_logout(mob/user) - return close_user_uis(user) - - /** - * private - * - * Handle clients switching mobs, by transferring their UIs. - * - * required user source The client's original mob. - * required user target The client's new mob. - * - * return bool If the UIs were transferred. - **/ -/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target) - if(!source || isnull(source.open_uis) || !istype(source.open_uis, /list) || open_uis.len == 0) - return 0 // The old mob had no open UIs. - - if(isnull(target.open_uis) || !istype(target.open_uis, /list)) - target.open_uis = list() // Create a list for the new mob if needed. - - for(var/datum/tgui/ui in source.open_uis) - ui.user = target // Inform the UIs of their new owner. - target.open_uis.Add(ui) // Transfer all the UIs. - - source.open_uis.Cut() // Clear the old list. - return 1 // Let the caller know we did it. diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index 55fe8f0bb5..d0d5ff8ebb 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -1,12 +1,11 @@ - /** - * tgui - * - * /tg/station user interface library - **/ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ - /** - * tgui datum (represents a UI). - **/ +/** + * tgui datum (represents a UI). + */ /datum/tgui /// The mob who opened/is using the UI. var/mob/user @@ -14,351 +13,282 @@ var/datum/src_object /// The title of te UI. var/title - /// The ui_key of the UI. This allows multiple UIs for one src_object. - var/ui_key /// The window_id for browse() and onclose(). - var/window_id - /// The window width. - var/width = 0 - /// The window height - var/height = 0 - /// The style to be used for this UI. - var/style = "nanotrasen" + var/datum/tgui_window/window + /// Key that is used for remembering the window geometry. + var/window_key + /// Deprecated: Window size. + var/window_size /// The interface (template) to be used for this UI. var/interface /// Update the UI every MC tick. var/autoupdate = TRUE /// If the UI has been initialized yet. var/initialized = FALSE - /// The data (and datastructure) used to initialize the UI. - var/list/initial_data - /// The static data used to initialize the UI. - var/list/initial_static_data + /// Time of opening the window. + var/opened_at + /// Stops further updates when close() was called. + var/closing = FALSE /// The status/visibility of the UI. var/status = UI_INTERACTIVE /// Topic state used to determine status/interactability. var/datum/ui_state/state = null - /// The parent UI. - var/datum/tgui/master_ui - /// Children of this UI. - var/list/datum/tgui/children = list() - var/custom_browser_id = FALSE - var/ui_screen = "home" - /** - * public - * - * Create a new UI. - * - * required user mob The mob who opened/is using the UI. - * required src_object datum The object or datum which owns the UI. - * required ui_key string The ui_key of the UI. - * required interface string The interface used to render the UI. - * optional title string The title of the UI. - * optional width int The window width. - * optional height int The window height. - * optional master_ui datum/tgui The parent UI. - * optional state datum/ui_state The state used to determine status. - * - * return datum/tgui The requested UI. - **/ -/datum/tgui/New(mob/user, datum/src_object, ui_key, interface, title, width = 0, height = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state, browser_id = null) +/** + * public + * + * Create a new UI. + * + * required user mob The mob who opened/is using the UI. + * required src_object datum The object or datum which owns the UI. + * required interface string The interface used to render the UI. + * optional title string The title of the UI. + * optional ui_x int Deprecated: Window width. + * optional ui_y int Deprecated: Window height. + * + * return datum/tgui The requested UI. + */ +/datum/tgui/New(mob/user, datum/src_object, interface, title, ui_x, ui_y) + log_tgui(user, "new [interface] fancy [user.client.prefs.tgui_fancy]") src.user = user src.src_object = src_object - src.ui_key = ui_key - src.window_id = browser_id ? browser_id : "[REF(src_object)]-[ui_key]" // DO NOT replace with \ref here. src_object could potentially be tagged - src.custom_browser_id = browser_id ? TRUE : FALSE - - set_interface(interface) - + src.window_key = "[REF(src_object)]-main" + src.interface = interface if(title) - src.title = sanitize(title) - if(width) - src.width = width - if(height) - src.height = height + src.title = title + src.state = src_object.ui_state() + // Deprecated + if(ui_x && ui_y) + src.window_size = list(ui_x, ui_y) - src.master_ui = master_ui - if(master_ui) - master_ui.children += src - src.state = state - - var/datum/asset/assets = get_asset_datum(/datum/asset/group/tgui) - assets.send(user) - - /** - * public - * - * Open this UI (and initialize it with data). - **/ +/** + * public + * + * Open this UI (and initialize it with data). + */ /datum/tgui/proc/open() if(!user.client) - return // Bail if there is no client. - - update_status(push = FALSE) // Update the window status. + return null + if(window) + return null + process_status() if(status < UI_UPDATE) - return // Bail if we're not supposed to open. - - var/window_size - if(width && height) // If we have a width and height, use them. - window_size = "size=[width]x[height];" + return null + window = SStgui.request_pooled_window(user) + if(!window) + return null + opened_at = world.time + window.acquire_lock(src) + if(!window.is_ready()) + window.initialize(inline_assets = list( + get_asset_datum(/datum/asset/simple/tgui), + )) else - window_size = "" - - // Remove titlebar and resize handles for a fancy window - var/have_title_bar - if(user.client.prefs.tgui_fancy) - have_title_bar = "titlebar=0;can_resize=0;" - else - have_title_bar = "titlebar=1;can_resize=1;" - - // Generate page html - var/html - html = SStgui.basehtml - // Allow the src object to override the html if needed - html = src_object.ui_base_html(html) - // Replace template tokens with important UI data - // NOTE: Intentional \ref usage; tgui datums can't/shouldn't - // be tagged, so this is an effective unwrap - html = replacetextEx(html, "\[ref]", "\ref[src]") - html = replacetextEx(html, "\[style]", style) - - // Open the window. - user << browse(html, "window=[window_id];can_minimize=0;auto_format=0;[window_size][have_title_bar]") - if (!custom_browser_id) - // Instruct the client to signal UI when the window is closed. - // NOTE: Intentional \ref usage; tgui datums can't/shouldn't - // be tagged, so this is an effective unwrap - winset(user, window_id, "on-close=\"uiclose \ref[src]\"") - - if(!initial_data) - initial_data = src_object.ui_data(user) - if(!initial_static_data) - initial_static_data = src_object.ui_static_data(user) - + window.send_message("ping") + window.send_asset(get_asset_datum(/datum/asset/simple/fontawesome)) + for(var/datum/asset/asset in src_object.ui_assets(user)) + window.send_asset(asset) + window.send_message("update", get_payload( + with_data = TRUE, + with_static_data = TRUE)) SStgui.on_open(src) - /** - * public - * - * Reinitialize the UI. - * (Possibly with a new interface and/or data). - * - * optional template string The name of the new interface. - * optional data list The new initial data. - **/ -/datum/tgui/proc/reinitialize(interface, list/data, list/static_data) - if(interface) - set_interface(interface) // Set a new interface. - if(data) - initial_data = data - if(static_data) - initial_static_data = static_data - open() - - /** - * public - * - * Close the UI, and all its children. - **/ -/datum/tgui/proc/close() - user << browse(null, "window=[window_id]") // Close the window. - src_object.ui_close() - SStgui.on_close(src) - for(var/datum/tgui/child in children) // Loop through and close all children. - child.close() - children.Cut() +/** + * public + * + * Close the UI. + * + * optional can_be_suspended bool + */ +/datum/tgui/proc/close(can_be_suspended = TRUE) + if(closing) + return + closing = TRUE + // If we don't have window_id, open proc did not have the opportunity + // to finish, therefore it's safe to skip this whole block. + if(window) + // Windows you want to keep are usually blue screens of death + // and we want to keep them around, to allow user to read + // the error message properly. + window.release_lock() + window.close(can_be_suspended) + src_object.ui_close(user) + SStgui.on_close(src) state = null - master_ui = null qdel(src) - /** - * public - * - * Set the style for this UI. - * - * required style string The new UI style. - **/ -/datum/tgui/proc/set_style(style) - src.style = lowertext(style) +/** + * public + * + * Enable/disable auto-updating of the UI. + * + * required value bool Enable/disable auto-updating. + */ +/datum/tgui/proc/set_autoupdate(autoupdate) + src.autoupdate = autoupdate - /** - * public - * - * Set the interface (template) for this UI. - * - * required interface string The new UI interface. - **/ -/datum/tgui/proc/set_interface(interface) - src.interface = lowertext(interface) +/** + * public + * + * Replace current ui.state with a new one. + * + * required state datum/ui_state/state Next state + */ +/datum/tgui/proc/set_state(datum/ui_state/state) + src.state = state - /** - * public - * - * Enable/disable auto-updating of the UI. - * - * required state bool Enable/disable auto-updating. - **/ -/datum/tgui/proc/set_autoupdate(state = TRUE) - autoupdate = state +/** + * public + * + * Makes an asset available to use in tgui. + * + * required asset datum/asset + */ +/datum/tgui/proc/send_asset(datum/asset/asset) + if(!window) + CRASH("send_asset() can only be called after open().") + window.send_asset(asset) - /** - * private - * - * Package the data to send to the UI, as JSON. - * This includes the UI data and config_data. - * - * return string The packaged JSON. - **/ -/datum/tgui/proc/get_json(list/data, list/static_data) +/** + * public + * + * Send a full update to the client (includes static data). + * + * optional custom_data list Custom data to send instead of ui_data. + * optional force bool Send an update even if UI is not interactive. + */ +/datum/tgui/proc/send_full_update(custom_data, force) + if(!user.client || !initialized || closing) + return + var/should_update_data = force || status >= UI_UPDATE + window.send_message("update", get_payload( + custom_data, + with_data = should_update_data, + with_static_data = TRUE)) + +/** + * public + * + * Send a partial update to the client (excludes static data). + * + * optional custom_data list Custom data to send instead of ui_data. + * optional force bool Send an update even if UI is not interactive. + */ +/datum/tgui/proc/send_update(custom_data, force) + if(!user.client || !initialized || closing) + return + var/should_update_data = force || status >= UI_UPDATE + window.send_message("update", get_payload( + custom_data, + with_data = should_update_data)) + +/** + * private + * + * Package the data to send to the UI, as JSON. + * + * return list + */ +/datum/tgui/proc/get_payload(custom_data, with_data, with_static_data) var/list/json_data = list() - json_data["config"] = list( "title" = title, "status" = status, - "screen" = ui_screen, - "style" = style, "interface" = interface, - "fancy" = user.client.prefs.tgui_fancy, - "locked" = user.client.prefs.tgui_lock && !custom_browser_id, - "observer" = isobserver(user), - "window" = window_id, - // NOTE: Intentional \ref usage; tgui datums can't/shouldn't - // be tagged, so this is an effective unwrap - "ref" = "\ref[src]" + "window" = list( + "key" = window_key, + "size" = window_size, + "fancy" = user.client.prefs.tgui_fancy, + "locked" = user.client.prefs.tgui_lock + ), + "user" = list( + "name" = "[user]", + "ckey" = "[user.ckey]", + "observer" = isobserver(user) + ) ) - - if(!isnull(data)) + var/data = custom_data || with_data && src_object.ui_data(user) + if(data) json_data["data"] = data - if(!isnull(static_data)) + var/static_data = with_static_data && src_object.ui_static_data(user) + if(static_data) json_data["static_data"] = static_data + if(src_object.tgui_shared_states) + json_data["shared"] = src_object.tgui_shared_states + return json_data - // Generate the JSON. - var/json = json_encode(json_data) - // Strip #255/improper. - json = replacetext(json, "\proper", "") - json = replacetext(json, "\improper", "") - return json - - /** - * private - * - * Handle clicks from the UI. - * Call the src_object's ui_act() if status is UI_INTERACTIVE. - * If the src_object's ui_act() returns 1, update all UIs attacked to it. - **/ -/datum/tgui/Topic(href, href_list) - if(user != usr) - return // Something is not right here. - - var/action = href_list["action"] - var/params = href_list; params -= "action" - - switch(action) - if("tgui:initialize") - user << output(url_encode(get_json(initial_data, initial_static_data)), "[custom_browser_id ? window_id : "[window_id].browser"]:initialize") - initialized = TRUE - if("tgui:view") - if(params["screen"]) - ui_screen = params["screen"] - SStgui.update_uis(src_object) - if("tgui:log") - // Force window to show frills on fatal errors - if(params["fatal"]) - winset(user, window_id, "titlebar=1;can-resize=1;size=600x600") - if("tgui:link") - user << link(params["url"]) - if("tgui:fancy") - user.client.prefs.tgui_fancy = TRUE - if("tgui:nofrills") - user.client.prefs.tgui_fancy = FALSE - else - update_status(push = FALSE) // Update the window state. - if(src_object.ui_act(action, params, src, state)) // Call ui_act() on the src_object. - SStgui.update_uis(src_object) // Update if the object requested it. - - /** - * private - * - * Update the UI. - * Only updates the data if update is true, otherwise only updates the status. - * - * optional force bool If the UI should be forced to update. - **/ +/** + * private + * + * Run an update cycle for this UI. Called internally by SStgui + * every second or so. + */ /datum/tgui/process(force = FALSE) + if(closing) + return var/datum/host = src_object.ui_host(user) - if(!src_object || !host || !user) // If the object or user died (or something else), abort. + // If the object or user died (or something else), abort. + if(!src_object || !host || !user || !window) + close(can_be_suspended = FALSE) + return + // Validate ping + if(!initialized && world.time - opened_at > TGUI_PING_TIMEOUT) + log_tgui(user, \ + "Error: Zombie window detected, killing it with fire.\n" \ + + "window_id: [window.id]\n" \ + + "opened_at: [opened_at]\n" \ + + "world.time: [world.time]") + close(can_be_suspended = FALSE) + return + // Update through a normal call to ui_interact + if(status != UI_DISABLED && (autoupdate || force)) + src_object.ui_interact(user, src) + return + // Update status only + var/needs_update = process_status() + if(status <= UI_CLOSE) close() return + if(needs_update) + window.send_message("update", get_payload()) - if(status && (force || autoupdate)) - update() // Update the UI if the status and update settings allow it. - else - update_status(push = TRUE) // Otherwise only update status. - - /** - * private - * - * Push data to an already open UI. - * - * required data list The data to send. - * optional force bool If the update should be sent regardless of state. - **/ -/datum/tgui/proc/push_data(data, static_data, force = FALSE) - update_status(push = FALSE) // Update the window state. - if(!initialized) - return // Cannot update UI if it is not set up yet. - if(status <= UI_DISABLED && !force) - return // Cannot update UI, we have no visibility. - - // Send the new JSON to the update() Javascript function. - user << output(url_encode(get_json(data, static_data)), "[custom_browser_id ? window_id : "[window_id].browser"]:update") - - /** - * private - * - * Updates the UI by interacting with the src_object again, which will hopefully - * call try_ui_update on it. - * - * optional force_open bool If force_open should be passed to ui_interact. - **/ -/datum/tgui/proc/update(force_open = FALSE) - src_object.ui_interact(user, ui_key, src, force_open, master_ui, state) - - /** - * private - * - * Update the status/visibility of the UI for its user. - * - * optional push bool Push an update to the UI (an update is always sent for UI_DISABLED). - **/ -/datum/tgui/proc/update_status(push = FALSE) - var/status = src_object.ui_status(user, state) - if(master_ui) - status = min(status, master_ui.status) - set_status(status, push) - if(status == UI_CLOSE) - close() - - /** - * private - * - * Set the status/visibility of the UI. - * - * required status int The status to set (UI_CLOSE/UI_DISABLED/UI_UPDATE/UI_INTERACTIVE). - * optional push bool Push an update to the UI (an update is always sent for UI_DISABLED). - **/ -/datum/tgui/proc/set_status(status, push = FALSE) - if(src.status != status) // Only update if status has changed. - if(src.status == UI_DISABLED) - src.status = status - if(push) - update() - else - src.status = status - if(status == UI_DISABLED || push) // Update if the UI just because disabled, or a push is requested. - push_data(null, force = TRUE) - -/datum/tgui/proc/log_message(message) - log_tgui("[user] ([user.ckey]) using \"[title]\":\n[message]") +/** + * private + * + * Updates the status, and returns TRUE if status has changed. + */ +/datum/tgui/proc/process_status() + var/prev_status = status + status = src_object.ui_status(user, state) + return prev_status != status +/** + * private + * + * Callback for handling incoming tgui messages. + */ +/datum/tgui/proc/on_message(type, list/payload, list/href_list) + // Pass act type messages to ui_act + if(type && copytext(type, 1, 5) == "act/") + process_status() + if(src_object.ui_act(copytext(type, 5), payload, src, state)) + SStgui.update_uis(src_object) + return FALSE + switch(type) + if("ready") + initialized = TRUE + if("pingReply") + initialized = TRUE + if("suspend") + close(can_be_suspended = TRUE) + if("close") + close(can_be_suspended = FALSE) + if("log") + if(href_list["fatal"]) + close(can_be_suspended = FALSE) + if("setSharedState") + if(status != UI_INTERACTIVE) + return + LAZYINITLIST(src_object.tgui_shared_states) + src_object.tgui_shared_states[href_list["key"]] = href_list["value"] + SStgui.update_uis(src_object) diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm new file mode 100644 index 0000000000..3f271163c9 --- /dev/null +++ b/code/modules/tgui/tgui_window.dm @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +/datum/tgui_window + var/id + var/client/client + var/pooled + var/pool_index + var/status = TGUI_WINDOW_CLOSED + var/locked = FALSE + var/datum/tgui/locked_by + var/fatally_errored = FALSE + var/message_queue + var/sent_assets = list() + +/** + * public + * + * Create a new tgui window. + * + * required client /client + * required id string A unique window identifier. + */ +/datum/tgui_window/New(client/client, id, pooled = FALSE) + src.id = id + src.client = client + src.pooled = pooled + if(pooled) + client.tgui_windows[id] = src + src.pool_index = TGUI_WINDOW_INDEX(id) + +/** + * public + * + * Initializes the window with a fresh page. Puts window into the "loading" + * state. You can begin sending messages right after initializing. Messages + * will be put into the queue until the window finishes loading. + * + * optional inline_assets list List of assets to inline into the html. + */ +/datum/tgui_window/proc/initialize(inline_assets = list()) + log_tgui(client, "[id]/initialize") + if(!client) + return + status = TGUI_WINDOW_LOADING + fatally_errored = FALSE + message_queue = null + // Build window options + var/options = "file=[id].html;can_minimize=0;auto_format=0;" + // Remove titlebar and resize handles for a fancy window + if(client.prefs.tgui_fancy) + options += "titlebar=0;can_resize=0;" + else + options += "titlebar=1;can_resize=1;" + // Generate page html + var/html = SStgui.basehtml + html = replacetextEx(html, "\[tgui:windowId]", id) + // Process inline assets + var/inline_styles = "" + var/inline_scripts = "" + for(var/datum/asset/asset in inline_assets) + var/mappings = asset.get_url_mappings() + for(var/name in mappings) + var/url = mappings[name] + // Not urlencoding since asset strings are considered safe + if(copytext(name, -4) == ".css") + inline_styles += "\n" + else if(copytext(name, -3) == ".js") + inline_scripts += "\n" + asset.send() + html = replacetextEx(html, "\n", inline_styles) + html = replacetextEx(html, "\n", inline_scripts) + // Open the window + client << browse(html, "window=[id];[options]") + // Instruct the client to signal UI when the window is closed. + winset(client, id, "on-close=\"uiclose [id]\"") + +/** + * public + * + * Checks if the window is ready to receive data. + * + * return bool + */ +/datum/tgui_window/proc/is_ready() + return status == TGUI_WINDOW_READY + +/** + * public + * + * Checks if the window can be sanely suspended. + * + * return bool + */ +/datum/tgui_window/proc/can_be_suspended() + return !fatally_errored \ + && pooled \ + && pool_index > 0 \ + && pool_index <= TGUI_WINDOW_SOFT_LIMIT \ + && status == TGUI_WINDOW_READY + +/** + * public + * + * Acquire the window lock. Pool will not be able to provide this window + * to other UIs for the duration of the lock. + * + * Can be given an optional tgui datum, which will hook its on_message + * callback into the message stream. + * + * optional ui /datum/tgui + */ +/datum/tgui_window/proc/acquire_lock(datum/tgui/ui) + locked = TRUE + locked_by = ui + +/** + * Release the window lock. + */ +/datum/tgui_window/proc/release_lock() + // Clean up assets sent by tgui datum which requested the lock + if(locked) + sent_assets = list() + locked = FALSE + locked_by = null + +/** + * public + * + * Close the UI. + * + * optional can_be_suspended bool + */ +/datum/tgui_window/proc/close(can_be_suspended = TRUE) + if(!client) + return + if(can_be_suspended && can_be_suspended()) + log_tgui(client, "[id]/close: suspending") + status = TGUI_WINDOW_READY + send_message("suspend") + return + log_tgui(client, "[id]/close") + release_lock() + status = TGUI_WINDOW_CLOSED + message_queue = null + // Do not close the window to give user some time + // to read the error message. + if(!fatally_errored) + client << browse(null, "window=[id]") + +/** + * public + * + * Sends a message to tgui window. + * + * required type string Message type + * required payload list Message payload + * optional force bool Send regardless of the ready status. + */ +/datum/tgui_window/proc/send_message(type, list/payload, force) + if(!client) + return + var/message = json_encode(list( + "type" = type, + "payload" = payload, + )) + // Strip #255/improper. + message = replacetext(message, "\proper", "") + message = replacetext(message, "\improper", "") + // Pack for sending via output() + message = url_encode(message) + // Place into queue if window is still loading + if(!force && status != TGUI_WINDOW_READY) + if(!message_queue) + message_queue = list() + message_queue += list(message) + return + client << output(message, "[id].browser:update") + +/** + * public + * + * Makes an asset available to use in tgui. + * + * required asset datum/asset + */ +/datum/tgui_window/proc/send_asset(datum/asset/asset) + if(!client || !asset) + return + if(istype(asset, /datum/asset/spritesheet)) + var/datum/asset/spritesheet/spritesheet = asset + send_message("asset/stylesheet", spritesheet.css_filename()) + send_message("asset/mappings", asset.get_url_mappings()) + sent_assets += list(asset) + asset.send(client) + +/** + * private + * + * Sends queued messages if the queue wasn't empty. + */ +/datum/tgui_window/proc/flush_message_queue() + if(!client || !message_queue) + return + for(var/message in message_queue) + client << output(message, "[id].browser:update") + message_queue = null + +/** + * private + * + * Callback for handling incoming tgui messages. + */ +/datum/tgui_window/proc/on_message(type, list/payload, list/href_list) + switch(type) + if("ready") + // Status can be READY if user has refreshed the window. + if(status == TGUI_WINDOW_READY) + // Resend the assets + for(var/asset in sent_assets) + send_asset(asset) + status = TGUI_WINDOW_READY + if("log") + if(href_list["fatal"]) + fatally_errored = TRUE + // Pass message to UI that requested the lock + if(locked && locked_by) + locked_by.on_message(type, payload, href_list) + flush_message_queue() + return + // If not locked, handle these message types + switch(type) + if("suspend") + close(can_be_suspended = TRUE) + if("close") + close(can_be_suspended = FALSE) diff --git a/code/modules/uplink/uplink_items/uplink_ammo.dm b/code/modules/uplink/uplink_items/uplink_ammo.dm index ce74773f8d..853f6111b2 100644 --- a/code/modules/uplink/uplink_items/uplink_ammo.dm +++ b/code/modules/uplink/uplink_items/uplink_ammo.dm @@ -291,10 +291,17 @@ /datum/uplink_item/ammo/bolt_action name = "Surplus Rifle Clip" desc = "A stripper clip used to quickly load bolt action rifles. Contains 5 rounds." - item = /obj/item/ammo_box/a762 + item = /obj/item/ammo_box/a762 cost = 1 include_modes = list(/datum/game_mode/nuclear) +/datum/uplink_item/ammo/bolt_action_bulk + name = "Surplus Rifle Clip Box" + desc = "An ammo box we found in a warehouse, holding 7 clips of 5 rounds for bolt-action rifles. Yes, the cheap ones." + item = /obj/item/storage/toolbox/ammo + cost = 4 + include_modes = list(/datum/game_mode/nuclear) + /datum/uplink_item/ammo/dark_gygax/bag name = "Dark Gygax Ammo Bag" desc = "A duffel bag containing ammo for three full reloads of the incendiary carbine and flash bang launcher that are equipped on a standard Dark Gygax exosuit." diff --git a/code/modules/uplink/uplink_items/uplink_bundles.dm b/code/modules/uplink/uplink_items/uplink_bundles.dm index 321b9121bc..1b7909a50d 100644 --- a/code/modules/uplink/uplink_items/uplink_bundles.dm +++ b/code/modules/uplink/uplink_items/uplink_bundles.dm @@ -50,7 +50,7 @@ Combines with all martial arts, but the user will be unable to bring themselves to use guns, nor remove the armbands." item = /obj/item/storage/box/syndie_kit/northstar cost = 20 - exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) /datum/uplink_item/suits/infiltrator_bundle name = "Insidious Infiltration Gear Case" @@ -117,7 +117,7 @@ you will receive. May contain discontinued and/or exotic items." item = /obj/item/storage/box/syndicate cost = 20 - exclude_modes = list(/datum/game_mode/nuclear) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/traitor/internal_affairs) cant_discount = TRUE /datum/uplink_item/bundles_TC/surplus @@ -127,7 +127,7 @@ item = /obj/structure/closet/crate cost = 20 player_minimum = 25 - exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) cant_discount = TRUE var/starting_crate_value = 50 @@ -163,7 +163,7 @@ /datum/uplink_item/bundles_TC/reroll name = "Renegotiate Contract" - desc = "Selecting this will inform the syndicate that you wish to change employers. Can only be done once; no take-backs." + desc = "Selecting this will inform your employers that you wish for new objectives. Can only be done once; no take-backs." item = /obj/effect/gibspawner/generic cost = 0 cant_discount = TRUE @@ -173,8 +173,7 @@ /datum/uplink_item/bundles_TC/reroll/purchase(mob/user, datum/component/uplink/U) var/datum/antagonist/traitor/T = user?.mind?.has_antag_datum(/datum/antagonist/traitor) if(istype(T)) - var/new_traitor_kind = get_random_traitor_kind(list(T.traitor_kind.type)) - T.set_traitor_kind(new_traitor_kind) + T.set_traitor_kind(/datum/traitor_class/human/subterfuge) else to_chat(user,"Invalid user for contract renegotiation.") @@ -184,6 +183,7 @@ item = /obj/effect/gibspawner/generic // non-tangible item because techwebs use this path to determine illegal tech cost = 0 cant_discount = TRUE + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/bundles_TC/random/purchase(mob/user, datum/component/uplink/U) var/list/uplink_items = U.uplink_items @@ -193,6 +193,8 @@ var/datum/uplink_item/I = uplink_items[category][item] if(src == I || !I.item) continue + if(istype(I, /datum/uplink_item/bundles_TC/reroll)) //oops! + continue if(U.telecrystals < I.cost) continue if(I.limited_stock == 0) diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm index 014e0452b5..c26a9ae1f0 100644 --- a/code/modules/uplink/uplink_items/uplink_clothing.dm +++ b/code/modules/uplink/uplink_items/uplink_clothing.dm @@ -97,3 +97,9 @@ item = /obj/item/clothing/gloves/tackler/combat/insulated include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) cost = 2 + +/datum/uplink_item/device_tools/syndicate_eyepatch + name = "Mechanical Eyepatch" + desc = "An eyepatch that connects itself to your eye socket, enhancing your shooting to an impossible degree, allowing your bullets to ricochet far more often than usual." + item = /obj/item/clothing/glasses/eyepatch/syndicate + cost = 8 diff --git a/code/modules/uplink/uplink_items/uplink_dangerous.dm b/code/modules/uplink/uplink_items/uplink_dangerous.dm index 99c9c505c0..58cb43996d 100644 --- a/code/modules/uplink/uplink_items/uplink_dangerous.dm +++ b/code/modules/uplink/uplink_items/uplink_dangerous.dm @@ -21,7 +21,7 @@ item = /obj/item/storage/box/syndie_kit/revolver cost = 13 surplus = 50 - exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) /datum/uplink_item/dangerous/rawketlawnchair name = "84mm Rocket Propelled Grenade Launcher" @@ -109,10 +109,10 @@ name = "Double-Bladed Energy Sword" desc = "The double-bladed energy sword does slightly more damage than a standard energy sword and will deflect \ all energy projectiles, but requires two hands to wield." - item = /obj/item/twohanded/dualsaber + item = /obj/item/dualsaber player_minimum = 25 cost = 16 - exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) /datum/uplink_item/dangerous/doublesword/get_discount() return pick(4;0.8,2;0.65,1;0.5) @@ -123,7 +123,7 @@ pocketed when inactive. Activating it produces a loud, distinctive noise." item = /obj/item/melee/transforming/energy/sword/saber cost = 8 - exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) /datum/uplink_item/dangerous/shield name = "Energy Shield" @@ -141,7 +141,7 @@ However, due to the size of the blade and obvious nature of the sheath, the weapon stands out as being obviously nefarious." item = /obj/item/storage/belt/sabre/rapier cost = 8 - exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) /datum/uplink_item/dangerous/flamethrower name = "Flamethrower" @@ -177,14 +177,26 @@ organic host as a home base and source of fuel. Holoparasites come in various types and share damage with their host." item = /obj/item/storage/box/syndie_kit/guardian cost = 15 + limited_stock = 1 // you can only have one holopara apparently? refundable = TRUE cant_discount = TRUE surplus = 0 - exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) player_minimum = 25 restricted = TRUE refund_path = /obj/item/guardiancreator/tech/choose/traitor +/datum/uplink_item/dangerous/nukieguardian // just like the normal holoparasites but without the support or deffensive stands because nukies shouldnt turtle + name = "Holoparasites" + desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an \ + organic host as a home base and source of fuel. Holoparasites come in various types and share damage with their host." + item = /obj/item/storage/box/syndie_kit/nukieguardian + cost = 15 + refundable = TRUE + surplus = 50 + refund_path = /obj/item/guardiancreator/tech/choose/nukie + include_modes = list(/datum/game_mode/nuclear) + /datum/uplink_item/dangerous/machinegun name = "L6 Squad Automatic Weapon" desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \ @@ -211,6 +223,7 @@ deal extra damage and hit targets further. Use a screwdriver to take out any attached tanks." item = /obj/item/melee/powerfist cost = 8 + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/dangerous/sniper name = "Sniper Rifle" @@ -250,4 +263,4 @@ darts effective at incapacitating a target." item = /obj/item/gun/ballistic/automatic/toy/pistol/riot cost = 3 - surplus = 10 \ No newline at end of file + surplus = 10 diff --git a/code/modules/uplink/uplink_items/uplink_devices.dm b/code/modules/uplink/uplink_items/uplink_devices.dm index df6373b8de..5f5eb91a04 100644 --- a/code/modules/uplink/uplink_items/uplink_devices.dm +++ b/code/modules/uplink/uplink_items/uplink_devices.dm @@ -147,6 +147,12 @@ item = /obj/item/aiModule/syndicate cost = 9 +/datum/uplink_item/device_tools/damaged_module + name = "Damaged AI Law Upload Module" + desc = "This AI law upload module has been laying around our warehouse for god knows how long. We do not know why you would ever use this." + item = /obj/item/aiModule/core/full/damaged + cost = 5 + /datum/uplink_item/device_tools/headsetupgrade name = "Headset Upgrader" desc = "A device that can be used to make one headset immune to flashbangs." @@ -200,16 +206,14 @@ this primer of questionable worth and value is rumored to increase your rifle-bolt-working and/or shotgun \ racking fivefold. Then again, the techniques here only work on bolt-actions and pump-actions..." item = /obj/item/book/granter/trait/rifleman - cost = 3 - restricted_roles = list("Operative") // i want it to be surplusable but i also want it to be mostly nukie only, please advise - surplus = 90 + cost = 3 // fuck it available for everyone /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 \ + desc = "Stimpacks, the tool of many great heroes. Makes you nearly immune to non-lethal weaponry for about \ 5 minutes after injection." item = /obj/item/reagent_containers/syringe/stimulants - cost = 3 + cost = 5 surplus = 90 /datum/uplink_item/device_tools/medkit @@ -230,17 +234,9 @@ /datum/uplink_item/device_tools/surgerybag_adv name = "Advanced Syndicate Surgery Duffel Bag" - desc = "The Syndicate surgery duffel bag is a toolkit containing all advanced surgery tools, surgical drapes, \ - a Syndicate brand MMI, a straitjacket, a muzzle, and an outdated, yet still useful Combat Medic Kit." + desc = "A Syndicate surgery duffel bag, with a set of upgraded surgery tools to boot." item = /obj/item/storage/backpack/duffelbag/syndie/surgery_adv - cost = 10 - -/datum/uplink_item/device_tools/brainwash_disk - name = "Brainwashing Surgery Program" - desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \ - Insert into an Operating Console to enable the procedure." - item = /obj/item/disk/surgery/brainwashing - cost = 3 + cost = 6 /datum/uplink_item/device_tools/encryptionkey name = "Syndicate Encryption Key" diff --git a/code/modules/uplink/uplink_items/uplink_explosives.dm b/code/modules/uplink/uplink_items/uplink_explosives.dm index c52651fee9..f44966fb3b 100644 --- a/code/modules/uplink/uplink_items/uplink_explosives.dm +++ b/code/modules/uplink/uplink_items/uplink_explosives.dm @@ -58,6 +58,7 @@ item = /obj/item/storage/backpack/duffelbag/syndie/x4 cost = 4 // cant_discount = TRUE + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/explosives/clown_bomb_clownops name = "Clown Bomb" @@ -79,6 +80,7 @@ item = /obj/item/cartridge/virus/syndicate cost = 5 restricted = TRUE + limited_stock = 1 /datum/uplink_item/explosives/emp name = "EMP Grenades and Implanter Kit" @@ -123,6 +125,7 @@ be defused, and some crew may attempt to do so." item = /obj/item/sbeacondrop/bomb cost = 11 + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/explosives/syndicate_detonator name = "Syndicate Detonator" @@ -140,7 +143,7 @@ in addition to dealing high amounts of damage to nearby personnel." item = /obj/item/grenade/syndieminibomb cost = 6 - exclude_modes = list(/datum/game_mode/nuclear/clown_ops) + exclude_modes = list(/datum/game_mode/nuclear/clown_ops, /datum/game_mode/traitor/internal_affairs) /datum/uplink_item/explosives/tearstache name = "Teachstache Grenade" diff --git a/code/modules/uplink/uplink_items/uplink_implants.dm b/code/modules/uplink/uplink_items/uplink_implants.dm index 02b8b1e01d..bb4e0c7960 100644 --- a/code/modules/uplink/uplink_items/uplink_implants.dm +++ b/code/modules/uplink/uplink_items/uplink_implants.dm @@ -29,6 +29,13 @@ item = /obj/item/storage/box/syndie_kit/imp_freedom cost = 5 +/datum/uplink_item/implants/warp + name = "Warp Implant" + desc = "An implant injected into the body and later activated at the user's will. It will inject eigenstasium which saves the user's location and teleports them there after five seconds. Lasts only fifteen times." + item = /obj/item/storage/box/syndie_kit/imp_warp + cost = 6 + exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) + /datum/uplink_item/implants/hijack name = "Hijack Implant" desc = "An implant that will let you hack into the APCs on station, allowing you to control them at will and the machinery within those rooms." diff --git a/code/modules/uplink/uplink_items/uplink_roles.dm b/code/modules/uplink/uplink_items/uplink_roles.dm index da25cf5298..b8eaf41371 100644 --- a/code/modules/uplink/uplink_items/uplink_roles.dm +++ b/code/modules/uplink/uplink_items/uplink_roles.dm @@ -30,6 +30,7 @@ item = /obj/item/gun/blastcannon cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist. restricted_roles = list("Research Director", "Scientist") + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/role_restricted/alientech name = "Alien Research Disk" @@ -39,6 +40,14 @@ cost = 12 restricted_roles = list("Research Director", "Scientist", "Roboticist") +/datum/uplink_item/device_tools/brainwash_disk + name = "Brainwashing Surgery Program" + desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \ + Insert into an Operating Console to enable the procedure." + item = /obj/item/disk/surgery/brainwashing + restricted_roles = list("Medical Doctor", "Roboticist") + cost = 5 + /datum/uplink_item/role_restricted/clown_bomb name = "Clown Bomb" desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \ @@ -92,6 +101,7 @@ player_minimum = 20 refundable = TRUE restricted_roles = list("Chaplain") + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/role_restricted/arcane_tome name = "Arcane Tome" @@ -101,6 +111,7 @@ player_minimum = 20 refundable = TRUE restricted_roles = list("Chaplain") + exclude_modes = list(/datum/game_mode/traitor/internal_affairs) /datum/uplink_item/role_restricted/explosive_hot_potato name = "Exploding Hot Potato" diff --git a/code/modules/uplink/uplink_items/uplink_stealth.dm b/code/modules/uplink/uplink_items/uplink_stealth.dm index b4933b30ba..ff6d66a483 100644 --- a/code/modules/uplink/uplink_items/uplink_stealth.dm +++ b/code/modules/uplink/uplink_items/uplink_stealth.dm @@ -51,7 +51,7 @@ gain skin as hard as steel and swat bullets from the air, but you also refuse to use dishonorable ranged weaponry." item = /obj/item/book/granter/martial/carp cost = 17 - player_minimum = 30 + player_minimum = 20 surplus = 0 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) @@ -61,10 +61,20 @@ and dodging all ranged weapon fire, but you will refuse to use dishonorable ranged weaponry." item = /obj/item/book/granter/martial/bass cost = 18 - player_minimum = 30 + player_minimum = 20 surplus = 0 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) +/datum/uplink_item/stealthy_weapons/martialartsthree + name = "Krav Maga Scroll" + desc = "This scroll contains the secrets of an ancient martial arts technique. You will gain special unarmed attacks for \ + stealthy takedowns." + item = /obj/item/book/granter/martial/krav_maga + cost = 16 + player_minimum = 25 + surplus = 0 + include_modes = list(/datum/game_mode/traitor/internal_affairs) + /datum/uplink_item/stealthy_weapons/crossbow name = "Miniature Energy Crossbow" desc = "A short bow mounted across a tiller in miniature. Small enough to \ diff --git a/code/modules/uplink/uplink_items/uplink_stealthdevices.dm b/code/modules/uplink/uplink_items/uplink_stealthdevices.dm index f1c27c640b..28d02cf79b 100644 --- a/code/modules/uplink/uplink_items/uplink_stealthdevices.dm +++ b/code/modules/uplink/uplink_items/uplink_stealthdevices.dm @@ -112,13 +112,13 @@ name = "Radio Jammer" desc = "This device will disrupt any nearby outgoing radio communication when activated. Does not affect binary chat." item = /obj/item/jammer - cost = 5 + cost = 2 /datum/uplink_item/stealthy_tools/smugglersatchel name = "Smuggler's Satchel" desc = "This satchel is thin enough to be hidden in the gap between plating and tiling; great for stashing \ your stolen goods. Comes with a crowbar and a floor tile inside. Properly hidden satchels have been \ - known to survive intact even beyond the current shift. " + known to survive intact even beyond the current shift, but this is just a myth. " item = /obj/item/storage/backpack/satchel/flat - cost = 2 + cost = 1 surplus = 30 diff --git a/code/modules/vehicles/_vehicle.dm b/code/modules/vehicles/_vehicle.dm index ac7fa879f4..12e9f365d0 100644 --- a/code/modules/vehicles/_vehicle.dm +++ b/code/modules/vehicles/_vehicle.dm @@ -18,6 +18,7 @@ var/canmove = TRUE var/emulate_door_bumps = TRUE //when bumping a door try to make occupants bump them to open them. var/default_driver_move = TRUE //handle driver movement instead of letting something else do it like riding datums. + var/enclosed = FALSE // is the rider protected from bullets? assume no var/list/autogrant_actions_passenger //plain list of typepaths var/list/autogrant_actions_controller //assoc list "[bitflag]" = list(typepaths) var/list/mob/occupant_actions //assoc list mob = list(type = action datum assigned to mob) @@ -166,3 +167,9 @@ if(trailer && .) var/dir_to_move = get_dir(trailer.loc, newloc) step(trailer, dir_to_move) + +/obj/vehicle/bullet_act(obj/item/projectile/Proj) //wrapper + if (!enclosed && length(occupants) && !Proj.force_hit && (Proj.def_zone == BODY_ZONE_HEAD || Proj.def_zone == BODY_ZONE_CHEST)) //allows bullets to hit drivers + occupants[1].bullet_act(Proj) // driver dinkage + return BULLET_ACT_HIT + . = ..() diff --git a/code/modules/vehicles/atv.dm b/code/modules/vehicles/atv.dm index 4a0e2f0b58..d125453e5a 100644 --- a/code/modules/vehicles/atv.dm +++ b/code/modules/vehicles/atv.dm @@ -68,7 +68,7 @@ /obj/vehicle/ridden/atv/snowmobile/Moved() . = ..() - var/static/list/snow_typecache = typecacheof(list(/turf/open/floor/plating/asteroid/snow/icemoon, /turf/open/floor/plating/snowed/smoothed/icemoon)) + var/static/list/snow_typecache = typecacheof(list(/turf/open/floor/plating/asteroid/snow/icemoon, /turf/open/floor/plating/snowed/smoothed/icemoon, /turf/open/floor/plating/snowed, /turf/open/floor/plating/asteroid/snow)) var/datum/component/riding/E = LoadComponent(/datum/component/riding) if(snow_typecache[loc.type]) E.vehicle_move_delay = 1 diff --git a/code/modules/vehicles/cars/car.dm b/code/modules/vehicles/cars/car.dm index d45cb8d26f..4545fab2a7 100644 --- a/code/modules/vehicles/cars/car.dm +++ b/code/modules/vehicles/cars/car.dm @@ -57,7 +57,7 @@ return FALSE return ..() -/obj/vehicle/sealed/car/attack_hand(mob/living/user) +/obj/vehicle/sealed/car/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(!(car_traits & CAN_KIDNAP)) return diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm index ef374f5db0..8f9d553ec7 100644 --- a/code/modules/vehicles/pimpin_ride.dm +++ b/code/modules/vehicles/pimpin_ride.dm @@ -62,11 +62,8 @@ if(floorbuffer) . += "cart_buffer" -/obj/vehicle/ridden/janicart/attack_hand(mob/user) - . = ..() - if(.) - return - else if(mybag) +/obj/vehicle/ridden/janicart/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) + if(mybag) mybag.forceMove(get_turf(user)) user.put_in_hands(mybag) mybag = null diff --git a/code/modules/vehicles/sealed.dm b/code/modules/vehicles/sealed.dm index edaab8b982..28f6b1cca8 100644 --- a/code/modules/vehicles/sealed.dm +++ b/code/modules/vehicles/sealed.dm @@ -1,4 +1,5 @@ /obj/vehicle/sealed + enclosed = TRUE // you're in a sealed vehicle dont get dinked idiot var/enter_delay = 20 flags_1 = BLOCK_FACE_ATOM_1 diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 6e6636cd62..a115300085 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -105,6 +105,12 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C ///Last world tick we sent a slogan message out var/last_slogan var/last_shopper + var/tilted = FALSE + var/tiltable = TRUE + var/squish_damage = 75 + var/forcecrit = 0 + var/num_shards = 7 + var/list/pinned_mobs = list() ///How many ticks until we can send another var/slogan_delay = 6000 ///Icon when vending an item to the user @@ -372,6 +378,7 @@ GLOBAL_LIST_EMPTY(vending_products) ..() if(panel_open) default_unfasten_wrench(user, I, time = 60) + unbuckle_all_mobs(TRUE) return TRUE /obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/I) @@ -435,6 +442,147 @@ GLOBAL_LIST_EMPTY(vending_products) updateUsrDialog() else . = ..() + if(tiltable && !tilted && I.force) + switch(rand(1, 100)) + if(1 to 5) + freebie(user, 3) + if(6 to 15) + freebie(user, 2) + if(16 to 25) + freebie(user, 1) + if(76 to 90) + tilt(user) + if(91 to 100) + tilt(user, crit=TRUE) + +/obj/machinery/vending/proc/freebie(mob/fatty, freebies) + visible_message("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"]!") + + for(var/i in 1 to freebies) + playsound(src, 'sound/machines/machine_vend.ogg', 50, TRUE, extrarange = -3) + for(var/datum/data/vending_product/R in shuffle(product_records)) + + if(R.amount <= 0) //Try to use a record that actually has something to dump. + continue + var/dump_path = R.product_path + if(!dump_path) + continue + + R.amount-- + new dump_path(get_turf(src)) + break + +/obj/machinery/vending/proc/tilt(mob/fatty, crit=FALSE) + visible_message("[src] tips over!") + tilted = TRUE + layer = ABOVE_MOB_LAYER + + var/crit_case + if(crit) + crit_case = rand(1,6) + + if(forcecrit) + crit_case = forcecrit + + if(in_range(fatty, src)) + for(var/mob/living/L in get_turf(fatty)) + var/mob/living/carbon/C = L + + if(istype(C)) + var/crit_rebate = 0 // lessen the normal damage we deal for some of the crits + + if(crit_case < 5) // the head asplode case has its own description + C.visible_message("[C] is crushed by [src]!", \ + "You are crushed by [src]!") + + switch(crit_case) // only carbons can have the fun crits + if(1) // shatter their legs and bleed 'em + crit_rebate = 60 + C.bleed(150) + var/obj/item/bodypart/l_leg/l = C.get_bodypart(BODY_ZONE_L_LEG) + if(l) + l.receive_damage(brute=200, updating_health=TRUE) + var/obj/item/bodypart/r_leg/r = C.get_bodypart(BODY_ZONE_R_LEG) + if(r) + r.receive_damage(brute=200, updating_health=TRUE) + if(l || r) + C.visible_message("[C]'s legs shatter with a sickening crunch!", \ + "Your legs shatter with a sickening crunch!") + if(2) // pin them beneath the machine until someone untilts it + forceMove(get_turf(C)) + buckle_mob(C, force=TRUE) + C.visible_message("[C] is pinned underneath [src]!", \ + "You are pinned down by [src]!") + if(3) // glass candy + crit_rebate = 50 + for(var/i = 0, i < num_shards, i++) + var/obj/item/shard/shard = new /obj/item/shard(get_turf(C)) + shard.embedding = list(embed_chance = 100, ignore_throwspeed_threshold = TRUE, impact_pain_mult=1, pain_chance=5) + shard.updateEmbedding() + C.hitby(shard, skipcatch = TRUE, hitpush = FALSE) + shard.embedding = list() + shard.updateEmbedding() + if(4) // paralyze this binch + // the new paraplegic gets like 4 lines of losing their legs so skip them + visible_message("[C]'s spinal cord is obliterated with a sickening crunch!", ignored_mobs = list(C)) + C.gain_trauma(/datum/brain_trauma/severe/paralysis/spinesnapped) + if(5) // limb squish! + for(var/i in C.bodyparts) + var/obj/item/bodypart/squish_part = i + if(squish_part.is_organic_limb()) + var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate)) + squish_part.force_wound_upwards(type_wound) + else + squish_part.receive_damage(brute=30) + C.visible_message("[C]'s body is maimed underneath the mass of [src]!", \ + "Your body is maimed underneath the mass of [src]!") + if(6) // skull squish! + var/obj/item/bodypart/head/O = C.get_bodypart(BODY_ZONE_HEAD) + if(O) + C.visible_message("[O] explodes in a shower of gore beneath [src]!", \ + "Oh f-") + O.dismember() + O.drop_organs() + qdel(O) + new /obj/effect/gibspawner/human/bodypartless(get_turf(C)) + + if(prob(30)) + C.apply_damage(max(0, squish_damage - crit_rebate), forced=TRUE, spread_damage=TRUE) // the 30% chance to spread the damage means you escape breaking any bones + else + C.take_bodypart_damage((squish_damage - crit_rebate)*0.5, wound_bonus = 5) // otherwise, deal it to 2 random limbs (or the same one) which will likely shatter something + C.take_bodypart_damage((squish_damage - crit_rebate)*0.5, wound_bonus = 5) + C.AddElement(/datum/element/squish, 18 SECONDS) + else + L.visible_message("[L] is crushed by [src]!", \ + "You are crushed by [src]!") + L.apply_damage(squish_damage, forced=TRUE) + if(crit_case) + L.apply_damage(squish_damage, forced=TRUE) + + L.Paralyze(60) + L.emote("scream") + playsound(L, 'sound/effects/blobattack.ogg', 40, TRUE) + playsound(L, 'sound/effects/splat.ogg', 50, TRUE) + + var/matrix/M = matrix() + M.Turn(pick(90, 270)) + transform = M + + if(get_turf(fatty) != get_turf(src)) + throw_at(get_turf(fatty), 1, 1, spin=FALSE) + +/obj/machinery/vending/proc/untilt(mob/user) + user.visible_message("[user] rights [src].", \ + "You right [src].") + + unbuckle_all_mobs(TRUE) + anchored = FALSE //so you can push it back into position + tilted = FALSE + layer = initial(layer) + + var/matrix/M = matrix() + M.Turn(0) + transform = M /obj/machinery/vending/proc/loadingAttempt(obj/item/I, mob/user) . = TRUE @@ -447,6 +595,12 @@ GLOBAL_LIST_EMPTY(vending_products) to_chat(user, "You insert [I] into [src]'s input compartment.") loaded_items++ + +/obj/machinery/vending/unbuckle_mob(mob/living/buckled_mob, force=FALSE) + if(!force) + return + . = ..() + /** * Is the passed in user allowed to load this vending machines compartments * @@ -511,23 +665,28 @@ GLOBAL_LIST_EMPTY(vending_products) if(seconds_electrified && !(stat & NOPOWER)) if(shock(user, 100)) return + if(tilted && !user.buckled && !isAI(user)) + to_chat(user, "You begin righting [src].") + if(do_after(user, 50, target=src)) + untilt(user) + return return ..() -/obj/machinery/vending/ui_base_html(html) - var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/vending) - . = replacetext(html, "", assets.css_tag()) +/obj/machinery/vending/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/vending), + ) -/obj/machinery/vending/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) +/obj/machinery/vending/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/vending) - assets.send(user) - ui = new(user, src, ui_key, "vending", name, 450, 600, master_ui, state) + ui = new(user, src, "Vending") ui.open() /obj/machinery/vending/ui_static_data(mob/user) . = list() .["onstation"] = onstation + .["department"] = payment_department .["product_records"] = list() for (var/datum/data/vending_product/R in product_records) var/list/data = list( @@ -554,7 +713,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, + price = R.custom_premium_price || extra_price, //may cause breakage. please note max_amount = R.max_amount, ref = REF(R), premium = TRUE @@ -563,28 +722,24 @@ 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)" + 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) + .["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 + .["user"]["department"] = C.registered_account.account_job.paycheck_department else - .["cost_text"] = " ([(cost_mult - 1) * 100]% EXTRA)" + .["user"]["job"] = "No Job" + .["user"]["department"] = "No Department" .["stock"] = list() for (var/datum/data/vending_product/R in product_records + coin_records + hidden_records) .["stock"][R.name] = R.amount - . .["extended_inventory"] = extended_inventory /obj/machinery/vending/ui_act(action, params) @@ -607,7 +762,9 @@ GLOBAL_LIST_EMPTY(vending_products) if(!R || !istype(R) || !R.product_path) vend_ready = TRUE return - var/price_to_use = R.custom_price || default_price + var/price_to_use = default_price + if(R.custom_price) + price_to_use = R.custom_price if(R in hidden_records) if(!extended_inventory) vend_ready = TRUE @@ -621,8 +778,10 @@ GLOBAL_LIST_EMPTY(vending_products) 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(onstation && 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) @@ -633,11 +792,20 @@ GLOBAL_LIST_EMPTY(vending_products) flick(icon_deny,src) vend_ready = TRUE return + // else if(age_restrictions && R.age_restricted && (!C.registered_age || C.registered_age < AGE_MINOR)) + // say("You are not of legal age to purchase [R.name].") + // if(!(usr in GLOB.narcd_underages)) + // Radio.set_frequency(FREQ_SECURITY) + // Radio.talk_into(src, "SECURITY ALERT: Underaged crewmember [H] recorded attempting to purchase [R.name] in [get_area(src)]. Please watch for substance abuse.", FREQ_SECURITY) + // GLOB.narcd_underages += H + // 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(account.account_job && account.account_job.paycheck_department == payment_department) + price_to_use = 0 + if(coin_records.Find(R) || hidden_records.Find(R)) + price_to_use = R.custom_premium_price ? R.custom_premium_price : extra_price 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) @@ -646,6 +814,8 @@ GLOBAL_LIST_EMPTY(vending_products) var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) if(D) D.adjust_money(price_to_use) + SSblackbox.record_feedback("amount", "vending_spent", price_to_use) + //log_econ("[price_to_use] credits were inserted into [src] by [D.account_holder] to buy [R].") if(last_shopper != usr || purchase_message_cooldown < world.time) say("Thank you for shopping with [src]!") purchase_message_cooldown = world.time + 5 SECONDS @@ -922,7 +1092,7 @@ GLOBAL_LIST_EMPTY(vending_products) C = H.get_idcard(TRUE) if(C?.registered_account) private_a = C.registered_account - say("\The [src] has been linked to [C].") + say("[src] has been linked to [C].") if(compartmentLoadAccessCheck(user)) if(istype(I, /obj/item/pen)) diff --git a/code/modules/vending/assist.dm b/code/modules/vending/assist.dm index 92e40bc3a8..29d1e760d4 100644 --- a/code/modules/vending/assist.dm +++ b/code/modules/vending/assist.dm @@ -14,8 +14,7 @@ /obj/item/stock_parts/cell/upgraded = 2) premium = list(/obj/item/stock_parts/cell/upgraded/plus = 2, /obj/item/flashlight/lantern = 2, - /obj/item/beacon = 2, - /obj/item/airlock_painter/decal = 5) + /obj/item/beacon = 2) product_ads = "Only the finest!;Have some tools.;The most robust equipment.;The finest gear in space!" 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 diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 9dfb4c76a0..bc824cc994 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -84,8 +84,10 @@ /obj/item/clothing/suit/poncho = 1, /obj/item/clothing/suit/poncho/green = 1, /obj/item/clothing/suit/poncho/red = 1, + /obj/item/clothing/head/maid = 1, /obj/item/clothing/under/costume/maid = 1, /obj/item/clothing/under/rank/civilian/janitor/maid = 1, + /obj/item/clothing/gloves/evening = 1, /obj/item/clothing/glasses/cold=1, /obj/item/clothing/glasses/heat=1, /obj/item/clothing/suit/whitedress = 1, @@ -114,7 +116,8 @@ /obj/item/gun/magic/wand = 2, /obj/item/clothing/glasses/sunglasses/garb = 2, /obj/item/clothing/glasses/sunglasses/blindfold = 1, - /obj/item/clothing/mask/muzzle = 2) + /obj/item/clothing/mask/muzzle = 2, + /obj/item/clothing/under/syndicate/camo/cosmetic = 3) premium = list(/obj/item/clothing/suit/pirate/captain = 2, /obj/item/clothing/head/pirate/captain = 2, /obj/item/clothing/head/helmet/roman/fake = 1, diff --git a/code/modules/vending/cartridge.dm b/code/modules/vending/cartridge.dm index beaf6bb873..69635007c9 100644 --- a/code/modules/vending/cartridge.dm +++ b/code/modules/vending/cartridge.dm @@ -10,6 +10,7 @@ /obj/item/cartridge/security = 10, /obj/item/cartridge/janitor = 10, /obj/item/cartridge/signal/toxins = 10, + /obj/item/cartridge/roboticist = 10, /obj/item/pda/heads = 10) premium = list(/obj/item/cartridge/captain = 2, /obj/item/cartridge/quartermaster = 2) diff --git a/code/modules/vending/clothesmate.dm b/code/modules/vending/clothesmate.dm index 963fff9368..7005a0b02f 100644 --- a/code/modules/vending/clothesmate.dm +++ b/code/modules/vending/clothesmate.dm @@ -14,6 +14,10 @@ /obj/item/clothing/head/beret/blue = 3, /obj/item/clothing/glasses/monocle = 3, /obj/item/clothing/suit/jacket = 4, + /obj/item/clothing/suit/jacket/flannel = 4, + /obj/item/clothing/suit/jacket/flannel/red = 4, + /obj/item/clothing/suit/jacket/flannel/aqua = 4, + /obj/item/clothing/suit/jacket/flannel/brown = 4, /obj/item/clothing/suit/jacket/puffer/vest = 4, /obj/item/clothing/suit/jacket/puffer = 4, /obj/item/clothing/suit/hooded/cloak/david = 4, @@ -150,7 +154,8 @@ /obj/item/clothing/under/costume/qipao/red = 3, /obj/item/clothing/under/costume/cheongsam = 3, /obj/item/clothing/under/costume/cheongsam/white = 3, - /obj/item/clothing/under/costume/cheongsam/red = 3) + /obj/item/clothing/under/costume/cheongsam/red = 3, + /obj/item/storage/backpack/snail = 3) contraband = list(/obj/item/clothing/under/syndicate/tacticool = 3, /obj/item/clothing/under/syndicate/tacticool/skirt = 3, /obj/item/clothing/mask/balaclava = 3, diff --git a/code/modules/vending/coffee.dm b/code/modules/vending/coffee.dm index ab64756868..fd555526c6 100644 --- a/code/modules/vending/coffee.dm +++ b/code/modules/vending/coffee.dm @@ -1,16 +1,20 @@ /obj/machinery/vending/coffee name = "\improper Solar's Best Hot Drinks" desc = "A vending machine which dispenses hot drinks." - product_ads = "Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies" + product_ads = "Just what you need!;Have a drink!;Drink up!;It's good for you!;Would you like a hot joe?;I'd kill for some coffee!;The best beans in the galaxy.;Only the finest brew for you.;Mmmm. Nothing like a coffee.;I like coffee, don't you?;Coffee helps you work!;Try some tea.;We hope you like the best!;Try our new chocolate!;Admin conspiracies" icon_state = "coffee" icon_vend = "coffee-vend" products = list(/obj/item/reagent_containers/food/drinks/coffee = 25, /obj/item/reagent_containers/food/drinks/mug/tea = 25, + /obj/item/reagent_containers/food/drinks/mug/tea/red = 10, + /obj/item/reagent_containers/food/drinks/mug/tea/green = 10, /obj/item/reagent_containers/food/drinks/mug/coco = 25) - contraband = list(/obj/item/reagent_containers/food/drinks/ice = 12) + contraband = list(/obj/item/reagent_containers/food/drinks/ice = 12, + /obj/item/reagent_containers/food/drinks/mug/tea/mush = 3,) premium = list(/obj/item/reagent_containers/food/condiment/milk = 2, /obj/item/reagent_containers/food/drinks/bottle/cream = 2, - /obj/item/reagent_containers/food/condiment/sugar = 1) + /obj/item/reagent_containers/food/condiment/sugar = 1, + /obj/item/reagent_containers/food/drinks/mug/tea/forest = 3,) refill_canister = /obj/item/vending_refill/coffee default_price = PRICE_REALLY_CHEAP diff --git a/code/modules/vending/cola.dm b/code/modules/vending/cola.dm index b667f4c7c9..bb5b8ef288 100644 --- a/code/modules/vending/cola.dm +++ b/code/modules/vending/cola.dm @@ -15,7 +15,8 @@ /obj/item/reagent_containers/food/drinks/soda_cans/sol_dry = 10, /obj/item/reagent_containers/glass/beaker/waterbottle = 10) contraband = list(/obj/item/reagent_containers/food/drinks/soda_cans/thirteenloko = 6, - /obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 6) + /obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 6, + /obj/item/reagent_containers/glass/beaker/waterbottle/wataur = 2) premium = list(/obj/item/reagent_containers/food/drinks/drinkingglass/filled/nuka_cola = 1, /obj/item/reagent_containers/food/drinks/soda_cans/air = 1, /obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1, diff --git a/code/modules/vending/engivend.dm b/code/modules/vending/engivend.dm index 50e0fb9cde..965ebddd15 100644 --- a/code/modules/vending/engivend.dm +++ b/code/modules/vending/engivend.dm @@ -15,7 +15,6 @@ /obj/item/electronics/airalarm = 10, /obj/item/electronics/firealarm = 10, /obj/item/electronics/firelock = 10, - /obj/item/airlock_painter/decal = 5, /obj/item/rcd_ammo = 3 ) contraband = list(/obj/item/stock_parts/cell/potato = 3, @@ -25,7 +24,8 @@ ) premium = list(/obj/item/storage/belt/utility = 3, /obj/item/storage/box/smart_metal_foam = 3, - /obj/item/rcd_ammo/large = 5 + /obj/item/rcd_ammo/large = 5, + /obj/item/storage/bag/material = 3 ) 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 diff --git a/code/modules/vending/games.dm b/code/modules/vending/games.dm index 7bed27b0bd..7fd8246dd6 100644 --- a/code/modules/vending/games.dm +++ b/code/modules/vending/games.dm @@ -4,7 +4,7 @@ product_ads = "Escape to a fantasy world!;Fuel your gambling addiction!;Ruin your friendships!;Roll for initiative!;Elves and dwarves!;Paranoid computers!;Totally not satanic!;Fun times forever!" icon_state = "games" products = list(/obj/item/toy/cards/deck = 5, - /obj/item/storage/pill_bottle/dice = 10, + /obj/item/storage/box/dice = 10, /obj/item/toy/cards/deck/cas = 3, /obj/item/toy/cards/deck/cas/black = 3, /obj/item/toy/cards/deck/unum = 3) diff --git a/code/modules/vending/kinkmate.dm b/code/modules/vending/kinkmate.dm index 24fb685eac..a78a4e6ef4 100644 --- a/code/modules/vending/kinkmate.dm +++ b/code/modules/vending/kinkmate.dm @@ -6,8 +6,10 @@ product_slogans = "Kinky!;Sexy!;Check me out, big boy!" vend_reply = "Have fun, you shameless pervert!" products = list( + /obj/item/clothing/head/maid = 5, /obj/item/clothing/under/costume/maid = 5, /obj/item/clothing/under/rank/civilian/janitor/maid = 5, + /obj/item/clothing/gloves/evening = 5, /obj/item/clothing/neck/petcollar = 5, /obj/item/clothing/neck/petcollar/choker = 5, /obj/item/clothing/neck/petcollar/leather = 5, @@ -21,10 +23,10 @@ /obj/item/dildo/custom = 5, /obj/item/electropack/shockcollar = 3, /obj/item/assembly/signaler = 3, - /obj/item/clothing/under/shorts/polychromic/pantsu, - /obj/item/clothing/under/misc/poly_bottomless, - /obj/item/clothing/under/misc/poly_tanktop, - /obj/item/clothing/under/misc/poly_tanktop/female + /obj/item/clothing/under/shorts/polychromic/pantsu = 3, + /obj/item/clothing/under/misc/poly_bottomless = 3, + /obj/item/clothing/under/misc/poly_tanktop = 3, + /obj/item/clothing/under/misc/poly_tanktop/female = 3 ) contraband = list( /obj/item/clothing/neck/petcollar/locked = 2, @@ -34,13 +36,11 @@ /obj/item/clothing/under/misc/keyholesweater = 2, /obj/item/clothing/under/misc/stripper/mankini = 2, /obj/item/clothing/under/costume/jabroni = 2, - /obj/item/dildo/flared/huge = 3, - /obj/item/reagent_containers/glass/bottle/crocin = 5, - /obj/item/reagent_containers/glass/bottle/camphor = 5 + /obj/item/clothing/gloves/evening/black = 2, + /obj/item/dildo/flared/huge = 3 ) premium = list( /obj/item/clothing/accessory/skullcodpiece/fake = 3, - /obj/item/reagent_containers/glass/bottle/hexacrocin = 10, /obj/item/clothing/under/pants/chaps = 5 ) refill_canister = /obj/item/vending_refill/kink diff --git a/code/modules/vending/liberation_toy.dm b/code/modules/vending/liberation_toy.dm index 1ce0b6cfaf..9093d55b0d 100644 --- a/code/modules/vending/liberation_toy.dm +++ b/code/modules/vending/liberation_toy.dm @@ -20,7 +20,7 @@ /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted/riot = 10, /obj/item/ammo_box/foambox/riot = 20, /obj/item/toy/katana = 10, - /obj/item/twohanded/dualsaber/toy = 5, + /obj/item/dualsaber/toy = 5, /obj/item/toy/cards/deck/syndicate = 10) //Gambling and it hurts, making it a +18 item armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF diff --git a/code/modules/vending/medical.dm b/code/modules/vending/medical.dm index fbd9a10bf2..795d35adc4 100644 --- a/code/modules/vending/medical.dm +++ b/code/modules/vending/medical.dm @@ -29,7 +29,12 @@ /obj/item/storage/hypospraykit/brute = 2, /obj/item/storage/hypospraykit/enlarge = 2, /obj/item/reagent_containers/glass/bottle/vial/small = 5, - /obj/item/storage/briefcase/medical = 2) + /obj/item/storage/briefcase/medical = 2, + /obj/item/stack/sticky_tape/surgical = 3, + /obj/item/healthanalyzer/wound = 4, + /obj/item/stack/medical/ointment = 2, + /obj/item/stack/medical/suture = 2, + /obj/item/stack/medical/bone_gel = 4) contraband = list(/obj/item/reagent_containers/pill/tox = 3, /obj/item/reagent_containers/pill/morphine = 4, /obj/item/reagent_containers/pill/charcoal = 6) @@ -41,7 +46,8 @@ /obj/item/wrench/medical = 1, /obj/item/storage/belt/medolier/full = 2, /obj/item/gun/syringe/dart = 2, - /obj/item/storage/briefcase/medical = 2) + /obj/item/storage/briefcase/medical = 2, + /obj/item/plunger/reinforced = 2) armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm index 694d2b0c34..31f3dc49f1 100644 --- a/code/modules/vending/medical_wall.dm +++ b/code/modules/vending/medical_wall.dm @@ -11,6 +11,8 @@ /obj/item/reagent_containers/medspray/silver_sulf = 2, /obj/item/reagent_containers/pill/charcoal = 2, /obj/item/reagent_containers/medspray/sterilizine = 1, + /obj/item/healthanalyzer/wound = 2, + /obj/item/stack/medical/bone_gel = 2, /obj/item/reagent_containers/syringe/dart = 10) contraband = list(/obj/item/reagent_containers/pill/tox = 2, /obj/item/reagent_containers/pill/morphine = 2) @@ -22,6 +24,7 @@ extra_price = PRICE_NORMAL payment_department = ACCOUNT_MED cost_multiplier_per_dept = list(ACCOUNT_MED = 0) + tiltable = FALSE /obj/item/vending_refill/wallmed machine_name = "NanoMed" diff --git a/code/modules/vending/megaseed.dm b/code/modules/vending/megaseed.dm index 2eb68aaf4a..45199298ca 100644 --- a/code/modules/vending/megaseed.dm +++ b/code/modules/vending/megaseed.dm @@ -4,7 +4,8 @@ product_slogans = "THIS'S WHERE TH' SEEDS LIVE! GIT YOU SOME!;Hands down the best seed selection on the station!;Also certain mushroom varieties available, more for experts! Get certified today!" product_ads = "We like plants!;Grow some crops!;Grow, baby, growww!;Aw h'yeah son!" icon_state = "seeds" - products = list(/obj/item/seeds/ambrosia = 3, + products = list(/obj/item/seeds/aloe = 3, + /obj/item/seeds/ambrosia = 3, /obj/item/seeds/apple = 3, /obj/item/seeds/banana = 3, /obj/item/seeds/berry = 3, diff --git a/code/modules/vending/security.dm b/code/modules/vending/security.dm index 35e4b3232a..8ad4b0568c 100644 --- a/code/modules/vending/security.dm +++ b/code/modules/vending/security.dm @@ -15,8 +15,7 @@ /obj/item/secbat = 5) contraband = list(/obj/item/clothing/glasses/sunglasses = 2, /obj/item/storage/fancy/donut_box = 2, - /obj/item/ssword_kit = 1, - /obj/item/storage/bag/ammo = 1) + /obj/item/ssword_kit = 1) premium = list(/obj/item/coin/antagtoken = 1, /obj/item/clothing/head/helmet/blueshirt = 1, /obj/item/clothing/suit/armor/vest/blueshirt = 1, @@ -24,7 +23,7 @@ /obj/item/clothing/gloves/tackler = 5, /obj/item/grenade/stingbang = 1, /obj/item/ssword_kit = 1, - /obj/item/storage/bag/ammo = 2) + /obj/item/storage/bag/ammo = 3) 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 diff --git a/code/modules/vending/snack.dm b/code/modules/vending/snack.dm index 7aef2b627c..ff8fd46676 100644 --- a/code/modules/vending/snack.dm +++ b/code/modules/vending/snack.dm @@ -12,7 +12,8 @@ /obj/item/reagent_containers/food/snacks/no_raisin = 5, /obj/item/reagent_containers/food/snacks/spacetwinkie = 5, /obj/item/reagent_containers/food/snacks/cheesiehonkers = 5, - /obj/item/reagent_containers/food/snacks/cornchips = 5) + /obj/item/reagent_containers/food/snacks/cornchips = 5, + /obj/item/reagent_containers/food/snacks/energybar = 6) contraband = list( /obj/item/reagent_containers/food/snacks/cracker = 10, /obj/item/reagent_containers/food/snacks/honeybar = 5, diff --git a/code/modules/vending/toys.dm b/code/modules/vending/toys.dm index d628c888a5..c5095ebff8 100644 --- a/code/modules/vending/toys.dm +++ b/code/modules/vending/toys.dm @@ -21,7 +21,7 @@ /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted = 10, /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted = 10, /obj/item/toy/katana = 10, - /obj/item/twohanded/dualsaber/toy = 5) + /obj/item/dualsaber/toy = 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 refill_canister = /obj/item/vending_refill/donksoft diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm index 76ef5e6f23..26beccaac0 100644 --- a/code/modules/vending/wardrobes.dm +++ b/code/modules/vending/wardrobes.dm @@ -248,6 +248,7 @@ vend_reply = "Thank you for using the BarDrobe!" products = list(/obj/item/clothing/head/that = 3, /obj/item/radio/headset/headset_srv = 3, + /obj/item/clothing/suit/hooded/wintercoat/bar = 3, /obj/item/clothing/under/suit/sl = 3, /obj/item/clothing/under/rank/civilian/bartender = 3, /obj/item/clothing/under/rank/civilian/bartender/skirt = 2, @@ -309,7 +310,7 @@ /obj/item/cartridge/janitor = 3, /obj/item/clothing/gloves/color/black = 2, /obj/item/clothing/head/soft/purple = 2, - /obj/item/twohanded/broom = 2, + /obj/item/broom = 2, /obj/item/paint/paint_remover = 2, /obj/item/melee/flyswatter = 2, /obj/item/flashlight = 2, diff --git a/code/modules/vending/youtool.dm b/code/modules/vending/youtool.dm index c936d9c32c..2119197aed 100644 --- a/code/modules/vending/youtool.dm +++ b/code/modules/vending/youtool.dm @@ -18,8 +18,7 @@ /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, - /obj/item/airlock_painter/decal = 3) + /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 diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm index 50cdc32bf6..a367abb098 100644 --- a/code/modules/vore/eating/belly_obj.dm +++ b/code/modules/vore/eating/belly_obj.dm @@ -542,8 +542,6 @@ if (!(R in contents)) return // User is not in this belly - 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.)") to_chat(owner,"Someone is attempting to climb out of your [lowertext(name)]!") diff --git a/code/modules/vore/eating/bellymodes.dm b/code/modules/vore/eating/bellymodes.dm index 77864021b4..291ef8654f 100644 --- a/code/modules/vore/eating/bellymodes.dm +++ b/code/modules/vore/eating/bellymodes.dm @@ -76,7 +76,7 @@ play_sound = pick(pred_digest) //Pref protection! - if (!M.vore_flags & DIGESTABLE || M.vore_flags & ABSORBED) + if (!CHECK_BITFIELD(M.vore_flags, DIGESTABLE) || M.vore_flags & ABSORBED) continue //Person just died in guts! diff --git a/code/modules/vore/eating/living.dm b/code/modules/vore/eating/living.dm index bffb8b2517..9395cef952 100644 --- a/code/modules/vore/eating/living.dm +++ b/code/modules/vore/eating/living.dm @@ -116,7 +116,7 @@ testing("[user] attempted to feed [prey] to [pred], via [lowertext(belly.name)] but it went wrong.") return - if (!prey.vore_flags & DEVOURABLE) + if (!CHECK_BITFIELD(prey.vore_flags, DEVOURABLE)) to_chat(user, "This can't be eaten!") return FALSE @@ -349,7 +349,7 @@ if(incapacitated(ignore_restraints = TRUE)) to_chat(src, "You can't do that while incapacitated.") return - if(next_move > world.time) + if(!CheckActionCooldown()) to_chat(src, "You can't do that so fast, slow down.") return @@ -366,11 +366,10 @@ if(QDELETED(tasted) || (tasted.ckey && !(tasted.client?.prefs.vore_flags & LICKABLE)) || !Adjacent(tasted) || incapacitated(ignore_restraints = TRUE)) return - changeNext_move(CLICK_CD_MELEE) + DelayNextAction(CLICK_CD_MELEE) visible_message("[src] licks [tasted]!","You lick [tasted]. They taste rather like [tasted.get_taste_message()].","Slurp!") - /mob/living/proc/get_taste_message(allow_generic = TRUE, datum/species/mrace) if(!vore_taste && !allow_generic) return FALSE diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index d4d92f54c4..2cb3a83257 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -11,9 +11,13 @@ var/icon_left = "bloodhand_left" var/icon_right = "bloodhand_right" hitsound = 'sound/hallucinations/growl1.ogg' - force = 21 // Just enough to break airlocks with melee attacks + force = 18 + sharpness = SHARP_POINTY //it's a claw, they're sharp. damtype = "brute" total_mass = TOTAL_MASS_HAND_REPLACEMENT + sharpness = SHARP_EDGED + wound_bonus = -30 + bare_wound_bonus = 15 /obj/item/zombie_hand/Initialize() . = ..() @@ -32,11 +36,15 @@ . = ..() if(!proximity_flag) return - else if(isliving(target)) - if(ishuman(target)) - try_to_zombie_infect(target) - else - check_feast(target, user) + else + if(istype(target, /obj)) //do far more damage to non mobs so we can get through airlocks + var/obj/target_object = target + target_object.take_damage(force * 3, BRUTE, "melee", 0) + else if(isliving(target)) + if(ishuman(target)) + try_to_zombie_infect(target) + else + check_feast(target, user) /proc/try_to_zombie_infect(mob/living/carbon/human/target) CHECK_DNA_AND_SPECIES(target) @@ -52,8 +60,6 @@ infection = new() infection.Insert(target) - - /obj/item/zombie_hand/suicide_act(mob/user) user.visible_message("[user] is ripping [user.p_their()] brains out! It looks like [user.p_theyre()] trying to commit suicide!") if(isliving(user)) @@ -75,3 +81,14 @@ user.updatehealth() user.adjustOrganLoss(ORGAN_SLOT_BRAIN, -hp_gained) // Zom Bee gibbers "BRAAAAISNSs!1!" user.adjust_nutrition(hp_gained, NUTRITION_LEVEL_FULL) + +/obj/item/paper/guides/antag/romerol_instructions + info = "How to do necromancy with chemicals:
      \ +
        \ +
      • Use a dropper or syringe (provided) to inject the Romerol (provided) into a target (not provided)
      • \ +
      • Wait for said target to die, or speed the process up by doing it yourself
      • \ +
      • Run away from the target, as they will be hostile when rising back up
      • \ +
      • Optionally: Inject chemical into foods and drinks to further spread possible infection
      • \ +
      • ???
      • \ +
      • Complete assigned objectives amidst the chaos
      • \ +
      " \ No newline at end of file diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index 3d045ba31e..2681f781a9 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -93,7 +93,8 @@ playsound(owner.loc, 'sound/hallucinations/far_noise.ogg', 50, 1) owner.do_jitter_animation(living_transformation_time) owner.Stun(living_transformation_time) - to_chat(owner, "You are now a zombie!") + to_chat(owner, "You are now a zombie! You claw and bite, turning your fellow crewmembers into friends that help spread the plague.") + to_chat(owner, "You are a zombie. Please act like one. Letting the crew remove the tumor inside your brain is a dick move to whoever infected you. Please do not do it.") /obj/item/organ/zombie_infection/nodamage causes_damage = FALSE diff --git a/config/awaymissionconfig.txt b/config/awaymissionconfig.txt index c6a5d9ef8f..768942c434 100644 --- a/config/awaymissionconfig.txt +++ b/config/awaymissionconfig.txt @@ -7,16 +7,13 @@ #Do NOT tick the maps during compile -- the game uses this list to decide which map to load. Ticking the maps will result in them ALL being loaded at once. #DO tick the associated code file for the away mission you are enabling. Otherwise, the map will be trying to reference objects which do not exist, which will cause runtime errors! -#_maps/RandomZLevels/away_mission/blackmarketpackers.dmm -#_maps/RandomZLevels/away_mission/spacebattle.dmm #_maps/RandomZLevels/away_mission/TheBeach.dmm #_maps/RandomZLevels/away_mission/Academy.dmm #_maps/RandomZLevels/away_mission/wildwest.dmm #_maps/RandomZLevels/away_mission/challenge.dmm -#_maps/RandomZLevels/away_mission/centcomAway.dmm #_maps/RandomZLevels/away_mission/moonoutpost19.dmm #_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm #_maps/RandomZLevels/away_mission/caves.dmm #_maps/RandomZLevels/away_mission/snowdin.dmm #_maps/RandomZLevels/away_mission/research.dmm -#_maps/RandomZLevels/away_mission/Cabin.dmm +#_maps/RandomZLevels/away_mission/SnowCabin.dmm \ No newline at end of file diff --git a/config/config.txt b/config/config.txt index 35af0e848b..46f9a0cdc4 100644 --- a/config/config.txt +++ b/config/config.txt @@ -8,6 +8,7 @@ $include donator_groupings.txt $include dynamic_config.txt $include plushies/defines.txt $include job_threats.txt +$include policy.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game # Example usage: @@ -524,3 +525,7 @@ FAIL2TOPIC_RULE_NAME _dd_fail2topic ## Enable automatic profiling - Byond 513.1506 and newer only. #AUTO_PROFILE + +## Uncomment to enable global ban DB using the provided URL. The API should expect to receive a ckey at the end of the URL. +## More API details can be found here: https://centcom.melonmesa.com +CENTCOM_BAN_DB https://centcom.melonmesa.com/ban/search diff --git a/config/game_options.txt b/config/game_options.txt index 405ec0405a..a5b0d0b8c4 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -116,6 +116,7 @@ CONTINUOUS CHANGELING CONTINUOUS WIZARD #CONTINUOUS MONKEY CONTINUOUS BLOODSUCKER +CONTINUOUS HERESY ##Note: do not toggle continuous off for these modes, as they have no antagonists and would thus end immediately! @@ -445,6 +446,7 @@ ROUNDSTART_RACES plasmaman #ROUNDSTART_RACES shadow ROUNDSTART_RACES felinid ROUNDSTART_RACES dwarf +ROUNDSTART_RACES ethereal ## Races that are better than humans in some ways, but worse in others #ROUNDSTART_RACES jelly diff --git a/config/in_character_filter.txt b/config/in_character_filter.txt new file mode 100644 index 0000000000..46df3fd60c --- /dev/null +++ b/config/in_character_filter.txt @@ -0,0 +1,7 @@ +############################################################################################### +# Words that will block in character chat messages from sending. # +# Case is not important. Commented-out examples are listed below, just remove the "#". # +############################################################################################### +#lol +#omg +#wtf \ No newline at end of file diff --git a/config/plushies/defines.txt b/config/plushies/defines.txt index e7a92f6ac2..7cd1d88f3e 100644 --- a/config/plushies/defines.txt +++ b/config/plushies/defines.txt @@ -1,2 +1,2 @@ -# EXAMPLE -# SNOWFLAKE_PLUSHIES example {"name":"example","desc":"thanks, coders.","icon_state":"","attack_verb":["thumped","whomped","bumped"],"squeak_override":{"sound/weapons/magout.ogg":1}} +# EXAMPLE +# SNOWFLAKE_PLUSHIES example {"name":"example","desc":"thanks, coders.","icon_state":"","attack_verb":["thumped","whomped","bumped"],"squeak_override":{"sound/weapons/magout.ogg":1}} diff --git a/config/policy.txt b/config/policy.txt new file mode 100644 index 0000000000..610acd2be8 --- /dev/null +++ b/config/policy.txt @@ -0,0 +1,13 @@ +## Policy configuration +## Current valid keys are: +## ON_CLONE - displayed after a successful cloning operation to the cloned person +## ON_DEFIB_INTACT - displayed after defibbing before memory loss time threshold +## ON_DEFIB_LATE - displayed after defibbing post memory loss time threshold +## +## EXAMPLE: +## POLICYCONFIG ON_CLONE insert text here span classes are fully supported + +## Misc entries for above + +## Defib time limit for "cloning memory disorder" memory loss in seconds +# DEFIB_CMD_TIME_LIMIT 300 diff --git a/config/spaceRuinBlacklist.txt b/config/spaceRuinBlacklist.txt index 90682f5bad..969e4135f6 100644 --- a/config/spaceRuinBlacklist.txt +++ b/config/spaceRuinBlacklist.txt @@ -52,3 +52,4 @@ #_maps/RandomRuins/SpaceRuins/arcade.dmm #_maps/RandomRuins/SpaceRuins/spacehermit.dmm #_maps/RandomRuins/SpaceRuins/advancedlab.dmm +#_maps/RandomRuins/SpaceRuins/spacediner.dmm diff --git a/dependencies.sh b/dependencies.sh index 83254509b9..75e49f3fe1 100644 --- a/dependencies.sh +++ b/dependencies.sh @@ -11,7 +11,7 @@ export BYOND_MINOR=${LIST[1]} unset LIST #rust_g git tag -export RUST_G_VERSION=0.4.3 +export RUST_G_VERSION=0.4.4 #bsql git tag export BSQL_VERSION=v1.4.0.0 diff --git a/html/admin/view_variables.css b/html/admin/view_variables.css index 83b3a37f3c..34c1a211eb 100644 --- a/html/admin/view_variables.css +++ b/html/admin/view_variables.css @@ -30,6 +30,6 @@ table.matrixbrak td.lbrak { border-right: none; } table.matrixbrak td.rbrak { - border-right: solid 0.5exrgb(95, 61, 61)k; + border-right: solid 0.5ex black; border-left: none; } diff --git a/html/changelog.html b/html/changelog.html index 248425b507..b1a10867b5 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,324 +50,1047 @@ -->
      -

      19 June 2020

      -

      Bhijn updated:

      +

      30 August 2020

      +

      raspy-on-osu updated:

        -
      • Atmos can no longer become completely bricked
      • +
      • new explosion echoes
      • +
      • explosion echo range
      • +
      • 5 new explosion related sounds
      -

      Funce updated:

      + +

      28 August 2020

      +

      timothyteakettle updated:

        -
      • Square root circuit should now actually work.
      • +
      • an ancient game over a thousand years old has re-emerged among crewmembers - rock paper scissors
      • +
      • you can now choose a body sprite as an anthromorph or anthromorphic insect, and can choose from aquatic/avian and apid respectively (and obviously back to the defaults too)
      -

      SmArtKar updated:

      + +

      27 August 2020

      +

      silicons updated:

        -
      • Fixed my runtimes
      • -
      -

      TheSpaghetti updated:

      -
        -
      • more insectoid insects
      • -
      -

      kevinz000 updated:

      -
        -
      • bay/polaris style say_emphasis has been added. You can now |italicize| _underline_ and +bold+ your messages.
      • +
      • eyebeam lighting can only have 128 maximum HSV saturation now.
      • +
      • no more shotgun stripper clips in boxes.
      • +
      • goliath tentacles now do 20 damage to mechs at 25% ap

      timothyteakettle updated:

        -
      • Adds the brain trauma event, where one player gets a random brain trauma!
      • -
      • Adds the wisdom cow event, where the wisdom cow appears on the station!
      • -
      • Adds the fake virus event, where people get fake virus symptoms.
      • -
      • Adds the stray cargo pod event, where a cargo pod crashes into the station.
      • -
      • Adds the fugitives event, where fugitives are loose on the station, and it's the hunters jobs to capture them.
      • +
      • changing your character's gender won't randomize its hairstyle and facial hairstyle now
      -

      18 June 2020

      -

      Detective-Google updated:

      +

      26 August 2020

      +

      ancientpower updated:

        -
      • cog is now less the suck
      • -
      • couple little derpy bits
      • -
      • malf disk and illegal tech disk moved from ashwalker base (guaranteed) to tendrils (chance based)
      • +
      • Ghosts can read newscasters by clicking on them.
      -

      SmArtKar updated:

      +

      silicons updated:

        -
      • Ported shuttles from beestation
      • -
      -

      timothyteakettle updated:

      -
        -
      • embeds got reworked, sticky tape was added, more bullets that ricochet also added
      • -
      • medbots can now be tipped over
      • -
      • added more medbot sounds
      • +
      • hierophant vortex blasts now have 50% armor penetration vs mecha
      • +
      • ventcrawling now kicks off every attached/buckled mob, even for non humans.
      -

      17 June 2020

      -

      SmArtKar updated:

      +

      25 August 2020

      +

      Hatterhat updated:

        -
      • New ID icons
      • -
      • Sutures and Meshes
      • +
      • Insidious combat gloves have been replaced by insidious guerilla gloves. They're generally the same, except now you can tackle with them.
      -

      Trilbyspaceclone updated:

      +

      Literallynotpickles updated:

        -
      • Gin export takes gin now
      • -
      - -

      16 June 2020

      -

      Ghommie updated:

      -
        -
      • You can't blink nor use LOOC/AOOC as a petrified statue anymore.
      • -
      -

      Trilbyspaceclone updated:

      -
        -
      • BEPIS decal painter has been moved to venders, replacing it being the flashdark
      • -
      -

      kevinz000 updated:

      -
        -
      • projectile ricochets now use a less hilariously terrible way of being handled and should be easier to w
      • -
      • projectile runtime/ricocheting
      • -
      • Lobotomy no longer has a 50% chance of giving you a nigh-unremovable trauma, but does 50 brain damage even on success. On failure, it will give you a lobotomy-class trauma.
      • -
      • spinesnapping from tackling now only gives a lobotomy class trauma instead of magic.
      • -
      -

      timothyteakettle updated:

      -
        -
      • Food carts now function as intended, allowing the pouring and mixing of drinks.
      • -
      • slimes can now change their color using alter form
      • -
      - -

      15 June 2020

      -

      Anturk, kevinz000 updated:

      -
        -
      • VV now properly allows access to datums in associative lists
      • -
      • SDQL2 printout has been upgraded for the 5th time.
      • -
      -

      kevinz000 updated:

      -
        -
      • plushies now work. credits to timothytea.
      • -
      • You can now tape knives to cleanbots
      • -
      -

      kevinz000 (port from VOREStation) updated:

      -
        -
      • Ported zoomba skins for cyborgs.
      • -
      - -

      14 June 2020

      -

      Bhijn updated:

      -
        -
      • raw HTML can no longer be used in flavortext
      • -
      • Added Lesbian Visibility Day (April 26th)
      • -
      • Added Bisexual Visibility Day (September 23rd)
      • -
      • Added Coming Out Day! (October 11th)
      • -
      • Added Intersex Awareness Day (October 26th)
      • -
      • Added Transgender Awareness Week (November 13th - 19th)
      • -
      • Added the Transgender Day of Remembrance (November 20th)
      • -
      • Added Asexual Awareness Week (Last full week of October, this year it'll be Oct. 25-31)
      • -
      • Added the Stonewall Riot Anniversary (June 28)
      • -
      • Moth week is now *actually* the last full week of July, instead of the 4th of every weekday + the 5th Sunday.
      • -
      -

      Floof Ball / Kathrin Morrison / Floof Ball#0798 updated:

      -
        -
      • Improvised Pistol + 32 ACP ammo.
      • -
      • Improvised Energy Gun. Fires 5 shots of 10 burn damage each. Can be upgraded with a lens made from glassworking and T4 parts for a minor buff.
      • -
      • Ammo + gun part loot spawners for mappers.
      • -
      • New sprites for Improvised Rifle, the ability to sling the rifle and a sprite for that.
      • -
      • New sprites for the Improvised Shotgun and its sling sprite.
      • -
      • Improvised shotguns are now two-handed only.
      • -
      • Improvised shotguns now only have a much less harsh 0.9* modifier, keeping them two hits to crit with slugs and buckshot. It can no longer be dual-wielded but can still be sawn off for w_class medium (can fit in backpacks).
      • -
      • Missing handsaw icons added in.
      • -
      • Crafting table cleaned up into sections.
      • -
      -

      Ghommie updated:

      -
        -
      • changed the weak attack message prefix from "inefficiently" to "limply", "feebly" and "saplessly" and lowered the threshold.
      • -
      • Fixing old beserker hardsuits having the wrong helmet type.
      • -
      -

      The0bserver and Stewydeadmike updated:

      -
        -
      • Hey, there's a bit of dust in this recipe book! Recipes using peas? How many recipes does this book even have?
      • -
      • Adds 6 new food items, and 1 new consumable reagent using all forms of the recently discovered peas. Ask your local botanist and chef for them today!
      • -
      -

      YakumoChen updated:

      -
        -
      • Adds polychrome options to loadout
      • -
      • Adds risque polychrome options to Kinkmate vendors
      • -
      -

      kevinz000 updated:

      -
        -
      • emissive blockers can no longer be radioactive.
      • -
      • Ghosts can now scan air inside most objects that contain air by clicking on them.
      • -
      • Directional blocking has been added, keybound to G. This will reduce a portion of incoming damage if done with eligible items at the cost of stamina damage incurred to the user based on damage blocked as well as while active, as well as in most cases preventing the user from doing any attacks while this is active.
      • -
      • Parrying has been added, keybound to F. Timing-based counterattacks, effect heavily dependent on the item, WIP.
      • -
      • Disks are now smaller.
      • -
      - -

      12 June 2020

      -

      EmeraldSundisk updated:

      -
        -
      • The Detective's Office has been commandeered in order to serve a Head of Security. Detectives will find their new office within starboard maintenance.
      • -
      • Adds the Head of Security's standard equipment to their new office.
      • -
      • Slight adjustment/expansion to the main security department
      • -
      • Additional maintenance work
      • -
      -

      timothyteakettle updated:

      -
        -
      • Crabs, cockroaches, slimes and crabs are now small enough to fit in pet carriers
      • -
      - -

      11 June 2020

      -

      Ghommie updated:

      -
        -
      • Balanced vending machine prices to be generally more affordable, a minority has been priced up though.
      • -
      - -

      10 June 2020

      -

      DeltaFire15 updated:

      -
        -
      • Golems / simillar now inherit the neutered antag datum if the creator is neutered.
      • -
      -

      Ghommie updated:

      -
        -
      • Fixing missing pill type buttons from the chem master UI.
      • -
      -

      Naksu updated:

      -
        -
      • Lighting corner updates are ever so slightly faster.
      • -
      -

      Putnam for helping me code the contamination clearing on people updated:

      -
        -
      • Lab made Zeolites have been remade anew and more affective now that they refined the best possable way to mix and make a supper Zeolite capable of clearing contamination form not only people but items!
      • -
      -

      Trilbyspaceclone updated:

      -
        -
      • Tank Dispender has been moved into toxin storage from toxins
      • -
      -

      kevinz000 updated:

      -
        -
      • traitor classes can now be poplocked. hijack/glorious death are now locked to 25/20 respectively.
      • -
      -

      timothyteakettle updated:

      -
        -
      • adds a new fermichem, used for creating sentient plushies!
      • -
      • Mice can now breed using cheese wedges
      • -
      • Royal cheese can be crafted to convert a mouse into king rat
      • -
      - -

      09 June 2020

      -

      Anonymous updated:

      -
        -
      • Added Orville-inspired clothing as a worthy alternative to Trek stuff.
      • -
      • Adds chaplain role allowance to the TMP Service Uniform loadout.
      • -
      • Adds paramedic in every medsci mentioned uniform loadout.
      • -
      -

      DeltaFire15 updated:

      -
        -
      • Offstation AIs can once again only interact with their z-level
      • -
      -

      Ghommie updated:

      -
        -
      • Fixing IC material containers interaction with stacks, for real.
      • -
      -

      Trilbyspaceclone updated:

      -
        -
      • Gasses like BZ and Masiam seem to just sell for less in cargo, markets seem to change it seems
      • -
      -

      kevinz000 updated:

      -
        -
      • plantpeople should stop dying in the halls now
      • -
      • Modifier-independent hotkey bindings have been added.
      • -
      - -

      08 June 2020

      -

      DeltaFire15 updated:

      -
        -
      • Delinging now properly removes their special role
      • -
      • Keycard auth devices now require two seperate IDs with sufficient access to auth.
      • -
      -

      Linzolle updated:

      -
        -
      • shotguns no longer delete chambered shells while firing
      • -
      -

      kevinz000 updated:

      -
        -
      • test
      • -
      -

      shellspeed1 updated:

      -
        -
      • Internal tanks are now printable at the engineering lathe.
      • -
      -

      timothyteakettle updated:

      -
        -
      • newly created areas using blueprints now maintain the previous areas noteleport value
      • -
      • kudzu seeds now actually spawn vines
      • -
      - -

      19 April 2020

      -

      Anonymous updated:

      -
        -
      • Xenohybrids will now scream like xeno.
      • -
      -

      Arturlang updated:

      -
        -
      • You can no longer spam craft things using the crafting menu
      • -
      -

      Detective-Google updated:

      -
        -
      • uncorks some of Lambda's rooms.
      • -
      -

      Ghommie updated:

      -
        -
      • Custom skin tone preferences.
      • -
      • Normalized box dorm lockers. Also removed a straight jacket found in the same area.
      • -
      -

      Jake Park updated:

      -
        -
      • fixed path name for youtool vending
      • +
      • You can now equip handheld crew monitors on all medical-related winter coats.

      Putnam3145 updated:

        -
      • Objectives now clean theirselves up instead of leaving null entries in lists everywhere.
      • +
      • vore now ejects occupants on death
      -

      Seris02 updated:

      +

      raspy-on-osu updated:

        -
      • stops magboots from not updating slowdowns
      • +
      • Thermoelectric Generator power output
      -

      Trilbyspaceclone updated:

      +

      timothyteakettle updated:

        -
      • Maints have seen an uptick in left over types of welders, and tools. As well as different types of masks
      • -
      • New type of 02 locker - Rng! It can have almost any type of gas/breath mask and almost any type of o2 tank as well as even plasma men internals - Fancy!
      • -
      • Tool lockers have 70% odds to have a spare random tool inside!
      • -
      • 12 new more drinks for most races!
      • -
      • New animations for mauna loa, and colour swap from red to blue for a Paramedic Hardsuit helm
      • -
      • Lowers cog champ ((the drink)) flare rate
      • -
      • Six more Sci based bounties have been posted at your local Cargo Bounty Request console
      • -
      • Mimes have made catnip plants not become invisible. How helpful.
      • -
      • Honey Palm now distills into mead rather then wine
      • +
      • I.P.Cs now short their circuits when expressing emotion, causing sparks to appear around them.
      -

      UristMcAstronaut updated:

      + +

      24 August 2020

      +

      MrJWhit updated:

        -
      • Adds circuit analyzers to maps and to integrated circuit printer and circuitry starter crate.
      • +
      • Fixes areas on expanded airlocks
      • +
      +

      silicons updated:

      +
        +
      • wormhole jaunters work
      • +
      • wormhole jaunters no longer get interference from bags of holding
      • +
      • airlocks now only shock on pulse/wirecutters instead of on tgui panel open.
      • +
      +

      timothyteakettle updated:

      +
        +
      • three new items are in the loadout for all donators
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • contraband black evening gloves in kinkvend
      • +
      + +

      23 August 2020

      +

      DeltaFire15 updated:

      +
        +
      • silicons and clockies can now access APCs properly
      • +
      +

      EmeraldSundisk updated:

      +
        +
      • Medbay now has a smartfridge for organ storage
      • +
      • Slight enhancements to the station's electrical wiring layout
      • +
      • Very small library renovation
      • +
      • Exterior airlocks have been given proper air systems for safety's sake
      • +
      +

      Ghommie updated:

      +
        +
      • Stops shielded hardsuits from slowly turning the wearer into a big glowing ball of stacked energy shield overlays.
      • +
      • the shielding overlay is merely visual as result. Aim your clicks.
      • +
      +

      Ludox235 updated:

      +
        +
      • no more 10 pop xenos (25pop now)
      • +
      +

      MrJWhit updated:

      +
        +
      • Increases the majority of airlocks by 1 tile.
      • +
      • Minor adjustments to the TEG engine.
      • +
      +

      Putnam3145 updated:

      +
        +
      • Simplemobs no longer count in dynamic.
      • +
      • "Story" storyteller no longer starts at a ludicrously low threat, always.
      • +
      • Blob threat now scales with coverage.
      • +
      • One person with their pref on no longer overpowers 40 people who might not even know there is one.
      • +
      • Negative-weight rulesets are no longer put into the list.
      • +
      +

      kiwedespars updated:

      +
        +
      • removed durathread from armwraps recipe.
      • +
      +

      lolman360 updated:

      +
        +
      • breath mask balaclava
      • +
      +

      timothyteakettle updated:

      +
        +
      • lizards are now a recommended species for mam snouts
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • new sprites for the temporal katana
      • +
      • suiciding with the temporal katana omae wa mou shinderius you into the shadow realm
      • +
      • twilight isnt earrape
      • +
      + +

      22 August 2020

      +

      Time-Green (copypasta'd by lolman360) updated:

      +
        +
      • plumbing
      • +
      • automatic hydro trays
      • +
      + +

      21 August 2020

      +

      LetterN updated:

      +
        +
      • Updates and adds some of the tips
      • +
      +

      Putnam3145 updated:

      +
        +
      • added reftracking as a compile flag
      • +
      +

      SmArtKar updated:

      +
        +
      • RSD limitation is now 500 tiles
      • +
      • Fixed broken RSD sprites
      • +
      • Removed that shuttle limit
      • +
      +

      timothyteakettle updated:

      +
        +
      • two snouts can once again be chosen in customization
      • +
      • lizard snouts work again
      • +
      + +

      20 August 2020

      +

      DeltaFire15 updated:

      +
        +
      • The cooking oil damage formula is no longer scuffed.
      • +
      • Changed the clockie help-link to lead to our own wiki.
      • +
      +

      Fikou updated:

      +
        +
      • admins can now do html in ahelps properly
      • +
      +

      Hatterhat updated:

      +
        +
      • Pirate threats are now announced as "business propositions", and their arrivals are now also announced properly.
      • +
      +

      tiramisuapimancer updated:

      +
        +
      • Ethereal hair is now their body color instead of accidentally white
      • +
      + +

      18 August 2020

      +

      DeltaFire15 updated:

      +
        +
      • kindle cast time: 15ds -> 25ds
      • +
      • Moved the Belligerent Scripture to where it should be in the code
      • +
      +

      Detective-Google updated:

      +
        +
      • glass floors
      • +
      • uncrowbarrable plasma floors tweak:disco inferno's plasma floors can no longer be crowbarred.
      • +
      • ghost cafe has funky fresh art
      • +
      • you can actually remove glass floors now
      • +
      • get_equipped_items is hopefully less gross
      • +
      • plasma cutters are no longer gay
      • +
      +

      Hatterhat updated:

      +
        +
      • Slaughter demons (and laughter demons, being a subtype) are MOB_SIZE_LARGE, with one of the more immediate effects being able to mark them with a crusher and backstab them.
      • +
      • The funny blyat men have stumbled upon another surplus of Mosin-Nagants and are starting to pack them into crates again.
      • +
      • Vehicle riders can now, by default, get shot in the face and/or chest.
      • +
      • Adminspawn only .357 DumDum rounds! Because sometimes the other guy just really needs to hurt.
      • +
      • Bluespace beakers now have a chemical window through the side that shows chemical overlays.
      • +
      • Plant DNA manipulators now let you chuck things over them. Or they WOULD, if LETPASSTHROW worked half a damn.
      • +
      +

      LetterN updated:

      +
        +
      • uplink implant states
      • +
      • tweaks how role assigning works
      • +
      +

      MrJWhit updated:

      +
        +
      • Gives ashwalkers nightvision
      • +
      • Makes tesla blast people, not the environment, to save the server.
      • +
      +

      TheObserver-sys updated:

      +
        +
      • moves Garlic sprites from growing.dmi to growing_vegetable.dmi
      • +
      • Removes the unused Electric Lime mutation, it just takes up space with no actual function nor sprites.
      • +
      • Gives Catnip growing sprites
      • +
      • Removes redundant images in growing.dmi
      • +
      +

      kiwedespars updated:

      +
        +
      • 10 force to a fucking rubber cock.
      • +
      +

      lolman360 updated:

      +
        +
      • shotgun stripper clip nerf. ammoboxes can now accept a load_delay that happens when they attack a magazine, internal or external.
      • +
      +

      ported from tg updated:

      +
        +
      • bronze airlocks and windows can now be built
      • +
      • i also tweaked bronze flooring to be cheaper.
      • +
      +

      silicons updated:

      +
        +
      • stamina draining projectiles without stamina for their primary damage type now has their stamina damage taken into account for shield blocking, rather than the block being done for free for that.
      • +
      +

      timothyteakettle updated:

      +
        +
      • snowflake code tidyup
      • +
      • snowflake code for mutant bodypart selection has been rewritten to be ~14x shorter
      • +
      • meat type and horns can now be selected by any species
      • +
      + +

      17 August 2020

      +

      DeltaFire15 updated:

      +
        +
      • Cogscarabs are no longer always Pogscarabs
      • +
      +

      Strazyplus updated:

      +
        +
      • Added drakeborgs
      • +
      • Added drakeplushies
      • +
      • added drakeborg sprites
      • +
      • added drakeplushie sprites
      • +
      • changed some code - added drakeplushies to backpack loadout Removed duplicate voresleeper belly sprites from engdrake & jantidrake. [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/)
      • +
      • Added CC BY-NC-SA 3.0 license details to icon/mob/cyborg moved drakeborg.dmi to icon/mob/cyborg
      • +
      + +

      16 August 2020

      +

      kiwedespars updated:

      +
        +
      • nerfed hypereut chaplain weapon.
      • +
      • 50% rng blockchance -> 0%
      • +
      • parry made much worse because it's an actual weapon and a roundstart one at that.
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • tips
      • +
      + +

      15 August 2020

      +

      LetterN updated:

      +
        +
      • missing anomaly core icons
      • +
      • wrong state. blame the tg vertion i copied
      • +
      +

      silicons updated:

      +
        +
      • the 8 rotation limit from clockwork chairs has been removed. please don't abuse this.
      • +
      • ethereals can now wear underwear
      • +
      + +

      14 August 2020

      +

      silicons updated:

      +
        +
      • abductors can buy things
      • +
      + +

      13 August 2020

      +

      LetterN updated:

      +
        +
      • Removes fermisleepers and reverts them to tg ones
      • +
      + +

      12 August 2020

      +

      DeltaFire15 updated:

      +
        +
      • hellgun single-pack classification: goodies -> armory
      • +
      +

      Detective-Google updated:

      +
        +
      • hallway table hallway table
      • +
      +

      Hatterhat updated:

      +
        +
      • The temporal katana is now slightly more worthy of the 2 spell point cost, with a smaller, antimagic respecting timestop, less force, and no random blockchance. Society has progressed past the need for blockchance.
      • +
      +

      LetterN updated:

      +
        +
      • Mafia Component
      • +
      • Fixed missing icons and handtele
      • +
      +

      Putnam3145 updated:

      +
        +
      • a whole lot of jank regarding funny part sprite display.
      • +
      +

      Toriate updated:

      +
        +
      • Opossums have migrated into the maintenance tunnels! Seek them out at your own peril!
      • +
      +

      ancientpower updated:

      +
        +
      • Doors added to the west side of box medbay to make things a bit more manageable.

      kappa-sama updated:

        -
      • aranesp heals 10 instead of 18 stamina per tick
      • -
      • removed roundstart hyper earrape screams from xenohybrids
      • +
      • smuggler satchel cost 2->1
      • +
      • radio jammer cost 5->2
      • +
      • smuggler satchel uplink description now implies that persistence is disabled
      -

      kevinz000 updated:

      +

      lolman360 updated:

        -
      • you can no longer stun xenos
      • -
      • Contractor kits are now poplocked to 30 players.
      • -
      • Shield bashing has been added
      • +
      • renameable necklace (accessory, attaches to suit) and ring (glove slot.)
      • +
      • custom rename is now 2048 characters? i think it's characters.
      • +
      +

      silicons updated:

      +
        +
      • You can now use anything as an emoji by doing :/obj/item/path/to/item:. This works for any /atom or subtype.
      • +
      +

      timothyteakettle updated:

      +
        +
      • syndicate agents now have access to mechanical aim enhancers which allow them to aim bullets to bounce off walls
      • +
      • ricochets work properly now for the bullets that support them
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • hair and some sechuds
      • +
      • ce hardsuit radproofing
      • +
      + +

      11 August 2020

      +

      Hatterhat updated:

      +
        +
      • PDA uplinks can now steal from pens. Properly. Just make sure to have a pen in your PDA, first.
      • +
      +

      kappa-sama updated:

      +
        +
      • tracer no longer gives you full stamheals per use
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • volaju two
      • +
      + +

      10 August 2020

      +

      Hatterhat updated:

      +
        +
      • Parry counterattack text now shows up.
      • +
      • Sterilized gauze is now better at stopping bleeding, and applies slightly faster. Very slightly faster.
      • +
      • Ointment and sutures now hold more in a stack (12 and 15, respectively).
      • +
      • Sterilized gauze can now be made by just pouring 10u sterilizine onto standard medical gauze, instead of having to craft it. Why you had to craft it, I will honestly never know.
      • +
      • Proto-kinetic glaives are more expensive, stagger/cooldown on failed parries increased slightly, perfect parries required for counterattack.
      • +
      • New item: Temporal Katana. 2 points for wizards, timestops upon successful parry, bokken quickparry stats (100 force on melee counter!).
      • +
      • Also you can *smirk. This has no mechanical effect, other than being smug.
      • +
      +

      KeRSedChaplain updated:

      +
        +
      • Added a guide for romerol usage
      • +
      • made infectious zombies not enter softcrit and take no stamina damage
      • +
      +

      LetterN updated:

      +
        +
      • clocktheme color
      • +
      • Ports TGUI-4
      • +
      +

      Lynxless updated:

      +
        +
      • Ports TG #51879
      • +
      +

      Owai-Seek updated:

      +
        +
      • Meatballs now spawn raw from food processors.
      • +
      +

      Putnam3145 updated:

      +
        +
      • Ethereals
      • +
      • (Hexa)crocin
      • +
      • (Hexa)camphor
      • +
      • Tweaked wording for marking tickets IC issue.
      • +
      • Rerolling your traitor goals will ONLY give you "proper" objectives.
      • +
      +

      Seris02 updated:

      +
        +
      • borgs being able to select and use a module when it's too damaged
      • +
      +

      Sishen1542 updated:

      +
        +
      • gave chairs active block/parry in exchange for removal of block_chance
      • +
      • replaces box whiteship tbaton with truncheon
      • +
      +

      kappa-sama updated:

      +
        +
      • made the Dirty Magazines crate cost 4000 instead of 12000 credits
      • +
      • MODS I SPILLED MU JUICE HEJPPHRLP HELPJ JLEP HELP
      • +
      +

      silicons updated:

      +
        +
      • player made areas are no longer valid for malf hacking
      • +
      • default space levels is 4 again.
      • +
      • rats now swarm instead of stacking on one spot.
      • +
      • getting hit by an explosion will now barely hard knockdown, but will leave you somewhat winded.
      • +
      +

      timothyteakettle updated:

      +
        +
      • speech verbs copy through dna copying now
      • +
      + +

      09 August 2020

      +

      Hatterhat updated:

      +
        +
      • Proto-kinetic glaives (not crushers) can parry now.
      • +
      +

      MrJWhit updated:

      +
        +
      • Adds a second shutter on the top of the hop line
      • +
      +

      silicons updated:

      +
        +
      • immovable rods no longer drop down chasms
      • +
      • fun removal: squeaking objects now have an 1 second cooldown between squeaks, and will have a 33% chance of interrupting any other squeaking object when Cross()ing, meaning no more ear-fuck conveyor belts.
      • +
      + +

      08 August 2020

      +

      DeltaFire15 updated:

      +
        +
      • Roundstart cultists now start with a replica fabricator - no brass though, make your own.
      • +
      • Kindle cast time: 10 > 15, mute after stun end: 2 > 5, slur after mute end: 3 > 5
      • +
      • The ratvarian spear no longer adds negative vitality under very specific circumstances.
      • +
      • The Ratvarian Spear can parry now! Short parries with low leeway, but low cooldown.
      • +
      • The brass claw, a implant-based weapon which gains combo on consecutive hits against the same target.
      • +
      • The sigil of rites, a sigil used to perform various rites with a cost of power and materials
      • +
      • The Rite of Advancement: Used to add a organ or cyberimplant to a clockie without need for surgery.
      • +
      • The Rite of Woundmending: Used to heal all wounds on another cultist, causing toxins damage in return.
      • +
      • The Rite of the Claw: Used to summon a brass claw implant. Maximum of 4 uses per round.
      • +
      +

      Hatterhat updated:

      +
        +
      • You can now buy a toolbox's worth of Mosin-Nagant ammo for a fairly discounted price.
      • +
      • Revolvers from the dedicated kit now have reskinning capabilities.
      • +
      • You can now actually buy the riflery primer, which lets you pump shotguns and work the Mosin's bolt faster.
      • +
      • Bulldog slug magazines now have a unique sprite.
      • +
      +

      Ludox235 updated:

      +
        +
      • Removed an abductee objective that told you to remove all oxygen.
      • +
      • Added a new abductee objective to replace the removed one.
      • +
      +

      Sishen1542 updated:

      +
        +
      • 🅱ï¸oneless
      • +
      • squishy slime emotes
      • +
      +

      timothyteakettle updated:

      +
        +
      • heparin makes you bleed half as much now
      • +
      • cuts make you bleed 25% less now
      • +
      • more items in the loadout and loadout has subcategories now for easier searching
      • +
      + +

      07 August 2020

      +

      dapnee updated:

      +
        +
      • fixed active tufs on some space ruins, murderdome VR, and a few on pubby, changed cargo autolathe to techfab, messed with pipe room leading to monastery.
      • +
      +

      lolman360 updated:

      +
        +
      • vendors are now unanchored when tipped. it just fell over it's not bolted to the ground anymore.
      • +
      • podpeople no fat when sunbathing.
      • +
      +

      silicons updated:

      +
        +
      • explosions only recurse one level into storage before dropping 1 level per storage layer.
      • +
      • volumetric storage is now minimum 16 pixels per item because 8 was ridiculous
      • +
      • shieldbash balanace --> balance
      • +
      • attempting to send too long of an emote will now reflect it back to you instead of cutting it off and discarding the overflow.
      • +
      • holoparasites can now play music
      • +
      • lethal blood now causes damaging bleeding instead of outright gibbing
      • +
      + +

      06 August 2020

      +

      Auris456852 updated:

      +
        +
      • Added B.O.O.P. Remote Control cartridges to the PTech.
      • +
      +

      Hatterhat updated:

      +
        +
      • Proto-kinetic glaives! Essentially a proto-kinetic crusher with a different blade, handguard, and goliath hide grip. Expensive, but elegant.
      • +
      • Door charges no longer knock people out.
      • +
      +

      Ludox235 updated:

      +
        +
      • You can now buy damaged AI upload modules in the traitor's uplink.
      • +
      +

      Seris02 updated:

      +
        +
      • fixed ghost chilis
      • +
      +

      Trilbyspaceclone updated:

      +
        +
      • 4 New blends of tea have been shipped to the station, and how to make them has been leaked!
      • +
      +

      b1tt3r1n0 updated:

      +
        +
      • Added the warp implant
      • +
      +

      dapnee updated:

      +
        +
      • added a hallway to telecoms for engineers to get there on meta
      • +
      +

      kappa-sama updated:

      +
        +
      • dildo circuit assemblies
      • +
      +

      lolman360 updated:

      +
        +
      • The Tendril-Mother on Lavaland has remembered how to make ashwalkers who know how to speak Draconic again.
      • +
      +

      timothyteakettle updated:

      +
        +
      • nanotrasen has decided to fire all disabled members of the security division and confiscate certain sentimental items from doctors
      • +
      • the custom tongue preference now passes through cloning so you spawn with your selected tongue
      • +
      • several changes to travelling traders so they look better and spawn slightly less often
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • nukies can buy holoparasites
      • +
      + +

      04 August 2020

      +

      Seris02 updated:

      +
        +
      • lizard spines
      • +
      +

      timothyteakettle updated:

      +
        +
      • due to further advancements in medical technology, you can now have holes poked into your body for fun and enjoyment
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • prefs for headpat wagging
      • +
      + +

      03 August 2020

      +

      KeRSedChaplain updated:

      +
        +
      • fixed clockwork guardians being able to reflect ranged weapons
      • +
      +

      Linzolle updated:

      +
        +
      • uv penlight no longer invisible
      • +
      +

      dapnee updated:

      +
        +
      • active turfs on box and xenohive, maintenance bar APC not being stringed correctly, turned a monitor to face a direction that makes sense, changed tag of camera in gravgen being misnamed
      • +
      +

      silicons updated:

      +
        +
      • shoves have been buffed to apply a status effect rather than a 0.85 movespeed modifier, meaning repeatedly shoving someone now renews the debuff
      • +
      • shoves now stagger for 3.5 seconds.
      • +
      • war operatives now actually time 20 minutes since roundstart to depart instead of 15.
      • +
      • explosive stand bombs can now be examined from any distance
      • +
      • explosive stand bombs are now a component.
      • +
      + +

      02 August 2020

      +

      Auris456852 updated:

      +
        +
      • Added B.O.O.P. Remote Control cartridges to the PTech.
      • +
      +

      Hatterhat updated:

      +
        +
      • Durathread reinforcement kits! Sprites by Toriate, sets jumpsuit armor to durathread levels, craft in the crafting menu.
      • +
      +

      KeRSedChaplain updated:

      +
        +
      • The belligerent scripture and a brass multitool, and a new marauder variant which act similar to holoparasites/guardian spirits.
      • +
      • Removed the abductor teleport consoles they get, removes abscond for the time being as I've not seen much use for it other than just spamming it and hoping you end up in the armory.
      • +
      • moved around scriptures to make the cult work better as being based around the station, makes the Ark scream more often and work as a summonable object, clockwork armor now has a flat 0 defense up to 10 instead of negatives against laser damage. Makes the Ark work better in a station based setting, as well as the Heralds beacon in case It works for the mode.
      • +
      • added powerloaderstep.ogg for Neovgre
      • +
      • changes 'Dread_Ipad.dmi' to 'clockwork_slab.dmi'
      • +
      +

      MrJWhit updated:

      +
        +
      • Adjusts abductor spawntext
      • +
      +

      Seris02 updated:

      +
        +
      • fixed replica pods
      • +
      +

      dapnee updated:

      +
        +
      • fixed active turfs on wizard ruin and space hermit, fixed missing APC's and added a light on Delta
      • +
      +

      ike709 and bobbahbrown updated:

      +
        +
      • Admins can now see your bans on (some) other servers.
      • +
      +

      kappa-sama updated:

      +
        +
      • chaplain cultists being able to convert people to full clockwork cult status
      • +
      +

      timothyteakettle updated:

      +
        +
      • combat mode now has weaker buffs in terms of damage dealt and took for being or not being in the mode
      • +
      • damage debuff for laying down has been decreased from 0.5x to 0.7x
      • +
      + +

      01 August 2020

      +

      dapnee updated:

      +
        +
      • added cake hat to bar, adds another atmostech spawn
      • +
      • sinks point in the right direction, APC won't spawn off the wall in circuits
      • +
      • changes commissary APC so it actually powers the room, adds a missing AIR alarm, arrivals no longer has active atmos tiles.
      • +
      +

      silicons updated:

      +
        +
      • toy shotguns no longer need 2 hands to fire
      • +
      • being on fire works again.
      • +
      +

      timothyteakettle updated:

      +
        +
      • monkeys no longer continuously bleed everywhere
      • +
      + +

      30 July 2020

      +

      Adelphon updated:

      +
        +
      • Created a Cosmetic version of the camo.
      • +
      +

      Arturlang updated:

      +
        +
      • Bloodsucker LifeTick runs from BiologicalLife now
      • +
      +

      Ryll-Ryll ported by silicons updated:

      +
        +
      • Shoelaces are now a thing. You can untie them by laying down next to someone.
      • +
      • shoes now have lace delays and some can't be laced at all
      • +
      • do after now tracks who's interacting with who, meaning some actions now break when the target moves away.
      • +
      +

      SiliconMain updated:

      +
        +
      • Ported the long range atmos analyzer from sk*rat, credit to NotRanged
      • +
      +

      silicons updated:

      +
        +
      • energy sword perfect parries now reflect projectiles back at their shooters.
      • +
      • any mob can now parry if they have the right item
      • +
      • beam rifles now go into emitters properly
      • +
      • clickdelay has been refactored into an experimental hybrid system. Check code/modules/mob/clickdelay.dm for more information.
      • +
      • Resisting no longer checks clickdelay, but is standardized to a 2 second per resist system for most forms of resisting. It still sets clickdelay, though.
      • +
      • Meters have been added for estimating time until next attack/resist. Won't be that useful due to our clickdelay currently being very short, though. They're visible from your hand and resist HUD elements. experimental: Most attacks and forms of attacking (minus unarmed because it's too much of a pain to refactor how hugs/gloves of the north star works) now check for time-since-last-attack rather than making it so you can't attack for said time. This means you can very quickly switch to a gun from a melee weapon, whereas in the old system a melee weapon would put you on lockout for 0.8 seconds, in the new system all the gun cares about is that you did not attack for at least 0.4 seconds.
      • +
      • All clickdelay setting/reading are now procs, so it should be trivial to implement another system where drawing/switching to a weapon requires you to have it out for x seconds before using it. I am not personally doing it at this point in time though because it will likely just annoy everyone with no real gain unless we do something like putting a 0.8 second switch-to cooldown for guns (which I did not, yet)
      • +
      • attack_hand has been refactored to on_attack_hand remove: sexchems no longer impact click delay
      • +
      • turrets now automatically stagger their shots. Happy parrying/blocking.
      • +
      • turrets now speed_process, they were shooting slower than they should be
      • +
      • anything can now block with the right items
      • +
      +

      timothyteakettle updated:

      +
        +
      • some crafted crates won't contain items now, and thus have stopped breaking the laws of physics
      • +
      • beepskys hats now follow the laws of gravity and move up/down when he bobs up and down
      • +
      + +

      29 July 2020

      +

      DeltaFire15 updated:

      +
        +
      • The 'Naked' outfit is no longer broken.
      • +
      +

      Ghommie updated:

      +
        +
      • fixed cremator trays, paleness examination strings, chat message for stamping paper, looping sounds, load away missions/VR admin verb, access requirements for using the sechuds.
      • +
      • Alt-Clicking a cigarette packet should pull the lighter out first if present, then cigarettes.
      • +
      +

      Hatterhat updated:

      +
        +
      • Directional windows can now be rotated counterclockwise properly again.
      • +
      +

      NecromancerAnne, Sirich96 updated:

      +
        +
      • Stunbaton sprites by Sirich96.
      • +
      • New sprites for the stunsword.

      necromanceranne updated:

        -
      • You can now craft armwraps!
      • -
      • Pugilists disarm you more easily and are harder to disarm. They also get a discount on disarm.
      • -
      • Pugilists only suffer a flat 10% chance to miss you. It's just like old punches! Kinda.
      • -
      • Chaplain's armbands are a +2, up from a +1!
      • -
      • Martial artists spend stamina when they disarm.
      • -
      • Rising Bass had several moves shortened and made stronger. Has a disarm override attack which does stamina damage and trips people on a disarm stun punch.
      • -
      • CQC had it's disarm move altered to be a stronger version of Krav Maga's. Dizzies and disarms on a disarm stun punch or just does some stamina damage and brute damage.
      • -
      • Sleeping Carp can punch you to the floor on a harm stun punch.
      • -
      • Hugs of the Northstar are no longer nodrop.
      • -
      • Adding in some overrides and proper flag checks for martial arts.
      • -
      • Stun thresholding stops disarm spams at extremely high stamina loss.
      • -
      • Ashen Arrows are actually called Ashen Arrows in the crafting menu.
      • +
      • Adds some in-hands for the rapier sheath.
      • +
      +

      timothyteakettle updated:

      +
        +
      • tail wagging should work in all cases now
      • +
      • bluespace jars work as intended now
      • +
      • aliens can remove embeds now
      • +
      • bloodsuckers are not affected by bloodloss
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • Flannel jackets and bartender winter coat
      • +
      + +

      28 July 2020

      +

      Cacogen updated:

      +
        +
      • OSHA has more pull than anyone could have expected. All armor provided by Nanotrasen and the syndicate now have tags that accurately lists defenses and resistances of a piece of clothing.
      • +
      +

      CameronWoof updated:

      +
        +
      • Exotic seed crates now contain a spaceman's trumpet seed packet.
      • +
      +

      EmeraldSundisk updated:

      +
        +
      • Renovates Snow Taxi's northeast bathroom to have multiple non-urinal toilets and showers
      • +
      • Adds signage/labeling to improve map readability
      • +
      • Adds a bathroom to the northwest station
      • +
      • Adds a filing cabinet to the cargo department
      • +
      • Area designation adjustments to account for the above changes
      • +
      • Adds a missing airlock cyclelink near medical
      • +
      +

      Ludox235 updated:

      +
        +
      • Makes the flavour text that appears when you become a zombie tell you to act like one.
      • +
      +

      MrJWhit updated:

      +
        +
      • Decluttered toxins and hid the yellow mix line in atmos, for metastation
      • +
      +

      SiliconMain updated:

      +
        +
      • Paramedic heirloom is now a zippo
      • +
      • Durathread belts now protect their contents from radiation, and can hold full sized extinguishers
      • +
      +

      Sishen1542 updated:

      +
        +
      • removed zoomba
      • +
      +

      dapnee updated:

      +
        +
      • added a fan to the listening outpost
      • +
      • added two missing r-walls near the SM, removed random light and wire node below the engine, and fixed the missing cable in the courtroom on Kilo
      • +
      +

      kappa-sama updated:

      +
        +
      • Stimpaks cost 5tc once more, up from 3tc.
      • +
      +

      silicons updated:

      +
        +
      • polychromatic cloaks to loadout
      • +
      • no more self healing with medibeam guns
      • +
      • oh no, taser buff. alt fire delay dropped to 0.4 seconds.
      • +
      • you can now shoot yourself by disarm-intenting yourself with a gun.
      • +
      +

      timothyteakettle updated:

      +
        +
      • species code is now slightly less messy
      • +
      • slight tweak to how material crafting works
      • +
      • changed up pet carriers / bluespace jars a bit so you can't fit certain things inside them and also the text shown for resist times is accurate
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • Black Box theft objective
      • +
      + +

      27 July 2020

      +

      Hatterhat updated:

      +
        +
      • Training bokkens! Make 'em from wood, use 'em in-hand to toggle between harmful and not-so-harmful, practice your parrying with them!
      • +
      • Marker beacons should have a sprite again.
      • +
      +

      silicons updated:

      +
        +
      • clownops and clown mobs now share the same faction. HONK!
      • +
      +

      timothyteakettle updated:

      +
        +
      • modern pickle technology now allows people who have been turned into pickles, to be retrieved through the medical course of dying
      • +
      + +

      26 July 2020

      +

      DeltaFire15 updated:

      +
        +
      • Organs now decay again.
      • +
      +

      Iatots updated:

      +
        +
      • Licking wounds now may cause you to spit out a hairball once in a while!
      • +
      • You can now craft a catgirl plushie with 3 of a new ingredient occasionally found in medbay!
      • +
      +

      dapnee updated:

      +
        +
      • removed legacy public mining shuttle area and remade lounge
      • +
      + +

      25 July 2020

      +

      CameronWoof updated:

      +
        +
      • Aloe now has an icon.
      • +
      +

      timothyteakettle updated:

      +
        +
      • beepsky replaces the word THREAT_LEVEL with the actual threat level
      • +
      + +

      24 July 2020

      +

      EmeraldSundisk updated:

      +
        +
      • Adds a CMO office, along with Virology and Genetics labs to Omega Station
      • +
      • Adds a second chemistry station to the chemistry lab
      • +
      • Adjusts the locations of some objects in medical to accommodate these new additions
      • +
      • Relocates the morgue
      • +
      • Relocates items in impacted areas of maintenance as well as the library
      • +
      • Fixes an air line Bartholomew somehow knocked out
      • +
      +

      Linzolle updated:

      +
        +
      • wounds now have a description on examine
      • +
      +

      Owai-Seek updated:

      +
        +
      • Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes
      • +
      • Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken
      • +
      • Organised the Food DMI a bit.
      • +
      • Deleted some stray pixels on some sprites.
      • +
      • Nuggie boxes are now centered correctly.
      • +
      • Icons for the the food items in this PR.
      • +
      +

      Sneakyrat6 updated:

      +
        +
      • Fixes dressers not giving you undies
      • +
      • Fixes Snaxi not loading properly because of typos
      • +
      • You can now burn photos
      • +
      +

      Zandario updated:

      +
        +
      • Murdered **tipes** and gave birth to **is**.
      • +
      +

      silicons updated:

      +
        +
      • sanitization now doesn't cut off 15.7 or something million possible colors from character preferences (instead of only allowing 16 values for R G and B, it now allows 256 each)
      • +
      • projectiles are by default 17.5 tiles per second instead of 12.5
      • +
      +

      timothyteakettle updated:

      +
        +
      • due to recent innovative research in the medical field, you now have bones
      • +
      • zombie claws are now sharp and do less damage, but can destroy non-lifeforms far faster
      • +
      • zombies now take less stamina damage
      • +
      • beepsky can now wear hats
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • rad and kravglove sprites
      • +
      + +

      23 July 2020

      +

      DeltaFire15 updated:

      +
        +
      • Traits are no longer fucked
      • +
      +

      Putnam3145 updated:

      +
        +
      • Slight optimization in chat code.
      • +
      +

      kappa-sama updated:

      +
        +
      • tendril chests being empty
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • fetish content
      • +
      + +

      22 July 2020

      +

      Ludox updated:

      +
        +
      • You can no longer be brainwashed into giving birth to a fake baby
      • +
      +

      kappa-sama updated:

      +
        +
      • brainwashing disk has lost its cost buffs (3->5) and is role restricted once more (medical doctor/roboticist)
      • +
      + +

      21 July 2020

      +

      Arturlang updated:

      +
        +
      • Decal painter ui now works, yay?
      • +
      +

      CameronWoof updated:

      +
        +
      • Adds aloe, a new growable plant
      • +
      • Adds medicated sutures and advanced regenerative meshes
      • +
      • Polypyrylium oligomers and liquid electricity now correctly populate
      • +
      +

      Chiirno updated:

      +
        +
      • Alt-click pill bottles places top-most pill into active hand.
      • +
      • Moved dice bags from pill_bottle/dice to box/dice to avoid dice bags being affected from medical specific pill bottle changes.
      • +
      +

      DeltaFire15 updated:

      +
        +
      • Swarmers can once again eat items as long as there's nothing living in them.
      • +
      +

      Funce updated:

      +
        +
      • Genetics spiderwebs are no longer impassable walls
      • +
      +

      Kraseo updated:

      +
        +
      • Damp rags no longer instantly apply their chemicals onto someone.
      • +
      +

      SiliconMain updated:

      +
        +
      • Geigers can no longer be contaminated
      • +
      +

      TheSpaghetti updated:

      +
        +
      • new snowflake trait
      • +
      +

      kappa-sama updated:

      +
        +
      • advanced surgery duffel bag no longer comes with a nukie medkit. it costs 4 less telecrystals to make up for this colossal nerf.
      • +
      • quartered the weight of the stray cargo pod event from 2x normal to 1/2 normal
      • +
      +

      silicons updated:

      +
        +
      • survivalists (from summon guns/magic) are proper objective'd pseudoantagonists again
      • +
      • summon guns/magic can only be used once each
      • +
      • summon guns/magic now only cost one point each
      • +
      • :dsmile: :dfrown: :dhsmile: :dpog: :dneutral:
      • +
      • gravity should update for mobs a fair bit faster
      • +
      • voting can now be done from the stat panel if the system is plurality and approval
      • +
      +

      timothyteakettle updated:

      +
        +
      • new fried component used for frying objects
      • +
      • various frying bugs fixed such as being able to unfry items and frying turfs with cold cooking oil
      • +
      + +

      20 July 2020

      +

      lolman360 updated:

      +
        +
      • Service borgs now have synthesizers instead of a violin and guitar.
      • +
      • borg RSF
      • +
      + +

      19 July 2020

      +

      Arturlang updated:

      +
        +
      • TGUI 3.0 and enables all the UIs, plus the smart asset cache, and all the things required for them
      • +
      +

      EmeraldSundisk updated:

      +
        +
      • Adds a pool to Delta Station
      • +
      • Adds light fixtures to specified areas
      • +
      • Relocates objects in impacted areas of Delta's starboard maintenance
      • +
      +

      MrJWhit updated:

      +
        +
      • Adds a small light next to the kitchen counter
      • +
      +

      Putnam3145 updated:

      +
        +
      • Pen uplinks no longer broken
      • +
      +

      TheObserver-sys updated:

      +
        +
      • Adds a new reaction: Slime Extractification. Take 30u Slime Jelly, 5u Frost Oil, and 5u plasma to generate a fresh grey slime extract.
      • +
      +

      Yakumo Chen updated:

      +
        +
      • Hierophant club now checks for friendly fire by default.
      • +
      +

      b1tt3r1n0 updated:

      +
        +
      • Added the updated circle game
      • +
      +

      silicons updated:

      +
        +
      • Unarmed parry is now a thing.
      • +
      +

      timothyteakettle updated:

      +
        +
      • plushies in the loadout have been replaced with a box that lets you choose one instead
      • +
      • wrestling should no longer have the ability to permanently rotate people
      • +
      • you can now select to wear a snail shell as your backpack in the customization menu
      • +
      +

      zeroisthebiggay updated:

      +
        +
      • martial arts twenty minpop
      • +
      • records
      • +
      + +

      17 July 2020

      +

      ShizCalev, Fikou updated:

      +
        +
      • Added some sanity checking for varedit values.
      • +
      • Fixed an exploit involving coins and mints that could crash the server.
      • +
      • Fixed an exploit that would allow you to destroy round-critical / indestructible items with folders.
      • +
      • Swarmers can no longer cut power lines by deconstructing catwalks underneath them.
      • +
      • Fixed a scenario that allowed infinite resource generation via ore machines.
      • +
      • you can no longer inject html in ahelps
      • +
      • you cant either, jannies
      • +
      +

      timothyteakettle updated:

      +
        +
      • fixes a small pickle related issue
      • +
      • recent culinary and scientific advancements have brought forth new pickle related technologies
      • +
      + +

      16 July 2020

      +

      DeltaFire15 updated:

      +
        +
      • Fixes a zeolite runtime caused by a missing check.
      • +
      +

      Sneakyrat6 updated:

      +
        +
      • Fixes being able to meta people real name with OOC Notes
      • +
      +

      timothyteakettle updated:

      +
        +
      • travelling traders from another dimension can now visit the station in search of something specific, and reward you for giving it to them
      • +
      • small error with pet carrier logic fixed and also making sure simple mobs are catered for properly inside bluespace jars
      • +
      • fixes coin related issue
      diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index ee2511d0f5..f0ff6a3c32 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -26015,3 +26015,1100 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - rscadd: Adds the stray cargo pod event, where a cargo pod crashes into the station. - rscadd: Adds the fugitives event, where fugitives are loose on the station, and it's the hunters jobs to capture them. +2020-06-20: + LetterN: + - rscadd: Asset cache from tg + - tweak: Made the map viewer not look bad + - bugfix: Admin matrix right-bracket + bunny232: + - rscdel: Removed unsavory things from the vent clog event +2020-06-21: + kevinz000: + - balance: calculations for punch hit chance has been drastically buffed in favor + of the attacker. +2020-06-22: + Ghommie (porting PRs by zxaber, Ryll-Ryll, AnturK): + - tweak: Certain small items purchased through cargo now get grouped into a single + box. They also are immune to the 10% private account fee. + - rscadd: Added single-order options for several existing products in the Cargo + Catalog. + - tweak: Medkit listings are now single-pack items, and considered small items that + get grouped into single boxes. Price for medkits is as close to unchanged as + is reasonable. + - rscadd: You can now beat on vending machines to try and knock loose free stuff! + You can also almost kill yourself doing it, so it's your call if your life is + worth ten bucks. + - rscadd: Cigarette packets now have coupons on the back for small cargo items! + Smoking DOES pay! + - tweak: Some single/small items in cargo have been rebranded as goodies, come in + lockboxes rather than crates, and can only be purchased with private accounts. + kevinz000: + - refactor: Life() is split into BiologicalLife() and PhysicalLife. A component + signal has been added that can prevent either from ticking. + shellspeed1: + - rscadd: Adds IV bags. +2020-06-24: + DeltaFire15: + - balance: Choosing a random item in your uplink will no longer sometimes reroll + your contract. + - rscdel: Syndicate crate event cannot fire as a random event anymore. + Detective-Google: + - bugfix: singulos no longer succ infinite rods out of the ice + - bugfix: one of the directions for the diag hudpatch was blu instead of orang + timothyteakettle: + - bugfix: bonfires/grills no longer produce infinite quantities of food + - bugfix: slime's alter form ability now updates their hair colour when changing + their body colour +2020-06-25: + Anonymous: + - rscadd: Added kepi and orvilike kepi. Available through loadout. + Detective Google: + - rscadd: Medigygax + Detective-Google: + - bugfix: malf AIs can no longer yeet the station while shunted + - bugfix: SMESes can now properly use self charging cells + - rscadd: ghosts now show up when the round ends + - balance: away missions + Funce: + - bugfix: Mentor SQL queries are now deleted properly. + Linzolle: + - bugfix: analyze function on chem master is no longer broken + - bugfix: organs now decay inside dead bodies again + dapnee: + - rscadd: wataur bottle item + - imageadd: wataur bottle and overlay +2020-06-26: + Ghommie: + - bugfix: Snore spam. + - bugfix: Hostile mobs shouldn't hit their original spawner structures or thoses + of the same faction. + silicons: + - bugfix: soap cleans blood again +2020-06-27: + Detective-Google: + - tweak: Lying down is better + timothyteakettle: + - rscadd: felinids now nya when tabled +2020-06-28: + Detective-Google: + - bugfix: cog is less the suck + - tweak: piggybacking is no longer absolutely inferior + Ghommie: + - bugfix: Fixing windows interaction with spraycans. + - bugfix: Fixing kinetic accelerator guns not working well with gun circuitries. + - bugfix: Fixing Zoomba borgs lights overlays. + - bugfix: Fixing the "absorb another ling" and "absorb the most dna" objectives + rolling when no other changeling is around. + - spellcheck: Clarified a pet peeve about the spread infestation ability. + - bugfix: BEPIS nodes won't show up anymore in the expert mode ui of the r&d console + anymore (good thing they weren't researchable). + - bugfix: Hopefully fixing sound loop edge cases. + - bugfix: Fixing pAI radios being permanently disabled by EMPs at times. + - rscadd: Windoors can now be obscured with spraycans just like windows. + Ghommie porting PRs by Qustinnus/Floyd, Willow, cacogen, nemvar, Ghilker and EOBGames (Inept): + - bugfix: Fixes a material duplication bug. + - code_imp: unique combinations of custom_materials lists are now shared between + objects + - rscadd: meat material. yes. + - rscadd: materials can now be used to build walls/floors. meat house + - bugfix: edible component now does not try to attack if you eat something with + it + - rscadd: Texture support for mat datums with thanks to 4DPlanner! + - bugfix: you no longer hit yourself with organs when eating + - rscadd: A whole bunch of materials are now datumised! Check out bronze, runed + metal, sand, sandstone, snow, paper, cardboard, bone and bamboo. Oh, and pizza. + Yes, pizza. + - balance: Buffs material floor tiles' throwforces from 1 to 10 (same as iron) to + better showcase the effect of different materials (e.g. meat vs. titanium) + - bugfix: Radioactive items no longer output a single . when examined at a distance + MrJWhit: + - rscdel: Removed air alarm in Snow Snaxi in Tcomms Sat + - rscdel: Removed trash bins in genetics and mining + - tweak: Gives cargo techs a cargolathe + Putnam3145: + - bugfix: lost my mind just a couple of times + b1tt3r1n0: + - rscadd: pouches, again, and and material pouches. + timothyteakettle: + - rscadd: support for custom blood colours implemented, slimes blood colour now + equivalent to their body colour +2020-06-29: + b1tt3r1n0: + - balance: Made teratomas from sdgf less powergame + timothyteakettle: + - bugfix: slimes no longer have white blood by default +2020-06-30: + Fikou: + - rscadd: spray cans, airlock painters, and decal painters added to engineering/service/autolathe + (where applicable) + Ghommie: + - bugfix: Fixed a gap on the male insect anthro torso sprite when facing south. + - bugfix: Fixed mecha ID access not being removable. + - bugfix: Fixed a peeve with the hypno trance status effect not sanitizing some + heard hypnosis inputs (i.e. custom say messages like say"honks*clownem ipsum + dolor") + - bugfix: fixed an issue about using stacks with only 1 amount left. + - bugfix: Fixed a peeve on attack messages against carbons/humans. + - bugfix: Fixed missing hypnochair board. + - bugfix: Fixed material walls and tiles. My bad on that port. + Ghommie (inspired by MrDoomBringer's work on tgstation): + - rscadd: New check skills UI. + Ghommie (porting PRs by XTDM, coiax, MrDoomBringer): + - tweak: Random Events now have a follow link for ghosts! + - rscadd: Adds the Spontaneous Brain Trauma to the event pool. Sometimes your brain + just goes a little wrong. + - rscadd: Sometimes a low level cloning pod will make errors in replicating your + brain, leaving you with a mild brain trauma. + - rscadd: When a person is cloned, any mental traumas are cloned as well. + - rscadd: The wizard federation announces that the Curse of Madness is out of beta + and is now available for purchase for 4 points. It causes long-lasting brain + traumas to all inhabitants of a target space station. + - rscadd: The wizard federation declines responsibility for any self-harm caused + by curses cast while inside the targeted station. + - rscadd: Due to the extensive testing of the Curse of Madness some unique new trauma + types have appeared across Nanotrasen-controlled space. + - rscadd: Curse of Madness can now be triggered by a wizard's Summon Events, at + the same chance as Summon Guns or Summon Magic. + - admin: When an admin triggers Curse of Madness manually, they can specify their + own dark truth to horrify the station with. + nightred: + - code_imp: Created two_handed component + - refactor: Updated all existing two handed items to use the new component + silicons: + - bugfix: typing indicators no longer generates duplicate message boxes. + - rscadd: config errors now have line numbers. + - tweak: outgoing mentorpms are now blue instead of green for the sender. + - soundadd: '*squish' + timothyteakettle: + - rscadd: you can now select your tongue and speech verb in the character customization + menu! + - rscadd: skeleton is now split into two more types, greater and lesser + - bugfix: non-carbon blood is now not white + - spellcheck: fixed a bunch of grammar/spelling mistakes +2020-07-02: + Ghommie: + - bugfix: Fixing a few issues with twohanded items. + - bugfix: Unum decks now work correctly. + - bugfix: Abductor walls are once again buildable with alien alloy. + Trilbyspaceclone: + - tweak: Makes pride and envy ruin a bit smaller! + - rscadd: Pride now has rings, lipstick wigs and silver walls/door making a nice + and polished look then cyan blue walls. + - rscadd: more trash and better dagger placement on food ruin + - rscadd: Snowboim now has snowballs and toy gifts for the two skeles daw! + - tweak: Beach boim now has carp light branding beer, as well as soap! + - tweak: Greed ruin now uses nice slick walls and carpet! + - tweak: Founten ruin looks a lot better with its carpets and well maintained fluff + things, but walls suffered and no longer can salvage ruined metal... + - rscadd: Alien nest has a bit more glowy floors of resin looking a bit more lived + in by the drones. As well as the "door" now being see through resin rather then + the thicker stuff that you cant see through + - rscadd: Pizza party has a few more gifts, some candy and snap pops yay! + - balance: Sloth ruin is about 15~ tiles shorter, has and has more fruit for a bowl. + How lazy! + silicons: + - bugfix: bohbombing is a thing now +2020-07-03: + Arturlang: + - rscadd: You can now toggle hardsuit helmets from the strip menu + Ghommie: + - bugfix: fixed custom speech/tongue stuff. + - balance: Lowered shaft miners' paycheck, they have other ways to make cash. + - rscadd: You can't (un)equip garments on/from obscured inventory slots anymore. + - balance: The stamina cost multiplier for swinging melee weapons against mobs has + been brought back to 1 from 0.8 + - balance: The stamina cost for throwing mobs now scales with their mob size variable. + LetterN: + - tweak: Ported some tags from tgui-3.0 to Vending.js + - bugfix: vending icons + - bugfix: r&d icons + - bugfix: chem master icons + Onule: + - tweak: titanium wall man good + Sonic121x: + - bugfix: Bringback the ChemMaster pill type button. + - bugfix: Fix Technode icon. + bunny232: + - tweak: Witchhunter hat no longer obscures mask ears ,eyes, face and mouth + timothyteakettle: + - bugfix: bloodpacks initialise correctly now +2020-07-04: + Sonic121x: + - rscadd: crushed Soldry sodacan + - rscadd: digitigrade version of chief medical officer's turtleneck and captain's + female formal outfit. + silicons: + - refactor: blood_DNA["color"] is now a single variable instead of a list +2020-07-05: + Ghommie: + - bugfix: You can now actually gain wiring experience from using cable coils. + - bugfix: Opening the View Skill Panel shouldn't trigger messages about insufficient + admin priviledges anymore. + Yakumo Chen, kappa-sama: + - rscdel: Removes improvised handguns + - rscdel: removed handsaws, improvised gun barrels (you can use atmos pipes again) + - balance: Guncrafting is less time and resource intensive + - tweak: Item names in guncrafting are user-friendly. + kappa-sama: + - rscadd: cloth string to replace durathread string + - rscdel: durathread string + - balance: All bows and arrows have had crafting times significantly reduced, coming + out at up to 6 times faster crafting speeds. Improvised bows no longer require + durathread; instead, they use cloth materials. + silicons: + - tweak: active blocking now has a toggle keybind + - rscadd: auto bunker override verb has been added + - balance: shields take 2.5 stam instead of 3.5 stam per second to maintain block + - rscadd: Cybernetic implant shields will auto-extend and be used to block if the + user has no item to block with + timothyteakettle: + - tweak: cooking oil is now far less lethal, requiring a higher volume of the reagent + to deal more damage +2020-07-07: + KasparoVy: + - tweak: Fixes misaligned south-facing silver legwraps sprite. + Owai-Seek: + - bugfix: Bee Balm is now visible. + Weblure: + - bugfix: Fixed the slowdown formula for small character sprites; you guys don't + use custom sprite sizes so just ignore these changes. + - bugfix: Fixed the "Move it to the threshold" button; it now does what it says. + - tweak: Reworded some text to be clearer. +2020-07-08: + DeltaFire15: + - bugfix: The kill-once objective now works properly. + EmeraldSundisk: + - rscadd: CogStation now has an apothecary + - rscdel: Removes an outdated note on sleepers + - tweak: Readjusts CogStation's chemistry lab + - tweak: Slight area designation adjustments for Robotics + - bugfix: The arrivals plaque should be readable now + Owai-Seek: + - rscadd: Margarine, Chili Cheese Fries. + - tweak: Egg Wraps are now categorized under egg foods. + - bugfix: Tuna Sandwich crafting/sprite is now visible. + - imageadd: Icons for chicken, cooked chicken, steak, grilled carp, corndogs + - imageadd: Icons for chili cheese fries, margarine, BLT sandwich + - imageadd: (Unused) icons for raw meatballs, and lard +2020-07-09: + timothyteakettle: + - rscadd: bluespace tray added, allowing twice as many items as the regular tray, + printable at the service lathe, researched through science + - rscadd: bluespace jar added, a kind of pet carrier that allows human sized mobs + inside, and smashes when thrown, researched and printed through science +2020-07-10: + Chiirno: + - code_imp: Gave jellypeople a unique brain object /obj/item/organ/brain/jelly + - imageadd: added an icon for jellypeople brains. + EmeraldSundisk: + - rscadd: Adds a pool to PubbyStation + - tweak: Slight adjustments to the surrounding area as to fit said pool + Sneakyrat6: + - bugfix: Fixes hair falling out of hoodies. + TheObserver-sys: + - bugfix: Actually adds the juice reagent to make laugh peas donuts. +2020-07-11: + Putnam3145: + - refactor: Gas mixtures now live entirely in a DLL. +2020-07-12: + DeltaFire15: + - balance: Sentinels compromise now heals augmented bodyparts. + EmeraldSundisk: + - rscadd: Adds turnstiles to CogStation's security wing + - rscadd: Readds robotics to the Corpse Disposal Network + - rscadd: Readds chemistry's ability to send items directly to the experimentation + lab + - tweak: Visual renovation and slight adjustments to CogStation's robotics lab + - tweak: Slight visual adjustments elsewhere (the library) + - bugfix: CogStation's mail and disposal pipes are once again complete + - bugfix: CogStation's robotics lab now has spawners, lights, and other room essentials + HeroWithYay: + - rscadd: Added Telecrystal Dust + - tweak: Telecrystals can be sold at cargo + LetterN: + - rscadd: Added d[thing] emojis + - bugfix: bye xss + MrJWhit: + - rscdel: Removes northern tunnel to the monastery on Pubby + Yakumo Chen: + - rscadd: Adds a wedding crate to cargo full of wedding attire. + kappa-sama: + - tweak: wisdom cow is half as common and is wise enough to lag the server 66% less + silicons: + - config: 'policy configuration added, plus support hooks for assisting enforcement + of clone memory disorder. logging: added logging of revival by defib, cloning, + strangereagent, and revival surgery' + - rscadd: You can now "audibly emote" by having ! at the start of a sentence. + timothyteakettle: + - rscadd: due to recent biological advancements, you can now make eye contact with + people. + zeroisthebiggay: + - bugfix: a singular stray pixel +2020-07-13: + Linzolle: + - bugfix: you can no longer vore and digest people regardless of vore preferences + Owai-Seek: + - tweak: Trashbags can now hold most shoes, and organs. + - balance: You can no longer nest nuke disks or hold brains in the trash. +2020-07-14: + silicons: + - rscadd: chemical reactions now are sorted by priority first and temperature second. + - rscadd: sec and medical records have been added to character setup. + - bugfix: circuit reagent heaters are now sanitized for temperature from 2.7 to + 1000. + timothyteakettle: + - bugfix: ports a money bag exploit +2020-07-15: + Sonic121x: + - bugfix: Paramedic jumpsuit +2020-07-16: + DeltaFire15: + - bugfix: Fixes a zeolite runtime caused by a missing check. + Sneakyrat6: + - bugfix: Fixes being able to meta people real name with OOC Notes + timothyteakettle: + - rscadd: travelling traders from another dimension can now visit the station in + search of something specific, and reward you for giving it to them + - bugfix: small error with pet carrier logic fixed and also making sure simple mobs + are catered for properly inside bluespace jars + - bugfix: fixes coin related issue +2020-07-17: + ShizCalev, Fikou: + - bugfix: Added some sanity checking for varedit values. + - bugfix: Fixed an exploit involving coins and mints that could crash the server. + - bugfix: Fixed an exploit that would allow you to destroy round-critical / indestructible + items with folders. + - bugfix: Swarmers can no longer cut power lines by deconstructing catwalks underneath + them. + - bugfix: Fixed a scenario that allowed infinite resource generation via ore machines. + - bugfix: you can no longer inject html in ahelps + - admin: you cant either, jannies + timothyteakettle: + - bugfix: fixes a small pickle related issue + - rscadd: recent culinary and scientific advancements have brought forth new pickle + related technologies +2020-07-19: + Arturlang: + - rscadd: TGUI 3.0 and enables all the UIs, plus the smart asset cache, and all + the things required for them + EmeraldSundisk: + - rscadd: Adds a pool to Delta Station + - rscadd: Adds light fixtures to specified areas + - tweak: Relocates objects in impacted areas of Delta's starboard maintenance + MrJWhit: + - rscadd: Adds a small light next to the kitchen counter + Putnam3145: + - bugfix: Pen uplinks no longer broken + TheObserver-sys: + - rscadd: 'Adds a new reaction: Slime Extractification. Take 30u Slime Jelly, 5u + Frost Oil, and 5u plasma to generate a fresh grey slime extract.' + Yakumo Chen: + - tweak: Hierophant club now checks for friendly fire by default. + b1tt3r1n0: + - rscadd: Added the updated circle game + silicons: + - rscadd: Unarmed parry is now a thing. + timothyteakettle: + - rscadd: plushies in the loadout have been replaced with a box that lets you choose + one instead + - bugfix: wrestling should no longer have the ability to permanently rotate people + - rscadd: you can now select to wear a snail shell as your backpack in the customization + menu + zeroisthebiggay: + - tweak: martial arts twenty minpop + - bugfix: records +2020-07-20: + lolman360: + - tweak: Service borgs now have synthesizers instead of a violin and guitar. + - bugfix: borg RSF +2020-07-21: + Arturlang: + - bugfix: Decal painter ui now works, yay? + CameronWoof: + - rscadd: Adds aloe, a new growable plant + - rscadd: Adds medicated sutures and advanced regenerative meshes + - bugfix: Polypyrylium oligomers and liquid electricity now correctly populate + Chiirno: + - rscadd: Alt-click pill bottles places top-most pill into active hand. + - tweak: Moved dice bags from pill_bottle/dice to box/dice to avoid dice bags being + affected from medical specific pill bottle changes. + DeltaFire15: + - bugfix: Swarmers can once again eat items as long as there's nothing living in + them. + Funce: + - bugfix: Genetics spiderwebs are no longer impassable walls + Kraseo: + - balance: Damp rags no longer instantly apply their chemicals onto someone. + SiliconMain: + - tweak: Geigers can no longer be contaminated + TheSpaghetti: + - rscadd: new snowflake trait + kappa-sama: + - balance: advanced surgery duffel bag no longer comes with a nukie medkit. it costs + 4 less telecrystals to make up for this colossal nerf. + - tweak: quartered the weight of the stray cargo pod event from 2x normal to 1/2 + normal + silicons: + - tweak: survivalists (from summon guns/magic) are proper objective'd pseudoantagonists + again + - tweak: summon guns/magic can only be used once each + - tweak: summon guns/magic now only cost one point each + - imageadd: ':dsmile: :dfrown: :dhsmile: :dpog: :dneutral:' + - bugfix: gravity should update for mobs a fair bit faster + - rscadd: voting can now be done from the stat panel if the system is plurality + and approval + timothyteakettle: + - rscadd: new fried component used for frying objects + - bugfix: various frying bugs fixed such as being able to unfry items and frying + turfs with cold cooking oil +2020-07-22: + Ludox: + - rscdel: You can no longer be brainwashed into giving birth to a fake baby + kappa-sama: + - balance: brainwashing disk has lost its cost buffs (3->5) and is role restricted + once more (medical doctor/roboticist) +2020-07-23: + DeltaFire15: + - bugfix: Traits are no longer fucked + Putnam3145: + - tweak: Slight optimization in chat code. + kappa-sama: + - bugfix: tendril chests being empty + zeroisthebiggay: + - rscadd: fetish content +2020-07-24: + EmeraldSundisk: + - rscadd: Adds a CMO office, along with Virology and Genetics labs to Omega Station + - rscadd: Adds a second chemistry station to the chemistry lab + - tweak: Adjusts the locations of some objects in medical to accommodate these new + additions + - tweak: Relocates the morgue + - tweak: Relocates items in impacted areas of maintenance as well as the library + - bugfix: Fixes an air line Bartholomew somehow knocked out + Linzolle: + - bugfix: wounds now have a description on examine + Owai-Seek: + - rscadd: Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes + - rscadd: Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken + - tweak: Organised the Food DMI a bit. + - tweak: Deleted some stray pixels on some sprites. + - tweak: Nuggie boxes are now centered correctly. + - imageadd: Icons for the the food items in this PR. + Sneakyrat6: + - bugfix: Fixes dressers not giving you undies + - bugfix: Fixes Snaxi not loading properly because of typos + - rscadd: You can now burn photos + Zandario: + - spellcheck: Murdered **tipes** and gave birth to **is**. + silicons: + - tweak: sanitization now doesn't cut off 15.7 or something million possible colors + from character preferences (instead of only allowing 16 values for R G and B, + it now allows 256 each) + - balance: projectiles are by default 17.5 tiles per second instead of 12.5 + timothyteakettle: + - rscadd: due to recent innovative research in the medical field, you now have bones + - tweak: zombie claws are now sharp and do less damage, but can destroy non-lifeforms + far faster + - tweak: zombies now take less stamina damage + - rscadd: beepsky can now wear hats + zeroisthebiggay: + - imageadd: rad and kravglove sprites +2020-07-25: + CameronWoof: + - bugfix: Aloe now has an icon. + timothyteakettle: + - bugfix: beepsky replaces the word THREAT_LEVEL with the actual threat level +2020-07-26: + DeltaFire15: + - bugfix: Organs now decay again. + Iatots: + - tweak: Licking wounds now may cause you to spit out a hairball once in a while! + - rscadd: You can now craft a catgirl plushie with 3 of a new ingredient occasionally + found in medbay! + dapnee: + - tweak: removed legacy public mining shuttle area and remade lounge +2020-07-27: + Hatterhat: + - rscadd: Training bokkens! Make 'em from wood, use 'em in-hand to toggle between + harmful and not-so-harmful, practice your parrying with them! + - bugfix: Marker beacons should have a sprite again. + silicons: + - rscadd: clownops and clown mobs now share the same faction. HONK! + timothyteakettle: + - bugfix: modern pickle technology now allows people who have been turned into pickles, + to be retrieved through the medical course of dying +2020-07-28: + Cacogen: + - rscadd: OSHA has more pull than anyone could have expected. All armor provided + by Nanotrasen and the syndicate now have tags that accurately lists defenses + and resistances of a piece of clothing. + CameronWoof: + - tweak: Exotic seed crates now contain a spaceman's trumpet seed packet. + EmeraldSundisk: + - rscadd: Renovates Snow Taxi's northeast bathroom to have multiple non-urinal toilets + and showers + - rscadd: Adds signage/labeling to improve map readability + - rscadd: Adds a bathroom to the northwest station + - rscadd: Adds a filing cabinet to the cargo department + - tweak: Area designation adjustments to account for the above changes + - bugfix: Adds a missing airlock cyclelink near medical + Ludox235: + - tweak: Makes the flavour text that appears when you become a zombie tell you to + act like one. + MrJWhit: + - tweak: Decluttered toxins and hid the yellow mix line in atmos, for metastation + SiliconMain: + - tweak: Paramedic heirloom is now a zippo + - tweak: Durathread belts now protect their contents from radiation, and can hold + full sized extinguishers + Sishen1542: + - rscdel: removed zoomba + dapnee: + - tweak: added a fan to the listening outpost + - bugfix: added two missing r-walls near the SM, removed random light and wire node + below the engine, and fixed the missing cable in the courtroom on Kilo + kappa-sama: + - balance: Stimpaks cost 5tc once more, up from 3tc. + silicons: + - rscadd: polychromatic cloaks to loadout + - rscdel: no more self healing with medibeam guns + - balance: oh no, taser buff. alt fire delay dropped to 0.4 seconds. + - rscadd: you can now shoot yourself by disarm-intenting yourself with a gun. + timothyteakettle: + - tweak: species code is now slightly less messy + - bugfix: slight tweak to how material crafting works + - bugfix: changed up pet carriers / bluespace jars a bit so you can't fit certain + things inside them and also the text shown for resist times is accurate + zeroisthebiggay: + - rscadd: Black Box theft objective +2020-07-29: + DeltaFire15: + - bugfix: The 'Naked' outfit is no longer broken. + Ghommie: + - bugfix: fixed cremator trays, paleness examination strings, chat message for stamping + paper, looping sounds, load away missions/VR admin verb, access requirements + for using the sechuds. + - tweak: Alt-Clicking a cigarette packet should pull the lighter out first if present, + then cigarettes. + Hatterhat: + - bugfix: Directional windows can now be rotated counterclockwise properly again. + NecromancerAnne, Sirich96: + - rscadd: Stunbaton sprites by Sirich96. + - rscadd: New sprites for the stunsword. + necromanceranne: + - rscadd: Adds some in-hands for the rapier sheath. + timothyteakettle: + - bugfix: tail wagging should work in all cases now + - bugfix: bluespace jars work as intended now + - bugfix: aliens can remove embeds now + - bugfix: bloodsuckers are not affected by bloodloss + zeroisthebiggay: + - rscadd: Flannel jackets and bartender winter coat +2020-07-30: + Adelphon: + - rscadd: Created a Cosmetic version of the camo. + Arturlang: + - code_imp: Bloodsucker LifeTick runs from BiologicalLife now + Ryll-Ryll ported by silicons: + - rscadd: Shoelaces are now a thing. You can untie them by laying down next to someone. + - tweak: shoes now have lace delays and some can't be laced at all + - refactor: do after now tracks who's interacting with who, meaning some actions + now break when the target moves away. + SiliconMain: + - rscadd: Ported the long range atmos analyzer from sk*rat, credit to NotRanged + silicons: + - rscadd: energy sword perfect parries now reflect projectiles back at their shooters. + - balance: any mob can now parry if they have the right item + - rscadd: beam rifles now go into emitters properly + - refactor: clickdelay has been refactored into an experimental hybrid system. Check + code/modules/mob/clickdelay.dm for more information. + - balance: Resisting no longer checks clickdelay, but is standardized to a 2 second + per resist system for most forms of resisting. It still sets clickdelay, though. + - rscadd: 'Meters have been added for estimating time until next attack/resist. + Won''t be that useful due to our clickdelay currently being very short, though. + They''re visible from your hand and resist HUD elements. experimental: Most + attacks and forms of attacking (minus unarmed because it''s too much of a pain + to refactor how hugs/gloves of the north star works) now check for time-since-last-attack + rather than making it so you can''t attack for said time. This means you can + very quickly switch to a gun from a melee weapon, whereas in the old system + a melee weapon would put you on lockout for 0.8 seconds, in the new system all + the gun cares about is that you did not attack for at least 0.4 seconds.' + - code_imp: All clickdelay setting/reading are now procs, so it should be trivial + to implement another system where drawing/switching to a weapon requires you + to have it out for x seconds before using it. I am not personally doing it at + this point in time though because it will likely just annoy everyone with no + real gain unless we do something like putting a 0.8 second switch-to cooldown + for guns (which I did not, yet) + - refactor: 'attack_hand has been refactored to on_attack_hand remove: sexchems + no longer impact click delay' + - rscadd: turrets now automatically stagger their shots. Happy parrying/blocking. + - bugfix: turrets now speed_process, they were shooting slower than they should + be + - balance: anything can now block with the right items + timothyteakettle: + - bugfix: some crafted crates won't contain items now, and thus have stopped breaking + the laws of physics + - tweak: beepskys hats now follow the laws of gravity and move up/down when he bobs + up and down +2020-08-01: + dapnee: + - tweak: added cake hat to bar, adds another atmostech spawn + - bugfix: sinks point in the right direction, APC won't spawn off the wall in circuits + - bugfix: changes commissary APC so it actually powers the room, adds a missing + AIR alarm, arrivals no longer has active atmos tiles. + silicons: + - tweak: toy shotguns no longer need 2 hands to fire + - bugfix: being on fire works again. + timothyteakettle: + - bugfix: monkeys no longer continuously bleed everywhere +2020-08-02: + Auris456852: + - rscadd: Added B.O.O.P. Remote Control cartridges to the PTech. + Hatterhat: + - rscadd: Durathread reinforcement kits! Sprites by Toriate, sets jumpsuit armor + to durathread levels, craft in the crafting menu. + KeRSedChaplain: + - rscadd: The belligerent scripture and a brass multitool, and a new marauder variant + which act similar to holoparasites/guardian spirits. + - rscdel: Removed the abductor teleport consoles they get, removes abscond for the + time being as I've not seen much use for it other than just spamming it and + hoping you end up in the armory. + - tweak: moved around scriptures to make the cult work better as being based around + the station, makes the Ark scream more often and work as a summonable object, + clockwork armor now has a flat 0 defense up to 10 instead of negatives against + laser damage. Makes the Ark work better in a station based setting, as well + as the Heralds beacon in case It works for the mode. + - soundadd: added powerloaderstep.ogg for Neovgre + - tweak: changes 'Dread_Ipad.dmi' to 'clockwork_slab.dmi' + MrJWhit: + - tweak: Adjusts abductor spawntext + Seris02: + - bugfix: fixed replica pods + dapnee: + - bugfix: fixed active turfs on wizard ruin and space hermit, fixed missing APC's + and added a light on Delta + ike709 and bobbahbrown: + - rscadd: Admins can now see your bans on (some) other servers. + kappa-sama: + - bugfix: chaplain cultists being able to convert people to full clockwork cult + status + timothyteakettle: + - tweak: combat mode now has weaker buffs in terms of damage dealt and took for + being or not being in the mode + - tweak: damage debuff for laying down has been decreased from 0.5x to 0.7x +2020-08-03: + KeRSedChaplain: + - bugfix: fixed clockwork guardians being able to reflect ranged weapons + Linzolle: + - bugfix: uv penlight no longer invisible + dapnee: + - bugfix: active turfs on box and xenohive, maintenance bar APC not being stringed + correctly, turned a monitor to face a direction that makes sense, changed tag + of camera in gravgen being misnamed + silicons: + - rscadd: shoves have been buffed to apply a status effect rather than a 0.85 movespeed + modifier, meaning repeatedly shoving someone now renews the debuff + - balance: shoves now stagger for 3.5 seconds. + - tweak: war operatives now actually time 20 minutes since roundstart to depart + instead of 15. + - balance: explosive stand bombs can now be examined from any distance + - code_imp: explosive stand bombs are now a component. +2020-08-04: + Seris02: + - bugfix: lizard spines + timothyteakettle: + - rscadd: due to further advancements in medical technology, you can now have holes + poked into your body for fun and enjoyment + zeroisthebiggay: + - rscadd: prefs for headpat wagging +2020-08-06: + Auris456852: + - rscadd: Added B.O.O.P. Remote Control cartridges to the PTech. + Hatterhat: + - rscadd: Proto-kinetic glaives! Essentially a proto-kinetic crusher with a different + blade, handguard, and goliath hide grip. Expensive, but elegant. + - balance: Door charges no longer knock people out. + Ludox235: + - rscadd: You can now buy damaged AI upload modules in the traitor's uplink. + Seris02: + - bugfix: fixed ghost chilis + Trilbyspaceclone: + - rscadd: 4 New blends of tea have been shipped to the station, and how to make + them has been leaked! + b1tt3r1n0: + - rscadd: Added the warp implant + dapnee: + - tweak: added a hallway to telecoms for engineers to get there on meta + kappa-sama: + - rscdel: dildo circuit assemblies + lolman360: + - bugfix: The Tendril-Mother on Lavaland has remembered how to make ashwalkers who + know how to speak Draconic again. + timothyteakettle: + - tweak: nanotrasen has decided to fire all disabled members of the security division + and confiscate certain sentimental items from doctors + - tweak: the custom tongue preference now passes through cloning so you spawn with + your selected tongue + - tweak: several changes to travelling traders so they look better and spawn slightly + less often + zeroisthebiggay: + - rscadd: nukies can buy holoparasites +2020-08-07: + dapnee: + - bugfix: fixed active tufs on some space ruins, murderdome VR, and a few on pubby, + changed cargo autolathe to techfab, messed with pipe room leading to monastery. + lolman360: + - bugfix: vendors are now unanchored when tipped. it just fell over it's not bolted + to the ground anymore. + - bugfix: podpeople no fat when sunbathing. + silicons: + - balance: explosions only recurse one level into storage before dropping 1 level + per storage layer. + - tweak: volumetric storage is now minimum 16 pixels per item because 8 was ridiculous + - spellcheck: shieldbash balanace --> balance + - rscadd: attempting to send too long of an emote will now reflect it back to you + instead of cutting it off and discarding the overflow. + - rscadd: holoparasites can now play music + - balance: lethal blood now causes damaging bleeding instead of outright gibbing +2020-08-08: + DeltaFire15: + - balance: Roundstart cultists now start with a replica fabricator - no brass though, + make your own. + - balance: 'Kindle cast time: 10 > 15, mute after stun end: 2 > 5, slur after mute + end: 3 > 5' + - bugfix: The ratvarian spear no longer adds negative vitality under very specific + circumstances. + - balance: The Ratvarian Spear can parry now! Short parries with low leeway, but + low cooldown. + - rscadd: The brass claw, a implant-based weapon which gains combo on consecutive + hits against the same target. + - rscadd: The sigil of rites, a sigil used to perform various rites with a cost + of power and materials + - rscadd: 'The Rite of Advancement: Used to add a organ or cyberimplant to a clockie + without need for surgery.' + - rscadd: 'The Rite of Woundmending: Used to heal all wounds on another cultist, + causing toxins damage in return.' + - rscadd: 'The Rite of the Claw: Used to summon a brass claw implant. Maximum of + 4 uses per round.' + Hatterhat: + - rscadd: You can now buy a toolbox's worth of Mosin-Nagant ammo for a fairly discounted + price. + - rscadd: Revolvers from the dedicated kit now have reskinning capabilities. + - bugfix: You can now actually buy the riflery primer, which lets you pump shotguns + and work the Mosin's bolt faster. + - imageadd: Bulldog slug magazines now have a unique sprite. + Ludox235: + - rscdel: Removed an abductee objective that told you to remove all oxygen. + - rscadd: Added a new abductee objective to replace the removed one. + Sishen1542: + - tweak: "\U0001F171\uFE0Foneless" + - rscadd: squishy slime emotes + timothyteakettle: + - tweak: heparin makes you bleed half as much now + - tweak: cuts make you bleed 25% less now + - rscadd: more items in the loadout and loadout has subcategories now for easier + searching +2020-08-09: + Hatterhat: + - rscadd: Proto-kinetic glaives (not crushers) can parry now. + MrJWhit: + - rscadd: Adds a second shutter on the top of the hop line + silicons: + - bugfix: immovable rods no longer drop down chasms + - rscdel: 'fun removal: squeaking objects now have an 1 second cooldown between + squeaks, and will have a 33% chance of interrupting any other squeaking object + when Cross()ing, meaning no more ear-fuck conveyor belts.' +2020-08-10: + Hatterhat: + - bugfix: Parry counterattack text now shows up. + - balance: Sterilized gauze is now better at stopping bleeding, and applies slightly + faster. Very slightly faster. + - balance: Ointment and sutures now hold more in a stack (12 and 15, respectively). + - tweak: Sterilized gauze can now be made by just pouring 10u sterilizine onto standard + medical gauze, instead of having to craft it. Why you had to craft it, I will + honestly never know. + - balance: Proto-kinetic glaives are more expensive, stagger/cooldown on failed + parries increased slightly, perfect parries required for counterattack. + - rscadd: 'New item: Temporal Katana. 2 points for wizards, timestops upon successful + parry, bokken quickparry stats (100 force on melee counter!).' + - rscadd: Also you can *smirk. This has no mechanical effect, other than being smug. + KeRSedChaplain: + - rscadd: Added a guide for romerol usage + - balance: made infectious zombies not enter softcrit and take no stamina damage + LetterN: + - tweak: clocktheme color + - code_imp: Ports TGUI-4 + Lynxless: + - rscadd: 'Ports TG #51879' + Owai-Seek: + - tweak: Meatballs now spawn raw from food processors. + Putnam3145: + - rscadd: Ethereals + - rscdel: (Hexa)crocin + - rscdel: (Hexa)camphor + - tweak: Tweaked wording for marking tickets IC issue. + - tweak: Rerolling your traitor goals will ONLY give you "proper" objectives. + Seris02: + - bugfix: borgs being able to select and use a module when it's too damaged + Sishen1542: + - balance: gave chairs active block/parry in exchange for removal of block_chance + - tweak: replaces box whiteship tbaton with truncheon + kappa-sama: + - balance: made the Dirty Magazines crate cost 4000 instead of 12000 credits + - rscadd: MODS I SPILLED MU JUICE HEJPPHRLP HELPJ JLEP HELP + silicons: + - balance: player made areas are no longer valid for malf hacking + - tweak: default space levels is 4 again. + - tweak: rats now swarm instead of stacking on one spot. + - balance: getting hit by an explosion will now barely hard knockdown, but will + leave you somewhat winded. + timothyteakettle: + - tweak: speech verbs copy through dna copying now +2020-08-11: + Hatterhat: + - bugfix: PDA uplinks can now steal from pens. Properly. Just make sure to have + a pen in your PDA, first. + kappa-sama: + - tweak: tracer no longer gives you full stamheals per use + zeroisthebiggay: + - rscadd: volaju two +2020-08-12: + DeltaFire15: + - balance: 'hellgun single-pack classification: goodies -> armory' + Detective-Google: + - bugfix: hallway table hallway table + Hatterhat: + - balance: The temporal katana is now slightly more worthy of the 2 spell point + cost, with a smaller, antimagic respecting timestop, less force, and no random + blockchance. Society has progressed past the need for blockchance. + LetterN: + - rscadd: Mafia Component + - bugfix: Fixed missing icons and handtele + Putnam3145: + - bugfix: a whole lot of jank regarding funny part sprite display. + Toriate: + - rscadd: Opossums have migrated into the maintenance tunnels! Seek them out at + your own peril! + ancientpower: + - tweak: Doors added to the west side of box medbay to make things a bit more manageable. + kappa-sama: + - tweak: smuggler satchel cost 2->1 + - tweak: radio jammer cost 5->2 + - bugfix: smuggler satchel uplink description now implies that persistence is disabled + lolman360: + - rscadd: renameable necklace (accessory, attaches to suit) and ring (glove slot.) + - tweak: custom rename is now 2048 characters? i think it's characters. + silicons: + - rscadd: You can now use anything as an emoji by doing :/obj/item/path/to/item:. + This works for any /atom or subtype. + timothyteakettle: + - rscadd: syndicate agents now have access to mechanical aim enhancers which allow + them to aim bullets to bounce off walls + - bugfix: ricochets work properly now for the bullets that support them + zeroisthebiggay: + - imageadd: hair and some sechuds + - balance: ce hardsuit radproofing +2020-08-13: + LetterN: + - rscdel: Removes fermisleepers and reverts them to tg ones +2020-08-14: + silicons: + - bugfix: abductors can buy things +2020-08-15: + LetterN: + - bugfix: missing anomaly core icons + - bugfix: wrong state. blame the tg vertion i copied + silicons: + - tweak: the 8 rotation limit from clockwork chairs has been removed. please don't + abuse this. + - tweak: ethereals can now wear underwear +2020-08-16: + kiwedespars: + - balance: nerfed hypereut chaplain weapon. + - balance: 50% rng blockchance -> 0% + - balance: parry made much worse because it's an actual weapon and a roundstart + one at that. + zeroisthebiggay: + - rscadd: tips + - rscdel: tips +2020-08-17: + DeltaFire15: + - bugfix: Cogscarabs are no longer always Pogscarabs + Strazyplus: + - rscadd: Added drakeborgs + - rscadd: Added drakeplushies + - imageadd: added drakeborg sprites + - imageadd: added drakeplushie sprites + - code_imp: changed some code - added drakeplushies to backpack loadout Removed + duplicate voresleeper belly sprites from engdrake & jantidrake. [CC BY-NC-SA + 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) + - rscadd: Added CC BY-NC-SA 3.0 license details to icon/mob/cyborg moved drakeborg.dmi + to icon/mob/cyborg +2020-08-18: + DeltaFire15: + - balance: 'kindle cast time: 15ds -> 25ds' + - tweak: Moved the Belligerent Scripture to where it should be in the code + Detective-Google: + - rscadd: glass floors + - rscadd: uncrowbarrable plasma floors tweak:disco inferno's plasma floors can no + longer be crowbarred. + - rscadd: ghost cafe has funky fresh art + - bugfix: you can actually remove glass floors now + - code_imp: get_equipped_items is hopefully less gross + - balance: plasma cutters are no longer gay + Hatterhat: + - balance: Slaughter demons (and laughter demons, being a subtype) are MOB_SIZE_LARGE, + with one of the more immediate effects being able to mark them with a crusher + and backstab them. + - balance: The funny blyat men have stumbled upon another surplus of Mosin-Nagants + and are starting to pack them into crates again. + - balance: Vehicle riders can now, by default, get shot in the face and/or chest. + - rscadd: Adminspawn only .357 DumDum rounds! Because sometimes the other guy just + really needs to hurt. + - rscadd: Bluespace beakers now have a chemical window through the side that shows + chemical overlays. + - rscadd: Plant DNA manipulators now let you chuck things over them. Or they WOULD, + if LETPASSTHROW worked half a damn. + LetterN: + - bugfix: uplink implant states + - tweak: tweaks how role assigning works + MrJWhit: + - rscadd: Gives ashwalkers nightvision + - balance: Makes tesla blast people, not the environment, to save the server. + TheObserver-sys: + - bugfix: moves Garlic sprites from growing.dmi to growing_vegetable.dmi + - rscdel: Removes the unused Electric Lime mutation, it just takes up space with + no actual function nor sprites. + - imageadd: Gives Catnip growing sprites + - imagedel: Removes redundant images in growing.dmi + kiwedespars: + - rscadd: 10 force to a fucking rubber cock. + lolman360: + - balance: shotgun stripper clip nerf. ammoboxes can now accept a load_delay that + happens when they attack a magazine, internal or external. + ported from tg: + - rscadd: bronze airlocks and windows can now be built + - balance: i also tweaked bronze flooring to be cheaper. + silicons: + - tweak: stamina draining projectiles without stamina for their primary damage type + now has their stamina damage taken into account for shield blocking, rather + than the block being done for free for that. + timothyteakettle: + - refactor: snowflake code tidyup + - refactor: snowflake code for mutant bodypart selection has been rewritten to be + ~14x shorter + - tweak: meat type and horns can now be selected by any species +2020-08-20: + DeltaFire15: + - bugfix: The cooking oil damage formula is no longer scuffed. + - tweak: Changed the clockie help-link to lead to our own wiki. + Fikou: + - admin: admins can now do html in ahelps properly + Hatterhat: + - balance: Pirate threats are now announced as "business propositions", and their + arrivals are now also announced properly. + tiramisuapimancer: + - bugfix: Ethereal hair is now their body color instead of accidentally white +2020-08-21: + LetterN: + - rscadd: Updates and adds some of the tips + Putnam3145: + - admin: added reftracking as a compile flag + SmArtKar: + - tweak: RSD limitation is now 500 tiles + - bugfix: Fixed broken RSD sprites + - config: Removed that shuttle limit + timothyteakettle: + - bugfix: two snouts can once again be chosen in customization + - bugfix: lizard snouts work again +2020-08-22: + Time-Green (copypasta'd by lolman360): + - rscadd: plumbing + - rscadd: automatic hydro trays +2020-08-23: + DeltaFire15: + - bugfix: silicons and clockies can now access APCs properly + EmeraldSundisk: + - rscadd: Medbay now has a smartfridge for organ storage + - rscadd: Slight enhancements to the station's electrical wiring layout + - rscadd: Very small library renovation + - bugfix: Exterior airlocks have been given proper air systems for safety's sake + Ghommie: + - bugfix: Stops shielded hardsuits from slowly turning the wearer into a big glowing + ball of stacked energy shield overlays. + - tweak: the shielding overlay is merely visual as result. Aim your clicks. + Ludox235: + - tweak: no more 10 pop xenos (25pop now) + MrJWhit: + - tweak: Increases the majority of airlocks by 1 tile. + - tweak: Minor adjustments to the TEG engine. + Putnam3145: + - balance: Simplemobs no longer count in dynamic. + - balance: '"Story" storyteller no longer starts at a ludicrously low threat, always.' + - balance: Blob threat now scales with coverage. + - tweak: One person with their pref on no longer overpowers 40 people who might + not even know there is one. + - bugfix: Negative-weight rulesets are no longer put into the list. + kiwedespars: + - tweak: removed durathread from armwraps recipe. + lolman360: + - rscadd: breath mask balaclava + timothyteakettle: + - bugfix: lizards are now a recommended species for mam snouts + zeroisthebiggay: + - rscadd: new sprites for the temporal katana + - rscadd: suiciding with the temporal katana omae wa mou shinderius you into the + shadow realm + - soundadd: twilight isnt earrape +2020-08-24: + MrJWhit: + - bugfix: Fixes areas on expanded airlocks + silicons: + - bugfix: wormhole jaunters work + - tweak: wormhole jaunters no longer get interference from bags of holding + - bugfix: airlocks now only shock on pulse/wirecutters instead of on tgui panel + open. + timothyteakettle: + - rscadd: three new items are in the loadout for all donators + zeroisthebiggay: + - rscadd: contraband black evening gloves in kinkvend +2020-08-25: + Hatterhat: + - rscadd: Insidious combat gloves have been replaced by insidious guerilla gloves. + They're generally the same, except now you can tackle with them. + Literallynotpickles: + - tweak: You can now equip handheld crew monitors on all medical-related winter + coats. + Putnam3145: + - tweak: vore now ejects occupants on death + raspy-on-osu: + - tweak: Thermoelectric Generator power output + timothyteakettle: + - tweak: I.P.Cs now short their circuits when expressing emotion, causing sparks + to appear around them. +2020-08-26: + ancientpower: + - tweak: Ghosts can read newscasters by clicking on them. + silicons: + - balance: hierophant vortex blasts now have 50% armor penetration vs mecha + - balance: ventcrawling now kicks off every attached/buckled mob, even for non humans. +2020-08-27: + silicons: + - tweak: eyebeam lighting can only have 128 maximum HSV saturation now. + - balance: no more shotgun stripper clips in boxes. + - balance: goliath tentacles now do 20 damage to mechs at 25% ap + timothyteakettle: + - tweak: changing your character's gender won't randomize its hairstyle and facial + hairstyle now +2020-08-28: + timothyteakettle: + - rscadd: an ancient game over a thousand years old has re-emerged among crewmembers + - rock paper scissors + - rscadd: you can now choose a body sprite as an anthromorph or anthromorphic insect, + and can choose from aquatic/avian and apid respectively (and obviously back + to the defaults too) +2020-08-30: + raspy-on-osu: + - rscadd: new explosion echoes + - tweak: explosion echo range + - soundadd: 5 new explosion related sounds diff --git a/html/ghost.png b/html/ghost.png new file mode 100644 index 0000000000..e4b426ca47 Binary files /dev/null and b/html/ghost.png differ diff --git a/icons/UI_Icons/Arcade/boss1.gif b/icons/UI_Icons/Arcade/boss1.gif new file mode 100644 index 0000000000..4730ac0021 Binary files /dev/null and b/icons/UI_Icons/Arcade/boss1.gif differ diff --git a/icons/UI_Icons/Arcade/boss2.gif b/icons/UI_Icons/Arcade/boss2.gif new file mode 100644 index 0000000000..d95fd84f0e Binary files /dev/null and b/icons/UI_Icons/Arcade/boss2.gif differ diff --git a/icons/UI_Icons/Arcade/boss3.gif b/icons/UI_Icons/Arcade/boss3.gif new file mode 100644 index 0000000000..e97056998a Binary files /dev/null and b/icons/UI_Icons/Arcade/boss3.gif differ diff --git a/icons/UI_Icons/Arcade/boss4.gif b/icons/UI_Icons/Arcade/boss4.gif new file mode 100644 index 0000000000..6695b6cfbf Binary files /dev/null and b/icons/UI_Icons/Arcade/boss4.gif differ diff --git a/icons/UI_Icons/Arcade/boss5.gif b/icons/UI_Icons/Arcade/boss5.gif new file mode 100644 index 0000000000..a827fb8c4e Binary files /dev/null and b/icons/UI_Icons/Arcade/boss5.gif differ diff --git a/icons/UI_Icons/Arcade/boss6.gif b/icons/UI_Icons/Arcade/boss6.gif new file mode 100644 index 0000000000..7a926cf89d Binary files /dev/null and b/icons/UI_Icons/Arcade/boss6.gif differ diff --git a/icons/UI_Icons/tgui/ntosradar_background.png b/icons/UI_Icons/tgui/ntosradar_background.png new file mode 100644 index 0000000000..bac7647e3a Binary files /dev/null and b/icons/UI_Icons/tgui/ntosradar_background.png differ diff --git a/icons/UI_Icons/tgui/ntosradar_pointer.png b/icons/UI_Icons/tgui/ntosradar_pointer.png new file mode 100644 index 0000000000..e71823f391 Binary files /dev/null and b/icons/UI_Icons/tgui/ntosradar_pointer.png differ diff --git a/icons/UI_Icons/tgui/ntosradar_pointer_S.png b/icons/UI_Icons/tgui/ntosradar_pointer_S.png new file mode 100644 index 0000000000..51a0dd49d9 Binary files /dev/null and b/icons/UI_Icons/tgui/ntosradar_pointer_S.png differ diff --git a/icons/effects/160x160.dmi b/icons/effects/160x160.dmi index 0a97573a9b..2adedb6c03 100644 Binary files a/icons/effects/160x160.dmi and b/icons/effects/160x160.dmi differ diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index b60ff97b2b..34f4adf6ce 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 0c4784553c..e5bff44ac4 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/effects/beam_splash.dmi b/icons/effects/beam_splash.dmi new file mode 100644 index 0000000000..d7deb3e927 Binary files /dev/null and b/icons/effects/beam_splash.dmi differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index a2fce4678f..52164e1d33 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/eldritch.dmi b/icons/effects/eldritch.dmi new file mode 100644 index 0000000000..82549dccf0 Binary files /dev/null and b/icons/effects/eldritch.dmi differ diff --git a/icons/effects/freeze.dmi b/icons/effects/freeze.dmi index 28db97d87b..0461619064 100644 Binary files a/icons/effects/freeze.dmi and b/icons/effects/freeze.dmi differ diff --git a/icons/effects/mouse_pointers/barn_target.dmi b/icons/effects/mouse_pointers/barn_target.dmi new file mode 100644 index 0000000000..475a2b88b1 Binary files /dev/null and b/icons/effects/mouse_pointers/barn_target.dmi differ diff --git a/icons/effects/mouse_pointers/blind_target.dmi b/icons/effects/mouse_pointers/blind_target.dmi new file mode 100644 index 0000000000..1d33fc7a4c Binary files /dev/null and b/icons/effects/mouse_pointers/blind_target.dmi differ diff --git a/icons/effects/mouse_pointers/cult_target.dmi b/icons/effects/mouse_pointers/cult_target.dmi new file mode 100644 index 0000000000..650feb3361 Binary files /dev/null and b/icons/effects/mouse_pointers/cult_target.dmi differ diff --git a/icons/effects/mouse_pointers/mecha_mouse-disable.dmi b/icons/effects/mouse_pointers/mecha_mouse-disable.dmi new file mode 100644 index 0000000000..48924c58c2 Binary files /dev/null and b/icons/effects/mouse_pointers/mecha_mouse-disable.dmi differ diff --git a/icons/effects/mouse_pointers/mecha_mouse.dmi b/icons/effects/mouse_pointers/mecha_mouse.dmi new file mode 100644 index 0000000000..4b46a44684 Binary files /dev/null and b/icons/effects/mouse_pointers/mecha_mouse.dmi differ diff --git a/icons/effects/mouse_pointers/mindswap_target.dmi b/icons/effects/mouse_pointers/mindswap_target.dmi new file mode 100644 index 0000000000..32ccda154d Binary files /dev/null and b/icons/effects/mouse_pointers/mindswap_target.dmi differ diff --git a/icons/effects/mouse_pointers/overload_machine_target.dmi b/icons/effects/mouse_pointers/overload_machine_target.dmi new file mode 100644 index 0000000000..8bc67cdab6 Binary files /dev/null and b/icons/effects/mouse_pointers/overload_machine_target.dmi differ diff --git a/icons/effects/mouse_pointers/override_machine_target.dmi b/icons/effects/mouse_pointers/override_machine_target.dmi new file mode 100644 index 0000000000..77dbb4ba32 Binary files /dev/null and b/icons/effects/mouse_pointers/override_machine_target.dmi differ diff --git a/icons/effects/supplypod_down_target.dmi b/icons/effects/mouse_pointers/supplypod_down_target.dmi similarity index 100% rename from icons/effects/supplypod_down_target.dmi rename to icons/effects/mouse_pointers/supplypod_down_target.dmi diff --git a/icons/effects/mouse_pointers/supplypod_pickturf.dmi b/icons/effects/mouse_pointers/supplypod_pickturf.dmi new file mode 100644 index 0000000000..3ca1131e1a Binary files /dev/null and b/icons/effects/mouse_pointers/supplypod_pickturf.dmi differ diff --git a/icons/effects/mouse_pointers/supplypod_pickturf_down.dmi b/icons/effects/mouse_pointers/supplypod_pickturf_down.dmi new file mode 100644 index 0000000000..113fe47540 Binary files /dev/null and b/icons/effects/mouse_pointers/supplypod_pickturf_down.dmi differ diff --git a/icons/effects/supplypod_target.dmi b/icons/effects/mouse_pointers/supplypod_target.dmi similarity index 100% rename from icons/effects/supplypod_target.dmi rename to icons/effects/mouse_pointers/supplypod_target.dmi diff --git a/icons/effects/mouse_pointers/throw_target.dmi b/icons/effects/mouse_pointers/throw_target.dmi new file mode 100644 index 0000000000..660eafbf2b Binary files /dev/null and b/icons/effects/mouse_pointers/throw_target.dmi differ diff --git a/icons/effects/mouse_pointers/wrap_target.dmi b/icons/effects/mouse_pointers/wrap_target.dmi new file mode 100644 index 0000000000..2e9a338c9e Binary files /dev/null and b/icons/effects/mouse_pointers/wrap_target.dmi differ diff --git a/icons/emoji_32.dmi b/icons/emoji_32.dmi new file mode 100644 index 0000000000..fdd6fc7d75 Binary files /dev/null and b/icons/emoji_32.dmi differ diff --git a/icons/materials/composite.dmi b/icons/materials/composite.dmi new file mode 100644 index 0000000000..a2a92b6eb7 Binary files /dev/null and b/icons/materials/composite.dmi differ diff --git a/icons/mecha/mech_construct.dmi b/icons/mecha/mech_construct.dmi index 6d48367f2a..2ae4a93a2e 100644 Binary files a/icons/mecha/mech_construct.dmi and b/icons/mecha/mech_construct.dmi differ diff --git a/icons/mecha/mech_construction.dmi b/icons/mecha/mech_construction.dmi index a1ac490f00..1f50346b71 100644 Binary files a/icons/mecha/mech_construction.dmi and b/icons/mecha/mech_construction.dmi differ diff --git a/icons/mecha/mecha.dmi b/icons/mecha/mecha.dmi index 4b09f791c3..310dd6709c 100644 Binary files a/icons/mecha/mecha.dmi and b/icons/mecha/mecha.dmi differ diff --git a/icons/misc/language.dmi b/icons/misc/language.dmi index 155dbab98d..9501dc9216 100644 Binary files a/icons/misc/language.dmi and b/icons/misc/language.dmi differ diff --git a/icons/mob/32x64.dmi b/icons/mob/32x64.dmi index 32b25ba739..cddf9599b4 100644 Binary files a/icons/mob/32x64.dmi and b/icons/mob/32x64.dmi differ diff --git a/icons/mob/actions/actions_ecult.dmi b/icons/mob/actions/actions_ecult.dmi new file mode 100644 index 0000000000..0a130f006e Binary files /dev/null and b/icons/mob/actions/actions_ecult.dmi differ diff --git a/icons/mob/actions/backgrounds.dmi b/icons/mob/actions/backgrounds.dmi index 07839588ce..6b983df95a 100644 Binary files a/icons/mob/actions/backgrounds.dmi and b/icons/mob/actions/backgrounds.dmi differ diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi index 13f97d3761..50bf65b27f 100644 Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ diff --git a/icons/mob/clockwork_mobs.dmi b/icons/mob/clockwork_mobs.dmi index 5985adf12d..54690f6cac 100644 Binary files a/icons/mob/clockwork_mobs.dmi and b/icons/mob/clockwork_mobs.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 0a1372ac2b..8594af8ec2 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index fd3016ac89..4ac82ca299 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/eyes.dmi b/icons/mob/clothing/eyes.dmi index 54ef7c5814..876159c258 100644 Binary files a/icons/mob/clothing/eyes.dmi and b/icons/mob/clothing/eyes.dmi differ diff --git a/icons/mob/clothing/feet_digi.dmi b/icons/mob/clothing/feet_digi.dmi index 7815f3d0a4..f798850ee7 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 856fe2149a..44499649f9 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 ccd902ec03..16571a4aa1 100644 Binary files a/icons/mob/clothing/head.dmi and b/icons/mob/clothing/head.dmi differ diff --git a/icons/mob/clothing/head_muzzled.dmi b/icons/mob/clothing/head_muzzled.dmi index 16cc63a13e..62c1ebea0a 100644 Binary files a/icons/mob/clothing/head_muzzled.dmi and b/icons/mob/clothing/head_muzzled.dmi differ diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi index c361563da3..ecc6e2dd2c 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 0a10f1edbe..a1404cfbce 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 86dec62a41..7bfecb4158 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 1c06c203e1..08d276a484 100644 Binary files a/icons/mob/clothing/suit.dmi and b/icons/mob/clothing/suit.dmi differ diff --git a/icons/mob/clothing/suit_digi.dmi b/icons/mob/clothing/suit_digi.dmi index ca2a088551..dd00713770 100644 Binary files a/icons/mob/clothing/suit_digi.dmi and b/icons/mob/clothing/suit_digi.dmi differ diff --git a/icons/mob/clothing/taur_canine.dmi b/icons/mob/clothing/taur_canine.dmi index 26e4d488cd..24cf51d2e5 100644 Binary files a/icons/mob/clothing/taur_canine.dmi and b/icons/mob/clothing/taur_canine.dmi differ diff --git a/icons/mob/clothing/taur_hooved.dmi b/icons/mob/clothing/taur_hooved.dmi index 993e9c2550..03fd8c8a30 100644 Binary files a/icons/mob/clothing/taur_hooved.dmi and b/icons/mob/clothing/taur_hooved.dmi differ diff --git a/icons/mob/clothing/taur_naga.dmi b/icons/mob/clothing/taur_naga.dmi index a4c3644003..d178ba4a1c 100644 Binary files a/icons/mob/clothing/taur_naga.dmi and b/icons/mob/clothing/taur_naga.dmi differ diff --git a/icons/mob/clothing/underwear.dmi b/icons/mob/clothing/underwear.dmi index f0c2cde93d..8cf1144a68 100644 Binary files a/icons/mob/clothing/underwear.dmi and b/icons/mob/clothing/underwear.dmi differ diff --git a/icons/mob/clothing/uniform.dmi b/icons/mob/clothing/uniform.dmi index 163d2dc2f2..3d24a9addd 100644 Binary files a/icons/mob/clothing/uniform.dmi and b/icons/mob/clothing/uniform.dmi differ diff --git a/icons/mob/clothing/uniform_digi.dmi b/icons/mob/clothing/uniform_digi.dmi index da94f97895..bcb894033e 100644 Binary files a/icons/mob/clothing/uniform_digi.dmi and b/icons/mob/clothing/uniform_digi.dmi differ diff --git a/icons/mob/cyborg/Drakeborg-licensing.txt b/icons/mob/cyborg/Drakeborg-licensing.txt new file mode 100644 index 0000000000..f2d3ca925c --- /dev/null +++ b/icons/mob/cyborg/Drakeborg-licensing.txt @@ -0,0 +1,69 @@ +Drakeborg & drakeplushies are created by deviantart.com/mizartz + +https://creativecommons.org/licenses/by-nc-sa/3.0/ +Attribution-NonCommercial-ShareAlike 3.0 Unported + +CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM ITS USE. +License +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS. + +1. Definitions + +"Adaptation" means a work based upon the Work, or upon the Work and other pre-existing works, such as a translation, adaptation, derivative work, arrangement of music or other alterations of a literary or artistic work, or phonogram or performance and includes cinematographic adaptations or any other form in which the Work may be recast, transformed, or adapted including in any form recognizably derived from the original, except that a work that constitutes a Collection will not be considered an Adaptation for the purpose of this License. For the avoidance of doubt, where the Work is a musical work, performance or phonogram, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered an Adaptation for the purpose of this License. +"Collection" means a collection of literary or artistic works, such as encyclopedias and anthologies, or performances, phonograms or broadcasts, or other works or subject matter other than works listed in Section 1(g) below, which, by reason of the selection and arrangement of their contents, constitute intellectual creations, in which the Work is included in its entirety in unmodified form along with one or more other contributions, each constituting separate and independent works in themselves, which together are assembled into a collective whole. A work that constitutes a Collection will not be considered an Adaptation (as defined above) for the purposes of this License. +"Distribute" means to make available to the public the original and copies of the Work or Adaptation, as appropriate, through sale or other transfer of ownership. +"License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, Noncommercial, ShareAlike. +"Licensor" means the individual, individuals, entity or entities that offer(s) the Work under the terms of this License. +"Original Author" means, in the case of a literary or artistic work, the individual, individuals, entity or entities who created the Work or if no individual or entity can be identified, the publisher; and in addition (i) in the case of a performance the actors, singers, musicians, dancers, and other persons who act, sing, deliver, declaim, play in, interpret or otherwise perform literary or artistic works or expressions of folklore; (ii) in the case of a phonogram the producer being the person or legal entity who first fixes the sounds of a performance or other sounds; and, (iii) in the case of broadcasts, the organization that transmits the broadcast. +"Work" means the literary and/or artistic work offered under the terms of this License including without limitation any production in the literary, scientific and artistic domain, whatever may be the mode or form of its expression including digital form, such as a book, pamphlet and other writing; a lecture, address, sermon or other work of the same nature; a dramatic or dramatico-musical work; a choreographic work or entertainment in dumb show; a musical composition with or without words; a cinematographic work to which are assimilated works expressed by a process analogous to cinematography; a work of drawing, painting, architecture, sculpture, engraving or lithography; a photographic work to which are assimilated works expressed by a process analogous to photography; a work of applied art; an illustration, map, plan, sketch or three-dimensional work relative to geography, topography, architecture or science; a performance; a broadcast; a phonogram; a compilation of data to the extent it is protected as a copyrightable work; or a work performed by a variety or circus performer to the extent it is not otherwise considered a literary or artistic work. +"You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation. +"Publicly Perform" means to perform public recitations of the Work and to communicate to the public those public recitations, by any means or process, including by wire or wireless means or public digital performances; to make available to the public Works in such a way that members of the public may access these Works from a place and at a place individually chosen by them; to perform the Work to the public by any means or process and the communication to the public of the performances of the Work, including by public digital performance; to broadcast and rebroadcast the Work by any means including signs, sounds or images. +"Reproduce" means to make copies of the Work by any means including without limitation by sound or visual recordings and the right of fixation and reproducing fixations of the Work, including storage of a protected performance or phonogram in digital form or other electronic medium. +2. Fair Dealing Rights. Nothing in this License is intended to reduce, limit, or restrict any uses free from copyright or rights arising from limitations or exceptions that are provided for in connection with the copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below: + +to Reproduce the Work, to incorporate the Work into one or more Collections, and to Reproduce the Work as incorporated in the Collections; +to create and Reproduce Adaptations provided that any such Adaptation, including any translation in any medium, takes reasonable steps to clearly label, demarcate or otherwise identify that changes were made to the original Work. For example, a translation could be marked "The original work was translated from English to Spanish," or a modification could indicate "The original work has been modified."; +to Distribute and Publicly Perform the Work including as incorporated in Collections; and, +to Distribute and Publicly Perform Adaptations. +The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. Subject to Section 8(f), all rights not expressly granted by Licensor are hereby reserved, including but not limited to the rights described in Section 4(e). + +4. Restrictions. The license granted in Section 3 above is expressly made subject to and limited by the following restrictions: + +You may Distribute or Publicly Perform the Work only under the terms of this License. You must include a copy of, or the Uniform Resource Identifier (URI) for, this License with every copy of the Work You Distribute or Publicly Perform. You may not offer or impose any terms on the Work that restrict the terms of this License or the ability of the recipient of the Work to exercise the rights granted to that recipient under the terms of the License. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties with every copy of the Work You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Work, You may not impose any effective technological measures on the Work that restrict the ability of a recipient of the Work from You to exercise the rights granted to that recipient under the terms of the License. This Section 4(a) applies to the Work as incorporated in a Collection, but this does not require the Collection apart from the Work itself to be made subject to the terms of this License. If You create a Collection, upon notice from any Licensor You must, to the extent practicable, remove from the Collection any credit as required by Section 4(d), as requested. If You create an Adaptation, upon notice from any Licensor You must, to the extent practicable, remove from the Adaptation any credit as required by Section 4(d), as requested. +You may Distribute or Publicly Perform an Adaptation only under: (i) the terms of this License; (ii) a later version of this License with the same License Elements as this License; (iii) a Creative Commons jurisdiction license (either this or a later license version) that contains the same License Elements as this License (e.g., Attribution-NonCommercial-ShareAlike 3.0 US) ("Applicable License"). You must include a copy of, or the URI, for Applicable License with every copy of each Adaptation You Distribute or Publicly Perform. You may not offer or impose any terms on the Adaptation that restrict the terms of the Applicable License or the ability of the recipient of the Adaptation to exercise the rights granted to that recipient under the terms of the Applicable License. You must keep intact all notices that refer to the Applicable License and to the disclaimer of warranties with every copy of the Work as included in the Adaptation You Distribute or Publicly Perform. When You Distribute or Publicly Perform the Adaptation, You may not impose any effective technological measures on the Adaptation that restrict the ability of a recipient of the Adaptation from You to exercise the rights granted to that recipient under the terms of the Applicable License. This Section 4(b) applies to the Adaptation as incorporated in a Collection, but this does not require the Collection apart from the Adaptation itself to be made subject to the terms of the Applicable License. +You may not exercise any of the rights granted to You in Section 3 above in any manner that is primarily intended for or directed toward commercial advantage or private monetary compensation. The exchange of the Work for other copyrighted works by means of digital file-sharing or otherwise shall not be considered to be intended for or directed toward commercial advantage or private monetary compensation, provided there is no payment of any monetary compensation in con-nection with the exchange of copyrighted works. +If You Distribute, or Publicly Perform the Work or any Adaptations or Collections, You must, unless a request has been made pursuant to Section 4(a), keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or if the Original Author and/or Licensor designate another party or parties (e.g., a sponsor institute, publishing entity, journal) for attribution ("Attribution Parties") in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; (ii) the title of the Work if supplied; (iii) to the extent reasonably practicable, the URI, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and, (iv) consistent with Section 3(b), in the case of an Adaptation, a credit identifying the use of the Work in the Adaptation (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). The credit required by this Section 4(d) may be implemented in any reasonable manner; provided, however, that in the case of a Adaptation or Collection, at a minimum such credit will appear, if a credit for all contributing authors of the Adaptation or Collection appears, then as part of these credits and in a manner at least as prominent as the credits for the other contributing authors. For the avoidance of doubt, You may only use the credit required by this Section for the purpose of attribution in the manner set out above and, by exercising Your rights under this License, You may not implicitly or explicitly assert or imply any connection with, sponsorship or endorsement by the Original Author, Licensor and/or Attribution Parties, as appropriate, of You or Your use of the Work, without the separate, express prior written permission of the Original Author, Licensor and/or Attribution Parties. +For the avoidance of doubt: + +Non-waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme cannot be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License; +Waivable Compulsory License Schemes. In those jurisdictions in which the right to collect royalties through any statutory or compulsory licensing scheme can be waived, the Licensor reserves the exclusive right to collect such royalties for any exercise by You of the rights granted under this License if Your exercise of such rights is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c) and otherwise waives the right to collect royalties through any statutory or compulsory licensing scheme; and, +Voluntary License Schemes. The Licensor reserves the right to collect royalties, whether individually or, in the event that the Licensor is a member of a collecting society that administers voluntary licensing schemes, via that society, from any exercise by You of the rights granted under this License that is for a purpose or use which is otherwise than noncommercial as permitted under Section 4(c). +Except as otherwise agreed in writing by the Licensor or as may be otherwise permitted by applicable law, if You Reproduce, Distribute or Publicly Perform the Work either by itself or as part of any Adaptations or Collections, You must not distort, mutilate, modify or take other derogatory action in relation to the Work which would be prejudicial to the Original Author's honor or reputation. Licensor agrees that in those jurisdictions (e.g. Japan), in which any exercise of the right granted in Section 3(b) of this License (the right to make Adaptations) would be deemed to be a distortion, mutilation, modification or other derogatory action prejudicial to the Original Author's honor and reputation, the Licensor will waive or not assert, as appropriate, this Section, to the fullest extent permitted by the applicable national law, to enable You to reasonably exercise Your right under Section 3(b) of this License (right to make Adaptations) but not otherwise. +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING AND TO THE FULLEST EXTENT PERMITTED BY APPLICABLE LAW, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO THIS EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + +This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Adaptations or Collections from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License. +Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above. +8. Miscellaneous + +Each time You Distribute or Publicly Perform the Work or a Collection, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License. +Each time You Distribute or Publicly Perform an Adaptation, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License. +If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. +No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent. +This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You. +The rights granted under, and the subject matter referenced, in this License were drafted utilizing the terminology of the Berne Convention for the Protection of Literary and Artistic Works (as amended on September 28, 1979), the Rome Convention of 1961, the WIPO Copyright Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and the Universal Copyright Convention (as revised on July 24, 1971). These rights and subject matter take effect in the relevant jurisdiction in which the License terms are sought to be enforced according to the corresponding provisions of the implementation of those treaty provisions in the applicable national law. If the standard suite of rights granted under applicable copyright law includes additional rights not granted under this License, such additional rights are deemed to be included in the License; this License is not intended to restrict the license of any rights under applicable law. +Creative Commons Notice +Creative Commons is not a party to this License, and makes no warranty whatsoever in connection with the Work. Creative Commons will not be liable to You or any party on any legal theory for any damages whatsoever, including without limitation any general, special, incidental or consequential damages arising in connection to this license. Notwithstanding the foregoing two (2) sentences, if Creative Commons has expressly identified itself as the Licensor hereunder, it shall have all rights and obligations of Licensor. + +Except for the limited purpose of indicating to the public that the Work is licensed under the CCPL, Creative Commons does not authorize the use by either party of the trademark "Creative Commons" or any related trademark or logo of Creative Commons without the prior written consent of Creative Commons. Any permitted use will be in compliance with Creative Commons' then-current trademark usage guidelines, as may be published on its website or otherwise made available upon request from time to time. For the avoidance of doubt, this trademark restriction does not form part of this License. + +Creative Commons may be contacted at https://creativecommons.org/. \ No newline at end of file diff --git a/icons/mob/cyborg/drakemech.dmi b/icons/mob/cyborg/drakemech.dmi new file mode 100644 index 0000000000..6a4845d983 Binary files /dev/null and b/icons/mob/cyborg/drakemech.dmi differ diff --git a/icons/mob/eldritch_mobs.dmi b/icons/mob/eldritch_mobs.dmi new file mode 100644 index 0000000000..8a16d53f88 Binary files /dev/null and b/icons/mob/eldritch_mobs.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index c21fa47b9c..1d2007fd63 100644 Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ diff --git a/icons/mob/human_face.dmi b/icons/mob/human_face.dmi index a4e2a9d5b2..8055233ea7 100644 Binary files a/icons/mob/human_face.dmi and b/icons/mob/human_face.dmi differ diff --git a/icons/mob/human_parts.dmi b/icons/mob/human_parts.dmi index 916686e63f..60978d55a2 100644 Binary files a/icons/mob/human_parts.dmi and b/icons/mob/human_parts.dmi differ diff --git a/icons/mob/human_parts_greyscale.dmi b/icons/mob/human_parts_greyscale.dmi index 989ec8049c..794074bfe4 100644 Binary files a/icons/mob/human_parts_greyscale.dmi and b/icons/mob/human_parts_greyscale.dmi differ diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi index 6b47171066..6dc8d82753 100644 Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi index 3750e28906..ca87f74a6f 100644 Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ diff --git a/icons/mob/inhands/antag/clockwork_lefthand.dmi b/icons/mob/inhands/antag/clockwork_lefthand.dmi index 88bd8ab710..080d7fdc83 100644 Binary files a/icons/mob/inhands/antag/clockwork_lefthand.dmi and b/icons/mob/inhands/antag/clockwork_lefthand.dmi differ diff --git a/icons/mob/inhands/antag/clockwork_righthand.dmi b/icons/mob/inhands/antag/clockwork_righthand.dmi index 20190e4add..42715d6e92 100644 Binary files a/icons/mob/inhands/antag/clockwork_righthand.dmi and b/icons/mob/inhands/antag/clockwork_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/belt_lefthand.dmi b/icons/mob/inhands/equipment/belt_lefthand.dmi index beac56725a..81b12c60f9 100644 Binary files a/icons/mob/inhands/equipment/belt_lefthand.dmi and b/icons/mob/inhands/equipment/belt_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/belt_righthand.dmi b/icons/mob/inhands/equipment/belt_righthand.dmi index da31cc9710..42ed3a30c6 100644 Binary files a/icons/mob/inhands/equipment/belt_righthand.dmi and b/icons/mob/inhands/equipment/belt_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 19738ed490..315ca5e924 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 9589e338e1..6af883f2e8 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_lefthand.dmi b/icons/mob/inhands/weapons/hammers_lefthand.dmi index 306fd0db8a..b753a1f181 100644 Binary files a/icons/mob/inhands/weapons/hammers_lefthand.dmi and b/icons/mob/inhands/weapons/hammers_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/hammers_righthand.dmi b/icons/mob/inhands/weapons/hammers_righthand.dmi index 674e4d510b..7650f6c760 100644 Binary files a/icons/mob/inhands/weapons/hammers_righthand.dmi and b/icons/mob/inhands/weapons/hammers_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi index 1e48d57ac7..23d80af9ef 100644 Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi index 5a5ee6f3db..702c0299b5 100644 Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ diff --git a/icons/mob/map_backgrounds.dmi b/icons/mob/map_backgrounds.dmi new file mode 100644 index 0000000000..dc6e3e46b1 Binary files /dev/null and b/icons/mob/map_backgrounds.dmi differ diff --git a/icons/mob/mob.dmi b/icons/mob/mob.dmi index de09fb1c63..23f0e2cc13 100644 Binary files a/icons/mob/mob.dmi and b/icons/mob/mob.dmi differ diff --git a/icons/mob/robots.dmi b/icons/mob/robots.dmi index 9bb41bf527..082bfb3c3e 100644 Binary files a/icons/mob/robots.dmi and b/icons/mob/robots.dmi differ diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index 60fe2f9839..30c23601a5 100644 Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ diff --git a/icons/mob/secbot_accessories.dmi b/icons/mob/secbot_accessories.dmi new file mode 100644 index 0000000000..944aac44f3 Binary files /dev/null and b/icons/mob/secbot_accessories.dmi differ diff --git a/icons/mob/wings.dmi b/icons/mob/wings.dmi index ace37b1f17..4523403344 100644 Binary files a/icons/mob/wings.dmi and b/icons/mob/wings.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index bebb625440..e1caad8279 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/assemblies/new_assemblies.dmi b/icons/obj/assemblies/new_assemblies.dmi index 2283b84c43..32eda1eb49 100644 Binary files a/icons/obj/assemblies/new_assemblies.dmi and b/icons/obj/assemblies/new_assemblies.dmi differ diff --git a/icons/obj/bloodpack.dmi b/icons/obj/bloodpack.dmi index 82b4c2e543..2355a81f8f 100644 Binary files a/icons/obj/bloodpack.dmi and b/icons/obj/bloodpack.dmi differ diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index aea15e2e39..cd12f4a457 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/clockwork_objects.dmi b/icons/obj/clockwork_objects.dmi index 1948bb605c..156d4fa0c6 100644 Binary files a/icons/obj/clockwork_objects.dmi and b/icons/obj/clockwork_objects.dmi differ diff --git a/icons/obj/closet.dmi b/icons/obj/closet.dmi index d3f055d1f2..b71b021d80 100644 Binary files a/icons/obj/closet.dmi and b/icons/obj/closet.dmi differ diff --git a/icons/obj/clothing/accessories.dmi b/icons/obj/clothing/accessories.dmi index c62a88c829..7d13e3f802 100644 Binary files a/icons/obj/clothing/accessories.dmi and b/icons/obj/clothing/accessories.dmi differ diff --git a/icons/obj/clothing/belt_overlays.dmi b/icons/obj/clothing/belt_overlays.dmi index 7e09d425fb..1c22a0ad1b 100644 Binary files a/icons/obj/clothing/belt_overlays.dmi and b/icons/obj/clothing/belt_overlays.dmi differ diff --git a/icons/obj/clothing/glasses.dmi b/icons/obj/clothing/glasses.dmi index e8ba88a12f..4fce479a9d 100644 Binary files a/icons/obj/clothing/glasses.dmi and b/icons/obj/clothing/glasses.dmi differ diff --git a/icons/obj/clothing/gloves.dmi b/icons/obj/clothing/gloves.dmi index 535ae0d241..c0f78ee604 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 93e499f595..8fbb2abe1e 100644 Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ diff --git a/icons/obj/clothing/reinf_kits.dmi b/icons/obj/clothing/reinf_kits.dmi new file mode 100644 index 0000000000..3b23d53342 Binary files /dev/null and b/icons/obj/clothing/reinf_kits.dmi differ diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi index 68210dc01f..3476b16258 100644 Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index 57424c7b99..76f5722c8b 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/contraband.dmi b/icons/obj/contraband.dmi index a1d5bc5900..a6c554f7da 100644 Binary files a/icons/obj/contraband.dmi and b/icons/obj/contraband.dmi differ diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi index c280ee786f..7dac61a663 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 193d4bc4da..5a9e1e54b6 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/icons/obj/doors/airlocks/shuttle/overlays.dmi b/icons/obj/doors/airlocks/shuttle/overlays.dmi index b2bb2cfa04..70df610212 100644 Binary files a/icons/obj/doors/airlocks/shuttle/overlays.dmi and b/icons/obj/doors/airlocks/shuttle/overlays.dmi differ diff --git a/icons/obj/doors/airlocks/shuttle/shuttle.dmi b/icons/obj/doors/airlocks/shuttle/shuttle.dmi index 0e05597163..b4b998e4bc 100644 Binary files a/icons/obj/doors/airlocks/shuttle/shuttle.dmi and b/icons/obj/doors/airlocks/shuttle/shuttle.dmi differ diff --git a/icons/obj/doors/doorfirewindow.dmi b/icons/obj/doors/doorfirewindow.dmi new file mode 100644 index 0000000000..76f8a7e98e Binary files /dev/null and b/icons/obj/doors/doorfirewindow.dmi differ diff --git a/icons/obj/doors/edge_Doorfire.dmi b/icons/obj/doors/edge_Doorfire.dmi index 3aad0114d4..51777624db 100644 Binary files a/icons/obj/doors/edge_Doorfire.dmi and b/icons/obj/doors/edge_Doorfire.dmi differ diff --git a/icons/obj/drinks.dmi b/icons/obj/drinks.dmi index 27caef76b2..5962e7522d 100644 Binary files a/icons/obj/drinks.dmi and b/icons/obj/drinks.dmi differ diff --git a/icons/obj/eldritch.dmi b/icons/obj/eldritch.dmi new file mode 100644 index 0000000000..50c2913708 Binary files /dev/null and b/icons/obj/eldritch.dmi differ diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi index 414930ac25..7ef3a7d418 100644 Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ diff --git a/icons/obj/food/containers.dmi b/icons/obj/food/containers.dmi index 641715fd87..5e1332ffd9 100644 Binary files a/icons/obj/food/containers.dmi and b/icons/obj/food/containers.dmi differ diff --git a/icons/obj/food/food.dmi b/icons/obj/food/food.dmi index e7196190cf..078cadfd60 100644 Binary files a/icons/obj/food/food.dmi and b/icons/obj/food/food.dmi differ diff --git a/icons/obj/food/piecake.dmi b/icons/obj/food/piecake.dmi index 5638235217..935f7e8ad5 100644 Binary files a/icons/obj/food/piecake.dmi and b/icons/obj/food/piecake.dmi differ diff --git a/icons/obj/food/soupsalad.dmi b/icons/obj/food/soupsalad.dmi index 378927e8f9..ca9c150480 100644 Binary files a/icons/obj/food/soupsalad.dmi and b/icons/obj/food/soupsalad.dmi differ diff --git a/icons/obj/guns/energy.dmi b/icons/obj/guns/energy.dmi index 33872719fe..7e7e4a644b 100644 Binary files a/icons/obj/guns/energy.dmi and b/icons/obj/guns/energy.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index 8c50e7da27..00670916db 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/hydroponics/growing.dmi b/icons/obj/hydroponics/growing.dmi index c93865ca77..0866791ed6 100644 Binary files a/icons/obj/hydroponics/growing.dmi and b/icons/obj/hydroponics/growing.dmi differ diff --git a/icons/obj/hydroponics/growing_flowers.dmi b/icons/obj/hydroponics/growing_flowers.dmi index 98d9af2ce6..b48051cc56 100644 Binary files a/icons/obj/hydroponics/growing_flowers.dmi and b/icons/obj/hydroponics/growing_flowers.dmi differ diff --git a/icons/obj/hydroponics/growing_vegetables.dmi b/icons/obj/hydroponics/growing_vegetables.dmi index b426b8f6de..ce0beb86ce 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 fd9d310c73..7474bb87ab 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 15b7e2b96c..b64c218c69 100644 Binary files a/icons/obj/hydroponics/seeds.dmi and b/icons/obj/hydroponics/seeds.dmi differ diff --git a/icons/obj/implants.dmi b/icons/obj/implants.dmi index a6d4697673..b7cb90e9f4 100644 Binary files a/icons/obj/implants.dmi and b/icons/obj/implants.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index c5b2b3fc42..c5aca2394f 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/icons/obj/janitor.dmi b/icons/obj/janitor.dmi index a157d333b0..b240391328 100644 Binary files a/icons/obj/janitor.dmi and b/icons/obj/janitor.dmi differ diff --git a/icons/obj/lavaland/terrain.dmi b/icons/obj/lavaland/terrain.dmi new file mode 100644 index 0000000000..4db51145ee Binary files /dev/null and b/icons/obj/lavaland/terrain.dmi differ diff --git a/icons/obj/license.txt b/icons/obj/license.txt new file mode 100644 index 0000000000..2e27ba80f2 --- /dev/null +++ b/icons/obj/license.txt @@ -0,0 +1,3 @@ +icons/obj/plushies.dmi's icon state of secdrake and meddrake by Mizartz. It has been licensed under the CC BY-NC-SA 3.0 license. + +CC BY-NC-SA 3.0 https://creativecommons.org/licenses/by-nc-sa/3.0/ \ No newline at end of file diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi index 675005da91..0e262895fd 100644 Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ diff --git a/icons/obj/machines/gateway.dmi b/icons/obj/machines/gateway.dmi index cfe4c26709..fc45145ae8 100644 Binary files a/icons/obj/machines/gateway.dmi and b/icons/obj/machines/gateway.dmi differ diff --git a/icons/obj/machines/medipen_refiller.dmi b/icons/obj/machines/medipen_refiller.dmi new file mode 100644 index 0000000000..300d218d2d Binary files /dev/null and b/icons/obj/machines/medipen_refiller.dmi differ diff --git a/icons/obj/machines/research.dmi b/icons/obj/machines/research.dmi index 7d64c494fd..7dcd4e6bcb 100644 Binary files a/icons/obj/machines/research.dmi and b/icons/obj/machines/research.dmi differ diff --git a/icons/obj/machines/sheetifier.dmi b/icons/obj/machines/sheetifier.dmi new file mode 100644 index 0000000000..46d8b06bab Binary files /dev/null and b/icons/obj/machines/sheetifier.dmi differ diff --git a/icons/obj/mafia.dmi b/icons/obj/mafia.dmi new file mode 100644 index 0000000000..c44b80aba1 Binary files /dev/null and b/icons/obj/mafia.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index 43bc9c48aa..e7063b71db 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/obj/modular_console.dmi b/icons/obj/modular_console.dmi index 8d4ec3e2d8..5d3cd0312c 100644 Binary files a/icons/obj/modular_console.dmi and b/icons/obj/modular_console.dmi differ diff --git a/icons/obj/modular_laptop.dmi b/icons/obj/modular_laptop.dmi index 1e506ca6fe..fd24d27a97 100644 Binary files a/icons/obj/modular_laptop.dmi and b/icons/obj/modular_laptop.dmi differ diff --git a/icons/obj/modular_tablet.dmi b/icons/obj/modular_tablet.dmi index 621874a969..32edb57475 100644 Binary files a/icons/obj/modular_tablet.dmi and b/icons/obj/modular_tablet.dmi differ diff --git a/icons/obj/module.dmi b/icons/obj/module.dmi index bdf2d5801b..ef3a98b875 100644 Binary files a/icons/obj/module.dmi and b/icons/obj/module.dmi differ diff --git a/icons/obj/pet_carrier.dmi b/icons/obj/pet_carrier.dmi index 340636056c..b02f9d6ce4 100644 Binary files a/icons/obj/pet_carrier.dmi and b/icons/obj/pet_carrier.dmi differ diff --git a/icons/obj/plumbing/fluid_ducts.dmi b/icons/obj/plumbing/fluid_ducts.dmi new file mode 100644 index 0000000000..87d9d2233b Binary files /dev/null and b/icons/obj/plumbing/fluid_ducts.dmi differ diff --git a/icons/obj/plumbing/plumbers.dmi b/icons/obj/plumbing/plumbers.dmi new file mode 100644 index 0000000000..242622e000 Binary files /dev/null and b/icons/obj/plumbing/plumbers.dmi differ diff --git a/icons/obj/plushes.dmi b/icons/obj/plushes.dmi index 3abb25d8b2..ac0c338016 100644 Binary files a/icons/obj/plushes.dmi and b/icons/obj/plushes.dmi differ diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 92e76f78bb..94568b8633 100644 Binary files a/icons/obj/projectiles.dmi and b/icons/obj/projectiles.dmi differ diff --git a/icons/obj/reagentfillings.dmi b/icons/obj/reagentfillings.dmi index f07928741d..1ac941bae3 100644 Binary files a/icons/obj/reagentfillings.dmi and b/icons/obj/reagentfillings.dmi differ diff --git a/icons/obj/smooth_structures/shuttle_window.dmi b/icons/obj/smooth_structures/shuttle_window.dmi index 2fbf93f703..cb07225a76 100644 Binary files a/icons/obj/smooth_structures/shuttle_window.dmi and b/icons/obj/smooth_structures/shuttle_window.dmi differ diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi index ac6478928d..1cdb3b6443 100644 Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi index 67c1a59c51..16efcf262e 100644 Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index a719356804..1f1709a10c 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/icons/obj/tiles.dmi b/icons/obj/tiles.dmi index 09568ebea1..38d153e261 100644 Binary files a/icons/obj/tiles.dmi and b/icons/obj/tiles.dmi differ diff --git a/icons/obj/tools.dmi b/icons/obj/tools.dmi index f1a8cf3c02..0a457777c2 100644 Binary files a/icons/obj/tools.dmi and b/icons/obj/tools.dmi differ diff --git a/icons/obj/watercloset.dmi b/icons/obj/watercloset.dmi index 4a299f29dd..2b64176878 100644 Binary files a/icons/obj/watercloset.dmi and b/icons/obj/watercloset.dmi differ diff --git a/icons/program_icons/borg_mon.gif b/icons/program_icons/borg_mon.gif new file mode 100644 index 0000000000..35d0f442fd Binary files /dev/null and b/icons/program_icons/borg_mon.gif differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 477120870b..f2b84bbe03 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/icons/turf/floors/glass.dmi b/icons/turf/floors/glass.dmi new file mode 100644 index 0000000000..adf6f57aaa Binary files /dev/null and b/icons/turf/floors/glass.dmi differ diff --git a/icons/turf/floors/reinf_glass.dmi b/icons/turf/floors/reinf_glass.dmi new file mode 100644 index 0000000000..dda99cd07f Binary files /dev/null and b/icons/turf/floors/reinf_glass.dmi differ diff --git a/icons/turf/shuttle.dmi b/icons/turf/shuttle.dmi index a09cb7a847..985b9991a0 100644 Binary files a/icons/turf/shuttle.dmi and b/icons/turf/shuttle.dmi differ diff --git a/icons/turf/walls/materialwall.dmi b/icons/turf/walls/materialwall.dmi new file mode 100644 index 0000000000..c497f76c2e Binary files /dev/null and b/icons/turf/walls/materialwall.dmi differ diff --git a/icons/turf/walls/shuttle_wall.dmi b/icons/turf/walls/shuttle_wall.dmi index cce97b2458..d9c904c336 100644 Binary files a/icons/turf/walls/shuttle_wall.dmi and b/icons/turf/walls/shuttle_wall.dmi differ diff --git a/interface/skin.dmf b/interface/skin.dmf index 8d68336754..cf49f0f30f 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -80,6 +80,7 @@ window "mainwindow" anchor2 = none background-color = #272727 is-visible = false + auto-format = false saved-params = "" elem "tooltip" type = BROWSER diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index 9f3d8911ec..9c35ddb75f 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -66,7 +66,9 @@ h1.alert, h2.alert {color: #000000;} .passive {color: #660000;} .userdanger {color: #ff0000; font-weight: bold; font-size: 3;} -.danger {color: #ff0000;} +.danger {color: #ff0000; font-weight: bold;} +.tinydanger {color: #ff0000; font-size: 85%;} +.smalldanger {color: #ff0000; font-size: 90%;} .warning {color: #ff0000; font-style: italic;} .boldwarning {color: #ff0000; font-style: italic; font-weight: bold} .announce {color: #228b22; font-weight: bold;} @@ -75,6 +77,9 @@ h1.alert, h2.alert {color: #000000;} .rose {color: #ff5050;} .info {color: #0000CC;} .notice {color: #000099;} +.tinynotice {color: #000099; font-size: 85%;} +.smallnotice {color: #000099; font-size: 90%;} +.smallnoticeital {color: #000099; font-style: italic; font-size: 90%;} .boldnotice {color: #000099; font-weight: bold;} .adminnotice {color: #0000ff;} .adminhelp {color: #ff0000; font-weight: bold;} diff --git a/libbyond-extools.so b/libbyond-extools.so new file mode 100644 index 0000000000..8e17f952f2 Binary files /dev/null and b/libbyond-extools.so differ diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 57cbdb6beb..0e971d4ced 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -41,20 +41,6 @@ /datum/status_effect/chem/breast_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. 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) - H.dropItemToGround(H.w_uniform, TRUE) - message = TRUE - if(H.wear_suit) - H.dropItemToGround(H.wear_suit, TRUE) - message = TRUE - if(message) - playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) - H.visible_message("[H]'s chest suddenly bursts forth, ripping their clothes off!'", \ - "Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!") - else - to_chat(H, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.") return ..() /datum/status_effect/chem/breast_enlarger/tick()//If you try to wear clothes, you fail. Slows you down if you're comically huge @@ -64,20 +50,9 @@ H.remove_status_effect(src) return moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click. - var/message = FALSE - if(H.w_uniform) - H.dropItemToGround(H.w_uniform, TRUE) - message = TRUE - if(H.wear_suit) - H.dropItemToGround(H.wear_suit, TRUE) - message = TRUE - if(message) - playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) - to_chat(H, "Your enormous breasts are way too large to fit anything over them!") if(last_checked_size != B.cached_size) H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/status_effect/breast_hypertrophy, multiplicative_slowdown = moveCalc) - sizeMoveMod(moveCalc) if (B.size == "huge") if(prob(1)) @@ -94,16 +69,8 @@ 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) return ..() -/datum/status_effect/chem/breast_enlarger/proc/sizeMoveMod(var/value) - if(cachedmoveCalc == value) - return - owner.next_move_modifier /= cachedmoveCalc - owner.next_move_modifier *= value - cachedmoveCalc = value - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /datum/status_effect/chem/penis_enlarger @@ -115,20 +82,6 @@ /datum/status_effect/chem/penis_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. 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) - H.dropItemToGround(H.w_uniform, TRUE) - message = TRUE - if(H.wear_suit) - H.dropItemToGround(H.wear_suit, TRUE) - message = TRUE - if(message) - playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) - H.visible_message("[H]'s schlong suddenly bursts forth, ripping their clothes off!'", \ - "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!") - else - to_chat(H, "Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.") return ..() @@ -140,18 +93,6 @@ return moveCalc = 1+((round(P.length) - 21)/3) //effects how fast you can move bloodCalc = 1+((round(P.length) - 21)/15) //effects how much blood you need (I didn' bother adding an arousal check because I'm spending too much time on this organ already.) - - var/message = FALSE - if(H.w_uniform) - H.dropItemToGround(H.w_uniform, TRUE) - message = TRUE - if(H.wear_suit) - H.dropItemToGround(H.wear_suit, TRUE) - message = TRUE - if(message) - playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) - to_chat(H, "Your enormous package is way to large to fit anything over!") - if(P.length < 22 && H.has_movespeed_modifier(/datum/movespeed_modifier/status_effect/penis_hypertrophy)) to_chat(owner, "Your rascally willy has become a more managable size, liberating your movements.") H.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/penis_hypertrophy) @@ -280,7 +221,7 @@ var/mob/living/carbon/M = owner //chem calculations - if(!owner.reagents.has_reagent(/datum/chemical_reaction/fermi/enthrall)) + if(!owner.reagents.has_reagent(/datum/reagent/fermi/enthrall)) if (phase < 3 && phase != 0) deltaResist += 3//If you've no chem, then you break out quickly if(prob(5)) @@ -642,16 +583,6 @@ C.Stun(60) to_chat(owner, "Your muscles seize up, then start spasming wildy!") - //wah intensifies wah-rks - else if (lowertext(customTriggers[trigger]) == "cum")//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - if (lewd) - if(ishuman(C)) - var/mob/living/carbon/human/H = C - H.mob_climax(forced_climax=TRUE) - C.SetStun(10)//We got your stun effects in somewhere, Kev. - else - C.throw_at(get_step_towards(hearing_args[HEARING_SPEAKER],C), 3, 1) //cut this if it's too hard to get working - //kneel (knockdown) else if (lowertext(customTriggers[trigger]) == "kneel")//as close to kneeling as you can get, I suppose. to_chat(owner, "You drop to the ground unsurreptitiously.") @@ -733,15 +664,6 @@ deltaResist *= 1.25 if (owner.reagents.has_reagent(/datum/reagent/medicine/neurine)) deltaResist *= 1.5 - if (!(owner.client?.prefs.cit_toggles & NO_APHRO) && lewd) - if (owner.reagents.has_reagent(/datum/reagent/drug/anaphrodisiac)) - deltaResist *= 1.5 - if (owner.reagents.has_reagent(/datum/reagent/drug/anaphrodisiacplus)) - deltaResist *= 2 - if (owner.reagents.has_reagent(/datum/reagent/drug/aphrodisiac)) - deltaResist *= 0.75 - if (owner.reagents.has_reagent(/datum/reagent/drug/aphrodisiacplus)) - deltaResist *= 0.5 //Antag resistance //cultists are already brainwashed by their god if(iscultist(owner)) diff --git a/modular_citadel/code/game/objects/cit_screenshake.dm b/modular_citadel/code/game/objects/cit_screenshake.dm index 188b8a48f9..222de37f82 100644 --- a/modular_citadel/code/game/objects/cit_screenshake.dm +++ b/modular_citadel/code/game/objects/cit_screenshake.dm @@ -45,18 +45,6 @@ . = ..() shake_camera(user, (pressureSetting * 0.75 + 1), (pressureSetting * 0.75)) -/obj/item/attack(mob/living/M, mob/living/user) - . = ..() - if(force >= 15) - shake_camera(user, ((force - 10) * 0.01 + 1), ((force - 10) * 0.01)) - if(M.client) - switch (M.client.prefs.damagescreenshake) - if (1) - shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015)) - if (2) - if(!CHECK_MOBILITY(M, MOBILITY_MOVE)) - shake_camera(M, ((force - 10) * 0.015 + 1), ((force - 10) * 0.015)) - /obj/item/attack_obj(obj/O, mob/living/user) . = ..() if(force >= 20) diff --git a/modular_citadel/code/modules/client/loadout/__donator.dm b/modular_citadel/code/modules/client/loadout/__donator.dm index 8ecc6151a1..06783df03d 100644 --- a/modular_citadel/code/modules/client/loadout/__donator.dm +++ b/modular_citadel/code/modules/client/loadout/__donator.dm @@ -1,496 +1,518 @@ //This is the file that handles donator loadout items. -/datum/gear/pingcoderfailsafe +/datum/gear/donator name = "IF YOU SEE THIS, PING A CODER RIGHT NOW!" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/bikehorn/golden + category = LOADOUT_CATEGORY_DONATOR ckeywhitelist = list("This entry should never appear with this variable set.") //If it does, then that means somebody fucked up the whitelist system pretty hard -/datum/gear/donortestingbikehorn +/datum/gear/donator/pet + name = "Pet Beacon" + slot = SLOT_IN_BACKPACK + path = /obj/item/choice_beacon/pet + ckeywhitelist = list() + donator_group_id = DONATOR_GROUP_TIER_1 // can be accessed by all donators + +/datum/gear/donator/carpet + name = "Carpet Beacon" + slot = SLOT_IN_BACKPACK + path = /obj/item/choice_beacon/box/carpet + ckeywhitelist = list() + donator_group_id = DONATOR_GROUP_TIER_1 + +/datum/gear/donator/chameleon_bedsheet + name = "Chameleon Bedsheet" + slot = SLOT_NECK + path = /obj/item/bedsheet/chameleon + ckeywhitelist = list() + donator_group_id = DONATOR_GROUP_TIER_1 + +/datum/gear/donator/donortestingbikehorn name = "Donor item testing bikehorn" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/bikehorn geargroupID = list("DONORTEST") //This is a list mainly for the sake of testing, but geargroupID works just fine with ordinary strings -/datum/gear/kevhorn +/datum/gear/donator/kevhorn name = "Airhorn" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/bikehorn/airhorn ckeywhitelist = list("kevinz000") -/datum/gear/cebusoap +/datum/gear/donator/cebusoap name = "Cebutris' soap" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/custom/ceb_soap ckeywhitelist = list("cebutris") -/datum/gear/kiaracloak +/datum/gear/donator/kiaracloak name = "Kiara's cloak" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/cloak/inferno ckeywhitelist = list("inferno707") -/datum/gear/kiaracollar +/datum/gear/donator/kiaracollar name = "Kiara's collar" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/petcollar/inferno ckeywhitelist = list("inferno707") -/datum/gear/kiaramedal +/datum/gear/donator/kiaramedal name = "Insignia of Steele" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/clothing/accessory/medal/steele ckeywhitelist = list("inferno707") -/datum/gear/hheart +/datum/gear/donator/hheart name = "The Hollow Heart" - category = SLOT_WEAR_MASK + slot = SLOT_WEAR_MASK path = /obj/item/clothing/mask/hheart ckeywhitelist = list("inferno707") -/datum/gear/engravedzippo +/datum/gear/donator/engravedzippo name = "Engraved zippo" - category = SLOT_HANDS + slot = SLOT_HANDS path = /obj/item/lighter/gold ckeywhitelist = list("dirtyoldharry") -/datum/gear/geisha +/datum/gear/donator/geisha name = "Geisha suit" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/geisha ckeywhitelist = list("atiefling") -/datum/gear/specialscarf +/datum/gear/donator/specialscarf name = "Special scarf" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/scarf/zomb ckeywhitelist = list("zombierobin") -/datum/gear/redmadcoat +/datum/gear/donator/redmadcoat name = "The Mad's labcoat" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/toggle/labcoat/mad/red ckeywhitelist = list("zombierobin") -/datum/gear/santahat +/datum/gear/donator/santahat name = "Santa hat" - category = SLOT_HEAD + slot = SLOT_HEAD path = /obj/item/clothing/head/santa/fluff ckeywhitelist = list("illotafv") -/datum/gear/reindeerhat +/datum/gear/donator/reindeerhat name = "Reindeer hat" - category = SLOT_HEAD + slot = SLOT_HEAD path = /obj/item/clothing/head/hardhat/reindeer/fluff ckeywhitelist = list("illotafv") -/datum/gear/treeplushie +/datum/gear/donator/treeplushie name = "Christmas tree plushie" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/plush/tree ckeywhitelist = list("illotafv") -/datum/gear/santaoutfit +/datum/gear/donator/santaoutfit name = "Santa costume" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/space/santa/fluff ckeywhitelist = list("illotafv") -/datum/gear/treecloak +/datum/gear/donator/treecloak name = "Christmas tree cloak" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/cloak/festive ckeywhitelist = list("illotafv") -/datum/gear/carrotplush +/datum/gear/donator/carrotplush name = "Carrot plushie" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/plush/carrot ckeywhitelist = list("improvedname") -/datum/gear/carrotcloak +/datum/gear/donator/carrotcloak name = "Carrot cloak" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/cloak/carrot ckeywhitelist = list("improvedname") -/datum/gear/albortorosamask +/datum/gear/donator/albortorosamask name = "Alborto Rosa mask" - category = SLOT_WEAR_MASK + slot = SLOT_WEAR_MASK path = /obj/item/clothing/mask/luchador/zigfie ckeywhitelist = list("zigfie") -/datum/gear/mankini +/datum/gear/donator/mankini name = "Mankini" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/stripper/mankini ckeywhitelist = list("zigfie") -/datum/gear/pinkshoes +/datum/gear/donator/pinkshoes name = "Pink shoes" - category = SLOT_SHOES + slot = SLOT_SHOES path = /obj/item/clothing/shoes/sneakers/pink ckeywhitelist = list("zigfie") -/datum/gear/reecesgreatcoat +/datum/gear/donator/reecesgreatcoat name = "Reece's Great Coat" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/trenchcoat/green ckeywhitelist = list("geemiesif") -/datum/gear/russianflask +/datum/gear/donator/russianflask name = "Russian flask" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/reagent_containers/food/drinks/flask/russian cost = 2 ckeywhitelist = list("slomka") -/datum/gear/stalkermask +/datum/gear/donator/stalkermask name = "S.T.A.L.K.E.R. mask" - category = SLOT_WEAR_MASK + slot = SLOT_WEAR_MASK path = /obj/item/clothing/mask/gas/stalker ckeywhitelist = list("slomka") -/datum/gear/stripedcollar +/datum/gear/donator/stripedcollar name = "Striped collar" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/petcollar/stripe ckeywhitelist = list("jademanique") -/datum/gear/performersoutfit +/datum/gear/donator/performersoutfit name = "Bluish performer's outfit" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/singer/yellow/custom ckeywhitelist = list("killer402402") -/datum/gear/vermillion +/datum/gear/donator/vermillion name = "Vermillion clothing" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/suit/vermillion ckeywhitelist = list("fractious") -/datum/gear/AM4B +/datum/gear/donator/AM4B name = "Foam Force AM4-B" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/gun/ballistic/automatic/AM4B ckeywhitelist = list("zeronetalpha") -/datum/gear/carrotsatchel +/datum/gear/donator/carrotsatchel name = "Carrot Satchel" - category = SLOT_HANDS + slot = SLOT_HANDS path = /obj/item/storage/backpack/satchel/carrot ckeywhitelist = list("improvedname") -/datum/gear/naomisweater +/datum/gear/donator/naomisweater name = "worn black sweater" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater/black/naomi ckeywhitelist = list("technicalmagi") -/datum/gear/naomicollar +/datum/gear/donator/naomicollar name = "worn pet collar" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/petcollar/naomi ckeywhitelist = list("technicalmagi") -/datum/gear/gladiator +/datum/gear/donator/gladiator name = "Gladiator Armor" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/under/costume/gladiator ckeywhitelist = list("aroche") -/datum/gear/bloodredtie +/datum/gear/donator/bloodredtie name = "Blood Red Tie" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/tie/bloodred ckeywhitelist = list("kyutness") -/datum/gear/puffydress +/datum/gear/donator/puffydress name = "Puffy Dress" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/puffydress ckeywhitelist = list("stallingratt") -/datum/gear/labredblack +/datum/gear/donator/labredblack name = "Black and Red Coat" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/toggle/labcoat/labredblack ckeywhitelist = list("blakeryan", "durandalphor") -/datum/gear/torisword +/datum/gear/donator/torisword name = "Rainbow Zweihander" - category = SLOT_IN_BACKPACK - path = /obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow + slot = SLOT_IN_BACKPACK + path = /obj/item/dualsaber/hypereutactic/toy/rainbow ckeywhitelist = list("annoymous35") -/datum/gear/darksabre +/datum/gear/donator/darksabre name = "Dark Sabre" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/darksabre ckeywhitelist = list("inferno707") -datum/gear/darksabresheath +/datum/gear/donator/darksabresheath name = "Dark Sabre Sheath" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/storage/belt/sabre/darksabre ckeywhitelist = list("inferno707") -/datum/gear/toriball +/datum/gear/donator/toriball name = "Rainbow Tennis Ball" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/rainbow ckeywhitelist = list("annoymous35") -/datum/gear/izzyball +/datum/gear/donator/izzyball name = "Katlin's Ball" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/rainbow/izzy ckeywhitelist = list("izzyinbox") -/datum/gear/cloak +/datum/gear/donator/cloak name = "Green Cloak" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/cloak/green ckeywhitelist = list("killer402402") -/datum/gear/steelflask +/datum/gear/donator/steelflask name = "Steel Flask" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/reagent_containers/food/drinks/flask/steel cost = 2 ckeywhitelist = list("nik707") -/datum/gear/paperhat +/datum/gear/donator/paperhat name = "Paper Hat" - category = SLOT_HEAD + slot = SLOT_HEAD path = /obj/item/clothing/head/paperhat ckeywhitelist = list("kered2") -/datum/gear/cloakce +/datum/gear/donator/cloakce name = "Polychromic CE Cloak" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/clothing/neck/cloak/polychromic/polyce ckeywhitelist = list("worksbythesea", "blakeryan") -/datum/gear/ssk +/datum/gear/donator/ssk name = "Stun Sword Kit" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/ssword_kit ckeywhitelist = list("phillip458") -/datum/gear/techcoat +/datum/gear/donator/techcoat name = "Techomancers Labcoat" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/clothing/suit/toggle/labcoat/mad/techcoat ckeywhitelist = list("wilchen") -/datum/gear/leechjar +/datum/gear/donator/leechjar name = "Jar of Leeches" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/custom/leechjar ckeywhitelist = list("sgtryder") -/datum/gear/darkarmor +/datum/gear/donator/darkarmor name = "Dark Armor" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/clothing/suit/armor/vest/darkcarapace ckeywhitelist = list("inferno707") -/datum/gear/devilwings +/datum/gear/donator/devilwings name = "Strange Wings" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/devilwings ckeywhitelist = list("kitsun") -/datum/gear/flagcape +/datum/gear/donator/flagcape name = "US Flag Cape" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/clothing/neck/flagcape ckeywhitelist = list("darnchacha") -/datum/gear/luckyjack +/datum/gear/donator/luckyjack name = "Lucky Jackboots" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/clothing/shoes/lucky ckeywhitelist = list("donaldtrumpthecommunist") -/datum/gear/raiqbawks +/datum/gear/donator/raiqbawks name = "Miami Boombox" - category = SLOT_HANDS + slot = SLOT_HANDS cost = 2 path = /obj/item/boombox/raiq ckeywhitelist = list("chefferz") -/datum/gear/m41 +/datum/gear/donator/m41 name = "Toy M41" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/gun/m41 ckeywhitelist = list("thalverscholen") -/datum/gear/Divine_robes +/datum/gear/donator/Divine_robes name = "Divine robes" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/custom/lunasune ckeywhitelist = list("invader4352") -/datum/gear/gothcoat +/datum/gear/donator/gothcoat name = "Goth Coat" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/gothcoat ckeywhitelist = list("norko") -/datum/gear/corgisuit +/datum/gear/donator/corgisuit name = "Corgi Suit" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/ian_costume ckeywhitelist = list("cathodetherobot") -/datum/gear/sharkcloth +/datum/gear/donator/sharkcloth name = "Leon's Skimpy Outfit" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/under/custom/leoskimpy ckeywhitelist = list("spectrosis") -/datum/gear/mimemask +/datum/gear/donator/mimemask name = "Mime Mask" - category = SLOT_WEAR_MASK + slot = SLOT_WEAR_MASK path = /obj/item/clothing/mask/gas/mime ckeywhitelist = list("pireamaineach") -/datum/gear/mimeoveralls +/datum/gear/donator/mimeoveralls name = "Mime's Overalls" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/under/custom/mimeoveralls ckeywhitelist = list("pireamaineach") -/datum/gear/soulneck +/datum/gear/donator/soulneck name = "Soul Necklace" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/undertale ckeywhitelist = list("twilightic") -/datum/gear/frenchberet +/datum/gear/donator/frenchberet name = "French Beret" - category = SLOT_HEAD + slot = SLOT_HEAD path = /obj/item/clothing/head/frenchberet ckeywhitelist = list("notazoltan") -/datum/gear/zuliecloak +/datum/gear/donator/zuliecloak name = "Project: Zul-E" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/cloak/zuliecloak ckeywhitelist = list("asky") -/datum/gear/blackredgold +/datum/gear/donator/blackredgold name = "Black, Red, and Gold Coat" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/blackredgold ckeywhitelist = list("ttbnc") -/datum/gear/fritzplush +/datum/gear/donator/fritzplush name = "Fritz Plushie" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/plush/mammal/dog/fritz ckeywhitelist = list("analwerewolf") -/datum/gear/kimono +/datum/gear/donator/kimono name = "Kimono" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/kimono ckeywhitelist = list("sfox63") -/datum/gear/commjacket +/datum/gear/donator/commjacket name = "Dusty Commisar's Cloak" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/commjacket ckeywhitelist = list("sadisticbatter") -/datum/gear/mw2_russian_para +/datum/gear/donator/mw2_russian_para name = "Russian Paratrooper Jumper" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/custom/mw2_russian_para ckeywhitelist = list("investigator77") -/datum/gear/longblackgloves +/datum/gear/donator/longblackgloves name = "Luna's Gauntlets" - category = SLOT_GLOVES + slot = SLOT_GLOVES path = /obj/item/clothing/gloves/longblackgloves ckeywhitelist = list("bigmanclancy") -/datum/gear/trendy_fit +/datum/gear/donator/trendy_fit name = "Trendy Fit" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/custom/trendy_fit ckeywhitelist = list("midgetdragon") -/datum/gear/singery +/datum/gear/donator/singery name = "Yellow Performer Outfit" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/singer/yellow ckeywhitelist = list("maxlynchy") -/datum/gear/csheet +/datum/gear/donator/csheet name = "NT Bedsheet" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/bedsheet/captain ckeywhitelist = list("tikibomb") -/datum/gear/borgplush +/datum/gear/donator/borgplush name = "Robot Plush" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/toy/plush/borgplushie ckeywhitelist = list("nicholaiavenicci") -/datum/gear/donorberet +/datum/gear/donator/donorberet name = "Atmos Beret" - category = SLOT_HEAD + slot = SLOT_HEAD path = /obj/item/clothing/head/blueberet ckeywhitelist = list("foxystalin") -/datum/gear/donorgoggles +/datum/gear/donator/donorgoggles name = "Flight Goggles" - category = SLOT_HEAD + slot = SLOT_HEAD path = /obj/item/clothing/head/flight ckeywhitelist = list("maxlynchy") -/datum/gear/onionneck +/datum/gear/donator/onionneck name = "Onion Necklace" - category = SLOT_NECK + slot = SLOT_NECK path = /obj/item/clothing/neck/necklace/onion ckeywhitelist = list("cdrcross") -/datum/gear/mikubikini +/datum/gear/donator/mikubikini name = "starlight singer bikini" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/under/custom/mikubikini ckeywhitelist = list("grandvegeta") -/datum/gear/mikujacket +/datum/gear/donator/mikujacket name = "starlight singer jacket" - category = SLOT_WEAR_SUIT + slot = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/mikujacket ckeywhitelist = list("grandvegeta") -/datum/gear/mikuhair +/datum/gear/donator/mikuhair name = "starlight singer hair" - category = SLOT_W_UNIFORM + slot = SLOT_W_UNIFORM path = /obj/item/clothing/head/mikuhair ckeywhitelist = list("grandvegeta") -/datum/gear/mikugloves +/datum/gear/donator/mikugloves name = "starlight singer gloves" - category = SLOT_GLOVES + slot = SLOT_GLOVES path = /obj/item/clothing/gloves/mikugloves ckeywhitelist = list("grandvegeta") -/datum/gear/mikuleggings +/datum/gear/donator/mikuleggings name = "starlight singer leggings" - category = SLOT_SHOES + slot = SLOT_SHOES path = /obj/item/clothing/shoes/sneakers/mikuleggings ckeywhitelist = list("grandvegeta") -/datum/gear/cosmos +/datum/gear/donator/cosmos name = "cosmic space bedsheet" - category = SLOT_IN_BACKPACK + slot = SLOT_IN_BACKPACK path = /obj/item/bedsheet/cosmos ckeywhitelist = list("grunnyyy") diff --git a/modular_citadel/code/modules/client/loadout/_loadout.dm b/modular_citadel/code/modules/client/loadout/_loadout.dm index 51256f8cde..0ebfa060f2 100644 --- a/modular_citadel/code/modules/client/loadout/_loadout.dm +++ b/modular_citadel/code/modules/client/loadout/_loadout.dm @@ -27,8 +27,13 @@ GLOBAL_LIST_EMPTY(loadout_whitelist_ids) /proc/initialize_global_loadout_items() load_loadout_config() for(var/item in subtypesof(/datum/gear)) - var/datum/gear/I = new item - LAZYSET(GLOB.loadout_items[slot_to_string(I.category)], I.name, I) + var/datum/gear/I = item + if(!initial(I.name)) + continue + I = new item + LAZYINITLIST(GLOB.loadout_items[I.category]) + LAZYINITLIST(GLOB.loadout_items[I.category][I.subcategory]) + GLOB.loadout_items[I.category][I.subcategory][I.name] = I if(islist(I.geargroupID)) var/list/ggidlist = I.geargroupID I.ckeywhitelist = list() @@ -41,7 +46,9 @@ GLOBAL_LIST_EMPTY(loadout_whitelist_ids) /datum/gear var/name - var/category + var/category = LOADOUT_CATEGORY_NONE + var/subcategory = LOADOUT_SUBCATEGORY_NONE + var/slot var/description var/path //item-to-spawn path var/cost = 1 //normally, each loadout costs a single point. diff --git a/modular_citadel/code/modules/client/loadout/_medical.dm b/modular_citadel/code/modules/client/loadout/_medical.dm index 604a0f96ae..e371db94fc 100644 --- a/modular_citadel/code/modules/client/loadout/_medical.dm +++ b/modular_citadel/code/modules/client/loadout/_medical.dm @@ -1,47 +1,45 @@ -/datum/gear/medicbriefcase +/datum/gear/hands/medicbriefcase name = "Medical Briefcase" - category = SLOT_HANDS path = /obj/item/storage/briefcase/medical restricted_roles = list("Medical Doctor", "Chief Medical Officer") restricted_desc = "MD, CMO" -/datum/gear/stethoscope +/datum/gear/neck/stethoscope name = "Stethoscope" - category = SLOT_NECK path = /obj/item/clothing/neck/stethoscope restricted_roles = list("Medical Doctor", "Chief Medical Officer") -/datum/gear/bluescrubs +/datum/gear/uniform/bluescrubs name = "Blue Scrubs" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/medical/doctor/blue restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") restricted_desc = "Medical" - -/datum/gear/greenscrubs + +/datum/gear/uniform/greenscrubs name = "Green Scrubs" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/medical/doctor/green restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") restricted_desc = "Medical" -/datum/gear/purplescrubs +/datum/gear/uniform/purplescrubs name = "Purple Scrubs" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/medical/doctor/purple restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") restricted_desc = "Medical" -/datum/gear/nursehat +/datum/gear/head/nursehat name = "Nurse Hat" - category = SLOT_HEAD path = /obj/item/clothing/head/nursehat + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") restricted_desc = "Medical" -/datum/gear/nursesuit +/datum/gear/uniform/nursesuit name = "Nurse Suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/rank/medical/doctor/nurse + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Medical Doctor", "Chief Medical Officer", "Geneticist", "Chemist", "Virologist") - restricted_desc = "Medical" \ No newline at end of file + restricted_desc = "Medical" diff --git a/modular_citadel/code/modules/client/loadout/_security.dm b/modular_citadel/code/modules/client/loadout/_security.dm index 72a6aab394..ab316d577b 100644 --- a/modular_citadel/code/modules/client/loadout/_security.dm +++ b/modular_citadel/code/modules/client/loadout/_security.dm @@ -1,71 +1,70 @@ -/datum/gear/navyblueuniformhos +/datum/gear/uniform/navyblueuniformhos name = "Head of Security navyblue uniform" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/security/head_of_security/formal restricted_roles = list("Head of Security") -/datum/gear/navybluehosberet +/datum/gear/head/navybluehosberet name = "Head of security's navyblue beret" - category = SLOT_HEAD path = /obj/item/clothing/head/beret/sec/navyhos + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Head of Security") -/datum/gear/navybluejackethos +/datum/gear/suit/navybluejackethos name = "head of security's navyblue jacket" - category = SLOT_WEAR_SUIT + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS path = /obj/item/clothing/suit/armor/hos/navyblue restricted_roles = list("Head of Security") -/datum/gear/navybluejacketofficer +/datum/gear/suit/navybluejacketofficer name = "security officer's navyblue jacket" - category = SLOT_WEAR_SUIT + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS path = /obj/item/clothing/suit/armor/navyblue restricted_roles = list("Security Officer") -/datum/gear/navyblueofficerberet +/datum/gear/head/navyblueofficerberet name = "Security officer's Navyblue beret" - category = SLOT_HEAD path = /obj/item/clothing/head/beret/sec/navyofficer + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Security Officer") -/datum/gear/navyblueuniformofficer +/datum/gear/uniform/navyblueuniformofficer name = "Security officer navyblue uniform" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/security/officer/formal restricted_roles = list("Security Officer") -/datum/gear/navybluejacketwarden +/datum/gear/suit/navybluejacketwarden name = "warden navyblue jacket" - category = SLOT_WEAR_SUIT + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS path = /obj/item/clothing/suit/armor/vest/warden/navyblue restricted_roles = list("Warden") -/datum/gear/navybluewardenberet +/datum/gear/head/navybluewardenberet name = "Warden's navyblue beret" - category = SLOT_HEAD path = /obj/item/clothing/head/beret/sec/navywarden + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Warden") -/datum/gear/navyblueuniformwarden +/datum/gear/uniform/navyblueuniformwarden name = "Warden navyblue uniform" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/security/warden/formal restricted_roles = list("Warden") -/datum/gear/secskirt +/datum/gear/uniform/secskirt name = "Security skirt" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/security/officer/skirt restricted_roles = list("Security Officer", "Warden", "Head of Security") -/datum/gear/hosskirt +/datum/gear/uniform/hosskirt name = "Head of security's skirt" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/rank/security/head_of_security/skirt restricted_roles = list("Head of Security") -/datum/gear/sechud +/datum/gear/glasses/sechud name = "Security Hud" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/hud/security - restricted_roles = list("Security Officer", "Warden", "Head of Security") \ No newline at end of file + restricted_roles = list("Security Officer", "Warden", "Head of Security") diff --git a/modular_citadel/code/modules/client/loadout/_service.dm b/modular_citadel/code/modules/client/loadout/_service.dm index ab3daa5f3c..848ad6233c 100644 --- a/modular_citadel/code/modules/client/loadout/_service.dm +++ b/modular_citadel/code/modules/client/loadout/_service.dm @@ -1,33 +1,33 @@ -/datum/gear/greytidestationwide +/datum/gear/uniform/greytidestationwide name = "Staff Assistant's jumpsuit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/staffassistant + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Assistant") -/datum/gear/neetsuit +/datum/gear/suit/neetsuit name = "D.A.B. suit" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/assu_suit + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Assistant") cost = 2 -/datum/gear/neethelm +/datum/gear/head/neethelm name = "D.A.B. helmet" - category = SLOT_HEAD path = /obj/item/clothing/head/assu_helmet + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Assistant") cost = 2 -/datum/gear/plushvar +/datum/gear/backpack/plushvar name = "Ratvar Plushie" - category = SLOT_IN_BACKPACK path = /obj/item/toy/plush/plushvar + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS cost = 5 restricted_roles = list("Chaplain") -/datum/gear/narplush +/datum/gear/backpack/narplush name = "Narsie Plushie" - category = SLOT_IN_BACKPACK path = /obj/item/toy/plush/narplush + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS cost = 5 restricted_roles = list("Chaplain") diff --git a/modular_citadel/code/modules/client/loadout/backpack.dm b/modular_citadel/code/modules/client/loadout/backpack.dm index 8d089a129a..0b700b11e2 100644 --- a/modular_citadel/code/modules/client/loadout/backpack.dm +++ b/modular_citadel/code/modules/client/loadout/backpack.dm @@ -1,132 +1,104 @@ -/datum/gear/plushcarp - name = "Space carp plushie" - category = SLOT_IN_BACKPACK - path = /obj/item/toy/plush/carpplushie +/datum/gear/backpack + category = LOADOUT_CATEGORY_BACKPACK + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_GENERAL + slot = SLOT_IN_BACKPACK -/datum/gear/plushliz - name = "Lizard plushie" - category = SLOT_IN_BACKPACK - path = /obj/item/toy/plush/lizardplushie +/datum/gear/backpack/plushbox + name = "Plushie Choice Box" + path = /obj/item/choice_beacon/box/plushie + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS -/datum/gear/plushsnek - name = "Snake plushie" - category = SLOT_IN_BACKPACK - path = /obj/item/toy/plush/snakeplushie - -/datum/gear/plushslime - name = "Slime plushie" - category = SLOT_IN_BACKPACK - path = /obj/item/toy/plush/slimeplushie - -/datum/gear/plushlamp - name = "Lamp plushie" - category = SLOT_IN_BACKPACK - path = /obj/item/toy/plush/lampplushie - -/datum/gear/tennis +/datum/gear/backpack/tennis name = "Classic Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS -/datum/gear/tennisred +/datum/gear/backpack/tennis/red name = "Red Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/red -/datum/gear/tennisyellow +/datum/gear/backpack/tennis/yellow name = "Yellow Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/yellow -/datum/gear/tennisgreen +/datum/gear/backpack/tennis/green name = "Green Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/green -/datum/gear/tenniscyan +/datum/gear/backpack/tennis/cyan name = "Cyan Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/cyan -/datum/gear/tennisblue +/datum/gear/backpack/tennis/blue name = "Blue Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/blue -/datum/gear/tennispurple +/datum/gear/backpack/tennis/purple name = "Purple Tennis Ball" - category = SLOT_IN_BACKPACK path = /obj/item/toy/tennis/purple -/datum/gear/dildo +/datum/gear/backpack/dildo name = "Customizable dildo" - category = SLOT_IN_BACKPACK path = /obj/item/dildo/custom + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS -/datum/gear/toykatana +/datum/gear/backpack/toykatana name = "Toy Katana" - category = SLOT_IN_BACKPACK path = /obj/item/toy/katana + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS cost = 3 -/datum/gear/tapeplayer +/datum/gear/backpack/tapeplayer name = "Taperecorder" - category = SLOT_IN_BACKPACK path = /obj/item/taperecorder -/datum/gear/tape +/datum/gear/backpack/tape name = "Spare cassette tape" - category = SLOT_IN_BACKPACK path = /obj/item/tape/random -/datum/gear/newspaper +/datum/gear/backpack/newspaper name = "Newspaper" - category = SLOT_IN_BACKPACK path = /obj/item/newspaper -/datum/gear/crayons +/datum/gear/backpack/crayons name = "Box of crayons" - category = SLOT_IN_BACKPACK path = /obj/item/storage/crayons + subcategory = LOADOUT_SUBCATEGORY_BACKPACK_TOYS -/datum/gear/multipen +/datum/gear/backpack/multipen name = "A multicolored pen" - category = SLOT_IN_BACKPACK path = /obj/item/pen/fourcolor -/datum/gear/fountainpen +/datum/gear/backpack/fountainpen name = "A fancy pen" - category = SLOT_IN_BACKPACK path = /obj/item/pen/fountain cost = 2 -/datum/gear/modular_tablet +/datum/gear/backpack/modular_tablet name = "A modular tablet" - category = SLOT_IN_BACKPACK path = /obj/item/modular_computer/tablet/preset/cheap/ cost = 4 -/datum/gear/modular_laptop +/datum/gear/backpack/modular_laptop name = "A modular laptop" - category = SLOT_IN_BACKPACK path = /obj/item/modular_computer/laptop/preset/civilian cost = 7 -/datum/gear/ringbox_gold +/datum/gear/backpack/ringbox_gold name = "A gold ring box" - category = SLOT_IN_BACKPACK path = /obj/item/storage/fancy/ringbox cost = 3 -/datum/gear/ringbox_silver +/datum/gear/backpack/ringbox_silver name = "A silver ring box" - category = SLOT_IN_BACKPACK path = /obj/item/storage/fancy/ringbox/silver cost = 3 -/datum/gear/ringbox_diamond +/datum/gear/backpack/ringbox_diamond name = "A diamond ring box" - category = SLOT_IN_BACKPACK path = /obj/item/storage/fancy/ringbox/diamond cost = 5 +/datum/gear/backpack/necklace//this is here because loadout doesn't support proper accessories + name = "A renameable necklace" + path = /obj/item/clothing/accessory/necklace diff --git a/modular_citadel/code/modules/client/loadout/glasses.dm b/modular_citadel/code/modules/client/loadout/glasses.dm index 57270d8e57..b0eecbbf28 100644 --- a/modular_citadel/code/modules/client/loadout/glasses.dm +++ b/modular_citadel/code/modules/client/loadout/glasses.dm @@ -1,49 +1,43 @@ -/datum/gear/blindfold +/datum/gear/glasses + category = LOADOUT_CATEGORY_GLASSES + slot = SLOT_GLASSES + +/datum/gear/glasses/blindfold name = "Blindfold" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/sunglasses/blindfold -/datum/gear/cold +/datum/gear/glasses/cold name = "Cold goggles" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/cold -/datum/gear/eyepatch +/datum/gear/glasses/eyepatch name = "Eyepatch" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/eyepatch -/datum/gear/heat +/datum/gear/glasses/heat name = "Heat goggles" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/heat -/datum/gear/hipster +/datum/gear/glasses/hipster name = "Hipster glasses" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/regular/hipster -/datum/gear/jamjar +/datum/gear/glasses/jamjar name = "Jamjar glasses" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/regular/jamjar -/datum/gear/monocle +/datum/gear/glasses/monocle name = "Monocle" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/monocle -/datum/gear/orange +/datum/gear/glasses/orange name = "Orange glasses" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/orange -/datum/gear/red +/datum/gear/glasses/red name = "Red Glasses" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/red -/datum/gear/prescription +/datum/gear/glasses/prescription name = "Prescription glasses" - category = SLOT_GLASSES path = /obj/item/clothing/glasses/regular diff --git a/modular_citadel/code/modules/client/loadout/gloves.dm b/modular_citadel/code/modules/client/loadout/gloves.dm index 72e6e91cfc..09694ddec7 100644 --- a/modular_citadel/code/modules/client/loadout/gloves.dm +++ b/modular_citadel/code/modules/client/loadout/gloves.dm @@ -1,23 +1,34 @@ -/datum/gear/fingerless +/datum/gear/gloves + category = LOADOUT_CATEGORY_GLOVES + slot = SLOT_GLOVES + +/datum/gear/gloves/fingerless name = "Fingerless Gloves" - category = SLOT_GLOVES path = /obj/item/clothing/gloves/fingerless -/datum/gear/goldring +/datum/gear/gloves/evening + name = "Evening gloves" + path = /obj/item/clothing/gloves/evening + +/datum/gear/gloves/midnight + name = "Midnight gloves" + path = /obj/item/clothing/gloves/evening/black + +/datum/gear/gloves/goldring name = "A gold ring" - category = SLOT_GLOVES path = /obj/item/clothing/gloves/ring cost = 2 -/datum/gear/silverring +/datum/gear/gloves/silverring name = "A silver ring" - category = SLOT_GLOVES path = /obj/item/clothing/gloves/ring/silver cost = 2 -/datum/gear/diamondring +/datum/gear/gloves/diamondring name = "A diamond ring" - category = SLOT_GLOVES path = /obj/item/clothing/gloves/ring/diamond cost = 4 - + +/datum/gear/gloves/customring + name = "A ring, renameable" + path = /obj/item/clothing/gloves/ring/custom diff --git a/modular_citadel/code/modules/client/loadout/hands.dm b/modular_citadel/code/modules/client/loadout/hands.dm index 3b07ecaec5..db57fb466b 100644 --- a/modular_citadel/code/modules/client/loadout/hands.dm +++ b/modular_citadel/code/modules/client/loadout/hands.dm @@ -1,67 +1,54 @@ -/datum/gear/cane +/datum/gear/hands + category = LOADOUT_CATEGORY_HANDS + slot = SLOT_HANDS + +/datum/gear/hands/cane name = "Cane" - category = SLOT_HANDS path = /obj/item/cane -/datum/gear/cigarettes +/datum/gear/hands/cigarettes name = "Cigarette pack" - category = SLOT_HANDS path = /obj/item/storage/fancy/cigarettes -/datum/gear/dice +/datum/gear/hands/dice name = "Dice bag" - category = SLOT_HANDS - path = /obj/item/storage/pill_bottle/dice + path = /obj/item/storage/box/dice -/datum/gear/eightball +/datum/gear/hands/eightball name = "Magic eightball" - category = SLOT_HANDS path = /obj/item/toy/eightball -/datum/gear/matches +/datum/gear/hands/matches name = "Matchbox" - category = SLOT_HANDS path = /obj/item/storage/box/matches -/datum/gear/cheaplighter +/datum/gear/hands/cheaplighter name = "Cheap lighter" - category = SLOT_HANDS path = /obj/item/lighter/greyscale -/datum/gear/cards +/datum/gear/hands/cards name = "Playing cards" - category = SLOT_HANDS path = /obj/item/toy/cards/deck -/datum/gear/skub +/datum/gear/hands/skub name = "Skub" - category = SLOT_HANDS path = /obj/item/skub -/datum/gear/carpplushie - name = "Space carp plushie" - category = SLOT_HANDS - path = /obj/item/toy/plush/carpplushie - -/datum/gear/wallet +/datum/gear/hands/wallet name = "Wallet" - category = SLOT_HANDS path = /obj/item/storage/wallet -/datum/gear/flask +/datum/gear/hands/flask name = "Flask" - category = SLOT_HANDS path = /obj/item/reagent_containers/food/drinks/flask cost = 2 -/datum/gear/zippolighter +/datum/gear/hands/zippolighter name = "Zippo Lighter" - category = SLOT_HANDS path = /obj/item/lighter cost = 2 -/datum/gear/cigar +/datum/gear/hands/cigar name = "Cigar" - category = SLOT_HANDS path = /obj/item/clothing/mask/cigarette/cigar cost = 4 //smoking is bad mkay diff --git a/modular_citadel/code/modules/client/loadout/head.dm b/modular_citadel/code/modules/client/loadout/head.dm index 28c6e8e8a6..fd03e2279f 100644 --- a/modular_citadel/code/modules/client/loadout/head.dm +++ b/modular_citadel/code/modules/client/loadout/head.dm @@ -1,103 +1,138 @@ -/datum/gear/baseball +/datum/gear/head + category = LOADOUT_CATEGORY_HEAD + subcategory = LOADOUT_SUBCATEGORY_HEAD_GENERAL + slot = SLOT_HEAD + +/datum/gear/head/baseball name = "Ballcap" - category = SLOT_HEAD path = /obj/item/clothing/head/soft/mime -/datum/gear/beanie +/datum/gear/head/beanie name = "Beanie" - category = SLOT_HEAD path = /obj/item/clothing/head/beanie -/datum/gear/beret +/datum/gear/head/beret name = "Black beret" - category = SLOT_HEAD path = /obj/item/clothing/head/beret/black -/datum/gear/flatcap +/datum/gear/head/flatcap name = "Flat cap" - category = SLOT_HEAD path = /obj/item/clothing/head/flatcap -/datum/gear/pirate +/datum/gear/head/pirate name = "Pirate hat" - category = SLOT_HEAD path = /obj/item/clothing/head/pirate -/datum/gear/rice_hat +/datum/gear/head/rice_hat name = "Rice hat" - category = SLOT_HEAD path = /obj/item/clothing/head/rice_hat -/datum/gear/ushanka - name = "Ushanka" - category = SLOT_HEAD +/datum/gear/head/ushanka path = /obj/item/clothing/head/ushanka -/datum/gear/slime +/datum/gear/head/slime name = "Slime hat" - category = SLOT_HEAD path = /obj/item/clothing/head/collectable/slime -/datum/gear/fedora +/datum/gear/head/fedora name = "Fedora" - category = SLOT_HEAD path = /obj/item/clothing/head/fedora -/datum/gear/that +/datum/gear/head/that name = "Top Hat" - category = SLOT_HEAD path = /obj/item/clothing/head/that -/datum/gear/flakhelm +/datum/gear/head/maidband + name = "Maid headband" + path= /obj/item/clothing/head/maid + +/datum/gear/head/flakhelm name = "Flak Helmet" - category = SLOT_HEAD path = /obj/item/clothing/head/flakhelm cost = 2 -/datum/gear/bunnyears +/datum/gear/head/bunnyears name = "Bunny Ears" - category = SLOT_HEAD path = /obj/item/clothing/head/rabbitears -/datum/gear/mailmanhat +/datum/gear/head/mailmanhat name = "Mailman's Hat" - category = SLOT_HEAD path = /obj/item/clothing/head/mailman //trek fancy Hats! -/datum/gear/trekcap +/datum/gear/head/trekcap name = "Federation Officer's Cap (White)" - category = SLOT_HEAD path = /obj/item/clothing/head/caphat/formal/fedcover + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Captain","Head of Personnel") -/datum/gear/trekcapcap +/datum/gear/head/trekcapcap name = "Federation Officer's Cap (Black)" - category = SLOT_HEAD path = /obj/item/clothing/head/caphat/formal/fedcover/black + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_roles = list("Captain","Head of Personnel") -/datum/gear/trekcapmedisci +/datum/gear/head/trekcapmedisci name = "Federation Officer's Cap (Blue)" - category = SLOT_HEAD path = /obj/item/clothing/head/caphat/formal/fedcover/medsci + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekcapeng +/datum/gear/head/trekcapeng name = "Federation Officer's Cap (Yellow)" - category = SLOT_HEAD path = /obj/item/clothing/head/caphat/formal/fedcover/eng + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") -/datum/gear/trekcapsec +/datum/gear/head/trekcapsec name = "Federation Officer's Cap (Red)" - category = SLOT_HEAD path = /obj/item/clothing/head/caphat/formal/fedcover/sec + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") +// orvilike "original" kepi +/datum/gear/head/orvkepicom + name = "Federation Kepi, command" + description = "A visored cap. Intended to be used with ORV uniform." + path = /obj/item/clothing/head/kepi/orvi/command + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS + restricted_desc = "Heads of Staff" + restricted_roles = list("Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer", "Quartermaster") + +/datum/gear/head/orvkepiops + name = "Federation Kepi, ops/sec" + description = "A visored cap. Intended to be used with ORV uniform." + path = /obj/item/clothing/head/kepi/orvi/engsec + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS + restricted_desc = "Engineering, Security and Cargo" + restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer", "Warden", "Detective", "Security Officer", "Head of Security", "Cargo Technician", "Shaft Miner", "Quartermaster") + +/datum/gear/head/orvkepimedsci + name = "Federation Kepi, medsci" + description = "A visored cap. Intended to be used with ORV uniform." + path = /obj/item/clothing/head/kepi/orvi/medsci + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS + restricted_desc = "Medical and Science" + restricted_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Paramedic", "Geneticist", "Research Director", "Scientist", "Roboticist") + +/datum/gear/head/orvkepisrv + name = "Federation Kepi, service" + description = "A visored cap. Intended to be used with ORV uniform." + path = /obj/item/clothing/head/kepi/orvi/service + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS + restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer" + restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain") + +/datum/gear/head/orvkepiass + name = "Federation Kepi, assistant" + description = "A visored cap. Intended to be used with ORV uniform." + path = /obj/item/clothing/head/kepi/orvi + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS + restricted_roles = list("Assistant") + /*Commenting out Until next Christmas or made automatic /datum/gear/santahatr name = "Red Santa Hat" @@ -111,29 +146,37 @@ */ //Cowboy Stuff -/datum/gear/cowboyhat +/datum/gear/head/cowboyhat name = "Cowboy Hat, Brown" - category = SLOT_HEAD path = /obj/item/clothing/head/cowboyhat -/datum/gear/cowboyhat/black +/datum/gear/head/cowboyhat/black name = "Cowboy Hat, Black" - category = SLOT_HEAD path = /obj/item/clothing/head/cowboyhat/black -/datum/gear/cowboyhat/white +/datum/gear/head/cowboyhat/white name = "Cowboy Hat, White" - category = SLOT_HEAD path = /obj/item/clothing/head/cowboyhat/white -/datum/gear/cowboyhat/pink +/datum/gear/head/cowboyhat/pink name = "Cowboy Hat, Pink" - category = SLOT_HEAD path = /obj/item/clothing/head/cowboyhat/pink -/datum/gear/cowboyhat/sec +/datum/gear/head/cowboyhat/sec name = "Cowboy Hat, Security" - category = SLOT_HEAD path = /obj/item/clothing/head/cowboyhat/sec + subcategory = LOADOUT_SUBCATEGORY_HEAD_JOBS restricted_desc = "Security" restricted_roles = list("Warden","Detective","Security Officer","Head of Security") + +/datum/gear/head/wkepi + name = "white kepi" + path = /obj/item/clothing/head/kepi + +/datum/gear/head/widered + name = "Wide red hat" + path = /obj/item/clothing/head/widered + +/datum/gear/head/kabuto + name = "Kabuto helmet" + path = /obj/item/clothing/head/kabuto diff --git a/modular_citadel/code/modules/client/loadout/mask.dm b/modular_citadel/code/modules/client/loadout/mask.dm index eeba06cad4..0d7e32552e 100644 --- a/modular_citadel/code/modules/client/loadout/mask.dm +++ b/modular_citadel/code/modules/client/loadout/mask.dm @@ -1,16 +1,16 @@ -/datum/gear/balaclava +/datum/gear/mask + category = LOADOUT_CATEGORY_MASK + slot = SLOT_WEAR_MASK + +/datum/gear/mask/balaclava name = "Balaclava" - category = SLOT_WEAR_MASK path = /obj/item/clothing/mask/balaclava -/datum/gear/moustache +/datum/gear/mask/moustache name = "Fake moustache" - category = SLOT_WEAR_MASK path = /obj/item/clothing/mask/fakemoustache -/datum/gear/joy +/datum/gear/mask/joy name = "Joy mask" - category = SLOT_WEAR_MASK path = /obj/item/clothing/mask/joy cost = 3 - diff --git a/modular_citadel/code/modules/client/loadout/neck.dm b/modular_citadel/code/modules/client/loadout/neck.dm index 320a83b87d..19311f703a 100644 --- a/modular_citadel/code/modules/client/loadout/neck.dm +++ b/modular_citadel/code/modules/client/loadout/neck.dm @@ -1,94 +1,88 @@ -/datum/gear/bluetie +/datum/gear/neck + category = LOADOUT_CATEGORY_NECK + subcategory = LOADOUT_SUBCATEGORY_NECK_GENERAL + slot = SLOT_NECK + +/datum/gear/neck/bluetie name = "Blue tie" - category = SLOT_NECK + subcategory = LOADOUT_SUBCATEGORY_NECK_TIE path = /obj/item/clothing/neck/tie/blue -/datum/gear/redtie +/datum/gear/neck/redtie name = "Red tie" - category = SLOT_NECK + subcategory = LOADOUT_SUBCATEGORY_NECK_TIE path = /obj/item/clothing/neck/tie/red -/datum/gear/blacktie +/datum/gear/neck/blacktie name = "Black tie" - category = SLOT_NECK + subcategory = LOADOUT_SUBCATEGORY_NECK_TIE path = /obj/item/clothing/neck/tie/black -/datum/gear/collar +/datum/gear/neck/collar name = "Collar" - category = SLOT_NECK path = /obj/item/clothing/neck/petcollar -/datum/gear/leathercollar +/datum/gear/neck/leathercollar name = "Leather collar" - category = SLOT_NECK path = /obj/item/clothing/neck/petcollar/leather -/datum/gear/choker +/datum/gear/neck/choker name = "Choker" - category = SLOT_NECK path = /obj/item/clothing/neck/petcollar/choker -/datum/gear/scarf +/datum/gear/neck/scarf name = "White scarf" - category = SLOT_NECK + subcategory = LOADOUT_SUBCATEGORY_NECK_SCARVES path = /obj/item/clothing/neck/scarf -/datum/gear/blackscarf +/datum/gear/neck/scarf/black name = "Black scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/black -/datum/gear/redscarf +/datum/gear/neck/scarf/red name = "Red scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/red -/datum/gear/greenscarf +/datum/gear/neck/scarf/green name = "Green scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/green -/datum/gear/darkbluescarf +/datum/gear/neck/scarf/darkblue name = "Dark blue scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/darkblue -/datum/gear/purplescarf +/datum/gear/neck/scarf/purple name = "Purple scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/purple -/datum/gear/yellowscarf +/datum/gear/neck/scarf/yellow name = "Yellow scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/yellow -/datum/gear/orangescarf +/datum/gear/neck/scarf/orange name = "Orange scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/orange -/datum/gear/cyanscarf +/datum/gear/neck/scarf/cyan name = "Cyan scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/scarf/cyan -/datum/gear/stripedredscarf +/datum/gear/neck/scarf/stripedred name = "Striped red scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/stripedredscarf -/datum/gear/stripedbluescarf +/datum/gear/neck/scarf/stripedblue name = "Striped blue scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/stripedbluescarf -/datum/gear/stripedgreenscarf +/datum/gear/neck/scarf/stripedgreen name = "Striped green scarf" - category = SLOT_NECK path = /obj/item/clothing/neck/stripedgreenscarf -/datum/gear/headphones +/datum/gear/neck/headphones name = "Headphones" - category = SLOT_NECK path = /obj/item/clothing/ears/headphones + +/datum/gear/neck/polycloak + name = "Polychromatic Cloak" + path = /obj/item/clothing/neck/cloak/polychromic diff --git a/modular_citadel/code/modules/client/loadout/shoes.dm b/modular_citadel/code/modules/client/loadout/shoes.dm index 3531e69cfd..76d7305971 100644 --- a/modular_citadel/code/modules/client/loadout/shoes.dm +++ b/modular_citadel/code/modules/client/loadout/shoes.dm @@ -1,84 +1,71 @@ -/datum/gear/laceup +/datum/gear/shoes + category = LOADOUT_CATEGORY_SHOES + slot = SLOT_SHOES + +/datum/gear/shoes/laceup name = "Laceup shoes" - category = SLOT_SHOES path = /obj/item/clothing/shoes/laceup -/datum/gear/workboots +/datum/gear/shoes/workboots name = "Work boots" - category = SLOT_SHOES path = /obj/item/clothing/shoes/workboots -/datum/gear/jackboots +/datum/gear/shoes/jackboots name = "Jackboots" - category = SLOT_SHOES path = /obj/item/clothing/shoes/jackboots -/datum/gear/winterboots +/datum/gear/shoes/winterboots name = "Winter boots" - category = SLOT_SHOES path = /obj/item/clothing/shoes/winterboots -/datum/gear/sandals +/datum/gear/shoes/sandals name = "Sandals" - category = SLOT_SHOES path = /obj/item/clothing/shoes/sandal -/datum/gear/blackshoes +/datum/gear/shoes/blackshoes name = "Black shoes" - category = SLOT_SHOES path = /obj/item/clothing/shoes/sneakers/black -/datum/gear/brownshoes +/datum/gear/shoes/brownshoes name = "Brown shoes" - category = SLOT_SHOES path = /obj/item/clothing/shoes/sneakers/brown -/datum/gear/whiteshoes +/datum/gear/shoes/whiteshoes name = "White shoes" - category = SLOT_SHOES path = /obj/item/clothing/shoes/sneakers/white -/datum/gear/gildedcuffs +/datum/gear/shoes/gildedcuffs name = "Gilded leg wraps" - category = SLOT_SHOES path= /obj/item/clothing/shoes/wraps -/datum/gear/silvercuffs +/datum/gear/shoes/silvercuffs name = "Silver leg wraps" - category = SLOT_SHOES path= /obj/item/clothing/shoes/wraps/silver -/datum/gear/redcuffs +/datum/gear/shoes/redcuffs name = "Red leg wraps" - category = SLOT_SHOES path= /obj/item/clothing/shoes/wraps/red -/datum/gear/bluecuffs +/datum/gear/shoes/bluecuffs name = "Blue leg wraps" - category = SLOT_SHOES path= /obj/item/clothing/shoes/wraps/blue -/datum/gear/christmasbootsr +/datum/gear/shoes/christmasbootsr name = "Red Christmas Boots" - category = SLOT_SHOES path= /obj/item/clothing/shoes/winterboots/christmasbootsr -/datum/gear/christmasbootsg +/datum/gear/shoes/christmasbootsg name = "Green Christmas Boots" - category = SLOT_SHOES path= /obj/item/clothing/shoes/winterboots/christmasbootsg -/datum/gear/santaboots +/datum/gear/shoes/santaboots name = "Santa Boots" - category = SLOT_SHOES path= /obj/item/clothing/shoes/winterboots/santaboots -/datum/gear/cowboyboots +/datum/gear/shoes/cowboyboots name = "Cowboy Boots, Brown" - category = SLOT_SHOES path = /obj/item/clothing/shoes/cowboyboots -/datum/gear/cowboyboots/black +/datum/gear/shoes/cowboyboots/black name = "Cowboy Boots, Black" - category = SLOT_SHOES - path = /obj/item/clothing/shoes/cowboyboots/black \ No newline at end of file + path = /obj/item/clothing/shoes/cowboyboots/black diff --git a/modular_citadel/code/modules/client/loadout/suit.dm b/modular_citadel/code/modules/client/loadout/suit.dm index fecf2a4dce..d0be26a8a4 100644 --- a/modular_citadel/code/modules/client/loadout/suit.dm +++ b/modular_citadel/code/modules/client/loadout/suit.dm @@ -1,235 +1,250 @@ -/datum/gear/poncho +/datum/gear/suit + category = LOADOUT_CATEGORY_SUIT + subcategory = LOADOUT_SUBCATEGORY_SUIT_GENERAL + slot = SLOT_WEAR_SUIT + +/datum/gear/suit/poncho name = "Poncho" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/poncho -/datum/gear/ponchogreen +/datum/gear/suit/ponchogreen name = "Green poncho" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/poncho/green -/datum/gear/ponchored +/datum/gear/suit/ponchored name = "Red poncho" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/poncho/red -/datum/gear/redhood +/datum/gear/suit/redhood name = "Red cloak" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/cloak/david cost = 3 -/datum/gear/jacketbomber +/datum/gear/suit/jacketbomber name = "Bomber jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/jacketleather +/datum/gear/suit/jacketflannelblack // all of these are reskins of bomber jackets but with the vibe to make you look like a true lumberjack + name = "Black flannel jacket" + path = /obj/item/clothing/suit/jacket/flannel + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS + +/datum/gear/suit/jacketflannelred + name = "Red flannel jacket" + path = /obj/item/clothing/suit/jacket/flannel/red + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS + +/datum/gear/suit/jacketflannelaqua + name = "Aqua flannel jacket" + path = /obj/item/clothing/suit/jacket/flannel/aqua + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS + +/datum/gear/suit/jacketflannelbrown + name = "Brown flannel jacket" + path = /obj/item/clothing/suit/jacket/flannel/brown + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS + +/datum/gear/suit/jacketleather name = "Leather jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/leather + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/overcoatleather +/datum/gear/suit/overcoatleather name = "Leather overcoat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/leather/overcoat + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/jacketpuffer +/datum/gear/suit/jacketpuffer name = "Puffer jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/puffer + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/vestpuffer +/datum/gear/suit/vestpuffer name = "Puffer vest" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/puffer/vest + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/jacketlettermanbrown +/datum/gear/suit/jacketlettermanbrown name = "Brown letterman jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/letterman + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/jacketlettermanred +/datum/gear/suit/jacketlettermanred name = "Red letterman jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/letterman_red + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/jacketlettermanNT +/datum/gear/suit/jacketlettermanNT name = "Nanotrasen letterman jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/letterman_nanotrasen + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/coat +/datum/gear/suit/coat name = "Winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat + subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS -/datum/gear/coat/aformal +/datum/gear/suit/coat/aformal name = "Assistant's formal winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/aformal -/datum/gear/coat/runed +/datum/gear/suit/coat/runed name = "Runed winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/narsie/fake -/datum/gear/coat/brass +/datum/gear/suit/coat/brass name = "Brass winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/ratvar/fake -/datum/gear/coat/polycoat +/datum/gear/suit/coat/polycoat name = "Polychromic winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/polychromic cost = 4 //too many people with neon green coats is hard on the eyes -/datum/gear/coat/med +/datum/gear/suit/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 +/datum/gear/suit/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 +/datum/gear/suit/coat/robotics name = "Robotics winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/robotics restricted_roles = list("Research Director", "Roboticist") -/datum/gear/coat/sci +/datum/gear/suit/coat/sci name = "Science winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/science restricted_roles = list("Research Director", "Scientist", "Roboticist") // Reserve it to the Science Departement -/datum/gear/coat/eng +/datum/gear/suit/coat/eng name = "Engineering winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/engineering restricted_roles = list("Chief Engineer", "Station Engineer") // Reserve it to Station Engineers and their boss, the Chief Engineer -/datum/gear/coat/eng/atmos +/datum/gear/suit/coat/eng/atmos name = "Atmospherics winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos restricted_roles = list("Chief Engineer", "Atmospheric Technician") // Reserve it to Atmos Techs and their boss, the Chief Engineer -/datum/gear/coat/hydro +/datum/gear/suit/coat/hydro name = "Hydroponics winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/hydro restricted_roles = list("Head of Personnel", "Botanist") // Reserve it to Botanists and their boss, the Head of Personnel -/datum/gear/coat/cargo +/datum/gear/suit/coat/bar + name = "Bar winter coat" + path = /obj/item/clothing/suit/hooded/wintercoat/bar + restricted_roles = list("Bartender") // Reserve it to Bartenders and not the Head of Personnel because he doesnt deserve to look as fancy as them + +/datum/gear/suit/coat/cargo name = "Cargo winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/cargo restricted_roles = list("Quartermaster", "Cargo Technician") // Reserve it to Cargo Techs and their boss, the Quartermaster -/datum/gear/coat/miner +/datum/gear/suit/coat/miner name = "Mining winter coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/miner restricted_roles = list("Quartermaster", "Shaft Miner") // Reserve it to Miners and their boss, the Quartermaster -/datum/gear/militaryjacket +/datum/gear/suit/militaryjacket name = "Military Jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/jacket/miljacket + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS -/datum/gear/ianshirt +/datum/gear/suit/ianshirt name = "Ian Shirt" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/ianshirt -/datum/gear/flakjack +/datum/gear/suit/flakjack name = "Flak Jacket" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/flakjack + subcategory = LOADOUT_SUBCATEGORY_SUIT_JACKETS cost = 2 -/datum/gear/trekds9_coat +/datum/gear/suit/trekds9_coat name = "DS9 Overcoat (use uniform)" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/trek/ds9 + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "All, barring Service and Civilian" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster", "Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Scientist", "Roboticist", "Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer", "Cargo Technician", "Shaft Miner") //everyone who actually deserves a job. //Federation jackets from movies -/datum/gear/trekcmdcap +/datum/gear/suit/trekcmdcap name = "Fed (movie) uniform, Black" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/fedcoat/capt + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_roles = list("Captain","Head of Personnel") -/datum/gear/trekcmdmov +/datum/gear/suit/trekcmdmov name = "Fed (movie) uniform, Red" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/fedcoat + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "Heads of Staff and Security" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster","Warden","Detective","Security Officer") -/datum/gear/trekmedscimov +/datum/gear/suit/trekmedscimov name = "Fed (movie) uniform, Blue" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/fedcoat/medsci + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengmov +/datum/gear/suit/trekengmov name = "Fed (movie) uniform, Yellow" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/fedcoat/eng + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "Engineering and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Cargo Technician", "Shaft Miner", "Quartermaster") -/datum/gear/trekcmdcapmod +/datum/gear/suit/trekcmdcapmod name = "Fed (Modern) uniform, White" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/modernfedcoat restricted_roles = list("Captain","Head of Personnel") -/datum/gear/trekcmdmod +/datum/gear/suit/trekcmdmod name = "Fed (Modern) uniform, Red" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/modernfedcoat/sec + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "Heads of Staff and Security" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster","Warden","Detective","Security Officer") -/datum/gear/trekmedscimod +/datum/gear/suit/trekmedscimod name = "Fed (Modern) uniform, Blue" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/modernfedcoat/medsci + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengmod +/datum/gear/suit/trekengmod name = "Fed (Modern) uniform, Yellow" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/storage/fluff/modernfedcoat/eng + subcategory = LOADOUT_SUBCATEGORY_SUIT_JOBS restricted_desc = "Engineering and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Cargo Technician", "Shaft Miner", "Quartermaster") -/datum/gear/christmascoatr +/datum/gear/suit/christmascoatr name = "Red Christmas Coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatr + subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS -/datum/gear/christmascoatg +/datum/gear/suit/christmascoatg name = "Green Christmas Coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatg + subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS -/datum/gear/christmascoatrg +/datum/gear/suit/christmascoatrg name = "Red and Green Christmas Coat" - category = SLOT_WEAR_SUIT path = /obj/item/clothing/suit/hooded/wintercoat/christmascoatrg + subcategory = LOADOUT_SUBCATEGORY_SUIT_COATS + +/datum/gear/suit/samurai + name = "Samurai outfit" + path = /obj/item/clothing/suit/samurai diff --git a/modular_citadel/code/modules/client/loadout/uniform.dm b/modular_citadel/code/modules/client/loadout/uniform.dm index e667626968..5ce73d1cfd 100644 --- a/modular_citadel/code/modules/client/loadout/uniform.dm +++ b/modular_citadel/code/modules/client/loadout/uniform.dm @@ -1,562 +1,542 @@ -/datum/gear/suitblack - name = "Black suit" - category = SLOT_W_UNIFORM - path = /obj/item/clothing/under/suit/black +/datum/gear/uniform + category = LOADOUT_CATEGORY_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_GENERAL + slot = SLOT_W_UNIFORM -/datum/gear/suitgreen +/datum/gear/uniform/suit + name = "Black suit" + path = /obj/item/clothing/under/suit/black + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SUITS + +/datum/gear/uniform/suit/green name = "Green suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/green -/datum/gear/suitred +/datum/gear/uniform/suit/red name = "Red suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/red -/datum/gear/suitcharcoal +/datum/gear/uniform/suit/charcoal name = "Charcoal suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/charcoal -/datum/gear/suitnavy +/datum/gear/uniform/suit/navy name = "Navy suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/navy -/datum/gear/suitburgundy +/datum/gear/uniform/suit/burgundy name = "Burgundy suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/burgundy -/datum/gear/suittan +/datum/gear/uniform/suit/tan name = "Tan suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/tan -/datum/gear/suitwhite +/datum/gear/uniform/suit/white name = "White suit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/suit/white -/datum/gear/assistantformal +/datum/gear/uniform/assistantformal name = "Assistant's formal uniform" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/assistantformal -/datum/gear/maidcostume +/datum/gear/uniform/maidcostume name = "Maid costume" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/maid -/datum/gear/mailmanuniform +/datum/gear/uniform/mailmanuniform name = "Mailman's jumpsuit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/mailman -/datum/gear/skirtblack +/datum/gear/uniform/skirt name = "Black skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SKIRTS -/datum/gear/skirtblue +/datum/gear/uniform/skirt/blue name = "Blue skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/blue -/datum/gear/skirtred +/datum/gear/uniform/skirt/red name = "Red skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/red -/datum/gear/skirtpurple +/datum/gear/uniform/skirt/purple name = "Purple skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/purple -/datum/gear/skirtplaid +/datum/gear/uniform/skirt/plaid name = "Plaid skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/plaid -/datum/gear/schoolgirlblue +/datum/gear/uniform/schoolgirlblue name = "Blue Schoolgirl Uniform" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/schoolgirl -/datum/gear/schoolgirlred +/datum/gear/uniform/schoolgirlred name = "Red Schoolgirl Uniform" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/schoolgirl/red -/datum/gear/schoolgirlgreen +/datum/gear/uniform/schoolgirlgreen name = "Green Schoolgirl Uniform" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/schoolgirl/green -/datum/gear/schoolgirlorange +/datum/gear/uniform/schoolgirlorange name = "Orange Schoolgirl Uniform" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/schoolgirl/orange -/datum/gear/stripeddress +/datum/gear/uniform/dress name = "Striped Dress" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/striped + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES -/datum/gear/sundresswhite +/datum/gear/uniform/dress/sun/white name = "White Sundress" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/sundress/white -/datum/gear/sundress +/datum/gear/uniform/dress/sun name = "Sundress" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/sundress -/datum/gear/greendress +/datum/gear/uniform/dress/green name = "Green Dress" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/green -/datum/gear/pinkdress +/datum/gear/uniform/dress/pink name = "Pink Dress" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/pink -/datum/gear/flowerdress + +/datum/gear/uniform/dress/orange name = "Flower Dress" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/flower -/datum/gear/sweptskirt +/datum/gear/uniform/skirt/swept name = "Swept skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/swept -/datum/gear/croptop +/datum/gear/uniform/croptop name = "Croptop" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/croptop -/datum/gear/yoga +/datum/gear/uniform/pants name = "Yoga Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/yoga + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_PANTS -/datum/gear/kilt +/datum/gear/uniform/kilt name = "Kilt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/kilt -/datum/gear/camoshorts +/datum/gear/uniform/pants/camo name = "Camo Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/camo -/datum/gear/athleticshorts +/datum/gear/uniform/shorts name = "Athletic Shorts" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/shorts/red + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SHORTS -/datum/gear/bjeans +/datum/gear/uniform/pants/bjeans name = "Black Jeans" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/blackjeans -/datum/gear/cjeans +/datum/gear/uniform/pants/cjeans name = "Classic Jeans" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/classicjeans -/datum/gear/khaki +/datum/gear/uniform/pants/khaki name = "Khaki Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/khaki -/datum/gear/wpants +/datum/gear/uniform/pants/white name = "White Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/white -/datum/gear/rpants +/datum/gear/uniform/pants/red name = "Red Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/red -/datum/gear/tpants +/datum/gear/uniform/pants/tan name = "Tan Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/tan -/datum/gear/trpants +/datum/gear/uniform/pants/track name = "Track Pants" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/track -/datum/gear/rippedjeans +/datum/gear/uniform/pants/ripped name = "Ripped Jeans" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/jeanripped -/datum/gear/jeanshort +/datum/gear/uniform/shorts/jean name = "Jean Shorts" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/jeanshort -/datum/gear/denimskirt +/datum/gear/uniform/skirt/denim name = "Denim Skirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/pants/denimskirt -/datum/gear/yoga - name = "Yoga Pants" - category = SLOT_W_UNIFORM - path = /obj/item/clothing/under/pants/yoga - // Pantsless Sweaters -/datum/gear/turtleneck +/datum/gear/uniform/turtleneck name = "Tactitool Turtleneck" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/syndicate/cosmetic -/datum/gear/creamsweater +/datum/gear/uniform/sweater name = "Cream Commando Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_SWEATERS -/datum/gear/blacksweater +/datum/gear/uniform/sweater/black name = "Black Commando Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater/black -/datum/gear/purpsweater +/datum/gear/uniform/sweater/purple name = "Purple Commando Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater/purple -/datum/gear/greensweater +/datum/gear/uniform/sweater/green name = "Green Commando Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater/green -/datum/gear/redsweater +/datum/gear/uniform/sweater/red name = "Red Commando Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater/red -/datum/gear/bluesweater +/datum/gear/uniform/sweater/blue name = "Navy Commando Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/sweater/blue -/datum/gear/keyholesweater +/datum/gear/uniform/sweater/keyhole name = "Keyhole Sweater" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/keyholesweater -/datum/gear/polyjump +/datum/gear/uniform/polyjump name = "Polychromic Jumpsuit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/polyjumpsuit cost = 2 - -/datum/gear/polyskirt + +/datum/gear/uniform/skirt/poly name = "Polychromic Jumpskirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/polychromic cost = 2 -/datum/gear/polysuit +/datum/gear/uniform/suit/poly name = "Polychromic Button-up Shirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/poly_shirt cost = 3 - -/datum/gear/polypleated + +/datum/gear/uniform/skirt/poly/pleated name = "Polychromic Pleated Sweaterskirt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/dress/skirt/polychromic/pleated cost = 3 -/datum/gear/polykilt +/datum/gear/uniform/polykilt name = "Polychromic Kilt" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/kilt/polychromic cost = 3 -/datum/gear/polyshorts +/datum/gear/uniform/shorts/poly name = "Polychromic Shorts" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/polyshorts cost = 3 -/datum/gear/polyshortpants +/datum/gear/uniform/shorts/poly/athletic name = "Polychromic Athletic Shorts" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/shorts/polychromic cost = 2 // Trekie things //TOS -/datum/gear/trekcmdtos +/datum/gear/uniform/trekcmdtos name = "TOS uniform, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Heads of Staff" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") -/datum/gear/trekmedscitos +/datum/gear/uniform/trekmedscitos name = "TOS uniform, med/sci" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/medsci + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengtos +/datum/gear/uniform/trekengtos name = "TOS uniform, ops/sec" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/engsec + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") //TNG -/datum/gear/trekcmdtng +/datum/gear/uniform/trekcmdtng name = "TNG uniform, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/next + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Heads of Staff" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") -/datum/gear/trekmedscitng +/datum/gear/uniform/trekmedscitng name = "TNG uniform, med/sci" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/medsci/next + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengtng +/datum/gear/uniform/trekengtng name = "TNG uniform, ops/sec" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/engsec/next + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") //VOY -/datum/gear/trekcmdvoy +/datum/gear/uniform/trekcmdvoy name = "VOY uniform, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/voy + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Heads of Staff" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") -/datum/gear/trekmedscivoy +/datum/gear/uniform/trekmedscivoy name = "VOY uniform, med/sci" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/medsci/voy + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengvoy +/datum/gear/uniform/trekengvoy name = "VOY uniform, ops/sec" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/engsec/voy + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") //DS9 -/datum/gear/trekcmdds9 +/datum/gear/uniform/trekcmdds9 name = "DS9 uniform, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/ds9 + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Heads of Staff" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") -/datum/gear/trekmedscids9 +/datum/gear/uniform/trekmedscids9 name = "DS9 uniform, med/sci" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/medsci/ds9 + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengds9 +/datum/gear/uniform/trekengds9 name = "DS9 uniform, ops/sec" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/engsec/ds9 + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") //ENT -/datum/gear/trekcmdent +/datum/gear/uniform/trekcmdent name = "ENT uniform, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/ent + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Heads of Staff" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster") -/datum/gear/trekmedscient +/datum/gear/uniform/trekmedscient name = "ENT uniform, med/sci" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/medsci/ent + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Research Director","Scientist", "Roboticist") -/datum/gear/trekengent +/datum/gear/uniform/trekengent name = "ENT uniform, ops/sec" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/engsec/ent + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Engineering, Security, and Cargo" restricted_roles = list("Chief Engineer","Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer","Head of Security","Cargo Technician", "Shaft Miner", "Quartermaster") //TheMotionPicture -/datum/gear/trekfedutil +/datum/gear/uniform/trekfedutil name = "TMP uniform" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/fedutil + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "All, barring Service and Civilian" restricted_roles = list("Head of Security","Captain","Head of Personnel","Chief Engineer","Research Director","Chief Medical Officer","Quartermaster", "Medical Doctor","Chemist","Virologist","Paramedic","Geneticist","Scientist", "Roboticist", "Atmospheric Technician","Station Engineer","Warden","Detective","Security Officer", "Cargo Technician", "Shaft Miner") -/datum/gear/trekfedtrainee +/datum/gear/uniform/trekfedtrainee name = "TMP uniform, trainee" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/fedutil/trainee + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Assistant", "Janitor", "Cargo Technician") -/datum/gear/trekfedservice +/datum/gear/uniform/trekfedservice name = "TMP uniform, service" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/fedutil/service + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer" restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain") //Orvilike -/datum/gear/orvcmd +/datum/gear/uniform/orvcmd name = "ORV uniform, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/orv + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Heads of Staff" restricted_roles = list("Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Research Director", "Chief Medical Officer", "Quartermaster") -/datum/gear/orvcmd_capt +/datum/gear/uniform/orvcmd_capt name = "ORV uniform, capt" - category = SLOT_W_UNIFORM + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS path = /obj/item/clothing/under/trek/command/orv/captain restricted_roles = list("Captain") -/datum/gear/orvmedsci +/datum/gear/uniform/orvmedsci name = "ORV uniform, med/sci" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/medsci/orv + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Medical and Science" restricted_roles = list("Chief Medical Officer", "Medical Doctor", "Chemist", "Virologist", "Paramedic", "Geneticist", "Research Director", "Scientist", "Roboticist") -/datum/gear/orvcmd_medsci +/datum/gear/uniform/orvcmd_medsci name = "ORV uniform, med/sci, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/orv/medsci + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Chief Medical Officer", "Research Director") -/datum/gear/orvops +/datum/gear/uniform/orvops name = "ORV uniform, ops/sec" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/engsec/orv + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_desc = "Engineering, Security and Cargo" restricted_roles = list("Chief Engineer", "Atmospheric Technician", "Station Engineer", "Warden", "Detective", "Security Officer", "Head of Security", "Cargo Technician", "Shaft Miner", "Quartermaster") -/datum/gear/orvcmd_ops +/datum/gear/uniform/orvcmd_ops name = "ORV uniform, ops/sec, cmd" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/command/orv/engsec + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Chief Engineer", "Head of Security") -/datum/gear/orvass +/datum/gear/uniform/orvass name = "ORV uniform, assistant" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/orv + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Assistant") -/datum/gear/orvsrv +/datum/gear/uniform/orvsrv name = "ORV uniform, service" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/trek/orv/service + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_JOBS restricted_roles = list("Assistant", "Bartender", "Botanist", "Cook", "Curator", "Janitor", "Chaplain") restricted_desc = "Service and Civilian, barring Clown, Mime and Lawyer" //Memes -/datum/gear/gear_harnesses +/datum/gear/uniform/gear_harnesses name = "Gear Harness" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/gear_harness //Christmas /*Commenting out Until next Christmas or made automatic -/datum/gear/christmasmaler +/datum/gear/uniform/christmasmaler name = "Red Masculine Christmas Suit" category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/christmas -/datum/gear/christmasmaleg +/datum/gear/uniform/christmasmaleg name = "Green Masculine Christmas Suit" category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/christmas/green -/datum/gear/christmasfemaler +/datum/gear/uniform/christmasfemaler name = "Red Feminine Christmas Suit" category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/christmas/croptop -/datum/gear/christmasfemaleg +/datum/gear/uniform/christmasfemaleg name = "Green Feminine Christmas Suit" category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/christmas/croptop/green -/datum/gear/pinkstripper +/datum/gear/uniform/pinkstripper name = "Pink stripper outfit" category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/stripper cost = 3 */ -/datum/gear/greenstripper +/datum/gear/uniform/greenstripper name = "Green stripper outfit" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/misc/stripper/green cost = 3 -/datum/gear/qipao +/datum/gear/uniform/qipao name = "Qipao, Black" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/qipao + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES cost = 3 -/datum/gear/qipao/white +/datum/gear/uniform/qipao/white name = "Qipao, White" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/qipao/white + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES cost = 3 -/datum/gear/qipao/red +/datum/gear/uniform/qipao/red name = "Qipao, Red" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/qipao/red + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES cost = 3 -/datum/gear/cheongsam +/datum/gear/uniform/cheongsam name = "Cheongsam, Black" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/cheongsam + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES cost = 3 -/datum/gear/cheongsam/white +/datum/gear/uniform/cheongsam/white name = "Cheongsam, White" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/cheongsam/white + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES cost = 3 -/datum/gear/cheongsam/red +/datum/gear/uniform/cheongsam/red name = "Cheongsam, Red" - category = SLOT_W_UNIFORM path = /obj/item/clothing/under/costume/cheongsam/red + subcategory = LOADOUT_SUBCATEGORY_UNIFORM_DRESSES cost = 3 + +/datum/gear/uniform/dress/black + name = "Black dress" + path = /obj/item/clothing/under/misc/black_dress + +/datum/gear/uniform/skirt/pinktutu + name = "Pink tutu" + path = /obj/item/clothing/under/misc/pinktutu + +/datum/gear/uniform/bathrobe + name = "Bathrobe" + path = /obj/item/clothing/under/misc/bathrobe + +/datum/gear/uniform/kimono + name = "Kimono" + path = /obj/item/clothing/under/costume/kimono + +/datum/gear/uniform/kimono/black + name = "Black kimono" + path = /obj/item/clothing/under/costume/kimono/black + +/datum/gear/uniform/kimono/kamishimo + name = "Kamishimo" + path = /obj/item/clothing/under/costume/kimono/kamishimo + +/datum/gear/uniform/kimono/fancy + name = "Fancy kimono" + path = /obj/item/clothing/under/costume/kimono/fancy + +/datum/gear/uniform/kimono/sakura + name = "Sakura kimono" + path = /obj/item/clothing/under/costume/kimono/sakura diff --git a/modular_citadel/code/modules/client/preferences_savefile.dm b/modular_citadel/code/modules/client/preferences_savefile.dm index c747c4cf32..bbd71d22e3 100644 --- a/modular_citadel/code/modules/client/preferences_savefile.dm +++ b/modular_citadel/code/modules/client/preferences_savefile.dm @@ -7,12 +7,12 @@ features["ipc_antenna"] = sanitize_inlist(features["ipc_antenna"], GLOB.ipc_antennas_list) //Citadel features["flavor_text"] = sanitize_text(features["flavor_text"], initial(features["flavor_text"])) - if(!features["mcolor2"] || features["mcolor"] == "#000") + if(!features["mcolor2"] || features["mcolor"] == "#000000") features["mcolor2"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F") - if(!features["mcolor3"] || features["mcolor"] == "#000") + if(!features["mcolor3"] || features["mcolor"] == "#000000") features["mcolor3"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F") - features["mcolor2"] = sanitize_hexcolor(features["mcolor2"], 3, 0) - features["mcolor3"] = sanitize_hexcolor(features["mcolor3"], 3, 0) + features["mcolor2"] = sanitize_hexcolor(features["mcolor2"], 6, FALSE) + features["mcolor3"] = sanitize_hexcolor(features["mcolor3"], 6, FALSE) /datum/preferences/proc/cit_character_pref_save(savefile/S) diff --git a/modular_citadel/code/modules/clothing/trek.dm b/modular_citadel/code/modules/clothing/trek.dm index c522d1af81..f7e8b6778e 100644 --- a/modular_citadel/code/modules/clothing/trek.dm +++ b/modular_citadel/code/modules/clothing/trek.dm @@ -162,3 +162,21 @@ /obj/item/clothing/head/caphat/formal/fedcover/black icon_state = "fedcapblack" item_state = "fedcapblack" + +//orvilike caps +/obj/item/clothing/head/kepi/orvi + name = "\improper Federation kepi" + desc = "A visored cap worn by all officers since 2550s." + icon_state = "kepi_ass" + +/obj/item/clothing/head/kepi/orvi/command + icon_state = "kepi_com" + +/obj/item/clothing/head/kepi/orvi/engsec + icon_state = "kepi_ops" + +/obj/item/clothing/head/kepi/orvi/medsci + icon_state = "kepi_medsci" + +/obj/item/clothing/head/kepi/orvi/service + icon_state = "kepi_srv" diff --git a/modular_citadel/code/modules/mentor/mentor_memo.dm b/modular_citadel/code/modules/mentor/mentor_memo.dm index b9f6833e32..8110c5ffcc 100644 --- a/modular_citadel/code/modules/mentor/mentor_memo.dm +++ b/modular_citadel/code/modules/mentor/mentor_memo.dm @@ -33,11 +33,14 @@ var/datum/DBQuery/query_memocheck = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("mentor_memo")] WHERE ckey = '[sql_ckey]'") if(!query_memocheck.Execute()) var/err = query_memocheck.ErrorMsg() + qdel(query_memocheck) log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n") return if(query_memocheck.NextRow()) + qdel(query_memocheck) to_chat(src, "You already have set a memo.") return + qdel(query_memocheck) var/memotext = input(src,"Write your Memo","Memo") as message if(!memotext) return @@ -46,20 +49,24 @@ var/datum/DBQuery/query_memoadd = SSdbcore.NewQuery("INSERT INTO [format_table_name("mentor_memo")] (ckey, memotext, timestamp) VALUES ('[sql_ckey]', '[memotext]', '[timestamp]')") if(!query_memoadd.Execute()) var/err = query_memoadd.ErrorMsg() + qdel(query_memoadd) log_game("SQL ERROR adding new memo. Error : \[[err]\]\n") return log_admin("[key_name(src)] has set a mentor memo: [memotext]") message_admins("[key_name_admin(src)] has set a mentor memo:
      [memotext]") + qdel(query_memoadd) if("Edit") var/datum/DBQuery/query_memolist = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("mentor_memo")]") if(!query_memolist.Execute()) var/err = query_memolist.ErrorMsg() + qdel(query_memolist) log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n") return var/list/memolist = list() while(query_memolist.NextRow()) var/lkey = query_memolist.item[1] memolist += "[lkey]" + qdel(query_memolist) if(!memolist.len) to_chat(src, "No memos found in database.") return @@ -70,10 +77,12 @@ var/datum/DBQuery/query_memofind = SSdbcore.NewQuery("SELECT memotext FROM [format_table_name("mentor_memo")] WHERE ckey = '[target_sql_ckey]'") if(!query_memofind.Execute()) var/err = query_memofind.ErrorMsg() + qdel(query_memofind) log_game("SQL ERROR obtaining memotext from memo table. Error : \[[err]\]\n") return if(query_memofind.NextRow()) var/old_memo = query_memofind.item[1] + qdel(query_memofind) var/new_memo = input("Input new memo", "New Memo", "[old_memo]", null) as message if(!new_memo) return @@ -83,6 +92,7 @@ var/datum/DBQuery/update_query = SSdbcore.NewQuery("UPDATE [format_table_name("mentor_memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'") if(!update_query.Execute()) var/err = update_query.ErrorMsg() + qdel(update_query) log_game("SQL ERROR editing memo. Error : \[[err]\]\n") return if(target_sql_ckey == sql_ckey) @@ -91,10 +101,14 @@ else log_admin("[key_name(src)] has edited [target_sql_ckey]'s mentor memo from [old_memo] to [new_memo]") message_admins("[key_name_admin(src)] has edited [target_sql_ckey]'s mentor memo from
      [old_memo]
      to
      [new_memo]") + qdel(update_query) + else + qdel(query_memofind) if("Show") var/datum/DBQuery/query_memoshow = SSdbcore.NewQuery("SELECT ckey, memotext, timestamp, last_editor FROM [format_table_name("mentor_memo")]") if(!query_memoshow.Execute()) var/err = query_memoshow.ErrorMsg() + qdel(query_memoshow) log_game("SQL ERROR obtaining ckey, memotext, timestamp, last_editor from memo table. Error : \[[err]\]\n") return var/output = null @@ -107,6 +121,7 @@ if(last_editor) output += "
      Last edit by [last_editor] (Click here to see edit log)" output += "
      [memotext]

      " + qdel(query_memoshow) if(!output) to_chat(src, "No memos found in database.") return @@ -115,12 +130,14 @@ var/datum/DBQuery/query_memodellist = SSdbcore.NewQuery("SELECT ckey FROM [format_table_name("mentor_memo")]") if(!query_memodellist.Execute()) var/err = query_memodellist.ErrorMsg() + qdel(query_memodellist) log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n") return var/list/memolist = list() while(query_memodellist.NextRow()) var/ckey = query_memodellist.item[1] memolist += "[ckey]" + qdel(query_memodellist) if(!memolist.len) to_chat(src, "No memos found in database.") return @@ -131,6 +148,7 @@ var/datum/DBQuery/query_memodel = SSdbcore.NewQuery("DELETE FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'") if(!query_memodel.Execute()) var/err = query_memodel.ErrorMsg() + qdel(query_memodel) log_game("SQL ERROR removing memo. Error : \[[err]\]\n") return if(target_sql_ckey == sql_ckey) @@ -138,4 +156,4 @@ message_admins("[key_name_admin(src)] has removed their mentor memo.") else log_admin("[key_name(src)] has removed [target_sql_ckey]'s mentor memo.") - message_admins("[key_name_admin(src)] has removed [target_sql_ckey]'s mentor memo.") \ No newline at end of file + message_admins("[key_name_admin(src)] has removed [target_sql_ckey]'s mentor memo.") diff --git a/modular_citadel/code/modules/mentor/mentorpm.dm b/modular_citadel/code/modules/mentor/mentorpm.dm index d2d04495d4..3260e96767 100644 --- a/modular_citadel/code/modules/mentor/mentorpm.dm +++ b/modular_citadel/code/modules/mentor/mentorpm.dm @@ -67,7 +67,7 @@ if(C.is_mentor()) if(is_mentor())//both are mentors to_chat(C, "Mentor PM from-[key_name_mentor(src, C, 1, 0, 0)]: [msg]") - to_chat(src, "Mentor PM to-[key_name_mentor(C, C, 1, 0, 0)]: [msg]") + to_chat(src, "Mentor PM to-[key_name_mentor(C, C, 1, 0, 0)]: [msg]") else //recipient is a mentor but sender is not to_chat(C, "Reply PM from-[key_name_mentor(src, C, 1, 0, show_char)]: [msg]") diff --git a/modular_citadel/code/modules/mob/cit_emotes.dm b/modular_citadel/code/modules/mob/cit_emotes.dm index 2be83733e5..e58c6bda30 100644 --- a/modular_citadel/code/modules/mob/cit_emotes.dm +++ b/modular_citadel/code/modules/mob/cit_emotes.dm @@ -244,3 +244,21 @@ user.nextsoundemote = world.time + 7 var/sound = pick('modular_citadel/sound/voice/bark1.ogg', 'modular_citadel/sound/voice/bark2.ogg') playsound(user, sound, 50, 1, -1) + +/datum/emote/living/squish + key = "squish" + key_third_person = "squishes" + message = "squishes!" + emote_type = EMOTE_AUDIBLE + muzzle_ignore = FALSE + restraint_check = FALSE + mob_type_allowed_typecache = list(/mob/living/carbon, /mob/living/silicon/pai) + +/datum/emote/living/squish/run_emote(mob/living/user, params) + if(!(. = ..())) + return + if(user.nextsoundemote >= world.time) + return + user.nextsoundemote = world.time + 7 + var/sound = pick('sound/voice/slime_squish.ogg') + playsound(user, sound, 50, 1, -1) diff --git a/modular_citadel/code/modules/mob/living/carbon/life.dm b/modular_citadel/code/modules/mob/living/carbon/life.dm deleted file mode 100644 index e94bd75985..0000000000 --- a/modular_citadel/code/modules/mob/living/carbon/life.dm +++ /dev/null @@ -1,3 +0,0 @@ -/mob/living/carbon/Life() - . = ..() - doSprintBufferRegen() diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm index 20917c4ba5..4829fd921c 100644 --- a/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm +++ b/modular_citadel/code/modules/projectiles/guns/ballistic/handguns.dm @@ -16,13 +16,12 @@ spread = 20 actions_types = list() -/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_icon() - ..() +/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_overlays() + . = ..() if(magazine) - cut_overlays() - add_overlay("foamsp-magazine") - else - cut_overlays() + . += "foamsp-magazine" + +/obj/item/gun/ballistic/automatic/toy/pistol/stealth/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" /////////RAYGUN MEMES///////// diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm index 8a1310d2f1..c2bf251de9 100644 --- a/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm +++ b/modular_citadel/code/modules/projectiles/guns/ballistic/rifles.dm @@ -155,11 +155,15 @@ casing_ejector = 0 spread = 10 recoil = 0.05 + automatic_burst_overlay = FALSE + var/magtype = "flechettegun" -/obj/item/gun/ballistic/automatic/flechette/update_icon() - cut_overlays() +/obj/item/gun/ballistic/automatic/flechette/update_overlays() + . = ..() if(magazine) - add_overlay("flechettegun-magazine") + . += "[magtype]-magazine" + +/obj/item/gun/ballistic/automatic/flechette/update_icon_state() icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" ///unique variant/// @@ -185,12 +189,7 @@ w_class = WEIGHT_CLASS_SMALL spread = 15 recoil = 0.1 - -/obj/item/gun/ballistic/automatic/flechette/shredder/update_icon() - cut_overlays() - if(magazine) - add_overlay("shreddergun-magazine") - icon_state = "[initial(icon_state)][chambered ? "" : "-e"]" + magtype = "shreddergun" /*///////////////////////////////////////////////////////////// //////////////////////// Zero's Meme ////////////////////////// @@ -218,17 +217,19 @@ burst_size = 4 //Shh. fire_delay = 1 var/body_color = "#3333aa" + automatic_burst_overlay = FALSE -/obj/item/gun/ballistic/automatic/AM4B/update_icon() - ..() +/obj/item/gun/ballistic/automatic/AM4B/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +/obj/item/gun/ballistic/automatic/AM4B/update_overlays() + . = ..() var/mutable_appearance/body_overlay = mutable_appearance('modular_citadel/icons/obj/guns/cit_guns.dmi', "AM4-Body") if(body_color) body_overlay.color = body_color - cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other - add_overlay(body_overlay) - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands() + . += body_overlay + /obj/item/gun/ballistic/automatic/AM4B/AltClick(mob/living/user) . = ..() if(!in_range(src, user)) //Basic checks to prevent abuse diff --git a/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm b/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm index 3c0a47bfd7..c4cf8fc00f 100644 --- a/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm +++ b/modular_citadel/code/modules/projectiles/guns/ballistic/spinfusor.dm @@ -55,8 +55,7 @@ /obj/item/gun/ballistic/automatic/spinfusor/attack_self(mob/living/user) return //caseless rounds are too glitchy to unload properly. Best to make it so that you cannot remove disks from the spinfusor -/obj/item/gun/ballistic/automatic/spinfusor/update_icon() - ..() +/obj/item/gun/ballistic/automatic/spinfusor/update_icon_state() icon_state = "spinfusor[magazine ? "-[get_ammo(1)]" : ""]" /obj/item/ammo_box/aspinfusor diff --git a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm index 49d48e0000..65609f5830 100644 --- a/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm +++ b/modular_citadel/code/modules/projectiles/guns/energy/energy_gun.dm @@ -14,16 +14,16 @@ obj/item/gun/energy/e_gun/cx flight_y_offset = 10 var/body_color = "#252528" -obj/item/gun/energy/e_gun/cx/update_icon() - ..() +obj/item/gun/energy/e_gun/cx/ComponentInitialize() + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + +obj/item/gun/energy/e_gun/cx/update_overlays() + . = ..() var/mutable_appearance/body_overlay = mutable_appearance('modular_citadel/icons/obj/guns/cit_guns.dmi', "cxegun_body") if(body_color) body_overlay.color = body_color - add_overlay(body_overlay) - - if(ismob(loc)) - var/mob/M = loc - M.update_inv_hands() + . += body_overlay obj/item/gun/energy/e_gun/cx/AltClick(mob/living/user) . = ..() diff --git a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm index 03a124e306..e81c7c18d3 100644 --- a/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm +++ b/modular_citadel/code/modules/projectiles/guns/pumpenergy.dm @@ -12,7 +12,7 @@ /obj/item/gun/energy/pumpaction/emp_act(severity) //makes it not rack itself when emp'd cell.use(round(cell.charge / severity)) - chambered = 0 //we empty the chamber + chambered = null //we empty the chamber update_icon() /obj/item/gun/energy/pumpaction/process() //makes it not rack itself when self-charging @@ -20,7 +20,7 @@ charge_tick++ if(charge_tick < charge_delay) return - charge_tick = 0 + charge_tick = null if(selfcharge == EGUN_SELFCHARGE_BORG) var/atom/owner = loc if(istype(owner, /obj/item/robot_module)) @@ -44,7 +44,7 @@ if(chambered && !chambered.BB) //if BB is null, i.e the shot has been fired... var/obj/item/ammo_casing/energy/shot = chambered cell.use(shot.e_cost)//... drain the cell cell - chambered = 0 //either way, released the prepared shot + chambered = null //either way, released the prepared shot /obj/item/gun/energy/pumpaction/post_set_firemode() var/has_shot = chambered @@ -52,13 +52,13 @@ if(has_shot) recharge_newshot(TRUE) -/obj/item/gun/energy/pumpaction/update_icon() //adds racked indicators +/obj/item/gun/energy/pumpaction/update_overlays() //adds racked indicators ..() var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] if(chambered) - add_overlay("[icon_state]_rack_[shot.select_name]") + . += "[icon_state]_rack_[shot.select_name]" else - add_overlay("[icon_state]_rack_empty") + . += "[icon_state]_rack_empty" /obj/item/gun/energy/pumpaction/proc/pump(mob/M) //pumping proc. Checks if the gun is empty and plays a different sound if it is. var/obj/item/ammo_casing/energy/shot = ammo_type[current_firemode_index] diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm index 37ec1ee69f..f3059a480a 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/SDGF.dm @@ -63,7 +63,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING startHunger = M.nutrition 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) + candies = pollGhostCandidates("Do you want to play as [M]'s defective clone? (Don't ERP without permission from the original)", ignore_category = POLL_IGNORE_CLONE) 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! @@ -112,7 +112,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.visible_message("[M] suddenly shudders, and splits into two identical twins!") SM.copy_languages(M, LANGUAGE_MIND) playerClone = TRUE - M.next_move_modifier = 1 + M.action_cooldown_mod = 1 M.adjust_nutrition(-500) //Damage the clone @@ -154,7 +154,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING 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!! + M.action_cooldown_mod += 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.adjust_nutrition(M.nutrition/2) @@ -164,7 +164,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING 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.set_nutrition(15)//YOU BEST BE EATTING AFTER THIS YOU CUTIE - M.next_move_modifier -= 4 + M.action_cooldown_mod -= 4 to_chat(M, "Your body splits away from the cell clone of yourself, leaving you with a drained and hollow feeling inside.") //clone @@ -195,14 +195,14 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING if (playerClone == TRUE)//If the player made a clone with it, then thats all they get. playerClone = FALSE return - if (M.next_move_modifier == 4 && !M.has_status_effect(/datum/status_effect/chem/SGDF))//checks if they're ingested over 20u of the stuff, but fell short of the required 30u to make a clone. + if (M.action_cooldown_mod == 4 && !M.has_status_effect(/datum/status_effect/chem/SGDF))//checks if they're ingested over 20u of the stuff, but fell short of the required 30u to make a clone. to_chat(M, "You feel the cells begin to merge with your body, unable to reach nucleation, they instead merge with your body, healing any wounds.") M.adjustCloneLoss(-10, 0) //I don't want to make Rezadone obsolete. M.adjustBruteLoss(-25, 0)// Note that this takes a long time to apply and makes you fat and useless when it's in you, I don't think this small burst of healing will be useful considering how long it takes to get there. M.adjustFireLoss(-25, 0) M.blood_volume += 250 M.heal_bodypart_damage(1,1) - M.next_move_modifier = 1 + M.action_cooldown_mod = 1 if (M.nutrition < 1500) 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. @@ -211,7 +211,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING M.adjustBruteLoss(-10, 0) M.adjustFireLoss(-10, 0) M.blood_volume += 100 - M.next_move_modifier = 1 + M.action_cooldown_mod = 1 if (M.nutrition < 1500) M.adjust_nutrition(500) @@ -325,7 +325,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING 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!! + M.action_cooldown_mod = 4//If this makes you fast then please fix it, it should make you slow!! if(51 to 73) M.adjust_nutrition(M.nutrition/2) if(74) @@ -339,7 +339,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING 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.set_nutrition(startHunger - 500) //YOU BEST BE RUNNING AWAY AFTER THIS YOU BADDIE - M.next_move_modifier = 1 + M.action_cooldown_mod = 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!") M.emote("scream") diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm index ca6bb302da..a6a9d7a85f 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/healing.dm @@ -200,17 +200,17 @@ /datum/reagent/fermi/zeolites name = "Artificial Zeolites" - description = "Lab made Zeolite, used to clear radiation form people and items alike! Splashing just a small amounts(5u) onto any item can clear away large amouts of contamination." + description = "Lab made Zeolite, used to clear radiation from people and items alike! Splashing just a small amount(5u) onto any item can clear away large amounts of contamination." pH = 8 color = "#FFDADA" - metabolization_rate = 8 * REAGENTS_METABOLISM //Lastes not long in body but heals a lot! + metabolization_rate = 8 * REAGENTS_METABOLISM //Metabolizes fast but heals a lot! value = REAGENT_VALUE_COMMON /datum/reagent/fermi/zeolites/on_mob_life(mob/living/carbon/M) var/datum/component/radioactive/contamination = M.GetComponent(/datum/component/radioactive) if(M.radiation > 0) M.radiation -= min(M.radiation, 60) - if(contamination.strength > 0) + if(contamination && contamination.strength > 0) contamination.strength -= min(contamination.strength, 100) ..() diff --git a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm index b2c80e4a16..39ba69bd61 100644 --- a/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm +++ b/modular_citadel/code/modules/reagents/chemistry/recipes/fermi.dm @@ -165,7 +165,7 @@ if(amount_to_spawn <= 0) amount_to_spawn = 1 for(var/i in 1 to amount_to_spawn) - var/mob/living/simple_animal/slime/S = new(T,"green") + var/mob/living/simple_animal/slime/S = new(T,"pyrite") S.damage_coeff = list(BRUTE = 0.9 , BURN = 2, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) S.name = "Living teratoma" S.real_name = "Living teratoma" @@ -178,7 +178,7 @@ name = "Sucubus milk" id = /datum/reagent/fermi/breast_enlarger results = list(/datum/reagent/fermi/breast_enlarger = 8) - required_reagents = list(/datum/reagent/medicine/salglu_solution = 1, /datum/reagent/consumable/milk = 1, /datum/reagent/medicine/synthflesh = 2, /datum/reagent/silicon = 3, /datum/reagent/drug/aphrodisiac = 3) + required_reagents = list(/datum/reagent/medicine/salglu_solution = 2, /datum/reagent/consumable/milk = 1, /datum/reagent/medicine/synthflesh = 2, /datum/reagent/silicon = 5) mix_message = "the reaction gives off a mist of milk." //FermiChem vars: OptimalTempMin = 200 @@ -218,7 +218,7 @@ name = "Incubus draft" id = /datum/reagent/fermi/penis_enlarger results = list(/datum/reagent/fermi/penis_enlarger = 8) - required_reagents = list(/datum/reagent/blood = 5, /datum/reagent/medicine/synthflesh = 2, /datum/reagent/carbon = 2, /datum/reagent/drug/aphrodisiac = 2, /datum/reagent/medicine/salglu_solution = 1) + required_reagents = list(/datum/reagent/blood = 5, /datum/reagent/medicine/synthflesh = 2, /datum/reagent/carbon = 5, /datum/reagent/medicine/salglu_solution = 2) mix_message = "the reaction gives off a spicy mist." //FermiChem vars: OptimalTempMin = 200 @@ -384,7 +384,7 @@ name = "Furranium" id = /datum/reagent/fermi/furranium results = list(/datum/reagent/fermi/furranium = 5) - required_reagents = list(/datum/reagent/drug/aphrodisiac = 1, /datum/reagent/moonsugar = 1, /datum/reagent/silver = 2, /datum/reagent/medicine/salglu_solution = 1) + required_reagents = list(/datum/reagent/pax/catnip = 1, /datum/reagent/silver = 2, /datum/reagent/medicine/salglu_solution = 2) mix_message = "You think you can hear a howl come from the beaker." //FermiChem vars: OptimalTempMin = 350 @@ -402,10 +402,6 @@ FermiChem = TRUE PurityMin = 0.3 -/datum/chemical_reaction/fermi/furranium/organic - id = "furranium_organic" - required_reagents = list(/datum/reagent/drug/aphrodisiac = 1, /datum/reagent/pax/catnip = 1, /datum/reagent/silver = 2, /datum/reagent/medicine/salglu_solution = 1) - //FOR INSTANT REACTIONS - DO NOT MULTIPLY LIMIT BY 10. //There's a weird rounding error or something ugh. @@ -607,4 +603,4 @@ ThermicConstant = 0 HIonRelease = 0.01 RateUpLim = 15 - FermiChem = TRUE \ No newline at end of file + FermiChem = TRUE diff --git a/modular_citadel/code/modules/reagents/objects/clothes.dm b/modular_citadel/code/modules/reagents/objects/clothes.dm index de4cb38360..ab4d49c56f 100644 --- a/modular_citadel/code/modules/reagents/objects/clothes.dm +++ b/modular_citadel/code/modules/reagents/objects/clothes.dm @@ -9,7 +9,7 @@ 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! -/obj/item/clothing/head/hattip/attack_hand(mob/user) +/obj/item/clothing/head/hattip/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(iscarbon(user)) var/mob/living/carbon/C = user if(is_ninja(C)) diff --git a/modular_citadel/code/modules/reagents/objects/items.dm b/modular_citadel/code/modules/reagents/objects/items.dm index 1924e7ee00..f4316b3c58 100644 --- a/modular_citadel/code/modules/reagents/objects/items.dm +++ b/modular_citadel/code/modules/reagents/objects/items.dm @@ -9,7 +9,7 @@ w_class = WEIGHT_CLASS_TINY //A little janky with pockets -/obj/item/fermichem/pHbooklet/attack_hand(mob/user) +/obj/item/fermichem/pHbooklet/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) if(user.get_held_index_of_item(src))//Does this check pockets too..? if(numberOfPages == 50) icon_state = "pHbookletOpen" diff --git a/modular_citadel/icons/mob/citadel_refs/furry_parts_greyscale.dmi b/modular_citadel/icons/mob/citadel_refs/furry_parts_greyscale.dmi deleted file mode 100644 index c8d5ceb0a6..0000000000 Binary files a/modular_citadel/icons/mob/citadel_refs/furry_parts_greyscale.dmi and /dev/null differ diff --git a/modular_citadel/icons/mob/mam_snouts.dmi b/modular_citadel/icons/mob/mam_snouts.dmi index ab1a4654b4..4f6682f789 100644 Binary files a/modular_citadel/icons/mob/mam_snouts.dmi and b/modular_citadel/icons/mob/mam_snouts.dmi differ diff --git a/modular_citadel/icons/mob/mutant_bodyparts.dmi b/modular_citadel/icons/mob/mutant_bodyparts.dmi deleted file mode 100644 index 95b121b453..0000000000 Binary files a/modular_citadel/icons/mob/mutant_bodyparts.dmi and /dev/null differ diff --git a/modular_citadel/icons/mob/widerobot.dmi b/modular_citadel/icons/mob/widerobot.dmi index 50c29bb75f..29eb35c715 100644 Binary files a/modular_citadel/icons/mob/widerobot.dmi and b/modular_citadel/icons/mob/widerobot.dmi differ diff --git a/rust_g.dll b/rust_g.dll old mode 100644 new mode 100755 index f4be6e730a..8cd62b8ca4 Binary files a/rust_g.dll and b/rust_g.dll differ diff --git a/sound/ambience/antag/ecult_op.ogg b/sound/ambience/antag/ecult_op.ogg new file mode 100644 index 0000000000..9944e833a6 Binary files /dev/null and b/sound/ambience/antag/ecult_op.ogg differ diff --git a/sound/ambience/LICENSE.txt b/sound/ambience/license.txt similarity index 52% rename from sound/ambience/LICENSE.txt rename to sound/ambience/license.txt index 5fb0ece74d..51f5a7e2bc 100644 --- a/sound/ambience/LICENSE.txt +++ b/sound/ambience/license.txt @@ -4,3 +4,8 @@ ambidet2.ogg is Night on the Docks, Piano by Kevin Macleod. It has been licensed It has been cropped for use ingame, and also fades in. aurora_caelus.ogg is Music for Manatees, by Kevin Macleod. It has been licensed under CC-BY 3.0 license. It has been cropped for use ingame, and also fades out. +title1.ogg is Flip-Flap created by Jakub "AceMan" SzelÄ…g and taken from http://www.modules.pl/?id=module&mod=453 +title2.ogg is Robocop Theme (gameboy) remixed by Eric Schumacker +title3.ogg is Tintin On The Moon remixed by Cuboos https://tgstation13.org/phpBB/viewtopic.php?f=10&t=2157 (assumed CC under allowing it to be submitted to the github, see thread) + +CC-BY 3.0: http://creativecommons.org/licenses/by/3.0/ diff --git a/sound/effects/butcher.ogg b/sound/effects/butcher.ogg new file mode 100644 index 0000000000..2e4a0d2ddc Binary files /dev/null and b/sound/effects/butcher.ogg differ diff --git a/sound/effects/creak1.ogg b/sound/effects/creak1.ogg new file mode 100644 index 0000000000..0cad4802ff Binary files /dev/null and b/sound/effects/creak1.ogg differ diff --git a/sound/effects/creak2.ogg b/sound/effects/creak2.ogg new file mode 100644 index 0000000000..707bf39e33 Binary files /dev/null and b/sound/effects/creak2.ogg differ diff --git a/sound/effects/creak3.ogg b/sound/effects/creak3.ogg new file mode 100644 index 0000000000..88ff37a339 Binary files /dev/null and b/sound/effects/creak3.ogg differ diff --git a/sound/effects/dismember.ogg b/sound/effects/dismember.ogg new file mode 100644 index 0000000000..f5015ad961 Binary files /dev/null and b/sound/effects/dismember.ogg differ diff --git a/sound/effects/explosioncreak1.ogg b/sound/effects/explosioncreak1.ogg new file mode 100644 index 0000000000..474f5febb5 Binary files /dev/null and b/sound/effects/explosioncreak1.ogg differ diff --git a/sound/effects/explosioncreak2.ogg b/sound/effects/explosioncreak2.ogg new file mode 100644 index 0000000000..75d323eb06 Binary files /dev/null and b/sound/effects/explosioncreak2.ogg differ diff --git a/sound/effects/footstep/rustystep1.ogg b/sound/effects/footstep/rustystep1.ogg new file mode 100644 index 0000000000..bf90d52779 Binary files /dev/null and b/sound/effects/footstep/rustystep1.ogg differ diff --git a/sound/effects/license.txt b/sound/effects/license.txt new file mode 100644 index 0000000000..c928a9872f --- /dev/null +++ b/sound/effects/license.txt @@ -0,0 +1,2 @@ +hit_punch.ogg and hit_kick.ogg are made by Taira Komori +(https://taira-komori.jpn.org/freesounden.html) diff --git a/sound/effects/meatslap.ogg b/sound/effects/meatslap.ogg new file mode 100644 index 0000000000..3d8ea7df1a Binary files /dev/null and b/sound/effects/meatslap.ogg differ diff --git a/sound/effects/wounds/blood1.ogg b/sound/effects/wounds/blood1.ogg new file mode 100644 index 0000000000..88c76eb9e3 Binary files /dev/null and b/sound/effects/wounds/blood1.ogg differ diff --git a/sound/effects/wounds/blood2.ogg b/sound/effects/wounds/blood2.ogg new file mode 100644 index 0000000000..0fb165108a Binary files /dev/null and b/sound/effects/wounds/blood2.ogg differ diff --git a/sound/effects/wounds/blood3.ogg b/sound/effects/wounds/blood3.ogg new file mode 100644 index 0000000000..f6024a5ff6 Binary files /dev/null and b/sound/effects/wounds/blood3.ogg differ diff --git a/sound/effects/wounds/crack1.ogg b/sound/effects/wounds/crack1.ogg new file mode 100644 index 0000000000..aa3bf0ab01 Binary files /dev/null and b/sound/effects/wounds/crack1.ogg differ diff --git a/sound/effects/wounds/crack2.ogg b/sound/effects/wounds/crack2.ogg new file mode 100644 index 0000000000..cef226c98b Binary files /dev/null and b/sound/effects/wounds/crack2.ogg differ diff --git a/sound/effects/wounds/crackandbleed.ogg b/sound/effects/wounds/crackandbleed.ogg new file mode 100644 index 0000000000..ea07f13d48 Binary files /dev/null and b/sound/effects/wounds/crackandbleed.ogg differ diff --git a/sound/effects/wounds/pierce1.ogg b/sound/effects/wounds/pierce1.ogg new file mode 100644 index 0000000000..cd7b7c3961 Binary files /dev/null and b/sound/effects/wounds/pierce1.ogg differ diff --git a/sound/effects/wounds/pierce2.ogg b/sound/effects/wounds/pierce2.ogg new file mode 100644 index 0000000000..4977cab299 Binary files /dev/null and b/sound/effects/wounds/pierce2.ogg differ diff --git a/sound/effects/wounds/pierce3.ogg b/sound/effects/wounds/pierce3.ogg new file mode 100644 index 0000000000..e81700b134 Binary files /dev/null and b/sound/effects/wounds/pierce3.ogg differ diff --git a/sound/effects/wounds/sizzle1.ogg b/sound/effects/wounds/sizzle1.ogg new file mode 100644 index 0000000000..4a3d229018 Binary files /dev/null and b/sound/effects/wounds/sizzle1.ogg differ diff --git a/sound/effects/wounds/sizzle2.ogg b/sound/effects/wounds/sizzle2.ogg new file mode 100644 index 0000000000..409206e58a Binary files /dev/null and b/sound/effects/wounds/sizzle2.ogg differ diff --git a/sound/machines/clockcult/ratvar_scream.ogg b/sound/machines/clockcult/ratvar_scream.ogg new file mode 100644 index 0000000000..5c0c0a0d63 Binary files /dev/null and b/sound/machines/clockcult/ratvar_scream.ogg differ diff --git a/sound/machines/sm/accent/delam/1.ogg b/sound/machines/sm/accent/delam/1.ogg new file mode 100644 index 0000000000..75c79f89ab Binary files /dev/null and b/sound/machines/sm/accent/delam/1.ogg differ diff --git a/sound/machines/sm/accent/delam/10.ogg b/sound/machines/sm/accent/delam/10.ogg new file mode 100644 index 0000000000..c87b63b526 Binary files /dev/null and b/sound/machines/sm/accent/delam/10.ogg differ diff --git a/sound/machines/sm/accent/delam/11.ogg b/sound/machines/sm/accent/delam/11.ogg new file mode 100644 index 0000000000..c7f678245b Binary files /dev/null and b/sound/machines/sm/accent/delam/11.ogg differ diff --git a/sound/machines/sm/accent/delam/12.ogg b/sound/machines/sm/accent/delam/12.ogg new file mode 100644 index 0000000000..a395942183 Binary files /dev/null and b/sound/machines/sm/accent/delam/12.ogg differ diff --git a/sound/machines/sm/accent/delam/13.ogg b/sound/machines/sm/accent/delam/13.ogg new file mode 100644 index 0000000000..934f17947d Binary files /dev/null and b/sound/machines/sm/accent/delam/13.ogg differ diff --git a/sound/machines/sm/accent/delam/14.ogg b/sound/machines/sm/accent/delam/14.ogg new file mode 100644 index 0000000000..4175e5b947 Binary files /dev/null and b/sound/machines/sm/accent/delam/14.ogg differ diff --git a/sound/machines/sm/accent/delam/15.ogg b/sound/machines/sm/accent/delam/15.ogg new file mode 100644 index 0000000000..dcf73deb84 Binary files /dev/null and b/sound/machines/sm/accent/delam/15.ogg differ diff --git a/sound/machines/sm/accent/delam/16.ogg b/sound/machines/sm/accent/delam/16.ogg new file mode 100644 index 0000000000..20bc19399b Binary files /dev/null and b/sound/machines/sm/accent/delam/16.ogg differ diff --git a/sound/machines/sm/accent/delam/17.ogg b/sound/machines/sm/accent/delam/17.ogg new file mode 100644 index 0000000000..b517fb3d3d Binary files /dev/null and b/sound/machines/sm/accent/delam/17.ogg differ diff --git a/sound/machines/sm/accent/delam/18.ogg b/sound/machines/sm/accent/delam/18.ogg new file mode 100644 index 0000000000..4ef138d27a Binary files /dev/null and b/sound/machines/sm/accent/delam/18.ogg differ diff --git a/sound/machines/sm/accent/delam/19.ogg b/sound/machines/sm/accent/delam/19.ogg new file mode 100644 index 0000000000..f638a6971b Binary files /dev/null and b/sound/machines/sm/accent/delam/19.ogg differ diff --git a/sound/machines/sm/accent/delam/2.ogg b/sound/machines/sm/accent/delam/2.ogg new file mode 100644 index 0000000000..5b480daa2e Binary files /dev/null and b/sound/machines/sm/accent/delam/2.ogg differ diff --git a/sound/machines/sm/accent/delam/20.ogg b/sound/machines/sm/accent/delam/20.ogg new file mode 100644 index 0000000000..6072bc6227 Binary files /dev/null and b/sound/machines/sm/accent/delam/20.ogg differ diff --git a/sound/machines/sm/accent/delam/21.ogg b/sound/machines/sm/accent/delam/21.ogg new file mode 100644 index 0000000000..1223dd946d Binary files /dev/null and b/sound/machines/sm/accent/delam/21.ogg differ diff --git a/sound/machines/sm/accent/delam/22.ogg b/sound/machines/sm/accent/delam/22.ogg new file mode 100644 index 0000000000..9ccfb9b55a Binary files /dev/null and b/sound/machines/sm/accent/delam/22.ogg differ diff --git a/sound/machines/sm/accent/delam/23.ogg b/sound/machines/sm/accent/delam/23.ogg new file mode 100644 index 0000000000..6399a8376a Binary files /dev/null and b/sound/machines/sm/accent/delam/23.ogg differ diff --git a/sound/machines/sm/accent/delam/24.ogg b/sound/machines/sm/accent/delam/24.ogg new file mode 100644 index 0000000000..b51d359807 Binary files /dev/null and b/sound/machines/sm/accent/delam/24.ogg differ diff --git a/sound/machines/sm/accent/delam/25.ogg b/sound/machines/sm/accent/delam/25.ogg new file mode 100644 index 0000000000..823f22f136 Binary files /dev/null and b/sound/machines/sm/accent/delam/25.ogg differ diff --git a/sound/machines/sm/accent/delam/26.ogg b/sound/machines/sm/accent/delam/26.ogg new file mode 100644 index 0000000000..24b2a2f040 Binary files /dev/null and b/sound/machines/sm/accent/delam/26.ogg differ diff --git a/sound/machines/sm/accent/delam/27.ogg b/sound/machines/sm/accent/delam/27.ogg new file mode 100644 index 0000000000..4b4b145b7b Binary files /dev/null and b/sound/machines/sm/accent/delam/27.ogg differ diff --git a/sound/machines/sm/accent/delam/28.ogg b/sound/machines/sm/accent/delam/28.ogg new file mode 100644 index 0000000000..7bc71bf0e6 Binary files /dev/null and b/sound/machines/sm/accent/delam/28.ogg differ diff --git a/sound/machines/sm/accent/delam/29.ogg b/sound/machines/sm/accent/delam/29.ogg new file mode 100644 index 0000000000..7fec2f271c Binary files /dev/null and b/sound/machines/sm/accent/delam/29.ogg differ diff --git a/sound/machines/sm/accent/delam/3.ogg b/sound/machines/sm/accent/delam/3.ogg new file mode 100644 index 0000000000..5b57cc2707 Binary files /dev/null and b/sound/machines/sm/accent/delam/3.ogg differ diff --git a/sound/machines/sm/accent/delam/30.ogg b/sound/machines/sm/accent/delam/30.ogg new file mode 100644 index 0000000000..ed1ec7d89f Binary files /dev/null and b/sound/machines/sm/accent/delam/30.ogg differ diff --git a/sound/machines/sm/accent/delam/31.ogg b/sound/machines/sm/accent/delam/31.ogg new file mode 100644 index 0000000000..0baa82e246 Binary files /dev/null and b/sound/machines/sm/accent/delam/31.ogg differ diff --git a/sound/machines/sm/accent/delam/32.ogg b/sound/machines/sm/accent/delam/32.ogg new file mode 100644 index 0000000000..e925b32d67 Binary files /dev/null and b/sound/machines/sm/accent/delam/32.ogg differ diff --git a/sound/machines/sm/accent/delam/33.ogg b/sound/machines/sm/accent/delam/33.ogg new file mode 100644 index 0000000000..9ddec0e84a Binary files /dev/null and b/sound/machines/sm/accent/delam/33.ogg differ diff --git a/sound/machines/sm/accent/delam/4.ogg b/sound/machines/sm/accent/delam/4.ogg new file mode 100644 index 0000000000..aa4f4da071 Binary files /dev/null and b/sound/machines/sm/accent/delam/4.ogg differ diff --git a/sound/machines/sm/accent/delam/5.ogg b/sound/machines/sm/accent/delam/5.ogg new file mode 100644 index 0000000000..be438f6f15 Binary files /dev/null and b/sound/machines/sm/accent/delam/5.ogg differ diff --git a/sound/machines/sm/accent/delam/6.ogg b/sound/machines/sm/accent/delam/6.ogg new file mode 100644 index 0000000000..b89d52a564 Binary files /dev/null and b/sound/machines/sm/accent/delam/6.ogg differ diff --git a/sound/machines/sm/accent/delam/7.ogg b/sound/machines/sm/accent/delam/7.ogg new file mode 100644 index 0000000000..3a9cfc62ca Binary files /dev/null and b/sound/machines/sm/accent/delam/7.ogg differ diff --git a/sound/machines/sm/accent/delam/8.ogg b/sound/machines/sm/accent/delam/8.ogg new file mode 100644 index 0000000000..7bc0a727fa Binary files /dev/null and b/sound/machines/sm/accent/delam/8.ogg differ diff --git a/sound/machines/sm/accent/delam/9.ogg b/sound/machines/sm/accent/delam/9.ogg new file mode 100644 index 0000000000..5c1bd37405 Binary files /dev/null and b/sound/machines/sm/accent/delam/9.ogg differ diff --git a/sound/machines/sm/accent/normal/1.ogg b/sound/machines/sm/accent/normal/1.ogg new file mode 100644 index 0000000000..e92beed7fe Binary files /dev/null and b/sound/machines/sm/accent/normal/1.ogg differ diff --git a/sound/machines/sm/accent/normal/10.ogg b/sound/machines/sm/accent/normal/10.ogg new file mode 100644 index 0000000000..9efb616f0b Binary files /dev/null and b/sound/machines/sm/accent/normal/10.ogg differ diff --git a/sound/machines/sm/accent/normal/11.ogg b/sound/machines/sm/accent/normal/11.ogg new file mode 100644 index 0000000000..2af0981ef1 Binary files /dev/null and b/sound/machines/sm/accent/normal/11.ogg differ diff --git a/sound/machines/sm/accent/normal/12.ogg b/sound/machines/sm/accent/normal/12.ogg new file mode 100644 index 0000000000..2fab78b02d Binary files /dev/null and b/sound/machines/sm/accent/normal/12.ogg differ diff --git a/sound/machines/sm/accent/normal/13.ogg b/sound/machines/sm/accent/normal/13.ogg new file mode 100644 index 0000000000..784e84e4a8 Binary files /dev/null and b/sound/machines/sm/accent/normal/13.ogg differ diff --git a/sound/machines/sm/accent/normal/14.ogg b/sound/machines/sm/accent/normal/14.ogg new file mode 100644 index 0000000000..af170394dd Binary files /dev/null and b/sound/machines/sm/accent/normal/14.ogg differ diff --git a/sound/machines/sm/accent/normal/15.ogg b/sound/machines/sm/accent/normal/15.ogg new file mode 100644 index 0000000000..05c88c6b29 Binary files /dev/null and b/sound/machines/sm/accent/normal/15.ogg differ diff --git a/sound/machines/sm/accent/normal/16.ogg b/sound/machines/sm/accent/normal/16.ogg new file mode 100644 index 0000000000..46b0e33980 Binary files /dev/null and b/sound/machines/sm/accent/normal/16.ogg differ diff --git a/sound/machines/sm/accent/normal/17.ogg b/sound/machines/sm/accent/normal/17.ogg new file mode 100644 index 0000000000..e432b2ee02 Binary files /dev/null and b/sound/machines/sm/accent/normal/17.ogg differ diff --git a/sound/machines/sm/accent/normal/18.ogg b/sound/machines/sm/accent/normal/18.ogg new file mode 100644 index 0000000000..1e0e91abc8 Binary files /dev/null and b/sound/machines/sm/accent/normal/18.ogg differ diff --git a/sound/machines/sm/accent/normal/19.ogg b/sound/machines/sm/accent/normal/19.ogg new file mode 100644 index 0000000000..31de063e02 Binary files /dev/null and b/sound/machines/sm/accent/normal/19.ogg differ diff --git a/sound/machines/sm/accent/normal/2.ogg b/sound/machines/sm/accent/normal/2.ogg new file mode 100644 index 0000000000..05e3c9ff17 Binary files /dev/null and b/sound/machines/sm/accent/normal/2.ogg differ diff --git a/sound/machines/sm/accent/normal/20.ogg b/sound/machines/sm/accent/normal/20.ogg new file mode 100644 index 0000000000..36810bd8f1 Binary files /dev/null and b/sound/machines/sm/accent/normal/20.ogg differ diff --git a/sound/machines/sm/accent/normal/21.ogg b/sound/machines/sm/accent/normal/21.ogg new file mode 100644 index 0000000000..306e8856e5 Binary files /dev/null and b/sound/machines/sm/accent/normal/21.ogg differ diff --git a/sound/machines/sm/accent/normal/22.ogg b/sound/machines/sm/accent/normal/22.ogg new file mode 100644 index 0000000000..38286aa98b Binary files /dev/null and b/sound/machines/sm/accent/normal/22.ogg differ diff --git a/sound/machines/sm/accent/normal/23.ogg b/sound/machines/sm/accent/normal/23.ogg new file mode 100644 index 0000000000..89f85fed91 Binary files /dev/null and b/sound/machines/sm/accent/normal/23.ogg differ diff --git a/sound/machines/sm/accent/normal/24.ogg b/sound/machines/sm/accent/normal/24.ogg new file mode 100644 index 0000000000..7c12a3e768 Binary files /dev/null and b/sound/machines/sm/accent/normal/24.ogg differ diff --git a/sound/machines/sm/accent/normal/25.ogg b/sound/machines/sm/accent/normal/25.ogg new file mode 100644 index 0000000000..f89175ceb1 Binary files /dev/null and b/sound/machines/sm/accent/normal/25.ogg differ diff --git a/sound/machines/sm/accent/normal/26.ogg b/sound/machines/sm/accent/normal/26.ogg new file mode 100644 index 0000000000..9efd1d8ef3 Binary files /dev/null and b/sound/machines/sm/accent/normal/26.ogg differ diff --git a/sound/machines/sm/accent/normal/27.ogg b/sound/machines/sm/accent/normal/27.ogg new file mode 100644 index 0000000000..1fb1edbb5a Binary files /dev/null and b/sound/machines/sm/accent/normal/27.ogg differ diff --git a/sound/machines/sm/accent/normal/28.ogg b/sound/machines/sm/accent/normal/28.ogg new file mode 100644 index 0000000000..890c5ea429 Binary files /dev/null and b/sound/machines/sm/accent/normal/28.ogg differ diff --git a/sound/machines/sm/accent/normal/29.ogg b/sound/machines/sm/accent/normal/29.ogg new file mode 100644 index 0000000000..cd2aa40714 Binary files /dev/null and b/sound/machines/sm/accent/normal/29.ogg differ diff --git a/sound/machines/sm/accent/normal/3.ogg b/sound/machines/sm/accent/normal/3.ogg new file mode 100644 index 0000000000..38de5571a4 Binary files /dev/null and b/sound/machines/sm/accent/normal/3.ogg differ diff --git a/sound/machines/sm/accent/normal/30.ogg b/sound/machines/sm/accent/normal/30.ogg new file mode 100644 index 0000000000..87d1782768 Binary files /dev/null and b/sound/machines/sm/accent/normal/30.ogg differ diff --git a/sound/machines/sm/accent/normal/31.ogg b/sound/machines/sm/accent/normal/31.ogg new file mode 100644 index 0000000000..9ce3eeb72e Binary files /dev/null and b/sound/machines/sm/accent/normal/31.ogg differ diff --git a/sound/machines/sm/accent/normal/32.ogg b/sound/machines/sm/accent/normal/32.ogg new file mode 100644 index 0000000000..26ca056142 Binary files /dev/null and b/sound/machines/sm/accent/normal/32.ogg differ diff --git a/sound/machines/sm/accent/normal/33.ogg b/sound/machines/sm/accent/normal/33.ogg new file mode 100644 index 0000000000..24964c1ce9 Binary files /dev/null and b/sound/machines/sm/accent/normal/33.ogg differ diff --git a/sound/machines/sm/accent/normal/4.ogg b/sound/machines/sm/accent/normal/4.ogg new file mode 100644 index 0000000000..2e71e976e8 Binary files /dev/null and b/sound/machines/sm/accent/normal/4.ogg differ diff --git a/sound/machines/sm/accent/normal/5.ogg b/sound/machines/sm/accent/normal/5.ogg new file mode 100644 index 0000000000..04852e10f2 Binary files /dev/null and b/sound/machines/sm/accent/normal/5.ogg differ diff --git a/sound/machines/sm/accent/normal/6.ogg b/sound/machines/sm/accent/normal/6.ogg new file mode 100644 index 0000000000..bf06c06bbe Binary files /dev/null and b/sound/machines/sm/accent/normal/6.ogg differ diff --git a/sound/machines/sm/accent/normal/7.ogg b/sound/machines/sm/accent/normal/7.ogg new file mode 100644 index 0000000000..d29821701f Binary files /dev/null and b/sound/machines/sm/accent/normal/7.ogg differ diff --git a/sound/machines/sm/accent/normal/8.ogg b/sound/machines/sm/accent/normal/8.ogg new file mode 100644 index 0000000000..0b94b9dbe0 Binary files /dev/null and b/sound/machines/sm/accent/normal/8.ogg differ diff --git a/sound/machines/sm/accent/normal/9.ogg b/sound/machines/sm/accent/normal/9.ogg new file mode 100644 index 0000000000..545b038be1 Binary files /dev/null and b/sound/machines/sm/accent/normal/9.ogg differ diff --git a/sound/machines/sm/loops/calm.ogg b/sound/machines/sm/loops/calm.ogg new file mode 100644 index 0000000000..cee14fcd13 Binary files /dev/null and b/sound/machines/sm/loops/calm.ogg differ diff --git a/sound/machines/sm/loops/delamming.ogg b/sound/machines/sm/loops/delamming.ogg new file mode 100644 index 0000000000..7d79f0e3c4 Binary files /dev/null and b/sound/machines/sm/loops/delamming.ogg differ diff --git a/sound/machines/sm/supermatter1.ogg b/sound/machines/sm/supermatter1.ogg index 1860e78800..be5185009e 100644 Binary files a/sound/machines/sm/supermatter1.ogg and b/sound/machines/sm/supermatter1.ogg differ diff --git a/sound/machines/sm/supermatter2.ogg b/sound/machines/sm/supermatter2.ogg index fb2d39fe26..5c98d28ed1 100644 Binary files a/sound/machines/sm/supermatter2.ogg and b/sound/machines/sm/supermatter2.ogg differ diff --git a/sound/machines/sm/supermatter3.ogg b/sound/machines/sm/supermatter3.ogg index 93ac3d505b..fb8e09166c 100644 Binary files a/sound/machines/sm/supermatter3.ogg and b/sound/machines/sm/supermatter3.ogg differ diff --git a/sound/magic/abomscream.ogg b/sound/magic/abomscream.ogg new file mode 100644 index 0000000000..4f450e05f7 Binary files /dev/null and b/sound/magic/abomscream.ogg differ diff --git a/sound/mecha/neostep1.ogg b/sound/mecha/neostep1.ogg new file mode 100644 index 0000000000..ce7f51ad23 Binary files /dev/null and b/sound/mecha/neostep1.ogg differ diff --git a/sound/mecha/neostep2.ogg b/sound/mecha/neostep2.ogg new file mode 100644 index 0000000000..e828d9eadd Binary files /dev/null and b/sound/mecha/neostep2.ogg differ diff --git a/sound/mecha/powerloader_step.ogg b/sound/mecha/powerloader_step.ogg new file mode 100644 index 0000000000..af427df865 Binary files /dev/null and b/sound/mecha/powerloader_step.ogg differ diff --git a/sound/music/twilight.ogg b/sound/music/twilight.ogg new file mode 100644 index 0000000000..635663314d Binary files /dev/null and b/sound/music/twilight.ogg differ diff --git a/sound/roundend/CitadelStationHasSeenBetterDays.ogg b/sound/roundend/CitadelStationHasSeenBetterDays.ogg new file mode 100644 index 0000000000..2fa0c5b33c Binary files /dev/null and b/sound/roundend/CitadelStationHasSeenBetterDays.ogg differ diff --git a/sound/voice/catpeople/distressed.ogg b/sound/voice/catpeople/distressed.ogg new file mode 100644 index 0000000000..cebe73dffc Binary files /dev/null and b/sound/voice/catpeople/distressed.ogg differ diff --git a/sound/voice/catpeople/license.txt b/sound/voice/catpeople/license.txt new file mode 100644 index 0000000000..7218480ddb --- /dev/null +++ b/sound/voice/catpeople/license.txt @@ -0,0 +1,2 @@ +distressed_cat.ogg from Cat annoyed meow / wail by jbierfeldt at https://freesound.org/people/jbierfeldt/sounds/440735/, chopped up and ogged +cat_puking.ogg from catpuking mp3 by NoiseCollector and Mocha the cat at https://freesound.org/people/NoiseCollector/sounds/80778/, chopped up, volume altered and ogged \ No newline at end of file diff --git a/sound/voice/catpeople/puking.ogg b/sound/voice/catpeople/puking.ogg new file mode 100644 index 0000000000..e19c10858f Binary files /dev/null and b/sound/voice/catpeople/puking.ogg differ diff --git a/sound/voice/slime_squish.ogg b/sound/voice/slime_squish.ogg new file mode 100644 index 0000000000..60e118e217 Binary files /dev/null and b/sound/voice/slime_squish.ogg differ diff --git a/sound/weapons/etherealhit.ogg b/sound/weapons/etherealhit.ogg new file mode 100644 index 0000000000..19da870961 Binary files /dev/null and b/sound/weapons/etherealhit.ogg differ diff --git a/sound/weapons/etherealmiss.ogg b/sound/weapons/etherealmiss.ogg new file mode 100644 index 0000000000..8feb7cdc91 Binary files /dev/null and b/sound/weapons/etherealmiss.ogg differ diff --git a/sound/weapons/guillotine.ogg b/sound/weapons/guillotine.ogg new file mode 100644 index 0000000000..f2647b43e3 Binary files /dev/null and b/sound/weapons/guillotine.ogg differ diff --git a/sound/weapons/shot.ogg b/sound/weapons/shot.ogg new file mode 100644 index 0000000000..6c57482973 Binary files /dev/null and b/sound/weapons/shot.ogg differ diff --git a/strings/abductee_objectives.txt b/strings/abductee_objectives.txt index 512fd2e60d..135bb7673b 100644 --- a/strings/abductee_objectives.txt +++ b/strings/abductee_objectives.txt @@ -13,7 +13,6 @@ You're throwing a huge rager. Make it as awesome as possible so the whole crew c The clown is not funny. You can do better! Steal his audience and make the crew laugh! You burn with passion for music. Share your vision. If anyone hates it, beat them on the head with your instrument! Go have a good conversation with the singularity/tesla/supermatter crystal. Bonus points if it responds. -You are pregnant and soon due. Find a safe place to deliver your baby. Expand the station. So much lies undiscovered. Look deeper into the machinations of the universe. Climb the corporate ladder all the way to the top! @@ -32,7 +31,7 @@ Flood the station's powernet with as much electricity as you can. Replace all the floor tiles with wood, carpeting, grass or bling. You must escape the station! Get the shuttle called! Don't allow anyone to be cloned. -The oxygen is killing them all and they don't even know it. Make sure no oxygen is on the station. +Their cold, mindless gaze pierce your soul. They see your every movements, it's merely a question of time before they try to control us further. Deactivate all cameras! Your body must be improved. Ingest as many drugs as you can. You are hungry. Eat as much food as you can find. You see you see what they cannot you see the open door you seeE you SEeEe you SEe yOU seEee SHOW THEM ALL diff --git a/strings/names/ethereal.txt b/strings/names/ethereal.txt new file mode 100644 index 0000000000..d3e6a26e6e --- /dev/null +++ b/strings/names/ethereal.txt @@ -0,0 +1,38 @@ +Aten +Apollo +Arche +Atlas +Eos +Halo +Kale +Nysa +Orion +Pallas +Rigel +Themis +Aurora +Andromeda +Lyra +Saggitarius +Crux +Canis +Cygnus +Corvus +Cepheus +Auriga +Corona +Aquilla +Serpens +Cetus +Puppis +Ophiuchus +Carina +Cassiopeia +Canes +Fornax +Berenices +Coma +Vela +Triangulum +Tau +Ceti \ No newline at end of file diff --git a/strings/round_start_sounds.txt b/strings/round_start_sounds.txt index c67bf6b4a6..177a3ea0a8 100644 --- a/strings/round_start_sounds.txt +++ b/strings/round_start_sounds.txt @@ -25,3 +25,4 @@ sound/music/rocketridersprayer.ogg sound/music/theend.ogg sound/music/flyinghigh.ogg sound/music/samsara.ogg +sound/music/twilight.ogg \ No newline at end of file diff --git a/strings/sillytips.txt b/strings/sillytips.txt index bc59a109f0..e6710de95e 100644 --- a/strings/sillytips.txt +++ b/strings/sillytips.txt @@ -25,6 +25,7 @@ This game is older than most of the people playing it. Do not go gentle into that good night. Flashbangs can weaken blob tiles, allowing for you and the crew to easily destroy them. Just the tip? +You can grab someone by clicking on them with the grab intent, then upgrade the grab by clicking on them once more. An aggressive grab will momentarily stun someone, allow you to place Mekhi on a table by clicking on it, or throw them by toggling on throwing. Some people are unable to read text on a game where half of it is based on text. As the Captain, you can use a whetstone to sharpen your fancy fountain pen for extra robustness. As the Lawyer, you are the last bastion of roleplay-focused jobs. Even the curator got a whip to go fight people with, that sellout! @@ -43,5 +44,8 @@ Plasma men are a powerful race with many perks! No really, I swear! So what if t As a Cargo Tech make sure to always buy a tesla to sell back to CC. They love those those. Trust me! Help. Maints. -BZ stops or slows down Lings chem regeneration drastically, make sure to BZ flood the station when lings are confirmed! Admins always regret meme options in their polls. +Putting cat ears on securitrons makes them table people and nya. Mekhi isn't a cat, but he still goes on the table, just roll with it. +As a Changeling, you can live without a head as they are merely vestigal to you, now, finally, you can be a Dullahan without it being Halloween. +People actually have fictional sex between fictional characters in this game. +When in doubt, take a break. A long break, preferably. If the game is wearing down your mental state and it's starting to lose any semblance of fun value, go and do something else for a month or two. By the time you come back, everything you liked will have been changed anyways. diff --git a/strings/tips.txt b/strings/tips.txt index b135692778..5dc4e1b985 100644 --- a/strings/tips.txt +++ b/strings/tips.txt @@ -1,83 +1,91 @@ Where the space map levels connect is randomized every round, but are otherwise kept consistent within rounds. Remember that they are not necessarily bidirectional! You can catch thrown items by toggling on your throw mode with an empty hand active. -To crack the safe in the vault, use a stethoscope or explosives on it. +To crack the safe in the vault, have a stethoscope in one of your hands and fiddle with the tumbler or you can alternatively use several concentrated explosive charges on it. Remember that the latter may result in the contents of the safe becoming a pile of ash. You can climb onto a table by dragging yourself onto one. This takes time and drops the items in your hands on the table. Clicking on a table that someone else is climbing onto will knock them down. You can drag other players onto yourself to open the strip menu, letting you remove their equipment or force them to wear something. Note that exosuits or helmets will block your access to the clothing beneath them, and that certain items take longer to strip or put on than others. Clicking on a windoor rather then bumping into it will keep it open, you can click it again to close it. You can spray a fire extinguisher, throw items or fire a gun while floating through space to change your direction. Simply fire opposite to where you want to go. You can change the control scheme by pressing tab. One is WASD, the other is the arrow keys. Keep in mind that hotkeys are also changed with this. -All vending machines can be hacked to obtain some contraband items from them, and many can be fed with coins to gain access to premium items. +All vending machines can be hacked to obtain some contraband items from them, and many may charge extra credits to give you premium items. Firesuits and winter coats offer mild protection from the cold, allowing you to spend longer periods of time near breaches and space than if wearing nothing at all. Glass shards can be welded to make glass, and metal rods can be welded to make metal. Ores can be welded too, but this takes a lot of fuel. If you need to drag multiple people either to safety or to space, bring a locker or crate over and stuff them all in before hauling them off. -You can grab someone by clicking on them with the grab intent, then upgrade the grab by clicking on them once more. An aggressive grab will momentarily stun someone, allow you to place Mekhi on a table by clicking on it, or throw them by toggling on throwing. +You can grab someone by clicking on them with the grab intent, then upgrade the grab by clicking on them once more. An aggressive grab can temporarily stun someone depending on their luck with resisting out of it, allowing you to slam them on a table by clicking on it, or throw them by toggling on throwing. Holding alt and left clicking a tile will allow you to see its contents in the top right window pane, which is much faster than right clicking. The resist button will allow you to resist out of handcuffs, being buckled to a chair or bed, out of locked lockers and more. Whenever you're stuck, try resisting! You can move an item out of the way by dragging it and then clicking on an adjacent tile with an empty hand. -You can recolor certain items like jumpsuits and gloves in washing machines by also throwing in a crayon. +You can recolor certain items like jumpsuits and gloves in washing machines by also throwing in a crayon. For more advanced fashion you can spray items with a spray can to tint its colors. Some items work better than others at displaying their tints, like sterile and paper masks, or darkly colored gloves. Maintenance is full of equipment that is randomized every round. Look around and see if anything is worth using. -Some roles cannot be antagonists by default, but antag selection is decided first. For instance, you can set Security Officer to High without affecting your chances of becoming an antag -- the game will just select a different role. +Some roles cannot be antagonists by default, but antag selection is decided first. For instance, you can set Security Officer to High without affecting your chances of becoming an antag - the game will just assign you to your next preferred role - or in the case that you have no such preferences set, a random role entirely. There are many places around the station to hide contraband. A few for starters: linen boxes, toilet cisterns, body bags. Experiment to find more! On all maps, you can use a machine in the vault to deposit space cash for cargo points. Otherwise, use it to steal the station's cash and get out before the alarm goes off. -As the Captain, you are one of the highest priority targets on the station. Everything from revolutions, to nuclear operatives, to traitors that need to rob you of your unique lasgun or your life are things to worry about. -As the Captain, always take the nuclear disk and pinpointer with you every shift. It's a good idea to give one of these to another head you can trust with keeping it safe, such as the Head of Security. +As the Captain, you are one of the highest priority targets on the station. Everything from revolutions looking to thwart your rule, to nuclear operatives seeking the disk, to traitors that need to rob you of your several high value items - or your life are all things to be concerned about. +As the Captain, always take the nuclear disk and pinpointer with you every shift. It's a good idea to give one of these to another head you can trust with keeping it safe, such as the Head of Personnel. As the Captain, you have absolute access and control over the station, but this does not mean that being a horrible person won't result in mutiny and a ban. As the Captain, you have a fancy pen that can be used as a holdout dagger or even as a scalpel in surgery! As the Captain, you can purchase a new emergency shuttle using a communications console. Some require credits, while others give you credits in exchange. Keep in mind that purchasing dangerous shuttles will incur the ire of your crew. -As the Chief Medical Officer, your hypospray is like a refillable instant injection syringe that can hold 30 units as opposed to the standard 15. -As the Chief Medical Officer, coordinate and communicate with your doctors, chemists, and geneticists during a nuclear emergency, blob infestation, or some other crisis to keep people alive and fighting. -As a Medical Doctor, pester Research for improved surgical tools. They work faster, don't cost much and are typically more deadly. +As the Chief Medical Officer, your hypospray is like the ones that your Medical Doctors can buy, except it comes in a fancy box that can hold several more hypovials than the standard, and already comes preloaded with specially-made high-capacity hypovials that hold double the reagents the standard ones do. +As the Chief Medical Officer, coordinate and communicate with your doctors, chemists, and paramedics during a nuclear emergency, blob infestation, or some other crisis to keep people alive and fighting. +As a Medical Doctor, pester Research for improved surgical tools. They work faster, combine the purposes of several tools in one (scalpel/saw, retractor/hemostat, drill/cautery), and don't cost many materials to boot! +As a Medical Doctor, the surgical saw and drill are both powerful weapons, the saw is sharp and can slice and dice, while the drill can quickly blind someone if aimed for the eyes. The laser scalpel is an upgraded version producible with Research's aid, and it has the highest force of most common place weapons, while still remaining sharp. As a Medical Doctor, your belt can hold a full set of surgical tools. Using sterilizine before each attempt during surgery will reduce your failure chance on tricky steps or when using less-than-optimal equipment. As a Medical Doctor, you can attempt to drain blood from a husk with a syringe to determine the cause. If you can extract blood, it was caused by extreme temperatures or lasers, if there is no blood to extract, you have confirmed the presence of changelings. As a Medical Doctor, while both heal toxin damage, the difference between charcoal and antitoxin is that charcoal will actively remove all other reagents from one's body, while antitoxin only removes various toxins - but can overdose. -As a Medical Doctor, you can surgically implant or extract things from people's chests. This can range from putting in a bomb to pulling out an alien larva. +As a Medical Doctor, you can surgically implant or extract things from people's chests by performing a cavity implant. This could range from inserting a suicide bomb to embedding the nuke disk into the Captain's chest. +As a Medical Doctor, it's of utmost urgency that you tend to anyone who's been hugged by a facehugger. You only have a couple of minutes from the initial attachment to perform organ manipulation to their chest and remove the rapidly developing alien embryo before it bursts out and immediately kills your patient. As a Medical Doctor, you must target the correct limb and be on help intent when trying to perform surgery on someone. Using disarm attempt will intentionally fail the surgery step. -As a Medical Doctor, corpses with the "...and their soul has departed" description no longer have a ghost attached to them and aren't usually revivable or cloneable. However it may prove useful to be creative in your revivification techniques with these bodies. -As a Medical Doctor, treating plasmamen is not impossible! Salbutamol stops them from suffocating and showers stop them from burning alive. You can even perform surgery on them by doing the procedure on a roller bed under a shower. +As a Medical Doctor, corpses with the "...and their soul has departed" description no longer have a ghost attached to them and can't be revived. However it may prove useful to be creative in your revivification techniques with these bodies. +As a Medical Doctor, treating plasmamen is not impossible! Salbutamol and epinephrine stops them from suffocating due to lack of internals and showers stop them from burning alive. You can even perform surgery on them by doing the procedure on a roller bed under a shower. 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 Medical Doctor, you can deal with patients who have absurd amounts of wounds by putting them in cryo. This will slowly treat all of their wounds simultaneously, but is much slower than direct treatment. +As a Medical Doctor, Critical Slash wounds are one of the most dangerous conditions someone can have. Apply gauze, epipens, sutures, cauteries, whatever you can, as soon as possible! +As a Medical Doctor, Saline-Glucose not only acts as a temporary boost to a patient's blood level, it also speeds regeneration! Perfect for drained patients! +As a Medical Doctor, medical gauze is an incredibly underrated tool. It can be used to entirely halt a limb from bleeding or sling one that's been shattered until it can be given proper attention. This even works on the dead, too! Be sure to stop someone's bleeding whether they're in critical condition or a corpse, as dragging someone whom is bleeding will rapidly deplete them of all their blood. +As a Chemist, there are dozens of chemicals that can heal, and even more that can cause harm. See which chemicals have the best synergy, both in healing, and in harming. 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. As a Chemist, you can make 100u bottles from plastic sheets. The ChemMaster can produce infinite 30u glass bottles as well. +As a Chemist, be sure to stock up some hypovials with useful chemicals for any doctors looking to heal on the go, you can also print out the deluxe hypovials at an autolathe specifically for the CMO's special hypospray. +As a Chemist, the reagent dartgun, while neutered in its ability to harm - can still be loaded up with morphine for a ghetto sedation weapon, and a quick shot of charcoal can make a slime hybrid regret their life choices in an instant. As a Geneticist, you can eject someone from cloning early by clicking on the cloner pod with your ID. Note that they will suffer more genetic damage and may lose vital organs from this. -As a Geneticist, becoming a hulk makes you capable of dealing high melee damage, stunlocking people, and punching through walls. However, you can't fire guns, will lose your hulk status if you take too much damage, and are not considered a human by the AI while you are a hulk. +As a Geneticist, becoming a hulk makes you capable of dealing high melee damage, becoming immune to most traditional stuns, and punching through walls. However, you can't fire guns, and will lose your hulk status if you take too much damage. As the Virologist, your viruses can range from healing powers so great that you can heal out of critical status, or diseases so dangerous they can kill the entire crew with airborne spontaneous combustion. Experiment! As the Virologist, you only require small amounts of vaccine to heal a sick patient. Work with the Chemist to distribute your cures more efficiently. As the Research Director, you can take AIs out of their cores by loading them into an intelliCard, and then from there into an AI system integrity restorer computer to revive and/or repair them. As the Research Director, you can lock down cyborgs instead of blowing them up. Then you can have their laws reset or if that doesn't work, safely dismantled. As the Research Director, you can upgrade your modular console with better computer parts to speed up its functions. This can be useful when using the AI system integrity restorer. As the Research Director, your console's NTnet monitoring tool can be used to retrieve airlock passkeys, provided that someone used a door remote. -As a Scientist, you can use the mutation toxin obtained from green slimes to turn yourself into a jelly mutant. Each subspecies has unique features - for example telepathic powers, duplicating bodies or integrating slime extracts! +As a Scientist, you can use the mutation toxin obtained from green slimes to turn yourself into a jelly mutant. Each subspecies has unique features - for example telepathic powers, duplicating bodies or integrating slime extracts for several unique effects! As a Scientist, you can maximize the number of uses you get out of a slime by feeding it slime steroid, created from purple slimes, while alive. You can then apply extract enhancer, created from cerulean slimes, on each extract. -As a Scientist, you can disable anomalies by scanning them with an analyzer, then send a signal on the frequency it gives you with a remote signalling device. This will leave behind an anomaly core, which can be used to construct a Phazon mech, or be used in the destructive analyzer for a 10,000 point bonus! +As a Scientist, you can disable anomalies by scanning them with an analyzer, and then sending a signal on the frequency it gives you with a remote signalling device. Alternatively, you can print out anomaly defusal tools which can instantly disable an anomaly at the protolathe with some research, both of these methods will leave behind an anomaly core, which can be used to construct a Phazon mech, or be used in the destructive analyzer for a 10,000 point bonus! As a Scientist, researchable stock parts can seriously improve the efficiency and speed of machines around the station. In some cases, it can even unlock new functions. As a Scientist, you can generate research points by letting the tachyon-doppler array record increasingly large explosions. As a Scientist, getting drunk just enough will speed up research. Skol! As a Scientist, you can get points by placing slime cores into the destructive analyzer! This even works with crossbred slime cores. -As a Scientist, work with botanists to get different types of seeds, as each type of seed can be used in the destructive analyzer for a small amount of Rnd type points! +As a Scientist, you can get a minuscule amount of points by sacrificing a packet of seeds from Hydroponics into the destructive analyzer! While each individual one may not yield many points per, you can quite easily amass a very large variety of seeds, which could add up over time for a couple extra minutes shaved off of maxing out RND. As a Roboticist, keep an ear out for anomaly announcements. If you get your hands on an anomaly core, you can build a Phazon mech! As a Roboticist, you can repair your cyborgs with a welding tool. If they have taken burn damage from lasers, you can remove their battery, expose the wiring with a screwdriver and replace their wires with a cable coil. As a Roboticist, you can reset a cyborg's module by cutting and mending the reset wire with a wire cutter. +As a Roboticist, pay mind when toying with a cyborg's wires. It's best to pulse wires before immediately cutting them, as cutting them right away without knowing what they do may sever them from the AI, or disable their camera. As a Roboticist, you can greatly help out Shaft Miners by building a Firefighter APLU equipped with a hydraulic clamp and plasma cutter. The mech is ash storm proof and can even walk across lava! -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 augment people with cyborg limbs. Augmented limbs are immune to the vacuum of space and temperatures while they can very easily be repaired with welders (brute) and cable coils (burn). 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 a Roboticist, you can upgrade medical bots with diamond-tipped syringes, hyposprays, and chemistry machine boards to make their injections pierce hardsuits, work faster, and inject higher quality medicines! +As the AI, you can click on people's names when they speak over the radio to jump your eye to them. This only works if there are cameras that can see them and are not wearing anything which would obsfuscate their face or tracking capabilities. 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. -As a Cyborg, choose your module carefully, as only cutting and mending your reset wire will let you repick it. If possible, refrain from choosing a module until a situation that requires one occurs. -As a Cyborg, you are immune to most forms of stunning, and excel at almost everything far better than humans. However, flashes can easily stunlock you and you cannot do any precision work as you lack hands. +As the AI, you can take pictures with your camera and upload them to newscasters. Cyborgs also share from this pool of pictures. +As a Cyborg, choose your module carefully, as only having your reset wire cut and mended by someone capable of manipulation will let you repick it. If possible, refrain from choosing a module until a situation that requires one occurs. +As a Cyborg, you are immune to most forms of stunning, and excel at almost everything far better than humans. However, flashes and EMPs can easily stunlock you and you fall short in performing any tasks which require hands. As a Cyborg, you are impervious to fires and heat. If you are rogue, you can release plasma fires everywhere and walk through them without a care in the world! As a Cyborg, you are extremely vulnerable to EMPs as EMPs both stun you and damage you. The ion rifle in the armory or a traitor with an EMP kit can kill you in seconds. As a Service Cyborg, your spray can knocks people down. However, it is blocked by gas masks. -As an Engineering Cyborg, you can attach air alarm/fire alarm/APC frames to walls by placing them on the floor and using a screwdriver on them. -As a Medical Cyborg, you can fully perform surgery and even augment people. Best of all, they have a 0% failure chance. -As a Janitor Cyborg, you are the bane of all slaughter demons and even Bubblegum himself. Cleaning up blood stains will severely gimp them. -As a Janitor Cyborg, you get a fancy bottle of drying agent! If you want to be nice, spray the janitor boots with them to magically upgrade them to absorbent galoshes. +As an Engineering Cyborg, you can attach air alarm/fire alarm/APC frames to walls by placing them on the floor and using a screwdriver on them. Alternatively, you can use your in-built pseudo-hand manipulator to show those organics who's boss! It can even perform complex tasks such as removing cells from APCs, or inserting plasma canisters into radiation collectors. +As a Medical Cyborg, you can fully perform surgery and even augment people. Best of all, they have a 0% failure chance, even if done on the floor. +As a Janitor Cyborg, you are the bane of all slaughter demons and can even foil Bubblegum himself. Cleaning up blood stains will severely gimp them, although the latter may just turn you into robotic paste. +As a Janitor Cyborg, you get a fancy bottle of drying agent! If you want to be nice, spray the janitor's galoshes with them to magically upgrade them to absorbent galoshes which automatically dry tiles. As the Chief Engineer, you can rename areas or create entirely new ones using your station blueprints. As the Chief Engineer, your hardsuit is significantly better than everybody else's. It has the best features of both engineering and atmospherics hardsuits - boasting nigh-invulnerability to radiation and all atmospheric conditions. As the Chief Engineer, you can spy on and even forge PDA communications with the message monitor console! The key is in your office. @@ -94,14 +102,14 @@ As an Engineer, you can convert tesla coils into corona analyzers by using a scr As an Engineer, you can use radiation collectors to generate research points. Load them with a 50/50 oxygen/tritium tank and use a multitool to switch them to research mode. As an Engineer, don't underestimate the humble P.A.C.M.A.N. generators. With upgraded parts, a couple units working in tandem are sufficient to take over for an exploded engine or shattered solars. As an Engineer, your departmental protolathe and circuit printer can manufacture the necessary circuit boards and components to build just about anything. Make extra medical machinery everywhere! Build a gibber for security! Set up an array of emitters pointing down the hall! The possibilities are endless! -As an Engineer, you can pry open secure storage by disabling the engine room APC's main breaker. This is obviously a bad idea if the engine is running. -Don't forget that Cargo has access to a meteor defense satellite that can be ordered BEFORE meteors hit the station. Any idle Engineers should have this on their to-do list. -As an Engineer, your RCD can be reloaded with mineral sheets instead of just compressed matter cartridges. +As an Engineer, you can pry open secure storage by disabling the engine room APC's environmental breaker. This is obviously a bad idea if the engine is running. +As an Engineer, don't forget that Cargo has access to a meteor defense satellite that can be ordered BEFORE meteors hit the station. Any idle Engineers should have this on their to-do list. +As an Engineer, your RCD can be reloaded with mineral sheets instead of just compressed matter cartridges. Materials which are combined alloys of other materials (such as reinforced glass and plasteel) provide more matter per sheet to the RCD. As an Atmospheric Technician, you can unwrench a pipe regardless of the pressures of the gases inside, but if they're too high they can burst out and injure you! As an Atmospheric Technician, look into replacing your gas pumps with volumetric gas pumps, as those move air in flat numerical amounts, rather than percentages which leave trace gases. -As an Atmospheric Technician, you are better suited to fighting fires than anyone else. As such, you have access to better firesuits, backpack firefighter tanks, and a completely heat and fire proof rigsuit. +As an Atmospheric Technician, you are better suited to fighting fires than anyone else. As such, you have access to better firesuits, backpack firefighter tanks, and a completely heat and fire proof hardsuit. As an Atmospheric Technician, your backpack firefighter tank can launch resin. This resin will extinguish fires and replace any gases with a safe, room-temperature airmix. -As an Atmospheric Technician, your ATMOS holofan projector blocks gases while allowing objects to pass through. With it, you can quickly contain gas spills, fires and hull breaches. Or, use it to seal a plasmaman cloning room. +As an Atmospheric Technician, your ATMOS holofan projectors can blocks gases and heat while allowing objects to pass through. With it, you can quickly contain gas spills, fires and hull breaches. Or, use it to create a plasmaman friendly lounge. As an Atmospheric Technician, burning a plasma/oxygen mix inside the incinerator will not only produce power, but also gases such as tritium and water vapor. As an Atmospheric Technician, you can change the layer of a pipe by clicking with it on a wrenched pipe or other atmos component of the desired layer. As an Atmospheric Technician, you can take a few cans worth of N2/N2O and cool it down at local freezers. This is a good idea when dealing with (or preparing for) a supermatter meltdown. @@ -111,65 +119,70 @@ As the Head of Security, don't let the power go to your head. You may have high As the Warden, your duty is to be the watchdog of the brig and handler of prisoners when little is happening, and to hand out equipment and weapons to the security officers when a crisis strikes. As the Warden, keep a close eye on the armory at all times, as it is a favored strike point of nuclear operatives and cocky traitors. As the Warden, if a prisoner's crimes are heinous enough you can put them in permabrig or the gulag. Make sure to check on them once in a while! -As the Warden, never underestimate the power of tech slugs! Scattershot fires a cone of weaker lasers, Ion slugs fires EMPs that only effect the tiles they hit, and Pulse slugs fire a singular laser that can one-hit almost any wall! -As the Warden, you can use a surgical saw on riot shotguns to shorten the barrel, making them able to fit in your backpack. +As the Warden, never underestimate the power of tech slugs! Scattershot fires a cone of weaker lasers with little damage fall off, Ion slugs fires EMPs that only effect the tiles they hit, and Pulse slugs fire a singular laser that can one-hit almost any wall! +As the Warden, you can use a surgical saw on riot shotguns to shorten the barrel, making them able to fit in your backpack. Make sure to empty them prior lest you blast yourself in the face! As the Warden, you can implant criminals you suspect might re-offend with devices that will track their location and allow you to remotely inject them with disabling chemicals. As the Warden, you can use handcuffs on orange prisoner shoes to turn them into cuffed shoes, forcing prisoners to walk and potentially thwarting an escape. -As the Warden, tracker implants can be used on sec officers. Doing this will let you track their corpse even without suits, though the implant will biodegrade after 5 minutes. -As the Warden, cryostasis shotgun darts hold 10u of chemicals that will not react untill it hits someone. -As the Warden, chemical implants can be loaded with a cocktail of healing or combat chems, perfect for the Hos or other sec officers to use. Be sure to keep a eye on them though, it will not auto inject! EMPs or starvation mite lead to the chemical implant to go off as well. -As the Warden, tracker implants can be used on sec officers. Doing this will let you be able to message them when telecoms are out, or when you suspect coms are compromised. This is also good against rogue AIs as the prisoner tracker doesn't leave logs or alarms for the AI. +As the Warden, tracker implants can be used on crewmembers. Doing this will let you track their person even without suit sensors and even instantly teleport to them at the local teleporter, although the implant will biodegrade after 5 minutes if its holder ever expires. +As the Warden, cryostasis shotgun darts hold 10u of chemicals that will not react until it hits someone. +As the Warden, chemical implants can be loaded with a cocktail of healing or combat chems, perfect for the HoS or other security officers to make use of in a pinch. Be sure to keep a eye on them though, as they cannot be injected without the prisoner management console! EMPs or starvation might lead to the chemical implant going off preemptively. +As the Warden, tracker implants can be used on your security officers. Doing this will let you be able to message them when telecomms are out, or when you suspect comms are compromised. This is also good against rogue AIs as the prisoner tracker doesn't leave logs or alarms for the AI. As a Security Officer, remember that correlation does not equal causation. Someone may have just been at the wrong place at the wrong time! -As a Security Officer, remember that your belt can hold more then one stun baton. -As a Security Officer, remember harm battoning someone in the head can deconvert them form a being a rev! This sadly doesn't work against the cult, nor does this protect them from getting reconverted. -As a Security Officer, remember that you can attach a sec-lite to your taser or your helmet! +As a Security Officer, remember that your belt can hold more than one stun baton. +As a Security Officer, remember harm beating someone in the head with a blunt object can deconvert them form a being a revolutionary! This sadly doesn't work against either cult, nor does this protect them from getting reconverted unlike a mindshield implant. +As a Security Officer, remember that you can attach a seclite to your taser or your helmet! As a Security Officer, communicate and coordinate with your fellow officers using the security channel (:s) to avoid confusion. -As a Security Officer, your sechuds or HUDsunglasses can not only see crewmates' job assignments and criminal status, but also if they are mindshield implanted. Use this to your advantage in a revolution to definitively tell who is on your side! +As a Security Officer, your security HUDglasses can not only see crewmates' job assignments and criminal status, but also if they are mindshield implanted. Use this to your advantage in a revolution to definitively tell who is on your side! As a Security Officer, mindshield implants can only prevent someone from being turned into a cultist: unlike revolutionaries, it will not de-cult them if they have already been converted. -As a Security Officer, examining someone while wearing sechuds or HUDsunglasses will let you set their arrest level, which will cause Beepsky and other security bots to chase after them. -As a Security Officer, you can take out the power cell on your baton to replace it with a better or fully charged one. Just use a screwdriver on your baton to remove the old cell -As a Security Officer, you can place riot shotguns on your armor, this even works with winter sec coats! +As a Security Officer, examining someone while wearing your security HUDglasses can allow you to swiftly edit their records and criminal status. Be sure to set someone to WANTED if you can't catch up to them, as it'll alert other officers of who's the bad guy, and cause the little security droids to chase after them for you. +As a Security Officer, you can take out the power cell on your baton to replace it with a better or fully charged one. Just use a screwdriver on your baton to remove the old cell. +As a Security Officer, you can just about any firearm on your vest, this even works with other non-standard armor-substitutes like security winter coats! As the Detective, people leave fingerprints everywhere and on everything. With the exception of white latex, gloves will hide them. All is not lost, however, as gloves leave fibers specific to their kind such as black or nitrile, pointing to a general department. -As the Detective, you can use your forensics scanner from a distance. -As the Detective, your revolver can be loaded with .357 ammunition obtained from a hacked autolathe. Firing it has a decent chance to blow up your revolver. +As the Detective, you can use your forensics scanner from a distance. Use this to scan boxes or other storage containers. +As the Detective, your revolver can be loaded with .357 ammunition. Use a screwdriver to permanently modify your revolver into using this type of ammunition, be warned however, firing it has a decent chance to cause the revolver to misfire and shoot you in the foot. As the Lawyer, try to negotiate with the Warden if sentences seem too high for the crime. -As the Lawyer, you can try to convince the captain and Head of Security to hold trials for prisoners in the courtroom. +As the Lawyer, you can try to convince the Captain and Head of Security to hold trials for prisoners in the courtroom. As the Head of Personnel, you are not higher ranking than other heads of staff, even though you are expected to take the Captain's place first should he go missing. If the situation seems too rough for you, consider allowing another head to become temporary Captain. -As the Head of Personnel, you are just as large a target as the Captain because of the potential power your ID and computer can hand out. +As the Head of Personnel, you are just as large a target as the Captain because of the potential power your ID and computer can hand out and your comparative vulnerability. As the Mime, your invisible wall power blocks people as well as projectiles. You can use it in a pinch to delay your pursuer. -As the Mime, you can use :r and :l to speak through your ventriloquist dummy. +As the Mime, you can use :r and :l to speak through your ventriloquist dummy. Sadly, this only works if your vow is broken, but at least you don't have to sacrifice your dignity by actually talking. As the Mime, your oath of silence is your source of power. Breaking it robs you of your powers and of your honor. +As the Mime, breaking your vow of silence is seen as incredibly dishonorable. Most people will seek to trouble and generally ignore a talking Mime. As the Clown, if you lose your banana peel, you can still slip people with your PDA! Honk! As the Clown, eating bananas heals you slightly. Honk! As the Clown, your Holy Grail is the mineral bananium, which can be given to the Roboticist to build you a fun and robust mech beloved by everyone. -As the Clown, you can use your stamp on a sheet of cardboard as the first step of making a honkbot. Fun for the whole crew! -As the Chaplain, your null rod has a lot of functions: it can convert water into holy water, which if spread on the ground prevents wizards from jaunting away, can destroy cultist runes by hitting them, and is a very powerful weapon to boot! -The Chaplain can bless any container with water by hitting it with their bible. Holy water has a myriad of uses against both cults and large amounts of it are a great contributor to success against them. -The Chaplain's holy weapon will kill clockwork marauders in two hits. -As the Chaplain, your bible is also a container that can store small items. Depending on your god, your starting bible may come with a surprise! -As the Chaplain, you are much more likely to get a response by praying to the gods than most people. To boost your chances, make altars with colorful crayon runes, lit candles, and wire art. +As the Clown, you can use your stamp on a sheet of flattened cardboard as the first step of making a honkbot. Fun for the whole crew! +As the Clown, your number one way to win over the crew's favor is by telling jokes and putting forth effort into being comedic. Everyone loves a good clown, but everyone despises a bad one. +As the Chaplain, your null rod has a lot of functions: while being an incredibly powerful weapon with an array of potential utilities depending upon the skin you chose for it, it also nulls cultist and wizard magic entirely, making you immune to them both and in some cases even harming the caster so long as you keep it in a pocket or in your hands. +As the Chaplain, you can bless any water container by hitting it with your bible to turn it into holy water. Holy water has a myriad of uses against both cults and large amounts of it are a great contributor to success against them. +As the Chaplain, your null rod will kill clockwork marauders in two hits while actively hindering their overall combat capabilities just by being nearby to them. +As the Chaplain, your bible is also a container that can store a singular small item. Depending on your God, your starting bible may come with a surprise! +As the Chaplain, you are much more likely to get a response by praying to the Gods than most people as your prayers will send a special noise cue directly to them! To further your chances of getting a response even further, pretty up your altar with crayon runes and wire art, and be sure to put a decent amount of effort into your prayers themselves. The Gods don't like lazy bums. As a Botanist, you can hack the MegaSeed Vendor to get access to more exotic seeds. These seeds can alternatively be ordered from cargo. As a Botanist, you can mutate the plants growing in your hydroponics trays with unstable mutagen or, as an alternative, crude radioactives from chemistry to get special variations. -As a Botanist, you should look into increasing the potency of your plants. This increases the size, amount of chemicals, points gained from grinding them in the biogenerator, and lets people know you are a proficient botanist. -As a Botanist, you can combine production trait chemicals just like a Chemist. Chlorine (blumpkin) + radium and phosphorus (glowshrooms) equals unstable mutagen! +As a Botanist, you should look into increasing the potency of your plants. This is shown by the size of the plant's sprite, and can increase the amount of chemicals, points gained from grinding them in the biogenerator, and lets people know you are a proficient botanist. +As a Botanist, you can combine production trait chemicals and mix your own complex chemicals inside of the plants themselves using precursors. Chlorine (blumpkin) + radium and phosphorus (glowshrooms) equals unstable mutagen! +As a Botanist, earthsblood is an incredibly powerful chemical found in Ambrosia Gaia, it heals all types of damages very rapidly but causes lingering brain damage and has a nasty overdose. You can combine the chemicals from watermelons (water), grass (hydrogen), and cherries (sugar) to mix mannitol in with your earthsblood to completely counteract its main drawback! +As a Botanist, Ambrosia Gaia is a plant mutated from Ambrosia Deus, which is a plant mutated from Ambrosia Vulgaris. The reagent contained within this plant known as earthsblood can make your trays and soil plots completely self sufficient when a plant containing such reagent is composted into them, meaning they won't need nutrients or water, and they'll automatically kill their own weeds and pests. As a Cook, you can load your food into snack vending machines. As a Cook, you can rename your custom made food with a pen. As a Cook, any food you make will be much healthier than the junk food found in vendors. Having the crew routinely eating from you will provide minor buffs. -As a Cook, being in the kitchen will make you remember the basics of Close Quarters Cooking. It is highly effective at removing Assistants from your workplace. +As a Cook, being in the kitchen will make you remember the basics of Close Quarters Cooking (CQC). It is highly effective at removing Assistants from your workplace. As a Cook, your Kitchenmate can vend out trays that fit on your belt slot. These trays pick up 7 food items at a time and are a quick way to transport large meals. As a Cook, the advanced roasting stick is used to cook food at a distance, and can be used on SME, singularity, and other objects that cook food normally. +As a Cook, the deep frier is a tool which can turn very large quantities of seemingly useless objects into food, albeit nutritionally poor and awful tasting food, but hey, food is food. As the Bartender, the drinks you start with only give you the basics. If you want more advanced mixtures, look into working with chemistry, hydroponics, or even mining for things to grind up and throw in! -As the Bartender, you can use a circular saw on your shotgun to make it easier to store. -As a Janitor, if someone steals your janicart, you can instead use your space cleaner spray, grenades, water sprayer, exact bloody revenge or order another from Cargo. +As the Bartender, you can use a circular saw on your shotgun to make it easier to store. Make sure to empty them prior lest you blast yourself in the face! +As a Janitor, if someone steals your janicart, you can instead use your spray bottles, soap, and arsenal of slippery objects to exact your bloody revenge.. ..or just order another one from Cargo. As a Janitor, the trash bag can be used to hold more than trash. Tools, medical equipment, smuggled nuclear disks... You name it! -As a Janitor, mousetraps can be used to create bombs or booby-trap containers. -Beware the Curator, for they are not completely defenseless. The curator's whip always disarms people, their laser pointer can blind humans and cyborgs, and can hide items in wirecut books. +As a Janitor, mousetraps can be used as bomb triggers to booby-trap containers. +As the Curator, for what it's worth, your toys and position are fairly robust. You can order a claymore, a whip, or a free space suit all at roundstart. The claymore is fairly underwhelming, however the whip is an incredibly robust weapon capable of always disarming, and that space suit is also better than the ones in EVA. As the Curator, be sure to keep the shelves stocked and the library clean for crew. As a Cargo Technician, you can hack MULEbots to make them faster, run over people in their way, and even let you ride them! As a Cargo Technician, you can order contraband items from the supply shuttle console by de-constructing it and using a multitool on the circuit board, the re-assembling it. As a Cargo Technician, you can earn more cargo points by shipping back crates from maintenance, liquid containers, plasma sheets, rare seeds from hydroponics, and more! As a Cargo Technician, you get 400 points per packet! Stamp the manifest and sending back the crate will give you 200 points for the paperwork and 200 points for the crate! -As a Cargo Technician, paperwork is an alternative option to shipping off plasma sheets and other goods. Order Paperwork crates and go into the crafting menu to turn pens and undone paper work into completed grant paper work to get 50 points per sheet! +As a Cargo Technician, paperwork and glass blowing are alternative options to shipping off plasma sheets and other goods. Order their respective kits and get to work! Paperwork can be done quickly via the crafting menu for a quick buck, while glass blowing is much more lucrative, but may require some more effort and time. As the Quartermaster, be sure to check the manifests on crates you receive to make sure all the info is correct. If there's a mistake, stamp the manifest DENIED and send it back in a crate with the items untouched for a refund! As the Quartermaster, you can construct an express supply console that instantly delivers crates by drop pod. The impact will cause a small explosion as well. As a Shaft Miner, the northern side of Lavaland has a lot more rare minerals than on the south. @@ -177,25 +190,25 @@ As a Shaft Miner, every monster on Lavaland has a pattern you can exploit to min As a Shaft Miner, you can harvest goliath plates from goliaths and upgrade your explorer's suit, mining hardsuits as well as Firefighter APLUs with them, greatly reducing incoming melee damage. As a Shaft Miner, always have a GPS on you, so a fellow miner or cyborg can come to save you if you die. As a Shaft Miner, you can craft a variety of equipment from the local fauna. Bone axes, lava boats and ash drake armour are just a few of them! -As a Traitor, the cryptographic sequencer (emag) can not only open doors, but also lockers, crates, APCs and more. It can hack cyborgs, and even cause bots to go berserk. Use it on the right machines, and you can even order more traitor gear or contact the Syndicate. Experiment! +As a Traitor, the cryptographic sequencer (emag) can not only open lockers, crates, APCs and more. It can also do things like hack cyborgs, and even cause bots to go berserk. Use it on the right machines, and you can even contact the Syndicate. Experiment! As a Traitor, subverting the AI to serve you can make it an extremely powerful ally. However, be careful of the wording in the laws you give it, as it may use your poorly written laws against you! As a Traitor, the Captain and the Head of Security are two of the most difficult to kill targets on the station. If either one is your target, plan carefully. -As a Traitor, you can manufacture and recycle revolver bullets at a hacked autolathe, making the revolver an extremely powerful tool. +As a Traitor, you can manufacture and recycle revolver bullets at a hacked autolathe, making the revolver an extremely powerful tool if you manage to nab an autolathe for yourself. As a Traitor, you may sometimes be assigned to hunt other traitors, and in turn be hunted by others. As a Traitor, the syndicate encryption key is very useful for coordinating plans with your fellow traitors -- or, of course, betraying them. As a Traitor, plasma can be injected into many things to sabotage them. Power cells, light bulbs, cigars and e-cigs will all explode when used. As a Nuclear Operative, communication is key! Use :t or :h to speak to your fellow operatives and coordinate an attack plan. -As a Nuclear Operative, you should look into purchasing a syndicate cyborg, as they can provide heavy fire support, full access, are immune to conventional stuns, and can easily take down the AI. +As a Nuclear Operative, you should look into purchasing one of the three Syndicate cyborgs in your uplink, as they can provide useful tactical support, function as walking access machines, are immune to conventional stuns, and can easily take down the AI. As a Nuclear Operative, stick together! While your equipment is robust, your fellow operatives are much better at saving your life: they can drag you away from danger while stunned and provide cover fire. As a Nuclear Operative, you might end up in a situation where the AI has bolted you into a room. Having some spare C4 in your pocket can save your life. As a Monkey, you can crawl through air or scrubber vents by alt+left clicking them. You must drop everything you are wearing and holding to do this, however. As a Monkey, you can still wear a few human items, such as backpacks, gas masks and hats, and still have two free hands. As the Malfunctioning AI, you can shunt to an APC if the situation gets bad. This disables your doomsday device if it is active. -As the Malfunctioning AI, you should either order your cyborgs to dismantle the robotics console or blow it up yourself in order to protect them. +As the Malfunctioning AI, you should either order your cyborgs to dismantle the robotics console or blow it up yourself in order to protect them. Do note that this will prevent you from hacking any cyborg made in the future. As the Malfunctioning AI, look into flooding the station with plasma fires to kill off large portions of the crew, letting you pick off the remaining few with space suits who escaped. -Xenomorphs? Science can craft deadly tech shells like pulse slugs and laser scatter shot that are highly effective against any alien threat. -When fighting aliens, it can be a good idea to turn off the gravity due to the alien's lack of zero-gravity control. -When fighting xenomorph aliens, consider a shield. Shields can block their pounces and be worn on the back, but beware of neurotoxin. +Xenomorphs? Any source of burn damage severely harms them. Science can craft deadly tech shells like pulse slugs and laser scatter shot that are highly effective against any alien threat. +When fighting Aliens, it can be a good idea to turn off the gravity due to the every caste of alien's lack of zero-gravity control, especially Hunters and Drones, which are completely and utterly helpless. +When fighting Aliens, consider a shield. A raised shield can halt their attempts to slash at you, and their disarms will always remove an item in your hand before knocking you over, always having something in your hand, no matter how small or worthless, can save your life. As an Alien, your melee prowess is unmatched, but your ranged abilities are sorely lacking. Make use of corners to force a melee confrontation! As an Alien, you take double damage from all burn attacks, such as lasers, welding tools, and fires. Furthermore, fire can destroy your resin and eggs. Expose areas to space to starve away any flamethrower fires before they can do damage! As an Alien, resin floors not only regenerate your plasma supply, but also passively heal you. Fight on resin floors to gain a home turf advantage! @@ -212,6 +225,7 @@ As the Blob, you can produce a Blobbernaut from a factory for 40 resources. Blob As the Blob, you can expand by clicking, create strong blobs with ctrl-click, rally spores with middle-click, and remove blobs with alt-click. You do not need to have your camera over the tile to do this. As the Blob, removing strong blobs, resource nodes, factories, and nodes will give you 4, 15, 25, and 25 resources back, respectively. As the Blob, talking will send a message to all other overminds and all Blobbernauts, allowing you to direct attacks and coordinate. +As the Blob, always make sure where you land is where you want to be, as it is very unlikely you will be getting too far away from it. Land in key points like the armory or the medical bay to immediately cripple the crew before they even find out you exist. Of course, always take into mind if being immediately discovered may outweight the benefits, and stick to maintenance close to these key points of interest to you. As a Blobbernaut, you can communicate with overminds and other Blobbernauts via :b. As a Blobbernaut, your HUD shows your health and the core health of the overmind that created you. As a Revolutionary, you cannot convert a head of staff or someone who has a mindshield implant, such as a security officer or those they implant. Implants can however be surgically removed, and do not carry over with cloning. Take control of medbay to keep control of conversions! @@ -220,6 +234,11 @@ As a Revolutionary, cargo can be your best friend or your worst nightmare. In th As a Revolutionary, your main power comes from how quickly you spread. Convert people as fast as you can and overwhelm the heads of staff before security can arm up. As a Changeling, the Extract DNA sting counts for your genome absorb objective, but does not let you respec your powers. As a Changeling, you can absorb someone by strangling them and using the Absorb verb; this gives you the ability to rechoose your powers, the DNA of whoever you absorbed, the memory of the absorbed, and some samples of things the absorbed said. +As a Changeling, absorbing someone will give you their full memory. This can include things such as a Traitor's uplink, thus absorbing one will allow you to access the Traitor uplink and buy toys for your Changeling self to abuse. +As a Changeling, absorbing another Changeling will permanently boost your chemical reserve, allow you to pick more abilities, and make the victim unable to revive. Be careful when exposing your identity to other Changelings, as they may be out of those wonderful benefits. +As a Changeling, BZ gas will dramatically slow down or even halt your natural chemical regeneration, be sure to avoid it at all costs as some lunatics may try and flood portions of the station to deal with you. +As a Changeling, death is not the end for you! You can revive after two minutes from being dead by triggering your stasis ability, and then waiting for the prompt to resurrect yourself to show up. +As a Changeling, your Regenerate Limbs power will quickly heal all of your wounds, but they'll still leave scars. Changelings can use Fleshmend to get rid of scars, or you can ingest Carpotoxin to get rid of them like a normal person. As a Cultist, do not cause too much chaos before your objective is completed. If the shuttle gets called too soon, you may not have enough time to win. As a Cultist, your team starts off very weak, but if necessary can quickly convert everything they have into raw power. Make sure you have the numbers and equipment to support going loud, or the cult will fall flat on its face. As a Cultist, the Blood Boil rune will deal massive amounts of brute damage to non-cultists, stamina damage to Ratvarian scum, and some damage to fellow cultists of Nar-Sie nearby, but will create a fire where the rune stands on use. @@ -239,9 +258,10 @@ You can deconvert Cultists of Nar-Sie and Servants of Ratvar by feeding them lar Tiles sprayed with holy water will permanently block Servants of Ratvar from teleporting onto them. As a Wizard, you can turn people to stone, then animate the resulting statue with a staff of animation to create an extremely powerful minion, for all of 5 minutes at least. As a Wizard, the fireball spell performs very poorly at close range, as it can easily catch you in the blast. It is best used as a form of artillery down long hallways. -As a Wizard, summoning guns will turn a large portion of the crew against themselves, but will also give everyone anything from a pea shooter to a BFG 9000. Use at your own risk! +As a Wizard, summoning guns will turn a large portion of the crew against themselves, but will also give everyone anything from a energy pistol to a pulse rifle. Use at your own risk! As a Wizard, the staff of chaos can fire any type of bolts from the magical wands. This can range from bolts of instant death to healing or reviving someone. As a Wizard, most spells become unusable if you are not wearing your robe, hat, and sandals. +As a Wizard, it's advisable that you don't dump all of your limited spell points into solely offensive spells, if you can't defend yourself then you're sure to get dunked. As an Abductor, you can select where your victims will be sent on the ship control console. As an Abductor Agent, the combat mode vest has much higher resistance to every kind of weapon, and your helmet prevents the AI from tracking you. As an Abductor, the baton can cycle between four modes: stun, sleep, cuff and probe. @@ -260,17 +280,24 @@ As a Drone, you can ping other drones to alert them of areas in the station in n As a Drone, you can repair yourself by using a screwdriver on yourself and standing still! As a Ghost, you can see the inside of a container on the ground by clicking on it. As a Ghost, you can double click on just about anything to follow it. Or just warp around! +As a Ghost, there's a button in the OOC tab labeled Observe, it lets you see through someone's eyes as if you were the one who's playing them. As a Devil, you gain power for every three souls you control, however you also become more obvious. As a Devil, as long as you control at least one other soul, you will automatically resurrect, as long as a banishment ritual is not performed. 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 hacking doors, cutting and mending a "test light wire" will restore power to the door. 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. +You can light a cigar on a supermatter crystal. +Using sticky tape on items can make them stick to people and walls! Be careful, grenades might stick to your hand during the moment of truth! +In a pinch, stripping yourself naked will give you a sizeable resistance to being tackled. What do you value more, your freedom or your dignity? +Wearing riot armor makes you significantly more effective at performing tackle takedowns, but will use extra stamina with each leap! It will also significantly protect you from other tackles! +Epipens contain a powerful coagulant that drastically reduces bleeding on all bleeding wounds. If you don't have time to properly treat someone with lots of slashes or piercings, stick them with a pen to buy some time! +Anything you can light a cigarette with, you can use to cauterize a bleeding wound. Technically, that includes the supermatter. +Suit storage units entirely purge radiation from any carbon mob put inside of them when cycling, at the cost of some horrific burns, this is a very effective strategy to clean someone up after they bathed in the engine. 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. +Being out of combat mode makes makes you deal less damage to people and objects when attacking. This stacks with the penalty incurred by resting. +Resting makes you deal less damage to people and objects when attacking. This stacks with the penalty incurred by being out of combat mode. 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/strings/traumas.json b/strings/traumas.json index 833c786b75..f8fed95c98 100644 --- a/strings/traumas.json +++ b/strings/traumas.json @@ -125,12 +125,14 @@ ";chemist can u @pick(create_verbs) holy @pick(mellens) for @pick(s_roles)???!!", "@pick(semicolon) LIZZARRD SPEAKIGN IN EVIL BULL LANGUAGE SCI!!", "@pick(semicolon)POST REBOOT MESSAGE LOLOL FUCK FUCK FUCK YOU", - "@pick(semicolon)so, i was trying to talk to someone on rp today, and then a mime walks up and pies them in the face along with some other prankster--i thought that mimes and clowns are supposed to be hired to entertain not to be a nuisance, and that if entertainment comes at someone elses expense then it's not supposed to be done. is that enough to like submit a player complaint or some shit or am i just being petty?", "@pick(semicolon)*nya", "@pick(semicolon)*awoo", "@pick(semicolon)*merp", "@pick(semicolon)*weh", - "@pick(semicolon)My balls finally feel full, again." + "@pick(semicolon)My balls finally feel full, again.", + "@pick(semicolon)Assaltign a sec osficer aren't crime if ur @pick(roles)", + ";SEC I SPILED MU JICE HELELPH HELPJ JLEP HELP", + "@pick(semicolon) atmos is chemistyr is radation fast air is FASTER cheemsitry and FASTER RADIATION AND FASTER DEATH!!!" ], "mutations": [ @@ -198,7 +200,7 @@ "abdoocters", "revinent" ], - + "bug": [ "", "IS TIS A BUG??", @@ -206,7 +208,7 @@ "BUG!!!", "HUE, FEATURE!!" ], - + "semicolon": [ "", ";", @@ -270,7 +272,7 @@ "arrdee", "sek" ], - + "cargo": [ "GUNS", "HATS", @@ -278,7 +280,7 @@ "MEMES", "GLOWY CYSTAL" ], - + "s_roles": [ "ert", "shadowlig", diff --git a/strings/wanted_message.json b/strings/wanted_message.json new file mode 100644 index 0000000000..18965b7026 --- /dev/null +++ b/strings/wanted_message.json @@ -0,0 +1,74 @@ +{ + "basemessage": [ + "Fugitive from the law due to", + "Needs to be interrogated for information about", + "Wanted by The Syndicate for", + "Ransomable to Nanotrasen for", + "Has exploitable information about" + ], + "verb": [ + "murdering", + "killing", + "accidentally destroying", + "destroying", + "knowing information about", + "stealing", + "slipping", + "sabotaging", + "robusting", + "collaborating with", + "being close friends with", + "cloning", + "befriending", + "bombing", + "kidnapping", + "pretending to be", + "seducing", + "ignoring", + "assassinating" + ], + "noun": { + "secret plans": 50, + "the hand teleporter": 50, + "an NT CentCom uniform": 50, + "a supermatter shard": 50, + "internal Syndicate documents": 50, + "experimental Nanotrasen technology": 50, + "bluespace crystals": 50, + "a cult": 50, + "shapeshifting creatures": 50, + "a toolbox": 10, + "a bar of soap": 10, + "lizardmen": 10, + "two million credits": 10, + "a gondola": 10, + "one billion credits": 5, + "research on floor clowns": 5, + "Officer Beepsky": 5, + "clown tears": 5, + "John F Kennedy 2": 5, + "Nanotrasen's swimsuit calendar": 5, + "a suspicious bus": 5, + "administrators": 5, + "a solid gold gondola": 5, + "the anime archive": 5, + "YALPER": 1, + "absolutely nothing": 1, + "Cuban Pete": 1, + "your mother": 1, + "WGW": 1 + }, + "location": { + "on Space Station 13": 50, + "somewhere in deep space": 50, + "on a remote syndicate base": 50, + "in a secure NT facility": 50, + "while on an escape shuttle": 10, + "while infiltrating CentCom headquarters": 10, + "deep in the necropolis": 10, + "during a drunken bar fight": 5, + "while stuck in a bathroom": 5, + "in a back alley on Mars": 5, + "on Virgo Orbital": 1 + } +} diff --git a/strings/wounds/bone_scar_desc.json b/strings/wounds/bone_scar_desc.json new file mode 100644 index 0000000000..3540547c4a --- /dev/null +++ b/strings/wounds/bone_scar_desc.json @@ -0,0 +1,26 @@ +{ + "generic": ["general disfigurement"], + + "bluntmoderate": [ + "the bone equivalent of a faded bruise", + "a series of tiny chip marks" + ], + + "bluntsevere": [ + "a series of faded hairline cracks", + "a small bone dent" + ], + + "bluntcritical": [ + "large streaks of refilled cracks", + "a fractal of reformed stress marks", + "a cluster of calluses" + ], + + "dismember": [ + "is slightly misaligned", + "has clearly been dropped recently", + "has a damaged socket" + ] + +} \ No newline at end of file diff --git a/strings/wounds/flesh_scar_desc.json b/strings/wounds/flesh_scar_desc.json new file mode 100644 index 0000000000..fb2b927a30 --- /dev/null +++ b/strings/wounds/flesh_scar_desc.json @@ -0,0 +1,86 @@ +{ + "generic": ["general disfigurement"], + + "bluntmoderate": [ + "light discoloring", + "a slight blue tint" + ], + + "bluntsevere": [ + "a faded, fist-sized bruise", + "a vaguely triangular peel scar" + ], + + "bluntcritical": [ + "a section of janky skin lines and badly healed scars", + "a large patch of uneven skin tone", + "a cluster of calluses" + ], + + + + "slashmoderate": [ + "light, faded lines", + "minor cut marks", + "a small faded slit", + "a series of small scars" + ], + + "slashsevere": [ + "a twisted line of faded gashes", + "a gnarled sickle-shaped slice scar" + ], + + "slashcritical": [ + "a winding path of very badly healed scar tissue", + "a series of peaks and valleys along a gruesome line of cut scar tissue", + "a grotesque snake of indentations and stitching scars" + ], + + + + "piercemoderate": [ + "a small, faded bruise", + "a small twist of reformed skin", + "a thumb-sized puncture scar" + ], + + "piercesevere": [ + "an ink-splat shaped pocket of scar tissue", + "a long-faded puncture wound", + "a tumbling puncture hole with evidence of faded stitching" + ], + + "piercecritical": [ + "a rippling shockwave of scar tissue", + "a wide, scattered cloud of shrapnel marks", + "a gruesome multi-pronged puncture scar" + ], + + + + "burnmoderate": [ + "small amoeba-shaped skinmarks", + "a faded streak of depressed skin" + ], + + "burnsevere": [ + "a large, jagged patch of faded skin", + "random spots of shiny, smooth skin", + "spots of taut, leathery skin" + ], + + "burncritical": [ + "massive, disfiguring keloid scars", + "several long streaks of badly discolored and malformed skin", + "unmistakeable splotches of dead tissue from serious burns" + ], + + + "dismember": [ + "is several skintone shades paler than the rest of the body", + "is a gruesome patchwork of artificial flesh", + "has a large series of attachment scars at the articulation points" + ] + +} \ No newline at end of file diff --git a/strings/wounds/scar_loc.json b/strings/wounds/scar_loc.json new file mode 100644 index 0000000000..f721294925 --- /dev/null +++ b/strings/wounds/scar_loc.json @@ -0,0 +1,52 @@ +{ + "": ["general area"], + + "head": [ + "left eyebrow", + "cheekbone", + "neck", + "throat", + "jawline", + "entire face" + ], + + "chest": [ + "upper chest", + "lower abdomen", + "midsection", + "collarbone", + "lower back" + ], + + "l_arm": [ + "outer left forearm", + "inner left wrist", + "left elbow", + "left bicep", + "left shoulder" + ], + + "r_arm": [ + "outer right forearm", + "inner right wrist", + "right elbow", + "right bicep", + "right shoulder" + ], + + "l_leg": [ + "inner left thigh", + "outer left calf", + "outer left hip", + "left kneecap", + "lower left shin" + ], + + "r_leg": [ + "inner right thigh", + "outer right calf", + "outer right hip", + "right kneecap", + "lower right shin" + ] +} \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index ada63806ee..adb110026c 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -38,6 +38,7 @@ #include "code\__DEFINES\configuration.dm" #include "code\__DEFINES\construction.dm" #include "code\__DEFINES\contracts.dm" +#include "code\__DEFINES\cooldowns.dm" #include "code\__DEFINES\cult.dm" #include "code\__DEFINES\diseases.dm" #include "code\__DEFINES\DNA.dm" @@ -46,6 +47,7 @@ #include "code\__DEFINES\dynamic.dm" #include "code\__DEFINES\economy.dm" #include "code\__DEFINES\events.dm" +#include "code\__DEFINES\exosuit_fabs.dm" #include "code\__DEFINES\exports.dm" #include "code\__DEFINES\fantasy_affixes.dm" #include "code\__DEFINES\food.dm" @@ -60,6 +62,7 @@ #include "code\__DEFINES\language.dm" #include "code\__DEFINES\layers_planes.dm" #include "code\__DEFINES\lighting.dm" +#include "code\__DEFINES\loadout.dm" #include "code\__DEFINES\logging.dm" #include "code\__DEFINES\machines.dm" #include "code\__DEFINES\maps.dm" @@ -78,6 +81,7 @@ #include "code\__DEFINES\networks.dm" #include "code\__DEFINES\pinpointers.dm" #include "code\__DEFINES\pipe_construction.dm" +#include "code\__DEFINES\plumbing.dm" #include "code\__DEFINES\pool.dm" #include "code\__DEFINES\power.dm" #include "code\__DEFINES\preferences.dm" @@ -92,6 +96,7 @@ #include "code\__DEFINES\reagents_specific_heat.dm" #include "code\__DEFINES\research.dm" #include "code\__DEFINES\robots.dm" +#include "code\__DEFINES\rockpaperscissors.dm" #include "code\__DEFINES\role_preferences.dm" #include "code\__DEFINES\rust_g.dm" #include "code\__DEFINES\say.dm" @@ -118,21 +123,23 @@ #include "code\__DEFINES\vv.dm" #include "code\__DEFINES\wall_dents.dm" #include "code\__DEFINES\wires.dm" +#include "code\__DEFINES\wounds.dm" #include "code\__DEFINES\_flags\_flags.dm" +#include "code\__DEFINES\_flags\do_after.dm" #include "code\__DEFINES\_flags\item_flags.dm" #include "code\__DEFINES\_flags\obj_flags.dm" +#include "code\__DEFINES\_flags\return_values.dm" +#include "code\__DEFINES\_flags\shields.dm" #include "code\__DEFINES\admin\keybindings.dm" +#include "code\__DEFINES\chemistry\reactions.dm" #include "code\__DEFINES\combat\attack_types.dm" #include "code\__DEFINES\combat\block.dm" #include "code\__DEFINES\combat\block_parry.dm" #include "code\__DEFINES\dcs\flags.dm" #include "code\__DEFINES\dcs\helpers.dm" #include "code\__DEFINES\dcs\signals.dm" -#include "code\__DEFINES\flags\do_after.dm" -#include "code\__DEFINES\flags\shields.dm" #include "code\__DEFINES\mapping\maploader.dm" #include "code\__DEFINES\material\worth.dm" -#include "code\__DEFINES\misc\return_values.dm" #include "code\__DEFINES\mobs\slowdowns.dm" #include "code\__DEFINES\research\stock_parts.dm" #include "code\__DEFINES\skills\defines.dm" @@ -197,6 +204,7 @@ #include "code\_globalvars\lists\client.dm" #include "code\_globalvars\lists\flavor_misc.dm" #include "code\_globalvars\lists\keybindings.dm" +#include "code\_globalvars\lists\loadout_categories.dm" #include "code\_globalvars\lists\maintenance_loot.dm" #include "code\_globalvars\lists\mapping.dm" #include "code\_globalvars\lists\medals.dm" @@ -217,6 +225,9 @@ #include "code\_onclick\observer.dm" #include "code\_onclick\other_mobs.dm" #include "code\_onclick\overmind.dm" +#include "code\_onclick\right_click.dm" +#include "code\_onclick\right_item_attack.dm" +#include "code\_onclick\right_other_mobs.dm" #include "code\_onclick\telekinesis.dm" #include "code\_onclick\hud\_defines.dm" #include "code\_onclick\hud\action_button.dm" @@ -226,6 +237,7 @@ #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\blob_overmind.dm" #include "code\_onclick\hud\blobbernauthud.dm" +#include "code\_onclick\hud\clockwork_marauder.dm" #include "code\_onclick\hud\constructs.dm" #include "code\_onclick\hud\credits.dm" #include "code\_onclick\hud\devil.dm" @@ -237,6 +249,7 @@ #include "code\_onclick\hud\hud.dm" #include "code\_onclick\hud\human.dm" #include "code\_onclick\hud\lavaland_elite.dm" +#include "code\_onclick\hud\map_popups.dm" #include "code\_onclick\hud\monkey.dm" #include "code\_onclick\hud\movable_screen_objects.dm" #include "code\_onclick\hud\parallax.dm" @@ -248,7 +261,11 @@ #include "code\_onclick\hud\robot.dm" #include "code\_onclick\hud\screen_objects.dm" #include "code\_onclick\hud\swarmer.dm" +#include "code\_onclick\hud\screen_objects\clickdelay.dm" +#include "code\_onclick\hud\screen_objects\sprint.dm" +#include "code\_onclick\hud\screen_objects\stamina.dm" #include "code\_onclick\hud\screen_objects\storage.dm" +#include "code\_onclick\hud\screen_objects\vore.dm" #include "code\controllers\admin.dm" #include "code\controllers\configuration_citadel.dm" #include "code\controllers\controller.dm" @@ -267,6 +284,7 @@ #include "code\controllers\configuration\entries\game_options.dm" #include "code\controllers\configuration\entries\general.dm" #include "code\controllers\configuration\entries\plushies.dm" +#include "code\controllers\configuration\entries\policy.dm" #include "code\controllers\subsystem\acid.dm" #include "code\controllers\subsystem\adjacent_air.dm" #include "code\controllers\subsystem\air.dm" @@ -285,6 +303,7 @@ #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\fail2topic.dm" #include "code\controllers\subsystem\fire_burning.dm" +#include "code\controllers\subsystem\fluid.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\holodeck.dm" #include "code\controllers\subsystem\icon_smooth.dm" @@ -334,6 +353,7 @@ #include "code\controllers\subsystem\processing\circuit.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" #include "code\controllers\subsystem\processing\fields.dm" +#include "code\controllers\subsystem\processing\huds.dm" #include "code\controllers\subsystem\processing\instruments.dm" #include "code\controllers\subsystem\processing\nanites.dm" #include "code\controllers\subsystem\processing\networks.dm" @@ -348,6 +368,7 @@ #include "code\datums\ai_laws.dm" #include "code\datums\armor.dm" #include "code\datums\beam.dm" +#include "code\datums\beepsky_fashion.dm" #include "code\datums\browser.dm" #include "code\datums\callback.dm" #include "code\datums\chatmessage.dm" @@ -358,11 +379,13 @@ #include "code\datums\datumvars.dm" #include "code\datums\dna.dm" #include "code\datums\dog_fashion.dm" +#include "code\datums\ductnet.dm" #include "code\datums\emotes.dm" #include "code\datums\ert.dm" #include "code\datums\explosion.dm" #include "code\datums\forced_movement.dm" #include "code\datums\holocall.dm" +#include "code\datums\http.dm" #include "code\datums\hud.dm" #include "code\datums\mind.dm" #include "code\datums\mutable_appearance.dm" @@ -405,15 +428,19 @@ #include "code\datums\components\construction.dm" #include "code\datums\components\dejavu.dm" #include "code\datums\components\earprotection.dm" +#include "code\datums\components\edible.dm" #include "code\datums\components\edit_complainer.dm" #include "code\datums\components\embedded.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\fried.dm" +#include "code\datums\components\gps.dm" #include "code\datums\components\identification.dm" #include "code\datums\components\igniter.dm" #include "code\datums\components\infective.dm" #include "code\datums\components\jousting.dm" +#include "code\datums\components\killerqueen.dm" #include "code\datums\components\knockback.dm" #include "code\datums\components\knockoff.dm" #include "code\datums\components\lifesteal.dm" @@ -425,6 +452,7 @@ #include "code\datums\components\mood.dm" #include "code\datums\components\nanites.dm" #include "code\datums\components\ntnet_interface.dm" +#include "code\datums\components\omen.dm" #include "code\datums\components\orbiter.dm" #include "code\datums\components\paintable.dm" #include "code\datums\components\pellet_cloud.dm" @@ -446,11 +474,12 @@ #include "code\datums\components\swarming.dm" #include "code\datums\components\tackle.dm" #include "code\datums\components\thermite.dm" +#include "code\datums\components\twohanded.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\virtual_reality.dm" #include "code\datums\components\wearertargeting.dm" #include "code\datums\components\wet_floor.dm" -#include "code\datums\components\crafting\craft.dm" +#include "code\datums\components\crafting\crafting.dm" #include "code\datums\components\crafting\guncrafting.dm" #include "code\datums\components\crafting\recipes.dm" #include "code\datums\components\crafting\glassware\glassware.dm" @@ -464,6 +493,11 @@ #include "code\datums\components\fantasy\affix.dm" #include "code\datums\components\fantasy\prefixes.dm" #include "code\datums\components\fantasy\suffixes.dm" +#include "code\datums\components\plumbing\_plumbing.dm" +#include "code\datums\components\plumbing\chemical_acclimator.dm" +#include "code\datums\components\plumbing\filter.dm" +#include "code\datums\components\plumbing\reaction_chamber.dm" +#include "code\datums\components\plumbing\splitter.dm" #include "code\datums\components\storage\storage.dm" #include "code\datums\components\storage\ui.dm" #include "code\datums\components\storage\concrete\_concrete.dm" @@ -533,6 +567,7 @@ #include "code\datums\elements\_element.dm" #include "code\datums\elements\art.dm" #include "code\datums\elements\beauty.dm" +#include "code\datums\elements\bsa_blocker.dm" #include "code\datums\elements\cleaning.dm" #include "code\datums\elements\decal.dm" #include "code\datums\elements\dusts_on_catatonia.dm" @@ -578,6 +613,8 @@ #include "code\datums\martial\wrestling.dm" #include "code\datums\materials\_material.dm" #include "code\datums\materials\basemats.dm" +#include "code\datums\materials\meat.dm" +#include "code\datums\materials\pizza.dm" #include "code\datums\mood_events\beauty_events.dm" #include "code\datums\mood_events\drink_events.dm" #include "code\datums\mood_events\drug_events.dm" @@ -616,6 +653,7 @@ #include "code\datums\status_effects\gas.dm" #include "code\datums\status_effects\neutral.dm" #include "code\datums\status_effects\status_effect.dm" +#include "code\datums\status_effects\wound_effects.dm" #include "code\datums\traits\_quirk.dm" #include "code\datums\traits\good.dm" #include "code\datums\traits\negative.dm" @@ -643,6 +681,13 @@ #include "code\datums\wires\syndicatebomb.dm" #include "code\datums\wires\tesla_coil.dm" #include "code\datums\wires\vending.dm" +#include "code\datums\wounds\_scars.dm" +#include "code\datums\wounds\_wounds.dm" +#include "code\datums\wounds\bones.dm" +#include "code\datums\wounds\burns.dm" +#include "code\datums\wounds\loss.dm" +#include "code\datums\wounds\pierce.dm" +#include "code\datums\wounds\slash.dm" #include "code\game\alternate_appearance.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm" @@ -692,6 +737,7 @@ #include "code\game\gamemodes\dynamic\dynamic_rulesets_midround.dm" #include "code\game\gamemodes\dynamic\dynamic_rulesets_roundstart.dm" #include "code\game\gamemodes\dynamic\dynamic_storytellers.dm" +#include "code\game\gamemodes\eldritch_cult\eldritch_cult.dm" #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\gangs\dominator.dm" #include "code\game\gamemodes\gangs\dominator_countdown.dm" @@ -738,7 +784,6 @@ #include "code\game\machinery\dna_scanner.dm" #include "code\game\machinery\doppler_array.dm" #include "code\game\machinery\droneDispenser.dm" -#include "code\game\machinery\exp_cloner.dm" #include "code\game\machinery\firealarm.dm" #include "code\game\machinery\flasher.dm" #include "code\game\machinery\gulag_item_reclaimer.dm" @@ -760,6 +805,7 @@ #include "code\game\machinery\rechargestation.dm" #include "code\game\machinery\recycler.dm" #include "code\game\machinery\requests_console.dm" +#include "code\game\machinery\sheetifier.dm" #include "code\game\machinery\shieldgen.dm" #include "code\game\machinery\Sleeper.dm" #include "code\game\machinery\slotmachine.dm" @@ -875,6 +921,7 @@ #include "code\game\mecha\equipment\weapons\mecha_ammo.dm" #include "code\game\mecha\equipment\weapons\weapons.dm" #include "code\game\mecha\medical\medical.dm" +#include "code\game\mecha\medical\medigax.dm" #include "code\game\mecha\medical\odysseus.dm" #include "code\game\mecha\working\ripley.dm" #include "code\game\mecha\working\working.dm" @@ -943,14 +990,18 @@ #include "code\game\objects\items\AI_modules.dm" #include "code\game\objects\items\airlock_painter.dm" #include "code\game\objects\items\apc_frame.dm" +#include "code\game\objects\items\armor_kits.dm" #include "code\game\objects\items\balls.dm" +#include "code\game\objects\items\binoculars.dm" #include "code\game\objects\items\blueprints.dm" #include "code\game\objects\items\body_egg.dm" #include "code\game\objects\items\bodybag.dm" #include "code\game\objects\items\boombox.dm" +#include "code\game\objects\items\broom.dm" #include "code\game\objects\items\candle.dm" #include "code\game\objects\items\cardboard_cutouts.dm" #include "code\game\objects\items\cards_ids.dm" +#include "code\game\objects\items\chainsaw.dm" #include "code\game\objects\items\charter.dm" #include "code\game\objects\items\chromosome.dm" #include "code\game\objects\items\chrono_eraser.dm" @@ -968,8 +1019,11 @@ #include "code\game\objects\items\dice.dm" #include "code\game\objects\items\dna_injector.dm" #include "code\game\objects\items\documents.dm" +#include "code\game\objects\items\dualsaber.dm" #include "code\game\objects\items\eightball.dm" +#include "code\game\objects\items\electrostaff.dm" #include "code\game\objects\items\extinguisher.dm" +#include "code\game\objects\items\fireaxe.dm" #include "code\game\objects\items\flamethrower.dm" #include "code\game\objects\items\gift.dm" #include "code\game\objects\items\granters.dm" @@ -988,6 +1042,7 @@ #include "code\game\objects\items\paiwire.dm" #include "code\game\objects\items\pet_carrier.dm" #include "code\game\objects\items\pinpointer.dm" +#include "code\game\objects\items\pitchfork.dm" #include "code\game\objects\items\plushes.dm" #include "code\game\objects\items\pneumaticCannon.dm" #include "code\game\objects\items\powerfist.dm" @@ -1004,6 +1059,7 @@ #include "code\game\objects\items\shrapnel.dm" #include "code\game\objects\items\signs.dm" #include "code\game\objects\items\singularityhammer.dm" +#include "code\game\objects\items\spear.dm" #include "code\game\objects\items\stunbaton.dm" #include "code\game\objects\items\taster.dm" #include "code\game\objects\items\teleportation.dm" @@ -1012,7 +1068,6 @@ #include "code\game\objects\items\theft_tools.dm" #include "code\game\objects\items\toys.dm" #include "code\game\objects\items\trash.dm" -#include "code\game\objects\items\twohanded.dm" #include "code\game\objects\items\vending_items.dm" #include "code\game\objects\items\weaponry.dm" #include "code\game\objects\items\circuitboards\circuitboard.dm" @@ -1106,6 +1161,7 @@ #include "code\game\objects\items\stacks\stack.dm" #include "code\game\objects\items\stacks\tape.dm" #include "code\game\objects\items\stacks\telecrystal.dm" +#include "code\game\objects\items\stacks\tickets.dm" #include "code\game\objects\items\stacks\wrap.dm" #include "code\game\objects\items\stacks\sheets\glass.dm" #include "code\game\objects\items\stacks\sheets\leather.dm" @@ -1136,7 +1192,6 @@ #include "code\game\objects\items\tanks\tanks.dm" #include "code\game\objects\items\tanks\watertank.dm" #include "code\game\objects\items\tools\crowbar.dm" -#include "code\game\objects\items\tools\saw.dm" #include "code\game\objects\items\tools\screwdriver.dm" #include "code\game\objects\items\tools\weldingtool.dm" #include "code\game\objects\items\tools\wirecutters.dm" @@ -1236,6 +1291,7 @@ #include "code\game\objects\structures\crates_lockers\crates\secure.dm" #include "code\game\objects\structures\crates_lockers\crates\wooden.dm" #include "code\game\objects\structures\icemoon\cave_entrance.dm" +#include "code\game\objects\structures\lavaland\geyser.dm" #include "code\game\objects\structures\lavaland\necropolis_tendril.dm" #include "code\game\objects\structures\signs\_signs.dm" #include "code\game\objects\structures\signs\signs_departments.dm" @@ -1252,6 +1308,7 @@ #include "code\game\turfs\open.dm" #include "code\game\turfs\turf.dm" #include "code\game\turfs\openspace\openspace.dm" +#include "code\game\turfs\openspace\transparent.dm" #include "code\game\turfs\simulated\chasm.dm" #include "code\game\turfs\simulated\dirtystation.dm" #include "code\game\turfs\simulated\floor.dm" @@ -1271,6 +1328,7 @@ #include "code\game\turfs\simulated\floor\plating\asteroid.dm" #include "code\game\turfs\simulated\floor\plating\dirt.dm" #include "code\game\turfs\simulated\floor\plating\misc_plating.dm" +#include "code\game\turfs\simulated\wall\material_walls.dm" #include "code\game\turfs\simulated\wall\mineral_walls.dm" #include "code\game\turfs\simulated\wall\misc_walls.dm" #include "code\game\turfs\simulated\wall\reinf_walls.dm" @@ -1334,6 +1392,7 @@ #include "code\modules\admin\verbs\pray.dm" #include "code\modules\admin\verbs\randomverbs.dm" #include "code\modules\admin\verbs\reestablish_db_connection.dm" +#include "code\modules\admin\verbs\shuttlepanel.dm" #include "code\modules\admin\verbs\spawnobjasmob.dm" #include "code\modules\admin\verbs\tripAI.dm" #include "code\modules\admin\verbs\SDQL2\SDQL_2.dm" @@ -1345,6 +1404,7 @@ #include "code\modules\admin\view_variables\mark_datum.dm" #include "code\modules\admin\view_variables\mass_edit_variables.dm" #include "code\modules\admin\view_variables\modify_variables.dm" +#include "code\modules\admin\view_variables\reference_tracking.dm" #include "code\modules\admin\view_variables\topic.dm" #include "code\modules\admin\view_variables\topic_basic.dm" #include "code\modules\admin\view_variables\topic_list.dm" @@ -1355,6 +1415,7 @@ #include "code\modules\antagonists\_common\antag_spawner.dm" #include "code\modules\antagonists\_common\antag_team.dm" #include "code\modules\antagonists\abductor\abductor.dm" +#include "code\modules\antagonists\abductor\ice_abductor.dm" #include "code\modules\antagonists\abductor\abductee\abductee.dm" #include "code\modules\antagonists\abductor\abductee\abductee_objectives.dm" #include "code\modules\antagonists\abductor\abductee\trauma.dm" @@ -1362,6 +1423,7 @@ #include "code\modules\antagonists\abductor\equipment\abduction_outfits.dm" #include "code\modules\antagonists\abductor\equipment\abduction_surgery.dm" #include "code\modules\antagonists\abductor\equipment\gland.dm" +#include "code\modules\antagonists\abductor\equipment\orderable_gear.dm" #include "code\modules\antagonists\abductor\equipment\glands\access.dm" #include "code\modules\antagonists\abductor\equipment\glands\blood.dm" #include "code\modules\antagonists\abductor\equipment\glands\chem.dm" @@ -1479,6 +1541,7 @@ #include "code\modules\antagonists\clockcult\clock_effects\servant_blocker.dm" #include "code\modules\antagonists\clockcult\clock_effects\spatial_gateway.dm" #include "code\modules\antagonists\clockcult\clock_helpers\clock_powerdrain.dm" +#include "code\modules\antagonists\clockcult\clock_helpers\clock_rites.dm" #include "code\modules\antagonists\clockcult\clock_helpers\component_helpers.dm" #include "code\modules\antagonists\clockcult\clock_helpers\fabrication_helpers.dm" #include "code\modules\antagonists\clockcult\clock_helpers\hierophant_network.dm" @@ -1486,6 +1549,7 @@ #include "code\modules\antagonists\clockcult\clock_helpers\ratvarian_language.dm" #include "code\modules\antagonists\clockcult\clock_helpers\scripture_checks.dm" #include "code\modules\antagonists\clockcult\clock_helpers\slab_abilities.dm" +#include "code\modules\antagonists\clockcult\clock_items\clock_augments.dm" #include "code\modules\antagonists\clockcult\clock_items\clock_components.dm" #include "code\modules\antagonists\clockcult\clock_items\clockwork_armor.dm" #include "code\modules\antagonists\clockcult\clock_items\clockwork_slab.dm" @@ -1497,6 +1561,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\brass_claw.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" @@ -1504,6 +1569,7 @@ #include "code\modules\antagonists\clockcult\clock_scriptures\scripture_applications.dm" #include "code\modules\antagonists\clockcult\clock_scriptures\scripture_cyborg.dm" #include "code\modules\antagonists\clockcult\clock_scriptures\scripture_drivers.dm" +#include "code\modules\antagonists\clockcult\clock_scriptures\scripture_judgement.dm" #include "code\modules\antagonists\clockcult\clock_scriptures\scripture_scripts.dm" #include "code\modules\antagonists\clockcult\clock_structures\_trap_object.dm" #include "code\modules\antagonists\clockcult\clock_structures\ark_of_the_clockwork_justicar.dm" @@ -1512,6 +1578,7 @@ #include "code\modules\antagonists\clockcult\clock_structures\heralds_beacon.dm" #include "code\modules\antagonists\clockcult\clock_structures\mania_motor.dm" #include "code\modules\antagonists\clockcult\clock_structures\ocular_warden.dm" +#include "code\modules\antagonists\clockcult\clock_structures\prolonging_prism.dm" #include "code\modules\antagonists\clockcult\clock_structures\ratvar_the_clockwork_justicar.dm" #include "code\modules\antagonists\clockcult\clock_structures\reflector.dm" #include "code\modules\antagonists\clockcult\clock_structures\stargazer.dm" @@ -1545,6 +1612,16 @@ #include "code\modules\antagonists\disease\disease_disease.dm" #include "code\modules\antagonists\disease\disease_event.dm" #include "code\modules\antagonists\disease\disease_mob.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_antag.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_book.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_effects.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_items.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_knowledge.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_magic.dm" +#include "code\modules\antagonists\eldritch_cult\eldritch_monster_antag.dm" +#include "code\modules\antagonists\eldritch_cult\knowledge\ash_lore.dm" +#include "code\modules\antagonists\eldritch_cult\knowledge\flesh_lore.dm" +#include "code\modules\antagonists\eldritch_cult\knowledge\rust_lore.dm" #include "code\modules\antagonists\ert\ert.dm" #include "code\modules\antagonists\fugitive\fugitive.dm" #include "code\modules\antagonists\fugitive\fugitive_outfits.dm" @@ -1630,6 +1707,11 @@ #include "code\modules\assembly\signaler.dm" #include "code\modules\assembly\timer.dm" #include "code\modules\assembly\voice.dm" +#include "code\modules\asset_cache\asset_cache.dm" +#include "code\modules\asset_cache\asset_cache_client.dm" +#include "code\modules\asset_cache\asset_cache_item.dm" +#include "code\modules\asset_cache\asset_list.dm" +#include "code\modules\asset_cache\asset_list_items.dm" #include "code\modules\atmospherics\multiz.dm" #include "code\modules\atmospherics\environmental\LINDA_fire.dm" #include "code\modules\atmospherics\environmental\LINDA_system.dm" @@ -1700,7 +1782,6 @@ #include "code\modules\awaymissions\mission_code\murderdome.dm" #include "code\modules\awaymissions\mission_code\research.dm" #include "code\modules\awaymissions\mission_code\snowdin.dm" -#include "code\modules\awaymissions\mission_code\spacebattle.dm" #include "code\modules\awaymissions\mission_code\stationCollision.dm" #include "code\modules\awaymissions\mission_code\undergroundoutpost45.dm" #include "code\modules\awaymissions\mission_code\wildwest.dm" @@ -1722,6 +1803,7 @@ #include "code\modules\cargo\bounty_console.dm" #include "code\modules\cargo\centcom_podlauncher.dm" #include "code\modules\cargo\console.dm" +#include "code\modules\cargo\coupon.dm" #include "code\modules\cargo\export_scanner.dm" #include "code\modules\cargo\exports.dm" #include "code\modules\cargo\expressconsole.dm" @@ -1762,6 +1844,7 @@ #include "code\modules\cargo\packs\emergency.dm" #include "code\modules\cargo\packs\engine.dm" #include "code\modules\cargo\packs\engineering.dm" +#include "code\modules\cargo\packs\goodies.dm" #include "code\modules\cargo\packs\livestock.dm" #include "code\modules\cargo\packs\materials.dm" #include "code\modules\cargo\packs\medical.dm" @@ -1772,7 +1855,6 @@ #include "code\modules\cargo\packs\service.dm" #include "code\modules\cargo\packs\vending.dm" #include "code\modules\chatter\chatter.dm" -#include "code\modules\client\asset_cache.dm" #include "code\modules\client\client_colour.dm" #include "code\modules\client\client_defines.dm" #include "code\modules\client\client_procs.dm" @@ -1784,6 +1866,7 @@ #include "code\modules\client\preferences_toggles.dm" #include "code\modules\client\preferences_vr.dm" #include "code\modules\client\verbs\aooc.dm" +#include "code\modules\client\verbs\autobunker.dm" #include "code\modules\client\verbs\etips.dm" #include "code\modules\client\verbs\looc.dm" #include "code\modules\client\verbs\minimap.dm" @@ -1933,6 +2016,7 @@ #include "code\modules\events\spider_infestation.dm" #include "code\modules\events\spontaneous_appendicitis.dm" #include "code\modules\events\stray_cargo.dm" +#include "code\modules\events\travelling_trader.dm" #include "code\modules\events\vent_clog.dm" #include "code\modules\events\wisdomcow.dm" #include "code\modules\events\wormholes.dm" @@ -1950,6 +2034,7 @@ #include "code\modules\events\wizard\imposter.dm" #include "code\modules\events\wizard\invincible.dm" #include "code\modules\events\wizard\lava.dm" +#include "code\modules\events\wizard\madness.dm" #include "code\modules\events\wizard\magicarp.dm" #include "code\modules\events\wizard\petsplosion.dm" #include "code\modules\events\wizard\race.dm" @@ -2213,6 +2298,7 @@ #include "code\modules\language\swarmer.dm" #include "code\modules\language\sylvan.dm" #include "code\modules\language\vampiric.dm" +#include "code\modules\language\voltaic.dm" #include "code\modules\language\xenocommon.dm" #include "code\modules\library\lib_codex_gigas.dm" #include "code\modules\library\lib_items.dm" @@ -2227,6 +2313,11 @@ #include "code\modules\lighting\lighting_setup.dm" #include "code\modules\lighting\lighting_source.dm" #include "code\modules\lighting\lighting_turf.dm" +#include "code\modules\mafia\_defines.dm" +#include "code\modules\mafia\controller.dm" +#include "code\modules\mafia\map_pieces.dm" +#include "code\modules\mafia\outfits.dm" +#include "code\modules\mafia\roles.dm" #include "code\modules\mapping\map_config.dm" #include "code\modules\mapping\map_orientation_pattern.dm" #include "code\modules\mapping\map_template.dm" @@ -2281,6 +2372,7 @@ #include "code\modules\mining\lavaland\ash_flora.dm" #include "code\modules\mining\lavaland\necropolis_chests.dm" #include "code\modules\mining\lavaland\ruins\gym.dm" +#include "code\modules\mob\clickdelay.dm" #include "code\modules\mob\death.dm" #include "code\modules\mob\emote.dm" #include "code\modules\mob\inventory.dm" @@ -2329,9 +2421,11 @@ #include "code\modules\mob\dead\observer\notificationprefs.dm" #include "code\modules\mob\dead\observer\observer.dm" #include "code\modules\mob\dead\observer\observer_movement.dm" +#include "code\modules\mob\dead\observer\orbit.dm" #include "code\modules\mob\dead\observer\say.dm" #include "code\modules\mob\living\blood.dm" #include "code\modules\mob\living\bloodcrawl.dm" +#include "code\modules\mob\living\clickdelay.dm" #include "code\modules\mob\living\damage_procs.dm" #include "code\modules\mob\living\death.dm" #include "code\modules\mob\living\emote.dm" @@ -2363,6 +2457,7 @@ #include "code\modules\mob\living\brain\say.dm" #include "code\modules\mob\living\brain\status_procs.dm" #include "code\modules\mob\living\carbon\carbon.dm" +#include "code\modules\mob\living\carbon\carbon_active_parry.dm" #include "code\modules\mob\living\carbon\carbon_defense.dm" #include "code\modules\mob\living\carbon\carbon_defines.dm" #include "code\modules\mob\living\carbon\carbon_movement.dm" @@ -2393,7 +2488,6 @@ #include "code\modules\mob\living\carbon\alien\humanoid\death.dm" #include "code\modules\mob\living\carbon\alien\humanoid\humanoid.dm" #include "code\modules\mob\living\carbon\alien\humanoid\humanoid_defense.dm" -#include "code\modules\mob\living\carbon\alien\humanoid\inventory.dm" #include "code\modules\mob\living\carbon\alien\humanoid\life.dm" #include "code\modules\mob\living\carbon\alien\humanoid\queen.dm" #include "code\modules\mob\living\carbon\alien\humanoid\update_icons.dm" @@ -2438,6 +2532,7 @@ #include "code\modules\mob\living\carbon\human\species_types\corporate.dm" #include "code\modules\mob\living\carbon\human\species_types\dullahan.dm" #include "code\modules\mob\living\carbon\human\species_types\dwarves.dm" +#include "code\modules\mob\living\carbon\human\species_types\ethereal.dm" #include "code\modules\mob\living\carbon\human\species_types\felinid.dm" #include "code\modules\mob\living\carbon\human\species_types\flypeople.dm" #include "code\modules\mob\living\carbon\human\species_types\furrypeople.dm" @@ -2454,6 +2549,7 @@ #include "code\modules\mob\living\carbon\human\species_types\synthliz.dm" #include "code\modules\mob\living\carbon\human\species_types\synths.dm" #include "code\modules\mob\living\carbon\human\species_types\vampire.dm" +#include "code\modules\mob\living\carbon\human\species_types\xeno.dm" #include "code\modules\mob\living\carbon\human\species_types\zombies.dm" #include "code\modules\mob\living\carbon\monkey\combat.dm" #include "code\modules\mob\living\carbon\monkey\death.dm" @@ -2517,7 +2613,9 @@ #include "code\modules\mob\living\simple_animal\constructs.dm" #include "code\modules\mob\living\simple_animal\corpse.dm" #include "code\modules\mob\living\simple_animal\damage_procs.dm" +#include "code\modules\mob\living\simple_animal\eldritch_demons.dm" #include "code\modules\mob\living\simple_animal\parrot.dm" +#include "code\modules\mob\living\simple_animal\pickle.dm" #include "code\modules\mob\living\simple_animal\shade.dm" #include "code\modules\mob\living\simple_animal\simple_animal.dm" #include "code\modules\mob\living\simple_animal\simple_animal_vr.dm" @@ -2549,6 +2647,7 @@ #include "code\modules\mob\living\simple_animal\friendly\penguin.dm" #include "code\modules\mob\living\simple_animal\friendly\pet.dm" #include "code\modules\mob\living\simple_animal\friendly\plushie.dm" +#include "code\modules\mob\living\simple_animal\friendly\possum.dm" #include "code\modules\mob\living\simple_animal\friendly\sloth.dm" #include "code\modules\mob\living\simple_animal\friendly\snake.dm" #include "code\modules\mob\living\simple_animal\friendly\drone\_drone.dm" @@ -2656,6 +2755,7 @@ #include "code\modules\mob\living\simple_animal\slime\slime_mobility.dm" #include "code\modules\mob\living\simple_animal\slime\subtypes.dm" #include "code\modules\modular_computers\laptop_vendor.dm" +#include "code\modules\modular_computers\computers\_modular_computer_shared.dm" #include "code\modules\modular_computers\computers\item\computer.dm" #include "code\modules\modular_computers\computers\item\computer_components.dm" #include "code\modules\modular_computers\computers\item\computer_damage.dm" @@ -2675,14 +2775,20 @@ #include "code\modules\modular_computers\file_system\program_events.dm" #include "code\modules\modular_computers\file_system\programs\airestorer.dm" #include "code\modules\modular_computers\file_system\programs\alarm.dm" +#include "code\modules\modular_computers\file_system\programs\arcade.dm" +#include "code\modules\modular_computers\file_system\programs\atmosscan.dm" #include "code\modules\modular_computers\file_system\programs\card.dm" +#include "code\modules\modular_computers\file_system\programs\cargobounty.dm" #include "code\modules\modular_computers\file_system\programs\configurator.dm" +#include "code\modules\modular_computers\file_system\programs\crewmanifest.dm" #include "code\modules\modular_computers\file_system\programs\file_browser.dm" +#include "code\modules\modular_computers\file_system\programs\jobmanagement.dm" #include "code\modules\modular_computers\file_system\programs\ntdownloader.dm" #include "code\modules\modular_computers\file_system\programs\ntmonitor.dm" #include "code\modules\modular_computers\file_system\programs\ntnrc_client.dm" -#include "code\modules\modular_computers\file_system\programs\nttransfer.dm" #include "code\modules\modular_computers\file_system\programs\powermonitor.dm" +#include "code\modules\modular_computers\file_system\programs\radar.dm" +#include "code\modules\modular_computers\file_system\programs\robocontrol.dm" #include "code\modules\modular_computers\file_system\programs\sm_monitor.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\contract_uplink.dm" #include "code\modules\modular_computers\file_system\programs\antagonist\dos.dm" @@ -2741,10 +2847,6 @@ #include "code\modules\NTNet\network.dm" #include "code\modules\NTNet\relays.dm" #include "code\modules\NTNet\services\_service.dm" -#include "code\modules\oracle_ui\assets.dm" -#include "code\modules\oracle_ui\hookup_procs.dm" -#include "code\modules\oracle_ui\oracle_ui.dm" -#include "code\modules\oracle_ui\themed.dm" #include "code\modules\paperwork\clipboard.dm" #include "code\modules\paperwork\contract.dm" #include "code\modules\paperwork\filingcabinet.dm" @@ -2767,6 +2869,21 @@ #include "code\modules\photography\photos\album.dm" #include "code\modules\photography\photos\frame.dm" #include "code\modules\photography\photos\photo.dm" +#include "code\modules\plumbing\ducts.dm" +#include "code\modules\plumbing\plumbers\_plumb_machinery.dm" +#include "code\modules\plumbing\plumbers\acclimator.dm" +#include "code\modules\plumbing\plumbers\autohydro.dm" +#include "code\modules\plumbing\plumbers\bottler.dm" +#include "code\modules\plumbing\plumbers\destroyer.dm" +#include "code\modules\plumbing\plumbers\fermenter.dm" +#include "code\modules\plumbing\plumbers\filter.dm" +#include "code\modules\plumbing\plumbers\grinder_chemical.dm" +#include "code\modules\plumbing\plumbers\medipenrefill.dm" +#include "code\modules\plumbing\plumbers\pill_press.dm" +#include "code\modules\plumbing\plumbers\pumps.dm" +#include "code\modules\plumbing\plumbers\reaction_chamber.dm" +#include "code\modules\plumbing\plumbers\splitters.dm" +#include "code\modules\plumbing\plumbers\synthesizer.dm" #include "code\modules\pool\pool_controller.dm" #include "code\modules\pool\pool_drain.dm" #include "code\modules\pool\pool_effects.dm" @@ -2984,6 +3101,7 @@ #include "code\modules\reagents\reagent_containers\blood_pack.dm" #include "code\modules\reagents\reagent_containers\borghydro.dm" #include "code\modules\reagents\reagent_containers\bottle.dm" +#include "code\modules\reagents\reagent_containers\chem_pack.dm" #include "code\modules\reagents\reagent_containers\dropper.dm" #include "code\modules\reagents\reagent_containers\glass.dm" #include "code\modules\reagents\reagent_containers\hypospray.dm" @@ -3015,6 +3133,7 @@ #include "code\modules\research\research_disk.dm" #include "code\modules\research\server.dm" #include "code\modules\research\stock_parts.dm" +#include "code\modules\research\anomaly\anomaly_core.dm" #include "code\modules\research\designs\AI_module_designs.dm" #include "code\modules\research\designs\autobotter_designs.dm" #include "code\modules\research\designs\autoylathe_designs.dm" @@ -3184,11 +3303,12 @@ #include "code\modules\spells\spell.dm" #include "code\modules\spells\spell_types\aimed.dm" #include "code\modules\spells\spell_types\area_teleport.dm" -#include "code\modules\spells\spell_types\barnyard.dm" #include "code\modules\spells\spell_types\bloodcrawl.dm" #include "code\modules\spells\spell_types\charge.dm" +#include "code\modules\spells\spell_types\cone_spells.dm" #include "code\modules\spells\spell_types\conjure.dm" #include "code\modules\spells\spell_types\construct_spells.dm" +#include "code\modules\spells\spell_types\curse.dm" #include "code\modules\spells\spell_types\devil.dm" #include "code\modules\spells\spell_types\devil_boons.dm" #include "code\modules\spells\spell_types\dumbfire.dm" @@ -3204,7 +3324,6 @@ #include "code\modules\spells\spell_types\lichdom.dm" #include "code\modules\spells\spell_types\lightning.dm" #include "code\modules\spells\spell_types\mime.dm" -#include "code\modules\spells\spell_types\mind_transfer.dm" #include "code\modules\spells\spell_types\projectile.dm" #include "code\modules\spells\spell_types\rightandwrong.dm" #include "code\modules\spells\spell_types\rod_form.dm" @@ -3221,12 +3340,18 @@ #include "code\modules\spells\spell_types\turf_teleport.dm" #include "code\modules\spells\spell_types\voice_of_god.dm" #include "code\modules\spells\spell_types\wizard.dm" +#include "code\modules\spells\spell_types\pointed\barnyard.dm" +#include "code\modules\spells\spell_types\pointed\blind.dm" +#include "code\modules\spells\spell_types\pointed\mind_transfer.dm" +#include "code\modules\spells\spell_types\pointed\pointed.dm" #include "code\modules\station_goals\bsa.dm" #include "code\modules\station_goals\dna_vault.dm" #include "code\modules\station_goals\shield.dm" #include "code\modules\station_goals\station_goal.dm" #include "code\modules\surgery\amputation.dm" +#include "code\modules\surgery\bone_mending.dm" #include "code\modules\surgery\brain_surgery.dm" +#include "code\modules\surgery\burn_dressing.dm" #include "code\modules\surgery\cavity_implant.dm" #include "code\modules\surgery\core_removal.dm" #include "code\modules\surgery\coronary_bypass.dm" @@ -3249,6 +3374,7 @@ #include "code\modules\surgery\plastic_surgery.dm" #include "code\modules\surgery\prosthetic_replacement.dm" #include "code\modules\surgery\remove_embedded_object.dm" +#include "code\modules\surgery\repair_puncture.dm" #include "code\modules\surgery\robot_brain_surgery.dm" #include "code\modules\surgery\robot_healing.dm" #include "code\modules\surgery\surgery.dm" @@ -3269,10 +3395,11 @@ #include "code\modules\surgery\advanced\bioware\nerve_grounding.dm" #include "code\modules\surgery\advanced\bioware\nerve_splicing.dm" #include "code\modules\surgery\advanced\bioware\vein_threading.dm" -#include "code\modules\surgery\bodyparts\bodyparts.dm" +#include "code\modules\surgery\bodyparts\_bodyparts.dm" #include "code\modules\surgery\bodyparts\dismemberment.dm" #include "code\modules\surgery\bodyparts\head.dm" #include "code\modules\surgery\bodyparts\helpers.dm" +#include "code\modules\surgery\bodyparts\parts.dm" #include "code\modules\surgery\bodyparts\robot_bodyparts.dm" #include "code\modules\surgery\organs\appendix.dm" #include "code\modules\surgery\organs\augments_arms.dm" @@ -3294,8 +3421,8 @@ #include "code\modules\tgs\includes.dm" #include "code\modules\tgui\external.dm" #include "code\modules\tgui\states.dm" -#include "code\modules\tgui\subsystem.dm" #include "code\modules\tgui\tgui.dm" +#include "code\modules\tgui\tgui_window.dm" #include "code\modules\tgui\states\admin.dm" #include "code\modules\tgui\states\always.dm" #include "code\modules\tgui\states\conscious.dm" @@ -3393,12 +3520,6 @@ #include "interface\menu.dm" #include "interface\stylesheet.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" -#include "modular_citadel\code\_onclick\hud\screen_objects.dm" -#include "modular_citadel\code\_onclick\hud\sprint.dm" -#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\objects\cit_screenshake.dm" @@ -3443,7 +3564,6 @@ #include "modular_citadel\code\modules\mob\living\living.dm" #include "modular_citadel\code\modules\mob\living\carbon\carbon.dm" #include "modular_citadel\code\modules\mob\living\carbon\damage_procs.dm" -#include "modular_citadel\code\modules\mob\living\carbon\life.dm" #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" diff --git a/tgui-next/.gitattributes b/tgui-next/.gitattributes deleted file mode 100644 index 0016cc3bf6..0000000000 --- a/tgui-next/.gitattributes +++ /dev/null @@ -1,10 +0,0 @@ -* text=auto - -## Enforce text mode and LF line breaks -*.js text eol=lf -*.css text eol=lf -*.html text eol=lf -*.json text eol=lf - -## Treat bundles as binary and ignore them during conflicts -*.bundle.* binary merge=tgui-merge-bundle diff --git a/tgui-next/.gitignore b/tgui-next/.gitignore deleted file mode 100644 index 416ca3768d..0000000000 --- a/tgui-next/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -node_modules -*.log -package-lock.json - -/packages/tgui/public/.tmp/**/* -/packages/tgui/public/**/*.hot-update.* -/packages/tgui/public/**/*.map diff --git a/tgui-next/docs/tutorial-and-examples.md b/tgui-next/docs/tutorial-and-examples.md deleted file mode 100644 index d038c1de61..0000000000 --- a/tgui-next/docs/tutorial-and-examples.md +++ /dev/null @@ -1,245 +0,0 @@ -# Tutorial and Examples - -## Main concepts - -Basic tgui backend code consists of the following vars and procs: - -``` -ui_interact(mob/user, ui_key, datum/tgui/ui, force_open, - datum/tgui/master_ui, datum/ui_state/state) -ui_data(mob/user) -ui_act(action, params) -``` - -- `src_object` - The atom, which UI corresponds to in the game world. -- `ui_interact` - The proc where you will handle a request to open an -interface. Typically, you would update an existing UI (if it exists), -or set up a new instance of UI by calling the `SStgui` subsystem. -- `ui_data` - In this proc you munges whatever complex data your `src_object` -has into an associative list, which will then be sent to UI as a JSON string. -- `ui_act` - This proc receives user actions and reacts to them by changing -the state of the game. -- `ui_state` (set in `ui_interact`) - This var dictates under what conditions -a UI may be interacted with. This may be the standard checks that check if -you are in range and conscious, or more. - -Once backend is complete, you create an new interface component on the -frontend, which will receive this JSON data and render it on screen. - -States are easy to write and extend, and what make tgui interactions so -powerful. Because states can be overridden from other procs, you can build -powerful interactions for embedded objects or remote access. - -## Using It - -### Backend - -Let's start with a very basic hello world. - -```dm -/obj/machinery/my_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "my_machine", name, 300, 300, master_ui, state) - ui.open() -``` - -This is the proc that defines our interface. There's a bit going on here, so -let's break it down. First, we override the ui_interact proc on our object. This -will be called by `interact` for you, which is in turn called by `attack_hand` -(or `attack_self` for items). `ui_interact` is also called to update a UI (hence -the `try_update_ui`), so we accept an existing UI to update. The `state` is a -default argument so that a caller can overload it with named arguments -(`ui_interact(state = overloaded_state)`) if needed. - -Inside the `if(!ui)` block (which means we are creating a new UI), we choose our -template, title, and size; we can also set various options like `style` (for -themes), or autoupdate. These options will be elaborated on later (as will -`ui_state`s). - -After `ui_interact`, we need to define `ui_data`. This just returns a list of -data for our object to use. Let's imagine our object has a few vars: - -```dm -/obj/machinery/my_machine/ui_data(mob/user) - var/list/data = list() - data["health"] = health - data["color"] = color - - return data -``` - -The `ui_data` proc is what people often find the hardest about tgui, but its -really quite simple! You just need to represent your object as numbers, strings, -and lists, instead of atoms and datums. - -Finally, the `ui_act` proc is called by the interface whenever the user used an -input. The input's `action` and `params` are passed to the proc. - -```dm -/obj/machinery/my_machine/ui_act(action, params) - if(..()) - return - switch(action) - if("change_color") - var/new_color = params["color"] - if(!(color in allowed_coors)) - return - color = new_color - . = TRUE - update_icon() -``` - -The `..()` (parent call) is very important here, as it is how we check that the -user is allowed to use this interface (to avoid so-called href exploits). It is -also very important to clamp and sanitize all input here. Always assume the user -is attempting to exploit the game. - -Also note the use of `. = TRUE` (or `FALSE`), which is used to notify the UI -that this input caused an update. This is especially important for UIs that do -not auto-update, as otherwise the user will never see their change. - -### Frontend - -Finally, you have to make a UI component. This is also a source of -confusion for many new users. If you got some basic javascript and HTML -knowledge, that should ease the learning process, although we recommend -getting yourself introduced to -[React and JSX](https://reactjs.org/docs/introducing-jsx.html). - -A component is not a regular HTML. A component is a pure function, which -accepts a `props` object (it contains properties passed to a component), -and outputs an HTML-like structure consisting of regular HTML elements and -other UI components. - -Interface component will always receive 1 prop which is called `state`. -This object contains a few special values: - -- `config` is always the same and is part of core tgui -(it will be explained later), -- `data` is the data returned from `ui_data` - -```jsx -import { Section, LabeledList } from '../components'; - -const SampleInterface = props => { - const { state } = props; - const { config, data } = state; - const { ref } = config; - return ( -
      - - - {data.health} - - - {data.color} - - -
      - ); -}; -``` - -This syntax can be very confusing at first, but it is very important to -realize that this is just a natural extension of javascript. Here's a few -examples of this syntax: - -Return a different element based on a condition: - -```jsx -if (condition) { - return ; -} -return ; -``` - -Conditionally render a element inside of another element: - -```jsx - - {showProgress && ( - - )} - -``` - -Looping over the array to make an element for each item: - -```jsx - - {items.map(item => ( - - {item.content} - - ))} - -``` - -### Routing table - -Once you finished creating your interface, you need to add a route entry to -the large `ROUTES` object, otherwise tgui won't know when and how to render -your interface. Key of this `ROUTES` object corresponds to the interface -name you use in DM code. - -```js -import { SampleInterface } from './interfaces/SampleInterface'; - -const ROUTES = { - sample_interface: { - component: () => SampleInterface, - scrollable: true, - }, -}; -``` - -## Copypasta - -We all do it, even the best of us. If you just want to make a tgui **fast**, -here's what you need (note that you'll probably be forced to clean your shit up -upon code review): - -```dm -/obj/copypasta/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) // Remember to use the appropriate state. - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "copypasta", name, 300, 300, master_ui, state) - ui.open() - -/obj/copypasta/ui_data(mob/user) - var/list/data = list() - data["var"] = var - return data - -/obj/copypasta/ui_act(action, params) - if(..()) - return - if(action == "copypasta") - var/newvar = params["var"] - // A demo of proper input sanitation. - var = CLAMP(newvar, min_val, max_val) - return TRUE - update_icon() // Not applicable to all objects. -``` - -And the template: - -```jsx -import { Section, LabeledList } from '../components'; - -const SampleInterface = props => { - const { state } = props; - const { config, data } = state; - const { ref } = config; - return ( -
      - - - {data.var} - - -
      - ); -}; -``` diff --git a/tgui-next/package.json b/tgui-next/package.json deleted file mode 100644 index 9b7253e131..0000000000 --- a/tgui-next/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "private": true, - "name": "tgui-next", - "version": "0.1.0", - "workspaces": [ - "packages/*" - ], - "scripts": { - "build": "eslint packages && cd packages/tgui && npx webpack --mode=production", - "watch": "cd packages/tgui-dev-server && node --experimental-modules index.js", - "analyze": "cd packages/tgui && npx webpack --mode=production --env.analyze=1", - "lint": "eslint packages" - }, - "dependencies": { - "babel-eslint": "^10.0.3", - "eslint": "^6.7.2", - "eslint-plugin-react": "^7.17.0" - } -} diff --git a/tgui-next/packages/common/math.js b/tgui-next/packages/common/math.js deleted file mode 100644 index a33b9aa214..0000000000 --- a/tgui-next/packages/common/math.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Limits a number to the range between 'min' and 'max'. - */ -export const clamp = (value, min = 0, max = 1) => { - return Math.max(min, Math.min(value, max)); -}; - -/** - * Returns a rounded number. - * TODO: Replace this native rounding function with a more robust one. - */ -export const round = value => Math.round(value); - -/** - * Returns a string representing a number in fixed point notation. - */ -export const toFixed = (value, fractionDigits = 0) => { - return Number(value).toFixed(fractionDigits); -}; diff --git a/tgui-next/packages/tgui/backend.js b/tgui-next/packages/tgui/backend.js deleted file mode 100644 index cdaf89fc6b..0000000000 --- a/tgui-next/packages/tgui/backend.js +++ /dev/null @@ -1,95 +0,0 @@ -import { UI_DISABLED, UI_INTERACTIVE } from './constants'; -import { tridentVersion, act as _act } from './byond'; - -/** - * This file provides a clear separation layer between backend updates - * and what state our React app sees. - * - * Sometimes backend can response without a "data" field, but our final - * state will still contain previous "data" because we are merging - * the response with already existing state. - */ - -/** - * Creates a backend update action. - */ -export const backendUpdate = state => ({ - type: 'backendUpdate', - payload: state, -}); - -/** - * Precisely defines state changes. - */ -export const backendReducer = (state, action) => { - const { type, payload } = action; - - if (type === 'backendUpdate') { - // Merge config - const config = { - ...state.config, - ...payload.config, - }; - // Merge data - const data = { - ...state.data, - ...payload.static_data, - ...payload.data, - }; - // Calculate our own fields - const visible = config.status !== UI_DISABLED; - const interactive = config.status === UI_INTERACTIVE; - // Return new state - return { - ...state, - config, - data, - visible, - interactive, - }; - } - - return state; -}; - -/** - * @typedef BackendState - * @type {{ - * config: { - * title: string, - * status: number, - * screen: string, - * style: string, - * interface: string, - * fancy: number, - * locked: number, - * observer: number, - * window: string, - * ref: string, - * }, - * data: any, - * visible: boolean, - * interactive: boolean, - * }} - */ - -/** - * A React hook (sort of) for getting tgui state and related functions. - * - * This is supposed to be replaced with a real React Hook, which can only - * be used in functional components. DO NOT use it in class-based components! - * - * @return {BackendState & { - * act: (action: string, params?: object) => void, - * }} - */ -export const useBackend = props => { - // TODO: Dispatch "act" calls as Redux actions - const { state, dispatch } = props; - const ref = state.config.ref; - const act = (action, params = {}) => _act(ref, action, params); - return { - ...state, - act, - }; -}; diff --git a/tgui-next/packages/tgui/byond.js b/tgui-next/packages/tgui/byond.js deleted file mode 100644 index 2b7d3ff772..0000000000 --- a/tgui-next/packages/tgui/byond.js +++ /dev/null @@ -1,84 +0,0 @@ -import { buildQueryString } from 'common/string'; - -/** - * Version of Trident engine used in Internet Explorer. - * - * - IE 8 - Trident 4.0 - * - IE 11 - Trident 7.0 - * - * @return An integer number or 'null' if this is not a trident engine. - */ -export const tridentVersion = (() => { - const { userAgent } = navigator; - const groups = userAgent.match(/Trident\/(\d+).+?;/i); - const majorVersion = groups[1]; - if (!majorVersion) { - return null; - } - return parseInt(majorVersion, 10); -})(); - -/** - * Helper to generate a BYOND href given 'params' as an object - * (with an optional 'url' for eg winset). - */ -const href = (url, params = {}) => { - return 'byond://' + url + '?' + buildQueryString(params); -}; - -export const callByond = (url, params = {}) => { - window.location.href = href(url, params); -}; - -/** - * A high-level abstraction of BYJAX. Makes a call to BYOND and returns - * a promise, which (if endpoint has a callback parameter) resolves - * with the return value of that call. - */ -export const callByondAsync = (url, params = {}) => { - // Create a callback array if it doesn't exist yet - window.__callbacks__ = window.__callbacks__ || []; - // Create a Promise and push its resolve function into callback array - const callbackIndex = window.__callbacks__.length; - const promise = new Promise(resolve => { - // TODO: Fix a potential memory leak - window.__callbacks__.push(resolve); - }); - // Call BYOND client - window.location.href = href(url, { - ...params, - callback: `__callbacks__[${callbackIndex}]`, - }); - return promise; -}; - -/** - * Literally types a command on the client. - */ -export const runCommand = command => callByond('winset', { command }); - -/** - * Helper to make a BYOND ui_act() call on the UI 'src' given an 'action' - * and optional 'params'. - */ -export const act = (src, action, params = {}) => { - return callByond('', { src, action, ...params }); -}; - -/** - * Calls 'winget' on window, retrieving value by the 'key'. - */ -export const winget = async (win, key) => { - const obj = await callByondAsync('winget', { - id: win, - property: key, - }); - return obj[key]; -}; - -/** - * Calls 'winset' on window, setting 'key' to 'value'. - */ -export const winset = (win, key, value) => callByond('winset', { - [`${win}.${key}`]: value, -}); diff --git a/tgui-next/packages/tgui/components/ColorBox.js b/tgui-next/packages/tgui/components/ColorBox.js deleted file mode 100644 index 0bfe368d82..0000000000 --- a/tgui-next/packages/tgui/components/ColorBox.js +++ /dev/null @@ -1,19 +0,0 @@ -import { classes, pureComponentHooks } from 'common/react'; -import { Box } from './Box'; - -export const ColorBox = props => { - const { color, content, className, ...rest } = props; - return ( - - ); -}; - -ColorBox.defaultHooks = pureComponentHooks; diff --git a/tgui-next/packages/tgui/components/Dimmer.js b/tgui-next/packages/tgui/components/Dimmer.js deleted file mode 100644 index 9d3ead0549..0000000000 --- a/tgui-next/packages/tgui/components/Dimmer.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Box } from './Box'; - -export const Dimmer = props => { - const { style, ...rest } = props; - return ( - - ); -}; diff --git a/tgui-next/packages/tgui/components/NoticeBox.js b/tgui-next/packages/tgui/components/NoticeBox.js deleted file mode 100644 index f57e4d9082..0000000000 --- a/tgui-next/packages/tgui/components/NoticeBox.js +++ /dev/null @@ -1,16 +0,0 @@ -import { classes, pureComponentHooks } from 'common/react'; -import { Box } from './Box'; - -export const NoticeBox = props => { - const { className, ...rest } = props; - return ( - - ); -}; - -NoticeBox.defaultHooks = pureComponentHooks; diff --git a/tgui-next/packages/tgui/components/ProgressBar.js b/tgui-next/packages/tgui/components/ProgressBar.js deleted file mode 100644 index e58bfa3869..0000000000 --- a/tgui-next/packages/tgui/components/ProgressBar.js +++ /dev/null @@ -1,50 +0,0 @@ -import { classes, pureComponentHooks } from 'common/react'; -import { clamp, toFixed } from 'common/math'; - -export const ProgressBar = props => { - const { - value, - minValue = 0, - maxValue = 1, - ranges = {}, - content, - children, - } = props; - const scaledValue = (value - minValue) / (maxValue - minValue); - const hasContent = content !== undefined || children !== undefined; - let { color } = props; - // Cycle through ranges in key order to determine progressbar color. - if (!color) { - for (let rangeName of Object.keys(ranges)) { - const range = ranges[rangeName]; - if (range && value >= range[0] && value <= range[1]) { - color = rangeName; - break; - } - } - } - // Default color - if (!color) { - color = 'default'; - } - return ( -
      -
      -
      - {hasContent && content} - {hasContent && children} - {!hasContent && toFixed(scaledValue * 100) + '%'} -
      -
      - ); -}; - -ProgressBar.defaultHooks = pureComponentHooks; diff --git a/tgui-next/packages/tgui/components/Tabs.js b/tgui-next/packages/tgui/components/Tabs.js deleted file mode 100644 index b3d02ef820..0000000000 --- a/tgui-next/packages/tgui/components/Tabs.js +++ /dev/null @@ -1,135 +0,0 @@ -import { classes, normalizeChildren } from 'common/react'; -import { Component } from 'inferno'; -import { Box } from './Box'; -import { Button } from './Button'; - -// A magic value for enforcing type safety -const TAB_MAGIC_TYPE = 'Tab'; - -const validateTabs = tabs => { - for (let tab of tabs) { - if (!tab.props || tab.props.__type__ !== TAB_MAGIC_TYPE) { - const json = JSON.stringify(tab, null, 2); - throw new Error(' only accepts children of type .' - + 'This is what we received: ' + json); - } - } -}; - -export class Tabs extends Component { - constructor(props) { - super(props); - this.state = { - activeTabKey: null, - }; - } - - getActiveTab() { - const { state, props } = this; - const tabs = normalizeChildren(props.children); - validateTabs(tabs); - // Get active tab - let activeTabKey = props.activeTab || state.activeTabKey; - // Verify that active tab exists - let activeTab = tabs - .find(tab => { - const key = tab.key || tab.props.label; - return key === activeTabKey; - }); - // Set first tab as the active tab - if (!activeTab) { - activeTab = tabs[0]; - activeTabKey = activeTab && (activeTab.key || activeTab.props.label); - } - return { - tabs, - activeTab, - activeTabKey, - }; - } - - render() { - const { props } = this; - const { - className, - vertical, - children, - ...rest - } = props; - const { - tabs, - activeTab, - activeTabKey, - } = this.getActiveTab(); - // Retrieve tab content - let content = null; - if (activeTab) { - content = activeTab.props.content || activeTab.props.children; - } - // Get children by calling a wrapper function - if (typeof content === 'function') { - content = content(activeTabKey); - } - return ( - -
      - {tabs.map(tab => { - const { - className, - label, - content, // ignored - children, // ignored - onClick, - highlight, - ...rest - } = tab.props; - const key = tab.key || tab.props.label; - const active = tab.active || key === activeTabKey; - return ( - - ); - })} -
      -
      - {content || null} -
      -
      - ); - } -} - -/** - * A dummy component, which is used for carrying props for the - * tab container. - */ -export const Tab = props => null; - -Tab.defaultProps = { - __type__: TAB_MAGIC_TYPE, -}; - -Tabs.Tab = Tab; diff --git a/tgui-next/packages/tgui/components/TitleBar.js b/tgui-next/packages/tgui/components/TitleBar.js deleted file mode 100644 index f0a5040500..0000000000 --- a/tgui-next/packages/tgui/components/TitleBar.js +++ /dev/null @@ -1,51 +0,0 @@ -import { classes, pureComponentHooks } from 'common/react'; -import { toTitleCase } from 'common/string'; -import { tridentVersion } from '../byond'; -import { UI_DISABLED, UI_INTERACTIVE, UI_UPDATE } from '../constants'; -import { Icon } from './Icon'; - -const statusToColor = status => { - switch (status) { - case UI_INTERACTIVE: - return 'good'; - case UI_UPDATE: - return 'average'; - case UI_DISABLED: - default: - return 'bad'; - } -}; - -export const TitleBar = props => { - const { className, title, status, fancy, onDragStart, onClose } = props; - return ( -
      - -
      - {title === title.toLowerCase() ? toTitleCase(title) : title} -
      -
      fancy && onDragStart(e)} /> - {!!fancy && ( -
      - {tridentVersion <= 4 ? 'x' : '×'} -
      - )} -
      - ); -}; - -TitleBar.defaultHooks = pureComponentHooks; diff --git a/tgui-next/packages/tgui/components/Toast.js b/tgui-next/packages/tgui/components/Toast.js deleted file mode 100644 index d3b9d603de..0000000000 --- a/tgui-next/packages/tgui/components/Toast.js +++ /dev/null @@ -1,57 +0,0 @@ -import { pureComponentHooks } from 'common/react'; - -export const Toast = props => { - const { content, children } = props; - return ( -
      - {content} - {children} -
      - ); -}; - -Toast.defaultHooks = pureComponentHooks; - -let toastTimeout; - -/** - * Shows a toast at the bottom of the screen. - * - * Takes the store's dispatch function, and text as a second argument. - */ -export const showToast = (dispatch, text) => { - if (toastTimeout) { - clearTimeout(toastTimeout); - } - toastTimeout = setTimeout(() => { - toastTimeout = undefined; - dispatch({ - type: 'hideToast', - }); - }, 5000); - dispatch({ - type: 'showToast', - payload: { text }, - }); -}; - -export const toastReducer = (state, action) => { - const { type, payload } = action; - - if (type === 'showToast') { - const { text } = payload; - return { - ...state, - toastText: text, - }; - } - - if (type === 'hideToast') { - return { - ...state, - toastText: null, - }; - } - - return state; -}; diff --git a/tgui-next/packages/tgui/drag.js b/tgui-next/packages/tgui/drag.js deleted file mode 100644 index a29146b796..0000000000 --- a/tgui-next/packages/tgui/drag.js +++ /dev/null @@ -1,146 +0,0 @@ -import { vecAdd, vecInverse, vecMultiply } from 'common/vector'; -import { winget, winset } from './byond'; -import { createLogger } from './logging'; - -const logger = createLogger('drag'); - -let ref; -let dragging = false; -let resizing = false; -let screenOffset = [0, 0]; -let dragPointOffset; -let resizeMatrix; -let initialSize; -let size; - -const getWindowPosition = ref => { - return winget(ref, 'pos').then(pos => [pos.x, pos.y]); -}; - -const setWindowPosition = (ref, vec) => { - return winset(ref, 'pos', vec[0] + ',' + vec[1]); -}; - -const setWindowSize = (ref, vec) => { - return winset(ref, 'size', vec[0] + ',' + vec[1]); -}; - -export const setupDrag = async state => { - logger.log('setting up'); - ref = state.config.window; - // Calculate offset caused by windows taskbar - const realPosition = await getWindowPosition(ref); - screenOffset = [ - realPosition[0] - window.screenLeft, - realPosition[1] - window.screenTop, - ]; - // Constraint window position - const [relocated, safePosition] = constraintPosition(realPosition); - if (relocated) { - setWindowPosition(ref, safePosition); - } - logger.debug('current state', { ref, screenOffset }); -}; - -/** - * Constraints window position to safe screen area, accounting for safe - * margins which could be a system taskbar. - */ -const constraintPosition = position => { - let x = position[0]; - let y = position[1]; - let relocated = false; - // Left - if (x < 0) { - x = 0; - relocated = true; - } - // Right - else if (x + window.innerWidth > window.screen.availWidth) { - x = window.screen.availWidth - window.innerWidth; - relocated = true; - } - // Top - if (y < 0) { - y = 0; - relocated = true; - } - // Bottom - else if (y + window.innerHeight > window.screen.availHeight) { - y = window.screen.availHeight - window.innerHeight; - relocated = true; - } - return [relocated, [x, y]]; -}; - -export const dragStartHandler = event => { - logger.log('drag start'); - dragging = true; - dragPointOffset = [ - window.screenLeft - event.screenX, - window.screenTop - event.screenY, - ]; - document.addEventListener('mousemove', dragMoveHandler); - document.addEventListener('mouseup', dragEndHandler); - dragMoveHandler(event); -}; - -const dragEndHandler = event => { - logger.log('drag end'); - dragMoveHandler(event); - document.removeEventListener('mousemove', dragMoveHandler); - document.removeEventListener('mouseup', dragEndHandler); - dragging = false; -}; - -const dragMoveHandler = event => { - if (!dragging) { - return; - } - event.preventDefault(); - setWindowPosition(ref, vecAdd( - [event.screenX, event.screenY], - screenOffset, - dragPointOffset)); -}; - -export const resizeStartHandler = (x, y) => event => { - resizeMatrix = [x, y]; - logger.log('resize start', resizeMatrix); - resizing = true; - dragPointOffset = [ - window.screenLeft - event.screenX, - window.screenTop - event.screenY, - ]; - initialSize = [ - window.innerWidth, - window.innerHeight, - ]; - document.addEventListener('mousemove', resizeMoveHandler); - document.addEventListener('mouseup', resizeEndHandler); - resizeMoveHandler(event); -}; - -const resizeEndHandler = event => { - logger.log('resize end', size); - resizeMoveHandler(event); - document.removeEventListener('mousemove', resizeMoveHandler); - document.removeEventListener('mouseup', resizeEndHandler); - resizing = false; -}; - -const resizeMoveHandler = event => { - if (!resizing) { - return; - } - event.preventDefault(); - size = vecAdd(initialSize, vecMultiply(resizeMatrix, vecAdd( - [event.screenX, event.screenY], - vecInverse([window.screenLeft, window.screenTop]), - dragPointOffset, - [1, 1]))); - // Sane window size values - size[0] = Math.max(size[0], 250); - size[1] = Math.max(size[1], 120); - setWindowSize(ref, size); -}; diff --git a/tgui-next/packages/tgui/index.js b/tgui-next/packages/tgui/index.js deleted file mode 100644 index 1a8b9d4eab..0000000000 --- a/tgui-next/packages/tgui/index.js +++ /dev/null @@ -1,167 +0,0 @@ -import 'core-js/es'; -import 'core-js/web/immediate'; -import 'core-js/web/queue-microtask'; -import 'core-js/web/timers'; -import 'regenerator-runtime/runtime'; -import './polyfills'; - -import { loadCSS } from 'fg-loadcss'; -import { render } from 'inferno'; -import { setupHotReloading } from 'tgui-dev-server/link/client'; -import { backendUpdate } from './backend'; -import { tridentVersion } from './byond'; -import { setupDrag } from './drag'; -import { createLogger } from './logging'; -import { getRoute } from './routes'; -import { createStore } from './store'; - -const logger = createLogger(); -const store = createStore(); -const reactRoot = document.getElementById('react-root'); - -let initialRender = true; -let handedOverToOldTgui = false; - -const renderLayout = () => { - // Short-circuit the renderer - if (handedOverToOldTgui) { - return; - } - // Mark the beginning of the render - let startedAt; - if (process.env.NODE_ENV !== 'production') { - startedAt = Date.now(); - } - try { - const state = store.getState(); - // Initial render setup - if (initialRender) { - logger.log('initial render', state); - - // ----- Old TGUI chain-loader: begin ----- - const route = getRoute(state); - // Route was not found, load old TGUI - if (!route) { - logger.info('loading old tgui'); - // Short-circuit the renderer - handedOverToOldTgui = true; - // Unsubscribe from updates - window.update = window.initialize = () => {}; - // IE8: Use a redirection method - if (tridentVersion <= 4) { - setTimeout(() => { - location.href = 'tgui-fallback.html?ref=' + window.__ref__; - }, 10); - return; - } - // Inject current state into the data holder - const holder = document.getElementById('data'); - holder.textContent = JSON.stringify(state); - // Load old TGUI by injecting new scripts - loadCSS('v4shim.css'); - loadCSS('tgui.css'); - const head = document.getElementsByTagName('head')[0]; - const script = document.createElement('script'); - script.type = 'text/javascript'; - script.src = 'tgui.js'; - head.appendChild(script); - // Bail - return; - } - // ----- Old TGUI chain-loader: end ----- - - // Setup dragging - setupDrag(state); - } - // Start rendering - const { Layout } = require('./layout'); - const element = ; - render(element, reactRoot); - } - catch (err) { - logger.error('rendering error', err); - } - // Report rendering time - if (process.env.NODE_ENV !== 'production') { - const finishedAt = Date.now(); - const diff = finishedAt - startedAt; - const diffFrames = (diff / 16.6667).toFixed(2); - logger.debug(`rendered in ${diff}ms (${diffFrames} frames)`); - if (initialRender) { - const diff = finishedAt - window.__inception__; - const diffFrames = (diff / 16.6667).toFixed(2); - logger.log(`fully loaded in ${diff}ms (${diffFrames} frames)`); - } - } - if (initialRender) { - initialRender = false; - } -}; - -// Parse JSON and report all abnormal JSON strings coming from BYOND -const parseStateJson = json => { - let reviver = (key, value) => { - if (typeof value === 'object' && value !== null) { - if (value.__number__) { - return parseFloat(value.__number__); - } - } - return value; - }; - // IE8: No reviver for you! - // See: https://stackoverflow.com/questions/1288962 - if (tridentVersion <= 4) { - reviver = undefined; - } - try { - return JSON.parse(json, reviver); - } - catch (err) { - logger.log(err); - logger.log('What we got:', json); - const msg = err && err.message; - throw new Error('JSON parsing error: ' + msg); - } -}; - -const setupApp = () => { - // Subscribe for redux state updates - store.subscribe(() => { - renderLayout(); - }); - - // Subscribe for bankend updates - window.update = window.initialize = stateJson => { - const state = parseStateJson(stateJson); - // Backend update dispatches a store action - store.dispatch(backendUpdate(state)); - }; - - // Enable hot module reloading - if (module.hot) { - setupHotReloading(); - module.hot.accept(['./layout', './routes'], () => { - renderLayout(); - }); - } - - // Process the early update queue - while (true) { - let stateJson = window.__updateQueue__.shift(); - if (!stateJson) { - break; - } - window.update(stateJson); - } - - // Dynamically load font-awesome from browser's cache - loadCSS('font-awesome.css'); -}; - -// IE8: Wait for DOM to properly load -if (tridentVersion <= 4 && document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', setupApp); -} -else { - setupApp(); -} diff --git a/tgui-next/packages/tgui/interfaces/Achievements.js b/tgui-next/packages/tgui/interfaces/Achievements.js deleted file mode 100644 index 6e2ad7a599..0000000000 --- a/tgui-next/packages/tgui/interfaces/Achievements.js +++ /dev/null @@ -1,134 +0,0 @@ -import { useBackend } from '../backend'; -import { Box, Icon, Table, Tabs } from '../components'; - -export const Achievement = props => { - const { - name, - desc, - icon_class, - value, - } = props; - return ( - - - - - -

      {name}

      - {desc} - - - - ); -}; - -export const Score = props => { - const { - name, - desc, - icon_class, - value, - } = props; - return ( - - - - - -

      {name}

      - {desc} - 0 ? 'good' : 'bad'} - content={value > 0 ? `Earned ${value} times` : 'Locked'} /> - - - ); -}; - -export const Achievements = props => { - const { data } = useBackend(props); - return ( - - {data.categories.map(category => ( - - - {data.achievements - .filter(x => x.category === category) - .map(achievement => { - if (achievement.score) { - return ( - - ); - } - return ( - - ); - })} - - - ))} - - - {data.highscore.map(highscore => ( - - - - - # - - - Key - - - Score - - - {Object.keys(highscore.scores).map((key, index) => ( - - - {index+1} - - - {index === 0 && ( - - )} - {key} - {index === 0 && ( - - )} - - - {highscore.scores[key]} - - - ))} -
      -
      - ))} -
      -
      -
      - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AiAirlock.js b/tgui-next/packages/tgui/interfaces/AiAirlock.js deleted file mode 100644 index 55a3cd4a22..0000000000 --- a/tgui-next/packages/tgui/interfaces/AiAirlock.js +++ /dev/null @@ -1,196 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, LabeledList, Section } from '../components'; - -export const AiAirlock = props => { - const { act, data } = useBackend(props); - const dangerMap = { - 2: { - color: 'good', - localStatusText: 'Offline', - }, - 1: { - color: 'average', - localStatusText: 'Caution', - }, - 0: { - color: 'bad', - localStatusText: 'Optimal', - }, - }; - const statusMain = dangerMap[data.power.main] || dangerMap[0]; - const statusBackup = dangerMap[data.power.backup] || dangerMap[0]; - const statusElectrify = dangerMap[data.shock] || dangerMap[0]; - return ( - -
      - - act('disrupt-main')} /> - )}> - {data.power.main ? 'Online' : 'Offline'} - {' '} - {(!data.wires.main_1 || !data.wires.main_2) - && '[Wires have been cut!]' - || (data.power.main_timeleft > 0 - && `[${data.power.main_timeleft}s]`)} - - act('disrupt-backup')} /> - )}> - {data.power.backup ? 'Online' : 'Offline'} - {' '} - {(!data.wires.backup_1 || !data.wires.backup_2) - && '[Wires have been cut!]' - || (data.power.backup_timeleft > 0 - && `[${data.power.backup_timeleft}s]`)} - - -
      -
      - - act('idscan-toggle')} /> - )}> - {!data.wires.id_scanner && '[Wires have been cut!]'} - - act('emergency-toggle')} /> - )} /> - - act('bolt-toggle')} /> - )}> - {!data.wires.bolts && '[Wires have been cut!]'} - - act('light-toggle')} /> - )}> - {!data.wires.lights && '[Wires have been cut!]'} - - act('safe-toggle')} /> - )}> - {!data.wires.safe && '[Wires have been cut!]'} - - act('speed-toggle')} /> - )}> - {!data.wires.timing && '[Wires have been cut!]'} - - - act('open-close')} /> - )}> - {!!(data.locked || data.welded) && ( - - [Door is {data.locked ? 'bolted' : ''} - {(data.locked && data.welded) ? ' and ' : ''} - {data.welded ? 'welded' : ''}!] - - )} - - -
      -
      - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AirAlarm.js b/tgui-next/packages/tgui/interfaces/AirAlarm.js deleted file mode 100644 index 20d808606c..0000000000 --- a/tgui-next/packages/tgui/interfaces/AirAlarm.js +++ /dev/null @@ -1,461 +0,0 @@ -import { toFixed } from 'common/math'; -import { decodeHtmlEntities } from 'common/string'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, NumberInput, Section } from '../components'; -import { getGasLabel } from '../constants'; -import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; - -export const AirAlarm = props => { - const { state } = props; - const { act, data } = useBackend(props); - const locked = data.locked && !data.siliconUser; - return ( - - act('lock')} /> - - {!locked && ( - - )} - - ); -}; - -const AirAlarmStatus = props => { - const { data } = useBackend(props); - const entries = (data.environment_data || []) - .filter(entry => entry.value >= 0.01); - const dangerMap = { - 0: { - color: 'good', - localStatusText: 'Optimal', - }, - 1: { - color: 'average', - localStatusText: 'Caution', - }, - 2: { - color: 'bad', - localStatusText: 'Danger (Internals Required)', - }, - }; - const localStatus = dangerMap[data.danger_level] || dangerMap[0]; - return ( -
      - - {entries.length > 0 && ( - - {entries.map(entry => { - const status = dangerMap[entry.danger_level] || dangerMap[0]; - return ( - - {toFixed(entry.value, 2)}{entry.unit} - - ); - })} - - {localStatus.localStatusText} - - - {data.atmos_alarm && 'Atmosphere Alarm' - || data.fire_alarm && 'Fire Alarm' - || 'Nominal'} - - - ) || ( - - Cannot obtain air sample for analysis. - - )} - {!!data.emagged && ( - - Safety measures offline. Device may exhibit abnormal behavior. - - )} - -
      - ); -}; - -const AIR_ALARM_ROUTES = { - home: { - title: 'Air Controls', - component: () => AirAlarmControlHome, - }, - vents: { - title: 'Vent Controls', - component: () => AirAlarmControlVents, - }, - scrubbers: { - title: 'Scrubber Controls', - component: () => AirAlarmControlScrubbers, - }, - modes: { - title: 'Operating Mode', - component: () => AirAlarmControlModes, - }, - thresholds: { - title: 'Alarm Thresholds', - component: () => AirAlarmControlThresholds, - }, -}; - -const AirAlarmControl = props => { - const { state } = props; - const { act, config } = useBackend(props); - const route = AIR_ALARM_ROUTES[config.screen] || AIR_ALARM_ROUTES.home; - const Component = route.component(); - return ( -
      act('tgui:view', { - screen: 'home', - })} /> - )}> - -
      - ); -}; - - -// Home screen -// -------------------------------------------------------- - -const AirAlarmControlHome = props => { - const { act, data } = useBackend(props); - const { - mode, - atmos_alarm, - } = data; - return ( - -
    - - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosControlConsole.js b/tgui-next/packages/tgui/interfaces/AtmosControlConsole.js deleted file mode 100644 index 80c23d434b..0000000000 --- a/tgui-next/packages/tgui/interfaces/AtmosControlConsole.js +++ /dev/null @@ -1,100 +0,0 @@ -import { map } from 'common/collections'; -import { toFixed } from 'common/math'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, LabeledList, NumberInput, Section } from '../components'; - -export const AtmosControlConsole = props => { - const { act, data } = useBackend(props); - const sensors = data.sensors || []; - return ( - -
    - {sensors.map(sensor => { - const gases = sensor.gases || {}; - return ( -
    - - - {toFixed(sensor.pressure, 2) + ' kPa'} - - {!!sensor.temperature && ( - - {toFixed(sensor.temperature, 2) + ' K'} - - )} - {map((gasPercent, gasId) => { - return ( - - {toFixed(gasPercent, 2) + '%'} - - ); - })(gases)} - -
    - ); - })} -
    - {data.tank && ( -
    act('reconnect')} /> - )}> - - -
    - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosFilter.js b/tgui-next/packages/tgui/interfaces/AtmosFilter.js deleted file mode 100644 index 35bbf34686..0000000000 --- a/tgui-next/packages/tgui/interfaces/AtmosFilter.js +++ /dev/null @@ -1,52 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, NumberInput, Section } from '../components'; -import { getGasLabel } from '../constants'; - -export const AtmosFilter = props => { - const { act, data } = useBackend(props); - const filterTypes = data.filter_types || []; - return ( -
    - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosMixer.js b/tgui-next/packages/tgui/interfaces/AtmosMixer.js deleted file mode 100644 index a944bfb686..0000000000 --- a/tgui-next/packages/tgui/interfaces/AtmosMixer.js +++ /dev/null @@ -1,66 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, NumberInput, Section } from '../components'; - -export const AtmosMixer = props => { - const { act, data } = useBackend(props); - return ( -
    - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosPump.js b/tgui-next/packages/tgui/interfaces/AtmosPump.js deleted file mode 100644 index 01c50de4d4..0000000000 --- a/tgui-next/packages/tgui/interfaces/AtmosPump.js +++ /dev/null @@ -1,63 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, NumberInput, Section } from '../components'; - -export const AtmosPump = props => { - const { act, data } = useBackend(props); - return ( -
    - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/AtmosRelief.js b/tgui-next/packages/tgui/interfaces/AtmosRelief.js deleted file mode 100644 index 4654ec6582..0000000000 --- a/tgui-next/packages/tgui/interfaces/AtmosRelief.js +++ /dev/null @@ -1,54 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, NumberInput, Section } from '../components'; - -export const AtmosRelief = props => { - const { act, data } = useBackend(props); - return ( -
    - - - act('open_pressure', { - open_pressure: value, - })} /> -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/BankMachine.js b/tgui-next/packages/tgui/interfaces/BankMachine.js deleted file mode 100644 index a3d52097ec..0000000000 --- a/tgui-next/packages/tgui/interfaces/BankMachine.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, LabeledList, NoticeBox, Section } from '../components'; - -export const BankMachine = props => { - const { act, data } = useBackend(props); - const { - current_balance, - siphoning, - station_name, - } = data; - return ( - -
    - - act(siphoning ? 'halt' : 'siphon')} /> - )}> - {current_balance + ' cr'} - - -
    - - Authorized personnel only - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Bepis.js b/tgui-next/packages/tgui/interfaces/Bepis.js deleted file mode 100644 index 993af415dc..0000000000 --- a/tgui-next/packages/tgui/interfaces/Bepis.js +++ /dev/null @@ -1,112 +0,0 @@ -import { multiline } from 'common/string'; -import { Fragment } from 'inferno'; -import { act } from '../byond'; -import { Section, LabeledList, Button, NumberInput, Box, Grid } from '../components'; - -export const Bepis = props => { - const { state } = props; - const { config, data } = state; - const { ref } = config; - const { - amount, - } = data; - return ( -
    -
    act(ref, 'toggle_power')} /> - )}> - All you need to know about the B.E.P.I.S. and you! - The B.E.P.I.S. performs hundreds of tests a second - using electrical and financial resources to invent - new products, or discover new technologies otherwise - overlooked for being too risky or too niche to produce! -
    -
    act(ref, 'account_reset')} /> - )}> - Console is currently being operated - by {data.account_owner ? data.account_owner : 'no one'}. -
    - - -
    - - - {data.stored_cash} - - - {data.accuracy_percentage}% - - - {data.positive_cash_offset} - - - {data.negative_cash_offset} - - - act(ref, 'amount', { - amount: value, - })} /> - - -
    - -
    - - - - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/BluespaceArtillery.js b/tgui-next/packages/tgui/interfaces/BluespaceArtillery.js deleted file mode 100644 index b9f07eabe9..0000000000 --- a/tgui-next/packages/tgui/interfaces/BluespaceArtillery.js +++ /dev/null @@ -1,78 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, NoticeBox, Section } from '../components'; - -export const BluespaceArtillery = props => { - const { act, data } = useBackend(props); - const { - notice, - connected, - unlocked, - target, - } = data; - return ( - - {!!notice && ( - - {notice} - - )} - {connected ? ( - -
    act('recalibrate')} /> - )}> - - {target || 'No Target Set'} - -
    -
    - {unlocked ? ( - -
    -
    - ) : ( -
    - - -
    - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/BorgPanel.js b/tgui-next/packages/tgui/interfaces/BorgPanel.js deleted file mode 100644 index 7cc4c860e6..0000000000 --- a/tgui-next/packages/tgui/interfaces/BorgPanel.js +++ /dev/null @@ -1,135 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, ProgressBar, Section } from '../components'; - -export const BorgPanel = props => { - const { act, data } = useBackend(props); - const borg = data.borg || {}; - const cell = data.cell || {}; - const cellPercent = cell.charge / cell.maxcharge; - const channels = data.channels || []; - const modules = data.modules || []; - const upgrades = data.upgrades || []; - const ais = data.ais || []; - const laws = data.laws || []; - return ( - -
    act('rename')} /> - )}> - - -
    -
    act('toggle_lawupdate')} /> - )}> - {laws.map(law => ( - - {law} - - ))} -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/BrigTimer.js b/tgui-next/packages/tgui/interfaces/BrigTimer.js deleted file mode 100644 index a83d643334..0000000000 --- a/tgui-next/packages/tgui/interfaces/BrigTimer.js +++ /dev/null @@ -1,55 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, Section } from '../components'; - -export const BrigTimer = props => { - const { act, data } = useBackend(props); - return ( -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Canister.js b/tgui-next/packages/tgui/interfaces/Canister.js deleted file mode 100644 index 0e2810e290..0000000000 --- a/tgui-next/packages/tgui/interfaces/Canister.js +++ /dev/null @@ -1,121 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { AnimatedNumber, Box, Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components'; - -export const Canister = props => { - const { act, data } = useBackend(props); - return ( - - - The regulator {data.hasHoldingTank ? 'is' : 'is not'} connected - to a tank. - -
    act('relabel')} /> - )}> - - - kPa - - - {!!data.isPrototype && ( - -
    - -
    - - - - kPa - - - -
    - -
    act('eject')} /> - )}> - {!!data.hasHoldingTank && ( - - - {data.holdingTank.name} - - - kPa - - - )} - {!data.hasHoldingTank && ( - - No Holding Tank - - )} -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Cargo.js b/tgui-next/packages/tgui/interfaces/Cargo.js deleted file mode 100644 index 133b1b00ab..0000000000 --- a/tgui-next/packages/tgui/interfaces/Cargo.js +++ /dev/null @@ -1,348 +0,0 @@ -import { map } from 'common/collections'; -import { Fragment } from 'inferno'; -import { act } from '../byond'; -import { AnimatedNumber, Box, Button, LabeledList, Section, Tabs } from '../components'; -import { InterfaceLockNoticeBox } from './common/InterfaceLockNoticeBox'; - -export const Cargo = props => { - const { state } = props; - const { config, data } = state; - const { ref } = config; - const supplies = data.supplies || {}; - const requests = data.requests || []; - const cart = data.cart || []; - - const cartTotalAmount = cart - .reduce((total, entry) => total + entry.cost, 0); - - const cartButtons = !data.requestonly && ( - - - {cart.length === 0 && 'Cart is empty'} - {cart.length === 1 && '1 item'} - {cart.length >= 2 && cart.length + ' items'} - {' '} - {cartTotalAmount > 0 && `(${cartTotalAmount} cr)`} - - - - ))} - - )} - {!condi && ( - this.setState({ - pillAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'pill', - amount: pillAmount, - volume: 'auto', - })} /> - )} - {!condi && ( - this.setState({ - patchAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'patch', - amount: patchAmount, - volume: 'auto', - })} /> - )} - {!condi && ( - this.setState({ - bottleAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'bottle', - amount: bottleAmount, - volume: 'auto', - })} /> - )} - {!condi && ( - this.setState({ - vialAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'hypoVial', - amount: vialAmount, - volume: 'auto', - })} /> - )} - {!condi && ( - this.setState({ - dartAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'smartDart', - amount: dartAmount, - volume: 'auto', - })} /> - )} - {!!condi && ( - this.setState({ - packAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'condimentPack', - amount: packAmount, - volume: 'auto', - })} /> - )} - {!!condi && ( - this.setState({ - bottleAmount: value, - })} - onCreate={() => act(ref, 'create', { - type: 'condimentBottle', - amount: bottleAmount, - volume: 'auto', - })} /> - )} - - ); - } -} - -const AnalysisResults = props => { - const { state, fermianalyze } = props; - const { ref } = state.config; - const { analyzeVars } = state.data; - return ( -
    act(ref, 'goScreen', { - screen: 'home', - })} /> - )}> - {!fermianalyze && ( - - - {analyzeVars.name} - - - {analyzeVars.state} - - - - {analyzeVars.color} - - - {analyzeVars.description} - - - {analyzeVars.metaRate} u/minute - - - {analyzeVars.overD} - - - {analyzeVars.addicD} - - - )} - {!!fermianalyze && ( - - - {analyzeVars.name} - - - {analyzeVars.state} - - - - {analyzeVars.color} - - - {analyzeVars.description} - - - {analyzeVars.metaRate} u/minute - - - {analyzeVars.overD} - - - {analyzeVars.addicD} - - - {analyzeVars.purityF} - - - {analyzeVars.inverseRatioF} - - - {analyzeVars.purityE} - - - {analyzeVars.minTemp} - - - {analyzeVars.maxTemp} - - - {analyzeVars.eTemp} - - - {analyzeVars.pHpeak} - - - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/ChemPress.js b/tgui-next/packages/tgui/interfaces/ChemPress.js deleted file mode 100644 index 155fa371fd..0000000000 --- a/tgui-next/packages/tgui/interfaces/ChemPress.js +++ /dev/null @@ -1,53 +0,0 @@ -import { useBackend } from '../backend'; -import { Box, Button, Input, LabeledList, NumberInput, Section } from '../components'; - -export const ChemPress = props => { - const { act, data } = useBackend(props); - const { - pill_size, - pill_name, - pill_style, - pill_styles = [], - } = data; - return ( -
    - - - act('change_pill_size', { - volume: value, - })} /> - - - act('change_pill_name', { - name: value, - })} /> - - - {pill_styles.map(pill => ( - - ))} - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/ChemReactionChamber.js b/tgui-next/packages/tgui/interfaces/ChemReactionChamber.js deleted file mode 100644 index 8c829258ec..0000000000 --- a/tgui-next/packages/tgui/interfaces/ChemReactionChamber.js +++ /dev/null @@ -1,98 +0,0 @@ -import { Component } from 'inferno'; -import { act } from '../byond'; -import { Box, Button, LabeledList, NumberInput, Section, Input } from '../components'; -import { map } from 'common/collections'; -import { classes } from 'common/react'; - - -export class ChemReactionChamber extends Component { - constructor() { - super(); - this.state = { - reagentName: "", - reagentQuantity: 1, - }; - } - - setReagentName(reagentName) { - this.setState({ - reagentName, - }); - } - - setReagentQuantity(reagentQuantity) { - this.setState({ - reagentQuantity, - }); - } - - render() { - const { state } = this.props; - const { config, data } = state; - const { ref } = config; - const emptying = data.emptying; - const reagents = data.reagents || []; - return ( -
    - {emptying ? "Emptying" : "Filling"} - - )} > - - - - this.setReagentName(value)} /> - - - this.setReagentQuantity(value)} /> - -
    - ); - } -} diff --git a/tgui-next/packages/tgui/interfaces/ChemSplitter.js b/tgui-next/packages/tgui/interfaces/ChemSplitter.js deleted file mode 100644 index 8e64c43e0f..0000000000 --- a/tgui-next/packages/tgui/interfaces/ChemSplitter.js +++ /dev/null @@ -1,48 +0,0 @@ -import { toFixed } from 'common/math'; -import { useBackend } from '../backend'; -import { LabeledList, NumberInput, Section } from '../components'; - -export const ChemSplitter = props => { - const { act, data } = useBackend(props); - const { - straight, - side, - max_transfer, - } = data; - return ( -
    - - - toFixed(value, 2)} - step={0.05} - stepPixelSize={4} - onChange={(e, value) => act('set_amount', { - target: 'straight', - amount: value, - })} /> - - - toFixed(value, 2)} - step={0.05} - stepPixelSize={4} - onChange={(e, value) => act('set_amount', { - target: 'side', - amount: value, - })} /> - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/ChemSynthesizer.js b/tgui-next/packages/tgui/interfaces/ChemSynthesizer.js deleted file mode 100644 index df56dfdc07..0000000000 --- a/tgui-next/packages/tgui/interfaces/ChemSynthesizer.js +++ /dev/null @@ -1,42 +0,0 @@ -import { toFixed } from 'common/math'; -import { useBackend } from '../backend'; -import { Box, Button, Section } from '../components'; - -export const ChemSynthesizer = props => { - const { act, data } = useBackend(props); - const { - amount, - current_reagent, - chemicals = [], - possible_amounts = [], - } = data; - return ( -
    - - {possible_amounts.map(possible_amount => ( -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/CodexGigas.js b/tgui-next/packages/tgui/interfaces/CodexGigas.js deleted file mode 100644 index f96ce9380b..0000000000 --- a/tgui-next/packages/tgui/interfaces/CodexGigas.js +++ /dev/null @@ -1,98 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, Section } from '../components'; - -// TODO: refactor the backend of this it's a trainwreck -export const CodexGigas = props => { - const { act, data } = useBackend(props); - const prefixes = [ - "Dark", - "Hellish", - "Fallen", - "Fiery", - "Sinful", - "Blood", - "Fluffy", - ]; - const titles = [ - "Lord", - "Prelate", - "Count", - "Viscount", - "Vizier", - "Elder", - "Adept", - ]; - const names = [ - "hal", - "ve", - "odr", - "neit", - "ci", - "quon", - "mya", - "folth", - "wren", - "geyr", - "hil", - "niet", - "twou", - "phi", - "coa", - ]; - const suffixes = [ - "the Red", - "the Soulless", - "the Master", - "the Lord of all things", - "Jr.", - ]; - return ( -
    - {data.name} - - - {prefixes.map(prefix => ( -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/ComputerFabricator.js b/tgui-next/packages/tgui/interfaces/ComputerFabricator.js deleted file mode 100644 index 87366f6f73..0000000000 --- a/tgui-next/packages/tgui/interfaces/ComputerFabricator.js +++ /dev/null @@ -1,403 +0,0 @@ -import { multiline } from 'common/string'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, Grid, Section, Table, Tooltip } from '../components'; - -export const ComputerFabricator = props => { - const { state } = props; - const { act, data } = useBackend(props); - return ( - -
    - Your perfect device, only three steps away... -
    - {data.state !== 0 && ( - - - - )} -
    - - {programs.map(program => ( - - -
    -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/NtosNetChat.js b/tgui-next/packages/tgui/interfaces/NtosNetChat.js deleted file mode 100644 index e6b2ff5f9d..0000000000 --- a/tgui-next/packages/tgui/interfaces/NtosNetChat.js +++ /dev/null @@ -1,170 +0,0 @@ -import { useBackend } from '../backend'; -import { AnimatedNumber, Box, Button, Grid, LabeledList, ProgressBar, Section, Input, Table, Icon, Flex } from '../components'; -import { Fragment } from 'inferno'; -import { createLogger } from '../logging'; - -const logger = createLogger('ntos chat'); - -export const NtosNetChat = props => { - const { act, data } = useBackend(props); - - const { - can_admin, - adminmode, - authed, - username, - active_channel, - is_operator, - all_channels = [], - clients = [], - messages = [], - } = data; - - const in_channel = (active_channel !== null); - const authorized = (authed || adminmode); - - return ( -
    - - - - - act('PRG_newchannel', { - new_channel_name: value, - })} /> - {all_channels.map(channel => ( -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/NtosWrapper.js b/tgui-next/packages/tgui/interfaces/NtosWrapper.js deleted file mode 100644 index b342883e79..0000000000 --- a/tgui-next/packages/tgui/interfaces/NtosWrapper.js +++ /dev/null @@ -1,109 +0,0 @@ -import { useBackend } from '../backend'; -import { Box, Button } from '../components'; -import { refocusLayout } from '../refocus'; - -export const NtosWrapper = props => { - const { children } = props; - const { act, data } = useBackend(props); - const { - PC_batteryicon, - PC_showbatteryicon, - PC_batterypercent, - PC_ntneticon, - PC_apclinkicon, - PC_stationtime, - PC_programheaders = [], - PC_showexitprogram, - } = data; - return ( -
    -
    { - refocusLayout(); - }}> -
    - - {PC_stationtime} - - - NtOS - -
    -
    - {PC_programheaders.map(header => ( - - - - ))} - - {PC_ntneticon && ( - - )} - - {!!PC_showbatteryicon && PC_batteryicon && ( - - {PC_batteryicon && ( - - )} - {PC_batterypercent && ( - PC_batterypercent - )} - - )} - {PC_apclinkicon && ( - - - - )} - {!!PC_showexitprogram && ( -
    -
    -
    - {children} -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/NuclearBomb.js b/tgui-next/packages/tgui/interfaces/NuclearBomb.js deleted file mode 100644 index 419fa7473e..0000000000 --- a/tgui-next/packages/tgui/interfaces/NuclearBomb.js +++ /dev/null @@ -1,121 +0,0 @@ -import { classes } from 'common/react'; -import { useBackend } from '../backend'; -import { Box, Button, Flex, Grid, Icon } from '../components'; - -// This ui is so many manual overrides and !important tags -// and hand made width sets that changing pretty much anything -// is going to require a lot of tweaking it get it looking correct again -// I'm sorry, but it looks bangin -const NukeKeypad = props => { - const { act } = useBackend(props); - const keypadKeys = [ - ['1', '4', '7', 'C'], - ['2', '5', '8', '0'], - ['3', '6', '9', 'E'], - ]; - return ( - - - {keypadKeys.map(keyColumn => ( - - {keyColumn.map(key => ( - - - - {data.sheets} - {(data.sheets >= 1) && ( - - )} - - - - - - {data.current_heat < 100 ? ( - Nominal - ) : ( - data.current_heat < 200 ? ( - Caution - ) : ( - DANGER - ) - )} - - - -
    - - - {data.power_output} - - - - - - - - {data.connected ? data.power_available : "Unconnected"} - - - -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/PowerMonitor.js b/tgui-next/packages/tgui/interfaces/PowerMonitor.js deleted file mode 100644 index 8998344be5..0000000000 --- a/tgui-next/packages/tgui/interfaces/PowerMonitor.js +++ /dev/null @@ -1,222 +0,0 @@ -import { map, sortBy } from 'common/collections'; -import { flow } from 'common/fp'; -import { toFixed } from 'common/math'; -import { pureComponentHooks } from 'common/react'; -import { Component, Fragment } from 'inferno'; -import { Box, Button, Chart, ColorBox, Flex, Icon, LabeledList, ProgressBar, Section, Table } from '../components'; - -const PEAK_DRAW = 500000; - -const powerRank = str => { - const unit = String(str.split(' ')[1]).toLowerCase(); - return ['w', 'kw', 'mw', 'gw'].indexOf(unit); -}; - -export class PowerMonitor extends Component { - constructor() { - super(); - this.state = { - sortByField: null, - }; - } - - render() { - const { state } = this.props; - const { data } = state; - const { history } = data; - const { sortByField } = this.state; - const supply = history.supply[history.supply.length - 1] || 0; - const demand = history.demand[history.demand.length - 1] || 0; - const supplyData = history.supply.map((value, i) => [i, value]); - const demandData = history.demand.map((value, i) => [i, value]); - const maxValue = Math.max( - PEAK_DRAW, - ...history.supply, - ...history.demand); - // Process area data - const areas = flow([ - map((area, i) => ({ - ...area, - // Generate a unique id - id: area.name + i, - })), - sortByField === 'name' && sortBy(area => area.name), - sortByField === 'charge' && sortBy(area => -area.charge), - sortByField === 'draw' && sortBy( - area => -powerRank(area.load), - area => -parseFloat(area.load)), - ])(data.areas); - return ( - - - -
    - - - - - - - - -
    -
    - -
    - - -
    -
    -
    -
    - - - Sort by: - - this.setState({ - sortByField: sortByField !== 'name' && 'name', - })} /> - this.setState({ - sortByField: sortByField !== 'charge' && 'charge', - })} /> - this.setState({ - sortByField: sortByField !== 'draw' && 'draw', - })} /> - - - - - Area - - - Charge - - - Draw - - - Eqp - - - Lgt - - - Env - - - {areas.map((area, i) => ( - - - - - - - - - ))} -
    - {area.name} - - - - {area.load} - - - - - - -
    -
    -
    - ); - } -} - -const AreaCharge = props => { - const { charging, charge } = props; - return ( - - 50 - ? 'battery-half' - : 'battery-quarter' - ) - || charging === 1 && 'bolt' - || charging === 2 && 'battery-full' - )} - color={( - charging === 0 && ( - charge > 50 - ? 'yellow' - : 'red' - ) - || charging === 1 && 'yellow' - || charging === 2 && 'green' - )} /> - - {toFixed(charge) + '%'} - - - ); -}; - -AreaCharge.defaultHooks = pureComponentHooks; - -const AreaStatusColorBox = props => { - const { status } = props; - const power = Boolean(status & 2); - const mode = Boolean(status & 1); - const tooltipText = (power ? 'On' : 'Off') - + ` [${mode ? 'auto' : 'manual'}]`; - return ( - - ); -}; - -AreaStatusColorBox.defaultHooks = pureComponentHooks; diff --git a/tgui-next/packages/tgui/interfaces/Radio.js b/tgui-next/packages/tgui/interfaces/Radio.js deleted file mode 100644 index e335cf1cac..0000000000 --- a/tgui-next/packages/tgui/interfaces/Radio.js +++ /dev/null @@ -1,108 +0,0 @@ -import { map } from 'common/collections'; -import { toFixed } from 'common/math'; -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, NumberInput, Section } from '../components'; -import { RADIO_CHANNELS } from '../constants'; - -export const Radio = props => { - const { act, data } = useBackend(props); - const { - freqlock, - frequency, - minFrequency, - maxFrequency, - listening, - broadcasting, - command, - useCommand, - subspace, - subspaceSwitchable, - } = data; - const tunedChannel = RADIO_CHANNELS - .find(channel => channel.freq === frequency); - const channels = map((value, key) => ({ - name: key, - status: !!value, - }))(data.channels); - return ( -
    - - - {freqlock && ( - - {toFixed(frequency / 10, 1) + ' kHz'} - - ) || ( - toFixed(value, 1)} - onDrag={(e, value) => act('frequency', { - adjust: (value - frequency / 10), - })} /> - )} - {tunedChannel && ( - - [{tunedChannel.name}] - - )} - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/RapidPipeDispenser.js b/tgui-next/packages/tgui/interfaces/RapidPipeDispenser.js deleted file mode 100644 index 17e4fd9d15..0000000000 --- a/tgui-next/packages/tgui/interfaces/RapidPipeDispenser.js +++ /dev/null @@ -1,188 +0,0 @@ -import { classes } from 'common/react'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, ColorBox, Flex, LabeledList, Section, Tabs } from '../components'; - -const ROOT_CATEGORIES = [ - 'Atmospherics', - 'Disposals', - 'Transit Tubes', -]; - -const ICON_BY_CATEGORY_NAME = { - 'Atmospherics': 'wrench', - 'Disposals': 'trash-alt', - 'Transit Tubes': 'bus', - 'Pipes': 'grip-lines', - 'Disposal Pipes': 'grip-lines', - 'Devices': 'microchip', - 'Heat Exchange': 'thermometer-half', - 'Station Equipment': 'microchip', -}; - -const PAINT_COLORS = { - grey: '#bbbbbb', - amethyst: '#a365ff', - blue: '#4466ff', - brown: '#b26438', - cyan: '#48eae8', - dark: '#808080', - green: '#1edd00', - orange: '#ffa030', - purple: '#b535ea', - red: '#ff3333', - violet: '#6e00f6', - yellow: '#ffce26', -}; - -const TOOLS = [ - { - name: 'Dispense', - bitmask: 1, - }, - { - name: 'Connect', - bitmask: 2, - }, - { - name: 'Destroy', - bitmask: 4, - }, - { - name: 'Paint', - bitmask: 8, - }, -]; - -export const RapidPipeDispenser = props => { - const { act, data } = useBackend(props); - const { - category: rootCategoryIndex, - categories = [], - selected_color, - piping_layer, - mode, - } = data; - const previews = data.preview_rows.flatMap(row => row.previews); - return ( - -
    - - - {ROOT_CATEGORIES.map((categoryName, i) => ( -
    - - -
    - {rootCategoryIndex === 0 && ( - - {[1, 2, 3].map(layer => ( - act('piping_layer', { - piping_layer: layer, - })} /> - ))} - - )} - - {previews.map(preview => ( - - ))} - -
    -
    - -
    - - {categories.map(category => ( - - {() => category.recipes.map(recipe => ( - act('pipe_type', { - pipe_type: recipe.pipe_index, - category: category.cat_name, - })} /> - ))} - - ))} - -
    -
    -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SatelliteControl.js b/tgui-next/packages/tgui/interfaces/SatelliteControl.js deleted file mode 100644 index 73a7f1ffbb..0000000000 --- a/tgui-next/packages/tgui/interfaces/SatelliteControl.js +++ /dev/null @@ -1,45 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, ProgressBar, Section, Table, Box } from '../components'; -import { Fragment } from 'inferno'; -import { LabeledListItem } from '../components/LabeledList'; - -export const SatelliteControl = props => { - const { act, data } = useBackend(props); - const satellites = data.satellites || []; - return ( - - {data.meteor_shield && ( -
    - - - - - -
    - )} -
    - - {satellites.map(satellite => ( - act('toggle', { - id: satellite.id, - })} - /> - ))} - -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/ShuttleManipulator.js b/tgui-next/packages/tgui/interfaces/ShuttleManipulator.js deleted file mode 100644 index 1cc361bc95..0000000000 --- a/tgui-next/packages/tgui/interfaces/ShuttleManipulator.js +++ /dev/null @@ -1,200 +0,0 @@ -import { map } from 'common/collections'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, LabeledList, Section, Table, Tabs } from '../components'; - -export const ShuttleManipulator = props => { - const { act, data } = useBackend(props); - const shuttles = data.shuttles || []; - const templateObject = data.templates || {}; - const selected = data.selected || {}; - const existingShuttle = data.existing_shuttle || {}; - return ( - - - {() => ( -
    - - {shuttles.map(shuttle => ( - - -
    -
    - )} -
    - - {() => ( -
    - - {map((template, templateId) => { - const templates = template.templates || []; - return ( - - {templates.map(actualTemplate => { - const isSelected = ( - actualTemplate.shuttle_id === selected.shuttle_id - ); - // Whoever made the structure being sent is an asshole - return ( -
    act('select_template', { - shuttle_id: actualTemplate.shuttle_id, - })} /> - )}> - {(!!actualTemplate.description - || !!actualTemplate.admin_notes - ) && ( - - {!!actualTemplate.description && ( - - {actualTemplate.description} - - )} - {!!actualTemplate.admin_notes && ( - - {actualTemplate.admin_notes} - - )} - - )} -
    - ); - })} -
    - ); - })(templateObject)} -
    -
    - )} -
    - -
    - {selected ? ( - -
    - {(!!selected.description || !!selected.admin_notes) && ( - - {!!selected.description && ( - - {selected.description} - - )} - {!!selected.admin_notes && ( - - {selected.admin_notes} - - )} - - )} -
    - {existingShuttle ? ( -
    - - act('jump_to', { - type: 'mobile', - id: existingShuttle.id, - })} /> - )}> - {existingShuttle.status} - {!!existingShuttle.timer && ( - - ({existingShuttle.timeleft}) - - )} - - -
    - ) : ( -
    - )} -
    -
    - - ) : 'No shuttle selected'} -
    - - - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Signaler.js b/tgui-next/packages/tgui/interfaces/Signaler.js deleted file mode 100644 index c656613141..0000000000 --- a/tgui-next/packages/tgui/interfaces/Signaler.js +++ /dev/null @@ -1,85 +0,0 @@ -import { Grid, NumberInput, Button, Section } from '../components'; -import { useBackend } from '../backend'; -import { toFixed } from 'common/math'; - -export const Signaler = props => { - const { act, data } = useBackend(props); - const { - code, - frequency, - minFrequency, - maxFrequency, - } = data; - - return ( -
    - - - Frequency: - - - toFixed(value, 1)} - width={13} - onDrag={(e, value) => act('freq', { - freq: value, - })} /> - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Sleeper.js b/tgui-next/packages/tgui/interfaces/Sleeper.js deleted file mode 100644 index dabf0f355d..0000000000 --- a/tgui-next/packages/tgui/interfaces/Sleeper.js +++ /dev/null @@ -1,181 +0,0 @@ -import { useBackend } from '../backend'; -import { Box, Section, LabeledList, Button, ProgressBar, Flex, AnimatedNumber } from '../components'; -import { Fragment } from 'inferno'; - -export const Sleeper = props => { - const { act, data } = useBackend(props); - - const { - occupied, - open, - occupant = [], - } = data; - - const preSortChems = data.chems || []; - const chems = preSortChems.sort((a, b) => { - const descA = a.name.toLowerCase(); - const descB = b.name.toLowerCase(); - if (descA < descB) { - return -1; - } - if (descA > descB) { - return 1; - } - return 0; - }); - const preSortSynth = data.synthchems || []; - const synthchems = preSortSynth.sort((a, b) => { - const descA = a.name.toLowerCase(); - const descB = b.name.toLowerCase(); - if (descA < descB) { - return -1; - } - if (descA > descB) { - return 1; - } - return 0; - }); - - const damageTypes = [ - { - label: 'Brute', - type: 'bruteLoss', - }, - { - label: 'Burn', - type: 'fireLoss', - }, - { - label: 'Toxin', - type: 'toxLoss', - }, - { - label: 'Oxygen', - type: 'oxyLoss', - }, - ]; - - return ( - -
    - {occupant.stat} - - )}> - {!!occupied && ( - - - - - {damageTypes.map(type => ( - - - - ))} - - - - - {data.blood_status} - - - {occupant.cloneLoss ? 'Damaged' : 'Healthy'} - - - {occupant.brainLoss ? 'Abnormal' : 'Healthy'} - - - - )} -
    -
    - - {data.chemical_list.map(specificChem => ( - - {specificChem.volume} units of {specificChem.name} - - ), - )} - -
    -
    act('door')} /> - )}> - {chems.map(chem => ( -
    -
    - {synthchems.map(chem => ( -
    -
    - {chems.map(chem => ( -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SmartVend.js b/tgui-next/packages/tgui/interfaces/SmartVend.js deleted file mode 100644 index d0c13ad259..0000000000 --- a/tgui-next/packages/tgui/interfaces/SmartVend.js +++ /dev/null @@ -1,61 +0,0 @@ -import { map } from 'common/collections'; -import { useBackend } from '../backend'; -import { Button, NoticeBox, Section, Table } from '../components'; - -export const SmartVend = props => { - const { act, data } = useBackend(props); - return ( -
    act('Dry')}> - {data.drying ? 'Stop drying' : 'Dry'} - - )}> - {data.contents.length === 0 && ( - - Unfortunately, this {data.name} is empty. - - ) || ( - - - - Item - - - - {data.verb ? data.verb : 'Dispense'} - - - {map((value, key) => ( - - - {value.name} - - - {value.amount} - - -
    - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Smes.js b/tgui-next/packages/tgui/interfaces/Smes.js deleted file mode 100644 index 7479af5894..0000000000 --- a/tgui-next/packages/tgui/interfaces/Smes.js +++ /dev/null @@ -1,176 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, NumberInput, LabeledList, ProgressBar, Section } from '../components'; - -export const Smes = props => { - const { act, data } = useBackend(props); - - let inputState; - if (data.capacityPercent >= 100) { - inputState = 'good'; - } - else if (data.inputting) { - inputState = 'average'; - } - else { - inputState = 'bad'; - } - let outputState; - if (data.outputting) { - outputState = 'good'; - } - else if (data.charge > 0) { - outputState = 'average'; - } - else { - outputState = 'bad'; - } - - return ( - -
    - -
    -
    - - act('tryinput')}> - {data.inputAttempt ? 'Auto' : 'Off'} - - }> - - {data.capacityPercent >= 100 - ? 'Fully Charged' - : data.inputting - ? 'Charging' - : 'Not Charging'} - - - - - - -
    -
    - - act('tryoutput')}> - {data.outputAttempt ? 'On' : 'Off'} - - }> - - {data.outputting - ? 'Sending' - : data.charge > 0 - ? 'Not Sending' - : 'No Charge'} - - - - - - -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SmokeMachine.js b/tgui-next/packages/tgui/interfaces/SmokeMachine.js deleted file mode 100644 index 16ba078910..0000000000 --- a/tgui-next/packages/tgui/interfaces/SmokeMachine.js +++ /dev/null @@ -1,71 +0,0 @@ -import { useBackend } from '../backend'; -import { Fragment } from 'inferno'; -import { AnimatedNumber, Box, Button, LabeledList, ProgressBar, NoticeBox, Section } from '../components'; - -export const SmokeMachine = props => { - const { act, data } = useBackend(props); - const { - TankContents, - isTankLoaded, - TankCurrentVolume, - TankMaxVolume, - active, - setting, - screen, - maxSetting = [], - } = data; - return ( - -
    act('power')} /> - )}> - - - {' / ' + TankMaxVolume} - - - - - { [1, 2, 3, 4, 5].map(amount => ( -
    -
    act('purge')} /> - )}> - {TankContents.map(chemical => ( - - - {' '} - units of {chemical.name} - - ))} -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SolarControl.js b/tgui-next/packages/tgui/interfaces/SolarControl.js deleted file mode 100644 index 1cfb4800c0..0000000000 --- a/tgui-next/packages/tgui/interfaces/SolarControl.js +++ /dev/null @@ -1,118 +0,0 @@ -import { toFixed } from 'common/math'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, Grid, LabeledList, NumberInput, ProgressBar, Section } from '../components'; - -export const SolarControl = props => { - const { act, data } = useBackend(props); - const { - generated, - generated_ratio, - azimuth_current, - azimuth_rate, - max_rotation_rate, - tracking_state, - connected_panels, - connected_tracker, - } = data; - return ( - -
    act('refresh')} /> - )}> - - - - - {connected_tracker ? 'OK' : 'N/A'} - - 0 ? 'good' : 'bad'}> - {connected_panels} - - - - - - - - - - - -
    -
    - - -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SpaceHeater.js b/tgui-next/packages/tgui/interfaces/SpaceHeater.js deleted file mode 100644 index c44f3e9c47..0000000000 --- a/tgui-next/packages/tgui/interfaces/SpaceHeater.js +++ /dev/null @@ -1,104 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, NumberInput, ProgressBar, Section } from '../components'; - -export const SpaceHeater = props => { - const { act, data } = useBackend(props); - return ( - -
    -
    -
    - - - 50 - ? 'bad' - : Math.abs(data.targetTemp - data.currentTemp) > 20 - ? 'average' - : 'good'}> - {data.currentTemp}°C - - - - {data.open && ( - act('target', { - target: value, - })} /> - ) || ( - data.targetTemp + '°C' - )} - - - {!data.open && 'Auto' || ( - -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SpawnersMenu.js b/tgui-next/packages/tgui/interfaces/SpawnersMenu.js deleted file mode 100644 index 27d8b1f9ff..0000000000 --- a/tgui-next/packages/tgui/interfaces/SpawnersMenu.js +++ /dev/null @@ -1,51 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, Section } from '../components'; - -export const SpawnersMenu = props => { - const { act, data } = useBackend(props); - const spawners = data.spawners || []; - return ( -
    - {spawners.map(spawner => ( -
    -
    - ))} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/SuitStorageUnit.js b/tgui-next/packages/tgui/interfaces/SuitStorageUnit.js deleted file mode 100644 index f858505a37..0000000000 --- a/tgui-next/packages/tgui/interfaces/SuitStorageUnit.js +++ /dev/null @@ -1,111 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, Icon, LabeledList, NoticeBox, Section } from '../components'; - -export const SuitStorageUnit = props => { - const { act, data } = useBackend(props); - const { - locked, - open, - safeties, - uv_active, - occupied, - suit, - helmet, - mask, - storage, - } = data; - return ( - - {!!(occupied && safeties) && ( - - Biological entity detected in suit chamber. Please remove - before continuing with operation. - - )} - {uv_active && ( - - Contents are currently being decontaminated. Please wait. - - ) || ( -
    - {!open && ( -
    - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Tank.js b/tgui-next/packages/tgui/interfaces/Tank.js deleted file mode 100644 index f91ff3af99..0000000000 --- a/tgui-next/packages/tgui/interfaces/Tank.js +++ /dev/null @@ -1,53 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, NumberInput, ProgressBar, Section } from '../components'; - -export const Tank = props => { - const { act, data } = useBackend(props); - return ( -
    - - - - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/TankDispenser.js b/tgui-next/packages/tgui/interfaces/TankDispenser.js deleted file mode 100644 index de05a5750b..0000000000 --- a/tgui-next/packages/tgui/interfaces/TankDispenser.js +++ /dev/null @@ -1,34 +0,0 @@ -import { useBackend } from '../backend'; -import { Button, LabeledList, Section } from '../components'; - -export const TankDispenser = props => { - const { act, data } = useBackend(props); - return ( -
    - - act('plasma')} /> - )}> - {data.plasma} - - act('oxygen')} /> - )}> - {data.oxygen} - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/TelecommsInteraction.js b/tgui-next/packages/tgui/interfaces/TelecommsInteraction.js deleted file mode 100644 index a67bfdf987..0000000000 --- a/tgui-next/packages/tgui/interfaces/TelecommsInteraction.js +++ /dev/null @@ -1,238 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { toFixed } from 'common/math'; -import { RADIO_CHANNELS } from '../constants'; -import { Button, LabeledList, NumberInput, NoticeBox, Section, Input } from '../components'; - -export const TeleInteract = props => { - const { act, data } = useBackend(props); - const { - notice = "", - multitool = false, - multitool_buf = null, - machine = null, - links = [], - freq_listening = [], - } = data; - const { - power = false, - id = "NULL", - network, - prefab = false, - hidden = false, - isrelay = false, - isbus = false, - } = machine; - return ( - - {!!notice && ( - - {notice} - - )} -
    - - -
    -
    - ) : ( - '' - )} -
    - - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/TelecommsLogBrowser.js b/tgui-next/packages/tgui/interfaces/TelecommsLogBrowser.js deleted file mode 100644 index 4b485a5880..0000000000 --- a/tgui-next/packages/tgui/interfaces/TelecommsLogBrowser.js +++ /dev/null @@ -1,174 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, LabeledList, NoticeBox, Section, Tabs, Input } from '../components'; - -export const TeleLogBrowser = props => { - const { act, data } = useBackend(props); - const { - notice, - network = "NULL", - servers, - selected = null, - selected_logs, - } = data; - const operational = (selected && selected.status); - return ( - - {!!notice && ( - - {notice} - - )} -
    - - - act('network', { - 'value': value, - })} /> - - -
    - - -
    - {(servers && servers.length) ? ( - - {servers.map(server => { - return ( - act('viewmachine', { - 'value': server.id, - })} /> - )}> - {`${server.name} (${server.id})`} - - ); - })} - - ) : ( - '404 Servers not found. Have you tried scanning the network?' - )} -
    -
    - -
    - {(operational && selected_logs) ? ( - selected_logs.map(logs => { - return ( -
    - - act('delete', { - 'value': logs.ref, - })} /> - )}> - {logs.name} - - - {logs.input_type} - - {logs.source && ( - - {`[${logs.source.name}] (Job: [${logs.source.job}])`} - - )} - {logs.race && ( - - {logs.race} - - )} - - {logs.message} - - -
    - ); - }) - ) : ( - "No server selected!" - )} -
    -
    -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/TelecommsMonitor.js b/tgui-next/packages/tgui/interfaces/TelecommsMonitor.js deleted file mode 100644 index 2b235d584b..0000000000 --- a/tgui-next/packages/tgui/interfaces/TelecommsMonitor.js +++ /dev/null @@ -1,221 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { RADIO_CHANNELS } from '../constants'; -import { Box, Button, LabeledList, NoticeBox, Section, Tabs, Input } from '../components'; - - -export const Telemonitor = props => { - const { act, data } = useBackend(props); - const { - notice, - network = "NULL", - servers, - selected = null, - selected_servers, - } = data; - const operational = (selected && selected.status); - - return ( - - {!!notice && ( - - {notice} - - )} -
    - - - act('network', { - 'value': value, - })} /> - - -
    - - -
    - {(servers && servers.length) ? ( - - {servers.map(server => { - return ( - act('viewmachine', { - 'value': server.id, - })} /> - )}> - {`${server.name} (${server.id})`} - - ); - })} - - ) : ( - '404 Servers not found. Have you tried scanning the network?' - )} -
    -
    - -
    - - - {operational ? ( - 'Running' - ) : ( - 'Server down!' - )} - - - {operational ? ( // Not to be confused to totaltraffic - selected.traffic <= 1024 ? ( - `${Math.max(selected.traffic, 0)} Gigabytes` - ) : ( - `${Math.round(selected.traffic/1024)} Terrabytes` - ) - ) : ( - '0 Gigabytes' - )} - - - {operational ? ( - selected.netspeed <= 1024 ? ( - `${selected.netspeed} Gigabytes/second` - ) : ( - `${Math.round(selected.netspeed/1024)} Terrabytes/second` - ) - ) : ( - '0 Gigabytes/second' - )} - - - {(operational && selected.long_range_link) ? ( - 'true' - ) : ( - 'false' - )} - - - - {operational && selected.freq_listening.map(thing => { - const valid = RADIO_CHANNELS - .find(channel => channel.freq === thing); - return ( - (valid) ? ( - - {`[${thing}] (${valid.name}) `} - - ) : ( - `[${thing}] ` - ) - ); - })} - - - -
    - {(operational && selected_servers) ? ( - - {selected_servers.map(server => { - return ( - act('viewmachine', { - 'value': server.id, - })} /> - )}> - {`${server.name} (${server.id})`} - - ); - })} - - ) : ( - !operational ? ( - "Server currently down! Cannot fetch the buffer list!" - ) : ( - "Buffer is empty!" - ) - )} -
    -
    -
    -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/TelecommsPDALog.js b/tgui-next/packages/tgui/interfaces/TelecommsPDALog.js deleted file mode 100644 index 914e751d05..0000000000 --- a/tgui-next/packages/tgui/interfaces/TelecommsPDALog.js +++ /dev/null @@ -1,420 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { act as _act } from '../byond'; -import { Button, LabeledList, NoticeBox, Section, Tabs, Input } from '../components'; - -export const TelePDALog = props => { - const { act, data } = useBackend(props); - const { - network, - notice = "", - authenticated = false, - canhack = false, - selected = null, - servers = [], - message_logs = [], - recon_logs = [], - } = data; - const fake_message = data.fake_message || { - 'sender': 'System Administrator', - 'job': 'Admin', - 'recepient': null, - 'message': 'This is a test, please ignore', - }; - const prioritycolorMap = { - 'Normal': 'warning', - 'High': 'bad', - 'Extreme': 'bad', - }; - const valid = (selected && selected.status && authenticated); - - if (data.hacking) { - return ( // should have used en -> jp unicode -> other encoding method->utf8 - - -

    - {"INTRN@L ACfES VIOL�TIa█ DEtE₡TED! Ree3ARcinG A█ \ - BAaKUP RdST�RE PbINT [0xcff32ca] - PLfASE aAIT"} -

    -
    - - {data.borg ? ( - - Brute-forcing for server key.
    - It will take 20 seconds for every character that the password has. -
    - In the meantime, this console can reveal your - true intentions if you let someone access it. - Make sure no humans enter the room during that time. -
    - ) : ( - - QnJ1dGUtZm9yY2luZyBmb3Igc2VydmVyIGtleS48YnI+IEl0IHdpbG
    - wgdGFrZSAyMCBzZWNvbmRzIGZvciBldmVyeSBjaGFyYWN0ZXIgdGhh
    - dCB0aGUgcGFzc3dvcmQgaGFzLiBJbiB0aGUgbWVhbnRpbWUsIHRoaX
    - MgY29uc29sZSBjYW4gcmV2ZWFsIHlvdXIgdHJ1ZSBpbnRlbnRpb25z
    - IGlmIHlvdSBsZXQgc29tZW9uZSBhY2Nlc3MgaXQuIE1ha2Ugc3VyZS
    - BubyBodW1hbnMgZW50ZXIgdGhlIHJvb20gZHVyaW5nIHRoYXQgdGltZS4=
    -
    -
    - )} -
    -
    - ); - } - - return ( - - {!!notice && ( - - {notice} - - )} -
    - - - act('network', { - 'value': value, - })} /> - - -
    - - -
    - {(servers && servers.length) ? ( - - {servers.map(server => { - return ( - act('viewmachine', { - 'value': server.id, - })} /> - )}> - {`${server.name} (${server.id})`} - - ); - })} - - ) : ( - '404 Servers not found. Have you tried scanning the network?' - )} -
    -
    - -
    -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Teleporter.js b/tgui-next/packages/tgui/interfaces/Teleporter.js deleted file mode 100644 index a2edfa9739..0000000000 --- a/tgui-next/packages/tgui/interfaces/Teleporter.js +++ /dev/null @@ -1,69 +0,0 @@ -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, Section } from '../components'; - -export const Teleporter = props => { - const { act, data } = useBackend(props); - const { - calibrated, - calibrating, - power_station, - regime_set, - teleporter_hub, - target, - } = data; - return ( -
    - {!power_station && ( - - No power station linked. - - ) || (!teleporter_hub && ( - - No hub linked. - - )) || ( - - act('regimeset')} /> - )}> - {regime_set} - - act('settarget')} /> - )}> - {target} - - act('calibrate')} /> - )}> - {calibrating && ( - - In Progress - - ) || (calibrated && ( - - Optimal - - ) || ( - - Sub-Optimal - - ))} - - - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/ThermoMachine.js b/tgui-next/packages/tgui/interfaces/ThermoMachine.js deleted file mode 100644 index acb31e34d7..0000000000 --- a/tgui-next/packages/tgui/interfaces/ThermoMachine.js +++ /dev/null @@ -1,77 +0,0 @@ -import { toFixed } from 'common/math'; -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { AnimatedNumber, Button, LabeledList, NumberInput, Section } from '../components'; - -export const ThermoMachine = props => { - const { act, data } = useBackend(props); - return ( - -
    - - - toFixed(value, 2)} /> - {' K'} - - - toFixed(value, 2)} /> - {' kPa'} - - -
    -
    act('power')} /> - )}> - - - act('target', { - target: value, - })} /> - - -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/TurbineComputer.js b/tgui-next/packages/tgui/interfaces/TurbineComputer.js deleted file mode 100644 index 4f632cc149..0000000000 --- a/tgui-next/packages/tgui/interfaces/TurbineComputer.js +++ /dev/null @@ -1,64 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Button, LabeledList, Section } from '../components'; - -export const TurbineComputer = props => { - const { act, data } = useBackend(props); - const operational = Boolean(data.compressor - && !data.compressor_broke - && data.turbine - && !data.turbine_broke); - return ( -
    -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Uplink.js b/tgui-next/packages/tgui/interfaces/Uplink.js deleted file mode 100644 index 4f2b047c9b..0000000000 --- a/tgui-next/packages/tgui/interfaces/Uplink.js +++ /dev/null @@ -1,186 +0,0 @@ -import { decodeHtmlEntities } from 'common/string'; -import { Component, Fragment } from 'inferno'; -import { act } from '../byond'; -import { Box, Button, Input, Section, Table, Tabs } from '../components'; - -// It's a class because we need to store state in the form of the current -// hovered item, and current search terms -export class Uplink extends Component { - constructor() { - super(); - this.state = { - hoveredItem: {}, - currentSearch: '', - }; - } - - setHoveredItem(hoveredItem) { - this.setState({ - hoveredItem, - }); - } - - setSearchText(currentSearch) { - this.setState({ - currentSearch, - }); - } - - render() { - const { state } = this.props; - const { config, data } = state; - const { ref } = config; - const { - compact_mode, - lockable, - telecrystals, - categories = [], - } = data; - const { hoveredItem, currentSearch } = this.state; - return ( -
    0 ? 'good' : 'bad'}> - {telecrystals} TC - - )} - buttons={( - - Search - this.setSearchText(value)} - ml={1} - mr={1} /> -
    - ); - } -} - -const ItemList = props => { - const { - items, - hoveredItem, - telecrystals, - compact, - onBuy, - onBuyMouseOver, - onBuyMouseOut, - } = props; - const hoveredCost = hoveredItem && hoveredItem.cost || 0; - if (compact) { - return ( - - {items.map(item => { - const notSameItem = hoveredItem && hoveredItem.name !== item.name; - const notEnoughHovered = telecrystals - hoveredCost < item.cost; - const disabledDueToHovered = notSameItem && notEnoughHovered; - return ( - - - {decodeHtmlEntities(item.name)} - - -
    - ); - } - return items.map(item => { - const notSameItem = hoveredItem && hoveredItem.name !== item.name; - const notEnoughHovered = telecrystals - hoveredCost < item.cost; - const disabledDueToHovered = notSameItem && notEnoughHovered; - return ( -
    onBuyMouseOver(item)} - onmouseout={() => onBuyMouseOut(item)} - onClick={() => onBuy(item)} /> - )}> - {decodeHtmlEntities(item.desc)} -
    - ); - }); -}; diff --git a/tgui-next/packages/tgui/interfaces/VaultController.js b/tgui-next/packages/tgui/interfaces/VaultController.js deleted file mode 100644 index 64e001d49a..0000000000 --- a/tgui-next/packages/tgui/interfaces/VaultController.js +++ /dev/null @@ -1,32 +0,0 @@ -import { toFixed } from 'common/math'; -import { useBackend } from '../backend'; -import { Button, LabeledList, ProgressBar, Section } from '../components'; - -export const VaultController = props => { - const { act, data } = useBackend(props); - return ( -
    act('togglelock')} /> - )}> - - - - - -
    - ); -}; diff --git a/tgui-next/packages/tgui/interfaces/Vending.js b/tgui-next/packages/tgui/interfaces/Vending.js deleted file mode 100644 index 3e48124fce..0000000000 --- a/tgui-next/packages/tgui/interfaces/Vending.js +++ /dev/null @@ -1,125 +0,0 @@ -import { Fragment } from 'inferno'; -import { act } from '../byond'; -import { Section, Box, Button, Table } from '../components'; -import { classes } from 'common/react'; - -export const Vending = props => { - const { state } = props; - const { config, data } = state; - const { ref } = config; - let inventory; - let custom = false; - if (data.vending_machine_input) { - inventory = data.vending_machine_input; - custom = true; - } else if (data.extended_inventory) { - inventory = [ - ...data.product_records, - ...data.coin_records, - ...data.hidden_records, - ]; - } else { - inventory = [ - ...data.product_records, - ...data.coin_records, - ]; - } - return ( - - {!!data.onstation && ( -
    - {data.user && ( - - Welcome, {data.user.name}, - {' '} - {data.user.job || "Unemployed"}! -
    - Your balance is {data.user.cash} credits. -
    - ) || ( - - No registered ID card!
    - Please contact your local HoP! -
    - )} -
    - )} -
    - - {inventory.map((product => { - const free = ( - !data.onstation - || product.price === 0 - ); - const to_pay = (!product.premium - ? Math.round(product.price * data.cost_mult) - : product.price - ); - const pay_text = (!product.premium - ? to_pay + ' cr' + data.cost_text - : to_pay + ' cr' - ); - return ( - - - {product.base64 ? ( - - ) : ( - - )} - {product.name} - - - - {data.stock[product.name]} in stock - - - - {custom && ( -
    -
    -
    - ); -}; \ No newline at end of file diff --git a/tgui-next/packages/tgui/interfaces/Wires.js b/tgui-next/packages/tgui/interfaces/Wires.js deleted file mode 100644 index f33b261738..0000000000 --- a/tgui-next/packages/tgui/interfaces/Wires.js +++ /dev/null @@ -1,59 +0,0 @@ -import { Fragment } from 'inferno'; -import { useBackend } from '../backend'; -import { Box, Button, LabeledList, Section } from '../components'; - -export const Wires = props => { - const { act, data } = useBackend(props); - const wires = data.wires || []; - const statuses = data.status || []; - return ( - -
    - - {wires.map(wire => ( - -
    - {!!statuses.length && ( -
    - {statuses.map(status => ( - - {status} - - ))} -
    - )} -
    - ); -}; diff --git a/tgui-next/packages/tgui/layout.js b/tgui-next/packages/tgui/layout.js deleted file mode 100644 index dcaba87204..0000000000 --- a/tgui-next/packages/tgui/layout.js +++ /dev/null @@ -1,95 +0,0 @@ -import { classes } from 'common/react'; -import { decodeHtmlEntities } from 'common/string'; -import { Component, Fragment } from 'inferno'; -import { runCommand, winset } from './byond'; -import { Box, TitleBar } from './components'; -import { Toast } from './components/Toast'; -import { UI_DISABLED, UI_INTERACTIVE } from './constants'; -import { dragStartHandler, resizeStartHandler } from './drag'; -import { releaseHeldKeys } from './hotkeys'; -import { createLogger } from './logging'; -import { refocusLayout } from './refocus'; -import { getRoute } from './routes'; - -const logger = createLogger('Layout'); - -export class Layout extends Component { - componentDidMount() { - refocusLayout(); - } - - render() { - const { props } = this; - const { state, dispatch } = props; - const { config } = state; - const route = getRoute(state); - if (!route) { - return `Component for '${config.interface}' was not found.`; - } - const RoutedComponent = route.component(); - const WrapperComponent = route.wrapper && route.wrapper(); - const { scrollable, theme } = route; - // Render content - let contentElement = ( -
    - - - -
    - ); - // Wrap into the wrapper component - if (WrapperComponent) { - contentElement = ( - - {contentElement} - - ); - } - // Determine when to show dimmer - const showDimmer = config.observer - ? config.status < UI_DISABLED - : config.status < UI_INTERACTIVE; - return ( -
    -
    - { - logger.log('pressed close'); - releaseHeldKeys(); - winset(config.window, 'is-visible', false); - runCommand(`uiclose ${config.ref}`); - }} /> - {contentElement} - {showDimmer && ( -
    - )} - {state.toastText && ( - - )} - {config.fancy && scrollable && ( - -
    -
    -
    - - )} -
    -
    - ); - } -} diff --git a/tgui-next/packages/tgui/polyfills.js b/tgui-next/packages/tgui/polyfills.js deleted file mode 100644 index 0c70827679..0000000000 --- a/tgui-next/packages/tgui/polyfills.js +++ /dev/null @@ -1,5 +0,0 @@ -// This one is necessary for Inferno to do complex DOM patching on IE8. -// Not the fastest one or most spec compliant, but hey, it works! -if (!window.Int32Array) { - window.Int32Array = Array; -} diff --git a/tgui-next/packages/tgui/public/tgui-fallback.html b/tgui-next/packages/tgui/public/tgui-fallback.html deleted file mode 100644 index b9757bac48..0000000000 --- a/tgui-next/packages/tgui/public/tgui-fallback.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - -
    -
    - Loading...
    -
    -
    - - - - - - - - - diff --git a/tgui-next/packages/tgui/public/tgui-main.html b/tgui-next/packages/tgui/public/tgui-main.html deleted file mode 100644 index d32a01f62a..0000000000 --- a/tgui-next/packages/tgui/public/tgui-main.html +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    - - - - - - - - diff --git a/tgui-next/packages/tgui/public/tgui.bundle.css b/tgui-next/packages/tgui/public/tgui.bundle.css deleted file mode 100644 index 26f8010e06..0000000000 --- a/tgui-next/packages/tgui/public/tgui.bundle.css +++ /dev/null @@ -1 +0,0 @@ -body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4,h5,h6{display:block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}td,th{vertical-align:baseline;text-align:left}.candystripe:nth-child(odd){background-color:rgba(0,0,0,.25)}.color-black{color:#0d0d0d!important}.color-white{color:#fff!important}.color-red{color:#d33!important}.color-orange{color:#f37827!important}.color-yellow{color:#fbd814!important}.color-olive{color:#c0d919!important}.color-green{color:#22be47!important}.color-teal{color:#00c5bd!important}.color-blue{color:#238cdc!important}.color-violet{color:#6c3fcc!important}.color-purple{color:#a93bcd!important}.color-pink{color:#e2439c!important}.color-brown{color:#af6d43!important}.color-grey{color:#7d7d7d!important}.color-good{color:#62b62a!important}.color-average{color:#f1951d!important}.color-bad{color:#d33!important}.color-label{color:#8496ab!important}.color-bg-black{background-color:#000!important}.color-bg-white{background-color:#d9d9d9!important}.color-bg-red{background-color:#bd2020!important}.color-bg-orange{background-color:#d95e0c!important}.color-bg-yellow{background-color:#d9b804!important}.color-bg-olive{background-color:#9aad14!important}.color-bg-green{background-color:#1b9638!important}.color-bg-teal{background-color:#009a93!important}.color-bg-blue{background-color:#1c71b1!important}.color-bg-violet{background-color:#552dab!important}.color-bg-purple{background-color:#8b2baa!important}.color-bg-pink{background-color:#cf2082!important}.color-bg-brown{background-color:#8c5836!important}.color-bg-grey{background-color:#646464!important}.color-bg-good{background-color:#4d9121!important}.color-bg-average{background-color:#cd7a0d!important}.color-bg-bad{background-color:#bd2020!important}.color-bg-label{background-color:#657a94!important}.display-none{display:none}.display-block{display:block}.display-inline{display:inline}.display-inline-block{display:inline-block}.m-0{margin:0}.mx-0{margin-left:0;margin-right:0}.my-0{margin-top:0;margin-bottom:0}.ml-0{margin-left:0}.mt-0{margin-top:0}.mr-0{margin-right:0}.mb-0{margin-bottom:0}.m-1{margin:6px}.mx-1{margin-left:6px;margin-right:6px}.my-1{margin-top:6px;margin-bottom:6px}.ml-1{margin-left:6px}.mt-1{margin-top:6px}.mr-1{margin-right:6px}.mb-1{margin-bottom:6px}.m-2{margin:12px}.mx-2{margin-left:12px;margin-right:12px}.my-2{margin-top:12px;margin-bottom:12px}.ml-2{margin-left:12px}.mt-2{margin-top:12px}.mr-2{margin-right:12px}.mb-2{margin-bottom:12px}.position-relative{position:relative}.position-absolute{position:absolute}.position-fixed{position:fixed}.position-sticky{position:sticky}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.text-baseline{text-align:baseline}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-pre{white-space:pre}.text-bold{font-weight:700}.text-italic{font-style:italic}.text-underline{text-decoration:underline}.BlockQuote{color:#8496ab;border-left:2px solid #8496ab;padding-left:6px}.Button{position:relative;display:inline-block;line-height:20px;padding:0 6px;margin-right:2px;white-space:nowrap;outline:0;border-radius:0;margin-bottom:2px;user-select:none;-ms-user-select:none}.Button:last-child{margin-right:0}.Button .fa,.Button .far,.Button .fas{margin-left:-3px;margin-right:-3px;min-width:16px;text-align:center}.Button--hasContent .fa,.Button--hasContent .far,.Button--hasContent .fas{margin-right:3px}.Button--ellipsis{overflow:hidden;text-overflow:ellipsis}.Button--fluid{display:block;margin-left:0;margin-right:0}.Button--color--black{transition:color 50ms,background-color 50ms;background-color:#000;color:#fff}.Button--color--black:hover{transition:color 0ms,background-color 0ms}.Button--color--black:focus{transition:color .1s,background-color .1s}.Button--color--black:focus,.Button--color--black:hover{background-color:#0a0a0a;color:#fff}.Button--color--white{transition:color 50ms,background-color 50ms;background-color:#d9d9d9;color:#000}.Button--color--white:hover{transition:color 0ms,background-color 0ms}.Button--color--white:focus{transition:color .1s,background-color .1s}.Button--color--white:focus,.Button--color--white:hover{background-color:#f3f3f3;color:#000}.Button--color--red{transition:color 50ms,background-color 50ms;background-color:#bd2020;color:#fff}.Button--color--red:hover{transition:color 0ms,background-color 0ms}.Button--color--red:focus{transition:color .1s,background-color .1s}.Button--color--red:focus,.Button--color--red:hover{background-color:#d52b2b;color:#fff}.Button--color--orange{transition:color 50ms,background-color 50ms;background-color:#d95e0c;color:#fff}.Button--color--orange:hover{transition:color 0ms,background-color 0ms}.Button--color--orange:focus{transition:color .1s,background-color .1s}.Button--color--orange:focus,.Button--color--orange:hover{background-color:#ed6f1d;color:#fff}.Button--color--yellow{transition:color 50ms,background-color 50ms;background-color:#d9b804;color:#000}.Button--color--yellow:hover{transition:color 0ms,background-color 0ms}.Button--color--yellow:focus{transition:color .1s,background-color .1s}.Button--color--yellow:focus,.Button--color--yellow:hover{background-color:#f3d00e;color:#000}.Button--color--olive{transition:color 50ms,background-color 50ms;background-color:#9aad14;color:#fff}.Button--color--olive:hover{transition:color 0ms,background-color 0ms}.Button--color--olive:focus{transition:color .1s,background-color .1s}.Button--color--olive:focus,.Button--color--olive:hover{background-color:#afc41f;color:#fff}.Button--color--green{transition:color 50ms,background-color 50ms;background-color:#1b9638;color:#fff}.Button--color--green:hover{transition:color 0ms,background-color 0ms}.Button--color--green:focus{transition:color .1s,background-color .1s}.Button--color--green:focus,.Button--color--green:hover{background-color:#27ab46;color:#fff}.Button--color--teal{transition:color 50ms,background-color 50ms;background-color:#009a93;color:#fff}.Button--color--teal:hover{transition:color 0ms,background-color 0ms}.Button--color--teal:focus{transition:color .1s,background-color .1s}.Button--color--teal:focus,.Button--color--teal:hover{background-color:#0aafa8;color:#fff}.Button--color--blue{transition:color 50ms,background-color 50ms;background-color:#1c71b1;color:#fff}.Button--color--blue:hover{transition:color 0ms,background-color 0ms}.Button--color--blue:focus{transition:color .1s,background-color .1s}.Button--color--blue:focus,.Button--color--blue:hover{background-color:#2883c8;color:#fff}.Button--color--violet{transition:color 50ms,background-color 50ms;background-color:#552dab;color:#fff}.Button--color--violet:hover{transition:color 0ms,background-color 0ms}.Button--color--violet:focus{transition:color .1s,background-color .1s}.Button--color--violet:focus,.Button--color--violet:hover{background-color:#653ac1;color:#fff}.Button--color--purple{transition:color 50ms,background-color 50ms;background-color:#8b2baa;color:#fff}.Button--color--purple:hover{transition:color 0ms,background-color 0ms}.Button--color--purple:focus{transition:color .1s,background-color .1s}.Button--color--purple:focus,.Button--color--purple:hover{background-color:#9e38c1;color:#fff}.Button--color--pink{transition:color 50ms,background-color 50ms;background-color:#cf2082;color:#fff}.Button--color--pink:hover{transition:color 0ms,background-color 0ms}.Button--color--pink:focus{transition:color .1s,background-color .1s}.Button--color--pink:focus,.Button--color--pink:hover{background-color:#dd3794;color:#fff}.Button--color--brown{transition:color 50ms,background-color 50ms;background-color:#8c5836;color:#fff}.Button--color--brown:hover{transition:color 0ms,background-color 0ms}.Button--color--brown:focus{transition:color .1s,background-color .1s}.Button--color--brown:focus,.Button--color--brown:hover{background-color:#a06844;color:#fff}.Button--color--grey{transition:color 50ms,background-color 50ms;background-color:#646464;color:#fff}.Button--color--grey:hover{transition:color 0ms,background-color 0ms}.Button--color--grey:focus{transition:color .1s,background-color .1s}.Button--color--grey:focus,.Button--color--grey:hover{background-color:#757575;color:#fff}.Button--color--good{transition:color 50ms,background-color 50ms;background-color:#4d9121;color:#fff}.Button--color--good:hover{transition:color 0ms,background-color 0ms}.Button--color--good:focus{transition:color .1s,background-color .1s}.Button--color--good:focus,.Button--color--good:hover{background-color:#5da52d;color:#fff}.Button--color--average{transition:color 50ms,background-color 50ms;background-color:#cd7a0d;color:#fff}.Button--color--average:hover{transition:color 0ms,background-color 0ms}.Button--color--average:focus{transition:color .1s,background-color .1s}.Button--color--average:focus,.Button--color--average:hover{background-color:#e68d18;color:#fff}.Button--color--bad{transition:color 50ms,background-color 50ms;background-color:#bd2020;color:#fff}.Button--color--bad:hover{transition:color 0ms,background-color 0ms}.Button--color--bad:focus{transition:color .1s,background-color .1s}.Button--color--bad:focus,.Button--color--bad:hover{background-color:#d52b2b;color:#fff}.Button--color--label{transition:color 50ms,background-color 50ms;background-color:#657a94;color:#fff}.Button--color--label:hover{transition:color 0ms,background-color 0ms}.Button--color--label:focus{transition:color .1s,background-color .1s}.Button--color--label:focus,.Button--color--label:hover{background-color:#7b8da4;color:#fff}.Button--color--default{transition:color 50ms,background-color 50ms;background-color:#3e6189;color:#fff}.Button--color--default:hover{transition:color 0ms,background-color 0ms}.Button--color--default:focus{transition:color .1s,background-color .1s}.Button--color--default:focus,.Button--color--default:hover{background-color:#4c729d;color:#fff}.Button--color--caution{transition:color 50ms,background-color 50ms;background-color:#d9b804;color:#000}.Button--color--caution:hover{transition:color 0ms,background-color 0ms}.Button--color--caution:focus{transition:color .1s,background-color .1s}.Button--color--caution:focus,.Button--color--caution:hover{background-color:#f3d00e;color:#000}.Button--color--danger{transition:color 50ms,background-color 50ms;background-color:#bd2020;color:#fff}.Button--color--danger:hover{transition:color 0ms,background-color 0ms}.Button--color--danger:focus{transition:color .1s,background-color .1s}.Button--color--danger:focus,.Button--color--danger:hover{background-color:#d52b2b;color:#fff}.Button--color--transparent{transition:color 50ms,background-color 50ms;background-color:#252525;color:#fff;background-color:rgba(37,37,37,0);color:hsla(0,0%,100%,.5)}.Button--color--transparent:hover{transition:color 0ms,background-color 0ms}.Button--color--transparent:focus{transition:color .1s,background-color .1s}.Button--color--transparent:focus,.Button--color--transparent:hover{background-color:#323232;color:#fff}.Button--disabled{background-color:#999!important}.Button--selected{transition:color 50ms,background-color 50ms;background-color:#1b9638;color:#fff}.Button--selected:hover{transition:color 0ms,background-color 0ms}.Button--selected:focus{transition:color .1s,background-color .1s}.Button--selected:focus,.Button--selected:hover{background-color:#27ab46;color:#fff}.ColorBox{display:inline-block;width:12px;height:12px;line-height:12px;text-align:center}.Dropdown{position:relative}.Dropdown__control{position:relative;display:inline-block;font-family:Verdana,sans-serif;font-size:12px;width:100px;line-height:17px;user-select:none}.Dropdown__arrow-button{float:right;padding-left:6px;border-left:1px solid #000;border-left:1px solid rgba(0,0,0,.25)}.Dropdown__menu{position:absolute;overflow-y:auto;z-index:5;width:100px;max-height:200px;overflow-y:scroll;border-radius:0 0 2px 2px;background-color:#000;background-color:rgba(0,0,0,.75)}.Dropdown__menuentry{padding:2px 4px;font-family:Verdana,sans-serif;font-size:12px;line-height:17px;transition:background-color .1s}.Dropdown__menuentry:hover{background-color:#444;transition:background-color 0ms}.Dropdown__over{top:auto;bottom:100%}.FatalError{display:block!important;position:absolute;top:0;left:0;right:0;bottom:0;padding:12px;font-size:12px;font-family:Consolas,monospace;color:#fff;background-color:#00d;z-index:1000;overflow:hidden;text-align:center}.FatalError__logo{display:inline-block;text-align:left;font-size:10px;line-height:8px;position:relative;margin-top:12px;top:0;left:0;animation:FatalError__rainbow 2s linear infinite alternate,FatalError__shadow 4s linear infinite alternate,FatalError__tfmX 3s infinite alternate,FatalError__tfmY 4s infinite alternate;white-space:pre-wrap;word-break:break-all}.FatalError__header{margin-top:12px}.FatalError__stack{text-align:left;white-space:pre-wrap;word-break:break-all;margin-top:24px;margin-bottom:24px}.FatalError__footer{margin-bottom:24px}@keyframes FatalError__rainbow{0%{color:#ff0}50%{color:#0ff}to{color:#f0f}}@keyframes FatalError__shadow{0%{left:-2px;text-shadow:4px 0 #f0f}50%{left:0;text-shadow:0 0 #0ff}to{left:2px;text-shadow:-4px 0 #ff0}}@keyframes FatalError__tfmX{0%{left:15px}to{left:-15px}}@keyframes FatalError__tfmY{to{top:-15px}}.Flex{display:-ms-flexbox;display:flex}.Flex--spacing--1{margin:-3px -3px 3px}.Flex--spacing--1>.Flex__item{margin:3px}.Flex--spacing--2{margin:-6px -6px 6px}.Flex--spacing--2>.Flex__item{margin:6px}.LabeledList{display:table;width:100%;width:calc(100% + 12px);border-collapse:collapse;border-spacing:0;margin:-3px -6px 0;padding:0}.LabeledList__row{display:table-row}.LabeledList__row:last-child .LabeledList__cell{padding-bottom:0}.LabeledList__cell{display:table-cell;margin:0;padding:3px 6px;border:0;text-align:left;vertical-align:baseline}.LabeledList__label{width:1%;white-space:nowrap;min-width:60px}.LabeledList__buttons{width:.1%;white-space:nowrap;text-align:right;padding-top:1px;padding-bottom:0}.Layout{bottom:0;right:0;color:#fff;background-color:#252525;background-image:linear-gradient(180deg,#2a2a2a 0,#202020)}.Layout,.Layout__titleBar{position:fixed;top:0;left:0}.Layout__titleBar{z-index:1;width:100%;height:32px}.Layout__content{position:fixed;top:32px;bottom:0;left:0;right:0;overflow-x:hidden;overflow-y:hidden;margin-bottom:-6px;scrollbar-base-color:#1c1c1c;scrollbar-face-color:#3b3b3b;scrollbar-3dlight-color:#252525;scrollbar-highlight-color:#252525;scrollbar-track-color:#1c1c1c;scrollbar-arrow-color:#929292;scrollbar-shadow-color:#3b3b3b}.Layout__content--scrollable{overflow-y:scroll;margin-bottom:0}.Layout__dimmer{top:32px;background-color:rgba(62,62,62,.25);pointer-events:none}.Layout__dimmer,.Layout__toast{position:fixed;bottom:0;left:0;right:0}.Layout__toast{font-size:12px;height:40px;line-height:39px;padding:0 12px;background-color:#131313;color:hsla(0,0%,100%,.8)}.Layout__resizeHandle__se{position:fixed;bottom:0;right:0;width:20px;height:20px;cursor:se-resize}.Layout__resizeHandle__s{position:fixed;bottom:0;left:0;right:0;height:6px;cursor:s-resize}.Layout__resizeHandle__e{position:fixed;top:0;bottom:0;right:0;width:3px;cursor:e-resize}.NoticeBox{padding:4px 6px;margin-bottom:6px;box-shadow:none;font-weight:700;font-style:italic;color:#000;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}.NtosHeader__left{position:absolute;left:12px}.NtosHeader__right{position:absolute;right:12px}.NtosHeader__icon{margin-top:-9px;margin-bottom:-6px;vertical-align:middle}.NtosWrapper__header{position:absolute;top:32px;left:0;right:0;height:28px;line-height:27px;background-color:rgba(0,0,0,.5);font-family:Consolas,monospace;font-size:14px;user-select:none;-ms-user-select:none}.NtosWrapper__content .Layout__content{margin-top:28px;font-family:Consolas,monospace;font-size:14px}.NuclearBomb__displayBox{background-color:#002003;border:4px inset #e8e4c9;color:#03e017;font-size:24px;font-family:monospace;padding:6px}.NuclearBomb__Button--keypad{background-color:#e8e4c9;border-color:#e8e4c9}.NuclearBomb__Button--keypad:hover{background-color:#f7f6ee!important;border-color:#f7f6ee!important}.NuclearBomb__Button--1{background-color:#d3cfb7!important;border-color:#d3cfb7!important;color:#a9a692!important}.NuclearBomb__Button--E{background-color:#d9b804!important;border-color:#d9b804!important}.NuclearBomb__Button--E:hover{background-color:#f3d00e!important;border-color:#f3d00e!important}.NuclearBomb__Button--C{background-color:#bd2020!important;border-color:#bd2020!important}.NuclearBomb__Button--C:hover{background-color:#d52b2b!important;border-color:#d52b2b!important}.NuclearBomb__NTIcon{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDQyNSAyMDAiIG9wYWNpdHk9Ii4zMyI+PHBhdGggZD0iTTE3OC4wMDQuMDM5SDEwNi44YTYuNzYxIDYuMDI2IDAgMDAtNi43NjEgNi4wMjV2MTg3Ljg3MmE2Ljc2MSA2LjAyNiAwIDAwNi43NjEgNi4wMjVoNTMuMTA3YTYuNzYxIDYuMDI2IDAgMDA2Ljc2Mi02LjAyNVY5Mi4zOTJsNzIuMjE2IDEwNC43YTYuNzYxIDYuMDI2IDAgMDA1Ljc2IDIuODdIMzE4LjJhNi43NjEgNi4wMjYgMCAwMDYuNzYxLTYuMDI2VjYuMDY0QTYuNzYxIDYuMDI2IDAgMDAzMTguMi4wNGgtNTQuNzE3YTYuNzYxIDYuMDI2IDAgMDAtNi43NiA2LjAyNXYxMDIuNjJMMTgzLjc2MyAyLjkwOWE2Ljc2MSA2LjAyNiAwIDAwLTUuNzYtMi44N3pNNC44NDUgMjIuMTA5QTEzLjQxMiAxMi41MDIgMCAwMTEzLjQ3OC4wMzloNjYuMTE4QTUuMzY1IDUgMCAwMTg0Ljk2IDUuMDR2NzkuODh6TTQyMC4xNTUgMTc3Ljg5MWExMy40MTIgMTIuNTAyIDAgMDEtOC42MzMgMjIuMDdoLTY2LjExOGE1LjM2NSA1IDAgMDEtNS4zNjUtNS4wMDF2LTc5Ljg4eiIvPjwvc3ZnPg==);background-size:70%;background-position:50%;background-repeat:no-repeat}.Input{position:relative;display:inline-block;width:120px;border:1px solid #88bfff;border:1px solid rgba(136,191,255,.75);border-radius:2px;color:#fff;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;overflow:visible}.Input--fluid{display:block;width:auto}.Input__baseline{display:inline-block;color:transparent}.Input__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:transparent;color:#fff;color:inherit}.Input__input:-ms-input-placeholder{font-style:italic;color:#777;color:hsla(0,0%,100%,.45)}.NumberInput{position:relative;display:inline-block;border:1px solid #88bfff;border:1px solid rgba(136,191,255,.75);border-radius:2px;color:#88bfff;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;text-align:right;overflow:visible;cursor:n-resize}.NumberInput--fluid{display:block}.NumberInput__content{margin-left:6px}.NumberInput__barContainer{position:absolute;top:2px;bottom:2px;left:2px}.NumberInput__bar{position:absolute;bottom:0;left:0;width:3px;box-sizing:border-box;border-bottom:1px solid #88bfff;background-color:#88bfff}.NumberInput__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:#000;color:#fff;text-align:right}.ProgressBar{display:inline-block;position:relative;width:100%;padding:0 6px;border-radius:0;background-color:transparent;transition:border-color .5s}.ProgressBar__fill{position:absolute;top:0;left:0;bottom:0;transition:background-color .5s,width .5s}.ProgressBar__content{position:relative;line-height:17px;width:100%;text-align:right}.ProgressBar--color--default{border:1px solid #3e6189}.ProgressBar--color--default .ProgressBar__fill{background-color:#3e6189}.ProgressBar--color--black{border:1px solid #000!important}.ProgressBar--color--black .ProgressBar__fill{background-color:#000}.ProgressBar--color--white{border:1px solid #d9d9d9!important}.ProgressBar--color--white .ProgressBar__fill{background-color:#d9d9d9}.ProgressBar--color--red{border:1px solid #bd2020!important}.ProgressBar--color--red .ProgressBar__fill{background-color:#bd2020}.ProgressBar--color--orange{border:1px solid #d95e0c!important}.ProgressBar--color--orange .ProgressBar__fill{background-color:#d95e0c}.ProgressBar--color--yellow{border:1px solid #d9b804!important}.ProgressBar--color--yellow .ProgressBar__fill{background-color:#d9b804}.ProgressBar--color--olive{border:1px solid #9aad14!important}.ProgressBar--color--olive .ProgressBar__fill{background-color:#9aad14}.ProgressBar--color--green{border:1px solid #1b9638!important}.ProgressBar--color--green .ProgressBar__fill{background-color:#1b9638}.ProgressBar--color--teal{border:1px solid #009a93!important}.ProgressBar--color--teal .ProgressBar__fill{background-color:#009a93}.ProgressBar--color--blue{border:1px solid #1c71b1!important}.ProgressBar--color--blue .ProgressBar__fill{background-color:#1c71b1}.ProgressBar--color--violet{border:1px solid #552dab!important}.ProgressBar--color--violet .ProgressBar__fill{background-color:#552dab}.ProgressBar--color--purple{border:1px solid #8b2baa!important}.ProgressBar--color--purple .ProgressBar__fill{background-color:#8b2baa}.ProgressBar--color--pink{border:1px solid #cf2082!important}.ProgressBar--color--pink .ProgressBar__fill{background-color:#cf2082}.ProgressBar--color--brown{border:1px solid #8c5836!important}.ProgressBar--color--brown .ProgressBar__fill{background-color:#8c5836}.ProgressBar--color--grey{border:1px solid #646464!important}.ProgressBar--color--grey .ProgressBar__fill{background-color:#646464}.ProgressBar--color--good{border:1px solid #4d9121!important}.ProgressBar--color--good .ProgressBar__fill{background-color:#4d9121}.ProgressBar--color--average{border:1px solid #cd7a0d!important}.ProgressBar--color--average .ProgressBar__fill{background-color:#cd7a0d}.ProgressBar--color--bad{border:1px solid #bd2020!important}.ProgressBar--color--bad .ProgressBar__fill{background-color:#bd2020}.ProgressBar--color--label{border:1px solid #657a94!important}.ProgressBar--color--label .ProgressBar__fill{background-color:#657a94}.Section{position:relative;margin-bottom:6px;background-color:#1a1a1a;background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5);box-sizing:border-box}.Section:last-child{margin-bottom:0}.Section__title{position:relative;padding:6px;border-bottom:2px solid #4972a1}.Section__titleText{font-size:14px;font-weight:700}.Section__buttons{position:absolute;display:inline-block;right:6px;margin-top:-1px}.Section__content{padding:8px 6px}.Section--level--1 .Section__titleText{font-size:14px}.Section--level--2 .Section__titleText{font-size:13px}.Section--level--3 .Section__titleText{font-size:12px}.Section--level--2,.Section--level--3{background-color:transparent;box-shadow:none;margin-left:-6px;margin-right:-6px}.Table{display:table;width:100%;border-collapse:collapse;border-spacing:0;margin:0}.Table--collapsing{width:auto}.Table__row{display:table-row}.Table__cell{display:table-cell;padding:0 3px}.Table__cell:first-child{padding-left:0}.Table__cell:last-child{padding-right:0}.Table__cell--header,.Table__row--header .Table__cell{font-weight:700;padding-bottom:6px}.Table__cell--collapsing{width:1%;white-space:nowrap}.Tabs__content{padding-top:6px;border-top:2px solid hsla(0,0%,100%,.1)}.Tabs--vertical{display:table-row}.Tabs--vertical>.Tabs__content{display:table-cell;width:100%;padding-top:0;padding-left:9px;border-top:0}.Tabs--vertical>.Tabs__tabBox{display:table-cell;border-right:2px solid hsla(0,0%,100%,.1);vertical-align:top}.Tabs--vertical>.Tabs__tabBox>.Tabs__tab{display:block!important;margin-right:0;margin-bottom:0;padding:1px 9px 0 6px;border-bottom:2px solid hsla(0,0%,100%,.1)}.Tabs--vertical>.Tabs__tabBox>.Tabs__tab:last-child{border-bottom:0}.TitleBar{background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 2px 2px rgba(0,0,0,.1);user-select:none;-ms-user-select:none}.TitleBar__clickable{color:hsla(0,0%,100%,.5);background-color:#363636;transition:color .25s,background-color .25s}.TitleBar__clickable:hover{color:#fff;background-color:#c00;transition:color 0ms,background-color 0ms}.TitleBar__title{position:absolute;top:0;left:46px;color:hsla(0,0%,100%,.75);font-size:14px;line-height:31px;white-space:nowrap}.TitleBar__dragZone{position:absolute;top:0;left:0;right:0;height:32px}.TitleBar__statusIcon{position:absolute;top:0;left:12px;transition:color .5s;font-size:20px;line-height:32px!important}.TitleBar__minimize{position:absolute;top:6px;right:46px}.TitleBar__close{position:absolute;top:-1px;right:0;width:45px;height:32px;font-size:20px;line-height:31px;text-align:center}.Tooltip{position:absolute;top:0;left:0;right:0;bottom:0;font-style:normal;font-weight:400}.Tooltip:after{position:absolute;display:block;white-space:nowrap;z-index:2;padding:6px 10px;transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;text-align:left;content:attr(data-tooltip);transition:all .15s;background-color:#000;box-shadow:1px 1px 15px -1px rgba(0,0,0,.5);border-radius:2px}.Tooltip:hover:after{transition:all 70ms;pointer-events:none;visibility:visible;opacity:1}.Tooltip--long:after{width:250px;white-space:normal}.Tooltip--top:after{bottom:100%;left:50%;transform:translateX(-50%) translateY(8px)}.Tooltip--bottom:after,.Tooltip--top:hover:after{transform:translateX(-50%) translateY(-8px)}.Tooltip--bottom:after{top:100%;left:50%}.Tooltip--bottom:hover:after{transform:translateX(-50%) translateY(8px)}.Tooltip--bottom-left:after{top:100%;right:50%;transform:translateX(12px) translateY(-8px)}.Tooltip--bottom-left:hover:after{transform:translateX(12px) translateY(8px)}.Tooltip--bottom-right:after{top:100%;left:50%;transform:translateX(-12px) translateY(-8px)}.Tooltip--bottom-right:hover:after{transform:translateX(-12px) translateY(8px)}.Tooltip--left:after{top:50%;right:100%;transform:translateX(8px) translateY(-50%)}.Tooltip--left:hover:after,.Tooltip--right:after{transform:translateX(-8px) translateY(-50%)}.Tooltip--right:after{top:50%;left:100%}.Tooltip--right:hover:after{transform:translateX(8px) translateY(-50%)}.Layout__content{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDQyNSAyMDAiIG9wYWNpdHk9Ii4zMyI+PHBhdGggZD0iTTE3OC4wMDQuMDM5SDEwNi44YTYuNzYxIDYuMDI2IDAgMDAtNi43NjEgNi4wMjV2MTg3Ljg3MmE2Ljc2MSA2LjAyNiAwIDAwNi43NjEgNi4wMjVoNTMuMTA3YTYuNzYxIDYuMDI2IDAgMDA2Ljc2Mi02LjAyNVY5Mi4zOTJsNzIuMjE2IDEwNC43YTYuNzYxIDYuMDI2IDAgMDA1Ljc2IDIuODdIMzE4LjJhNi43NjEgNi4wMjYgMCAwMDYuNzYxLTYuMDI2VjYuMDY0QTYuNzYxIDYuMDI2IDAgMDAzMTguMi4wNGgtNTQuNzE3YTYuNzYxIDYuMDI2IDAgMDAtNi43NiA2LjAyNXYxMDIuNjJMMTgzLjc2MyAyLjkwOWE2Ljc2MSA2LjAyNiAwIDAwLTUuNzYtMi44N3pNNC44NDUgMjIuMTA5QTEzLjQxMiAxMi41MDIgMCAwMTEzLjQ3OC4wMzloNjYuMTE4QTUuMzY1IDUgMCAwMTg0Ljk2IDUuMDR2NzkuODh6TTQyMC4xNTUgMTc3Ljg5MWExMy40MTIgMTIuNTAyIDAgMDEtOC42MzMgMjIuMDdoLTY2LjExOGE1LjM2NSA1IDAgMDEtNS4zNjUtNS4wMDF2LTc5Ljg4eiIvPjwvc3ZnPg==);background-size:70%;background-position:50%;background-repeat:no-repeat}.action_test{display:inherit}.theme-cardtable .Button{position:relative;display:inline-block;line-height:20px;padding:0 6px;margin-right:2px;white-space:nowrap;outline:0;border-radius:0;margin-bottom:2px;user-select:none;-ms-user-select:none}.theme-cardtable .Button:last-child{margin-right:0}.theme-cardtable .Button .fa,.theme-cardtable .Button .far,.theme-cardtable .Button .fas{margin-left:-3px;margin-right:-3px;min-width:16px;text-align:center}.theme-cardtable .Button--hasContent .fa,.theme-cardtable .Button--hasContent .far,.theme-cardtable .Button--hasContent .fas{margin-right:3px}.theme-cardtable .Button--ellipsis{overflow:hidden;text-overflow:ellipsis}.theme-cardtable .Button--fluid{display:block;margin-left:0;margin-right:0}.theme-cardtable .Button--color--default{transition:color 50ms,background-color 50ms;background-color:#117039;color:#fff}.theme-cardtable .Button--color--default:hover{transition:color 0ms,background-color 0ms}.theme-cardtable .Button--color--default:focus{transition:color .1s,background-color .1s}.theme-cardtable .Button--color--default:focus,.theme-cardtable .Button--color--default:hover{background-color:#1c8247;color:#fff}.theme-cardtable .Button--color--caution{transition:color 50ms,background-color 50ms;background-color:#be6209;color:#fff}.theme-cardtable .Button--color--caution:hover{transition:color 0ms,background-color 0ms}.theme-cardtable .Button--color--caution:focus{transition:color .1s,background-color .1s}.theme-cardtable .Button--color--caution:focus,.theme-cardtable .Button--color--caution:hover{background-color:#d67313;color:#fff}.theme-cardtable .Button--color--danger{transition:color 50ms,background-color 50ms;background-color:#9a9d00;color:#fff}.theme-cardtable .Button--color--danger:hover{transition:color 0ms,background-color 0ms}.theme-cardtable .Button--color--danger:focus{transition:color .1s,background-color .1s}.theme-cardtable .Button--color--danger:focus,.theme-cardtable .Button--color--danger:hover{background-color:#afb30a;color:#fff}.theme-cardtable .Button--color--transparent{transition:color 50ms,background-color 50ms;background-color:#117039;color:#fff;background-color:rgba(17,112,57,0);color:hsla(0,0%,100%,.5)}.theme-cardtable .Button--color--transparent:hover{transition:color 0ms,background-color 0ms}.theme-cardtable .Button--color--transparent:focus{transition:color .1s,background-color .1s}.theme-cardtable .Button--color--transparent:focus,.theme-cardtable .Button--color--transparent:hover{background-color:#1c8247;color:#fff}.theme-cardtable .Button--disabled{background-color:#363636!important}.theme-cardtable .Button--selected{transition:color 50ms,background-color 50ms;background-color:#9d0808;color:#fff}.theme-cardtable .Button--selected:hover{transition:color 0ms,background-color 0ms}.theme-cardtable .Button--selected:focus{transition:color .1s,background-color .1s}.theme-cardtable .Button--selected:focus,.theme-cardtable .Button--selected:hover{background-color:#b31212;color:#fff}.theme-cardtable .Layout{position:fixed;top:0;bottom:0;left:0;right:0;color:#fff;background-color:#117039;background-image:linear-gradient(180deg,#117039 0,#117039)}.theme-cardtable .Layout__titleBar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px}.theme-cardtable .Layout__content{position:fixed;top:32px;bottom:0;left:0;right:0;overflow-x:hidden;overflow-y:hidden;margin-bottom:-6px;scrollbar-base-color:#0d542b;scrollbar-face-color:#16914a;scrollbar-3dlight-color:#117039;scrollbar-highlight-color:#117039;scrollbar-track-color:#0d542b;scrollbar-arrow-color:#5ae695;scrollbar-shadow-color:#16914a}.theme-cardtable .Layout__content--scrollable{overflow-y:scroll;margin-bottom:0}.theme-cardtable .Layout__dimmer{position:fixed;top:32px;bottom:0;left:0;right:0;background-color:rgba(39,148,85,.25);pointer-events:none}.theme-cardtable .Layout__toast{position:fixed;bottom:0;left:0;right:0;font-size:12px;height:40px;line-height:39px;padding:0 12px;background-color:#09381d;color:hsla(0,0%,100%,.8)}.theme-cardtable .Layout__resizeHandle__se{position:fixed;bottom:0;right:0;width:20px;height:20px;cursor:se-resize}.theme-cardtable .Layout__resizeHandle__s{position:fixed;bottom:0;left:0;right:0;height:6px;cursor:s-resize}.theme-cardtable .Layout__resizeHandle__e{position:fixed;top:0;bottom:0;right:0;width:3px;cursor:e-resize}.theme-cardtable .Input{position:relative;display:inline-block;width:120px;border:1px solid #88bfff;border:1px solid rgba(136,191,255,.75);border-radius:0;color:#fff;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;overflow:visible}.theme-cardtable .Input--fluid{display:block;width:auto}.theme-cardtable .Input__baseline{display:inline-block;color:transparent}.theme-cardtable .Input__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:transparent;color:#fff;color:inherit}.theme-cardtable .Input__input:-ms-input-placeholder{font-style:italic;color:#777;color:hsla(0,0%,100%,.45)}.theme-cardtable .NumberInput{position:relative;display:inline-block;border:1px solid #fff;border:1px solid hsla(0,0%,100%,.75);border-radius:0;color:#fff;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;text-align:right;overflow:visible;cursor:n-resize}.theme-cardtable .NumberInput--fluid{display:block}.theme-cardtable .NumberInput__content{margin-left:6px}.theme-cardtable .NumberInput__barContainer{position:absolute;top:2px;bottom:2px;left:2px}.theme-cardtable .NumberInput__bar{position:absolute;bottom:0;left:0;width:3px;box-sizing:border-box;border-bottom:1px solid #fff;background-color:#fff}.theme-cardtable .NumberInput__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:#000;color:#fff;text-align:right}.theme-cardtable .ProgressBar{display:inline-block;position:relative;width:100%;padding:0 6px;border-radius:0;background-color:rgba(0,0,0,.5);transition:border-color .5s}.theme-cardtable .ProgressBar__fill{position:absolute;top:0;left:0;bottom:0;transition:background-color .5s,width .5s}.theme-cardtable .ProgressBar__content{position:relative;line-height:17px;width:100%;text-align:right}.theme-cardtable .ProgressBar--color--default{border:1px solid #000}.theme-cardtable .ProgressBar--color--default .ProgressBar__fill{background-color:#000}.theme-cardtable .Section{position:relative;margin-bottom:6px;background-color:#1a1a1a;background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5);box-sizing:border-box}.theme-cardtable .Section:last-child{margin-bottom:0}.theme-cardtable .Section__title{position:relative;padding:6px;border-bottom:2px solid #000}.theme-cardtable .Section__titleText{font-size:14px;font-weight:700}.theme-cardtable .Section__buttons{position:absolute;display:inline-block;right:6px;margin-top:-1px}.theme-cardtable .Section__content{padding:8px 6px}.theme-cardtable .Section--level--1 .Section__titleText{font-size:14px}.theme-cardtable .Section--level--2 .Section__titleText{font-size:13px}.theme-cardtable .Section--level--3 .Section__titleText{font-size:12px}.theme-cardtable .Section--level--2,.theme-cardtable .Section--level--3{background-color:transparent;box-shadow:none;margin-left:-6px;margin-right:-6px}.theme-cardtable .TitleBar{background-color:#381608;border-bottom:1px solid #161616;box-shadow:0 2px 2px rgba(0,0,0,.1);user-select:none;-ms-user-select:none}.theme-cardtable .TitleBar__clickable{color:hsla(0,0%,100%,.5);background-color:#381608;transition:color .25s,background-color .25s}.theme-cardtable .TitleBar__clickable:hover{color:#fff;background-color:#c00;transition:color 0ms,background-color 0ms}.theme-cardtable .TitleBar__title{position:absolute;top:0;left:46px;color:hsla(0,0%,100%,.75);font-size:14px;line-height:31px;white-space:nowrap}.theme-cardtable .TitleBar__dragZone{position:absolute;top:0;left:0;right:0;height:32px}.theme-cardtable .TitleBar__statusIcon{position:absolute;top:0;left:12px;transition:color .5s;font-size:20px;line-height:32px!important}.theme-cardtable .TitleBar__minimize{position:absolute;top:6px;right:46px}.theme-cardtable .TitleBar__close{position:absolute;top:-1px;right:0;width:45px;height:32px;font-size:20px;line-height:31px;text-align:center}.theme-cardtable .Button{border:2px solid #fff}.theme-ntos .Button{position:relative;display:inline-block;line-height:20px;padding:0 6px;margin-right:2px;white-space:nowrap;outline:0;border-radius:2px;margin-bottom:2px;user-select:none;-ms-user-select:none}.theme-ntos .Button:last-child{margin-right:0}.theme-ntos .Button .fa,.theme-ntos .Button .far,.theme-ntos .Button .fas{margin-left:-3px;margin-right:-3px;min-width:16px;text-align:center}.theme-ntos .Button--hasContent .fa,.theme-ntos .Button--hasContent .far,.theme-ntos .Button--hasContent .fas{margin-right:3px}.theme-ntos .Button--ellipsis{overflow:hidden;text-overflow:ellipsis}.theme-ntos .Button--fluid{display:block;margin-left:0;margin-right:0}.theme-ntos .Button--color--default{transition:color 50ms,background-color 50ms;background-color:#384e68;color:#fff}.theme-ntos .Button--color--default:hover{transition:color 0ms,background-color 0ms}.theme-ntos .Button--color--default:focus{transition:color .1s,background-color .1s}.theme-ntos .Button--color--default:focus,.theme-ntos .Button--color--default:hover{background-color:#465e7a;color:#fff}.theme-ntos .Button--color--caution{transition:color 50ms,background-color 50ms;background-color:#d9b804;color:#000}.theme-ntos .Button--color--caution:hover{transition:color 0ms,background-color 0ms}.theme-ntos .Button--color--caution:focus{transition:color .1s,background-color .1s}.theme-ntos .Button--color--caution:focus,.theme-ntos .Button--color--caution:hover{background-color:#f3d00e;color:#000}.theme-ntos .Button--color--danger{transition:color 50ms,background-color 50ms;background-color:#bd2020;color:#fff}.theme-ntos .Button--color--danger:hover{transition:color 0ms,background-color 0ms}.theme-ntos .Button--color--danger:focus{transition:color .1s,background-color .1s}.theme-ntos .Button--color--danger:focus,.theme-ntos .Button--color--danger:hover{background-color:#d52b2b;color:#fff}.theme-ntos .Button--color--transparent{transition:color 50ms,background-color 50ms;background-color:#1f2b39;color:#fff;background-color:rgba(31,43,57,0);color:rgba(227,240,255,.75)}.theme-ntos .Button--color--transparent:hover{transition:color 0ms,background-color 0ms}.theme-ntos .Button--color--transparent:focus{transition:color .1s,background-color .1s}.theme-ntos .Button--color--transparent:focus,.theme-ntos .Button--color--transparent:hover{background-color:#2b3847;color:#fff}.theme-ntos .Button--disabled{background-color:#999!important}.theme-ntos .Button--selected{transition:color 50ms,background-color 50ms;background-color:#1b9638;color:#fff}.theme-ntos .Button--selected:hover{transition:color 0ms,background-color 0ms}.theme-ntos .Button--selected:focus{transition:color .1s,background-color .1s}.theme-ntos .Button--selected:focus,.theme-ntos .Button--selected:hover{background-color:#27ab46;color:#fff}.theme-ntos .Layout{position:fixed;top:0;bottom:0;left:0;right:0;color:#fff;background-color:#1f2b39;background-image:linear-gradient(180deg,#223040 0,#1b2633)}.theme-ntos .Layout__titleBar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px}.theme-ntos .Layout__content{position:fixed;top:32px;bottom:0;left:0;right:0;overflow-x:hidden;overflow-y:hidden;margin-bottom:-6px;scrollbar-base-color:#17202b;scrollbar-face-color:#2e3f55;scrollbar-3dlight-color:#1f2b39;scrollbar-highlight-color:#1f2b39;scrollbar-track-color:#17202b;scrollbar-arrow-color:#7693b5;scrollbar-shadow-color:#2e3f55}.theme-ntos .Layout__content--scrollable{overflow-y:scroll;margin-bottom:0}.theme-ntos .Layout__dimmer{position:fixed;top:32px;bottom:0;left:0;right:0;background-color:rgba(55,69,85,.25);pointer-events:none}.theme-ntos .Layout__toast{position:fixed;bottom:0;left:0;right:0;font-size:12px;height:40px;line-height:39px;padding:0 12px;background-color:#0f151d;color:hsla(0,0%,100%,.8)}.theme-ntos .Layout__resizeHandle__se{position:fixed;bottom:0;right:0;width:20px;height:20px;cursor:se-resize}.theme-ntos .Layout__resizeHandle__s{position:fixed;bottom:0;left:0;right:0;height:6px;cursor:s-resize}.theme-ntos .Layout__resizeHandle__e{position:fixed;top:0;bottom:0;right:0;width:3px;cursor:e-resize}.theme-ntos .ProgressBar{display:inline-block;position:relative;width:100%;padding:0 6px;border-radius:2px;background-color:rgba(0,0,0,.5);transition:border-color .5s}.theme-ntos .ProgressBar__fill{position:absolute;top:0;left:0;bottom:0;transition:background-color .5s,width .5s}.theme-ntos .ProgressBar__content{position:relative;line-height:17px;width:100%;text-align:right}.theme-ntos .ProgressBar--color--default{border:1px solid #384e68}.theme-ntos .ProgressBar--color--default .ProgressBar__fill{background-color:#384e68}.theme-ntos .Section{position:relative;margin-bottom:6px;background-color:#1a1a1a;background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5);box-sizing:border-box}.theme-ntos .Section:last-child{margin-bottom:0}.theme-ntos .Section__title{position:relative;padding:6px;border-bottom:2px solid #4972a1}.theme-ntos .Section__titleText{font-size:14px;font-weight:700}.theme-ntos .Section__buttons{position:absolute;display:inline-block;right:6px;margin-top:-1px}.theme-ntos .Section__content{padding:8px 6px}.theme-ntos .Section--level--1 .Section__titleText{font-size:14px}.theme-ntos .Section--level--2 .Section__titleText{font-size:13px}.theme-ntos .Section--level--3 .Section__titleText{font-size:12px}.theme-ntos .Section--level--2,.theme-ntos .Section--level--3{background-color:transparent;box-shadow:none;margin-left:-6px;margin-right:-6px}.theme-ntos .TitleBar{background-color:#2a3b4e;border-bottom:1px solid #161616;box-shadow:0 2px 2px rgba(0,0,0,.1);user-select:none;-ms-user-select:none}.theme-ntos .TitleBar__clickable{color:hsla(0,0%,100%,.5);background-color:#2a3b4e;transition:color .25s,background-color .25s}.theme-ntos .TitleBar__clickable:hover{color:#fff;background-color:#c00;transition:color 0ms,background-color 0ms}.theme-ntos .TitleBar__title{position:absolute;top:0;left:46px;color:hsla(0,0%,100%,.75);font-size:14px;line-height:31px;white-space:nowrap}.theme-ntos .TitleBar__dragZone{position:absolute;top:0;left:0;right:0;height:32px}.theme-ntos .TitleBar__statusIcon{position:absolute;top:0;left:12px;transition:color .5s;font-size:20px;line-height:32px!important}.theme-ntos .TitleBar__minimize{position:absolute;top:6px;right:46px}.theme-ntos .TitleBar__close{position:absolute;top:-1px;right:0;width:45px;height:32px;font-size:20px;line-height:31px;text-align:center}.theme-hackerman .Button{position:relative;display:inline-block;line-height:20px;padding:0 6px;margin-right:2px;white-space:nowrap;outline:0;border-radius:0;margin-bottom:2px;user-select:none;-ms-user-select:none}.theme-hackerman .Button:last-child{margin-right:0}.theme-hackerman .Button .fa,.theme-hackerman .Button .far,.theme-hackerman .Button .fas{margin-left:-3px;margin-right:-3px;min-width:16px;text-align:center}.theme-hackerman .Button--hasContent .fa,.theme-hackerman .Button--hasContent .far,.theme-hackerman .Button--hasContent .fas{margin-right:3px}.theme-hackerman .Button--ellipsis{overflow:hidden;text-overflow:ellipsis}.theme-hackerman .Button--fluid{display:block;margin-left:0;margin-right:0}.theme-hackerman .Button--color--default{transition:color 50ms,background-color 50ms;background-color:#0f0;color:#000}.theme-hackerman .Button--color--default:hover{transition:color 0ms,background-color 0ms}.theme-hackerman .Button--color--default:focus{transition:color .1s,background-color .1s}.theme-hackerman .Button--color--default:focus,.theme-hackerman .Button--color--default:hover{background-color:#26ff26;color:#000}.theme-hackerman .Button--color--caution{transition:color 50ms,background-color 50ms;background-color:#d9b804;color:#000}.theme-hackerman .Button--color--caution:hover{transition:color 0ms,background-color 0ms}.theme-hackerman .Button--color--caution:focus{transition:color .1s,background-color .1s}.theme-hackerman .Button--color--caution:focus,.theme-hackerman .Button--color--caution:hover{background-color:#f3d00e;color:#000}.theme-hackerman .Button--color--danger{transition:color 50ms,background-color 50ms;background-color:#bd2020;color:#fff}.theme-hackerman .Button--color--danger:hover{transition:color 0ms,background-color 0ms}.theme-hackerman .Button--color--danger:focus{transition:color .1s,background-color .1s}.theme-hackerman .Button--color--danger:focus,.theme-hackerman .Button--color--danger:hover{background-color:#d52b2b;color:#fff}.theme-hackerman .Button--color--transparent{transition:color 50ms,background-color 50ms;background-color:#121b12;color:#fff;background-color:rgba(18,27,18,0);color:hsla(0,0%,100%,.5)}.theme-hackerman .Button--color--transparent:hover{transition:color 0ms,background-color 0ms}.theme-hackerman .Button--color--transparent:focus{transition:color .1s,background-color .1s}.theme-hackerman .Button--color--transparent:focus,.theme-hackerman .Button--color--transparent:hover{background-color:#1d271d;color:#fff}.theme-hackerman .Button--disabled{background-color:#4a6a4a!important}.theme-hackerman .Button--selected{transition:color 50ms,background-color 50ms;background-color:#0f0;color:#000}.theme-hackerman .Button--selected:hover{transition:color 0ms,background-color 0ms}.theme-hackerman .Button--selected:focus{transition:color .1s,background-color .1s}.theme-hackerman .Button--selected:focus,.theme-hackerman .Button--selected:hover{background-color:#26ff26;color:#000}.theme-hackerman .Input{position:relative;display:inline-block;width:120px;border:1px solid #0f0;border:1px solid rgba(0,255,0,.75);border-radius:2px;color:#fff;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;overflow:visible}.theme-hackerman .Input--fluid{display:block;width:auto}.theme-hackerman .Input__baseline{display:inline-block;color:transparent}.theme-hackerman .Input__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:transparent;color:#fff;color:inherit}.theme-hackerman .Input__input:-ms-input-placeholder{font-style:italic;color:#777;color:hsla(0,0%,100%,.45)}.theme-hackerman .Layout{position:fixed;top:0;bottom:0;left:0;right:0;color:#fff;background-color:#121b12;background-image:linear-gradient(180deg,#121b12 0,#121b12)}.theme-hackerman .Layout__titleBar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px}.theme-hackerman .Layout__content{position:fixed;top:32px;bottom:0;left:0;right:0;overflow-x:hidden;overflow-y:hidden;margin-bottom:-6px;scrollbar-base-color:#0e140e;scrollbar-face-color:#253725;scrollbar-3dlight-color:#121b12;scrollbar-highlight-color:#121b12;scrollbar-track-color:#0e140e;scrollbar-arrow-color:#74a274;scrollbar-shadow-color:#253725}.theme-hackerman .Layout__content--scrollable{overflow-y:scroll;margin-bottom:0}.theme-hackerman .Layout__dimmer{position:fixed;top:32px;bottom:0;left:0;right:0;background-color:rgba(40,50,40,.25);pointer-events:none}.theme-hackerman .Layout__toast{position:fixed;bottom:0;left:0;right:0;font-size:12px;height:40px;line-height:39px;padding:0 12px;background-color:#090e09;color:hsla(0,0%,100%,.8)}.theme-hackerman .Layout__resizeHandle__se{position:fixed;bottom:0;right:0;width:20px;height:20px;cursor:se-resize}.theme-hackerman .Layout__resizeHandle__s{position:fixed;bottom:0;left:0;right:0;height:6px;cursor:s-resize}.theme-hackerman .Layout__resizeHandle__e{position:fixed;top:0;bottom:0;right:0;width:3px;cursor:e-resize}.theme-hackerman .Section{position:relative;margin-bottom:6px;background-color:#1a1a1a;background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5);box-sizing:border-box}.theme-hackerman .Section:last-child{margin-bottom:0}.theme-hackerman .Section__title{position:relative;padding:6px;border-bottom:2px solid #0f0}.theme-hackerman .Section__titleText{font-size:14px;font-weight:700}.theme-hackerman .Section__buttons{position:absolute;display:inline-block;right:6px;margin-top:-1px}.theme-hackerman .Section__content{padding:8px 6px}.theme-hackerman .Section--level--1 .Section__titleText{font-size:14px}.theme-hackerman .Section--level--2 .Section__titleText{font-size:13px}.theme-hackerman .Section--level--3 .Section__titleText{font-size:12px}.theme-hackerman .Section--level--2,.theme-hackerman .Section--level--3{background-color:transparent;box-shadow:none;margin-left:-6px;margin-right:-6px}.theme-hackerman .TitleBar{background-color:#223d22;border-bottom:1px solid #161616;box-shadow:0 2px 2px rgba(0,0,0,.1);user-select:none;-ms-user-select:none}.theme-hackerman .TitleBar__clickable{color:hsla(0,0%,100%,.5);background-color:#223d22;transition:color .25s,background-color .25s}.theme-hackerman .TitleBar__clickable:hover{color:#fff;background-color:#c00;transition:color 0ms,background-color 0ms}.theme-hackerman .TitleBar__title{position:absolute;top:0;left:46px;color:hsla(0,0%,100%,.75);font-size:14px;line-height:31px;white-space:nowrap}.theme-hackerman .TitleBar__dragZone{position:absolute;top:0;left:0;right:0;height:32px}.theme-hackerman .TitleBar__statusIcon{position:absolute;top:0;left:12px;transition:color .5s;font-size:20px;line-height:32px!important}.theme-hackerman .TitleBar__minimize{position:absolute;top:6px;right:46px}.theme-hackerman .TitleBar__close{position:absolute;top:-1px;right:0;width:45px;height:32px;font-size:20px;line-height:31px;text-align:center}.theme-hackerman .Layout__content{background-image:none}.theme-hackerman .Button{font-family:monospace;border:2px outset #0a0;outline:1px solid #007a00}.theme-hackerman .candystripe:nth-child(odd){background-color:rgba(0,100,0,.5)}.theme-retro .Button{position:relative;display:inline-block;line-height:20px;padding:0 6px;margin-right:2px;white-space:nowrap;outline:0;border-radius:0;margin-bottom:2px;user-select:none;-ms-user-select:none}.theme-retro .Button:last-child{margin-right:0}.theme-retro .Button .fa,.theme-retro .Button .far,.theme-retro .Button .fas{margin-left:-3px;margin-right:-3px;min-width:16px;text-align:center}.theme-retro .Button--hasContent .fa,.theme-retro .Button--hasContent .far,.theme-retro .Button--hasContent .fas{margin-right:3px}.theme-retro .Button--ellipsis{overflow:hidden;text-overflow:ellipsis}.theme-retro .Button--fluid{display:block;margin-left:0;margin-right:0}.theme-retro .Button--color--default{transition:color 50ms,background-color 50ms;background-color:#e8e4c9;color:#000}.theme-retro .Button--color--default:hover{transition:color 0ms,background-color 0ms}.theme-retro .Button--color--default:focus{transition:color .1s,background-color .1s}.theme-retro .Button--color--default:focus,.theme-retro .Button--color--default:hover{background-color:#f7f6ee;color:#000}.theme-retro .Button--color--caution{transition:color 50ms,background-color 50ms;background-color:#be6209;color:#fff}.theme-retro .Button--color--caution:hover{transition:color 0ms,background-color 0ms}.theme-retro .Button--color--caution:focus{transition:color .1s,background-color .1s}.theme-retro .Button--color--caution:focus,.theme-retro .Button--color--caution:hover{background-color:#d67313;color:#fff}.theme-retro .Button--color--danger{transition:color 50ms,background-color 50ms;background-color:#9a9d00;color:#fff}.theme-retro .Button--color--danger:hover{transition:color 0ms,background-color 0ms}.theme-retro .Button--color--danger:focus{transition:color .1s,background-color .1s}.theme-retro .Button--color--danger:focus,.theme-retro .Button--color--danger:hover{background-color:#afb30a;color:#fff}.theme-retro .Button--color--transparent{transition:color 50ms,background-color 50ms;background-color:#e8e4c9;color:#000;background-color:rgba(232,228,201,0);color:hsla(0,0%,100%,.5)}.theme-retro .Button--color--transparent:hover{transition:color 0ms,background-color 0ms}.theme-retro .Button--color--transparent:focus{transition:color .1s,background-color .1s}.theme-retro .Button--color--transparent:focus,.theme-retro .Button--color--transparent:hover{background-color:#f7f6ee;color:#000}.theme-retro .Button--disabled{background-color:#363636!important}.theme-retro .Button--selected{transition:color 50ms,background-color 50ms;background-color:#9d0808;color:#fff}.theme-retro .Button--selected:hover{transition:color 0ms,background-color 0ms}.theme-retro .Button--selected:focus{transition:color .1s,background-color .1s}.theme-retro .Button--selected:focus,.theme-retro .Button--selected:hover{background-color:#b31212;color:#fff}.theme-retro .Layout{position:fixed;top:0;bottom:0;left:0;right:0;color:#fff;background-color:#e8e4c9;background-image:linear-gradient(180deg,#e8e4c9 0,#e8e4c9)}.theme-retro .Layout__titleBar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px}.theme-retro .Layout__content{position:fixed;top:32px;bottom:0;left:0;right:0;overflow-x:hidden;overflow-y:hidden;margin-bottom:-6px;scrollbar-base-color:#c8be7d;scrollbar-face-color:#eae7ce;scrollbar-3dlight-color:#e8e4c9;scrollbar-highlight-color:#e8e4c9;scrollbar-track-color:#c8be7d;scrollbar-arrow-color:#f4f2e4;scrollbar-shadow-color:#eae7ce}.theme-retro .Layout__content--scrollable{overflow-y:scroll;margin-bottom:0}.theme-retro .Layout__dimmer{position:fixed;top:32px;bottom:0;left:0;right:0;background-color:rgba(251,250,246,.25);pointer-events:none}.theme-retro .Layout__toast{position:fixed;bottom:0;left:0;right:0;font-size:12px;height:40px;line-height:39px;padding:0 12px;background-color:#988d41;color:hsla(0,0%,100%,.8)}.theme-retro .Layout__resizeHandle__se{position:fixed;bottom:0;right:0;width:20px;height:20px;cursor:se-resize}.theme-retro .Layout__resizeHandle__s{position:fixed;bottom:0;left:0;right:0;height:6px;cursor:s-resize}.theme-retro .Layout__resizeHandle__e{position:fixed;top:0;bottom:0;right:0;width:3px;cursor:e-resize}.theme-retro .ProgressBar{display:inline-block;position:relative;width:100%;padding:0 6px;border-radius:0;background-color:rgba(0,0,0,.5);transition:border-color .5s}.theme-retro .ProgressBar__fill{position:absolute;top:0;left:0;bottom:0;transition:background-color .5s,width .5s}.theme-retro .ProgressBar__content{position:relative;line-height:17px;width:100%;text-align:right}.theme-retro .ProgressBar--color--default{border:1px solid #000}.theme-retro .ProgressBar--color--default .ProgressBar__fill{background-color:#000}.theme-retro .Section{position:relative;margin-bottom:6px;background-color:#1a1a1a;background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5);box-sizing:border-box}.theme-retro .Section:last-child{margin-bottom:0}.theme-retro .Section__title{position:relative;padding:6px;border-bottom:2px solid #000}.theme-retro .Section__titleText{font-size:14px;font-weight:700}.theme-retro .Section__buttons{position:absolute;display:inline-block;right:6px;margin-top:-1px}.theme-retro .Section__content{padding:8px 6px}.theme-retro .Section--level--1 .Section__titleText{font-size:14px}.theme-retro .Section--level--2 .Section__titleText{font-size:13px}.theme-retro .Section--level--3 .Section__titleText{font-size:12px}.theme-retro .Section--level--2,.theme-retro .Section--level--3{background-color:transparent;box-shadow:none;margin-left:-6px;margin-right:-6px}.theme-retro .TitleBar{background-color:#585337;border-bottom:1px solid #161616;box-shadow:0 2px 2px rgba(0,0,0,.1);user-select:none;-ms-user-select:none}.theme-retro .TitleBar__clickable{color:hsla(0,0%,100%,.5);background-color:#585337;transition:color .25s,background-color .25s}.theme-retro .TitleBar__clickable:hover{color:#fff;background-color:#c00;transition:color 0ms,background-color 0ms}.theme-retro .TitleBar__title{position:absolute;top:0;left:46px;color:hsla(0,0%,100%,.75);font-size:14px;line-height:31px;white-space:nowrap}.theme-retro .TitleBar__dragZone{position:absolute;top:0;left:0;right:0;height:32px}.theme-retro .TitleBar__statusIcon{position:absolute;top:0;left:12px;transition:color .5s;font-size:20px;line-height:32px!important}.theme-retro .TitleBar__minimize{position:absolute;top:6px;right:46px}.theme-retro .TitleBar__close{position:absolute;top:-1px;right:0;width:45px;height:32px;font-size:20px;line-height:31px;text-align:center}.theme-retro .Button{font-family:monospace;color:#161613;border:8px outset #e8e4c9;outline:3px solid #161613}.theme-retro .Layout__content{background-image:none}.theme-syndicate .Button{position:relative;display:inline-block;line-height:20px;padding:0 6px;margin-right:2px;white-space:nowrap;outline:0;border-radius:0;margin-bottom:2px;user-select:none;-ms-user-select:none}.theme-syndicate .Button:last-child{margin-right:0}.theme-syndicate .Button .fa,.theme-syndicate .Button .far,.theme-syndicate .Button .fas{margin-left:-3px;margin-right:-3px;min-width:16px;text-align:center}.theme-syndicate .Button--hasContent .fa,.theme-syndicate .Button--hasContent .far,.theme-syndicate .Button--hasContent .fas{margin-right:3px}.theme-syndicate .Button--ellipsis{overflow:hidden;text-overflow:ellipsis}.theme-syndicate .Button--fluid{display:block;margin-left:0;margin-right:0}.theme-syndicate .Button--color--default{transition:color 50ms,background-color 50ms;background-color:#397439;color:#fff}.theme-syndicate .Button--color--default:hover{transition:color 0ms,background-color 0ms}.theme-syndicate .Button--color--default:focus{transition:color .1s,background-color .1s}.theme-syndicate .Button--color--default:focus,.theme-syndicate .Button--color--default:hover{background-color:#478647;color:#fff}.theme-syndicate .Button--color--caution{transition:color 50ms,background-color 50ms;background-color:#be6209;color:#fff}.theme-syndicate .Button--color--caution:hover{transition:color 0ms,background-color 0ms}.theme-syndicate .Button--color--caution:focus{transition:color .1s,background-color .1s}.theme-syndicate .Button--color--caution:focus,.theme-syndicate .Button--color--caution:hover{background-color:#d67313;color:#fff}.theme-syndicate .Button--color--danger{transition:color 50ms,background-color 50ms;background-color:#9a9d00;color:#fff}.theme-syndicate .Button--color--danger:hover{transition:color 0ms,background-color 0ms}.theme-syndicate .Button--color--danger:focus{transition:color .1s,background-color .1s}.theme-syndicate .Button--color--danger:focus,.theme-syndicate .Button--color--danger:hover{background-color:#afb30a;color:#fff}.theme-syndicate .Button--color--transparent{transition:color 50ms,background-color 50ms;background-color:#550202;color:#fff;background-color:rgba(85,2,2,0);color:hsla(0,0%,100%,.5)}.theme-syndicate .Button--color--transparent:hover{transition:color 0ms,background-color 0ms}.theme-syndicate .Button--color--transparent:focus{transition:color .1s,background-color .1s}.theme-syndicate .Button--color--transparent:focus,.theme-syndicate .Button--color--transparent:hover{background-color:#650c0c;color:#fff}.theme-syndicate .Button--disabled{background-color:#363636!important}.theme-syndicate .Button--selected{transition:color 50ms,background-color 50ms;background-color:#9d0808;color:#fff}.theme-syndicate .Button--selected:hover{transition:color 0ms,background-color 0ms}.theme-syndicate .Button--selected:focus{transition:color .1s,background-color .1s}.theme-syndicate .Button--selected:focus,.theme-syndicate .Button--selected:hover{background-color:#b31212;color:#fff}.theme-syndicate .Layout{position:fixed;top:0;bottom:0;left:0;right:0;color:#fff;background-color:#550202;background-image:linear-gradient(180deg,#730303 0,#370101)}.theme-syndicate .Layout__titleBar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px}.theme-syndicate .Layout__content{position:fixed;top:32px;bottom:0;left:0;right:0;overflow-x:hidden;overflow-y:hidden;margin-bottom:-6px;scrollbar-base-color:#400202;scrollbar-face-color:#7e0303;scrollbar-3dlight-color:#550202;scrollbar-highlight-color:#550202;scrollbar-track-color:#400202;scrollbar-arrow-color:#fa3030;scrollbar-shadow-color:#7e0303}.theme-syndicate .Layout__content--scrollable{overflow-y:scroll;margin-bottom:0}.theme-syndicate .Layout__dimmer{position:fixed;top:32px;bottom:0;left:0;right:0;background-color:rgba(117,22,22,.25);pointer-events:none}.theme-syndicate .Layout__toast{position:fixed;bottom:0;left:0;right:0;font-size:12px;height:40px;line-height:39px;padding:0 12px;background-color:#2b0101;color:hsla(0,0%,100%,.8)}.theme-syndicate .Layout__resizeHandle__se{position:fixed;bottom:0;right:0;width:20px;height:20px;cursor:se-resize}.theme-syndicate .Layout__resizeHandle__s{position:fixed;bottom:0;left:0;right:0;height:6px;cursor:s-resize}.theme-syndicate .Layout__resizeHandle__e{position:fixed;top:0;bottom:0;right:0;width:3px;cursor:e-resize}.theme-syndicate .NoticeBox{padding:4px 6px;margin-bottom:6px;box-shadow:none;font-weight:700;font-style:italic;color:#fff;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}.theme-syndicate .Input{position:relative;display:inline-block;width:120px;border:1px solid #87ce87;border:1px solid rgba(135,206,135,.75);border-radius:2px;color:#fff;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;overflow:visible}.theme-syndicate .Input--fluid{display:block;width:auto}.theme-syndicate .Input__baseline{display:inline-block;color:transparent}.theme-syndicate .Input__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:transparent;color:#fff;color:inherit}.theme-syndicate .Input__input:-ms-input-placeholder{font-style:italic;color:#777;color:hsla(0,0%,100%,.45)}.theme-syndicate .NumberInput{position:relative;display:inline-block;border:1px solid #87ce87;border:1px solid rgba(135,206,135,.75);border-radius:2px;color:#87ce87;background-color:#000;background-color:rgba(0,0,0,.75);padding:0 4px;margin-right:2px;line-height:17px;text-align:right;overflow:visible;cursor:n-resize}.theme-syndicate .NumberInput--fluid{display:block}.theme-syndicate .NumberInput__content{margin-left:6px}.theme-syndicate .NumberInput__barContainer{position:absolute;top:2px;bottom:2px;left:2px}.theme-syndicate .NumberInput__bar{position:absolute;bottom:0;left:0;width:3px;box-sizing:border-box;border-bottom:1px solid #87ce87;background-color:#87ce87}.theme-syndicate .NumberInput__input{display:block;position:absolute;top:0;bottom:0;left:0;right:0;border:0;outline:0;width:100%;font-size:12px;line-height:17px;height:17px;margin:0;padding:0 6px;font-family:Verdana,sans-serif;background-color:#000;color:#fff;text-align:right}.theme-syndicate .ProgressBar{display:inline-block;position:relative;width:100%;padding:0 6px;border-radius:0;background-color:rgba(0,0,0,.5);transition:border-color .5s}.theme-syndicate .ProgressBar__fill{position:absolute;top:0;left:0;bottom:0;transition:background-color .5s,width .5s}.theme-syndicate .ProgressBar__content{position:relative;line-height:17px;width:100%;text-align:right}.theme-syndicate .ProgressBar--color--default{border:1px solid #306330}.theme-syndicate .ProgressBar--color--default .ProgressBar__fill{background-color:#306330}.theme-syndicate .Section{position:relative;margin-bottom:6px;background-color:#1a1a1a;background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5);box-sizing:border-box}.theme-syndicate .Section:last-child{margin-bottom:0}.theme-syndicate .Section__title{position:relative;padding:6px;border-bottom:2px solid #397439}.theme-syndicate .Section__titleText{font-size:14px;font-weight:700}.theme-syndicate .Section__buttons{position:absolute;display:inline-block;right:6px;margin-top:-1px}.theme-syndicate .Section__content{padding:8px 6px}.theme-syndicate .Section--level--1 .Section__titleText{font-size:14px}.theme-syndicate .Section--level--2 .Section__titleText{font-size:13px}.theme-syndicate .Section--level--3 .Section__titleText{font-size:12px}.theme-syndicate .Section--level--2,.theme-syndicate .Section--level--3{background-color:transparent;box-shadow:none;margin-left:-6px;margin-right:-6px}.theme-syndicate .TitleBar{background-color:#910101;border-bottom:1px solid #161616;box-shadow:0 2px 2px rgba(0,0,0,.1);user-select:none;-ms-user-select:none}.theme-syndicate .TitleBar__clickable{color:hsla(0,0%,100%,.5);background-color:#910101;transition:color .25s,background-color .25s}.theme-syndicate .TitleBar__clickable:hover{color:#fff;background-color:#c00;transition:color 0ms,background-color 0ms}.theme-syndicate .TitleBar__title{position:absolute;top:0;left:46px;color:hsla(0,0%,100%,.75);font-size:14px;line-height:31px;white-space:nowrap}.theme-syndicate .TitleBar__dragZone{position:absolute;top:0;left:0;right:0;height:32px}.theme-syndicate .TitleBar__statusIcon{position:absolute;top:0;left:12px;transition:color .5s;font-size:20px;line-height:32px!important}.theme-syndicate .TitleBar__minimize{position:absolute;top:6px;right:46px}.theme-syndicate .TitleBar__close{position:absolute;top:-1px;right:0;width:45px;height:32px;font-size:20px;line-height:31px;text-align:center}.theme-syndicate .Tooltip{position:absolute;top:0;left:0;right:0;bottom:0;font-style:normal;font-weight:400}.theme-syndicate .Tooltip:after{position:absolute;display:block;white-space:nowrap;z-index:2;padding:6px 10px;transform:translateX(-50%);pointer-events:none;visibility:hidden;opacity:0;text-align:left;content:attr(data-tooltip);transition:all .15s;background-color:#4a0202;box-shadow:1px 1px 15px -1px rgba(0,0,0,.5);border-radius:2px}.theme-syndicate .Tooltip:hover:after{transition:all 70ms;pointer-events:none;visibility:visible;opacity:1}.theme-syndicate .Tooltip--long:after{width:250px;white-space:normal}.theme-syndicate .Tooltip--top:after{bottom:100%;left:50%;transform:translateX(-50%) translateY(8px)}.theme-syndicate .Tooltip--bottom:after,.theme-syndicate .Tooltip--top:hover:after{transform:translateX(-50%) translateY(-8px)}.theme-syndicate .Tooltip--bottom:after{top:100%;left:50%}.theme-syndicate .Tooltip--bottom:hover:after{transform:translateX(-50%) translateY(8px)}.theme-syndicate .Tooltip--bottom-left:after{top:100%;right:50%;transform:translateX(12px) translateY(-8px)}.theme-syndicate .Tooltip--bottom-left:hover:after{transform:translateX(12px) translateY(8px)}.theme-syndicate .Tooltip--bottom-right:after{top:100%;left:50%;transform:translateX(-12px) translateY(-8px)}.theme-syndicate .Tooltip--bottom-right:hover:after{transform:translateX(-12px) translateY(8px)}.theme-syndicate .Tooltip--left:after{top:50%;right:100%;transform:translateX(8px) translateY(-50%)}.theme-syndicate .Tooltip--left:hover:after,.theme-syndicate .Tooltip--right:after{transform:translateX(-8px) translateY(-50%)}.theme-syndicate .Tooltip--right:after{top:50%;left:100%}.theme-syndicate .Tooltip--right:hover:after{transform:translateX(8px) translateY(-50%)}.theme-syndicate .Layout__content{background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDIwMCAyODkuNzQyIiBvcGFjaXR5PSIuMzMiPjxwYXRoIGQ9Ik05My41MzggMGMtMTguMTEzIDAtMzQuMjIgMy4xMTItNDguMzI0IDkuMzM0LTEzLjk2NSA2LjIyMi0yNC42MTIgMTUuMDcyLTMxLjk0IDI2LjU0N0M2LjA4NCA0Ny4yMiAyLjk3MiA2MC42MzEgMi45NzIgNzYuMTE2YzAgMTAuNjQ3IDIuNzI1IDIwLjQ2NSA4LjE3NSAyOS40NTMgNS42MTYgOC45ODcgMTQuMDM5IDE3LjM1MiAyNS4yNyAyNS4wOTQgMTEuMjMgNy42MDYgMjYuNTA3IDE1LjQxOSA0NS44MyAyMy40MzggMTkuOTg0IDguMjk2IDM0Ljg0OSAxNS41NTUgNDQuNTkzIDIxLjc3NiA5Ljc0NCA2LjIyMyAxNi43NjEgMTIuODU5IDIxLjA1NSAxOS45MSA0LjI5NSA3LjA1MiA2LjQ0MiAxNS43NjQgNi40NDIgMjYuMTM0IDAgMTYuMTc4LTUuMjAyIDI4LjQ4My0xNS42MDYgMzYuOTE3LTEwLjI0IDguNDM1LTI1LjAyMiAxMi42NTMtNDQuMzQ1IDEyLjY1My0xNC4wMzkgMC0yNS41MTYtMS42Ni0zNC40MzQtNC45NzgtOC45MTgtMy40NTctMTYuMTg2LTguNzExLTIxLjgtMTUuNzYzLTUuNjE2LTcuMDUyLTEwLjA3Ni0xNi42NjEtMTMuMzc5LTI4LjgyOUgwdjU2LjgyN2MzMy44NTcgNy4zMjggNjMuNzQ5IDEwLjk5NCA4OS42NzggMTAuOTk0IDE2LjAyIDAgMzAuNzItMS4zODMgNDQuMDk4LTQuMTQ4IDEzLjU0Mi0yLjkwNCAyNS4xMDQtNy40NjcgMzQuNjgzLTEzLjY5IDkuNzQ0LTYuMzU5IDE3LjM0LTE0LjUxOSAyMi43OS0yNC40NzQgNS40NS0xMC4wOTMgOC4xNzUtMjIuNCA4LjE3NS0zNi45MTcgMC0xMi45OTctMy4zMDItMjQuMzM1LTkuOTA4LTM0LjAxNC02LjQ0LTkuODE4LTE1LjUyNS0xOC41MjctMjcuMjUxLTI2LjEzMi0xMS41NjEtNy42MDQtMjcuOTExLTE1LjgzMS00OS4wNTEtMjQuNjgtMTcuNTA2LTcuMTktMzAuNzItMTMuNjktMzkuNjM4LTE5LjQ5N1M1NC45NjkgOTMuNzU2IDQ5LjQ3OSA4Ny4zMTZjLTUuNDI2LTYuMzY2LTkuNjU4LTE1LjA3LTkuNjU4LTI0Ljg4NyAwLTkuMjY0IDIuMDc1LTE3LjIxNCA2LjIyMy0yMy44NUM1Ny4xNDIgMjQuMTggODcuMzMxIDM2Ljc4MiA5MS4xMiA2Mi45MjVjNC44NCA2Ljc3NSA4Ljg1IDE2LjI0NyAxMi4wMyAyOC40MTVoMjAuNTMydi01NmMtNC40NzktNS45MjQtOS45NTUtMTAuNjMxLTE1LjkwOS0xNC4zNzMgMS42NC40NzkgMy4xOSAxLjAyMyA0LjYzOSAxLjY0IDYuNDk4IDIuNjI2IDEyLjE2OCA3LjMyNyAxNy4wMDcgMTQuMTAzIDQuODQgNi43NzUgOC44NSAxNi4yNDYgMTIuMDMgMjguNDE0IDAgMCA4LjQ4LS4xMjkgOC40OS0uMDAyLjQxNyA2LjQxNS0xLjc1NCA5LjQ1My00LjEyNCAxMi41NjEtMi40MTcgMy4xNy01LjE0NSA2Ljc5LTQuMDAzIDEzLjAwMyAxLjUwOCA4LjIwMyAxMC4xODQgMTAuNTk3IDE0LjYyMiA5LjMxMi0zLjMxOC0uNS01LjMxOC0xLjc1LTUuMzE4LTEuNzVzMS44NzYuOTk5IDUuNjUtMS4zNmMtMy4yNzYuOTU2LTEwLjcwNC0uNzk3LTExLjgtNi43NjMtLjk1OC01LjIwOC45NDYtNy4yOTUgMy40LTEwLjUxNCAyLjQ1NS0zLjIyIDUuMjg1LTYuOTU5IDQuNjg1LTE0LjQ4OWwuMDAzLjAwMmg4LjkyN3YtNTZjLTE1LjA3Mi0zLjg3MS0yNy42NTMtNi4zNi0zNy43NDctNy40NjVDMTE0LjI3OS41NTIgMTA0LjA0NiAwIDkzLjUzNyAwem03MC4zMjEgMTcuMzA5bC4yMzggNDAuMzA1YzEuMzE4IDEuMjI2IDIuNDQgMi4yNzggMy4zNDEgMy4xMDYgNC44NCA2Ljc3NSA4Ljg1IDE2LjI0NiAxMi4wMyAyOC40MTRIMjAwdi01NmMtNi42NzctNC41OTQtMTkuODM2LTEwLjQ3My0zNi4xNC0xNS44MjV6bS0yOC4xMiA1LjYwNWw4LjU2NSAxNy43MTdjLTExLjk3LTYuNDY3LTEzLjg0Ny05LjcxNy04LjU2NS0xNy43MTd6bTIyLjc5NyAwYzIuNzcxIDggMS43ODcgMTEuMjUtNC40OTQgMTcuNzE3bDQuNDk0LTE3LjcxN3ptMTUuMjIyIDI0LjAwOWw4LjU2NSAxNy43MTZjLTExLjk3LTYuNDY2LTEzLjg0Ny05LjcxNy04LjU2NS0xNy43MTZ6bTIyLjc5NyAwYzIuNzcxIDggMS43ODcgMTEuMjUtNC40OTQgMTcuNzE2bDQuNDk0LTE3LjcxNnpNOTcuNDQgNDkuMTNsOC41NjUgMTcuNzE2Yy0xMS45Ny02LjQ2Ny0xMy44NDctOS43MTctOC41NjUtMTcuNzE2em0yMi43OTUgMGMyLjc3MiA3Ljk5OSAxLjc4OCAxMS4yNS00LjQ5MyAxNy43MTZsNC40OTMtMTcuNzE2eiIvPjwvc3ZnPg==)} \ No newline at end of file diff --git a/tgui-next/packages/tgui/public/tgui.bundle.js b/tgui-next/packages/tgui/public/tgui.bundle.js deleted file mode 100644 index f7aa949c08..0000000000 --- a/tgui-next/packages/tgui/public/tgui.bundle.js +++ /dev/null @@ -1,3 +0,0 @@ -!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=165)}([function(e,t,n){"use strict";t.__esModule=!0;var o=n(387);Object.keys(o).forEach((function(e){"default"!==e&&"__esModule"!==e&&(t[e]=o[e])}))},function(e,t,n){"use strict";var o=n(5),r=n(20).f,a=n(26),i=n(22),c=n(89),l=n(122),u=n(61);e.exports=function(e,t){var n,d,s,p,m,f=e.target,h=e.global,C=e.stat;if(n=h?o:C?o[f]||c(f,{}):(o[f]||{}).prototype)for(d in t){if(p=t[d],s=e.noTargetGet?(m=r(n,d))&&m.value:n[d],!u(h?d:f+(C?".":"#")+d,e.forced)&&s!==undefined){if(typeof p==typeof s)continue;l(p,s)}(e.sham||s&&s.sham)&&a(p,"sham",!0),i(n,d,p,e)}}},function(e,t,n){"use strict";t.__esModule=!0,t.Chart=t.Tooltip=t.Toast=t.TitleBar=t.Tabs=t.Table=t.Section=t.ProgressBar=t.NumberInput=t.NoticeBox=t.LabeledList=t.Input=t.Icon=t.Grid=t.Flex=t.Dropdown=t.Dimmer=t.Collapsible=t.ColorBox=t.Button=t.Box=t.BlockQuote=t.AnimatedNumber=void 0;var o=n(158);t.AnimatedNumber=o.AnimatedNumber;var r=n(392);t.BlockQuote=r.BlockQuote;var a=n(19);t.Box=a.Box;var i=n(114);t.Button=i.Button;var c=n(394);t.ColorBox=c.ColorBox;var l=n(395);t.Collapsible=l.Collapsible;var u=n(396);t.Dimmer=u.Dimmer;var d=n(397);t.Dropdown=d.Dropdown;var s=n(398);t.Flex=s.Flex;var p=n(161);t.Grid=p.Grid;var m=n(87);t.Icon=m.Icon;var f=n(160);t.Input=f.Input;var h=n(163);t.LabeledList=h.LabeledList;var C=n(399);t.NoticeBox=C.NoticeBox;var g=n(400);t.NumberInput=g.NumberInput;var b=n(401);t.ProgressBar=b.ProgressBar;var N=n(402);t.Section=N.Section;var v=n(162);t.Table=v.Table;var V=n(403);t.Tabs=V.Tabs;var y=n(404);t.TitleBar=y.TitleBar;var _=n(117);t.Toast=_.Toast;var k=n(159);t.Tooltip=k.Tooltip;var x=n(405);t.Chart=x.Chart},function(e,t,n){"use strict";t.__esModule=!0,t.useBackend=t.backendReducer=t.backendUpdate=void 0;var o=n(32),r=n(16);t.backendUpdate=function(e){return{type:"backendUpdate",payload:e}};t.backendReducer=function(e,t){var n=t.type,r=t.payload;if("backendUpdate"===n){var a=Object.assign({},e.config,{},r.config),i=Object.assign({},e.data,{},r.static_data,{},r.data),c=a.status!==o.UI_DISABLED,l=a.status===o.UI_INTERACTIVE;return Object.assign({},e,{config:a,data:i,visible:c,interactive:l})}return e};t.useBackend=function(e){var t=e.state,n=(e.dispatch,t.config.ref);return Object.assign({},t,{act:function(e,t){return void 0===t&&(t={}),(0,r.act)(n,e,t)}})}},function(e,t,n){"use strict";e.exports=function(e){try{return!!e()}catch(t){return!0}}},function(e,t,n){"use strict";(function(t){var n=function(e){return e&&e.Math==Math&&e};e.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof t&&t)||Function("return this")()}).call(this,n(118))},function(e,t,n){"use strict";e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){"use strict";var o,r=n(9),a=n(5),i=n(6),c=n(15),l=n(74),u=n(26),d=n(22),s=n(13).f,p=n(37),m=n(53),f=n(12),h=n(58),C=a.DataView,g=C&&C.prototype,b=a.Int8Array,N=b&&b.prototype,v=a.Uint8ClampedArray,V=v&&v.prototype,y=b&&p(b),_=N&&p(N),k=Object.prototype,x=k.isPrototypeOf,L=f("toStringTag"),w=h("TYPED_ARRAY_TAG"),B=!(!a.ArrayBuffer||!C),S=B&&!!m&&"Opera"!==l(a.opera),I=!1,T={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},A=function(e){var t=l(e);return"DataView"===t||c(T,t)},E=function(e){return i(e)&&c(T,l(e))};for(o in T)a[o]||(S=!1);if((!S||"function"!=typeof y||y===Function.prototype)&&(y=function(){throw TypeError("Incorrect invocation")},S))for(o in T)a[o]&&m(a[o],y);if((!S||!_||_===k)&&(_=y.prototype,S))for(o in T)a[o]&&m(a[o].prototype,_);if(S&&p(V)!==_&&m(V,_),r&&!c(_,L))for(o in I=!0,s(_,L,{get:function(){return i(this)?this[w]:undefined}}),T)a[o]&&u(a[o],w,o);B&&m&&p(g)!==k&&m(g,k),e.exports={NATIVE_ARRAY_BUFFER:B,NATIVE_ARRAY_BUFFER_VIEWS:S,TYPED_ARRAY_TAG:I&&w,aTypedArray:function(e){if(E(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(m){if(x.call(y,e))return e}else for(var t in T)if(c(T,o)){var n=a[t];if(n&&(e===n||x.call(n,e)))return e}throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(e,t,n){if(r){if(n)for(var o in T){var i=a[o];i&&c(i.prototype,e)&&delete i.prototype[e]}_[e]&&!n||d(_,e,n?t:S&&N[e]||t)}},exportTypedArrayStaticMethod:function(e,t,n){var o,i;if(r){if(m){if(n)for(o in T)(i=a[o])&&c(i,e)&&delete i[e];if(y[e]&&!n)return;try{return d(y,e,n?t:S&&b[e]||t)}catch(l){}}for(o in T)!(i=a[o])||i[e]&&!n||d(i,e,t)}},isView:A,isTypedArray:E,TypedArray:y,TypedArrayPrototype:_}},function(e,t,n){"use strict";var o=n(6);e.exports=function(e){if(!o(e))throw TypeError(String(e)+" is not an object");return e}},function(e,t,n){"use strict";var o=n(4);e.exports=!o((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(e,t,n){"use strict";var o=n(30),r=Math.min;e.exports=function(e){return e>0?r(o(e),9007199254740991):0}},function(e,t,n){"use strict";t.__esModule=!0,t.isFalsy=t.pureComponentHooks=t.shallowDiffers=t.normalizeChildren=t.classes=void 0;t.classes=function(e){for(var t="",n=0;n_;_++)if((p||_ in v)&&(b=V(g=v[_],_,N),e))if(t)x[_]=b;else if(b)switch(e){case 3:return!0;case 5:return g;case 6:return _;case 2:l.call(x,g)}else if(d)return!1;return s?-1:u||d?d:x}};e.exports={forEach:u(0),map:u(1),filter:u(2),some:u(3),every:u(4),find:u(5),findIndex:u(6)}},function(e,t,n){"use strict";t.__esModule=!0,t.Box=t.computeBoxProps=t.unit=void 0;var o=n(0),r=n(11),a=n(393),i=n(32);function c(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var l=function(e){return"string"==typeof e?e:"number"==typeof e?6*e+"px":void 0};t.unit=l;var u=function(e){return"string"==typeof e&&i.CSS_COLORS.includes(e)},d=function(e){return function(t,n){(0,r.isFalsy)(n)||(t[e]=n)}},s=function(e){return function(t,n){(0,r.isFalsy)(n)||(t[e]=l(n))}},p=function(e,t){return function(n,o){(0,r.isFalsy)(o)||(n[e]=t)}},m=function(e,t){return function(n,o){if(!(0,r.isFalsy)(o))for(var a=0;a0&&(t.style=l),t};t.computeBoxProps=C;var g=function(e){var t=e.as,n=void 0===t?"div":t,i=e.className,l=e.content,d=e.children,s=c(e,["as","className","content","children"]),p=e.textColor||e.color,m=e.backgroundColor;if("function"==typeof d)return d(C(e));var f=C(s);return(0,o.createVNode)(a.VNodeFlags.HtmlElement,n,(0,r.classes)([i,u(p)&&"color-"+p,u(m)&&"color-bg-"+m]),l||d,a.ChildFlags.UnknownChildren,f)};t.Box=g,g.defaultHooks=r.pureComponentHooks;var b=function(e){var t=e.children,n=c(e,["children"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,g,Object.assign({position:"relative"},n,{children:(0,o.createComponentVNode)(2,g,{fillPositionedParent:!0,children:t})})))};b.defaultHooks=r.pureComponentHooks,g.Forced=b},function(e,t,n){"use strict";var o=n(9),r=n(71),a=n(46),i=n(25),c=n(34),l=n(15),u=n(119),d=Object.getOwnPropertyDescriptor;t.f=o?d:function(e,t){if(e=i(e),t=c(t,!0),u)try{return d(e,t)}catch(n){}if(l(e,t))return a(!r.f.call(e,t),e[t])}},function(e,t,n){"use strict";e.exports=function(e){if(e==undefined)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){"use strict";var o=n(5),r=n(26),a=n(15),i=n(89),c=n(90),l=n(35),u=l.get,d=l.enforce,s=String(String).split("String");(e.exports=function(e,t,n,c){var l=!!c&&!!c.unsafe,u=!!c&&!!c.enumerable,p=!!c&&!!c.noTargetGet;"function"==typeof n&&("string"!=typeof t||a(n,"name")||r(n,"name",t),d(n).source=s.join("string"==typeof t?t:"")),e!==o?(l?!p&&e[t]&&(u=!0):delete e[t],u?e[t]=n:r(e,t,n)):u?e[t]=n:i(t,n)})(Function.prototype,"toString",(function(){return"function"==typeof this&&u(this).source||c(this)}))},function(e,t,n){"use strict";t.__esModule=!0,t.buildQueryString=t.decodeHtmlEntities=t.toTitleCase=t.capitalize=t.testGlobPattern=t.multiline=void 0;t.multiline=function o(e){if(Array.isArray(e))return o(e.join(""));var t,n=e.split("\n"),r=n,a=Array.isArray(r),i=0;for(r=a?r:r[Symbol.iterator]();;){var c;if(a){if(i>=r.length)break;c=r[i++]}else{if((i=r.next()).done)break;c=i.value}for(var l=c,u=0;u",apos:"'"};return e.replace(/
    /gi,"\n").replace(/<\/?[a-z0-9-_]+[^>]*>/gi,"").replace(/&(nbsp|amp|quot|lt|gt|apos);/g,(function(e,n){return t[n]})).replace(/&#?([0-9]+);/gi,(function(e,t){var n=parseInt(t,10);return String.fromCharCode(n)})).replace(/&#x?([0-9a-f]+);/gi,(function(e,t){var n=parseInt(t,16);return String.fromCharCode(n)}))};t.buildQueryString=function(e){return Object.keys(e).map((function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])})).join("&")}},function(e,t,n){"use strict";t.__esModule=!0,t.zipWith=t.zip=t.reduce=t.sortBy=t.map=t.toArray=void 0;t.toArray=function(e){if(Array.isArray(e))return e;if("object"==typeof e){var t=Object.prototype.hasOwnProperty,n=[];for(var o in e)t.call(e,o)&&n.push(e[o]);return n}return[]};var o=function(e){return function(t){if(null===t&&t===undefined)return t;if(Array.isArray(t)){for(var n=[],o=0;oc)return 1}return 0};t.sortBy=function(){for(var e=arguments.length,t=new Array(e),n=0;n"+i+""}},function(e,t,n){"use strict";var o=n(4);e.exports=function(e){return o((function(){var t=""[e]('"');return t!==t.toLowerCase()||t.split('"').length>3}))}},function(e,t,n){"use strict";var o=Math.ceil,r=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?r:o)(e)}},function(e,t,n){"use strict";e.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},function(e,t,n){"use strict";t.__esModule=!0,t.getGasColor=t.getGasLabel=t.RADIO_CHANNELS=t.CSS_COLORS=t.COLORS=t.UI_CLOSE=t.UI_DISABLED=t.UI_UPDATE=t.UI_INTERACTIVE=void 0;t.UI_INTERACTIVE=2;t.UI_UPDATE=1;t.UI_DISABLED=0;t.UI_CLOSE=-1;t.COLORS={department:{captain:"#c06616",security:"#e74c3c",medbay:"#3498db",science:"#9b59b6",engineering:"#f1c40f",cargo:"#f39c12",centcom:"#00c100",other:"#c38312"},damageType:{oxy:"#3498db",toxin:"#2ecc71",burn:"#e67e22",brute:"#e74c3c"}};t.CSS_COLORS=["black","white","red","orange","yellow","olive","green","teal","blue","violet","purple","pink","brown","grey","good","average","bad","label"];t.RADIO_CHANNELS=[{name:"Syndicate",freq:1213,color:"#a52a2a"},{name:"Red Team",freq:1215,color:"#ff4444"},{name:"Blue Team",freq:1217,color:"#3434fd"},{name:"CentCom",freq:1337,color:"#2681a5"},{name:"Supply",freq:1347,color:"#b88646"},{name:"Service",freq:1349,color:"#6ca729"},{name:"Science",freq:1351,color:"#c68cfa"},{name:"Command",freq:1353,color:"#5177ff"},{name:"Medical",freq:1355,color:"#57b8f0"},{name:"Engineering",freq:1357,color:"#f37746"},{name:"Security",freq:1359,color:"#dd3535"},{name:"AI Private",freq:1447,color:"#d65d95"},{name:"Common",freq:1459,color:"#1ecc43"}];var o=[{id:"o2",name:"Oxygen",label:"O\u2082",color:"blue"},{id:"n2",name:"Nitrogen",label:"N\u2082",color:"red"},{id:"co2",name:"Carbon Dioxide",label:"CO\u2082",color:"grey"},{id:"plasma",name:"Plasma",label:"Plasma",color:"pink"},{id:"water_vapor",name:"Water Vapor",label:"H\u2082O",color:"grey"},{id:"nob",name:"Hyper-noblium",label:"Hyper-nob",color:"teal"},{id:"n2o",name:"Nitrous Oxide",label:"N\u2082O",color:"red"},{id:"no2",name:"Nitryl",label:"NO\u2082",color:"brown"},{id:"tritium",name:"Tritium",label:"Tritium",color:"green"},{id:"bz",name:"BZ",label:"BZ",color:"purple"},{id:"stim",name:"Stimulum",label:"Stimulum",color:"purple"},{id:"pluox",name:"Pluoxium",label:"Pluoxium",color:"blue"},{id:"miasma",name:"Miasma",label:"Miasma",color:"olive"}];t.getGasLabel=function(e,t){var n=String(e).toLowerCase(),r=o.find((function(e){return e.id===n||e.name.toLowerCase()===n}));return r&&r.label||t||e};t.getGasColor=function(e){var t=String(e).toLowerCase(),n=o.find((function(e){return e.id===t||e.name.toLowerCase()===t}));return n&&n.color}},function(e,t,n){"use strict";var o={}.toString;e.exports=function(e){return o.call(e).slice(8,-1)}},function(e,t,n){"use strict";var o=n(6);e.exports=function(e,t){if(!o(e))return e;var n,r;if(t&&"function"==typeof(n=e.toString)&&!o(r=n.call(e)))return r;if("function"==typeof(n=e.valueOf)&&!o(r=n.call(e)))return r;if(!t&&"function"==typeof(n=e.toString)&&!o(r=n.call(e)))return r;throw TypeError("Can't convert object to primitive value")}},function(e,t,n){"use strict";var o,r,a,i=n(121),c=n(5),l=n(6),u=n(26),d=n(15),s=n(72),p=n(59),m=c.WeakMap;if(i){var f=new m,h=f.get,C=f.has,g=f.set;o=function(e,t){return g.call(f,e,t),t},r=function(e){return h.call(f,e)||{}},a=function(e){return C.call(f,e)}}else{var b=s("state");p[b]=!0,o=function(e,t){return u(e,b,t),t},r=function(e){return d(e,b)?e[b]:{}},a=function(e){return d(e,b)}}e.exports={set:o,get:r,has:a,enforce:function(e){return a(e)?r(e):o(e,{})},getterFor:function(e){return function(t){var n;if(!l(t)||(n=r(t)).type!==e)throw TypeError("Incompatible receiver, "+e+" required");return n}}}},function(e,t,n){"use strict";var o=n(123),r=n(5),a=function(e){return"function"==typeof e?e:undefined};e.exports=function(e,t){return arguments.length<2?a(o[e])||a(r[e]):o[e]&&o[e][t]||r[e]&&r[e][t]}},function(e,t,n){"use strict";var o=n(15),r=n(14),a=n(72),i=n(102),c=a("IE_PROTO"),l=Object.prototype;e.exports=i?Object.getPrototypeOf:function(e){return e=r(e),o(e,c)?e[c]:"function"==typeof e.constructor&&e instanceof e.constructor?e.constructor.prototype:e instanceof Object?l:null}},function(e,t,n){"use strict";e.exports=!1},function(e,t,n){"use strict";var o=n(4);e.exports=function(e,t){var n=[][e];return!n||!o((function(){n.call(null,t||function(){throw 1},1)}))}},function(e,t,n){"use strict";var o=n(1),r=n(5),a=n(9),i=n(113),c=n(7),l=n(77),u=n(55),d=n(46),s=n(26),p=n(10),m=n(137),f=n(151),h=n(34),C=n(15),g=n(74),b=n(6),N=n(42),v=n(53),V=n(47).f,y=n(152),_=n(18).forEach,k=n(54),x=n(13),L=n(20),w=n(35),B=n(79),S=w.get,I=w.set,T=x.f,A=L.f,E=Math.round,P=r.RangeError,M=l.ArrayBuffer,O=l.DataView,R=c.NATIVE_ARRAY_BUFFER_VIEWS,F=c.TYPED_ARRAY_TAG,D=c.TypedArray,j=c.TypedArrayPrototype,z=c.aTypedArrayConstructor,H=c.isTypedArray,G=function(e,t){for(var n=0,o=t.length,r=new(z(e))(o);o>n;)r[n]=t[n++];return r},U=function(e,t){T(e,t,{get:function(){return S(this)[t]}})},K=function(e){var t;return e instanceof M||"ArrayBuffer"==(t=g(e))||"SharedArrayBuffer"==t},Y=function(e,t){return H(e)&&"symbol"!=typeof t&&t in e&&String(+t)==String(t)},q=function(e,t){return Y(e,t=h(t,!0))?d(2,e[t]):A(e,t)},W=function(e,t,n){return!(Y(e,t=h(t,!0))&&b(n)&&C(n,"value"))||C(n,"get")||C(n,"set")||n.configurable||C(n,"writable")&&!n.writable||C(n,"enumerable")&&!n.enumerable?T(e,t,n):(e[t]=n.value,e)};a?(R||(L.f=q,x.f=W,U(j,"buffer"),U(j,"byteOffset"),U(j,"byteLength"),U(j,"length")),o({target:"Object",stat:!0,forced:!R},{getOwnPropertyDescriptor:q,defineProperty:W}),e.exports=function(e,t,n){var a=e.match(/\d+$/)[0]/8,c=e+(n?"Clamped":"")+"Array",l="get"+e,d="set"+e,h=r[c],C=h,g=C&&C.prototype,x={},L=function(e,t){var n=S(e);return n.view[l](t*a+n.byteOffset,!0)},w=function(e,t,o){var r=S(e);n&&(o=(o=E(o))<0?0:o>255?255:255&o),r.view[d](t*a+r.byteOffset,o,!0)},A=function(e,t){T(e,t,{get:function(){return L(this,t)},set:function(e){return w(this,t,e)},enumerable:!0})};R?i&&(C=t((function(e,t,n,o){return u(e,C,c),B(b(t)?K(t)?o!==undefined?new h(t,f(n,a),o):n!==undefined?new h(t,f(n,a)):new h(t):H(t)?G(C,t):y.call(C,t):new h(m(t)),e,C)})),v&&v(C,D),_(V(h),(function(e){e in C||s(C,e,h[e])})),C.prototype=g):(C=t((function(e,t,n,o){u(e,C,c);var r,i,l,d=0,s=0;if(b(t)){if(!K(t))return H(t)?G(C,t):y.call(C,t);r=t,s=f(n,a);var h=t.byteLength;if(o===undefined){if(h%a)throw P("Wrong length");if((i=h-s)<0)throw P("Wrong length")}else if((i=p(o)*a)+s>h)throw P("Wrong length");l=i/a}else l=m(t),r=new M(i=l*a);for(I(e,{buffer:r,byteOffset:s,byteLength:i,length:l,view:new O(r)});ddocument.F=Object<\/script>"),e.close(),p=e.F;n--;)delete p[d][a[n]];return p()};e.exports=Object.create||function(e,t){var n;return null!==e?(s[d]=o(e),n=new s,s[d]=null,n[u]=e):n=p(),t===undefined?n:r(n,t)},i[u]=!0},function(e,t,n){"use strict";var o=n(13).f,r=n(15),a=n(12)("toStringTag");e.exports=function(e,t,n){e&&!r(e=n?e:e.prototype,a)&&o(e,a,{configurable:!0,value:t})}},function(e,t,n){"use strict";var o=n(12),r=n(42),a=n(26),i=o("unscopables"),c=Array.prototype;c[i]==undefined&&a(c,i,r(null)),e.exports=function(e){c[i][e]=!0}},function(e,t,n){"use strict";var o=n(8),r=n(31),a=n(12)("species");e.exports=function(e,t){var n,i=o(e).constructor;return i===undefined||(n=o(i)[a])==undefined?t:r(n)}},function(e,t,n){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){"use strict";var o=n(124),r=n(93).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return o(e,r)}},function(e,t,n){"use strict";var o=n(31);e.exports=function(e,t,n){if(o(e),t===undefined)return e;switch(n){case 0:return function(){return e.call(t)};case 1:return function(n){return e.call(t,n)};case 2:return function(n,o){return e.call(t,n,o)};case 3:return function(n,o,r){return e.call(t,n,o,r)}}return function(){return e.apply(t,arguments)}}},function(e,t,n){"use strict";var o=n(34),r=n(13),a=n(46);e.exports=function(e,t,n){var i=o(t);i in e?r.f(e,i,a(0,n)):e[i]=n}},function(e,t,n){"use strict";var o=n(59),r=n(6),a=n(15),i=n(13).f,c=n(58),l=n(67),u=c("meta"),d=0,s=Object.isExtensible||function(){return!0},p=function(e){i(e,u,{value:{objectID:"O"+ ++d,weakData:{}}})},m=e.exports={REQUIRED:!1,fastKey:function(e,t){if(!r(e))return"symbol"==typeof e?e:("string"==typeof e?"S":"P")+e;if(!a(e,u)){if(!s(e))return"F";if(!t)return"E";p(e)}return e[u].objectID},getWeakData:function(e,t){if(!a(e,u)){if(!s(e))return!0;if(!t)return!1;p(e)}return e[u].weakData},onFreeze:function(e){return l&&m.REQUIRED&&s(e)&&!a(e,u)&&p(e),e}};o[u]=!0},function(e,t,n){"use strict";t.__esModule=!0,t.createLogger=void 0;n(154);var o=n(16),r=0,a=1,i=2,c=3,l=4,u=function(e,t){for(var n=arguments.length,r=new Array(n>2?n-2:0),a=2;a=i){var c=[t].concat(r).map((function(e){return"string"==typeof e?e:e instanceof Error?e.stack||String(e):JSON.stringify(e)})).filter((function(e){return e})).join(" ")+"\nUser Agent: "+navigator.userAgent;(0,o.act)(window.__ref__,"tgui:log",{log:c})}};t.createLogger=function(e){return{debug:function(){for(var t=arguments.length,n=new Array(t),o=0;od;)if((c=l[d++])!=c)return!0}else for(;u>d;d++)if((e||d in l)&&l[d]===n)return e||d||0;return!e&&-1}};e.exports={includes:i(!0),indexOf:i(!1)}},function(e,t,n){"use strict";var o=n(4),r=/#|\.prototype\./,a=function(e,t){var n=c[i(e)];return n==u||n!=l&&("function"==typeof t?o(t):!!t)},i=a.normalize=function(e){return String(e).replace(r,".").toLowerCase()},c=a.data={},l=a.NATIVE="N",u=a.POLYFILL="P";e.exports=a},function(e,t,n){"use strict";var o=n(124),r=n(93);e.exports=Object.keys||function(e){return o(e,r)}},function(e,t,n){"use strict";var o=n(6),r=n(52),a=n(12)("species");e.exports=function(e,t){var n;return r(e)&&("function"!=typeof(n=e.constructor)||n!==Array&&!r(n.prototype)?o(n)&&null===(n=n[a])&&(n=undefined):n=undefined),new(n===undefined?Array:n)(0===t?0:t)}},function(e,t,n){"use strict";var o=n(4),r=n(12),a=n(96),i=r("species");e.exports=function(e){return a>=51||!o((function(){var t=[];return(t.constructor={})[i]=function(){return{foo:1}},1!==t[e](Boolean).foo}))}},function(e,t,n){"use strict";e.exports={}},function(e,t,n){"use strict";var o=n(22);e.exports=function(e,t,n){for(var r in t)o(e,r,t[r],n);return e}},function(e,t,n){"use strict";var o=n(4);e.exports=!o((function(){return Object.isExtensible(Object.preventExtensions({}))}))},function(e,t,n){"use strict";var o=n(8),r=n(98),a=n(10),i=n(48),c=n(99),l=n(132),u=function(e,t){this.stopped=e,this.result=t};(e.exports=function(e,t,n,d,s){var p,m,f,h,C,g,b,N=i(t,n,d?2:1);if(s)p=e;else{if("function"!=typeof(m=c(e)))throw TypeError("Target is not iterable");if(r(m)){for(f=0,h=a(e.length);h>f;f++)if((C=d?N(o(b=e[f])[0],b[1]):N(e[f]))&&C instanceof u)return C;return new u(!1)}p=m.call(e)}for(g=p.next;!(b=g.call(p)).done;)if("object"==typeof(C=l(p,N,b.value,d))&&C&&C instanceof u)return C;return new u(!1)}).stop=function(e){return new u(!0,e)}},function(e,t,n){"use strict";t.__esModule=!0,t.InterfaceLockNoticeBox=void 0;var o=n(0),r=n(2);t.InterfaceLockNoticeBox=function(e){var t=e.siliconUser,n=e.locked,a=e.onLockStatusChange,i=e.accessText;return t?(0,o.createComponentVNode)(2,r.NoticeBox,{children:(0,o.createComponentVNode)(2,r.Flex,{align:"center",children:[(0,o.createComponentVNode)(2,r.Flex.Item,{children:"Interface lock status:"}),(0,o.createComponentVNode)(2,r.Flex.Item,{grow:1}),(0,o.createComponentVNode)(2,r.Flex.Item,{children:(0,o.createComponentVNode)(2,r.Button,{m:0,color:"gray",icon:n?"lock":"unlock",content:n?"Locked":"Unlocked",onClick:function(){a&&a(!n)}})})]})}):(0,o.createComponentVNode)(2,r.NoticeBox,{children:["Swipe ",i||"an ID card"," ","to ",n?"unlock":"lock"," this interface."]})}},function(e,t,n){"use strict";t.__esModule=!0,t.compose=t.flow=void 0;t.flow=function o(){for(var e=arguments.length,t=new Array(e),n=0;n1?r-1:0),i=1;i=c.length)break;d=c[u++]}else{if((u=c.next()).done)break;d=u.value}var s=d;Array.isArray(s)?n=o.apply(void 0,s).apply(void 0,[n].concat(a)):s&&(n=s.apply(void 0,[n].concat(a)))}return n}};t.compose=function(){for(var e=arguments.length,t=new Array(e),n=0;n1?o-1:0),a=1;a=0:s>p;p+=m)p in d&&(l=n(l,d[p],p,u));return l}};e.exports={left:c(!1),right:c(!0)}},function(e,t,n){"use strict";var o=n(5),r=n(9),a=n(7).NATIVE_ARRAY_BUFFER,i=n(26),c=n(66),l=n(4),u=n(55),d=n(30),s=n(10),p=n(137),m=n(218),f=n(47).f,h=n(13).f,C=n(97),g=n(43),b=n(35),N=b.get,v=b.set,V="ArrayBuffer",y="DataView",_="Wrong length",k=o[V],x=k,L=o[y],w=o.RangeError,B=m.pack,S=m.unpack,I=function(e){return[255&e]},T=function(e){return[255&e,e>>8&255]},A=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},E=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},P=function(e){return B(e,23,4)},M=function(e){return B(e,52,8)},O=function(e,t){h(e.prototype,t,{get:function(){return N(this)[t]}})},R=function(e,t,n,o){var r=p(n),a=N(e);if(r+t>a.byteLength)throw w("Wrong index");var i=N(a.buffer).bytes,c=r+a.byteOffset,l=i.slice(c,c+t);return o?l:l.reverse()},F=function(e,t,n,o,r,a){var i=p(n),c=N(e);if(i+t>c.byteLength)throw w("Wrong index");for(var l=N(c.buffer).bytes,u=i+c.byteOffset,d=o(+r),s=0;sH;)(D=z[H++])in x||i(x,D,k[D]);j.constructor=x}var G=new L(new x(2)),U=L.prototype.setInt8;G.setInt8(0,2147483648),G.setInt8(1,2147483649),!G.getInt8(0)&&G.getInt8(1)||c(L.prototype,{setInt8:function(e,t){U.call(this,e,t<<24>>24)},setUint8:function(e,t){U.call(this,e,t<<24>>24)}},{unsafe:!0})}else x=function(e){u(this,x,V);var t=p(e);v(this,{bytes:C.call(new Array(t),0),byteLength:t}),r||(this.byteLength=t)},L=function(e,t,n){u(this,L,y),u(e,x,y);var o=N(e).byteLength,a=d(t);if(a<0||a>o)throw w("Wrong offset");if(a+(n=n===undefined?o-a:s(n))>o)throw w(_);v(this,{buffer:e,byteLength:n,byteOffset:a}),r||(this.buffer=e,this.byteLength=n,this.byteOffset=a)},r&&(O(x,"byteLength"),O(L,"buffer"),O(L,"byteLength"),O(L,"byteOffset")),c(L.prototype,{getInt8:function(e){return R(this,1,e)[0]<<24>>24},getUint8:function(e){return R(this,1,e)[0]},getInt16:function(e){var t=R(this,2,e,arguments.length>1?arguments[1]:undefined);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=R(this,2,e,arguments.length>1?arguments[1]:undefined);return t[1]<<8|t[0]},getInt32:function(e){return E(R(this,4,e,arguments.length>1?arguments[1]:undefined))},getUint32:function(e){return E(R(this,4,e,arguments.length>1?arguments[1]:undefined))>>>0},getFloat32:function(e){return S(R(this,4,e,arguments.length>1?arguments[1]:undefined),23)},getFloat64:function(e){return S(R(this,8,e,arguments.length>1?arguments[1]:undefined),52)},setInt8:function(e,t){F(this,1,e,I,t)},setUint8:function(e,t){F(this,1,e,I,t)},setInt16:function(e,t){F(this,2,e,T,t,arguments.length>2?arguments[2]:undefined)},setUint16:function(e,t){F(this,2,e,T,t,arguments.length>2?arguments[2]:undefined)},setInt32:function(e,t){F(this,4,e,A,t,arguments.length>2?arguments[2]:undefined)},setUint32:function(e,t){F(this,4,e,A,t,arguments.length>2?arguments[2]:undefined)},setFloat32:function(e,t){F(this,4,e,P,t,arguments.length>2?arguments[2]:undefined)},setFloat64:function(e,t){F(this,8,e,M,t,arguments.length>2?arguments[2]:undefined)}});g(x,V),g(L,y),e.exports={ArrayBuffer:x,DataView:L}},function(e,t,n){"use strict";var o=n(1),r=n(5),a=n(61),i=n(22),c=n(50),l=n(68),u=n(55),d=n(6),s=n(4),p=n(75),m=n(43),f=n(79);e.exports=function(e,t,n){var h=-1!==e.indexOf("Map"),C=-1!==e.indexOf("Weak"),g=h?"set":"add",b=r[e],N=b&&b.prototype,v=b,V={},y=function(e){var t=N[e];i(N,e,"add"==e?function(e){return t.call(this,0===e?0:e),this}:"delete"==e?function(e){return!(C&&!d(e))&&t.call(this,0===e?0:e)}:"get"==e?function(e){return C&&!d(e)?undefined:t.call(this,0===e?0:e)}:"has"==e?function(e){return!(C&&!d(e))&&t.call(this,0===e?0:e)}:function(e,n){return t.call(this,0===e?0:e,n),this})};if(a(e,"function"!=typeof b||!(C||N.forEach&&!s((function(){(new b).entries().next()})))))v=n.getConstructor(t,e,h,g),c.REQUIRED=!0;else if(a(e,!0)){var _=new v,k=_[g](C?{}:-0,1)!=_,x=s((function(){_.has(1)})),L=p((function(e){new b(e)})),w=!C&&s((function(){for(var e=new b,t=5;t--;)e[g](t,t);return!e.has(-0)}));L||((v=t((function(t,n){u(t,v,e);var o=f(new b,t,v);return n!=undefined&&l(n,o[g],o,h),o}))).prototype=N,N.constructor=v),(x||w)&&(y("delete"),y("has"),h&&y("get")),(w||k)&&y(g),C&&N.clear&&delete N.clear}return V[e]=v,o({global:!0,forced:v!=b},V),m(v,e),C||n.setStrong(v,e,h),v}},function(e,t,n){"use strict";var o=n(6),r=n(53);e.exports=function(e,t,n){var a,i;return r&&"function"==typeof(a=t.constructor)&&a!==n&&o(i=a.prototype)&&i!==n.prototype&&r(e,i),e}},function(e,t,n){"use strict";var o=Math.expm1,r=Math.exp;e.exports=!o||o(10)>22025.465794806718||o(10)<22025.465794806718||-2e-17!=o(-2e-17)?function(e){return 0==(e=+e)?e:e>-1e-6&&e<1e-6?e+e*e/2:r(e)-1}:o},function(e,t,n){"use strict";e.exports="\t\n\x0B\f\r \xa0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\ufeff"},function(e,t,n){"use strict";var o=n(38),r=n(5),a=n(4);e.exports=o||!a((function(){var e=Math.random();__defineSetter__.call(null,e,(function(){})),delete r[e]}))},function(e,t,n){"use strict";var o=n(8);e.exports=function(){var e=o(this),t="";return e.global&&(t+="g"),e.ignoreCase&&(t+="i"),e.multiline&&(t+="m"),e.dotAll&&(t+="s"),e.unicode&&(t+="u"),e.sticky&&(t+="y"),t}},function(e,t,n){"use strict";var o,r,a=n(83),i=RegExp.prototype.exec,c=String.prototype.replace,l=i,u=(o=/a/,r=/b*/g,i.call(o,"a"),i.call(r,"a"),0!==o.lastIndex||0!==r.lastIndex),d=/()??/.exec("")[1]!==undefined;(u||d)&&(l=function(e){var t,n,o,r,l=this;return d&&(n=new RegExp("^"+l.source+"$(?!\\s)",a.call(l))),u&&(t=l.lastIndex),o=i.call(l,e),u&&o&&(l.lastIndex=l.global?o.index+o[0].length:t),d&&o&&o.length>1&&c.call(o[0],n,(function(){for(r=1;r")})),d=!a((function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var n="ab".split(e);return 2!==n.length||"a"!==n[0]||"b"!==n[1]}));e.exports=function(e,t,n,s){var p=i(e),m=!a((function(){var t={};return t[p]=function(){return 7},7!=""[e](t)})),f=m&&!a((function(){var t=!1,n=/a/;return"split"===e&&((n={}).constructor={},n.constructor[l]=function(){return n},n.flags="",n[p]=/./[p]),n.exec=function(){return t=!0,null},n[p](""),!t}));if(!m||!f||"replace"===e&&!u||"split"===e&&!d){var h=/./[p],C=n(p,""[e],(function(e,t,n,o,r){return t.exec===c?m&&!r?{done:!0,value:h.call(t,n,o)}:{done:!0,value:e.call(n,t,o)}:{done:!1}})),g=C[0],b=C[1];r(String.prototype,e,g),r(RegExp.prototype,p,2==t?function(e,t){return b.call(e,this,t)}:function(e){return b.call(e,this)}),s&&o(RegExp.prototype[p],"sham",!0)}}},function(e,t,n){"use strict";var o=n(33),r=n(84);e.exports=function(e,t){var n=e.exec;if("function"==typeof n){var a=n.call(e,t);if("object"!=typeof a)throw TypeError("RegExp exec method returned something other than an Object or null");return a}if("RegExp"!==o(e))throw TypeError("RegExp#exec called on incompatible receiver");return r.call(e,t)}},function(e,t,n){"use strict";t.__esModule=!0,t.Icon=void 0;var o=n(0),r=n(11),a=n(19);var i=/-o$/,c=function(e){var t=e.name,n=e.size,c=e.spin,l=e.className,u=e.style,d=void 0===u?{}:u,s=e.rotation,p=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,["name","size","spin","className","style","rotation"]);n&&(d["font-size"]=100*n+"%"),"number"==typeof s&&(d.transform="rotate("+s+"deg)");var m=i.test(t),f=t.replace(i,"");return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({as:"i",className:(0,r.classes)([l,m?"far":"fas","fa-"+f,c&&"fa-spin"]),style:d},p)))};t.Icon=c,c.defaultHooks=r.pureComponentHooks},function(e,t,n){"use strict";var o=n(5),r=n(6),a=o.document,i=r(a)&&r(a.createElement);e.exports=function(e){return i?a.createElement(e):{}}},function(e,t,n){"use strict";var o=n(5),r=n(26);e.exports=function(e,t){try{r(o,e,t)}catch(n){o[e]=t}return t}},function(e,t,n){"use strict";var o=n(120),r=Function.toString;"function"!=typeof o.inspectSource&&(o.inspectSource=function(e){return r.call(e)}),e.exports=o.inspectSource},function(e,t,n){"use strict";var o=n(38),r=n(120);(e.exports=function(e,t){return r[e]||(r[e]=t!==undefined?t:{})})("versions",[]).push({version:"3.4.8",mode:o?"pure":"global",copyright:"\xa9 2019 Denis Pushkarev (zloirock.ru)"})},function(e,t,n){"use strict";var o=n(36),r=n(47),a=n(94),i=n(8);e.exports=o("Reflect","ownKeys")||function(e){var t=r.f(i(e)),n=a.f;return n?t.concat(n(e)):t}},function(e,t,n){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(e,t,n){"use strict";t.f=Object.getOwnPropertySymbols},function(e,t,n){"use strict";var o=n(4);e.exports=!!Object.getOwnPropertySymbols&&!o((function(){return!String(Symbol())}))},function(e,t,n){"use strict";var o,r,a=n(5),i=n(73),c=a.process,l=c&&c.versions,u=l&&l.v8;u?r=(o=u.split("."))[0]+o[1]:i&&(!(o=i.match(/Edge\/(\d+)/))||o[1]>=74)&&(o=i.match(/Chrome\/(\d+)/))&&(r=o[1]),e.exports=r&&+r},function(e,t,n){"use strict";var o=n(14),r=n(41),a=n(10);e.exports=function(e){for(var t=o(this),n=a(t.length),i=arguments.length,c=r(i>1?arguments[1]:undefined,n),l=i>2?arguments[2]:undefined,u=l===undefined?n:r(l,n);u>c;)t[c++]=e;return t}},function(e,t,n){"use strict";var o=n(12),r=n(65),a=o("iterator"),i=Array.prototype;e.exports=function(e){return e!==undefined&&(r.Array===e||i[a]===e)}},function(e,t,n){"use strict";var o=n(74),r=n(65),a=n(12)("iterator");e.exports=function(e){if(e!=undefined)return e[a]||e["@@iterator"]||r[o(e)]}},function(e,t,n){"use strict";var o={};o[n(12)("toStringTag")]="z",e.exports="[object z]"===String(o)},function(e,t,n){"use strict";var o=n(1),r=n(203),a=n(37),i=n(53),c=n(43),l=n(26),u=n(22),d=n(12),s=n(38),p=n(65),m=n(134),f=m.IteratorPrototype,h=m.BUGGY_SAFARI_ITERATORS,C=d("iterator"),g=function(){return this};e.exports=function(e,t,n,d,m,b,N){r(n,t,d);var v,V,y,_=function(e){if(e===m&&B)return B;if(!h&&e in L)return L[e];switch(e){case"keys":case"values":case"entries":return function(){return new n(this,e)}}return function(){return new n(this)}},k=t+" Iterator",x=!1,L=e.prototype,w=L[C]||L["@@iterator"]||m&&L[m],B=!h&&w||_(m),S="Array"==t&&L.entries||w;if(S&&(v=a(S.call(new e)),f!==Object.prototype&&v.next&&(s||a(v)===f||(i?i(v,f):"function"!=typeof v[C]&&l(v,C,g)),c(v,k,!0,!0),s&&(p[k]=g))),"values"==m&&w&&"values"!==w.name&&(x=!0,B=function(){return w.call(this)}),s&&!N||L[C]===B||l(L,C,B),p[t]=B,m)if(V={values:_("values"),keys:b?B:_("keys"),entries:_("entries")},N)for(y in V)!h&&!x&&y in L||u(L,y,V[y]);else o({target:t,proto:!0,forced:h||x},V);return V}},function(e,t,n){"use strict";var o=n(4);e.exports=!o((function(){function e(){}return e.prototype.constructor=null,Object.getPrototypeOf(new e)!==e.prototype}))},function(e,t,n){"use strict";var o=n(10),r=n(104),a=n(21),i=Math.ceil,c=function(e){return function(t,n,c){var l,u,d=String(a(t)),s=d.length,p=c===undefined?" ":String(c),m=o(n);return m<=s||""==p?d:(l=m-s,(u=r.call(p,i(l/p.length))).length>l&&(u=u.slice(0,l)),e?d+u:u+d)}};e.exports={start:c(!1),end:c(!0)}},function(e,t,n){"use strict";var o=n(30),r=n(21);e.exports="".repeat||function(e){var t=String(r(this)),n="",a=o(e);if(a<0||a==Infinity)throw RangeError("Wrong number of repetitions");for(;a>0;(a>>>=1)&&(t+=t))1&a&&(n+=t);return n}},function(e,t,n){"use strict";e.exports=Math.sign||function(e){return 0==(e=+e)||e!=e?e:e<0?-1:1}},function(e,t,n){"use strict";var o,r,a,i=n(5),c=n(4),l=n(33),u=n(48),d=n(127),s=n(88),p=n(146),m=i.location,f=i.setImmediate,h=i.clearImmediate,C=i.process,g=i.MessageChannel,b=i.Dispatch,N=0,v={},V=function(e){if(v.hasOwnProperty(e)){var t=v[e];delete v[e],t()}},y=function(e){return function(){V(e)}},_=function(e){V(e.data)},k=function(e){i.postMessage(e+"",m.protocol+"//"+m.host)};f&&h||(f=function(e){for(var t=[],n=1;arguments.length>n;)t.push(arguments[n++]);return v[++N]=function(){("function"==typeof e?e:Function(e)).apply(undefined,t)},o(N),N},h=function(e){delete v[e]},"process"==l(C)?o=function(e){C.nextTick(y(e))}:b&&b.now?o=function(e){b.now(y(e))}:g&&!p?(a=(r=new g).port2,r.port1.onmessage=_,o=u(a.postMessage,a,1)):!i.addEventListener||"function"!=typeof postMessage||i.importScripts||c(k)?o="onreadystatechange"in s("script")?function(e){d.appendChild(s("script")).onreadystatechange=function(){d.removeChild(this),V(e)}}:function(e){setTimeout(y(e),0)}:(o=k,i.addEventListener("message",_,!1))),e.exports={set:f,clear:h}},function(e,t,n){"use strict";var o=n(6),r=n(33),a=n(12)("match");e.exports=function(e){var t;return o(e)&&((t=e[a])!==undefined?!!t:"RegExp"==r(e))}},function(e,t,n){"use strict";var o=n(30),r=n(21),a=function(e){return function(t,n){var a,i,c=String(r(t)),l=o(n),u=c.length;return l<0||l>=u?e?"":undefined:(a=c.charCodeAt(l))<55296||a>56319||l+1===u||(i=c.charCodeAt(l+1))<56320||i>57343?e?c.charAt(l):a:e?c.slice(l,l+2):i-56320+(a-55296<<10)+65536}};e.exports={codeAt:a(!1),charAt:a(!0)}},function(e,t,n){"use strict";var o=n(107);e.exports=function(e){if(o(e))throw TypeError("The method doesn't accept regular expressions");return e}},function(e,t,n){"use strict";var o=n(12)("match");e.exports=function(e){var t=/./;try{"/./"[e](t)}catch(n){try{return t[o]=!1,"/./"[e](t)}catch(r){}}return!1}},function(e,t,n){"use strict";var o=n(108).charAt;e.exports=function(e,t,n){return t+(n?o(e,t).length:1)}},function(e,t,n){"use strict";var o=n(4),r=n(81);e.exports=function(e){return o((function(){return!!r[e]()||"\u200b\x85\u180e"!="\u200b\x85\u180e"[e]()||r[e].name!==e}))}},function(e,t,n){"use strict";var o=n(5),r=n(4),a=n(75),i=n(7).NATIVE_ARRAY_BUFFER_VIEWS,c=o.ArrayBuffer,l=o.Int8Array;e.exports=!i||!r((function(){l(1)}))||!r((function(){new l(-1)}))||!a((function(e){new l,new l(null),new l(1.5),new l(e)}),!0)||r((function(){return 1!==new l(new c(2),1,undefined).length}))},function(e,t,n){"use strict";t.__esModule=!0,t.ButtonInput=t.ButtonConfirm=t.ButtonCheckbox=t.Button=void 0;var o=n(0),r=n(11),a=n(16),i=n(115),c=n(51),l=n(116),u=n(19),d=n(87),s=n(159);n(160),n(161);function p(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function m(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var f=(0,c.createLogger)("Button"),h=function(e){var t=e.className,n=e.fluid,c=e.icon,p=e.color,h=e.disabled,C=e.selected,g=e.tooltip,b=e.tooltipPosition,N=e.ellipsis,v=e.content,V=e.iconRotation,y=e.iconSpin,_=e.children,k=e.onclick,x=e.onClick,L=m(e,["className","fluid","icon","color","disabled","selected","tooltip","tooltipPosition","ellipsis","content","iconRotation","iconSpin","children","onclick","onClick"]),w=!(!v&&!_);return k&&f.warn("Lowercase 'onclick' is not supported on Button and lowercase prop names are discouraged in general. Please use a camelCase'onClick' instead and read: https://infernojs.org/docs/guides/event-handling"),(0,o.normalizeProps)((0,o.createComponentVNode)(2,u.Box,Object.assign({as:"span",className:(0,r.classes)(["Button",n&&"Button--fluid",h&&"Button--disabled",C&&"Button--selected",w&&"Button--hasContent",N&&"Button--ellipsis",p&&"string"==typeof p?"Button--color--"+p:"Button--color--default",t]),tabIndex:!h&&"0",unselectable:a.tridentVersion<=4,onclick:function(e){(0,l.refocusLayout)(),!h&&x&&x(e)},onKeyDown:function(e){var t=window.event?e.which:e.keyCode;return t===i.KEY_SPACE||t===i.KEY_ENTER?(e.preventDefault(),void(!h&&x&&x(e))):t===i.KEY_ESCAPE?(e.preventDefault(),void(0,l.refocusLayout)()):void 0}},L,{children:[c&&(0,o.createComponentVNode)(2,d.Icon,{name:c,rotation:V,spin:y}),v,_,g&&(0,o.createComponentVNode)(2,s.Tooltip,{content:g,position:b})]})))};t.Button=h,h.defaultHooks=r.pureComponentHooks;var C=function(e){var t=e.checked,n=m(e,["checked"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,h,Object.assign({color:"transparent",icon:t?"check-square-o":"square-o",selected:t},n)))};t.ButtonCheckbox=C,h.Checkbox=C;var g=function(e){function t(){var t;return(t=e.call(this)||this).state={clickedOnce:!1},t.handleClick=function(){t.state.clickedOnce&&t.setClickedOnce(!1)},t}p(t,e);var n=t.prototype;return n.setClickedOnce=function(e){var t=this;this.setState({clickedOnce:e}),e?setTimeout((function(){return window.addEventListener("click",t.handleClick)})):window.removeEventListener("click",this.handleClick)},n.render=function(){var e=this,t=this.props,n=t.confirmMessage,r=void 0===n?"Confirm?":n,a=t.confirmColor,i=void 0===a?"bad":a,c=t.color,l=t.content,u=t.onClick,d=m(t,["confirmMessage","confirmColor","color","content","onClick"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,h,Object.assign({content:this.state.clickedOnce?r:l,color:this.state.clickedOnce?i:c,onClick:function(){return e.state.clickedOnce?u():e.setClickedOnce(!0)}},d)))},t}(o.Component);t.ButtonConfirm=g,h.Confirm=g;var b=function(e){function t(){var t;return(t=e.call(this)||this).inputRef=(0,o.createRef)(),t.state={inInput:!1},t}p(t,e);var n=t.prototype;return n.setInInput=function(e){if(this.setState({inInput:e}),this.inputRef){var t=this.inputRef.current;if(e){t.value=this.props.currentValue||"";try{t.focus(),t.select()}catch(n){}}}},n.commitResult=function(e){if(this.inputRef){var t=this.inputRef.current;if(""!==t.value)return void this.props.onCommit(e,t.value);if(!this.props.defaultValue)return;this.props.onCommit(e,this.props.defaultValue)}},n.render=function(){var e=this,t=this.props,n=t.fluid,a=t.content,c=t.color,l=void 0===c?"default":c,d=(t.placeholder,t.maxLength,m(t,["fluid","content","color","placeholder","maxLength"]));return(0,o.normalizeProps)((0,o.createComponentVNode)(2,u.Box,Object.assign({className:(0,r.classes)(["Button",n&&"Button--fluid","Button--color--"+l])},d,{onClick:function(){return e.setInInput(!0)},children:[(0,o.createVNode)(1,"div",null,a,0),(0,o.createVNode)(64,"input","NumberInput__input",null,1,{style:{display:this.state.inInput?undefined:"none","text-align":"left"},onBlur:function(t){e.state.inInput&&(e.setInInput(!1),e.commitResult(t))},onKeyDown:function(t){if(t.keyCode===i.KEY_ENTER)return e.setInInput(!1),void e.commitResult(t);t.keyCode===i.KEY_ESCAPE&&e.setInInput(!1)}},null,this.inputRef)]})))},t}(o.Component);t.ButtonInput=b,h.Input=b},function(e,t,n){"use strict";t.__esModule=!0,t.hotKeyReducer=t.hotKeyMiddleware=t.releaseHeldKeys=t.KEY_MINUS=t.KEY_EQUAL=t.KEY_Z=t.KEY_Y=t.KEY_X=t.KEY_W=t.KEY_V=t.KEY_U=t.KEY_T=t.KEY_S=t.KEY_R=t.KEY_Q=t.KEY_P=t.KEY_O=t.KEY_N=t.KEY_M=t.KEY_L=t.KEY_K=t.KEY_J=t.KEY_I=t.KEY_H=t.KEY_G=t.KEY_F=t.KEY_E=t.KEY_D=t.KEY_C=t.KEY_B=t.KEY_A=t.KEY_9=t.KEY_8=t.KEY_7=t.KEY_6=t.KEY_5=t.KEY_4=t.KEY_3=t.KEY_2=t.KEY_1=t.KEY_0=t.KEY_SPACE=t.KEY_ESCAPE=t.KEY_ALT=t.KEY_CTRL=t.KEY_SHIFT=t.KEY_ENTER=t.KEY_TAB=t.KEY_BACKSPACE=void 0;var o=n(51),r=n(16),a=(0,o.createLogger)("hotkeys");t.KEY_BACKSPACE=8;t.KEY_TAB=9;t.KEY_ENTER=13;t.KEY_SHIFT=16;t.KEY_CTRL=17;t.KEY_ALT=18;t.KEY_ESCAPE=27;t.KEY_SPACE=32;t.KEY_0=48;t.KEY_1=49;t.KEY_2=50;t.KEY_3=51;t.KEY_4=52;t.KEY_5=53;t.KEY_6=54;t.KEY_7=55;t.KEY_8=56;t.KEY_9=57;t.KEY_A=65;t.KEY_B=66;t.KEY_C=67;t.KEY_D=68;t.KEY_E=69;t.KEY_F=70;t.KEY_G=71;t.KEY_H=72;t.KEY_I=73;t.KEY_J=74;t.KEY_K=75;t.KEY_L=76;t.KEY_M=77;t.KEY_N=78;t.KEY_O=79;t.KEY_P=80;t.KEY_Q=81;t.KEY_R=82;t.KEY_S=83;t.KEY_T=84;t.KEY_U=85;t.KEY_V=86;t.KEY_W=87;t.KEY_X=88;t.KEY_Y=89;t.KEY_Z=90;t.KEY_EQUAL=187;t.KEY_MINUS=189;var i=[17,18,16],c=[27,13,32,9,17,16],l={},u=function(e,t,n,o){var r="";return e&&(r+="Ctrl+"),t&&(r+="Alt+"),n&&(r+="Shift+"),r+=o>=48&&o<=90?String.fromCharCode(o):"["+o+"]"},d=function(e){var t=window.event?e.which:e.keyCode,n=e.ctrlKey,o=e.altKey,r=e.shiftKey;return{keyCode:t,ctrlKey:n,altKey:o,shiftKey:r,hasModifierKeys:n||o||r,keyString:u(n,o,r,t)}},s=function(){for(var e=0,t=Object.keys(l);e4&&function(e,t){if(!e.defaultPrevented){var n=e.target&&e.target.localName;if("input"!==n&&"textarea"!==n){var o=d(e),i=o.keyCode,u=o.ctrlKey,s=o.shiftKey;u||s||c.includes(i)||("keydown"!==t||l[i]?"keyup"===t&&l[i]&&(a.debug("passthrough",t,o),(0,r.callByond)("",{__keyup:i})):(a.debug("passthrough",t,o),(0,r.callByond)("",{__keydown:i})))}}}(e,t),function(e,t,n){if("keyup"===t){var o=d(e),r=o.ctrlKey,c=o.altKey,l=o.keyCode,u=o.hasModifierKeys,s=o.keyString;u&&!i.includes(l)&&(a.log(s),r&&c&&8===l&&setTimeout((function(){throw new Error("OOPSIE WOOPSIE!! UwU We made a fucky wucky!! A wittle fucko boingo! The code monkeys at our headquarters are working VEWY HAWD to fix this!")})),n({type:"hotKey",payload:o}))}}(e,t,n)},document.addEventListener("keydown",(function(e){var n=window.event?e.which:e.keyCode;t(e,"keydown"),l[n]=!0})),document.addEventListener("keyup",(function(e){var n=window.event?e.which:e.keyCode;t(e,"keyup"),l[n]=!1})),r.tridentVersion>4&&function(e){var t;document.addEventListener("focusout",(function(){t=setTimeout(e)})),document.addEventListener("focusin",(function(){clearTimeout(t)})),window.addEventListener("beforeunload",e)}((function(){s()})),function(e){return function(t){return e(t)}}};t.hotKeyReducer=function(e,t){var n=t.type,o=t.payload;if("hotKey"===n){var r=o.ctrlKey,a=o.altKey,i=o.keyCode;return r&&a&&187===i?Object.assign({},e,{showKitchenSink:!e.showKitchenSink}):e}return e}},function(e,t,n){"use strict";t.__esModule=!0,t.refocusLayout=void 0;var o=n(16);t.refocusLayout=function(){if(!(o.tridentVersion<=4)){var e=document.getElementById("Layout__content");e&&e.focus()}}},function(e,t,n){"use strict";t.__esModule=!0,t.toastReducer=t.showToast=t.Toast=void 0;var o,r=n(0),a=n(11),i=function(e){var t=e.content,n=e.children;return(0,r.createVNode)(1,"div","Layout__toast",[t,n],0)};t.Toast=i,i.defaultHooks=a.pureComponentHooks;t.showToast=function(e,t){o&&clearTimeout(o),o=setTimeout((function(){o=undefined,e({type:"hideToast"})}),5e3),e({type:"showToast",payload:{text:t}})};t.toastReducer=function(e,t){var n=t.type,o=t.payload;if("showToast"===n){var r=o.text;return Object.assign({},e,{toastText:r})}return"hideToast"===n?Object.assign({},e,{toastText:null}):e}},function(e,t,n){"use strict";var o;o=function(){return this}();try{o=o||new Function("return this")()}catch(r){"object"==typeof window&&(o=window)}e.exports=o},function(e,t,n){"use strict";var o=n(9),r=n(4),a=n(88);e.exports=!o&&!r((function(){return 7!=Object.defineProperty(a("div"),"a",{get:function(){return 7}}).a}))},function(e,t,n){"use strict";var o=n(5),r=n(89),a=o["__core-js_shared__"]||r("__core-js_shared__",{});e.exports=a},function(e,t,n){"use strict";var o=n(5),r=n(90),a=o.WeakMap;e.exports="function"==typeof a&&/native code/.test(r(a))},function(e,t,n){"use strict";var o=n(15),r=n(92),a=n(20),i=n(13);e.exports=function(e,t){for(var n=r(t),c=i.f,l=a.f,u=0;ul;)o(c,n=t[l++])&&(~a(u,n)||u.push(n));return u}},function(e,t,n){"use strict";var o=n(95);e.exports=o&&!Symbol.sham&&"symbol"==typeof Symbol()},function(e,t,n){"use strict";var o=n(9),r=n(13),a=n(8),i=n(62);e.exports=o?Object.defineProperties:function(e,t){a(e);for(var n,o=i(t),c=o.length,l=0;c>l;)r.f(e,n=o[l++],t[n]);return e}},function(e,t,n){"use strict";var o=n(36);e.exports=o("document","documentElement")},function(e,t,n){"use strict";var o=n(25),r=n(47).f,a={}.toString,i="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],c=function(e){try{return r(e)}catch(t){return i.slice()}};e.exports.f=function(e){return i&&"[object Window]"==a.call(e)?c(e):r(o(e))}},function(e,t,n){"use strict";var o=n(12);t.f=o},function(e,t,n){"use strict";var o=n(14),r=n(41),a=n(10),i=Math.min;e.exports=[].copyWithin||function(e,t){var n=o(this),c=a(n.length),l=r(e,c),u=r(t,c),d=arguments.length>2?arguments[2]:undefined,s=i((d===undefined?c:r(d,c))-u,c-l),p=1;for(u0;)u in n?n[l]=n[u]:delete n[l],l+=p,u+=p;return n}},function(e,t,n){"use strict";var o=n(52),r=n(10),a=n(48);e.exports=function i(e,t,n,c,l,u,d,s){for(var p,m=l,f=0,h=!!d&&a(d,s,3);f0&&o(p))m=i(e,t,p,r(p.length),m,u-1)-1;else{if(m>=9007199254740991)throw TypeError("Exceed the acceptable array length");e[m]=p}m++}f++}return m}},function(e,t,n){"use strict";var o=n(8);e.exports=function(e,t,n,r){try{return r?t(o(n)[0],n[1]):t(n)}catch(i){var a=e["return"];throw a!==undefined&&o(a.call(e)),i}}},function(e,t,n){"use strict";var o=n(25),r=n(44),a=n(65),i=n(35),c=n(101),l=i.set,u=i.getterFor("Array Iterator");e.exports=c(Array,"Array",(function(e,t){l(this,{type:"Array Iterator",target:o(e),index:0,kind:t})}),(function(){var e=u(this),t=e.target,n=e.kind,o=e.index++;return!t||o>=t.length?(e.target=undefined,{value:undefined,done:!0}):"keys"==n?{value:o,done:!1}:"values"==n?{value:t[o],done:!1}:{value:[o,t[o]],done:!1}}),"values"),a.Arguments=a.Array,r("keys"),r("values"),r("entries")},function(e,t,n){"use strict";var o,r,a,i=n(37),c=n(26),l=n(15),u=n(12),d=n(38),s=u("iterator"),p=!1;[].keys&&("next"in(a=[].keys())?(r=i(i(a)))!==Object.prototype&&(o=r):p=!0),o==undefined&&(o={}),d||l(o,s)||c(o,s,(function(){return this})),e.exports={IteratorPrototype:o,BUGGY_SAFARI_ITERATORS:p}},function(e,t,n){"use strict";var o=n(6);e.exports=function(e){if(!o(e)&&null!==e)throw TypeError("Can't set "+String(e)+" as a prototype");return e}},function(e,t,n){"use strict";var o=n(25),r=n(30),a=n(10),i=n(39),c=Math.min,l=[].lastIndexOf,u=!!l&&1/[1].lastIndexOf(1,-0)<0,d=i("lastIndexOf");e.exports=u||d?function(e){if(u)return l.apply(this,arguments)||0;var t=o(this),n=a(t.length),i=n-1;for(arguments.length>1&&(i=c(i,r(arguments[1]))),i<0&&(i=n+i);i>=0;i--)if(i in t&&t[i]===e)return i||0;return-1}:l},function(e,t,n){"use strict";var o=n(30),r=n(10);e.exports=function(e){if(e===undefined)return 0;var t=o(e),n=r(t);if(t!==n)throw RangeError("Wrong length or index");return n}},function(e,t,n){"use strict";var o=n(31),r=n(6),a=[].slice,i={},c=function(e,t,n){if(!(t in i)){for(var o=[],r=0;r1?arguments[1]:undefined,3);t=t?t.next:n.first;)for(o(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!g(this,e)}}),a(d.prototype,n?{get:function(e){var t=g(this,e);return t&&t.value},set:function(e,t){return C(this,0===e?0:e,t)}}:{add:function(e){return C(this,e=0===e?0:e,e)}}),s&&o(d.prototype,"size",{get:function(){return m(this).size}}),d},setStrong:function(e,t,n){var o=t+" Iterator",r=h(t),a=h(o);u(e,t,(function(e,t){f(this,{type:o,target:e,state:r(e),kind:t,last:undefined})}),(function(){for(var e=a(this),t=e.kind,n=e.last;n&&n.removed;)n=n.previous;return e.target&&(e.last=n=n?n.next:e.state.first)?"keys"==t?{value:n.key,done:!1}:"values"==t?{value:n.value,done:!1}:{value:[n.key,n.value],done:!1}:(e.target=undefined,{value:undefined,done:!0})}),n?"entries":"values",!n,!0),d(t)}}},function(e,t,n){"use strict";var o=Math.log;e.exports=Math.log1p||function(e){return(e=+e)>-1e-8&&e<1e-8?e-e*e/2:o(1+e)}},function(e,t,n){"use strict";var o=n(6),r=Math.floor;e.exports=function(e){return!o(e)&&isFinite(e)&&r(e)===e}},function(e,t,n){"use strict";var o=n(5),r=n(56).trim,a=n(81),i=o.parseInt,c=/^[+-]?0[Xx]/,l=8!==i(a+"08")||22!==i(a+"0x16");e.exports=l?function(e,t){var n=r(String(e));return i(n,t>>>0||(c.test(n)?16:10))}:i},function(e,t,n){"use strict";var o=n(9),r=n(62),a=n(25),i=n(71).f,c=function(e){return function(t){for(var n,c=a(t),l=r(c),u=l.length,d=0,s=[];u>d;)n=l[d++],o&&!i.call(c,n)||s.push(e?[n,c[n]]:c[n]);return s}};e.exports={entries:c(!0),values:c(!1)}},function(e,t,n){"use strict";e.exports=Object.is||function(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}},function(e,t,n){"use strict";var o=n(5);e.exports=o.Promise},function(e,t,n){"use strict";var o=n(73);e.exports=/(iphone|ipod|ipad).*applewebkit/i.test(o)},function(e,t,n){"use strict";var o,r,a,i,c,l,u,d,s=n(5),p=n(20).f,m=n(33),f=n(106).set,h=n(146),C=s.MutationObserver||s.WebKitMutationObserver,g=s.process,b=s.Promise,N="process"==m(g),v=p(s,"queueMicrotask"),V=v&&v.value;V||(o=function(){var e,t;for(N&&(e=g.domain)&&e.exit();r;){t=r.fn,r=r.next;try{t()}catch(n){throw r?i():a=undefined,n}}a=undefined,e&&e.enter()},N?i=function(){g.nextTick(o)}:C&&!h?(c=!0,l=document.createTextNode(""),new C(o).observe(l,{characterData:!0}),i=function(){l.data=c=!c}):b&&b.resolve?(u=b.resolve(undefined),d=u.then,i=function(){d.call(u,o)}):i=function(){f.call(s,o)}),e.exports=V||function(e){var t={fn:e,next:undefined};a&&(a.next=t),r||(r=t,i()),a=t}},function(e,t,n){"use strict";var o=n(8),r=n(6),a=n(149);e.exports=function(e,t){if(o(e),r(t)&&t.constructor===e)return t;var n=a.f(e);return(0,n.resolve)(t),n.promise}},function(e,t,n){"use strict";var o=n(31),r=function(e){var t,n;this.promise=new e((function(e,o){if(t!==undefined||n!==undefined)throw TypeError("Bad Promise constructor");t=e,n=o})),this.resolve=o(t),this.reject=o(n)};e.exports.f=function(e){return new r(e)}},function(e,t,n){"use strict";var o=n(73);e.exports=/Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(o)},function(e,t,n){"use strict";var o=n(348);e.exports=function(e,t){var n=o(e);if(n%t)throw RangeError("Wrong offset");return n}},function(e,t,n){"use strict";var o=n(14),r=n(10),a=n(99),i=n(98),c=n(48),l=n(7).aTypedArrayConstructor;e.exports=function(e){var t,n,u,d,s,p,m=o(e),f=arguments.length,h=f>1?arguments[1]:undefined,C=h!==undefined,g=a(m);if(g!=undefined&&!i(g))for(p=(s=g.call(m)).next,m=[];!(d=p.call(s)).done;)m.push(d.value);for(C&&f>2&&(h=c(h,arguments[2],2)),n=r(m.length),u=new(l(this))(n),t=0;n>t;t++)u[t]=C?h(m[t],t):m[t];return u}},function(e,t,n){"use strict";var o=n(66),r=n(50).getWeakData,a=n(8),i=n(6),c=n(55),l=n(68),u=n(18),d=n(15),s=n(35),p=s.set,m=s.getterFor,f=u.find,h=u.findIndex,C=0,g=function(e){return e.frozen||(e.frozen=new b)},b=function(){this.entries=[]},N=function(e,t){return f(e.entries,(function(e){return e[0]===t}))};b.prototype={get:function(e){var t=N(this,e);if(t)return t[1]},has:function(e){return!!N(this,e)},set:function(e,t){var n=N(this,e);n?n[1]=t:this.entries.push([e,t])},"delete":function(e){var t=h(this.entries,(function(t){return t[0]===e}));return~t&&this.entries.splice(t,1),!!~t}},e.exports={getConstructor:function(e,t,n,u){var s=e((function(e,o){c(e,s,t),p(e,{type:t,id:C++,frozen:undefined}),o!=undefined&&l(o,e[u],e,n)})),f=m(t),h=function(e,t,n){var o=f(e),i=r(a(t),!0);return!0===i?g(o).set(t,n):i[o.id]=n,e};return o(s.prototype,{"delete":function(e){var t=f(this);if(!i(e))return!1;var n=r(e);return!0===n?g(t)["delete"](e):n&&d(n,t.id)&&delete n[t.id]},has:function(e){var t=f(this);if(!i(e))return!1;var n=r(e);return!0===n?g(t).has(e):n&&d(n,t.id)}}),o(s.prototype,n?{get:function(e){var t=f(this);if(i(e)){var n=r(e);return!0===n?g(t).get(e):n?n[t.id]:undefined}},set:function(e,t){return h(this,e,t)}}:{add:function(e){return h(this,e,!0)}}),s}}},function(e,t,n){"use strict";t.__esModule=!0,t.setupHotReloading=t.sendLogEntry=void 0;t.sendLogEntry=function(e,t){};t.setupHotReloading=function(){0}},function(e,t,n){"use strict";t.__esModule=!0,t.resizeStartHandler=t.dragStartHandler=t.setupDrag=void 0;var o,r,a,i,c,l=n(156),u=n(16),d=(0,n(51).createLogger)("drag"),s=!1,p=!1,m=[0,0],f=function(e){return(0,u.winget)(e,"pos").then((function(e){return[e.x,e.y]}))},h=function(e,t){return(0,u.winset)(e,"pos",t[0]+","+t[1])},C=function(e){var t,n,r,a;return regeneratorRuntime.async((function(i){for(;;)switch(i.prev=i.next){case 0:return d.log("setting up"),o=e.config.window,i.next=4,regeneratorRuntime.awrap(f(o));case 4:t=i.sent,m=[t[0]-window.screenLeft,t[1]-window.screenTop],n=g(t),r=n[0],a=n[1],r&&h(o,a),d.debug("current state",{ref:o,screenOffset:m});case 9:case"end":return i.stop()}}))};t.setupDrag=C;var g=function(e){var t=e[0],n=e[1],o=!1;return t<0?(t=0,o=!0):t+window.innerWidth>window.screen.availWidth&&(t=window.screen.availWidth-window.innerWidth,o=!0),n<0?(n=0,o=!0):n+window.innerHeight>window.screen.availHeight&&(n=window.screen.availHeight-window.innerHeight,o=!0),[o,[t,n]]};t.dragStartHandler=function(e){d.log("drag start"),s=!0,r=[window.screenLeft-e.screenX,window.screenTop-e.screenY],document.addEventListener("mousemove",N),document.addEventListener("mouseup",b),N(e)};var b=function y(e){d.log("drag end"),N(e),document.removeEventListener("mousemove",N),document.removeEventListener("mouseup",y),s=!1},N=function(e){s&&(e.preventDefault(),h(o,(0,l.vecAdd)([e.screenX,e.screenY],m,r)))};t.resizeStartHandler=function(e,t){return function(n){a=[e,t],d.log("resize start",a),p=!0,r=[window.screenLeft-n.screenX,window.screenTop-n.screenY],i=[window.innerWidth,window.innerHeight],document.addEventListener("mousemove",V),document.addEventListener("mouseup",v),V(n)}};var v=function _(e){d.log("resize end",c),V(e),document.removeEventListener("mousemove",V),document.removeEventListener("mouseup",_),p=!1},V=function(e){p&&(e.preventDefault(),(c=(0,l.vecAdd)(i,(0,l.vecMultiply)(a,(0,l.vecAdd)([e.screenX,e.screenY],(0,l.vecInverse)([window.screenLeft,window.screenTop]),r,[1,1]))))[0]=Math.max(c[0],250),c[1]=Math.max(c[1],120),function(e,t){(0,u.winset)(e,"size",t[0]+","+t[1])}(o,c))}},function(e,t,n){"use strict";t.__esModule=!0,t.vecNormalize=t.vecLength=t.vecInverse=t.vecScale=t.vecDivide=t.vecMultiply=t.vecSubtract=t.vecAdd=t.vecCreate=void 0;var o=n(24);t.vecCreate=function(){for(var e=arguments.length,t=new Array(e),n=0;n35;return(0,o.createVNode)(1,"div",(0,r.classes)(["Tooltip",i&&"Tooltip--long",a&&"Tooltip--"+a]),null,1,{"data-tooltip":t})}},function(e,t,n){"use strict";t.__esModule=!0,t.Input=void 0;var o=n(0),r=n(11),a=n(19);function i(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var c=function(e){return(0,r.isFalsy)(e)?"":e},l=function(e){var t,n;function l(){var t;return(t=e.call(this)||this).inputRef=(0,o.createRef)(),t.state={editing:!1},t.handleInput=function(e){var n=t.state.editing,o=t.props.onInput;n||t.setEditing(!0),o&&o(e,e.target.value)},t.handleFocus=function(e){t.state.editing||t.setEditing(!0)},t.handleBlur=function(e){var n=t.state.editing,o=t.props.onChange;n&&(t.setEditing(!1),o&&o(e,e.target.value))},t.handleKeyDown=function(e){var n=t.props,o=n.onInput,r=n.onChange,a=n.onEnter;return 13===e.keyCode?(t.setEditing(!1),r&&r(e,e.target.value),o&&o(e,e.target.value),a&&a(e,e.target.value),void(t.props.selfClear?e.target.value="":e.target.blur())):27===e.keyCode?(t.setEditing(!1),e.target.value=c(t.props.value),void e.target.blur()):void 0},t}n=e,(t=l).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var u=l.prototype;return u.componentDidMount=function(){var e=this.props.value,t=this.inputRef.current;t&&(t.value=c(e))},u.componentDidUpdate=function(e,t){var n=this.state.editing,o=e.value,r=this.props.value,a=this.inputRef.current;a&&!n&&o!==r&&(a.value=c(r))},u.setEditing=function(e){this.setState({editing:e})},u.render=function(){var e=this.props,t=(e.selfClear,e.onInput,e.onChange,e.onEnter,e.value,e.maxLength),n=e.placeholder,c=i(e,["selfClear","onInput","onChange","onEnter","value","maxLength","placeholder"]),l=c.className,u=c.fluid,d=i(c,["className","fluid"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({className:(0,r.classes)(["Input",u&&"Input--fluid",l])},d,{children:[(0,o.createVNode)(1,"div","Input__baseline",".",16),(0,o.createVNode)(64,"input","Input__input",null,1,{placeholder:n,onInput:this.handleInput,onFocus:this.handleFocus,onBlur:this.handleBlur,onKeyDown:this.handleKeyDown,maxLength:t},null,this.inputRef)]})))},l}(o.Component);t.Input=l},function(e,t,n){"use strict";t.__esModule=!0,t.GridColumn=t.Grid=void 0;var o=n(0),r=n(162),a=n(11);function i(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var c=function(e){var t=e.children,n=i(e,["children"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,r.Table,Object.assign({},n,{children:(0,o.createComponentVNode)(2,r.Table.Row,{children:t})})))};t.Grid=c,c.defaultHooks=a.pureComponentHooks;var l=function(e){var t=e.size,n=void 0===t?1:t,a=e.style,c=i(e,["size","style"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,r.Table.Cell,Object.assign({style:Object.assign({width:n+"%"},a)},c)))};t.GridColumn=l,c.defaultHooks=a.pureComponentHooks,c.Column=l},function(e,t,n){"use strict";t.__esModule=!0,t.TableCell=t.TableRow=t.Table=void 0;var o=n(0),r=n(11),a=n(19);function i(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var c=function(e){var t=e.collapsing,n=e.className,c=e.content,l=e.children,u=i(e,["collapsing","className","content","children"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({as:"table",className:(0,r.classes)(["Table",t&&"Table--collapsing",n])},u,{children:(0,o.createVNode)(1,"tbody",null,[c,l],0)})))};t.Table=c,c.defaultHooks=r.pureComponentHooks;var l=function(e){var t=e.className,n=e.header,c=i(e,["className","header"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({as:"tr",className:(0,r.classes)(["Table__row",n&&"Table__row--header",t])},c)))};t.TableRow=l,l.defaultHooks=r.pureComponentHooks;var u=function(e){var t=e.className,n=e.collapsing,c=e.header,l=i(e,["className","collapsing","header"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({as:"td",className:(0,r.classes)(["Table__cell",n&&"Table__cell--collapsing",c&&"Table__cell--header",t])},l)))};t.TableCell=u,u.defaultHooks=r.pureComponentHooks,c.Row=l,c.Cell=u},function(e,t,n){"use strict";t.__esModule=!0,t.LabeledListDivider=t.LabeledListItem=t.LabeledList=void 0;var o=n(0),r=n(11),a=n(19),i=function(e){var t=e.children;return(0,o.createVNode)(1,"table","LabeledList",t,0)};t.LabeledList=i,i.defaultHooks=r.pureComponentHooks;var c=function(e){var t=e.className,n=e.label,i=e.labelColor,c=void 0===i?"label":i,l=e.color,u=e.buttons,d=e.content,s=e.children;return(0,o.createVNode)(1,"tr",(0,r.classes)(["LabeledList__row",t]),[(0,o.createComponentVNode)(2,a.Box,{as:"td",color:c,className:(0,r.classes)(["LabeledList__cell","LabeledList__label"]),content:n+":"}),(0,o.createComponentVNode)(2,a.Box,{as:"td",color:l,className:(0,r.classes)(["LabeledList__cell","LabeledList__content"]),colSpan:u?undefined:2,children:[d,s]}),u&&(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__buttons",u,0)],0)};t.LabeledListItem=c,c.defaultHooks=r.pureComponentHooks;var l=function(e){var t=e.size,n=void 0===t?1:t;return(0,o.createVNode)(1,"tr","LabeledList__row",(0,o.createVNode)(1,"td",null,null,1,{style:{"padding-bottom":(0,a.unit)(n)}}),2)};t.LabeledListDivider=l,l.defaultHooks=r.pureComponentHooks,i.Item=c,i.Divider=l},function(e,t,n){"use strict";t.__esModule=!0,t.BeakerContents=void 0;var o=n(0),r=n(2);t.BeakerContents=function(e){var t=e.beakerLoaded,n=e.beakerContents;return(0,o.createComponentVNode)(2,r.Box,{children:[!t&&(0,o.createComponentVNode)(2,r.Box,{color:"label",children:"No beaker loaded."})||0===n.length&&(0,o.createComponentVNode)(2,r.Box,{color:"label",children:"Beaker is empty."}),n.map((function(e){return(0,o.createComponentVNode)(2,r.Box,{color:"label",children:[e.volume," units of ",e.name,", Purity: ",e.purity]},e.name)}))]})}},function(e,t,n){n(166),n(167),n(168),n(169),n(170),n(171),e.exports=n(172)},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n(173),n(174),n(175),n(176),n(177),n(178),n(179),n(180),n(181),n(182),n(183),n(184),n(185),n(186),n(187),n(188),n(189),n(190),n(191),n(192),n(193),n(194),n(195),n(196),n(198),n(200),n(201),n(202),n(133),n(204),n(205),n(206),n(207),n(208),n(209),n(210),n(211),n(212),n(213),n(214),n(215),n(216),n(217),n(219),n(220),n(221),n(222),n(223),n(225),n(226),n(228),n(229),n(230),n(231),n(232),n(233),n(234),n(235),n(236),n(237),n(238),n(239),n(240),n(241),n(243),n(244),n(245),n(246),n(247),n(248),n(249),n(250),n(251),n(252),n(253),n(254),n(255),n(257),n(258),n(259),n(260),n(261),n(262),n(264),n(265),n(267),n(269),n(270),n(271),n(272),n(273),n(274),n(275),n(276),n(277),n(278),n(279),n(280),n(281),n(282),n(283),n(284),n(285),n(286),n(287),n(288),n(289),n(290),n(291),n(293),n(294),n(295),n(298),n(299),n(300),n(301),n(302),n(303),n(304),n(305),n(306),n(307),n(308),n(309),n(310),n(311),n(312),n(313),n(314),n(315),n(316),n(317),n(318),n(319),n(320),n(321),n(322),n(323),n(324),n(325),n(326),n(327),n(328),n(329),n(330),n(331),n(332),n(333),n(334),n(335),n(336),n(337),n(338),n(339),n(340),n(341),n(342),n(343),n(344),n(345),n(346),n(347),n(349),n(350),n(351),n(352),n(353),n(354),n(355),n(356),n(357),n(358),n(359),n(360),n(361),n(362),n(363),n(364),n(365),n(366),n(367),n(368),n(369),n(370),n(371),n(372),n(373),n(374),n(375),n(376),n(377),n(378),n(379),n(380),n(381),n(382),n(383),n(384),n(385),n(386);var o=n(0);n(388),n(389);var r=n(390),a=(n(154),n(3)),i=n(16),c=n(155),l=n(51),u=n(157),d=n(513),s=(0,l.createLogger)(),p=(0,d.createStore)(),m=document.getElementById("react-root"),f=!0,h=!1,C=function(){for(p.subscribe((function(){!function(){if(!h){0;try{var e=p.getState();if(f){if(s.log("initial render",e),!(0,u.getRoute)(e)){if(s.info("loading old tgui"),h=!0,window.update=window.initialize=function(){},i.tridentVersion<=4)return void setTimeout((function(){location.href="tgui-fallback.html?ref="+window.__ref__}),10);document.getElementById("data").textContent=JSON.stringify(e),(0,r.loadCSS)("v4shim.css"),(0,r.loadCSS)("tgui.css");var t=document.getElementsByTagName("head")[0],a=document.createElement("script");return a.type="text/javascript",a.src="tgui.js",void t.appendChild(a)}(0,c.setupDrag)(e)}var l=n(515).Layout,d=(0,o.createComponentVNode)(2,l,{state:e,dispatch:p.dispatch});(0,o.render)(d,m)}catch(C){s.error("rendering error",C)}f&&(f=!1)}}()})),window.update=window.initialize=function(e){var t=function(e){var t=function(e,t){return"object"==typeof t&&null!==t&&t.__number__?parseFloat(t.__number__):t};i.tridentVersion<=4&&(t=undefined);try{return JSON.parse(e,t)}catch(o){s.log(o),s.log("What we got:",e);var n=o&&o.message;throw new Error("JSON parsing error: "+n)}}(e);p.dispatch((0,a.backendUpdate)(t))};;){var e=window.__updateQueue__.shift();if(!e)break;window.update(e)}(0,r.loadCSS)("font-awesome.css")};i.tridentVersion<=4&&"loading"===document.readyState?document.addEventListener("DOMContentLoaded",C):C()},function(e,t,n){"use strict";var o=n(1),r=n(5),a=n(36),i=n(38),c=n(9),l=n(95),u=n(125),d=n(4),s=n(15),p=n(52),m=n(6),f=n(8),h=n(14),C=n(25),g=n(34),b=n(46),N=n(42),v=n(62),V=n(47),y=n(128),_=n(94),k=n(20),x=n(13),L=n(71),w=n(26),B=n(22),S=n(91),I=n(72),T=n(59),A=n(58),E=n(12),P=n(129),M=n(27),O=n(43),R=n(35),F=n(18).forEach,D=I("hidden"),j=E("toPrimitive"),z=R.set,H=R.getterFor("Symbol"),G=Object.prototype,U=r.Symbol,K=a("JSON","stringify"),Y=k.f,q=x.f,W=y.f,$=L.f,Q=S("symbols"),X=S("op-symbols"),Z=S("string-to-symbol-registry"),J=S("symbol-to-string-registry"),ee=S("wks"),te=r.QObject,ne=!te||!te.prototype||!te.prototype.findChild,oe=c&&d((function(){return 7!=N(q({},"a",{get:function(){return q(this,"a",{value:7}).a}})).a}))?function(e,t,n){var o=Y(G,t);o&&delete G[t],q(e,t,n),o&&e!==G&&q(G,t,o)}:q,re=function(e,t){var n=Q[e]=N(U.prototype);return z(n,{type:"Symbol",tag:e,description:t}),c||(n.description=t),n},ae=l&&"symbol"==typeof U.iterator?function(e){return"symbol"==typeof e}:function(e){return Object(e)instanceof U},ie=function(e,t,n){e===G&&ie(X,t,n),f(e);var o=g(t,!0);return f(n),s(Q,o)?(n.enumerable?(s(e,D)&&e[D][o]&&(e[D][o]=!1),n=N(n,{enumerable:b(0,!1)})):(s(e,D)||q(e,D,b(1,{})),e[D][o]=!0),oe(e,o,n)):q(e,o,n)},ce=function(e,t){f(e);var n=C(t),o=v(n).concat(pe(n));return F(o,(function(t){c&&!ue.call(n,t)||ie(e,t,n[t])})),e},le=function(e,t){return t===undefined?N(e):ce(N(e),t)},ue=function(e){var t=g(e,!0),n=$.call(this,t);return!(this===G&&s(Q,t)&&!s(X,t))&&(!(n||!s(this,t)||!s(Q,t)||s(this,D)&&this[D][t])||n)},de=function(e,t){var n=C(e),o=g(t,!0);if(n!==G||!s(Q,o)||s(X,o)){var r=Y(n,o);return!r||!s(Q,o)||s(n,D)&&n[D][o]||(r.enumerable=!0),r}},se=function(e){var t=W(C(e)),n=[];return F(t,(function(e){s(Q,e)||s(T,e)||n.push(e)})),n},pe=function(e){var t=e===G,n=W(t?X:C(e)),o=[];return F(n,(function(e){!s(Q,e)||t&&!s(G,e)||o.push(Q[e])})),o};(l||(B((U=function(){if(this instanceof U)throw TypeError("Symbol is not a constructor");var e=arguments.length&&arguments[0]!==undefined?String(arguments[0]):undefined,t=A(e),n=function o(e){this===G&&o.call(X,e),s(this,D)&&s(this[D],t)&&(this[D][t]=!1),oe(this,t,b(1,e))};return c&&ne&&oe(G,t,{configurable:!0,set:n}),re(t,e)}).prototype,"toString",(function(){return H(this).tag})),L.f=ue,x.f=ie,k.f=de,V.f=y.f=se,_.f=pe,c&&(q(U.prototype,"description",{configurable:!0,get:function(){return H(this).description}}),i||B(G,"propertyIsEnumerable",ue,{unsafe:!0}))),u||(P.f=function(e){return re(E(e),e)}),o({global:!0,wrap:!0,forced:!l,sham:!l},{Symbol:U}),F(v(ee),(function(e){M(e)})),o({target:"Symbol",stat:!0,forced:!l},{"for":function(e){var t=String(e);if(s(Z,t))return Z[t];var n=U(t);return Z[t]=n,J[n]=t,n},keyFor:function(e){if(!ae(e))throw TypeError(e+" is not a symbol");if(s(J,e))return J[e]},useSetter:function(){ne=!0},useSimple:function(){ne=!1}}),o({target:"Object",stat:!0,forced:!l,sham:!c},{create:le,defineProperty:ie,defineProperties:ce,getOwnPropertyDescriptor:de}),o({target:"Object",stat:!0,forced:!l},{getOwnPropertyNames:se,getOwnPropertySymbols:pe}),o({target:"Object",stat:!0,forced:d((function(){_.f(1)}))},{getOwnPropertySymbols:function(e){return _.f(h(e))}}),K)&&o({target:"JSON",stat:!0,forced:!l||d((function(){var e=U();return"[null]"!=K([e])||"{}"!=K({a:e})||"{}"!=K(Object(e))}))},{stringify:function(e,t,n){for(var o,r=[e],a=1;arguments.length>a;)r.push(arguments[a++]);if(o=t,(m(t)||e!==undefined)&&!ae(e))return p(t)||(t=function(e,t){if("function"==typeof o&&(t=o.call(this,e,t)),!ae(t))return t}),r[1]=t,K.apply(null,r)}});U.prototype[j]||w(U.prototype,j,U.prototype.valueOf),O(U,"Symbol"),T[D]=!0},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(5),i=n(15),c=n(6),l=n(13).f,u=n(122),d=a.Symbol;if(r&&"function"==typeof d&&(!("description"in d.prototype)||d().description!==undefined)){var s={},p=function(){var e=arguments.length<1||arguments[0]===undefined?undefined:String(arguments[0]),t=this instanceof p?new d(e):e===undefined?d():d(e);return""===e&&(s[t]=!0),t};u(p,d);var m=p.prototype=d.prototype;m.constructor=p;var f=m.toString,h="Symbol(test)"==String(d("test")),C=/^Symbol\((.*)\)[^)]+$/;l(m,"description",{configurable:!0,get:function(){var e=c(this)?this.valueOf():this,t=f.call(e);if(i(s,e))return"";var n=h?t.slice(7,-1):t.replace(C,"$1");return""===n?undefined:n}}),o({global:!0,forced:!0},{Symbol:p})}},function(e,t,n){"use strict";n(27)("asyncIterator")},function(e,t,n){"use strict";n(27)("hasInstance")},function(e,t,n){"use strict";n(27)("isConcatSpreadable")},function(e,t,n){"use strict";n(27)("iterator")},function(e,t,n){"use strict";n(27)("match")},function(e,t,n){"use strict";n(27)("replace")},function(e,t,n){"use strict";n(27)("search")},function(e,t,n){"use strict";n(27)("species")},function(e,t,n){"use strict";n(27)("split")},function(e,t,n){"use strict";n(27)("toPrimitive")},function(e,t,n){"use strict";n(27)("toStringTag")},function(e,t,n){"use strict";n(27)("unscopables")},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(52),i=n(6),c=n(14),l=n(10),u=n(49),d=n(63),s=n(64),p=n(12),m=n(96),f=p("isConcatSpreadable"),h=9007199254740991,C="Maximum allowed index exceeded",g=m>=51||!r((function(){var e=[];return e[f]=!1,e.concat()[0]!==e})),b=s("concat"),N=function(e){if(!i(e))return!1;var t=e[f];return t!==undefined?!!t:a(e)};o({target:"Array",proto:!0,forced:!g||!b},{concat:function(e){var t,n,o,r,a,i=c(this),s=d(i,0),p=0;for(t=-1,o=arguments.length;th)throw TypeError(C);for(n=0;n=h)throw TypeError(C);u(s,p++,a)}return s.length=p,s}})},function(e,t,n){"use strict";var o=n(1),r=n(130),a=n(44);o({target:"Array",proto:!0},{copyWithin:r}),a("copyWithin")},function(e,t,n){"use strict";var o=n(1),r=n(18).every;o({target:"Array",proto:!0,forced:n(39)("every")},{every:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(97),a=n(44);o({target:"Array",proto:!0},{fill:r}),a("fill")},function(e,t,n){"use strict";var o=n(1),r=n(18).filter,a=n(4),i=n(64)("filter"),c=i&&!a((function(){[].filter.call({length:-1,0:1},(function(e){throw e}))}));o({target:"Array",proto:!0,forced:!i||!c},{filter:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(18).find,a=n(44),i=!0;"find"in[]&&Array(1).find((function(){i=!1})),o({target:"Array",proto:!0,forced:i},{find:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}}),a("find")},function(e,t,n){"use strict";var o=n(1),r=n(18).findIndex,a=n(44),i=!0;"findIndex"in[]&&Array(1).findIndex((function(){i=!1})),o({target:"Array",proto:!0,forced:i},{findIndex:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}}),a("findIndex")},function(e,t,n){"use strict";var o=n(1),r=n(131),a=n(14),i=n(10),c=n(30),l=n(63);o({target:"Array",proto:!0},{flat:function(){var e=arguments.length?arguments[0]:undefined,t=a(this),n=i(t.length),o=l(t,0);return o.length=r(o,t,t,n,0,e===undefined?1:c(e)),o}})},function(e,t,n){"use strict";var o=n(1),r=n(131),a=n(14),i=n(10),c=n(31),l=n(63);o({target:"Array",proto:!0},{flatMap:function(e){var t,n=a(this),o=i(n.length);return c(e),(t=l(n,0)).length=r(t,n,n,o,0,1,e,arguments.length>1?arguments[1]:undefined),t}})},function(e,t,n){"use strict";var o=n(1),r=n(197);o({target:"Array",proto:!0,forced:[].forEach!=r},{forEach:r})},function(e,t,n){"use strict";var o=n(18).forEach,r=n(39);e.exports=r("forEach")?function(e){return o(this,e,arguments.length>1?arguments[1]:undefined)}:[].forEach},function(e,t,n){"use strict";var o=n(1),r=n(199);o({target:"Array",stat:!0,forced:!n(75)((function(e){Array.from(e)}))},{from:r})},function(e,t,n){"use strict";var o=n(48),r=n(14),a=n(132),i=n(98),c=n(10),l=n(49),u=n(99);e.exports=function(e){var t,n,d,s,p,m=r(e),f="function"==typeof this?this:Array,h=arguments.length,C=h>1?arguments[1]:undefined,g=C!==undefined,b=0,N=u(m);if(g&&(C=o(C,h>2?arguments[2]:undefined,2)),N==undefined||f==Array&&i(N))for(n=new f(t=c(m.length));t>b;b++)l(n,b,g?C(m[b],b):m[b]);else for(p=(s=N.call(m)).next,n=new f;!(d=p.call(s)).done;b++)l(n,b,g?a(s,C,[d.value,b],!0):d.value);return n.length=b,n}},function(e,t,n){"use strict";var o=n(1),r=n(60).includes,a=n(44);o({target:"Array",proto:!0},{includes:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}}),a("includes")},function(e,t,n){"use strict";var o=n(1),r=n(60).indexOf,a=n(39),i=[].indexOf,c=!!i&&1/[1].indexOf(1,-0)<0,l=a("indexOf");o({target:"Array",proto:!0,forced:c||l},{indexOf:function(e){return c?i.apply(this,arguments)||0:r(this,e,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";n(1)({target:"Array",stat:!0},{isArray:n(52)})},function(e,t,n){"use strict";var o=n(134).IteratorPrototype,r=n(42),a=n(46),i=n(43),c=n(65),l=function(){return this};e.exports=function(e,t,n){var u=t+" Iterator";return e.prototype=r(o,{next:a(1,n)}),i(e,u,!1,!0),c[u]=l,e}},function(e,t,n){"use strict";var o=n(1),r=n(57),a=n(25),i=n(39),c=[].join,l=r!=Object,u=i("join",",");o({target:"Array",proto:!0,forced:l||u},{join:function(e){return c.call(a(this),e===undefined?",":e)}})},function(e,t,n){"use strict";var o=n(1),r=n(136);o({target:"Array",proto:!0,forced:r!==[].lastIndexOf},{lastIndexOf:r})},function(e,t,n){"use strict";var o=n(1),r=n(18).map,a=n(4),i=n(64)("map"),c=i&&!a((function(){[].map.call({length:-1,0:1},(function(e){throw e}))}));o({target:"Array",proto:!0,forced:!i||!c},{map:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(49);o({target:"Array",stat:!0,forced:r((function(){function e(){}return!(Array.of.call(e)instanceof e)}))},{of:function(){for(var e=0,t=arguments.length,n=new("function"==typeof this?this:Array)(t);t>e;)a(n,e,arguments[e++]);return n.length=t,n}})},function(e,t,n){"use strict";var o=n(1),r=n(76).left;o({target:"Array",proto:!0,forced:n(39)("reduce")},{reduce:function(e){return r(this,e,arguments.length,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(76).right;o({target:"Array",proto:!0,forced:n(39)("reduceRight")},{reduceRight:function(e){return r(this,e,arguments.length,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(6),a=n(52),i=n(41),c=n(10),l=n(25),u=n(49),d=n(64),s=n(12)("species"),p=[].slice,m=Math.max;o({target:"Array",proto:!0,forced:!d("slice")},{slice:function(e,t){var n,o,d,f=l(this),h=c(f.length),C=i(e,h),g=i(t===undefined?h:t,h);if(a(f)&&("function"!=typeof(n=f.constructor)||n!==Array&&!a(n.prototype)?r(n)&&null===(n=n[s])&&(n=undefined):n=undefined,n===Array||n===undefined))return p.call(f,C,g);for(o=new(n===undefined?Array:n)(m(g-C,0)),d=0;C1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(31),a=n(14),i=n(4),c=n(39),l=[],u=l.sort,d=i((function(){l.sort(undefined)})),s=i((function(){l.sort(null)})),p=c("sort");o({target:"Array",proto:!0,forced:d||!s||p},{sort:function(e){return e===undefined?u.call(a(this)):u.call(a(this),r(e))}})},function(e,t,n){"use strict";n(54)("Array")},function(e,t,n){"use strict";var o=n(1),r=n(41),a=n(30),i=n(10),c=n(14),l=n(63),u=n(49),d=n(64),s=Math.max,p=Math.min,m=9007199254740991,f="Maximum allowed length exceeded";o({target:"Array",proto:!0,forced:!d("splice")},{splice:function(e,t){var n,o,d,h,C,g,b=c(this),N=i(b.length),v=r(e,N),V=arguments.length;if(0===V?n=o=0:1===V?(n=0,o=N-v):(n=V-2,o=p(s(a(t),0),N-v)),N+n-o>m)throw TypeError(f);for(d=l(b,o),h=0;hN-o+n;h--)delete b[h-1]}else if(n>o)for(h=N-o;h>v;h--)g=h+n-1,(C=h+o-1)in b?b[g]=b[C]:delete b[g];for(h=0;h>1,h=23===t?r(2,-24)-r(2,-77):0,C=e<0||0===e&&1/e<0?1:0,g=0;for((e=o(e))!=e||e===1/0?(u=e!=e?1:0,l=m):(l=a(i(e)/c),e*(d=r(2,-l))<1&&(l--,d*=2),(e+=l+f>=1?h/d:h*r(2,1-f))*d>=2&&(l++,d/=2),l+f>=m?(u=0,l=m):l+f>=1?(u=(e*d-1)*r(2,t),l+=f):(u=e*r(2,f-1)*r(2,t),l=0));t>=8;s[g++]=255&u,u/=256,t-=8);for(l=l<0;s[g++]=255&l,l/=256,p-=8);return s[--g]|=128*C,s},unpack:function(e,t){var n,o=e.length,a=8*o-t-1,i=(1<>1,l=a-7,u=o-1,d=e[u--],s=127&d;for(d>>=7;l>0;s=256*s+e[u],u--,l-=8);for(n=s&(1<<-l)-1,s>>=-l,l+=t;l>0;n=256*n+e[u],u--,l-=8);if(0===s)s=1-c;else{if(s===i)return n?NaN:d?-1/0:1/0;n+=r(2,t),s-=c}return(d?-1:1)*n*r(2,s-t)}}},function(e,t,n){"use strict";var o=n(1),r=n(7);o({target:"ArrayBuffer",stat:!0,forced:!r.NATIVE_ARRAY_BUFFER_VIEWS},{isView:r.isView})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(77),i=n(8),c=n(41),l=n(10),u=n(45),d=a.ArrayBuffer,s=a.DataView,p=d.prototype.slice;o({target:"ArrayBuffer",proto:!0,unsafe:!0,forced:r((function(){return!new d(2).slice(1,undefined).byteLength}))},{slice:function(e,t){if(p!==undefined&&t===undefined)return p.call(i(this),e);for(var n=i(this).byteLength,o=c(e,n),r=c(t===undefined?n:t,n),a=new(u(this,d))(l(r-o)),m=new s(this),f=new s(a),h=0;o9999?"+":"";return n+r(a(e),n?6:4,0)+"-"+r(this.getUTCMonth()+1,2,0)+"-"+r(this.getUTCDate(),2,0)+"T"+r(this.getUTCHours(),2,0)+":"+r(this.getUTCMinutes(),2,0)+":"+r(this.getUTCSeconds(),2,0)+"."+r(t,3,0)+"Z"}:l},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(14),i=n(34);o({target:"Date",proto:!0,forced:r((function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})}))},{toJSON:function(e){var t=a(this),n=i(t);return"number"!=typeof n||isFinite(n)?t.toISOString():null}})},function(e,t,n){"use strict";var o=n(26),r=n(227),a=n(12)("toPrimitive"),i=Date.prototype;a in i||o(i,a,r)},function(e,t,n){"use strict";var o=n(8),r=n(34);e.exports=function(e){if("string"!==e&&"number"!==e&&"default"!==e)throw TypeError("Incorrect hint");return r(o(this),"number"!==e)}},function(e,t,n){"use strict";var o=n(22),r=Date.prototype,a="Invalid Date",i=r.toString,c=r.getTime;new Date(NaN)+""!=a&&o(r,"toString",(function(){var e=c.call(this);return e==e?i.call(this):a}))},function(e,t,n){"use strict";n(1)({target:"Function",proto:!0},{bind:n(138)})},function(e,t,n){"use strict";var o=n(6),r=n(13),a=n(37),i=n(12)("hasInstance"),c=Function.prototype;i in c||r.f(c,i,{value:function(e){if("function"!=typeof this||!o(e))return!1;if(!o(this.prototype))return e instanceof this;for(;e=a(e);)if(this.prototype===e)return!0;return!1}})},function(e,t,n){"use strict";var o=n(9),r=n(13).f,a=Function.prototype,i=a.toString,c=/^\s*function ([^ (]*)/;!o||"name"in a||r(a,"name",{configurable:!0,get:function(){try{return i.call(this).match(c)[1]}catch(e){return""}}})},function(e,t,n){"use strict";var o=n(5);n(43)(o.JSON,"JSON",!0)},function(e,t,n){"use strict";var o=n(78),r=n(139);e.exports=o("Map",(function(e){return function(){return e(this,arguments.length?arguments[0]:undefined)}}),r)},function(e,t,n){"use strict";var o=n(1),r=n(140),a=Math.acosh,i=Math.log,c=Math.sqrt,l=Math.LN2;o({target:"Math",stat:!0,forced:!a||710!=Math.floor(a(Number.MAX_VALUE))||a(Infinity)!=Infinity},{acosh:function(e){return(e=+e)<1?NaN:e>94906265.62425156?i(e)+l:r(e-1+c(e-1)*c(e+1))}})},function(e,t,n){"use strict";var o=n(1),r=Math.asinh,a=Math.log,i=Math.sqrt;o({target:"Math",stat:!0,forced:!(r&&1/r(0)>0)},{asinh:function c(e){return isFinite(e=+e)&&0!=e?e<0?-c(-e):a(e+i(e*e+1)):e}})},function(e,t,n){"use strict";var o=n(1),r=Math.atanh,a=Math.log;o({target:"Math",stat:!0,forced:!(r&&1/r(-0)<0)},{atanh:function(e){return 0==(e=+e)?e:a((1+e)/(1-e))/2}})},function(e,t,n){"use strict";var o=n(1),r=n(105),a=Math.abs,i=Math.pow;o({target:"Math",stat:!0},{cbrt:function(e){return r(e=+e)*i(a(e),1/3)}})},function(e,t,n){"use strict";var o=n(1),r=Math.floor,a=Math.log,i=Math.LOG2E;o({target:"Math",stat:!0},{clz32:function(e){return(e>>>=0)?31-r(a(e+.5)*i):32}})},function(e,t,n){"use strict";var o=n(1),r=n(80),a=Math.cosh,i=Math.abs,c=Math.E;o({target:"Math",stat:!0,forced:!a||a(710)===Infinity},{cosh:function(e){var t=r(i(e)-1)+1;return(t+1/(t*c*c))*(c/2)}})},function(e,t,n){"use strict";var o=n(1),r=n(80);o({target:"Math",stat:!0,forced:r!=Math.expm1},{expm1:r})},function(e,t,n){"use strict";n(1)({target:"Math",stat:!0},{fround:n(242)})},function(e,t,n){"use strict";var o=n(105),r=Math.abs,a=Math.pow,i=a(2,-52),c=a(2,-23),l=a(2,127)*(2-c),u=a(2,-126),d=function(e){return e+1/i-1/i};e.exports=Math.fround||function(e){var t,n,a=r(e),s=o(e);return al||n!=n?s*Infinity:s*n}},function(e,t,n){"use strict";var o=n(1),r=Math.hypot,a=Math.abs,i=Math.sqrt;o({target:"Math",stat:!0,forced:!!r&&r(Infinity,NaN)!==Infinity},{hypot:function(e,t){for(var n,o,r=0,c=0,l=arguments.length,u=0;c0?(o=n/u)*o:n;return u===Infinity?Infinity:u*i(r)}})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=Math.imul;o({target:"Math",stat:!0,forced:r((function(){return-5!=a(4294967295,5)||2!=a.length}))},{imul:function(e,t){var n=+e,o=+t,r=65535&n,a=65535&o;return 0|r*a+((65535&n>>>16)*a+r*(65535&o>>>16)<<16>>>0)}})},function(e,t,n){"use strict";var o=n(1),r=Math.log,a=Math.LOG10E;o({target:"Math",stat:!0},{log10:function(e){return r(e)*a}})},function(e,t,n){"use strict";n(1)({target:"Math",stat:!0},{log1p:n(140)})},function(e,t,n){"use strict";var o=n(1),r=Math.log,a=Math.LN2;o({target:"Math",stat:!0},{log2:function(e){return r(e)/a}})},function(e,t,n){"use strict";n(1)({target:"Math",stat:!0},{sign:n(105)})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(80),i=Math.abs,c=Math.exp,l=Math.E;o({target:"Math",stat:!0,forced:r((function(){return-2e-17!=Math.sinh(-2e-17)}))},{sinh:function(e){return i(e=+e)<1?(a(e)-a(-e))/2:(c(e-1)-c(-e-1))*(l/2)}})},function(e,t,n){"use strict";var o=n(1),r=n(80),a=Math.exp;o({target:"Math",stat:!0},{tanh:function(e){var t=r(e=+e),n=r(-e);return t==Infinity?1:n==Infinity?-1:(t-n)/(a(e)+a(-e))}})},function(e,t,n){"use strict";n(43)(Math,"Math",!0)},function(e,t,n){"use strict";var o=n(1),r=Math.ceil,a=Math.floor;o({target:"Math",stat:!0},{trunc:function(e){return(e>0?a:r)(e)}})},function(e,t,n){"use strict";var o=n(9),r=n(5),a=n(61),i=n(22),c=n(15),l=n(33),u=n(79),d=n(34),s=n(4),p=n(42),m=n(47).f,f=n(20).f,h=n(13).f,C=n(56).trim,g="Number",b=r[g],N=b.prototype,v=l(p(N))==g,V=function(e){var t,n,o,r,a,i,c,l,u=d(e,!1);if("string"==typeof u&&u.length>2)if(43===(t=(u=C(u)).charCodeAt(0))||45===t){if(88===(n=u.charCodeAt(2))||120===n)return NaN}else if(48===t){switch(u.charCodeAt(1)){case 66:case 98:o=2,r=49;break;case 79:case 111:o=8,r=55;break;default:return+u}for(i=(a=u.slice(2)).length,c=0;cr)return NaN;return parseInt(a,o)}return+u};if(a(g,!b(" 0o1")||!b("0b1")||b("+0x1"))){for(var y,_=function(e){var t=arguments.length<1?0:e,n=this;return n instanceof _&&(v?s((function(){N.valueOf.call(n)})):l(n)!=g)?u(new b(V(t)),n,_):V(t)},k=o?m(b):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,isFinite,isInteger,isNaN,isSafeInteger,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,parseFloat,parseInt,isInteger".split(","),x=0;k.length>x;x++)c(b,y=k[x])&&!c(_,y)&&h(_,y,f(b,y));_.prototype=N,N.constructor=_,i(r,g,_)}},function(e,t,n){"use strict";n(1)({target:"Number",stat:!0},{EPSILON:Math.pow(2,-52)})},function(e,t,n){"use strict";n(1)({target:"Number",stat:!0},{isFinite:n(256)})},function(e,t,n){"use strict";var o=n(5).isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&o(e)}},function(e,t,n){"use strict";n(1)({target:"Number",stat:!0},{isInteger:n(141)})},function(e,t,n){"use strict";n(1)({target:"Number",stat:!0},{isNaN:function(e){return e!=e}})},function(e,t,n){"use strict";var o=n(1),r=n(141),a=Math.abs;o({target:"Number",stat:!0},{isSafeInteger:function(e){return r(e)&&a(e)<=9007199254740991}})},function(e,t,n){"use strict";n(1)({target:"Number",stat:!0},{MAX_SAFE_INTEGER:9007199254740991})},function(e,t,n){"use strict";n(1)({target:"Number",stat:!0},{MIN_SAFE_INTEGER:-9007199254740991})},function(e,t,n){"use strict";var o=n(1),r=n(263);o({target:"Number",stat:!0,forced:Number.parseFloat!=r},{parseFloat:r})},function(e,t,n){"use strict";var o=n(5),r=n(56).trim,a=n(81),i=o.parseFloat,c=1/i(a+"-0")!=-Infinity;e.exports=c?function(e){var t=r(String(e)),n=i(t);return 0===n&&"-"==t.charAt(0)?-0:n}:i},function(e,t,n){"use strict";var o=n(1),r=n(142);o({target:"Number",stat:!0,forced:Number.parseInt!=r},{parseInt:r})},function(e,t,n){"use strict";var o=n(1),r=n(30),a=n(266),i=n(104),c=n(4),l=1..toFixed,u=Math.floor,d=function p(e,t,n){return 0===t?n:t%2==1?p(e,t-1,n*e):p(e*e,t/2,n)},s=function(e){for(var t=0,n=e;n>=4096;)t+=12,n/=4096;for(;n>=2;)t+=1,n/=2;return t};o({target:"Number",proto:!0,forced:l&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!c((function(){l.call({})}))},{toFixed:function(e){var t,n,o,c,l=a(this),p=r(e),m=[0,0,0,0,0,0],f="",h="0",C=function(e,t){for(var n=-1,o=t;++n<6;)o+=e*m[n],m[n]=o%1e7,o=u(o/1e7)},g=function(e){for(var t=6,n=0;--t>=0;)n+=m[t],m[t]=u(n/e),n=n%e*1e7},b=function(){for(var e=6,t="";--e>=0;)if(""!==t||0===e||0!==m[e]){var n=String(m[e]);t=""===t?n:t+i.call("0",7-n.length)+n}return t};if(p<0||p>20)throw RangeError("Incorrect fraction digits");if(l!=l)return"NaN";if(l<=-1e21||l>=1e21)return String(l);if(l<0&&(f="-",l=-l),l>1e-21)if(n=(t=s(l*d(2,69,1))-69)<0?l*d(2,-t,1):l/d(2,t,1),n*=4503599627370496,(t=52-t)>0){for(C(0,n),o=p;o>=7;)C(1e7,0),o-=7;for(C(d(10,o,1),0),o=t-1;o>=23;)g(1<<23),o-=23;g(1<0?f+((c=h.length)<=p?"0."+i.call("0",p-c)+h:h.slice(0,c-p)+"."+h.slice(c-p)):f+h}})},function(e,t,n){"use strict";var o=n(33);e.exports=function(e){if("number"!=typeof e&&"Number"!=o(e))throw TypeError("Incorrect invocation");return+e}},function(e,t,n){"use strict";var o=n(1),r=n(268);o({target:"Object",stat:!0,forced:Object.assign!==r},{assign:r})},function(e,t,n){"use strict";var o=n(9),r=n(4),a=n(62),i=n(94),c=n(71),l=n(14),u=n(57),d=Object.assign,s=Object.defineProperty;e.exports=!d||r((function(){if(o&&1!==d({b:1},d(s({},"a",{enumerable:!0,get:function(){s(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},n=Symbol();return e[n]=7,"abcdefghijklmnopqrst".split("").forEach((function(e){t[e]=e})),7!=d({},e)[n]||"abcdefghijklmnopqrst"!=a(d({},t)).join("")}))?function(e,t){for(var n=l(e),r=arguments.length,d=1,s=i.f,p=c.f;r>d;)for(var m,f=u(arguments[d++]),h=s?a(f).concat(s(f)):a(f),C=h.length,g=0;C>g;)m=h[g++],o&&!p.call(f,m)||(n[m]=f[m]);return n}:d},function(e,t,n){"use strict";n(1)({target:"Object",stat:!0,sham:!n(9)},{create:n(42)})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(82),i=n(14),c=n(31),l=n(13);r&&o({target:"Object",proto:!0,forced:a},{__defineGetter__:function(e,t){l.f(i(this),e,{get:c(t),enumerable:!0,configurable:!0})}})},function(e,t,n){"use strict";var o=n(1),r=n(9);o({target:"Object",stat:!0,forced:!r,sham:!r},{defineProperties:n(126)})},function(e,t,n){"use strict";var o=n(1),r=n(9);o({target:"Object",stat:!0,forced:!r,sham:!r},{defineProperty:n(13).f})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(82),i=n(14),c=n(31),l=n(13);r&&o({target:"Object",proto:!0,forced:a},{__defineSetter__:function(e,t){l.f(i(this),e,{set:c(t),enumerable:!0,configurable:!0})}})},function(e,t,n){"use strict";var o=n(1),r=n(143).entries;o({target:"Object",stat:!0},{entries:function(e){return r(e)}})},function(e,t,n){"use strict";var o=n(1),r=n(67),a=n(4),i=n(6),c=n(50).onFreeze,l=Object.freeze;o({target:"Object",stat:!0,forced:a((function(){l(1)})),sham:!r},{freeze:function(e){return l&&i(e)?l(c(e)):e}})},function(e,t,n){"use strict";var o=n(1),r=n(68),a=n(49);o({target:"Object",stat:!0},{fromEntries:function(e){var t={};return r(e,(function(e,n){a(t,e,n)}),undefined,!0),t}})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(25),i=n(20).f,c=n(9),l=r((function(){i(1)}));o({target:"Object",stat:!0,forced:!c||l,sham:!c},{getOwnPropertyDescriptor:function(e,t){return i(a(e),t)}})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(92),i=n(25),c=n(20),l=n(49);o({target:"Object",stat:!0,sham:!r},{getOwnPropertyDescriptors:function(e){for(var t,n,o=i(e),r=c.f,u=a(o),d={},s=0;u.length>s;)(n=r(o,t=u[s++]))!==undefined&&l(d,t,n);return d}})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(128).f;o({target:"Object",stat:!0,forced:r((function(){return!Object.getOwnPropertyNames(1)}))},{getOwnPropertyNames:a})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(14),i=n(37),c=n(102);o({target:"Object",stat:!0,forced:r((function(){i(1)})),sham:!c},{getPrototypeOf:function(e){return i(a(e))}})},function(e,t,n){"use strict";n(1)({target:"Object",stat:!0},{is:n(144)})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(6),i=Object.isExtensible;o({target:"Object",stat:!0,forced:r((function(){i(1)}))},{isExtensible:function(e){return!!a(e)&&(!i||i(e))}})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(6),i=Object.isFrozen;o({target:"Object",stat:!0,forced:r((function(){i(1)}))},{isFrozen:function(e){return!a(e)||!!i&&i(e)}})},function(e,t,n){"use strict";var o=n(1),r=n(4),a=n(6),i=Object.isSealed;o({target:"Object",stat:!0,forced:r((function(){i(1)}))},{isSealed:function(e){return!a(e)||!!i&&i(e)}})},function(e,t,n){"use strict";var o=n(1),r=n(14),a=n(62);o({target:"Object",stat:!0,forced:n(4)((function(){a(1)}))},{keys:function(e){return a(r(e))}})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(82),i=n(14),c=n(34),l=n(37),u=n(20).f;r&&o({target:"Object",proto:!0,forced:a},{__lookupGetter__:function(e){var t,n=i(this),o=c(e,!0);do{if(t=u(n,o))return t.get}while(n=l(n))}})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(82),i=n(14),c=n(34),l=n(37),u=n(20).f;r&&o({target:"Object",proto:!0,forced:a},{__lookupSetter__:function(e){var t,n=i(this),o=c(e,!0);do{if(t=u(n,o))return t.set}while(n=l(n))}})},function(e,t,n){"use strict";var o=n(1),r=n(6),a=n(50).onFreeze,i=n(67),c=n(4),l=Object.preventExtensions;o({target:"Object",stat:!0,forced:c((function(){l(1)})),sham:!i},{preventExtensions:function(e){return l&&r(e)?l(a(e)):e}})},function(e,t,n){"use strict";var o=n(1),r=n(6),a=n(50).onFreeze,i=n(67),c=n(4),l=Object.seal;o({target:"Object",stat:!0,forced:c((function(){l(1)})),sham:!i},{seal:function(e){return l&&r(e)?l(a(e)):e}})},function(e,t,n){"use strict";n(1)({target:"Object",stat:!0},{setPrototypeOf:n(53)})},function(e,t,n){"use strict";var o=n(100),r=n(22),a=n(292);o||r(Object.prototype,"toString",a,{unsafe:!0})},function(e,t,n){"use strict";var o=n(100),r=n(74);e.exports=o?{}.toString:function(){return"[object "+r(this)+"]"}},function(e,t,n){"use strict";var o=n(1),r=n(143).values;o({target:"Object",stat:!0},{values:function(e){return r(e)}})},function(e,t,n){"use strict";var o=n(1),r=n(142);o({global:!0,forced:parseInt!=r},{parseInt:r})},function(e,t,n){"use strict";var o,r,a,i,c=n(1),l=n(38),u=n(5),d=n(36),s=n(145),p=n(22),m=n(66),f=n(43),h=n(54),C=n(6),g=n(31),b=n(55),N=n(33),v=n(90),V=n(68),y=n(75),_=n(45),k=n(106).set,x=n(147),L=n(148),w=n(296),B=n(149),S=n(297),I=n(35),T=n(61),A=n(12),E=n(96),P=A("species"),M="Promise",O=I.get,R=I.set,F=I.getterFor(M),D=s,j=u.TypeError,z=u.document,H=u.process,G=d("fetch"),U=B.f,K=U,Y="process"==N(H),q=!!(z&&z.createEvent&&u.dispatchEvent),W=0,$=T(M,(function(){if(!(v(D)!==String(D))){if(66===E)return!0;if(!Y&&"function"!=typeof PromiseRejectionEvent)return!0}if(l&&!D.prototype["finally"])return!0;if(E>=51&&/native code/.test(D))return!1;var e=D.resolve(1),t=function(e){e((function(){}),(function(){}))};return(e.constructor={})[P]=t,!(e.then((function(){}))instanceof t)})),Q=$||!y((function(e){D.all(e)["catch"]((function(){}))})),X=function(e){var t;return!(!C(e)||"function"!=typeof(t=e.then))&&t},Z=function(e,t,n){if(!t.notified){t.notified=!0;var o=t.reactions;x((function(){for(var r=t.value,a=1==t.state,i=0;o.length>i;){var c,l,u,d=o[i++],s=a?d.ok:d.fail,p=d.resolve,m=d.reject,f=d.domain;try{s?(a||(2===t.rejection&&ne(e,t),t.rejection=1),!0===s?c=r:(f&&f.enter(),c=s(r),f&&(f.exit(),u=!0)),c===d.promise?m(j("Promise-chain cycle")):(l=X(c))?l.call(c,p,m):p(c)):m(r)}catch(h){f&&!u&&f.exit(),m(h)}}t.reactions=[],t.notified=!1,n&&!t.rejection&&ee(e,t)}))}},J=function(e,t,n){var o,r;q?((o=z.createEvent("Event")).promise=t,o.reason=n,o.initEvent(e,!1,!0),u.dispatchEvent(o)):o={promise:t,reason:n},(r=u["on"+e])?r(o):"unhandledrejection"===e&&w("Unhandled promise rejection",n)},ee=function(e,t){k.call(u,(function(){var n,o=t.value;if(te(t)&&(n=S((function(){Y?H.emit("unhandledRejection",o,e):J("unhandledrejection",e,o)})),t.rejection=Y||te(t)?2:1,n.error))throw n.value}))},te=function(e){return 1!==e.rejection&&!e.parent},ne=function(e,t){k.call(u,(function(){Y?H.emit("rejectionHandled",e):J("rejectionhandled",e,t.value)}))},oe=function(e,t,n,o){return function(r){e(t,n,r,o)}},re=function(e,t,n,o){t.done||(t.done=!0,o&&(t=o),t.value=n,t.state=2,Z(e,t,!0))},ae=function ie(e,t,n,o){if(!t.done){t.done=!0,o&&(t=o);try{if(e===n)throw j("Promise can't be resolved itself");var r=X(n);r?x((function(){var o={done:!1};try{r.call(n,oe(ie,e,o,t),oe(re,e,o,t))}catch(a){re(e,o,a,t)}})):(t.value=n,t.state=1,Z(e,t,!1))}catch(a){re(e,{done:!1},a,t)}}};$&&(D=function(e){b(this,D,M),g(e),o.call(this);var t=O(this);try{e(oe(ae,this,t),oe(re,this,t))}catch(n){re(this,t,n)}},(o=function(e){R(this,{type:M,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:W,value:undefined})}).prototype=m(D.prototype,{then:function(e,t){var n=F(this),o=U(_(this,D));return o.ok="function"!=typeof e||e,o.fail="function"==typeof t&&t,o.domain=Y?H.domain:undefined,n.parent=!0,n.reactions.push(o),n.state!=W&&Z(this,n,!1),o.promise},"catch":function(e){return this.then(undefined,e)}}),r=function(){var e=new o,t=O(e);this.promise=e,this.resolve=oe(ae,e,t),this.reject=oe(re,e,t)},B.f=U=function(e){return e===D||e===a?new r(e):K(e)},l||"function"!=typeof s||(i=s.prototype.then,p(s.prototype,"then",(function(e,t){var n=this;return new D((function(e,t){i.call(n,e,t)})).then(e,t)}),{unsafe:!0}),"function"==typeof G&&c({global:!0,enumerable:!0,forced:!0},{fetch:function(e){return L(D,G.apply(u,arguments))}}))),c({global:!0,wrap:!0,forced:$},{Promise:D}),f(D,M,!1,!0),h(M),a=d(M),c({target:M,stat:!0,forced:$},{reject:function(e){var t=U(this);return t.reject.call(undefined,e),t.promise}}),c({target:M,stat:!0,forced:l||$},{resolve:function(e){return L(l&&this===a?D:this,e)}}),c({target:M,stat:!0,forced:Q},{all:function(e){var t=this,n=U(t),o=n.resolve,r=n.reject,a=S((function(){var n=g(t.resolve),a=[],i=0,c=1;V(e,(function(e){var l=i++,u=!1;a.push(undefined),c++,n.call(t,e).then((function(e){u||(u=!0,a[l]=e,--c||o(a))}),r)})),--c||o(a)}));return a.error&&r(a.value),n.promise},race:function(e){var t=this,n=U(t),o=n.reject,r=S((function(){var r=g(t.resolve);V(e,(function(e){r.call(t,e).then(n.resolve,o)}))}));return r.error&&o(r.value),n.promise}})},function(e,t,n){"use strict";var o=n(5);e.exports=function(e,t){var n=o.console;n&&n.error&&(1===arguments.length?n.error(e):n.error(e,t))}},function(e,t,n){"use strict";e.exports=function(e){try{return{error:!1,value:e()}}catch(t){return{error:!0,value:t}}}},function(e,t,n){"use strict";var o=n(1),r=n(38),a=n(145),i=n(4),c=n(36),l=n(45),u=n(148),d=n(22);o({target:"Promise",proto:!0,real:!0,forced:!!a&&i((function(){a.prototype["finally"].call({then:function(){}},(function(){}))}))},{"finally":function(e){var t=l(this,c("Promise")),n="function"==typeof e;return this.then(n?function(n){return u(t,e()).then((function(){return n}))}:e,n?function(n){return u(t,e()).then((function(){throw n}))}:e)}}),r||"function"!=typeof a||a.prototype["finally"]||d(a.prototype,"finally",c("Promise").prototype["finally"])},function(e,t,n){"use strict";var o=n(1),r=n(36),a=n(31),i=n(8),c=n(4),l=r("Reflect","apply"),u=Function.apply;o({target:"Reflect",stat:!0,forced:!c((function(){l((function(){}))}))},{apply:function(e,t,n){return a(e),i(n),l?l(e,t,n):u.call(e,t,n)}})},function(e,t,n){"use strict";var o=n(1),r=n(36),a=n(31),i=n(8),c=n(6),l=n(42),u=n(138),d=n(4),s=r("Reflect","construct"),p=d((function(){function e(){}return!(s((function(){}),[],e)instanceof e)})),m=!d((function(){s((function(){}))})),f=p||m;o({target:"Reflect",stat:!0,forced:f,sham:f},{construct:function(e,t){a(e),i(t);var n=arguments.length<3?e:a(arguments[2]);if(m&&!p)return s(e,t,n);if(e==n){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var o=[null];return o.push.apply(o,t),new(u.apply(e,o))}var r=n.prototype,d=l(c(r)?r:Object.prototype),f=Function.apply.call(e,d,t);return c(f)?f:d}})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(8),i=n(34),c=n(13);o({target:"Reflect",stat:!0,forced:n(4)((function(){Reflect.defineProperty(c.f({},1,{value:1}),1,{value:2})})),sham:!r},{defineProperty:function(e,t,n){a(e);var o=i(t,!0);a(n);try{return c.f(e,o,n),!0}catch(r){return!1}}})},function(e,t,n){"use strict";var o=n(1),r=n(8),a=n(20).f;o({target:"Reflect",stat:!0},{deleteProperty:function(e,t){var n=a(r(e),t);return!(n&&!n.configurable)&&delete e[t]}})},function(e,t,n){"use strict";var o=n(1),r=n(6),a=n(8),i=n(15),c=n(20),l=n(37);o({target:"Reflect",stat:!0},{get:function u(e,t){var n,o,d=arguments.length<3?e:arguments[2];return a(e)===d?e[t]:(n=c.f(e,t))?i(n,"value")?n.value:n.get===undefined?undefined:n.get.call(d):r(o=l(e))?u(o,t,d):void 0}})},function(e,t,n){"use strict";var o=n(1),r=n(9),a=n(8),i=n(20);o({target:"Reflect",stat:!0,sham:!r},{getOwnPropertyDescriptor:function(e,t){return i.f(a(e),t)}})},function(e,t,n){"use strict";var o=n(1),r=n(8),a=n(37);o({target:"Reflect",stat:!0,sham:!n(102)},{getPrototypeOf:function(e){return a(r(e))}})},function(e,t,n){"use strict";n(1)({target:"Reflect",stat:!0},{has:function(e,t){return t in e}})},function(e,t,n){"use strict";var o=n(1),r=n(8),a=Object.isExtensible;o({target:"Reflect",stat:!0},{isExtensible:function(e){return r(e),!a||a(e)}})},function(e,t,n){"use strict";n(1)({target:"Reflect",stat:!0},{ownKeys:n(92)})},function(e,t,n){"use strict";var o=n(1),r=n(36),a=n(8);o({target:"Reflect",stat:!0,sham:!n(67)},{preventExtensions:function(e){a(e);try{var t=r("Object","preventExtensions");return t&&t(e),!0}catch(n){return!1}}})},function(e,t,n){"use strict";var o=n(1),r=n(8),a=n(6),i=n(15),c=n(4),l=n(13),u=n(20),d=n(37),s=n(46);o({target:"Reflect",stat:!0,forced:c((function(){var e=l.f({},"a",{configurable:!0});return!1!==Reflect.set(d(e),"a",1,e)}))},{set:function p(e,t,n){var o,c,m=arguments.length<4?e:arguments[3],f=u.f(r(e),t);if(!f){if(a(c=d(e)))return p(c,t,n,m);f=s(0)}if(i(f,"value")){if(!1===f.writable||!a(m))return!1;if(o=u.f(m,t)){if(o.get||o.set||!1===o.writable)return!1;o.value=n,l.f(m,t,o)}else l.f(m,t,s(0,n));return!0}return f.set!==undefined&&(f.set.call(m,n),!0)}})},function(e,t,n){"use strict";var o=n(1),r=n(8),a=n(135),i=n(53);i&&o({target:"Reflect",stat:!0},{setPrototypeOf:function(e,t){r(e),a(t);try{return i(e,t),!0}catch(n){return!1}}})},function(e,t,n){"use strict";var o=n(9),r=n(5),a=n(61),i=n(79),c=n(13).f,l=n(47).f,u=n(107),d=n(83),s=n(22),p=n(4),m=n(54),f=n(12)("match"),h=r.RegExp,C=h.prototype,g=/a/g,b=/a/g,N=new h(g)!==g;if(o&&a("RegExp",!N||p((function(){return b[f]=!1,h(g)!=g||h(b)==b||"/a/i"!=h(g,"i")})))){for(var v=function(e,t){var n=this instanceof v,o=u(e),r=t===undefined;return!n&&o&&e.constructor===v&&r?e:i(N?new h(o&&!r?e.source:e,t):h((o=e instanceof v)?e.source:e,o&&r?d.call(e):t),n?this:C,v)},V=function(e){e in v||c(v,e,{configurable:!0,get:function(){return h[e]},set:function(t){h[e]=t}})},y=l(h),_=0;y.length>_;)V(y[_++]);C.constructor=v,v.prototype=C,s(r,"RegExp",v)}m("RegExp")},function(e,t,n){"use strict";var o=n(1),r=n(84);o({target:"RegExp",proto:!0,forced:/./.exec!==r},{exec:r})},function(e,t,n){"use strict";var o=n(9),r=n(13),a=n(83);o&&"g"!=/./g.flags&&r.f(RegExp.prototype,"flags",{configurable:!0,get:a})},function(e,t,n){"use strict";var o=n(22),r=n(8),a=n(4),i=n(83),c=RegExp.prototype,l=c.toString,u=a((function(){return"/a/b"!=l.call({source:"a",flags:"b"})})),d="toString"!=l.name;(u||d)&&o(RegExp.prototype,"toString",(function(){var e=r(this),t=String(e.source),n=e.flags;return"/"+t+"/"+String(n===undefined&&e instanceof RegExp&&!("flags"in c)?i.call(e):n)}),{unsafe:!0})},function(e,t,n){"use strict";var o=n(78),r=n(139);e.exports=o("Set",(function(e){return function(){return e(this,arguments.length?arguments[0]:undefined)}}),r)},function(e,t,n){"use strict";var o=n(1),r=n(108).codeAt;o({target:"String",proto:!0},{codePointAt:function(e){return r(this,e)}})},function(e,t,n){"use strict";var o,r=n(1),a=n(20).f,i=n(10),c=n(109),l=n(21),u=n(110),d=n(38),s="".endsWith,p=Math.min,m=u("endsWith");r({target:"String",proto:!0,forced:!!(d||m||(o=a(String.prototype,"endsWith"),!o||o.writable))&&!m},{endsWith:function(e){var t=String(l(this));c(e);var n=arguments.length>1?arguments[1]:undefined,o=i(t.length),r=n===undefined?o:p(i(n),o),a=String(e);return s?s.call(t,a,r):t.slice(r-a.length,r)===a}})},function(e,t,n){"use strict";var o=n(1),r=n(41),a=String.fromCharCode,i=String.fromCodePoint;o({target:"String",stat:!0,forced:!!i&&1!=i.length},{fromCodePoint:function(e){for(var t,n=[],o=arguments.length,i=0;o>i;){if(t=+arguments[i++],r(t,1114111)!==t)throw RangeError(t+" is not a valid code point");n.push(t<65536?a(t):a(55296+((t-=65536)>>10),t%1024+56320))}return n.join("")}})},function(e,t,n){"use strict";var o=n(1),r=n(109),a=n(21);o({target:"String",proto:!0,forced:!n(110)("includes")},{includes:function(e){return!!~String(a(this)).indexOf(r(e),arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(108).charAt,r=n(35),a=n(101),i=r.set,c=r.getterFor("String Iterator");a(String,"String",(function(e){i(this,{type:"String Iterator",string:String(e),index:0})}),(function(){var e,t=c(this),n=t.string,r=t.index;return r>=n.length?{value:undefined,done:!0}:(e=o(n,r),t.index+=e.length,{value:e,done:!1})}))},function(e,t,n){"use strict";var o=n(85),r=n(8),a=n(10),i=n(21),c=n(111),l=n(86);o("match",1,(function(e,t,n){return[function(t){var n=i(this),o=t==undefined?undefined:t[e];return o!==undefined?o.call(t,n):new RegExp(t)[e](String(n))},function(e){var o=n(t,e,this);if(o.done)return o.value;var i=r(e),u=String(this);if(!i.global)return l(i,u);var d=i.unicode;i.lastIndex=0;for(var s,p=[],m=0;null!==(s=l(i,u));){var f=String(s[0]);p[m]=f,""===f&&(i.lastIndex=c(u,a(i.lastIndex),d)),m++}return 0===m?null:p}]}))},function(e,t,n){"use strict";var o=n(1),r=n(103).end;o({target:"String",proto:!0,forced:n(150)},{padEnd:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(103).start;o({target:"String",proto:!0,forced:n(150)},{padStart:function(e){return r(this,e,arguments.length>1?arguments[1]:undefined)}})},function(e,t,n){"use strict";var o=n(1),r=n(25),a=n(10);o({target:"String",stat:!0},{raw:function(e){for(var t=r(e.raw),n=a(t.length),o=arguments.length,i=[],c=0;n>c;)i.push(String(t[c++])),c]*>)/g,h=/\$([$&'`]|\d\d?)/g;o("replace",2,(function(e,t,n){return[function(n,o){var r=l(this),a=n==undefined?undefined:n[e];return a!==undefined?a.call(n,r,o):t.call(String(r),n,o)},function(e,a){var l=n(t,e,this,a);if(l.done)return l.value;var m=r(e),f=String(this),h="function"==typeof a;h||(a=String(a));var C=m.global;if(C){var g=m.unicode;m.lastIndex=0}for(var b=[];;){var N=d(m,f);if(null===N)break;if(b.push(N),!C)break;""===String(N[0])&&(m.lastIndex=u(f,i(m.lastIndex),g))}for(var v,V="",y=0,_=0;_=y&&(V+=f.slice(y,x)+I,y=x+k.length)}return V+f.slice(y)}];function o(e,n,o,r,i,c){var l=o+e.length,u=r.length,d=h;return i!==undefined&&(i=a(i),d=f),t.call(c,d,(function(t,a){var c;switch(a.charAt(0)){case"$":return"$";case"&":return e;case"`":return n.slice(0,o);case"'":return n.slice(l);case"<":c=i[a.slice(1,-1)];break;default:var d=+a;if(0===d)return t;if(d>u){var s=m(d/10);return 0===s?t:s<=u?r[s-1]===undefined?a.charAt(1):r[s-1]+a.charAt(1):t}c=r[d-1]}return c===undefined?"":c}))}}))},function(e,t,n){"use strict";var o=n(85),r=n(8),a=n(21),i=n(144),c=n(86);o("search",1,(function(e,t,n){return[function(t){var n=a(this),o=t==undefined?undefined:t[e];return o!==undefined?o.call(t,n):new RegExp(t)[e](String(n))},function(e){var o=n(t,e,this);if(o.done)return o.value;var a=r(e),l=String(this),u=a.lastIndex;i(u,0)||(a.lastIndex=0);var d=c(a,l);return i(a.lastIndex,u)||(a.lastIndex=u),null===d?-1:d.index}]}))},function(e,t,n){"use strict";var o=n(85),r=n(107),a=n(8),i=n(21),c=n(45),l=n(111),u=n(10),d=n(86),s=n(84),p=n(4),m=[].push,f=Math.min,h=!p((function(){return!RegExp(4294967295,"y")}));o("split",2,(function(e,t,n){var o;return o="c"=="abbc".split(/(b)*/)[1]||4!="test".split(/(?:)/,-1).length||2!="ab".split(/(?:ab)*/).length||4!=".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length?function(e,n){var o=String(i(this)),a=n===undefined?4294967295:n>>>0;if(0===a)return[];if(e===undefined)return[o];if(!r(e))return t.call(o,e,a);for(var c,l,u,d=[],p=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),f=0,h=new RegExp(e.source,p+"g");(c=s.call(h,o))&&!((l=h.lastIndex)>f&&(d.push(o.slice(f,c.index)),c.length>1&&c.index=a));)h.lastIndex===c.index&&h.lastIndex++;return f===o.length?!u&&h.test("")||d.push(""):d.push(o.slice(f)),d.length>a?d.slice(0,a):d}:"0".split(undefined,0).length?function(e,n){return e===undefined&&0===n?[]:t.call(this,e,n)}:t,[function(t,n){var r=i(this),a=t==undefined?undefined:t[e];return a!==undefined?a.call(t,r,n):o.call(String(r),t,n)},function(e,r){var i=n(o,e,this,r,o!==t);if(i.done)return i.value;var s=a(e),p=String(this),m=c(s,RegExp),C=s.unicode,g=(s.ignoreCase?"i":"")+(s.multiline?"m":"")+(s.unicode?"u":"")+(h?"y":"g"),b=new m(h?s:"^(?:"+s.source+")",g),N=r===undefined?4294967295:r>>>0;if(0===N)return[];if(0===p.length)return null===d(b,p)?[p]:[];for(var v=0,V=0,y=[];V1?arguments[1]:undefined,t.length)),o=String(e);return s?s.call(t,o,n):t.slice(n,n+o.length)===o}})},function(e,t,n){"use strict";var o=n(1),r=n(56).trim;o({target:"String",proto:!0,forced:n(112)("trim")},{trim:function(){return r(this)}})},function(e,t,n){"use strict";var o=n(1),r=n(56).end,a=n(112)("trimEnd"),i=a?function(){return r(this)}:"".trimEnd;o({target:"String",proto:!0,forced:a},{trimEnd:i,trimRight:i})},function(e,t,n){"use strict";var o=n(1),r=n(56).start,a=n(112)("trimStart"),i=a?function(){return r(this)}:"".trimStart;o({target:"String",proto:!0,forced:a},{trimStart:i,trimLeft:i})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("anchor")},{anchor:function(e){return r(this,"a","name",e)}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("big")},{big:function(){return r(this,"big","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("blink")},{blink:function(){return r(this,"blink","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("bold")},{bold:function(){return r(this,"b","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("fixed")},{fixed:function(){return r(this,"tt","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("fontcolor")},{fontcolor:function(e){return r(this,"font","color",e)}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("fontsize")},{fontsize:function(e){return r(this,"font","size",e)}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("italics")},{italics:function(){return r(this,"i","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("link")},{link:function(e){return r(this,"a","href",e)}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("small")},{small:function(){return r(this,"small","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("strike")},{strike:function(){return r(this,"strike","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("sub")},{sub:function(){return r(this,"sub","","")}})},function(e,t,n){"use strict";var o=n(1),r=n(28);o({target:"String",proto:!0,forced:n(29)("sup")},{sup:function(){return r(this,"sup","","")}})},function(e,t,n){"use strict";n(40)("Float32",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";var o=n(30);e.exports=function(e){var t=o(e);if(t<0)throw RangeError("The argument can't be less than 0");return t}},function(e,t,n){"use strict";n(40)("Float64",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";n(40)("Int8",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";n(40)("Int16",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";n(40)("Int32",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";n(40)("Uint8",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";n(40)("Uint8",(function(e){return function(t,n,o){return e(this,t,n,o)}}),!0)},function(e,t,n){"use strict";n(40)("Uint16",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";n(40)("Uint32",(function(e){return function(t,n,o){return e(this,t,n,o)}}))},function(e,t,n){"use strict";var o=n(7),r=n(130),a=o.aTypedArray;(0,o.exportTypedArrayMethod)("copyWithin",(function(e,t){return r.call(a(this),e,t,arguments.length>2?arguments[2]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=n(18).every,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("every",(function(e){return r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=n(97),a=o.aTypedArray;(0,o.exportTypedArrayMethod)("fill",(function(e){return r.apply(a(this),arguments)}))},function(e,t,n){"use strict";var o=n(7),r=n(18).filter,a=n(45),i=o.aTypedArray,c=o.aTypedArrayConstructor;(0,o.exportTypedArrayMethod)("filter",(function(e){for(var t=r(i(this),e,arguments.length>1?arguments[1]:undefined),n=a(this,this.constructor),o=0,l=t.length,u=new(c(n))(l);l>o;)u[o]=t[o++];return u}))},function(e,t,n){"use strict";var o=n(7),r=n(18).find,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("find",(function(e){return r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=n(18).findIndex,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("findIndex",(function(e){return r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=n(18).forEach,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("forEach",(function(e){r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(113);(0,n(7).exportTypedArrayStaticMethod)("from",n(152),o)},function(e,t,n){"use strict";var o=n(7),r=n(60).includes,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("includes",(function(e){return r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=n(60).indexOf,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("indexOf",(function(e){return r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(5),r=n(7),a=n(133),i=n(12)("iterator"),c=o.Uint8Array,l=a.values,u=a.keys,d=a.entries,s=r.aTypedArray,p=r.exportTypedArrayMethod,m=c&&c.prototype[i],f=!!m&&("values"==m.name||m.name==undefined),h=function(){return l.call(s(this))};p("entries",(function(){return d.call(s(this))})),p("keys",(function(){return u.call(s(this))})),p("values",h,!f),p(i,h,!f)},function(e,t,n){"use strict";var o=n(7),r=o.aTypedArray,a=o.exportTypedArrayMethod,i=[].join;a("join",(function(e){return i.apply(r(this),arguments)}))},function(e,t,n){"use strict";var o=n(7),r=n(136),a=o.aTypedArray;(0,o.exportTypedArrayMethod)("lastIndexOf",(function(e){return r.apply(a(this),arguments)}))},function(e,t,n){"use strict";var o=n(7),r=n(18).map,a=n(45),i=o.aTypedArray,c=o.aTypedArrayConstructor;(0,o.exportTypedArrayMethod)("map",(function(e){return r(i(this),e,arguments.length>1?arguments[1]:undefined,(function(e,t){return new(c(a(e,e.constructor)))(t)}))}))},function(e,t,n){"use strict";var o=n(7),r=n(113),a=o.aTypedArrayConstructor;(0,o.exportTypedArrayStaticMethod)("of",(function(){for(var e=0,t=arguments.length,n=new(a(this))(t);t>e;)n[e]=arguments[e++];return n}),r)},function(e,t,n){"use strict";var o=n(7),r=n(76).left,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("reduce",(function(e){return r(a(this),e,arguments.length,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=n(76).right,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("reduceRight",(function(e){return r(a(this),e,arguments.length,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=o.aTypedArray,a=o.exportTypedArrayMethod,i=Math.floor;a("reverse",(function(){for(var e,t=r(this).length,n=i(t/2),o=0;o1?arguments[1]:undefined,1),n=this.length,o=i(e),c=r(o.length),u=0;if(c+t>n)throw RangeError("Wrong length");for(;ua;)d[a]=n[a++];return d}),a((function(){new Int8Array(1).slice()})))},function(e,t,n){"use strict";var o=n(7),r=n(18).some,a=o.aTypedArray;(0,o.exportTypedArrayMethod)("some",(function(e){return r(a(this),e,arguments.length>1?arguments[1]:undefined)}))},function(e,t,n){"use strict";var o=n(7),r=o.aTypedArray,a=o.exportTypedArrayMethod,i=[].sort;a("sort",(function(e){return i.call(r(this),e)}))},function(e,t,n){"use strict";var o=n(7),r=n(10),a=n(41),i=n(45),c=o.aTypedArray;(0,o.exportTypedArrayMethod)("subarray",(function(e,t){var n=c(this),o=n.length,l=a(e,o);return new(i(n,n.constructor))(n.buffer,n.byteOffset+l*n.BYTES_PER_ELEMENT,r((t===undefined?o:a(t,o))-l))}))},function(e,t,n){"use strict";var o=n(5),r=n(7),a=n(4),i=o.Int8Array,c=r.aTypedArray,l=r.exportTypedArrayMethod,u=[].toLocaleString,d=[].slice,s=!!i&&a((function(){u.call(new i(1))}));l("toLocaleString",(function(){return u.apply(s?d.call(c(this)):c(this),arguments)}),a((function(){return[1,2].toLocaleString()!=new i([1,2]).toLocaleString()}))||!a((function(){i.prototype.toLocaleString.call([1,2])})))},function(e,t,n){"use strict";var o=n(7).exportTypedArrayMethod,r=n(4),a=n(5).Uint8Array,i=a&&a.prototype||{},c=[].toString,l=[].join;r((function(){c.call({})}))&&(c=function(){return l.call(this)});var u=i.toString!=c;o("toString",c,u)},function(e,t,n){"use strict";var o,r=n(5),a=n(66),i=n(50),c=n(78),l=n(153),u=n(6),d=n(35).enforce,s=n(121),p=!r.ActiveXObject&&"ActiveXObject"in r,m=Object.isExtensible,f=function(e){return function(){return e(this,arguments.length?arguments[0]:undefined)}},h=e.exports=c("WeakMap",f,l);if(s&&p){o=l.getConstructor(f,"WeakMap",!0),i.REQUIRED=!0;var C=h.prototype,g=C["delete"],b=C.has,N=C.get,v=C.set;a(C,{"delete":function(e){if(u(e)&&!m(e)){var t=d(this);return t.frozen||(t.frozen=new o),g.call(this,e)||t.frozen["delete"](e)}return g.call(this,e)},has:function(e){if(u(e)&&!m(e)){var t=d(this);return t.frozen||(t.frozen=new o),b.call(this,e)||t.frozen.has(e)}return b.call(this,e)},get:function(e){if(u(e)&&!m(e)){var t=d(this);return t.frozen||(t.frozen=new o),b.call(this,e)?N.call(this,e):t.frozen.get(e)}return N.call(this,e)},set:function(e,t){if(u(e)&&!m(e)){var n=d(this);n.frozen||(n.frozen=new o),b.call(this,e)?v.call(this,e,t):n.frozen.set(e,t)}else v.call(this,e,t);return this}})}},function(e,t,n){"use strict";n(78)("WeakSet",(function(e){return function(){return e(this,arguments.length?arguments[0]:undefined)}}),n(153))},function(e,t,n){"use strict";var o=n(1),r=n(5),a=n(106);o({global:!0,bind:!0,enumerable:!0,forced:!r.setImmediate||!r.clearImmediate},{setImmediate:a.set,clearImmediate:a.clear})},function(e,t,n){"use strict";var o=n(1),r=n(5),a=n(147),i=n(33),c=r.process,l="process"==i(c);o({global:!0,enumerable:!0,noTargetGet:!0},{queueMicrotask:function(e){var t=l&&c.domain;a(t?t.bind(e):e)}})},function(e,t,n){"use strict";var o=n(1),r=n(5),a=n(73),i=[].slice,c=function(e){return function(t,n){var o=arguments.length>2,r=o?i.call(arguments,2):undefined;return e(o?function(){("function"==typeof t?t:Function(t)).apply(this,r)}:t,n)}};o({global:!0,bind:!0,forced:/MSIE .\./.test(a)},{setTimeout:c(r.setTimeout),setInterval:c(r.setInterval)})},function(e,t,n){"use strict";t.__esModule=!0,t._CI=Ie,t._HI=D,t._M=Te,t._MCCC=Me,t._ME=Ee,t._MFCC=Oe,t._MP=Be,t._MR=ve,t.__render=ze,t.createComponentVNode=function(e,t,n,o,r){var i=new T(1,null,null,e=function(e,t){if(12&e)return e;if(t.prototype&&t.prototype.render)return 4;if(t.render)return 32776;return 8}(e,t),o,function(e,t,n){var o=(32768&e?t.render:t).defaultProps;if(a(o))return n;if(a(n))return d(o,null);return B(n,o)}(e,t,n),function(e,t,n){if(4&e)return n;var o=(32768&e?t.render:t).defaultHooks;if(a(o))return n;if(a(n))return o;return B(n,o)}(e,t,r),t);x.createVNode&&x.createVNode(i);return i},t.createFragment=P,t.createPortal=function(e,t){var n=D(e);return A(1024,1024,null,n,0,null,n.key,t)},t.createRef=function(){return{current:null}},t.createRenderer=function(e){return function(t,n,o,r){e||(e=t),He(n,e,o,r)}},t.createTextVNode=E,t.createVNode=A,t.directClone=M,t.findDOMfromVNode=v,t.forwardRef=function(e){return{render:e}},t.getFlagsForElementVnode=function(e){switch(e){case"svg":return 32;case"input":return 64;case"select":return 256;case"textarea":return 128;case m:return 8192;default:return 1}},t.linkEvent=function(e,t){if(c(t))return{data:e,event:t};return null},t.normalizeProps=function(e){var t=e.props;if(t){var n=e.flags;481&n&&(void 0!==t.children&&a(e.children)&&F(e,t.children),void 0!==t.className&&(e.className=t.className||null,t.className=undefined)),void 0!==t.key&&(e.key=t.key,t.key=undefined),void 0!==t.ref&&(e.ref=8&n?d(e.ref,t.ref):t.ref,t.ref=undefined)}return e},t.render=He,t.rerender=We,t.version=t.options=t.Fragment=t.EMPTY_OBJ=t.Component=void 0;var o=Array.isArray;function r(e){var t=typeof e;return"string"===t||"number"===t}function a(e){return null==e}function i(e){return null===e||!1===e||!0===e||void 0===e}function c(e){return"function"==typeof e}function l(e){return"string"==typeof e}function u(e){return null===e}function d(e,t){var n={};if(e)for(var o in e)n[o]=e[o];if(t)for(var r in t)n[r]=t[r];return n}function s(e){return!u(e)&&"object"==typeof e}var p={};t.EMPTY_OBJ=p;var m="$F";function f(e){return e.substr(2).toLowerCase()}function h(e,t){e.appendChild(t)}function C(e,t,n){u(n)?h(e,t):e.insertBefore(t,n)}function g(e,t){e.removeChild(t)}function b(e){for(var t;(t=e.shift())!==undefined;)t()}function N(e,t,n){var o=e.children;return 4&n?o.$LI:8192&n?2===e.childFlags?o:o[t?0:o.length-1]:o}function v(e,t){for(var n;e;){if(2033&(n=e.flags))return e.dom;e=N(e,t,n)}return null}function V(e,t){do{var n=e.flags;if(2033&n)return void g(t,e.dom);var o=e.children;if(4&n&&(e=o.$LI),8&n&&(e=o),8192&n){if(2!==e.childFlags){for(var r=0,a=o.length;r0,f=u(p),h=l(p)&&p[0]===I;m||f||h?(n=n||t.slice(0,d),(m||h)&&(s=M(s)),(f||h)&&(s.key=I+d),n.push(s)):n&&n.push(s),s.flags|=65536}}a=0===(n=n||t).length?1:8}else(n=t).flags|=65536,81920&t.flags&&(n=M(t)),a=2;return e.children=n,e.childFlags=a,e}function D(e){return i(e)||r(e)?E(e,null):o(e)?P(e,0,null):16384&e.flags?M(e):e}var j="http://www.w3.org/1999/xlink",z="http://www.w3.org/XML/1998/namespace",H={"xlink:actuate":j,"xlink:arcrole":j,"xlink:href":j,"xlink:role":j,"xlink:show":j,"xlink:title":j,"xlink:type":j,"xml:base":z,"xml:lang":z,"xml:space":z};function G(e){return{onClick:e,onDblClick:e,onFocusIn:e,onFocusOut:e,onKeyDown:e,onKeyPress:e,onKeyUp:e,onMouseDown:e,onMouseMove:e,onMouseUp:e,onTouchEnd:e,onTouchMove:e,onTouchStart:e}}var U=G(0),K=G(null),Y=G(!0);function q(e,t){var n=t.$EV;return n||(n=t.$EV=G(null)),n[e]||1==++U[e]&&(K[e]=function(e){var t="onClick"===e||"onDblClick"===e?function(e){return function(t){0===t.button?$(t,!0,e,J(t)):t.stopPropagation()}}(e):function(e){return function(t){$(t,!1,e,J(t))}}(e);return document.addEventListener(f(e),t),t}(e)),n}function W(e,t){var n=t.$EV;n&&n[e]&&(0==--U[e]&&(document.removeEventListener(f(e),K[e]),K[e]=null),n[e]=null)}function $(e,t,n,o){var r=function(e){return c(e.composedPath)?e.composedPath()[0]:e.target}(e);do{if(t&&r.disabled)return;var a=r.$EV;if(a){var i=a[n];if(i&&(o.dom=r,i.event?i.event(i.data,e):i(e),e.cancelBubble))return}r=r.parentNode}while(!u(r))}function Q(){this.cancelBubble=!0,this.immediatePropagationStopped||this.stopImmediatePropagation()}function X(){return this.defaultPrevented}function Z(){return this.cancelBubble}function J(e){var t={dom:document};return e.isDefaultPrevented=X,e.isPropagationStopped=Z,e.stopPropagation=Q,Object.defineProperty(e,"currentTarget",{configurable:!0,get:function(){return t.dom}}),t}function ee(e,t,n){if(e[t]){var o=e[t];o.event?o.event(o.data,n):o(n)}else{var r=t.toLowerCase();e[r]&&e[r](n)}}function te(e,t){var n=function(n){var o=this.$V;if(o){var r=o.props||p,a=o.dom;if(l(e))ee(r,e,n);else for(var i=0;i-1&&t.options[i]&&(c=t.options[i].value),n&&a(c)&&(c=e.defaultValue),le(o,c)}}var se,pe,me=te("onInput",he),fe=te("onChange");function he(e,t,n){var o=e.value,r=t.value;if(a(o)){if(n){var i=e.defaultValue;a(i)||i===r||(t.defaultValue=i,t.value=i)}}else r!==o&&(t.defaultValue=o,t.value=o)}function Ce(e,t,n,o,r,a){64&e?ce(o,n):256&e?de(o,n,r,t):128&e&&he(o,n,r),a&&(n.$V=t)}function ge(e,t,n){64&e?function(e,t){oe(t.type)?(ne(e,"change",ae),ne(e,"click",ie)):ne(e,"input",re)}(t,n):256&e?function(e){ne(e,"change",ue)}(t):128&e&&function(e,t){ne(e,"input",me),t.onChange&&ne(e,"change",fe)}(t,n)}function be(e){return e.type&&oe(e.type)?!a(e.checked):!a(e.value)}function Ne(e){e&&!S(e,null)&&e.current&&(e.current=null)}function ve(e,t,n){e&&(c(e)||void 0!==e.current)&&n.push((function(){S(e,t)||void 0===e.current||(e.current=t)}))}function Ve(e,t){ye(e),V(e,t)}function ye(e){var t,n=e.flags,o=e.children;if(481&n){t=e.ref;var r=e.props;Ne(t);var i=e.childFlags;if(!u(r))for(var l=Object.keys(r),d=0,s=l.length;d0;for(var c in i&&(a=be(n))&&ge(t,o,n),n)we(c,null,n[c],o,r,a,null);i&&Ce(t,e,o,n,!0,a)}function Se(e,t,n){var o=D(e.render(t,e.state,n)),r=n;return c(e.getChildContext)&&(r=d(n,e.getChildContext())),e.$CX=r,o}function Ie(e,t,n,o,r,a){var i=new t(n,o),l=i.$N=Boolean(t.getDerivedStateFromProps||i.getSnapshotBeforeUpdate);if(i.$SVG=r,i.$L=a,e.children=i,i.$BS=!1,i.context=o,i.props===p&&(i.props=n),l)i.state=_(i,n,i.state);else if(c(i.componentWillMount)){i.$BR=!0,i.componentWillMount();var d=i.$PS;if(!u(d)){var s=i.state;if(u(s))i.state=d;else for(var m in d)s[m]=d[m];i.$PS=null}i.$BR=!1}return i.$LI=Se(i,n,o),i}function Te(e,t,n,o,r,a){var i=e.flags|=16384;481&i?Ee(e,t,n,o,r,a):4&i?function(e,t,n,o,r,a){var i=Ie(e,e.type,e.props||p,n,o,a);Te(i.$LI,t,i.$CX,o,r,a),Me(e.ref,i,a)}(e,t,n,o,r,a):8&i?(!function(e,t,n,o,r,a){Te(e.children=D(function(e,t){return 32768&e.flags?e.type.render(e.props||p,e.ref,t):e.type(e.props||p,t)}(e,n)),t,n,o,r,a)}(e,t,n,o,r,a),Oe(e,a)):512&i||16&i?Ae(e,t,r):8192&i?function(e,t,n,o,r,a){var i=e.children,c=e.childFlags;12&c&&0===i.length&&(c=e.childFlags=2,i=e.children=O());2===c?Te(i,n,r,o,r,a):Pe(i,n,t,o,r,a)}(e,n,t,o,r,a):1024&i&&function(e,t,n,o,r){Te(e.children,e.ref,t,!1,null,r);var a=O();Ae(a,n,o),e.dom=a.dom}(e,n,t,r,a)}function Ae(e,t,n){var o=e.dom=document.createTextNode(e.children);u(t)||C(t,o,n)}function Ee(e,t,n,o,r,i){var c=e.flags,l=e.props,d=e.className,s=e.children,p=e.childFlags,m=e.dom=function(e,t){return t?document.createElementNS("http://www.w3.org/2000/svg",e):document.createElement(e)}(e.type,o=o||(32&c)>0);if(a(d)||""===d||(o?m.setAttribute("class",d):m.className=d),16===p)L(m,s);else if(1!==p){var f=o&&"foreignObject"!==e.type;2===p?(16384&s.flags&&(e.children=s=M(s)),Te(s,m,n,f,null,i)):8!==p&&4!==p||Pe(s,m,n,f,null,i)}u(t)||C(t,m,r),u(l)||Be(e,c,l,m,o),ve(e.ref,m,i)}function Pe(e,t,n,o,r,a){for(var i=0;i0,u!==d){var f=u||p;if((c=d||p)!==p)for(var h in(s=(448&r)>0)&&(m=be(c)),c){var C=f[h],g=c[h];C!==g&&we(h,C,g,l,o,m,e)}if(f!==p)for(var b in f)a(c[b])&&!a(f[b])&&we(b,f[b],null,l,o,m,e)}var N=t.children,v=t.className;e.className!==v&&(a(v)?l.removeAttribute("class"):o?l.setAttribute("class",v):l.className=v);4096&r?function(e,t){e.textContent!==t&&(e.textContent=t)}(l,N):Fe(e.childFlags,t.childFlags,e.children,N,l,n,o&&"foreignObject"!==t.type,null,e,i);s&&Ce(r,t,l,c,!1,m);var V=t.ref,y=e.ref;y!==V&&(Ne(y),ve(V,l,i))}(e,t,o,r,m,s):4&m?function(e,t,n,o,r,a,i){var l=t.children=e.children;if(u(l))return;l.$L=i;var s=t.props||p,m=t.ref,f=e.ref,h=l.state;if(!l.$N){if(c(l.componentWillReceiveProps)){if(l.$BR=!0,l.componentWillReceiveProps(s,o),l.$UN)return;l.$BR=!1}u(l.$PS)||(h=d(h,l.$PS),l.$PS=null)}De(l,h,s,n,o,r,!1,a,i),f!==m&&(Ne(f),ve(m,l,i))}(e,t,n,o,r,l,s):8&m?function(e,t,n,o,r,i,l){var u=!0,d=t.props||p,s=t.ref,m=e.props,f=!a(s),h=e.children;f&&c(s.onComponentShouldUpdate)&&(u=s.onComponentShouldUpdate(m,d));if(!1!==u){f&&c(s.onComponentWillUpdate)&&s.onComponentWillUpdate(m,d);var C=t.type,g=D(32768&t.flags?C.render(d,s,o):C(d,o));Re(h,g,n,o,r,i,l),t.children=g,f&&c(s.onComponentDidUpdate)&&s.onComponentDidUpdate(m,d)}else t.children=h}(e,t,n,o,r,l,s):16&m?function(e,t){var n=t.children,o=t.dom=e.dom;n!==e.children&&(o.nodeValue=n)}(e,t):512&m?t.dom=e.dom:8192&m?function(e,t,n,o,r,a){var i=e.children,c=t.children,l=e.childFlags,u=t.childFlags,d=null;12&u&&0===c.length&&(u=t.childFlags=2,c=t.children=O());var s=0!=(2&u);if(12&l){var p=i.length;(8&l&&8&u||s||!s&&c.length>p)&&(d=v(i[p-1],!1).nextSibling)}Fe(l,u,i,c,n,o,r,d,e,a)}(e,t,n,o,r,s):function(e,t,n,o){var r=e.ref,a=t.ref,c=t.children;if(Fe(e.childFlags,t.childFlags,e.children,c,r,n,!1,null,e,o),t.dom=e.dom,r!==a&&!i(c)){var l=c.dom;g(r,l),h(a,l)}}(e,t,o,s)}function Fe(e,t,n,o,r,a,i,c,l,u){switch(e){case 2:switch(t){case 2:Re(n,o,r,a,i,c,u);break;case 1:Ve(n,r);break;case 16:ye(n),L(r,o);break;default:!function(e,t,n,o,r,a){ye(e),Pe(t,n,o,r,v(e,!0),a),V(e,n)}(n,o,r,a,i,u)}break;case 1:switch(t){case 2:Te(o,r,a,i,c,u);break;case 1:break;case 16:L(r,o);break;default:Pe(o,r,a,i,c,u)}break;case 16:switch(t){case 16:!function(e,t,n){e!==t&&(""!==e?n.firstChild.nodeValue=t:L(n,t))}(n,o,r);break;case 2:ke(r),Te(o,r,a,i,c,u);break;case 1:ke(r);break;default:ke(r),Pe(o,r,a,i,c,u)}break;default:switch(t){case 16:_e(n),L(r,o);break;case 2:xe(r,l,n),Te(o,r,a,i,c,u);break;case 1:xe(r,l,n);break;default:var d=0|n.length,s=0|o.length;0===d?s>0&&Pe(o,r,a,i,c,u):0===s?xe(r,l,n):8===t&&8===e?function(e,t,n,o,r,a,i,c,l,u){var d,s,p=a-1,m=i-1,f=0,h=e[f],C=t[f];e:{for(;h.key===C.key;){if(16384&C.flags&&(t[f]=C=M(C)),Re(h,C,n,o,r,c,u),e[f]=C,++f>p||f>m)break e;h=e[f],C=t[f]}for(h=e[p],C=t[m];h.key===C.key;){if(16384&C.flags&&(t[m]=C=M(C)),Re(h,C,n,o,r,c,u),e[p]=C,p--,m--,f>p||f>m)break e;h=e[p],C=t[m]}}if(f>p){if(f<=m)for(s=(d=m+1)m)for(;f<=p;)Ve(e[f++],n);else!function(e,t,n,o,r,a,i,c,l,u,d,s,p){var m,f,h,C=0,g=c,b=c,N=a-c+1,V=i-c+1,_=new Int32Array(V+1),k=N===o,x=!1,L=0,w=0;if(r<4||(N|V)<32)for(C=g;C<=a;++C)if(m=e[C],wc?x=!0:L=c,16384&f.flags&&(t[c]=f=M(f)),Re(m,f,l,n,u,d,p),++w;break}!k&&c>i&&Ve(m,l)}else k||Ve(m,l);else{var B={};for(C=b;C<=i;++C)B[t[C].key]=C;for(C=g;C<=a;++C)if(m=e[C],wg;)Ve(e[g++],l);_[c-b]=C+1,L>c?x=!0:L=c,16384&(f=t[c]).flags&&(t[c]=f=M(f)),Re(m,f,l,n,u,d,p),++w}else k||Ve(m,l);else k||Ve(m,l)}if(k)xe(l,s,e),Pe(t,l,n,u,d,p);else if(x){var S=function(e){var t=0,n=0,o=0,r=0,a=0,i=0,c=0,l=e.length;l>je&&(je=l,se=new Int32Array(l),pe=new Int32Array(l));for(;n>1]]0&&(pe[n]=se[a-1]),se[a]=n)}a=r+1;var u=new Int32Array(a);i=se[a-1];for(;a-- >0;)u[a]=i,i=pe[i],se[a]=0;return u}(_);for(c=S.length-1,C=V-1;C>=0;C--)0===_[C]?(16384&(f=t[L=C+b]).flags&&(t[L]=f=M(f)),Te(f,l,n,u,(h=L+1)=0;C--)0===_[C]&&(16384&(f=t[L=C+b]).flags&&(t[L]=f=M(f)),Te(f,l,n,u,(h=L+1)i?i:a,p=0;pi)for(p=s;p0&&b(r),k.v=!1,c(n)&&n(),c(x.renderComplete)&&x.renderComplete(i,t)}function He(e,t,n,o){void 0===n&&(n=null),void 0===o&&(o=p),ze(e,t,n,o)}"undefined"!=typeof document&&window.Node&&(Node.prototype.$EV=null,Node.prototype.$V=null);var Ge=[],Ue="undefined"!=typeof Promise?Promise.resolve().then.bind(Promise.resolve()):function(e){window.setTimeout(e,0)},Ke=!1;function Ye(e,t,n,o){var r=e.$PS;if(c(t)&&(t=t(r?d(e.state,r):e.state,e.props,e.context)),a(r))e.$PS=t;else for(var i in t)r[i]=t[i];if(e.$BR)c(n)&&e.$L.push(n.bind(e));else{if(!k.v&&0===Ge.length)return void $e(e,o,n);if(-1===Ge.indexOf(e)&&Ge.push(e),Ke||(Ke=!0,Ue(We)),c(n)){var l=e.$QU;l||(l=e.$QU=[]),l.push(n)}}}function qe(e){for(var t=e.$QU,n=0,o=t.length;n0&&b(r),k.v=!1}else e.state=e.$PS,e.$PS=null;c(n)&&n.call(e)}}var Qe=function(e,t){this.state=null,this.$BR=!1,this.$BS=!0,this.$PS=null,this.$LI=null,this.$UN=!1,this.$CX=null,this.$QU=null,this.$N=!1,this.$L=null,this.$SVG=!1,this.props=e||p,this.context=t||p};t.Component=Qe,Qe.prototype.forceUpdate=function(e){this.$UN||Ye(this,{},e,!0)},Qe.prototype.setState=function(e,t){this.$UN||this.$BS||Ye(this,e,t,!1)},Qe.prototype.render=function(e,t,n){return null};t.version="7.3.3"},function(e,t,n){"use strict";var o=function(e){var t,n=Object.prototype,o=n.hasOwnProperty,r="function"==typeof Symbol?Symbol:{},a=r.iterator||"@@iterator",i=r.asyncIterator||"@@asyncIterator",c=r.toStringTag||"@@toStringTag";function l(e,t,n,o){var r=t&&t.prototype instanceof h?t:h,a=Object.create(r.prototype),i=new w(o||[]);return a._invoke=function(e,t,n){var o=d;return function(r,a){if(o===p)throw new Error("Generator is already running");if(o===m){if("throw"===r)throw a;return S()}for(n.method=r,n.arg=a;;){var i=n.delegate;if(i){var c=k(i,n);if(c){if(c===f)continue;return c}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===d)throw o=m,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=p;var l=u(e,t,n);if("normal"===l.type){if(o=n.done?m:s,l.arg===f)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o=m,n.method="throw",n.arg=l.arg)}}}(e,n,i),a}function u(e,t,n){try{return{type:"normal",arg:e.call(t,n)}}catch(o){return{type:"throw",arg:o}}}e.wrap=l;var d="suspendedStart",s="suspendedYield",p="executing",m="completed",f={};function h(){}function C(){}function g(){}var b={};b[a]=function(){return this};var N=Object.getPrototypeOf,v=N&&N(N(B([])));v&&v!==n&&o.call(v,a)&&(b=v);var V=g.prototype=h.prototype=Object.create(b);function y(e){["next","throw","return"].forEach((function(t){e[t]=function(e){return this._invoke(t,e)}}))}function _(e){var t;this._invoke=function(n,r){function a(){return new Promise((function(t,a){!function i(t,n,r,a){var c=u(e[t],e,n);if("throw"!==c.type){var l=c.arg,d=l.value;return d&&"object"==typeof d&&o.call(d,"__await")?Promise.resolve(d.__await).then((function(e){i("next",e,r,a)}),(function(e){i("throw",e,r,a)})):Promise.resolve(d).then((function(e){l.value=e,r(l)}),(function(e){return i("throw",e,r,a)}))}a(c.arg)}(n,r,t,a)}))}return t=t?t.then(a,a):a()}}function k(e,n){var o=e.iterator[n.method];if(o===t){if(n.delegate=null,"throw"===n.method){if(e.iterator["return"]&&(n.method="return",n.arg=t,k(e,n),"throw"===n.method))return f;n.method="throw",n.arg=new TypeError("The iterator does not provide a 'throw' method")}return f}var r=u(o,e.iterator,n.arg);if("throw"===r.type)return n.method="throw",n.arg=r.arg,n.delegate=null,f;var a=r.arg;return a?a.done?(n[e.resultName]=a.value,n.next=e.nextLoc,"return"!==n.method&&(n.method="next",n.arg=t),n.delegate=null,f):a:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,f)}function x(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function L(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function w(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(x,this),this.reset(!0)}function B(e){if(e){var n=e[a];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,i=function n(){for(;++r=0;--a){var i=this.tryEntries[a],c=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var l=o.call(i,"catchLoc"),u=o.call(i,"finallyLoc");if(l&&u){if(this.prev=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),L(n),f}},"catch":function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var o=n.completion;if("throw"===o.type){var r=o.arg;L(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(e,n,o){return this.delegate={iterator:B(e),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=t),f}},e}(e.exports);try{regeneratorRuntime=o}catch(r){Function("r","regeneratorRuntime = r")(o)}},function(e,t,n){"use strict";window.Int32Array||(window.Int32Array=Array)},function(e,t,n){"use strict";(function(e){ -/*! loadCSS. [c]2017 Filament Group, Inc. MIT License */ -var n;n=void 0!==e?e:void 0,t.loadCSS=function(e,t,o,r){var a,i=n.document,c=i.createElement("link");if(t)a=t;else{var l=(i.body||i.getElementsByTagName("head")[0]).childNodes;a=l[l.length-1]}var u=i.styleSheets;if(r)for(var d in r)r.hasOwnProperty(d)&&c.setAttribute(d,r[d]);c.rel="stylesheet",c.href=e,c.media="only x",function m(e){if(i.body)return e();setTimeout((function(){m(e)}))}((function(){a.parentNode.insertBefore(c,t?a:a.nextSibling)}));var s=function f(e){for(var t=c.href,n=u.length;n--;)if(u[n].href===t)return e();setTimeout((function(){f(e)}))};function p(){c.addEventListener&&c.removeEventListener("load",p),c.media=o||"all"}return c.addEventListener&&c.addEventListener("load",p),c.onloadcssdefined=s,s(p),c}}).call(this,n(118))},function(e,t,n){"use strict";t.__esModule=!0,t.Achievements=t.Score=t.Achievement=void 0;var o=n(0),r=n(3),a=n(2),i=function(e){var t=e.name,n=e.desc,r=e.icon_class,i=e.value;return(0,o.createVNode)(1,"tr",null,[(0,o.createVNode)(1,"td",null,(0,o.createComponentVNode)(2,a.Box,{className:r}),2,{style:{padding:"6px"}}),(0,o.createVNode)(1,"td",null,[(0,o.createVNode)(1,"h1",null,t,0),n,(0,o.createComponentVNode)(2,a.Box,{color:i?"good":"bad",content:i?"Unlocked":"Locked"})],0,{style:{"vertical-align":"top"}})],4,null,t)};t.Achievement=i;var c=function(e){var t=e.name,n=e.desc,r=e.icon_class,i=e.value;return(0,o.createVNode)(1,"tr",null,[(0,o.createVNode)(1,"td",null,(0,o.createComponentVNode)(2,a.Box,{className:r}),2,{style:{padding:"6px"}}),(0,o.createVNode)(1,"td",null,[(0,o.createVNode)(1,"h1",null,t,0),n,(0,o.createComponentVNode)(2,a.Box,{color:i>0?"good":"bad",content:i>0?"Earned "+i+" times":"Locked"})],0,{style:{"vertical-align":"top"}})],4,null,t)};t.Score=c;t.Achievements=function(e){var t=(0,r.useBackend)(e).data;return(0,o.createComponentVNode)(2,a.Tabs,{children:[t.categories.map((function(e){return(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:e,children:(0,o.createComponentVNode)(2,a.Box,{as:"Table",children:t.achievements.filter((function(t){return t.category===e})).map((function(e){return e.score?(0,o.createComponentVNode)(2,c,{name:e.name,desc:e.desc,icon_class:e.icon_class,value:e.value},e.name):(0,o.createComponentVNode)(2,i,{name:e.name,desc:e.desc,icon_class:e.icon_class,value:e.value},e.name)}))})},e)})),(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:"High Scores",children:(0,o.createComponentVNode)(2,a.Tabs,{vertical:!0,children:t.highscore.map((function(e){return(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:e.name,children:(0,o.createComponentVNode)(2,a.Table,{children:[(0,o.createComponentVNode)(2,a.Table.Row,{className:"candystripe",children:[(0,o.createComponentVNode)(2,a.Table.Cell,{color:"label",textAlign:"center",children:"#"}),(0,o.createComponentVNode)(2,a.Table.Cell,{color:"label",textAlign:"center",children:"Key"}),(0,o.createComponentVNode)(2,a.Table.Cell,{color:"label",textAlign:"center",children:"Score"})]}),Object.keys(e.scores).map((function(n,r){return(0,o.createComponentVNode)(2,a.Table.Row,{className:"candystripe",m:2,children:[(0,o.createComponentVNode)(2,a.Table.Cell,{color:"label",textAlign:"center",children:r+1}),(0,o.createComponentVNode)(2,a.Table.Cell,{color:n===t.user_ckey&&"green",textAlign:"center",children:[0===r&&(0,o.createComponentVNode)(2,a.Icon,{name:"crown",color:"gold",mr:2}),n,0===r&&(0,o.createComponentVNode)(2,a.Icon,{name:"crown",color:"gold",ml:2})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{textAlign:"center",children:e.scores[n]})]},n)}))]})},e.name)}))})})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.BlockQuote=void 0;var o=n(0),r=n(11),a=n(19);t.BlockQuote=function(e){var t=e.className,n=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,["className"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({className:(0,r.classes)(["BlockQuote",t])},n)))}},function(e,t,n){"use strict";var o,r;t.__esModule=!0,t.VNodeFlags=t.ChildFlags=void 0,t.VNodeFlags=o,function(e){e[e.HtmlElement=1]="HtmlElement",e[e.ComponentUnknown=2]="ComponentUnknown",e[e.ComponentClass=4]="ComponentClass",e[e.ComponentFunction=8]="ComponentFunction",e[e.Text=16]="Text",e[e.SvgElement=32]="SvgElement",e[e.InputElement=64]="InputElement",e[e.TextareaElement=128]="TextareaElement",e[e.SelectElement=256]="SelectElement",e[e.Void=512]="Void",e[e.Portal=1024]="Portal",e[e.ReCreate=2048]="ReCreate",e[e.ContentEditable=4096]="ContentEditable",e[e.Fragment=8192]="Fragment",e[e.InUse=16384]="InUse",e[e.ForwardRef=32768]="ForwardRef",e[e.Normalized=65536]="Normalized",e[e.ForwardRefComponent=32776]="ForwardRefComponent",e[e.FormElement=448]="FormElement",e[e.Element=481]="Element",e[e.Component=14]="Component",e[e.DOMRef=2033]="DOMRef",e[e.InUseOrNormalized=81920]="InUseOrNormalized",e[e.ClearInUse=-16385]="ClearInUse",e[e.ComponentKnown=12]="ComponentKnown"}(o||(t.VNodeFlags=o={})),t.ChildFlags=r,function(e){e[e.UnknownChildren=0]="UnknownChildren",e[e.HasInvalidChildren=1]="HasInvalidChildren",e[e.HasVNodeChildren=2]="HasVNodeChildren",e[e.HasNonKeyedChildren=4]="HasNonKeyedChildren",e[e.HasKeyedChildren=8]="HasKeyedChildren",e[e.HasTextChildren=16]="HasTextChildren",e[e.MultipleChildren=12]="MultipleChildren"}(r||(t.ChildFlags=r={}))},function(e,t,n){"use strict";t.__esModule=!0,t.ColorBox=void 0;var o=n(0),r=n(11),a=n(19);var i=function(e){var t=e.color,n=e.content,i=e.className,c=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,["color","content","className"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({className:(0,r.classes)(["ColorBox",i]),color:n?null:"transparent",backgroundColor:t,content:n||"."},c)))};t.ColorBox=i,i.defaultHooks=r.pureComponentHooks},function(e,t,n){"use strict";t.__esModule=!0,t.Collapsible=void 0;var o=n(0),r=n(19),a=n(114);var i=function(e){var t,n;function i(t){var n;n=e.call(this,t)||this;var o=t.open;return n.state={open:o||!1},n}return n=e,(t=i).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,i.prototype.render=function(){var e=this,t=this.props,n=this.state.open,i=t.children,c=t.color,l=void 0===c?"default":c,u=t.title,d=t.buttons,s=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(t,["children","color","title","buttons"]);return(0,o.createComponentVNode)(2,r.Box,{mb:1,children:[(0,o.createVNode)(1,"div","Table",[(0,o.createVNode)(1,"div","Table__cell",(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Button,Object.assign({fluid:!0,color:l,icon:n?"chevron-down":"chevron-right",onClick:function(){return e.setState({open:!n})}},s,{children:u}))),2),d&&(0,o.createVNode)(1,"div","Table__cell Table__cell--collapsing",d,0)],0),n&&(0,o.createComponentVNode)(2,r.Box,{mt:1,children:i})]})},i}(o.Component);t.Collapsible=i},function(e,t,n){"use strict";t.__esModule=!0,t.Dimmer=void 0;var o=n(0),r=n(19);t.Dimmer=function(e){var t=e.style,n=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,["style"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,r.Box,Object.assign({style:Object.assign({position:"absolute",top:0,bottom:0,left:0,right:0,"background-color":"rgba(0, 0, 0, 0.75)","z-index":1},t)},n)))}},function(e,t,n){"use strict";t.__esModule=!0,t.Dropdown=void 0;var o=n(0),r=n(11),a=n(19),i=n(87);function c(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var l=function(e){var t,n;function l(t){var n;return(n=e.call(this,t)||this).state={selected:t.selected,open:!1},n.handleClick=function(){n.state.open&&n.setOpen(!1)},n}n=e,(t=l).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var u=l.prototype;return u.componentWillUnmount=function(){window.removeEventListener("click",this.handleClick)},u.setOpen=function(e){var t=this;this.setState({open:e}),e?(setTimeout((function(){return window.addEventListener("click",t.handleClick)})),this.menuRef.focus()):window.removeEventListener("click",this.handleClick)},u.setSelected=function(e){this.setState({selected:e}),this.setOpen(!1),this.props.onSelected(e)},u.buildMenu=function(){var e=this,t=this.props.options,n=(void 0===t?[]:t).map((function(t){return(0,o.createVNode)(1,"div","Dropdown__menuentry",t,0,{onClick:function(n){e.setSelected(t)}},t)}));return n.length?n:"No Options Found"},u.render=function(){var e=this,t=this.props,n=t.color,l=void 0===n?"default":n,u=t.over,d=t.width,s=(t.onClick,t.selected,c(t,["color","over","width","onClick","selected"])),p=s.className,m=c(s,["className"]),f=u?!this.state.open:this.state.open,h=this.state.open?(0,o.createVNode)(1,"div",(0,r.classes)(["Dropdown__menu",u&&"Dropdown__over"]),this.buildMenu(),0,{tabIndex:"-1",style:{width:d}},null,(function(t){e.menuRef=t})):null;return(0,o.createVNode)(1,"div","Dropdown",[(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({width:d,className:(0,r.classes)(["Dropdown__control","Button","Button--color--"+l,p])},m,{onClick:function(t){e.setOpen(!e.state.open)},children:[(0,o.createVNode)(1,"span","Dropdown__selected-text",this.state.selected,0),(0,o.createVNode)(1,"span","Dropdown__arrow-button",(0,o.createComponentVNode)(2,i.Icon,{name:f?"chevron-up":"chevron-down"}),2)]}))),h],0)},l}(o.Component);t.Dropdown=l},function(e,t,n){"use strict";t.__esModule=!0,t.FlexItem=t.computeFlexItemProps=t.Flex=t.computeFlexProps=void 0;var o=n(0),r=n(11),a=n(19);function i(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var c=function(e){var t=e.className,n=e.direction,o=e.wrap,a=e.align,c=e.justify,l=e.spacing,u=void 0===l?0:l,d=i(e,["className","direction","wrap","align","justify","spacing"]);return Object.assign({className:(0,r.classes)(["Flex",u>0&&"Flex--spacing--"+u,t]),style:Object.assign({},d.style,{"flex-direction":n,"flex-wrap":o,"align-items":a,"justify-content":c})},d)};t.computeFlexProps=c;var l=function(e){return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({},c(e))))};t.Flex=l,l.defaultHooks=r.pureComponentHooks;var u=function(e){var t=e.className,n=e.grow,o=e.order,a=e.align,c=i(e,["className","grow","order","align"]);return Object.assign({className:(0,r.classes)(["Flex__item",t]),style:Object.assign({},c.style,{"flex-grow":n,order:o,"align-self":a})},c)};t.computeFlexItemProps=u;var d=function(e){return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({},u(e))))};t.FlexItem=d,d.defaultHooks=r.pureComponentHooks,l.Item=d},function(e,t,n){"use strict";t.__esModule=!0,t.NoticeBox=void 0;var o=n(0),r=n(11),a=n(19);var i=function(e){var t=e.className,n=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,["className"]);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({className:(0,r.classes)(["NoticeBox",t])},n)))};t.NoticeBox=i,i.defaultHooks=r.pureComponentHooks},function(e,t,n){"use strict";t.__esModule=!0,t.NumberInput=void 0;var o=n(0),r=n(17),a=n(11),i=n(16),c=n(158),l=n(19);var u=function(e){var t,n;function u(t){var n;n=e.call(this,t)||this;var a=t.value;return n.inputRef=(0,o.createRef)(),n.state={value:a,dragging:!1,editing:!1,internalValue:null,origin:null,suppressingFlicker:!1},n.flickerTimer=null,n.suppressFlicker=function(){var e=n.props.suppressFlicker;e>0&&(n.setState({suppressingFlicker:!0}),clearTimeout(n.flickerTimer),n.flickerTimer=setTimeout((function(){return n.setState({suppressingFlicker:!1})}),e))},n.handleDragStart=function(e){var t=n.props.value;n.state.editing||(document.body.style["pointer-events"]="none",n.ref=e.target,n.setState({dragging:!1,origin:e.screenY,value:t,internalValue:t}),n.timer=setTimeout((function(){n.setState({dragging:!0})}),250),n.dragInterval=setInterval((function(){var t=n.state,o=t.dragging,r=t.value,a=n.props.onDrag;o&&a&&a(e,r)}),500),document.addEventListener("mousemove",n.handleDragMove),document.addEventListener("mouseup",n.handleDragEnd))},n.handleDragMove=function(e){var t=n.props,o=t.minValue,a=t.maxValue,i=t.step,c=t.stepPixelSize;n.setState((function(t){var n=Object.assign({},t),l=n.origin-e.screenY;if(t.dragging){var u=Number.isFinite(o)?o%i:0;n.internalValue=(0,r.clamp)(n.internalValue+l*i/c,o-i,a+i),n.value=(0,r.clamp)(n.internalValue-n.internalValue%i+u,o,a),n.origin=e.screenY}else Math.abs(l)>4&&(n.dragging=!0);return n}))},n.handleDragEnd=function(e){var t=n.props,o=t.onChange,r=t.onDrag,a=n.state,i=a.dragging,c=a.value,l=a.internalValue;if(document.body.style["pointer-events"]="auto",clearTimeout(n.timer),clearInterval(n.dragInterval),n.setState({dragging:!1,editing:!i,origin:null}),document.removeEventListener("mousemove",n.handleDragMove),document.removeEventListener("mouseup",n.handleDragEnd),i)n.suppressFlicker(),o&&o(e,c),r&&r(e,c);else if(n.inputRef){var u=n.inputRef.current;u.value=l;try{u.focus(),u.select()}catch(d){}}},n}return n=e,(t=u).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,u.prototype.render=function(){var e=this,t=this.state,n=t.dragging,u=t.editing,d=t.value,s=t.suppressingFlicker,p=this.props,m=p.className,f=p.fluid,h=p.animated,C=p.value,g=p.unit,b=p.minValue,N=p.maxValue,v=p.height,V=p.width,y=p.lineHeight,_=p.fontSize,k=p.format,x=p.onChange,L=p.onDrag,w=C;(n||s)&&(w=d);var B=function(e){return(0,o.createVNode)(1,"div","NumberInput__content",e+(g?" "+g:""),0,{unselectable:i.tridentVersion<=4})},S=h&&!n&&!s&&(0,o.createComponentVNode)(2,c.AnimatedNumber,{value:w,format:k,children:B})||B(k?k(w):w);return(0,o.createComponentVNode)(2,l.Box,{className:(0,a.classes)(["NumberInput",f&&"NumberInput--fluid",m]),minWidth:V,minHeight:v,lineHeight:y,fontSize:_,onMouseDown:this.handleDragStart,children:[(0,o.createVNode)(1,"div","NumberInput__barContainer",(0,o.createVNode)(1,"div","NumberInput__bar",null,1,{style:{height:(0,r.clamp)((w-b)/(N-b)*100,0,100)+"%"}}),2),S,(0,o.createVNode)(64,"input","NumberInput__input",null,1,{style:{display:u?undefined:"none",height:v,"line-height":y,"font-size":_},onBlur:function(t){if(u){var n=(0,r.clamp)(t.target.value,b,N);e.setState({editing:!1,value:n}),e.suppressFlicker(),x&&x(t,n),L&&L(t,n)}},onKeyDown:function(t){if(13===t.keyCode){var n=(0,r.clamp)(t.target.value,b,N);return e.setState({editing:!1,value:n}),e.suppressFlicker(),x&&x(t,n),void(L&&L(t,n))}27!==t.keyCode||e.setState({editing:!1})}},null,this.inputRef)]})},u}(o.Component);t.NumberInput=u,u.defaultHooks=a.pureComponentHooks,u.defaultProps={minValue:-Infinity,maxValue:+Infinity,step:1,stepPixelSize:1,suppressFlicker:50}},function(e,t,n){"use strict";t.__esModule=!0,t.ProgressBar=void 0;var o=n(0),r=n(11),a=n(17),i=function(e){var t=e.value,n=e.minValue,i=void 0===n?0:n,c=e.maxValue,l=void 0===c?1:c,u=e.ranges,d=void 0===u?{}:u,s=e.content,p=e.children,m=(t-i)/(l-i),f=s!==undefined||p!==undefined,h=e.color;if(!h)for(var C=0,g=Object.keys(d);C=N[0]&&t<=N[1]){h=b;break}}return h||(h="default"),(0,o.createVNode)(1,"div",(0,r.classes)(["ProgressBar","ProgressBar--color--"+h]),[(0,o.createVNode)(1,"div","ProgressBar__fill",null,1,{style:{width:100*(0,a.clamp)(m,0,1)+"%"}}),(0,o.createVNode)(1,"div","ProgressBar__content",[f&&s,f&&p,!f&&(0,a.toFixed)(100*m)+"%"],0)],4)};t.ProgressBar=i,i.defaultHooks=r.pureComponentHooks},function(e,t,n){"use strict";t.__esModule=!0,t.Section=void 0;var o=n(0),r=n(11),a=n(19);var i=function(e){var t=e.className,n=e.title,i=e.level,c=void 0===i?1:i,l=e.buttons,u=e.content,d=e.children,s=function(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}(e,["className","title","level","buttons","content","children"]),p=!(0,r.isFalsy)(n)||!(0,r.isFalsy)(l),m=!(0,r.isFalsy)(u)||!(0,r.isFalsy)(d);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({className:(0,r.classes)(["Section","Section--level--"+c,t])},s,{children:[p&&(0,o.createVNode)(1,"div","Section__title",[(0,o.createVNode)(1,"span","Section__titleText",n,0),(0,o.createVNode)(1,"div","Section__buttons",l,0)],4),m&&(0,o.createVNode)(1,"div","Section__content",[u,d],0)]})))};t.Section=i,i.defaultHooks=r.pureComponentHooks},function(e,t,n){"use strict";t.__esModule=!0,t.Tab=t.Tabs=void 0;var o=n(0),r=n(11),a=n(19),i=n(114);function c(e,t){if(null==e)return{};var n,o,r={},a=Object.keys(e);for(o=0;o=0||(r[n]=e[n]);return r}var l=function(e){var t=e,n=Array.isArray(t),o=0;for(t=n?t:t[Symbol.iterator]();;){var r;if(n){if(o>=t.length)break;r=t[o++]}else{if((o=t.next()).done)break;r=o.value}var a=r;if(!a.props||"Tab"!==a.props.__type__){var i=JSON.stringify(a,null,2);throw new Error(" only accepts children of type .This is what we received: "+i)}}},u=function(e){var t,n;function u(t){var n;return(n=e.call(this,t)||this).state={activeTabKey:null},n}n=e,(t=u).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var d=u.prototype;return d.getActiveTab=function(){var e=this.state,t=this.props,n=(0,r.normalizeChildren)(t.children);l(n);var o=t.activeTab||e.activeTabKey,a=n.find((function(e){return(e.key||e.props.label)===o}));return a||(a=n[0],o=a&&(a.key||a.props.label)),{tabs:n,activeTab:a,activeTabKey:o}},d.render=function(){var e=this,t=this.props,n=t.className,l=t.vertical,u=(t.children,c(t,["className","vertical","children"])),d=this.getActiveTab(),s=d.tabs,p=d.activeTab,m=d.activeTabKey,f=null;return p&&(f=p.props.content||p.props.children),"function"==typeof f&&(f=f(m)),(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({className:(0,r.classes)(["Tabs",l&&"Tabs--vertical",n])},u,{children:[(0,o.createVNode)(1,"div","Tabs__tabBox",s.map((function(t){var n=t.props,a=n.className,l=n.label,u=(n.content,n.children,n.onClick),d=n.highlight,s=c(n,["className","label","content","children","onClick","highlight"]),p=t.key||t.props.label,f=t.active||p===m;return(0,o.normalizeProps)((0,o.createComponentVNode)(2,i.Button,Object.assign({className:(0,r.classes)(["Tabs__tab",f&&"Tabs__tab--active",d&&!f&&"color-yellow",a]),selected:f,color:"transparent",onClick:function(n){e.setState({activeTabKey:p}),u&&u(n,t)}},s,{children:l}),p))})),0),(0,o.createVNode)(1,"div","Tabs__content",f||null,0)]})))},u}(o.Component);t.Tabs=u;var d=function(e){return null};t.Tab=d,d.defaultProps={__type__:"Tab"},u.Tab=d},function(e,t,n){"use strict";t.__esModule=!0,t.TitleBar=void 0;var o=n(0),r=n(11),a=n(23),i=n(16),c=n(32),l=n(87),u=function(e){switch(e){case c.UI_INTERACTIVE:return"good";case c.UI_UPDATE:return"average";case c.UI_DISABLED:default:return"bad"}},d=function(e){var t=e.className,n=e.title,c=e.status,d=e.fancy,s=e.onDragStart,p=e.onClose;return(0,o.createVNode)(1,"div",(0,r.classes)(["TitleBar",t]),[(0,o.createComponentVNode)(2,l.Icon,{className:"TitleBar__statusIcon",color:u(c),name:"eye"}),(0,o.createVNode)(1,"div","TitleBar__title",n===n.toLowerCase()?(0,a.toTitleCase)(n):n,0),(0,o.createVNode)(1,"div","TitleBar__dragZone",null,1,{onMousedown:function(e){return d&&s(e)}}),!!d&&(0,o.createVNode)(1,"div","TitleBar__close TitleBar__clickable",i.tridentVersion<=4?"x":"\xd7",0,{onclick:p})],0)};t.TitleBar=d,d.defaultHooks=r.pureComponentHooks},function(e,t,n){"use strict";t.__esModule=!0,t.Chart=void 0;var o=n(0),r=n(24),a=n(19),i=n(11),c=n(16);var l=function(e,t,n,o){if(0===e.length)return[];var a=(0,r.zipWith)(Math.min).apply(void 0,e),i=(0,r.zipWith)(Math.max).apply(void 0,e);return n!==undefined&&(a[0]=n[0],i[0]=n[1]),o!==undefined&&(a[1]=o[0],i[1]=o[1]),(0,r.map)((function(e){return(0,r.zipWith)((function(e,t,n,o){return(e-t)/(n-t)*o}))(e,a,i,t)}))(e)},u=function(e){for(var t="",n=0;n=0||(r[n]=e[n]);return r}(t,["data","rangeX","rangeY","fillColor","strokeColor","strokeWidth"]),g=this.state.viewBox,b=l(r,g,i,c);if(b.length>0){var N=b[0],v=b[b.length-1];b.push([g[0]+h,v[1]]),b.push([g[0]+h,-h]),b.push([-h,-h]),b.push([-h,N[1]])}var V=u(b);return(0,o.normalizeProps)((0,o.createComponentVNode)(2,a.Box,Object.assign({position:"relative"},C,{children:function(t){return(0,o.normalizeProps)((0,o.createVNode)(1,"div",null,(0,o.createVNode)(32,"svg",null,(0,o.createVNode)(32,"polyline",null,null,1,{transform:"scale(1, -1) translate(0, -"+g[1]+")",fill:s,stroke:m,"stroke-width":h,points:V}),2,{viewBox:"0 0 "+g[0]+" "+g[1],preserveAspectRatio:"none",style:{position:"absolute",top:0,left:0,right:0,bottom:0,overflow:"hidden"}}),2,Object.assign({},t),null,e.ref))}})))},r}(o.Component);d.defaultHooks=i.pureComponentHooks;var s={Line:c.tridentVersion<=4?function(e){return null}:d};t.Chart=s},function(e,t,n){"use strict";t.__esModule=!0,t.AiAirlock=void 0;var o=n(0),r=n(3),a=n(2);t.AiAirlock=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c={2:{color:"good",localStatusText:"Offline"},1:{color:"average",localStatusText:"Caution"},0:{color:"bad",localStatusText:"Optimal"}},l=c[i.power.main]||c[0],u=c[i.power.backup]||c[0],d=c[i.shock]||c[0];return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Power Status",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Main",color:l.color,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",disabled:!i.power.main,content:"Disrupt",onClick:function(){return n("disrupt-main")}}),children:[i.power.main?"Online":"Offline"," ",i.wires.main_1&&i.wires.main_2?i.power.main_timeleft>0&&"["+i.power.main_timeleft+"s]":"[Wires have been cut!]"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Backup",color:u.color,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",disabled:!i.power.backup,content:"Disrupt",onClick:function(){return n("disrupt-backup")}}),children:[i.power.backup?"Online":"Offline"," ",i.wires.backup_1&&i.wires.backup_2?i.power.backup_timeleft>0&&"["+i.power.backup_timeleft+"s]":"[Wires have been cut!]"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Electrify",color:d.color,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"wrench",disabled:!(i.wires.shock&&0===i.shock),content:"Restore",onClick:function(){return n("shock-restore")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"bolt",disabled:!i.wires.shock,content:"Temporary",onClick:function(){return n("shock-temp")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"bolt",disabled:!i.wires.shock,content:"Permanent",onClick:function(){return n("shock-perm")}})],4),children:[2===i.shock?"Safe":"Electrified"," ",(i.wires.shock?i.shock_timeleft>0&&"["+i.shock_timeleft+"s]":"[Wires have been cut!]")||-1===i.shock_timeleft&&"[Permanent]"]})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Access and Door Control",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"ID Scan",color:"bad",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.id_scanner?"power-off":"times",content:i.id_scanner?"Enabled":"Disabled",selected:i.id_scanner,disabled:!i.wires.id_scanner,onClick:function(){return n("idscan-toggle")}}),children:!i.wires.id_scanner&&"[Wires have been cut!]"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Emergency Access",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.emergency?"power-off":"times",content:i.emergency?"Enabled":"Disabled",selected:i.emergency,onClick:function(){return n("emergency-toggle")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Divider),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door Bolts",color:"bad",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.locked?"lock":"unlock",content:i.locked?"Lowered":"Raised",selected:i.locked,disabled:!i.wires.bolts,onClick:function(){return n("bolt-toggle")}}),children:!i.wires.bolts&&"[Wires have been cut!]"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door Bolt Lights",color:"bad",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.lights?"power-off":"times",content:i.lights?"Enabled":"Disabled",selected:i.lights,disabled:!i.wires.lights,onClick:function(){return n("light-toggle")}}),children:!i.wires.lights&&"[Wires have been cut!]"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door Force Sensors",color:"bad",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.safe?"power-off":"times",content:i.safe?"Enabled":"Disabled",selected:i.safe,disabled:!i.wires.safe,onClick:function(){return n("safe-toggle")}}),children:!i.wires.safe&&"[Wires have been cut!]"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door Timing Safety",color:"bad",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.speed?"power-off":"times",content:i.speed?"Enabled":"Disabled",selected:i.speed,disabled:!i.wires.timing,onClick:function(){return n("speed-toggle")}}),children:!i.wires.timing&&"[Wires have been cut!]"}),(0,o.createComponentVNode)(2,a.LabeledList.Divider),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door Control",color:"bad",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:i.opened?"sign-out-alt":"sign-in-alt",content:i.opened?"Open":"Closed",selected:i.opened,disabled:i.locked||i.welded,onClick:function(){return n("open-close")}}),children:!(!i.locked&&!i.welded)&&(0,o.createVNode)(1,"span",null,[(0,o.createTextVNode)("[Door is "),i.locked?"bolted":"",i.locked&&i.welded?" and ":"",i.welded?"welded":"",(0,o.createTextVNode)("!]")],0)})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.AirAlarm=void 0;var o=n(0),r=n(17),a=n(23),i=n(3),c=n(2),l=n(32),u=n(69);t.AirAlarm=function(e){var t=e.state,n=(0,i.useBackend)(e),r=n.act,a=n.data,c=a.locked&&!a.siliconUser;return(0,o.createFragment)([(0,o.createComponentVNode)(2,u.InterfaceLockNoticeBox,{siliconUser:a.siliconUser,locked:a.locked,onLockStatusChange:function(){return r("lock")}}),(0,o.createComponentVNode)(2,d,{state:t}),!c&&(0,o.createComponentVNode)(2,p,{state:t})],0)};var d=function(e){var t=(0,i.useBackend)(e).data,n=(t.environment_data||[]).filter((function(e){return e.value>=.01})),a={0:{color:"good",localStatusText:"Optimal"},1:{color:"average",localStatusText:"Caution"},2:{color:"bad",localStatusText:"Danger (Internals Required)"}},l=a[t.danger_level]||a[0];return(0,o.createComponentVNode)(2,c.Section,{title:"Air Status",children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[n.length>0&&(0,o.createFragment)([n.map((function(e){var t=a[e.danger_level]||a[0];return(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:e.name,color:t.color,children:[(0,r.toFixed)(e.value,2),e.unit]},e.name)})),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Local status",color:l.color,children:l.localStatusText}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Area status",color:t.atmos_alarm||t.fire_alarm?"bad":"good",children:(t.atmos_alarm?"Atmosphere Alarm":t.fire_alarm&&"Fire Alarm")||"Nominal"})],0)||(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Warning",color:"bad",children:"Cannot obtain air sample for analysis."}),!!t.emagged&&(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Warning",color:"bad",children:"Safety measures offline. Device may exhibit abnormal behavior."})]})})},s={home:{title:"Air Controls",component:function(){return m}},vents:{title:"Vent Controls",component:function(){return f}},scrubbers:{title:"Scrubber Controls",component:function(){return C}},modes:{title:"Operating Mode",component:function(){return b}},thresholds:{title:"Alarm Thresholds",component:function(){return N}}},p=function(e){var t=e.state,n=(0,i.useBackend)(e),r=n.act,a=n.config,l=s[a.screen]||s.home,u=l.component();return(0,o.createComponentVNode)(2,c.Section,{title:l.title,buttons:"home"!==a.screen&&(0,o.createComponentVNode)(2,c.Button,{icon:"arrow-left",content:"Back",onClick:function(){return r("tgui:view",{screen:"home"})}}),children:(0,o.createComponentVNode)(2,u,{state:t})})},m=function(e){var t=(0,i.useBackend)(e),n=t.act,r=t.data,a=r.mode,l=r.atmos_alarm;return(0,o.createFragment)([(0,o.createComponentVNode)(2,c.Button,{icon:l?"exclamation-triangle":"exclamation",color:l&&"caution",content:"Area Atmosphere Alarm",onClick:function(){return n(l?"reset":"alarm")}}),(0,o.createComponentVNode)(2,c.Box,{mt:1}),(0,o.createComponentVNode)(2,c.Button,{icon:3===a?"exclamation-triangle":"exclamation",color:3===a&&"danger",content:"Panic Siphon",onClick:function(){return n("mode",{mode:3===a?1:3})}}),(0,o.createComponentVNode)(2,c.Box,{mt:2}),(0,o.createComponentVNode)(2,c.Button,{icon:"sign-out-alt",content:"Vent Controls",onClick:function(){return n("tgui:view",{screen:"vents"})}}),(0,o.createComponentVNode)(2,c.Box,{mt:1}),(0,o.createComponentVNode)(2,c.Button,{icon:"filter",content:"Scrubber Controls",onClick:function(){return n("tgui:view",{screen:"scrubbers"})}}),(0,o.createComponentVNode)(2,c.Box,{mt:1}),(0,o.createComponentVNode)(2,c.Button,{icon:"cog",content:"Operating Mode",onClick:function(){return n("tgui:view",{screen:"modes"})}}),(0,o.createComponentVNode)(2,c.Box,{mt:1}),(0,o.createComponentVNode)(2,c.Button,{icon:"chart-bar",content:"Alarm Thresholds",onClick:function(){return n("tgui:view",{screen:"thresholds"})}})],4)},f=function(e){var t=e.state,n=(0,i.useBackend)(e).data.vents;return n&&0!==n.length?n.map((function(e){return(0,o.normalizeProps)((0,o.createComponentVNode)(2,h,Object.assign({state:t},e),e.id_tag))})):"Nothing to show"},h=function(e){var t=e.id_tag,n=e.long_name,r=e.power,l=e.checks,u=e.excheck,d=e.incheck,s=e.direction,p=e.external,m=e.internal,f=e.extdefault,h=e.intdefault,C=(0,i.useBackend)(e).act;return(0,o.createComponentVNode)(2,c.Section,{level:2,title:(0,a.decodeHtmlEntities)(n),buttons:(0,o.createComponentVNode)(2,c.Button,{icon:r?"power-off":"times",selected:r,content:r?"On":"Off",onClick:function(){return C("power",{id_tag:t,val:Number(!r)})}}),children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Mode",children:"release"===s?"Pressurizing":"Releasing"}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Pressure Regulator",children:[(0,o.createComponentVNode)(2,c.Button,{icon:"sign-in-alt",content:"Internal",selected:d,onClick:function(){return C("incheck",{id_tag:t,val:l})}}),(0,o.createComponentVNode)(2,c.Button,{icon:"sign-out-alt",content:"External",selected:u,onClick:function(){return C("excheck",{id_tag:t,val:l})}})]}),!!d&&(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Internal Target",children:[(0,o.createComponentVNode)(2,c.NumberInput,{value:Math.round(m),unit:"kPa",width:"75px",minValue:0,step:10,maxValue:5066,onChange:function(e,n){return C("set_internal_pressure",{id_tag:t,value:n})}}),(0,o.createComponentVNode)(2,c.Button,{icon:"undo",disabled:h,content:"Reset",onClick:function(){return C("reset_internal_pressure",{id_tag:t})}})]}),!!u&&(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"External Target",children:[(0,o.createComponentVNode)(2,c.NumberInput,{value:Math.round(p),unit:"kPa",width:"75px",minValue:0,step:10,maxValue:5066,onChange:function(e,n){return C("set_external_pressure",{id_tag:t,value:n})}}),(0,o.createComponentVNode)(2,c.Button,{icon:"undo",disabled:f,content:"Reset",onClick:function(){return C("reset_external_pressure",{id_tag:t})}})]})]})})},C=function(e){var t=e.state,n=(0,i.useBackend)(e).data.scrubbers;return n&&0!==n.length?n.map((function(e){return(0,o.normalizeProps)((0,o.createComponentVNode)(2,g,Object.assign({state:t},e),e.id_tag))})):"Nothing to show"},g=function(e){var t=e.long_name,n=e.power,r=e.scrubbing,u=e.id_tag,d=e.widenet,s=e.filter_types,p=(0,i.useBackend)(e).act;return(0,o.createComponentVNode)(2,c.Section,{level:2,title:(0,a.decodeHtmlEntities)(t),buttons:(0,o.createComponentVNode)(2,c.Button,{icon:n?"power-off":"times",content:n?"On":"Off",selected:n,onClick:function(){return p("power",{id_tag:u,val:Number(!n)})}}),children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Mode",children:[(0,o.createComponentVNode)(2,c.Button,{icon:r?"filter":"sign-in-alt",color:r||"danger",content:r?"Scrubbing":"Siphoning",onClick:function(){return p("scrubbing",{id_tag:u,val:Number(!r)})}}),(0,o.createComponentVNode)(2,c.Button,{icon:d?"expand":"compress",selected:d,content:d?"Expanded range":"Normal range",onClick:function(){return p("widenet",{id_tag:u,val:Number(!d)})}})]}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Filters",children:r&&s.map((function(e){return(0,o.createComponentVNode)(2,c.Button,{icon:e.enabled?"check-square-o":"square-o",content:(0,l.getGasLabel)(e.gas_id,e.gas_name),title:e.gas_name,selected:e.enabled,onClick:function(){return p("toggle_filter",{id_tag:u,val:e.gas_id})}},e.gas_id)}))||"N/A"})]})})},b=function(e){var t=(0,i.useBackend)(e),n=t.act,r=t.data.modes;return r&&0!==r.length?r.map((function(e){return(0,o.createFragment)([(0,o.createComponentVNode)(2,c.Button,{icon:e.selected?"check-square-o":"square-o",selected:e.selected,color:e.selected&&e.danger&&"danger",content:e.name,onClick:function(){return n("mode",{mode:e.mode})}}),(0,o.createComponentVNode)(2,c.Box,{mt:1})],4,e.mode)})):"Nothing to show"},N=function(e){var t=(0,i.useBackend)(e),n=t.act,a=t.data.thresholds;return(0,o.createVNode)(1,"table","LabeledList",[(0,o.createVNode)(1,"thead",null,(0,o.createVNode)(1,"tr",null,[(0,o.createVNode)(1,"td"),(0,o.createVNode)(1,"td","color-bad","min2",16),(0,o.createVNode)(1,"td","color-average","min1",16),(0,o.createVNode)(1,"td","color-average","max1",16),(0,o.createVNode)(1,"td","color-bad","max2",16)],4),2),(0,o.createVNode)(1,"tbody",null,a.map((function(e){return(0,o.createVNode)(1,"tr",null,[(0,o.createVNode)(1,"td","LabeledList__label",e.name,0),e.settings.map((function(e){return(0,o.createVNode)(1,"td",null,(0,o.createComponentVNode)(2,c.Button,{content:(0,r.toFixed)(e.selected,2),onClick:function(){return n("threshold",{env:e.env,"var":e.val})}}),2,null,e.val)}))],0,null,e.name)})),0)],4,{style:{width:"100%"}})}},function(e,t,n){"use strict";t.__esModule=!0,t.AirlockElectronics=void 0;var o=n(0),r=n(3),a=n(2);t.AirlockElectronics=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.regions||[],l={0:{icon:"times-circle"},1:{icon:"stop-circle"},2:{icon:"check-circle"}};return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Main",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Access Required",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.oneAccess?"unlock":"lock",content:i.oneAccess?"One":"All",onClick:function(){return n("one_access")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Mass Modify",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"check-double",content:"Grant All",onClick:function(){return n("grant_all")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"undo",content:"Clear All",onClick:function(){return n("clear_all")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Unrestricted Access",children:[(0,o.createComponentVNode)(2,a.Button,{icon:1&i.unres_direction?"check-square-o":"square-o",content:"North",selected:1&i.unres_direction,onClick:function(){return n("direc_set",{unres_direction:"1"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:2&i.unres_direction?"check-square-o":"square-o",content:"South",selected:2&i.unres_direction,onClick:function(){return n("direc_set",{unres_direction:"2"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:4&i.unres_direction?"check-square-o":"square-o",content:"East",selected:4&i.unres_direction,onClick:function(){return n("direc_set",{unres_direction:"4"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:8&i.unres_direction?"check-square-o":"square-o",content:"West",selected:8&i.unres_direction,onClick:function(){return n("direc_set",{unres_direction:"8"})}})]})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Access",children:(0,o.createComponentVNode)(2,a.Box,{height:"261px",children:(0,o.createComponentVNode)(2,a.Tabs,{vertical:!0,children:c.map((function(e){var t=e.name,r=e.accesses||[],i=l[function(e){var t=!1,n=!1;return e.forEach((function(e){e.req?t=!0:n=!0})),!t&&n?0:t&&n?1:2}(r)].icon;return(0,o.createComponentVNode)(2,a.Tabs.Tab,{icon:i,label:t,children:function(){return r.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{children:(0,o.createComponentVNode)(2,a.Button,{icon:e.req?"check-square-o":"square-o",content:e.name,selected:e.req,onClick:function(){return n("set",{access:e.id})}})},e.id)}))}},t)}))})})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.Apc=void 0;var o=n(0),r=n(3),a=n(2),i=n(69);t.Apc=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.locked&&!c.siliconUser,u={2:{color:"good",externalPowerText:"External Power",chargingText:"Fully Charged"},1:{color:"average",externalPowerText:"Low External Power",chargingText:"Charging"},0:{color:"bad",externalPowerText:"No External Power",chargingText:"Not Charging"}},d={1:{icon:"terminal",content:"Override Programming",action:"hack"},2:{icon:"caret-square-down",content:"Shunt Core Process",action:"occupy"},3:{icon:"caret-square-left",content:"Return to Main Core",action:"deoccupy"},4:{icon:"caret-square-down",content:"Shunt Core Process",action:"occupy"}},s=u[c.externalPower]||u[0],p=u[c.chargingStatus]||u[0],m=c.powerChannels||[],f=d[c.malfStatus]||d[0],h=c.powerCellStatus/100;return c.failTime>0?(0,o.createComponentVNode)(2,a.NoticeBox,{children:[(0,o.createVNode)(1,"b",null,(0,o.createVNode)(1,"h3",null,"SYSTEM FAILURE",16),2),(0,o.createVNode)(1,"i",null,"I/O regulators malfunction detected! Waiting for system reboot...",16),(0,o.createVNode)(1,"br"),"Automatic reboot in ",c.failTime," seconds...",(0,o.createComponentVNode)(2,a.Button,{icon:"sync",content:"Reboot Now",onClick:function(){return n("reboot")}})]}):(0,o.createFragment)([(0,o.createComponentVNode)(2,i.InterfaceLockNoticeBox,{siliconUser:c.siliconUser,locked:c.locked,onLockStatusChange:function(){return n("lock")}}),(0,o.createComponentVNode)(2,a.Section,{title:"Power Status",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Main Breaker",color:s.color,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:c.isOperating?"power-off":"times",content:c.isOperating?"On":"Off",selected:c.isOperating&&!l,disabled:l,onClick:function(){return n("breaker")}}),children:["[ ",s.externalPowerText," ]"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power Cell",children:(0,o.createComponentVNode)(2,a.ProgressBar,{color:"good",value:h})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Charge Mode",color:p.color,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:c.chargeMode?"sync":"close",content:c.chargeMode?"Auto":"Off",disabled:l,onClick:function(){return n("charge")}}),children:["[ ",p.chargingText," ]"]})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Power Channels",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[m.map((function(e){var t=e.topicParams;return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.title,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{inline:!0,mx:2,color:e.status>=2?"good":"bad",children:e.status>=2?"On":"Off"}),(0,o.createComponentVNode)(2,a.Button,{icon:"sync",content:"Auto",selected:!l&&(1===e.status||3===e.status),disabled:l,onClick:function(){return n("channel",t.auto)}}),(0,o.createComponentVNode)(2,a.Button,{icon:"power-off",content:"On",selected:!l&&2===e.status,disabled:l,onClick:function(){return n("channel",t.on)}}),(0,o.createComponentVNode)(2,a.Button,{icon:"times",content:"Off",selected:!l&&0===e.status,disabled:l,onClick:function(){return n("channel",t.off)}})],4),children:e.powerLoad},e.title)})),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Total Load",children:(0,o.createVNode)(1,"b",null,c.totalLoad,0)})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Misc",buttons:!!c.siliconUser&&(0,o.createFragment)([!!c.malfStatus&&(0,o.createComponentVNode)(2,a.Button,{icon:f.icon,content:f.content,color:"bad",onClick:function(){return n(f.action)}}),(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",content:"Overload",onClick:function(){return n("overload")}})],0),children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Cover Lock",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:c.coverLocked?"lock":"unlock",content:c.coverLocked?"Engaged":"Disengaged",disabled:l,onClick:function(){return n("cover")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Emergency Lighting",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",content:c.emergencyLights?"Enabled":"Disabled",disabled:l,onClick:function(){return n("emergency_lighting")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Night Shift Lighting",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",content:c.nightshiftLights?"Enabled":"Disabled",disabled:l,onClick:function(){return n("toggle_nightshift")}})})]}),c.hijackable&&(0,o.createComponentVNode)(2,a.Section,{title:"Hijacking",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"unlock",content:"Hijack",disabled:c.hijacker,onClick:function(){return n("hijack")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"lock",content:"Lockdown",disabled:!c.lockdownavail,onClick:function(){return n("lockdown")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",content:"Drain",disabled:!c.drainavail,onClick:function(){return n("drain")}})],4)})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.AtmosAlertConsole=void 0;var o=n(0),r=n(3),a=n(2);t.AtmosAlertConsole=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.priority||[],l=i.minor||[];return(0,o.createComponentVNode)(2,a.Section,{title:"Alarms",children:(0,o.createVNode)(1,"ul",null,[c.length>0?c.map((function(e){return(0,o.createVNode)(1,"li",null,(0,o.createComponentVNode)(2,a.Button,{icon:"times",content:e,color:"bad",onClick:function(){return n("clear",{zone:e})}}),2,null,e)})):(0,o.createVNode)(1,"li","color-good","No Priority Alerts",16),l.length>0?l.map((function(e){return(0,o.createVNode)(1,"li",null,(0,o.createComponentVNode)(2,a.Button,{icon:"times",content:e,color:"average",onClick:function(){return n("clear",{zone:e})}}),2,null,e)})):(0,o.createVNode)(1,"li","color-good","No Minor Alerts",16)],0)})}},function(e,t,n){"use strict";t.__esModule=!0,t.AtmosControlConsole=void 0;var o=n(0),r=n(24),a=n(17),i=n(3),c=n(2);t.AtmosControlConsole=function(e){var t=(0,i.useBackend)(e),n=t.act,l=t.data,u=l.sensors||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,c.Section,{title:!!l.tank&&u[0].long_name,children:u.map((function(e){var t=e.gases||{};return(0,o.createComponentVNode)(2,c.Section,{title:!l.tank&&e.long_name,level:2,children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Pressure",children:(0,a.toFixed)(e.pressure,2)+" kPa"}),!!e.temperature&&(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Temperature",children:(0,a.toFixed)(e.temperature,2)+" K"}),(0,r.map)((function(e,t){return(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:t,children:(0,a.toFixed)(e,2)+"%"})}))(t)]})},e.id_tag)}))}),l.tank&&(0,o.createComponentVNode)(2,c.Section,{title:"Controls",buttons:(0,o.createComponentVNode)(2,c.Button,{icon:"undo",content:"Reconnect",onClick:function(){return n("reconnect")}}),children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Input Injector",children:(0,o.createComponentVNode)(2,c.Button,{icon:l.inputting?"power-off":"times",content:l.inputting?"Injecting":"Off",selected:l.inputting,onClick:function(){return n("input")}})}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Input Rate",children:(0,o.createComponentVNode)(2,c.NumberInput,{value:l.inputRate,unit:"L/s",width:"63px",minValue:0,maxValue:200,suppressFlicker:2e3,onChange:function(e,t){return n("rate",{rate:t})}})}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Output Regulator",children:(0,o.createComponentVNode)(2,c.Button,{icon:l.outputting?"power-off":"times",content:l.outputting?"Open":"Closed",selected:l.outputting,onClick:function(){return n("output")}})}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Output Pressure",children:(0,o.createComponentVNode)(2,c.NumberInput,{value:parseFloat(l.outputPressure),unit:"kPa",width:"75px",minValue:0,maxValue:4500,step:10,suppressFlicker:2e3,onChange:function(e,t){return n("pressure",{pressure:t})}})})]})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.AtmosFilter=void 0;var o=n(0),r=n(3),a=n(2),i=n(32);t.AtmosFilter=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.filter_types||[];return(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power",children:(0,o.createComponentVNode)(2,a.Button,{icon:c.on?"power-off":"times",content:c.on?"On":"Off",selected:c.on,onClick:function(){return n("power")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Transfer Rate",children:[(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(c.rate),width:"63px",unit:"L/s",minValue:0,maxValue:200,onDrag:function(e,t){return n("rate",{rate:t})}}),(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"plus",content:"Max",disabled:c.rate===c.max_rate,onClick:function(){return n("rate",{rate:"max"})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Filter",children:l.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{selected:e.selected,content:(0,i.getGasLabel)(e.id,e.name),onClick:function(){return n("filter",{mode:e.id})}},e.id)}))})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.AtmosMixer=void 0;var o=n(0),r=n(3),a=n(2);t.AtmosMixer=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.on?"power-off":"times",content:i.on?"On":"Off",selected:i.on,onClick:function(){return n("power")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Output Pressure",children:[(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.set_pressure),unit:"kPa",width:"75px",minValue:0,maxValue:4500,step:10,onChange:function(e,t){return n("pressure",{pressure:t})}}),(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"plus",content:"Max",disabled:i.set_pressure===i.max_pressure,onClick:function(){return n("pressure",{pressure:"max"})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Node 1",children:(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:i.node1_concentration,unit:"%",width:"60px",minValue:0,maxValue:100,stepPixelSize:2,onDrag:function(e,t){return n("node1",{concentration:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Node 2",children:(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:i.node2_concentration,unit:"%",width:"60px",minValue:0,maxValue:100,stepPixelSize:2,onDrag:function(e,t){return n("node2",{concentration:t})}})})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.AtmosPump=void 0;var o=n(0),r=n(3),a=n(2);t.AtmosPump=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.on?"power-off":"times",content:i.on?"On":"Off",selected:i.on,onClick:function(){return n("power")}})}),i.max_rate?(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Transfer Rate",children:[(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.rate),width:"63px",unit:"L/s",minValue:0,maxValue:200,onChange:function(e,t){return n("rate",{rate:t})}}),(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"plus",content:"Max",disabled:i.rate===i.max_rate,onClick:function(){return n("rate",{rate:"max"})}})]}):(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Output Pressure",children:[(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.pressure),unit:"kPa",width:"75px",minValue:0,maxValue:4500,step:10,onChange:function(e,t){return n("pressure",{pressure:t})}}),(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"plus",content:"Max",disabled:i.pressure===i.max_pressure,onClick:function(){return n("pressure",{pressure:"max"})}})]})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.BankMachine=void 0;var o=n(0),r=n(3),a=n(2);t.BankMachine=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.current_balance,l=i.siphoning,u=i.station_name;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:u+" Vault",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current Balance",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:l?"times":"sync",content:l?"Stop Siphoning":"Siphon Credits",selected:l,onClick:function(){return n(l?"halt":"siphon")}}),children:c+" cr"})})}),(0,o.createComponentVNode)(2,a.NoticeBox,{textAlign:"center",children:"Authorized personnel only"})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.BluespaceArtillery=void 0;var o=n(0),r=n(3),a=n(2);t.BluespaceArtillery=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.notice,l=i.connected,u=i.unlocked,d=i.target;return(0,o.createFragment)([!!c&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:c}),l?(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Target",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"crosshairs",disabled:!u,onClick:function(){return n("recalibrate")}}),children:(0,o.createComponentVNode)(2,a.Box,{color:d?"average":"bad",fontSize:"25px",children:d||"No Target Set"})}),(0,o.createComponentVNode)(2,a.Section,{children:u?(0,o.createComponentVNode)(2,a.Box,{style:{margin:"auto"},children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:"FIRE",color:"bad",disabled:!d,fontSize:"30px",textAlign:"center",lineHeight:"46px",onClick:function(){return n("fire")}})}):(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{color:"bad",fontSize:"18px",children:"Bluespace artillery is currently locked."}),(0,o.createComponentVNode)(2,a.Box,{mt:1,children:"Awaiting authorization via keycard reader from at minimum two station heads."})],4)})],4):(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Maintenance",children:(0,o.createComponentVNode)(2,a.Button,{icon:"wrench",content:"Complete Deployment",onClick:function(){return n("build")}})})})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.Bepis=void 0;var o=n(0),r=(n(23),n(16)),a=n(2);t.Bepis=function(e){var t=e.state,n=t.config,i=t.data,c=n.ref,l=i.amount;return(0,o.createComponentVNode)(2,a.Section,{title:"Business Exploration Protocol Incubation Sink",children:[(0,o.createComponentVNode)(2,a.Section,{title:"Information",backgroundColor:"#450F44",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"power-off",content:i.manual_power?"Off":"On",selected:!i.manual_power,onClick:function(){return(0,r.act)(c,"toggle_power")}}),children:"All you need to know about the B.E.P.I.S. and you! The B.E.P.I.S. performs hundreds of tests a second using electrical and financial resources to invent new products, or discover new technologies otherwise overlooked for being too risky or too niche to produce!"}),(0,o.createComponentVNode)(2,a.Section,{title:"Payer's Account",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"redo-alt",content:"Reset Account",onClick:function(){return(0,r.act)(c,"account_reset")}}),children:["Console is currently being operated by ",i.account_owner?i.account_owner:"no one","."]}),(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{size:1.5,children:[(0,o.createComponentVNode)(2,a.Section,{title:"Stored Data and Statistics",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Deposited Credits",children:i.stored_cash}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Investment Variability",children:[i.accuracy_percentage,"%"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Innovation Bonus",children:i.positive_cash_offset}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Risk Offset",color:"bad",children:i.negative_cash_offset}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Deposit Amount",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:l,unit:"Credits",minValue:100,maxValue:3e4,step:100,stepPixelSize:2,onChange:function(e,t){return(0,r.act)(c,"amount",{amount:t})}})})]})}),(0,o.createComponentVNode)(2,a.Box,{children:[(0,o.createComponentVNode)(2,a.Button,{icon:"donate",content:"Deposit Credits",disabled:1===i.manual_power||1===i.silicon_check,onClick:function(){return(0,r.act)(c,"deposit_cash")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Withdraw Credits",disabled:1===i.manual_power,onClick:function(){return(0,r.act)(c,"withdraw_cash")}})]})]}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Market Data and Analysis",children:[(0,o.createComponentVNode)(2,a.Box,{children:["Average technology cost: ",i.mean_value]}),(0,o.createComponentVNode)(2,a.Box,{children:["Current chance of Success: Est. ",i.success_estimate,"%"]}),i.error_name&&(0,o.createComponentVNode)(2,a.Box,{color:"bad",children:"Previous Failure Reason: Deposited cash value too low. Please insert more money for future success."}),(0,o.createComponentVNode)(2,a.Box,{m:1}),(0,o.createComponentVNode)(2,a.Button,{icon:"microscope",disabled:1===i.manual_power,onClick:function(){return(0,r.act)(c,"begin_experiment")},content:"Begin Testing"})]})})]})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.BorgPanel=void 0;var o=n(0),r=n(3),a=n(2);t.BorgPanel=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.borg||{},l=i.cell||{},u=l.charge/l.maxcharge,d=i.channels||[],s=i.modules||[],p=i.upgrades||[],m=i.ais||[],f=i.laws||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:c.name,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"pencil-alt",content:"Rename",onClick:function(){return n("rename")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Status",children:[(0,o.createComponentVNode)(2,a.Button,{icon:c.emagged?"check-square-o":"square-o",content:"Emagged",selected:c.emagged,onClick:function(){return n("toggle_emagged")}}),(0,o.createComponentVNode)(2,a.Button,{icon:c.lockdown?"check-square-o":"square-o",content:"Locked Down",selected:c.lockdown,onClick:function(){return n("toggle_lockdown")}}),(0,o.createComponentVNode)(2,a.Button,{icon:c.scrambledcodes?"check-square-o":"square-o",content:"Scrambled Codes",selected:c.scrambledcodes,onClick:function(){return n("toggle_scrambledcodes")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Charge",children:[l.missing?(0,o.createVNode)(1,"span","color-bad","No cell installed",16):(0,o.createComponentVNode)(2,a.ProgressBar,{value:u,content:l.charge+" / "+l.maxcharge}),(0,o.createVNode)(1,"br"),(0,o.createComponentVNode)(2,a.Button,{icon:"pencil-alt",content:"Set",onClick:function(){return n("set_charge")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Change",onClick:function(){return n("change_cell")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"trash",content:"Remove",color:"bad",onClick:function(){return n("remove_cell")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Radio Channels",children:d.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{icon:e.installed?"check-square-o":"square-o",content:e.name,selected:e.installed,onClick:function(){return n("toggle_radio",{channel:e.name})}},e.name)}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Module",children:s.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{icon:c.active_module===e.type?"check-square-o":"square-o",content:e.name,selected:c.active_module===e.type,onClick:function(){return n("setmodule",{module:e.type})}},e.type)}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Upgrades",children:p.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{icon:e.installed?"check-square-o":"square-o",content:e.name,selected:e.installed,onClick:function(){return n("toggle_upgrade",{upgrade:e.type})}},e.type)}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Master AI",children:m.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{icon:e.connected?"check-square-o":"square-o",content:e.name,selected:e.connected,onClick:function(){return n("slavetoai",{slavetoai:e.ref})}},e.ref)}))})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Laws",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:c.lawupdate?"check-square-o":"square-o",content:"Lawsync",selected:c.lawupdate,onClick:function(){return n("toggle_lawupdate")}}),children:f.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{children:e},e)}))})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.BrigTimer=void 0;var o=n(0),r=n(3),a=n(2);t.BrigTimer=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{title:"Cell Timer",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"clock-o",content:i.timing?"Stop":"Start",selected:i.timing,onClick:function(){return n(i.timing?"stop":"start")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"lightbulb-o",content:i.flash_charging?"Recharging":"Flash",disabled:i.flash_charging,onClick:function(){return n("flash")}})],4),children:[(0,o.createComponentVNode)(2,a.Button,{icon:"fast-backward",onClick:function(){return n("time",{adjust:-600})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"backward",onClick:function(){return n("time",{adjust:-100})}})," ",String(i.minutes).padStart(2,"0"),":",String(i.seconds).padStart(2,"0")," ",(0,o.createComponentVNode)(2,a.Button,{icon:"forward",onClick:function(){return n("time",{adjust:100})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"fast-forward",onClick:function(){return n("time",{adjust:600})}}),(0,o.createVNode)(1,"br"),(0,o.createComponentVNode)(2,a.Button,{icon:"hourglass-start",content:"Short",onClick:function(){return n("preset",{preset:"short"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"hourglass-start",content:"Medium",onClick:function(){return n("preset",{preset:"medium"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"hourglass-start",content:"Long",onClick:function(){return n("preset",{preset:"long"})}})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.Canvas=void 0;var o=n(0),r=n(3),a=n(2);n(11);var i=function(e){var t,n;function r(t){var n;return(n=e.call(this,t)||this).canvasRef=(0,o.createRef)(),n.onCVClick=t.onCanvasClick,n}n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var a=r.prototype;return a.componentDidMount=function(){this.drawCanvas(this.props)},a.componentDidUpdate=function(){this.drawCanvas(this.props)},a.drawCanvas=function(e){var t=this.canvasRef.current.getContext("2d"),n=e.value,o=n.length;if(o){var r=n[0].length,a=Math.round(this.canvasRef.current.width/o),i=Math.round(this.canvasRef.current.height/r);t.save(),t.scale(a,i);for(var c=0;c=0||(r[n]=e[n]);return r}(t,["res","value","px_per_unit"]),c=n.length*a,l=0!==c?n[0].length*a:0;return(0,o.normalizeProps)((0,o.createVNode)(1,"canvas",null,"Canvas failed to render.",16,Object.assign({width:c||300,height:l||300},i,{onClick:function(t){return e.clickwrapper(t)}}),null,this.canvasRef))},r}(o.Component);t.Canvas=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data;return(0,o.createComponentVNode)(2,a.Box,{textAlign:"center",children:[(0,o.createComponentVNode)(2,i,{value:c.grid,onCanvasClick:function(e,t){return n("paint",{x:e,y:t})}}),(0,o.createComponentVNode)(2,a.Box,{children:[!c.finalized&&(0,o.createComponentVNode)(2,a.Button.Confirm,{onClick:function(){return n("finalize")},content:"Finalize"}),c.name]})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.Canister=void 0;var o=n(0),r=n(3),a=n(2);t.Canister=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.NoticeBox,{children:["The regulator ",i.hasHoldingTank?"is":"is not"," connected to a tank."]}),(0,o.createComponentVNode)(2,a.Section,{title:"Canister",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"pencil-alt",content:"Relabel",onClick:function(){return n("relabel")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure",children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:i.tankPressure})," kPa"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Port",color:i.portConnected?"good":"average",content:i.portConnected?"Connected":"Not Connected"}),!!i.isPrototype&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Access",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.restricted?"lock":"unlock",color:"caution",content:i.restricted?"Restricted to Engineering":"Public",onClick:function(){return n("restricted")}})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Valve",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Release Pressure",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.releasePressure/(i.maxReleasePressure-i.minReleasePressure),children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:i.releasePressure})," kPa"]})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure Regulator",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"undo",disabled:i.releasePressure===i.defaultReleasePressure,content:"Reset",onClick:function(){return n("pressure",{pressure:"reset"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"minus",disabled:i.releasePressure<=i.minReleasePressure,content:"Min",onClick:function(){return n("pressure",{pressure:"min"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"pencil-alt",content:"Set",onClick:function(){return n("pressure",{pressure:"input"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",disabled:i.releasePressure>=i.maxReleasePressure,content:"Max",onClick:function(){return n("pressure",{pressure:"max"})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Valve",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.valveOpen?"unlock":"lock",color:i.valveOpen?i.hasHoldingTank?"caution":"danger":null,content:i.valveOpen?"Open":"Closed",onClick:function(){return n("valve")}})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Holding Tank",buttons:!!i.hasHoldingTank&&(0,o.createComponentVNode)(2,a.Button,{icon:"eject",color:i.valveOpen&&"danger",content:"Eject",onClick:function(){return n("eject")}}),children:[!!i.hasHoldingTank&&(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Label",children:i.holdingTank.name}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure",children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:i.holdingTank.tankPressure})," kPa"]})]}),!i.hasHoldingTank&&(0,o.createComponentVNode)(2,a.Box,{color:"average",children:"No Holding Tank"})]})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.CargoExpress=t.Cargo=void 0;var o=n(0),r=n(24),a=n(16),i=n(2),c=n(69);t.Cargo=function(e){var t=e.state,n=t.config,r=t.data,c=n.ref,s=r.supplies||{},p=r.requests||[],m=r.cart||[],f=m.reduce((function(e,t){return e+t.cost}),0),h=!r.requestonly&&(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Box,{inline:!0,mx:1,children:[0===m.length&&"Cart is empty",1===m.length&&"1 item",m.length>=2&&m.length+" items"," ",f>0&&"("+f+" cr)"]}),(0,o.createComponentVNode)(2,i.Button,{icon:"times",color:"transparent",content:"Clear",onClick:function(){return(0,a.act)(c,"clear")}})],4);return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{title:"Cargo",buttons:(0,o.createComponentVNode)(2,i.Box,{inline:!0,bold:!0,children:[(0,o.createComponentVNode)(2,i.AnimatedNumber,{value:Math.round(r.points)})," credits"]}),children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Shuttle",children:r.docked&&!r.requestonly&&(0,o.createComponentVNode)(2,i.Button,{content:r.location,onClick:function(){return(0,a.act)(c,"send")}})||r.location}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"CentCom Message",children:r.message}),r.loan&&!r.requestonly?(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Loan",children:r.loan_dispatched?(0,o.createComponentVNode)(2,i.Box,{color:"bad",children:"Loaned to Centcom"}):(0,o.createComponentVNode)(2,i.Button,{content:"Loan Shuttle",disabled:!(r.away&&r.docked),onClick:function(){return(0,a.act)(c,"loan")}})}):""]})}),(0,o.createComponentVNode)(2,i.Tabs,{mt:2,children:[(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Catalog",icon:"list",lineHeight:"23px",children:function(){return(0,o.createComponentVNode)(2,i.Section,{title:"Catalog",buttons:(0,o.createFragment)([h,(0,o.createComponentVNode)(2,i.Button,{ml:1,icon:r.self_paid?"check-square-o":"square-o",content:"Buy Privately",selected:r.self_paid,onClick:function(){return(0,a.act)(c,"toggleprivate")}})],0),children:(0,o.createComponentVNode)(2,l,{state:t,supplies:s})})}},"catalog"),(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Requests ("+p.length+")",icon:"envelope",highlight:p.length>0,lineHeight:"23px",children:function(){return(0,o.createComponentVNode)(2,i.Section,{title:"Active Requests",buttons:!r.requestonly&&(0,o.createComponentVNode)(2,i.Button,{icon:"times",content:"Clear",color:"transparent",onClick:function(){return(0,a.act)(c,"denyall")}}),children:(0,o.createComponentVNode)(2,u,{state:t,requests:p})})}},"requests"),!r.requestonly&&(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Checkout ("+m.length+")",icon:"shopping-cart",highlight:m.length>0,lineHeight:"23px",children:function(){return(0,o.createComponentVNode)(2,i.Section,{title:"Current Cart",buttons:h,children:(0,o.createComponentVNode)(2,d,{state:t,cart:m})})}},"cart")]})],4)};var l=function(e){var t=e.state,n=e.supplies,c=t.config,l=t.data,u=c.ref,d=function(e){var t=n[e].packs;return(0,o.createVNode)(1,"table","LabeledList",t.map((function(e){return(0,o.createVNode)(1,"tr","LabeledList__row candystripe",[(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__label",[e.name,(0,o.createTextVNode)(":")],0),(0,o.createVNode)(1,"td","LabeledList__cell",!!e.access&&(0,o.createFragment)([(0,o.createTextVNode)("Restrictions Apply")],4),0),(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__buttons",(0,o.createComponentVNode)(2,i.Button,{fluid:!0,disabled:l.self_paid&&!e.can_private_buy&&!l.emagged,content:(l.self_paid?Math.round(1.1*e.cost):e.cost)+" credits",tooltip:e.desc,tooltipPosition:"left",onClick:function(){return(0,a.act)(u,"add",{id:e.id})}}),2)],4,null,e.name)})),0)};return(0,o.createComponentVNode)(2,i.Tabs,{vertical:!0,children:(0,r.map)((function(e){var t=e.name;return(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:t,children:d},t)}))(n)})},u=function(e){var t=e.state,n=e.requests,r=t.config,c=t.data,l=r.ref;return 0===n.length?(0,o.createComponentVNode)(2,i.Box,{color:"good",children:"No Requests"}):(0,o.createVNode)(1,"table","LabeledList",n.map((function(e){return(0,o.createFragment)([(0,o.createVNode)(1,"tr","LabeledList__row candystripe",[(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__label",[(0,o.createTextVNode)("#"),e.id,(0,o.createTextVNode)(":")],0),(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__content",e.object,0),(0,o.createVNode)(1,"td","LabeledList__cell",[(0,o.createTextVNode)("By "),(0,o.createVNode)(1,"b",null,e.orderer,0)],4),(0,o.createVNode)(1,"td","LabeledList__cell",(0,o.createVNode)(1,"i",null,e.reason,0),2),(0,o.createVNode)(1,"td","LabeledList__cell LabeledList__buttons",[e.cost,(0,o.createTextVNode)(" credits"),(0,o.createTextVNode)(" "),!c.requestonly&&(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Button,{icon:"check",color:"good",onClick:function(){return(0,a.act)(l,"approve",{id:e.id})}}),(0,o.createComponentVNode)(2,i.Button,{icon:"times",color:"bad",onClick:function(){return(0,a.act)(l,"deny",{id:e.id})}})],4)],0)],4)],4,e.id)})),0)},d=function(e){var t=e.state,n=e.cart,r=t.config,c=t.data,l=r.ref;return(0,o.createFragment)([0===n.length&&"Nothing in cart",n.length>0&&(0,o.createComponentVNode)(2,i.LabeledList,{children:n.map((function(e){return(0,o.createComponentVNode)(2,i.LabeledList.Item,{className:"candystripe",label:"#"+e.id,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Box,{inline:!0,mx:2,children:[!!e.paid&&(0,o.createVNode)(1,"b",null,"[Paid Privately]",16)," ",e.cost," credits"]}),(0,o.createComponentVNode)(2,i.Button,{icon:"minus",onClick:function(){return(0,a.act)(l,"remove",{id:e.id})}})],4),children:e.object},e.id)}))}),n.length>0&&!c.requestonly&&(0,o.createComponentVNode)(2,i.Box,{mt:2,children:1===c.away&&1===c.docked&&(0,o.createComponentVNode)(2,i.Button,{color:"green",style:{"line-height":"28px",padding:"0 12px"},content:"Confirm the order",onClick:function(){return(0,a.act)(l,"send")}})||(0,o.createComponentVNode)(2,i.Box,{opacity:.5,children:["Shuttle in ",c.location,"."]})})],0)};t.CargoExpress=function(e){var t=e.state,n=t.config,r=t.data,u=n.ref,d=r.supplies||{};return(0,o.createFragment)([(0,o.createComponentVNode)(2,c.InterfaceLockNoticeBox,{siliconUser:r.siliconUser,locked:r.locked,onLockStatusChange:function(){return(0,a.act)(u,"lock")},accessText:"a QM-level ID card"}),!r.locked&&(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{title:"Cargo Express",buttons:(0,o.createComponentVNode)(2,i.Box,{inline:!0,bold:!0,children:[(0,o.createComponentVNode)(2,i.AnimatedNumber,{value:Math.round(r.points)})," credits"]}),children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Landing Location",children:[(0,o.createComponentVNode)(2,i.Button,{content:"Cargo Bay",selected:!r.usingBeacon,onClick:function(){return(0,a.act)(u,"LZCargo")}}),(0,o.createComponentVNode)(2,i.Button,{selected:r.usingBeacon,disabled:!r.hasBeacon,onClick:function(){return(0,a.act)(u,"LZBeacon")},children:[r.beaconzone," (",r.beaconName,")"]}),(0,o.createComponentVNode)(2,i.Button,{content:r.printMsg,disabled:!r.canBuyBeacon,onClick:function(){return(0,a.act)(u,"printBeacon")}})]}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Notice",children:r.message})]})}),(0,o.createComponentVNode)(2,l,{state:t,supplies:d})],4)],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.CellularEmporium=void 0;var o=n(0),r=n(3),a=n(2);t.CellularEmporium=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.abilities;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Genetic Points",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"undo",content:"Readapt",disabled:!i.can_readapt,onClick:function(){return n("readapt")}}),children:i.genetic_points_remaining})})}),(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:c.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{className:"candystripe",label:e.name,buttons:(0,o.createFragment)([e.dna_cost," ",(0,o.createComponentVNode)(2,a.Button,{content:e.owned?"Evolved":"Evolve",selected:e.owned,onClick:function(){return n("evolve",{name:e.name})}})],0),children:[e.desc,(0,o.createComponentVNode)(2,a.Box,{color:"good",children:e.helptext})]},e.name)}))})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.CentcomPodLauncher=void 0;var o=n(0),r=(n(23),n(3)),a=n(2);t.CentcomPodLauncher=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.NoticeBox,{children:"To use this, simply spawn the atoms you want in one of the five Centcom Supplypod Bays. Items in the bay will then be launched inside your supplypod, one turf-full at a time! You can optionally use the following buttons to configure how the supplypod acts."}),(0,o.createComponentVNode)(2,a.Section,{title:"Centcom Pod Customization (To be used against Helen Weinstein)",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Supply Bay",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Bay #1",selected:1===i.bayNumber,onClick:function(){return n("bay1")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Bay #2",selected:2===i.bayNumber,onClick:function(){return n("bay2")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Bay #3",selected:3===i.bayNumber,onClick:function(){return n("bay3")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Bay #4",selected:4===i.bayNumber,onClick:function(){return n("bay4")}}),(0,o.createComponentVNode)(2,a.Button,{content:"ERT Bay",selected:5===i.bayNumber,tooltip:"This bay is located on the western edge of CentCom. Its the\nglass room directly west of where ERT spawn, and south of the\nCentCom ferry. Useful for launching ERT/Deathsquads/etc. onto\nthe station via drop pods.",onClick:function(){return n("bay5")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Teleport to",children:[(0,o.createComponentVNode)(2,a.Button,{content:i.bay,onClick:function(){return n("teleportCentcom")}}),(0,o.createComponentVNode)(2,a.Button,{content:i.oldArea?i.oldArea:"Where you were",disabled:!i.oldArea,onClick:function(){return n("teleportBack")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Clone Mode",children:(0,o.createComponentVNode)(2,a.Button,{content:"Launch Clones",selected:i.launchClone,tooltip:"Choosing this will create a duplicate of the item to be\nlaunched in Centcom, allowing you to send one type of item\nmultiple times. Either way, the atoms are forceMoved into\nthe supplypod after it lands (but before it opens).",onClick:function(){return n("launchClone")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Launch style",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Ordered",selected:1===i.launchChoice,tooltip:'Instead of launching everything in the bay at once, this\nwill "scan" things (one turf-full at a time) in order, left\nto right and top to bottom. undoing will reset the "scanner"\nto the top-leftmost position.',onClick:function(){return n("launchOrdered")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Random",selected:2===i.launchChoice,tooltip:"Instead of launching everything in the bay at once, this\nwill launch one random turf of items at a time.",onClick:function(){return n("launchRandom")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Explosion",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Custom Size",selected:1===i.explosionChoice,tooltip:"This will cause an explosion of whatever size you like\n(including flame range) to occur as soon as the supplypod\nlands. Dont worry, supply-pods are explosion-proof!",onClick:function(){return n("explosionCustom")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Adminbus",selected:2===i.explosionChoice,tooltip:"This will cause a maxcap explosion (dependent on server\nconfig) to occur as soon as the supplypod lands. Dont worry,\nsupply-pods are explosion-proof!",onClick:function(){return n("explosionBus")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Damage",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Custom Damage",selected:1===i.damageChoice,tooltip:"Anyone caught under the pod when it lands will be dealt\nthis amount of brute damage. Sucks to be them!",onClick:function(){return n("damageCustom")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Gib",selected:2===i.damageChoice,tooltip:"This will attempt to gib any mob caught under the pod when\nit lands, as well as dealing a nice 5000 brute damage. Ya\nknow, just to be sure!",onClick:function(){return n("damageGib")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Effects",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Stun",selected:i.effectStun,tooltip:"Anyone who is on the turf when the supplypod is launched\nwill be stunned until the supplypod lands. They cant get\naway that easy!",onClick:function(){return n("effectStun")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Delimb",selected:i.effectLimb,tooltip:"This will cause anyone caught under the pod to lose a limb,\nexcluding their head.",onClick:function(){return n("effectLimb")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Yeet Organs",selected:i.effectOrgans,tooltip:"This will cause anyone caught under the pod to lose all\ntheir limbs and organs in a spectacular fashion.",onClick:function(){return n("effectOrgans")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Movement",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Bluespace",selected:i.effectBluespace,tooltip:"Gives the supplypod an advanced Bluespace Recyling Device.\nAfter opening, the supplypod will be warped directly to the\nsurface of a nearby NT-designated trash planet (/r/ss13).",onClick:function(){return n("effectBluespace")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Stealth",selected:i.effectStealth,tooltip:'This hides the red target icon from appearing when you\nlaunch the supplypod. Combos well with the "Invisible"\nstyle. Sneak attack, go!',onClick:function(){return n("effectStealth")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Quiet",selected:i.effectQuiet,tooltip:"This will keep the supplypod from making any sounds, except\nfor those specifically set by admins in the Sound section.",onClick:function(){return n("effectQuiet")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Reverse Mode",selected:i.effectReverse,tooltip:"This pod will not send any items. Instead, after landing,\nthe supplypod will close (similar to a normal closet closing),\nand then launch back to the right centcom bay to drop off any\nnew contents.",onClick:function(){return n("effectReverse")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Missile Mode",selected:i.effectMissile,tooltip:"This pod will not send any items. Instead, it will immediately\ndelete after landing (Similar visually to setting openDelay\n& departDelay to 0, but this looks nicer). Useful if you just\nwanna fuck some shit up. Combos well with the Missile style.",onClick:function(){return n("effectMissile")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Any Descent Angle",selected:i.effectCircle,tooltip:"This will make the supplypod come in from any angle. Im not\nsure why this feature exists, but here it is.",onClick:function(){return n("effectCircle")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Machine Gun Mode",selected:i.effectBurst,tooltip:"This will make each click launch 5 supplypods inaccuratly\naround the target turf (a 3x3 area). Combos well with the\nMissile Mode if you dont want shit lying everywhere after.",onClick:function(){return n("effectBurst")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Specific Target",selected:i.effectTarget,tooltip:"This will make the supplypod target a specific atom, instead\nof the mouses position. Smiting does this automatically!",onClick:function(){return n("effectTarget")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Name/Desc",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Custom Name/Desc",selected:i.effectName,tooltip:"Allows you to add a custom name and description.",onClick:function(){return n("effectName")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Alert Ghosts",selected:i.effectAnnounce,tooltip:"Alerts ghosts when a pod is launched. Useful if some dumb\nshit is aboutta come outta the pod.",onClick:function(){return n("effectAnnounce")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Sound",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Custom Falling Sound",selected:i.fallingSound,tooltip:"Choose a sound to play as the pod falls. Note that for this\nto work right you should know the exact length of the sound,\nin seconds.",onClick:function(){return n("fallSound")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Custom Landing Sound",selected:i.landingSound,tooltip:"Choose a sound to play when the pod lands.",onClick:function(){return n("landingSound")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Custom Opening Sound",selected:i.openingSound,tooltip:"Choose a sound to play when the pod opens.",onClick:function(){return n("openingSound")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Custom Leaving Sound",selected:i.leavingSound,tooltip:"Choose a sound to play when the pod departs (whether that be\ndelection in the case of a bluespace pod, or leaving for\ncentcom for a reversing pod).",onClick:function(){return n("leavingSound")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Admin Sound Volume",selected:i.soundVolume,tooltip:"Choose the volume for the sound to play at. Default values\nare between 1 and 100, but hey, do whatever. Im a tooltip,\nnot a cop.",onClick:function(){return n("soundVolume")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Timers",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Custom Falling Duration",selected:4!==i.fallDuration,tooltip:"Set how long the animation for the pod falling lasts. Create\ndramatic, slow falling pods!",onClick:function(){return n("fallDuration")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Custom Landing Time",selected:20!==i.landingDelay,tooltip:"Choose the amount of time it takes for the supplypod to hit\nthe station. By default this value is 0.5 seconds.",onClick:function(){return n("landingDelay")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Custom Opening Time",selected:30!==i.openingDelay,tooltip:"Choose the amount of time it takes for the supplypod to open\nafter landing. Useful for giving whatevers inside the pod a\nnice dramatic entrance! By default this value is 3 seconds.",onClick:function(){return n("openingDelay")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Custom Leaving Time",selected:30!==i.departureDelay,tooltip:"Choose the amount of time it takes for the supplypod to leave\nafter landing. By default this value is 3 seconds.",onClick:function(){return n("departureDelay")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Style",children:[(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.styleChoice,tooltip:"Same color scheme as the normal station-used supplypods",onClick:function(){return n("styleStandard")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Advanced",selected:2===i.styleChoice,tooltip:"The same as the stations upgraded blue-and-white\nBluespace Supplypods",onClick:function(){return n("styleBluespace")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Syndicate",selected:4===i.styleChoice,tooltip:"A menacing black and blood-red. Great for sending meme-ops\nin style!",onClick:function(){return n("styleSyndie")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Deathsquad",selected:5===i.styleChoice,tooltip:"A menacing black and dark blue. Great for sending deathsquads\nin style!",onClick:function(){return n("styleBlue")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Cult Pod",selected:6===i.styleChoice,tooltip:"A blood and rune covered cult pod!",onClick:function(){return n("styleCult")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Missile",selected:7===i.styleChoice,tooltip:"A large missile. Combos well with a missile mode, so the\nmissile doesnt stick around after landing.",onClick:function(){return n("styleMissile")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Syndicate Missile",selected:8===i.styleChoice,tooltip:"A large blood-red missile. Combos well with missile mode,\nso the missile doesnt stick around after landing.",onClick:function(){return n("styleSMissile")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Supply Crate",selected:9===i.styleChoice,tooltip:"A large, dark-green military supply crate.",onClick:function(){return n("styleBox")}}),(0,o.createComponentVNode)(2,a.Button,{content:"HONK",selected:10===i.styleChoice,tooltip:"A colorful, clown inspired look.",onClick:function(){return n("styleHONK")}}),(0,o.createComponentVNode)(2,a.Button,{content:"~Fruit",selected:11===i.styleChoice,tooltip:"For when an orange is angry",onClick:function(){return n("styleFruit")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Invisible",selected:12===i.styleChoice,tooltip:'Makes the supplypod invisible! Useful for when you want to\nuse this feature with a gateway or something. Combos well\nwith the "Stealth" and "Quiet Landing" effects.',onClick:function(){return n("styleInvisible")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Gondola",selected:13===i.styleChoice,tooltip:"This gondola can control when he wants to deliver his supplies\nif he has a smart enough mind, so offer up his body to ghosts\nfor maximum enjoyment. (Make sure to turn off bluespace and\nset a arbitrarily high open-time if you do!",onClick:function(){return n("styleGondola")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Show Contents (See Through Pod)",selected:14===i.styleChoice,tooltip:"By selecting this, the pod will instead look like whatevers\ninside it (as if it were the contents falling by themselves,\nwithout a pod). Useful for launching mechs at the station\nand standing tall as they soar in from the heavens.",onClick:function(){return n("styleSeeThrough")}})]})]})}),(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:i.numObjects+" turfs in "+i.bay,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{content:"undo Pody Bay",tooltip:"Manually undoes the possible things to launch in the\npod bay.",onClick:function(){return n("undo")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Enter Launch Mode",selected:i.giveLauncher,tooltip:"THE CODEX ASTARTES CALLS THIS MANEUVER: STEEL RAIN",onClick:function(){return n("giveLauncher")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Clear Selected Bay",color:"bad",tooltip:"This will delete all objs and mobs from the selected bay.",tooltipPosition:"left",onClick:function(){return n("clearBay")}})],4)})})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemAcclimator=void 0;var o=n(0),r=n(3),a=n(2);t.ChemAcclimator=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Acclimator",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current Temperature",children:[i.chem_temp," K"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Target Temperature",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.target_temperature,unit:"K",width:"59px",minValue:0,maxValue:1e3,step:5,stepPixelSize:2,onChange:function(e,t){return n("set_target_temperature",{temperature:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Acceptable Temp. Difference",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.allowed_temperature_difference,unit:"K",width:"59px",minValue:1,maxValue:i.target_temperature,stepPixelSize:2,onChange:function(e,t){n("set_allowed_temperature_difference",{temperature:t})}})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Status",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"power-off",content:i.enabled?"On":"Off",selected:i.enabled,onClick:function(){return n("toggle_power")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Volume",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.max_volume,unit:"u",width:"50px",minValue:i.reagent_volume,maxValue:200,step:2,stepPixelSize:2,onChange:function(e,t){return n("change_volume",{volume:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current Operation",children:i.acclimate_state}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current State",children:i.emptying?"Emptying":"Filling"})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemDebugSynthesizer=void 0;var o=n(0),r=n(3),a=n(2);t.ChemDebugSynthesizer=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.amount,l=i.beakerCurrentVolume,u=i.beakerMaxVolume,d=i.isBeakerLoaded,s=i.beakerContents,p=void 0===s?[]:s;return(0,o.createComponentVNode)(2,a.Section,{title:"Recipient",buttons:d?(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",onClick:function(){return n("ejectBeaker")}}),(0,o.createComponentVNode)(2,a.NumberInput,{value:c,unit:"u",minValue:1,maxValue:u,step:1,stepPixelSize:2,onChange:function(e,t){return n("amount",{amount:t})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",content:"Input",onClick:function(){return n("input")}})],4):(0,o.createComponentVNode)(2,a.Button,{icon:"plus",content:"Create Beaker",onClick:function(){return n("makecup")}}),children:d?(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:l})," / "+u+" u"]}),p.length>0?(0,o.createComponentVNode)(2,a.LabeledList,{children:p.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.name,children:[e.volume," u"]},e.name)}))}):(0,o.createComponentVNode)(2,a.Box,{color:"bad",children:"Recipient Empty"})],0):(0,o.createComponentVNode)(2,a.Box,{color:"average",children:"No Recipient"})})}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemDispenser=void 0;var o=n(0),r=n(17),a=n(23),i=n(3),c=n(2);t.ChemDispenser=function(e){var t=(0,i.useBackend)(e),n=t.act,l=t.data,u=!!l.recordingRecipe,d=Object.keys(l.recipes).map((function(e){return{name:e,contents:l.recipes[e]}})),s=l.beakerTransferAmounts||[],p=u&&Object.keys(l.recordingRecipe).map((function(e){return{id:e,name:(0,a.toTitleCase)(e.replace(/_/," ")),volume:l.recordingRecipe[e]}}))||l.beakerContents||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,c.Section,{title:"Status",buttons:u&&(0,o.createComponentVNode)(2,c.Box,{inline:!0,mx:1,color:"red",children:[(0,o.createComponentVNode)(2,c.Icon,{name:"circle",mr:1}),"Recording"]}),children:(0,o.createComponentVNode)(2,c.LabeledList,{children:(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Energy",children:(0,o.createComponentVNode)(2,c.ProgressBar,{value:l.energy/l.maxEnergy,content:(0,r.toFixed)(l.energy)+" units"})})})}),(0,o.createComponentVNode)(2,c.Section,{title:"Recipes",buttons:(0,o.createFragment)([!u&&(0,o.createComponentVNode)(2,c.Box,{inline:!0,mx:1,children:(0,o.createComponentVNode)(2,c.Button,{color:"transparent",content:"Clear recipes",onClick:function(){return n("clear_recipes")}})}),!u&&(0,o.createComponentVNode)(2,c.Button,{icon:"circle",disabled:!l.isBeakerLoaded,content:"Record",onClick:function(){return n("record_recipe")}}),u&&(0,o.createComponentVNode)(2,c.Button,{icon:"ban",color:"transparent",content:"Discard",onClick:function(){return n("cancel_recording")}}),u&&(0,o.createComponentVNode)(2,c.Button,{icon:"save",color:"green",content:"Save",onClick:function(){return n("save_recording")}})],0),children:(0,o.createComponentVNode)(2,c.Box,{mr:-1,children:[d.map((function(e){return(0,o.createComponentVNode)(2,c.Button,{icon:"tint",width:"129.5px",lineHeight:"21px",content:e.name,onClick:function(){return n("dispense_recipe",{recipe:e.name})}},e.name)})),0===d.length&&(0,o.createComponentVNode)(2,c.Box,{color:"light-gray",children:"No recipes."})]})}),(0,o.createComponentVNode)(2,c.Section,{title:"Dispense",buttons:s.map((function(e){return(0,o.createComponentVNode)(2,c.Button,{icon:"plus",selected:e===l.amount,content:e,onClick:function(){return n("amount",{target:e})}},e)})),children:(0,o.createComponentVNode)(2,c.Box,{mr:-1,children:l.chemicals.map((function(e){return(0,o.createComponentVNode)(2,c.Button,{icon:"tint",width:"129.5px",lineHeight:"21px",content:e.title,onClick:function(){return n("dispense",{reagent:e.id})}},e.id)}))})}),(0,o.createComponentVNode)(2,c.Section,{title:"Beaker",buttons:s.map((function(e){return(0,o.createComponentVNode)(2,c.Button,{icon:"minus",disabled:u,content:e,onClick:function(){return n("remove",{amount:e})}},e)})),children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Beaker",buttons:!!l.isBeakerLoaded&&(0,o.createComponentVNode)(2,c.Button,{icon:"eject",content:"Eject",disabled:!l.isBeakerLoaded,onClick:function(){return n("eject")}}),children:(u?"Virtual beaker":l.isBeakerLoaded&&(0,o.createFragment)([(0,o.createComponentVNode)(2,c.AnimatedNumber,{initial:0,value:l.beakerCurrentVolume}),(0,o.createTextVNode)("/"),l.beakerMaxVolume,(0,o.createTextVNode)(" units, "),l.beakerCurrentpH,(0,o.createTextVNode)(" pH")],0))||"No beaker"}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Contents",children:[(0,o.createComponentVNode)(2,c.Box,{color:"label",children:l.isBeakerLoaded||u?0===p.length&&"Nothing":"N/A"}),p.map((function(e){return(0,o.createComponentVNode)(2,c.Box,{color:"label",children:[(0,o.createComponentVNode)(2,c.AnimatedNumber,{initial:0,value:e.volume})," ","units of ",e.name]},e.name)}))]})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemFilter=t.ChemFilterPane=void 0;var o=n(0),r=n(3),a=n(2);var i=function(e){var t=(0,r.useBackend)(e).act,n=e.title,i=e.list,c=e.reagentName,l=e.onReagentInput,u=n.toLowerCase();return(0,o.createComponentVNode)(2,a.Section,{title:n,minHeight:40,ml:.5,mr:.5,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Input,{placeholder:"Reagent",width:"140px",onInput:function(e,t){return l(t)}}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",onClick:function(){return t("add",{which:u,name:c})}})],4),children:i.map((function(e){return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"minus",content:e,onClick:function(){return t("remove",{which:u,reagent:e})}})],4,e)}))})};t.ChemFilterPane=i;var c=function(e){var t,n;function r(){var t;return(t=e.call(this)||this).state={leftReagentName:"",rightReagentName:""},t}n=e,(t=r).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var c=r.prototype;return c.setLeftReagentName=function(e){this.setState({leftReagentName:e})},c.setRightReagentName=function(e){this.setState({rightReagentName:e})},c.render=function(){var e=this,t=this.props.state,n=t.data,r=n.left,c=void 0===r?[]:r,l=n.right,u=void 0===l?[]:l;return(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,i,{title:"Left",list:c,reagentName:this.state.leftReagentName,onReagentInput:function(t){return e.setLeftReagentName(t)},state:t})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,i,{title:"Right",list:u,reagentName:this.state.rightReagentName,onReagentInput:function(t){return e.setRightReagentName(t)},state:t})})]})},r}(o.Component);t.ChemFilter=c},function(e,t,n){"use strict";t.__esModule=!0,t.ChemHeater=void 0;var o=n(0),r=n(17),a=n(3),i=n(2),c=n(164);t.ChemHeater=function(e){var t=(0,a.useBackend)(e),n=t.act,l=t.data,u=l.targetTemp,d=l.isActive,s=l.isBeakerLoaded,p=l.currentTemp,m=l.currentpH,f=l.beakerCurrentVolume,h=l.beakerMaxVolume,C=l.beakerContents,g=void 0===C?[]:C;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{title:"Thermostat",buttons:(0,o.createComponentVNode)(2,i.Button,{icon:d?"power-off":"times",selected:d,content:d?"On":"Off",onClick:function(){return n("power")}}),children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Target",children:(0,o.createComponentVNode)(2,i.NumberInput,{width:"65px",unit:"K",step:2,stepPixelSize:1,value:(0,r.round)(u),minValue:0,maxValue:1e3,onDrag:function(e,t){return n("temperature",{target:t})}})}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Temperature",children:(0,o.createComponentVNode)(2,i.Box,{width:"60px",textAlign:"right",children:s&&(0,o.createComponentVNode)(2,i.AnimatedNumber,{value:p,format:function(e){return(0,r.toFixed)(e)+" K"}})||"\u2014"})}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"pH",children:(0,o.createComponentVNode)(2,i.Box,{width:"60px",textAlign:"right",children:s&&(0,o.createComponentVNode)(2,i.AnimatedNumber,{value:m,format:function(e){return(0,r.toFixed)(e)+" pH"}})||"-"})})]})}),(0,o.createComponentVNode)(2,i.Section,{title:"Beaker",buttons:!!s&&(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Box,{inline:!0,color:"label",mr:2,children:[f," / ",h," units"]}),(0,o.createComponentVNode)(2,i.Button,{icon:"eject",content:"Eject",onClick:function(){return n("eject")}})],4),children:(0,o.createComponentVNode)(2,c.BeakerContents,{beakerLoaded:s,beakerContents:g})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemMaster=void 0;var o=n(0),r=n(16),a=n(2);t.ChemMaster=function(e){var t=e.state,n=t.config,l=t.data,d=n.ref,s=(l.screen,l.beakerContents),p=void 0===s?[]:s,m=l.bufferContents,f=void 0===m?[]:m,h=l.beakerCurrentVolume,C=l.beakerMaxVolume,g=l.isBeakerLoaded,b=l.isPillBottleLoaded,N=l.pillBottleCurrentAmount,v=l.pillBottleMaxAmount;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Beaker",buttons:!!l.isBeakerLoaded&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"label",mr:2,children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:h,initial:0})," / "+C+" units"]}),(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",onClick:function(){return(0,r.act)(d,"eject")}})],4),children:[!g&&(0,o.createComponentVNode)(2,a.Box,{color:"label",mt:"3px",mb:"5px",children:"No beaker loaded."}),!!g&&0===p.length&&(0,o.createComponentVNode)(2,a.Box,{color:"label",mt:"3px",mb:"5px",children:"Beaker is empty."}),(0,o.createComponentVNode)(2,i,{children:p.map((function(e){return(0,o.createComponentVNode)(2,c,{state:t,chemical:e,transferTo:"buffer"},e.id)}))})]}),(0,o.createComponentVNode)(2,a.Section,{title:"Buffer",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"label",mr:1,children:"Mode:"}),(0,o.createComponentVNode)(2,a.Button,{color:l.mode?"good":"bad",icon:l.mode?"exchange-alt":"times",content:l.mode?"Transfer":"Destroy",onClick:function(){return(0,r.act)(d,"toggleMode")}})],4),children:[0===f.length&&(0,o.createComponentVNode)(2,a.Box,{color:"label",mt:"3px",mb:"5px",children:"Buffer is empty."}),(0,o.createComponentVNode)(2,i,{children:f.map((function(e){return(0,o.createComponentVNode)(2,c,{state:t,chemical:e,transferTo:"beaker"},e.id)}))})]}),(0,o.createComponentVNode)(2,a.Section,{title:"Packaging",children:(0,o.createComponentVNode)(2,u,{state:t})}),!!b&&(0,o.createComponentVNode)(2,a.Section,{title:"Pill Bottle",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"label",mr:2,children:[N," / ",v," pills"]}),(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",onClick:function(){return(0,r.act)(d,"ejectPillBottle")}})],4)})],0)};var i=a.Table,c=function(e){var t=e.state,n=e.chemical,i=e.transferTo,c=t.config.ref;return(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{color:"label",children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:n.volume,initial:0})," units of "+n.name]}),(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,children:[(0,o.createComponentVNode)(2,a.Button,{content:"1",onClick:function(){return(0,r.act)(c,"transfer",{id:n.id,amount:1,to:i})}}),(0,o.createComponentVNode)(2,a.Button,{content:"5",onClick:function(){return(0,r.act)(c,"transfer",{id:n.id,amount:5,to:i})}}),(0,o.createComponentVNode)(2,a.Button,{content:"10",onClick:function(){return(0,r.act)(c,"transfer",{id:n.id,amount:10,to:i})}}),(0,o.createComponentVNode)(2,a.Button,{content:"All",onClick:function(){return(0,r.act)(c,"transfer",{id:n.id,amount:1e3,to:i})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"ellipsis-h",title:"Custom amount",onClick:function(){return(0,r.act)(c,"transfer",{id:n.id,amount:-1,to:i})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"question",title:"Analyze",onClick:function(){return(0,r.act)(c,"analyze",{id:n.id})}})]})]},n.id)},l=function(e){var t=e.label,n=e.amountUnit,r=e.amount,i=e.onChangeAmount,c=e.onCreate,l=e.sideNote;return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:t,children:[(0,o.createComponentVNode)(2,a.NumberInput,{width:14,unit:n,step:1,stepPixelSize:15,value:r,minValue:1,maxValue:10,onChange:i}),(0,o.createComponentVNode)(2,a.Button,{ml:1,content:"Create",onClick:c}),(0,o.createComponentVNode)(2,a.Box,{inline:!0,ml:1,color:"label",content:l})]})},u=function(e){var t,n;function i(){var t;return(t=e.call(this)||this).state={pillAmount:1,patchAmount:1,bottleAmount:1,packAmount:1,vialAmount:1,dartAmount:1},t}return n=e,(t=i).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,i.prototype.render=function(){var e=this,t=(this.state,this.props),n=t.state.config.ref,i=this.state,c=i.pillAmount,u=i.patchAmount,d=i.bottleAmount,s=i.packAmount,p=i.vialAmount,m=i.dartAmount,f=t.state.data,h=f.condi,C=f.chosenPillStyle,g=f.pillStyles,b=void 0===g?[]:g;return(0,o.createComponentVNode)(2,a.LabeledList,{children:[!h&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pill type",children:b.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{width:5,selected:e.id===C,textAlign:"center",color:"transparent",onClick:function(){return(0,r.act)(n,"pillStyle",{id:e.id})},children:(0,o.createComponentVNode)(2,a.Box,{mx:-1,className:e.className})},e.id)}))}),!h&&(0,o.createComponentVNode)(2,l,{label:"Pills",amount:c,amountUnit:"pills",sideNote:"max 50u",onChangeAmount:function(t,n){return e.setState({pillAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"pill",amount:c,volume:"auto"})}}),!h&&(0,o.createComponentVNode)(2,l,{label:"Patches",amount:u,amountUnit:"patches",sideNote:"max 40u",onChangeAmount:function(t,n){return e.setState({patchAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"patch",amount:u,volume:"auto"})}}),!h&&(0,o.createComponentVNode)(2,l,{label:"Bottles",amount:d,amountUnit:"bottles",sideNote:"max 30u",onChangeAmount:function(t,n){return e.setState({bottleAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"bottle",amount:d,volume:"auto"})}}),!h&&(0,o.createComponentVNode)(2,l,{label:"Hypovials",amount:p,amountUnit:"vials",sideNote:"max 60u",onChangeAmount:function(t,n){return e.setState({vialAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"hypoVial",amount:p,volume:"auto"})}}),!h&&(0,o.createComponentVNode)(2,l,{label:"Smartdarts",amount:m,amountUnit:"darts",sideNote:"max 20u",onChangeAmount:function(t,n){return e.setState({dartAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"smartDart",amount:m,volume:"auto"})}}),!!h&&(0,o.createComponentVNode)(2,l,{label:"Packs",amount:s,amountUnit:"packs",sideNote:"max 10u",onChangeAmount:function(t,n){return e.setState({packAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"condimentPack",amount:s,volume:"auto"})}}),!!h&&(0,o.createComponentVNode)(2,l,{label:"Bottles",amount:d,amountUnit:"bottles",sideNote:"max 50u",onChangeAmount:function(t,n){return e.setState({bottleAmount:n})},onCreate:function(){return(0,r.act)(n,"create",{type:"condimentBottle",amount:d,volume:"auto"})}})]})},i}(o.Component)},function(e,t,n){"use strict";t.__esModule=!0,t.ChemPress=void 0;var o=n(0),r=n(3),a=n(2);t.ChemPress=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.pill_size,l=i.pill_name,u=i.pill_style,d=i.pill_styles,s=void 0===d?[]:d;return(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pill Volume",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:c,unit:"u",width:"43px",minValue:5,maxValue:50,step:1,stepPixelSize:2,onChange:function(e,t){return n("change_pill_size",{volume:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pill Name",children:(0,o.createComponentVNode)(2,a.Input,{value:l,onChange:function(e,t){return n("change_pill_name",{name:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pill Style",children:s.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{width:5,selected:e.id===u,textAlign:"center",color:"transparent",onClick:function(){return n("change_pill_style",{id:e.id})},children:(0,o.createComponentVNode)(2,a.Box,{mx:-1,className:e.class_name})},e.id)}))})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemReactionChamber=void 0;var o=n(0),r=n(16),a=n(2),i=n(24),c=n(11);var l=function(e){var t,n;function l(){var t;return(t=e.call(this)||this).state={reagentName:"",reagentQuantity:1},t}n=e,(t=l).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n;var u=l.prototype;return u.setReagentName=function(e){this.setState({reagentName:e})},u.setReagentQuantity=function(e){this.setState({reagentQuantity:e})},u.render=function(){var e=this,t=this.props.state,n=t.config,l=t.data,u=n.ref,d=l.emptying,s=l.reagents||[];return(0,o.createComponentVNode)(2,a.Section,{title:"Reagents",buttons:(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,color:d?"bad":"good",children:d?"Emptying":"Filling"}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createVNode)(1,"tr","LabledList__row",[(0,o.createVNode)(1,"td","LabeledList__cell",(0,o.createComponentVNode)(2,a.Input,{fluid:!0,value:"",placeholder:"Reagent Name",onInput:function(t,n){return e.setReagentName(n)}}),2,{colSpan:"2"}),(0,o.createVNode)(1,"td",(0,c.classes)(["LabeledList__buttons","LabeledList__cell"]),[(0,o.createComponentVNode)(2,a.NumberInput,{value:this.state.reagentQuantity,minValue:1,maxValue:100,step:1,stepPixelSize:3,width:"39px",onDrag:function(t,n){return e.setReagentQuantity(n)}}),(0,o.createComponentVNode)(2,a.Box,{inline:!0,mr:1}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",onClick:function(){return(0,r.act)(u,"add",{chem:e.state.reagentName,amount:e.state.reagentQuantity})}})],4)],4),(0,i.map)((function(e,t){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:t,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"minus",color:"bad",onClick:function(){return(0,r.act)(u,"remove",{chem:t})}}),children:e},t)}))(s)]})})},l}(o.Component);t.ChemReactionChamber=l},function(e,t,n){"use strict";t.__esModule=!0,t.ChemSplitter=void 0;var o=n(0),r=n(17),a=n(3),i=n(2);t.ChemSplitter=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.straight,u=c.side,d=c.max_transfer;return(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Straight",children:(0,o.createComponentVNode)(2,i.NumberInput,{value:l,unit:"u",width:"55px",minValue:1,maxValue:d,format:function(e){return(0,r.toFixed)(e,2)},step:.05,stepPixelSize:4,onChange:function(e,t){return n("set_amount",{target:"straight",amount:t})}})}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Side",children:(0,o.createComponentVNode)(2,i.NumberInput,{value:u,unit:"u",width:"55px",minValue:1,maxValue:d,format:function(e){return(0,r.toFixed)(e,2)},step:.05,stepPixelSize:4,onChange:function(e,t){return n("set_amount",{target:"side",amount:t})}})})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.ChemSynthesizer=void 0;var o=n(0),r=n(17),a=n(3),i=n(2);t.ChemSynthesizer=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.amount,u=c.current_reagent,d=c.chemicals,s=void 0===d?[]:d,p=c.possible_amounts,m=void 0===p?[]:p;return(0,o.createComponentVNode)(2,i.Section,{children:[(0,o.createComponentVNode)(2,i.Box,{children:m.map((function(e){return(0,o.createComponentVNode)(2,i.Button,{icon:"plus",content:(0,r.toFixed)(e,0),selected:e===l,onClick:function(){return n("amount",{target:e})}},(0,r.toFixed)(e,0))}))}),(0,o.createComponentVNode)(2,i.Box,{mt:1,children:s.map((function(e){return(0,o.createComponentVNode)(2,i.Button,{icon:"tint",content:e.title,width:"129px",selected:e.id===u,onClick:function(){return n("select",{reagent:e.id})}},e.id)}))})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.CodexGigas=void 0;var o=n(0),r=n(3),a=n(2);t.CodexGigas=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{children:[i.name,(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Prefix",children:["Dark","Hellish","Fallen","Fiery","Sinful","Blood","Fluffy"].map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e,disabled:1!==i.currentSection,onClick:function(){return n(e+" ")}},e.toLowerCase())}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Title",children:["Lord","Prelate","Count","Viscount","Vizier","Elder","Adept"].map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e,disabled:i.currentSection>2,onClick:function(){return n(e+" ")}},e.toLowerCase())}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Name",children:["hal","ve","odr","neit","ci","quon","mya","folth","wren","geyr","hil","niet","twou","phi","coa"].map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e,disabled:i.currentSection>4,onClick:function(){return n(e)}},e.toLowerCase())}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Suffix",children:["the Red","the Soulless","the Master","the Lord of all things","Jr."].map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e,disabled:4!==i.currentSection,onClick:function(){return n(" "+e)}},e.toLowerCase())}))}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Submit",children:(0,o.createComponentVNode)(2,a.Button,{content:"Search",disabled:i.currentSection<4,onClick:function(){return n("search")}})})]})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.ComputerFabricator=void 0;var o=n(0),r=(n(23),n(3)),a=n(2);t.ComputerFabricator=function(e){var t=e.state,n=(0,r.useBackend)(e),c=n.act,l=n.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{italic:!0,fontSize:"20px",children:"Your perfect device, only three steps away..."}),0!==l.state&&(0,o.createComponentVNode)(2,a.Button,{fluid:!0,mb:1,icon:"circle",content:"Clear Order",onClick:function(){return c("clean_order")}}),(0,o.createComponentVNode)(2,i,{state:t})],0)};var i=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return 0===i.state?(0,o.createComponentVNode)(2,a.Section,{title:"Step 1",minHeight:51,children:[(0,o.createComponentVNode)(2,a.Box,{mt:5,bold:!0,textAlign:"center",fontSize:"40px",children:"Choose your Device"}),(0,o.createComponentVNode)(2,a.Box,{mt:3,children:(0,o.createComponentVNode)(2,a.Grid,{width:"100%",children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"laptop",content:"Laptop",textAlign:"center",fontSize:"30px",lineHeight:"50px",onClick:function(){return n("pick_device",{pick:"1"})}})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"tablet-alt",content:"Tablet",textAlign:"center",fontSize:"30px",lineHeight:"50px",onClick:function(){return n("pick_device",{pick:"2"})}})})]})})]}):1===i.state?(0,o.createComponentVNode)(2,a.Section,{title:"Step 2: Customize your device",minHeight:47,buttons:(0,o.createComponentVNode)(2,a.Box,{bold:!0,color:"good",children:[i.totalprice," cr"]}),children:[(0,o.createComponentVNode)(2,a.Table,{children:[(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Battery:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"Allows your device to operate without external utility power\nsource. Advanced batteries increase battery life.",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_battery,onClick:function(){return n("hw_battery",{battery:"1"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Upgraded",selected:2===i.hw_battery,onClick:function(){return n("hw_battery",{battery:"2"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Advanced",selected:3===i.hw_battery,onClick:function(){return n("hw_battery",{battery:"3"})}})})]}),(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Hard Drive:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"Stores file on your device. Advanced drives can store more\nfiles, but use more power, shortening battery life.",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_disk,onClick:function(){return n("hw_disk",{disk:"1"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Upgraded",selected:2===i.hw_disk,onClick:function(){return n("hw_disk",{disk:"2"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Advanced",selected:3===i.hw_disk,onClick:function(){return n("hw_disk",{disk:"3"})}})})]}),(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Network Card:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"Allows your device to wirelessly connect to stationwide NTNet\nnetwork. Basic cards are limited to on-station use, while\nadvanced cards can operate anywhere near the station, which\nincludes asteroid outposts",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"None",selected:0===i.hw_netcard,onClick:function(){return n("hw_netcard",{netcard:"0"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_netcard,onClick:function(){return n("hw_netcard",{netcard:"1"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Advanced",selected:2===i.hw_netcard,onClick:function(){return n("hw_netcard",{netcard:"2"})}})})]}),(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Nano Printer:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"A device that allows for various paperwork manipulations,\nsuch as, scanning of documents or printing new ones.\nThis device was certified EcoFriendlyPlus and is capable of\nrecycling existing paper for printing purposes.",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"None",selected:0===i.hw_nanoprint,onClick:function(){return n("hw_nanoprint",{print:"0"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_nanoprint,onClick:function(){return n("hw_nanoprint",{print:"1"})}})})]}),(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Card Reader:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"Adds a slot that allows you to manipulate RFID cards.\nPlease note that this is not necessary to allow the device\nto read your identification, it is just necessary to\nmanipulate other cards.",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"None",selected:0===i.hw_card,onClick:function(){return n("hw_card",{card:"0"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_card,onClick:function(){return n("hw_card",{card:"1"})}})})]}),2!==i.devtype&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Processor Unit:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"A component critical for your device's functionality.\nIt allows you to run programs from your hard drive.\nAdvanced CPUs use more power, but allow you to run\nmore programs on background at once.",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_cpu,onClick:function(){return n("hw_cpu",{cpu:"1"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Advanced",selected:2===i.hw_cpu,onClick:function(){return n("hw_cpu",{cpu:"2"})}})})]}),(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,position:"relative",children:["Tesla Relay:",(0,o.createComponentVNode)(2,a.Tooltip,{content:"An advanced wireless power relay that allows your device\nto connect to nearby area power controller to provide\nalternative power source. This component is currently\nunavailable on tablet computers due to size restrictions.",position:"right"})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"None",selected:0===i.hw_tesla,onClick:function(){return n("hw_tesla",{tesla:"0"})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{content:"Standard",selected:1===i.hw_tesla,onClick:function(){return n("hw_tesla",{tesla:"1"})}})})]})],4)]}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,mt:3,content:"Confirm Order",color:"good",textAlign:"center",fontSize:"18px",lineHeight:"26px",onClick:function(){return n("confirm_order")}})]}):2===i.state?(0,o.createComponentVNode)(2,a.Section,{title:"Step 3: Payment",minHeight:47,children:[(0,o.createComponentVNode)(2,a.Box,{italic:!0,textAlign:"center",fontSize:"20px",children:"Your device is ready for fabrication..."}),(0,o.createComponentVNode)(2,a.Box,{bold:!0,mt:2,textAlign:"center",fontSize:"16px",children:[(0,o.createComponentVNode)(2,a.Box,{inline:!0,children:"Please insert the required"})," ",(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"good",children:[i.totalprice," cr"]})]}),(0,o.createComponentVNode)(2,a.Box,{bold:!0,mt:1,textAlign:"center",fontSize:"18px",children:"Current:"}),(0,o.createComponentVNode)(2,a.Box,{bold:!0,mt:.5,textAlign:"center",fontSize:"18px",color:i.credits>=i.totalprice?"good":"bad",children:[i.credits," cr"]}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:"Purchase",disabled:i.credits=10&&e<20?i.COLORS.department.security:e>=20&&e<30?i.COLORS.department.medbay:e>=30&&e<40?i.COLORS.department.science:e>=40&&e<50?i.COLORS.department.engineering:e>=50&&e<60?i.COLORS.department.cargo:e>=200&&e<230?i.COLORS.department.centcom:i.COLORS.department.other},u=function(e){var t=e.type,n=e.value;return(0,o.createComponentVNode)(2,a.Box,{inline:!0,width:4,color:i.COLORS.damageType[t],textAlign:"center",children:n})};t.CrewConsole=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,d=i.sensors||[];return(0,o.createComponentVNode)(2,a.Section,{minHeight:90,children:(0,o.createComponentVNode)(2,a.Table,{children:[(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,children:"Name"}),(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,collapsing:!0}),(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,collapsing:!0,textAlign:"center",children:"Vitals"}),(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,children:"Position"}),!!i.link_allowed&&(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,collapsing:!0,children:"Tracking"})]}),d.map((function(e){return(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:(f=e.ijob,f%10==0),color:l(e.ijob),children:[e.name," (",e.assignment,")"]}),(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,textAlign:"center",children:(0,o.createComponentVNode)(2,a.ColorBox,{color:(t=e.oxydam,r=e.toxdam,d=e.burndam,s=e.brutedam,p=t+r+d+s,m=Math.min(Math.max(Math.ceil(p/25),0),5),c[m])})}),(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,textAlign:"center",children:null!==e.oxydam?(0,o.createComponentVNode)(2,a.Box,{inline:!0,children:[(0,o.createComponentVNode)(2,u,{type:"oxy",value:e.oxydam}),"/",(0,o.createComponentVNode)(2,u,{type:"toxin",value:e.toxdam}),"/",(0,o.createComponentVNode)(2,u,{type:"burn",value:e.burndam}),"/",(0,o.createComponentVNode)(2,u,{type:"brute",value:e.brutedam})]}):e.life_status?"Alive":"Dead"}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:null!==e.pos_x?e.area:"N/A"}),!!i.link_allowed&&(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,children:(0,o.createComponentVNode)(2,a.Button,{content:"Track",disabled:!e.can_track,onClick:function(){return n("select_person",{name:e.name})}})})]},e.name);var t,r,d,s,p,m,f}))]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.Cryo=void 0;var o=n(0),r=n(3),a=n(2),i=n(164);t.Cryo=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Occupant",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Occupant",content:c.occupant.name?c.occupant.name:"No Occupant"}),!!c.hasOccupant&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"State",content:c.occupant.stat,color:c.occupant.statstate}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Temperature",color:c.occupant.temperaturestatus,children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:c.occupant.bodyTemperature})," K"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Health",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:c.occupant.health/c.occupant.maxHealth,color:c.occupant.health>0?"good":"average",children:(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:c.occupant.health})})}),[{label:"Brute",type:"bruteLoss"},{label:"Respiratory",type:"oxyLoss"},{label:"Toxin",type:"toxLoss"},{label:"Burn",type:"fireLoss"}].map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.label,children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:c.occupant[e.type]/100,children:(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:c.occupant[e.type]})})},e.id)}))],0)]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Cell",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power",content:(0,o.createComponentVNode)(2,a.Button,{icon:c.isOperating?"power-off":"times",disabled:c.isOpen,onClick:function(){return n("power")},color:c.isOperating&&"green",children:c.isOperating?"On":"Off"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Temperature",children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:c.cellTemperature})," K"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door",children:[(0,o.createComponentVNode)(2,a.Button,{icon:c.isOpen?"unlock":"lock",onClick:function(){return n("door")},content:c.isOpen?"Open":"Closed"}),(0,o.createComponentVNode)(2,a.Button,{icon:c.autoEject?"sign-out-alt":"sign-in-alt",onClick:function(){return n("autoeject")},content:c.autoEject?"Auto":"Manual"})]})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Beaker",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"eject",disabled:!c.isBeakerLoaded,onClick:function(){return n("ejectbeaker")},content:"Eject"}),children:(0,o.createComponentVNode)(2,i.BeakerContents,{beakerLoaded:c.isBeakerLoaded,beakerContents:c.beakerContents})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.PersonalCrafting=void 0;var o=n(0),r=n(24),a=n(3),i=n(2),c=function(e){var t=e.craftables,n=void 0===t?[]:t,r=(0,a.useBackend)(e),c=r.act,l=r.data,u=l.craftability,d=void 0===u?{}:u,s=l.display_compact,p=l.display_craftable_only;return n.map((function(e){return p&&!d[e.ref]?null:s?(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:e.name,className:"candystripe",buttons:(0,o.createComponentVNode)(2,i.Button,{icon:"cog",content:"Craft",disabled:!d[e.ref],tooltip:e.tool_text&&"Tools needed: "+e.tool_text,tooltipPosition:"left",onClick:function(){return c("make",{recipe:e.ref})}}),children:e.req_text},e.name):(0,o.createComponentVNode)(2,i.Section,{title:e.name,level:2,buttons:(0,o.createComponentVNode)(2,i.Button,{icon:"cog",content:"Craft",disabled:!d[e.ref],onClick:function(){return c("make",{recipe:e.ref})}}),children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[!!e.req_text&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Required",children:e.req_text}),!!e.catalyst_text&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Catalyst",children:e.catalyst_text}),!!e.tool_text&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Tools",children:e.tool_text})]})},e.name)}))};t.PersonalCrafting=function(e){var t=e.state,n=(0,a.useBackend)(e),l=n.act,u=n.data,d=u.busy,s=u.display_craftable_only,p=u.display_compact,m=(0,r.map)((function(e,t){return{category:t,subcategory:e,hasSubcats:"has_subcats"in e,firstSubcatName:Object.keys(e).find((function(e){return"has_subcats"!==e}))}}))(u.crafting_recipes||{}),f=!!d&&(0,o.createComponentVNode)(2,i.Dimmer,{fontSize:"40px",textAlign:"center",children:(0,o.createComponentVNode)(2,i.Box,{mt:30,children:[(0,o.createComponentVNode)(2,i.Icon,{name:"cog",spin:1})," Crafting..."]})});return(0,o.createFragment)([f,(0,o.createComponentVNode)(2,i.Section,{title:"Personal Crafting",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Button,{icon:p?"check-square-o":"square-o",content:"Compact",selected:p,onClick:function(){return l("toggle_compact")}}),(0,o.createComponentVNode)(2,i.Button,{icon:s?"check-square-o":"square-o",content:"Craftable Only",selected:s,onClick:function(){return l("toggle_recipes")}})],4),children:(0,o.createComponentVNode)(2,i.Tabs,{children:m.map((function(e){return(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:e.category,onClick:function(){return l("set_category",{category:e.category,subcategory:e.firstSubcatName})},children:function(){return!e.hasSubcats&&(0,o.createComponentVNode)(2,c,{craftables:e.subcategory,state:t})||(0,o.createComponentVNode)(2,i.Tabs,{vertical:!0,children:(0,r.map)((function(e,n){if("has_subcats"!==n)return(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:n,onClick:function(){return l("set_category",{subcategory:n})},children:function(){return(0,o.createComponentVNode)(2,c,{craftables:e,state:t})}})}))(e.subcategory)})}},e.category)}))})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.DecalPainter=void 0;var o=n(0),r=n(3),a=n(2);t.DecalPainter=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.decal_list||[],l=i.color_list||[],u=i.dir_list||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Decal Type",children:c.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e.name,selected:e.decal===i.decal_style,onClick:function(){return n("select decal",{decals:e.decal})}},e.decal)}))}),(0,o.createComponentVNode)(2,a.Section,{title:"Decal Color",children:l.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:"red"===e.colors?"Red":"white"===e.colors?"White":"Yellow",selected:e.colors===i.decal_color,onClick:function(){return n("select color",{colors:e.colors})}},e.colors)}))}),(0,o.createComponentVNode)(2,a.Section,{title:"Decal Direction",children:u.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:1===e.dirs?"North":2===e.dirs?"South":4===e.dirs?"East":"West",selected:e.dirs===i.decal_direction,onClick:function(){return n("selected direction",{dirs:e.dirs})}},e.dirs)}))})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.DisposalUnit=void 0;var o=n(0),r=n(3),a=n(2);t.DisposalUnit=function(e){var t,n,i=(0,r.useBackend)(e),c=i.act,l=i.data;return l.full_pressure?(t="good",n="Ready"):l.panel_open?(t="bad",n="Power Disabled"):l.pressure_charging?(t="average",n="Pressurizing"):(t="bad",n="Off"),(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"State",color:t,children:n}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:l.per,color:"good"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Handle",children:(0,o.createComponentVNode)(2,a.Button,{icon:l.flush?"toggle-on":"toggle-off",disabled:l.isai||l.panel_open,content:l.flush?"Disengage":"Engage",onClick:function(){return c(l.flush?"handle-0":"handle-1")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Eject",children:(0,o.createComponentVNode)(2,a.Button,{icon:"sign-out-alt",disabled:l.isai,content:"Eject Contents",onClick:function(){return c("eject")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power",children:(0,o.createComponentVNode)(2,a.Button,{icon:"power-off",disabled:l.panel_open,selected:l.pressure_charging,onClick:function(){return c(l.pressure_charging?"pump-0":"pump-1")}})})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.DnaVault=void 0;var o=n(0),r=n(3),a=n(2);t.DnaVault=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.completed,l=i.used,u=i.choiceA,d=i.choiceB,s=i.dna,p=i.dna_max,m=i.plants,f=i.plants_max,h=i.animals,C=i.animals_max;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"DNA Vault Database",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Human DNA",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:s/p,content:s+" / "+p+" Samples"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Plant DNA",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:m/f,content:m+" / "+f+" Samples"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Animal DNA",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:h/h,content:h+" / "+C+" Samples"})})]})}),!(!c||l)&&(0,o.createComponentVNode)(2,a.Section,{title:"Personal Gene Therapy",children:[(0,o.createComponentVNode)(2,a.Box,{bold:!0,textAlign:"center",mb:1,children:"Applicable Gene Therapy Treatments"}),(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,bold:!0,content:u,textAlign:"center",onClick:function(){return n("gene",{choice:u})}})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,bold:!0,content:d,textAlign:"center",onClick:function(){return n("gene",{choice:d})}})})]})]})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.EightBallVote=void 0;var o=n(0),r=n(3),a=n(2),i=n(23);t.EightBallVote=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.question,u=c.shaking,d=c.answers,s=void 0===d?[]:d;return u?(0,o.createComponentVNode)(2,a.Section,{children:[(0,o.createComponentVNode)(2,a.Box,{bold:!0,textAlign:"center",fontSize:"16px",m:1,children:['"',l,'"']}),(0,o.createComponentVNode)(2,a.Grid,{children:s.map((function(e){return(0,o.createComponentVNode)(2,a.Grid.Column,{children:[(0,o.createComponentVNode)(2,a.Button,{fluid:!0,bold:!0,content:(0,i.toTitleCase)(e.answer),selected:e.selected,fontSize:"16px",lineHeight:"24px",textAlign:"center",mb:1,onClick:function(){return n("vote",{answer:e.answer})}}),(0,o.createComponentVNode)(2,a.Box,{bold:!0,textAlign:"center",fontSize:"30px",children:e.amount})]},e.answer)}))})]}):(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No question is currently being asked."})}},function(e,t,n){"use strict";t.__esModule=!0,t.EmergencyShuttleConsole=void 0;var o=n(0),r=n(2),a=n(3);t.EmergencyShuttleConsole=function(e){var t=(0,a.useBackend)(e),n=t.act,i=t.data,c=i.timer_str,l=i.enabled,u=i.emagged,d=i.engines_started,s=i.authorizations_remaining,p=i.authorizations,m=void 0===p?[]:p;return(0,o.createComponentVNode)(2,r.Section,{children:[(0,o.createComponentVNode)(2,r.Box,{bold:!0,fontSize:"40px",textAlign:"center",fontFamily:"monospace",children:c}),(0,o.createComponentVNode)(2,r.Box,{textAlign:"center",fontSize:"16px",mb:1,children:[(0,o.createComponentVNode)(2,r.Box,{inline:!0,bold:!0,children:"ENGINES:"}),(0,o.createComponentVNode)(2,r.Box,{inline:!0,color:d?"good":"average",ml:1,children:d?"Online":"Idle"})]}),(0,o.createComponentVNode)(2,r.Section,{title:"Early Launch Authorization",level:2,buttons:(0,o.createComponentVNode)(2,r.Button,{icon:"times",content:"Repeal All",color:"bad",disabled:!l,onClick:function(){return n("abort")}}),children:[(0,o.createComponentVNode)(2,r.Grid,{children:[(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.Button,{fluid:!0,icon:"exclamation-triangle",color:"good",content:"AUTHORIZE",disabled:!l,onClick:function(){return n("authorize")}})}),(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.Button,{fluid:!0,icon:"minus",content:"REPEAL",disabled:!l,onClick:function(){return n("repeal")}})})]}),(0,o.createComponentVNode)(2,r.Section,{title:"Authorizations",level:3,minHeight:"150px",buttons:(0,o.createComponentVNode)(2,r.Box,{inline:!0,bold:!0,color:u?"bad":"good",children:u?"ERROR":"Remaining: "+s}),children:[m.length>0?m.map((function(e){return(0,o.createComponentVNode)(2,r.Box,{bold:!0,fontSize:"16px",className:"candystripe",children:[e.name," (",e.job,")"]},e.name)})):(0,o.createComponentVNode)(2,r.Box,{bold:!0,textAlign:"center",fontSize:"16px",color:"average",children:"No Active Authorizations"}),m.map((function(e){return(0,o.createComponentVNode)(2,r.Box,{bold:!0,fontSize:"16px",className:"candystripe",children:[e.name," (",e.job,")"]},e.name)}))]})]})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.EngravedMessage=void 0;var o=n(0),r=n(23),a=n(3),i=n(2);t.EngravedMessage=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.admin_mode,u=c.creator_key,d=c.creator_name,s=c.has_liked,p=c.has_disliked,m=c.hidden_message,f=c.is_creator,h=c.num_likes,C=c.num_dislikes,g=c.realdate;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{children:[(0,o.createComponentVNode)(2,i.Box,{bold:!0,textAlign:"center",fontSize:"20px",mb:2,children:(0,r.decodeHtmlEntities)(m)}),(0,o.createComponentVNode)(2,i.Grid,{children:[(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.Button,{fluid:!0,icon:"arrow-up",content:" "+h,disabled:f,selected:s,textAlign:"center",fontSize:"16px",lineHeight:"24px",onClick:function(){return n("like")}})}),(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.Button,{fluid:!0,icon:"circle",disabled:f,selected:!p&&!s,textAlign:"center",fontSize:"16px",lineHeight:"24px",onClick:function(){return n("neutral")}})}),(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.Button,{fluid:!0,icon:"arrow-down",content:" "+C,disabled:f,selected:p,textAlign:"center",fontSize:"16px",lineHeight:"24px",onClick:function(){return n("dislike")}})})]})]}),(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Created On",children:g})})}),(0,o.createComponentVNode)(2,i.Section),!!l&&(0,o.createComponentVNode)(2,i.Section,{title:"Admin Panel",buttons:(0,o.createComponentVNode)(2,i.Button,{icon:"times",content:"Delete",color:"bad",onClick:function(){return n("delete")}}),children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Creator Ckey",children:u}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Creator Character Name",children:d})]})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.Gps=void 0;var o=n(0),r=n(24),a=n(70),i=n(17),c=n(156),l=n(3),u=n(2),d=function(e){return(0,r.map)(parseFloat)(e.split(", "))};t.Gps=function(e){var t=(0,l.useBackend)(e),n=t.act,s=t.data,p=s.currentArea,m=s.currentCoords,f=s.globalmode,h=s.power,C=s.tag,g=s.updating,b=(0,a.flow)([(0,r.map)((function(e,t){var n=e.dist&&Math.round((0,c.vecLength)((0,c.vecSubtract)(d(m),d(e.coords))));return Object.assign({},e,{dist:n,index:t})})),(0,r.sortBy)((function(e){return e.dist===undefined}),(function(e){return e.entrytag}))])(s.signals||[]);return(0,o.createFragment)([(0,o.createComponentVNode)(2,u.Section,{title:"Control",buttons:(0,o.createComponentVNode)(2,u.Button,{icon:"power-off",content:h?"On":"Off",selected:h,onClick:function(){return n("power")}}),children:(0,o.createComponentVNode)(2,u.LabeledList,{children:[(0,o.createComponentVNode)(2,u.LabeledList.Item,{label:"Tag",children:(0,o.createComponentVNode)(2,u.Button,{icon:"pencil-alt",content:C,onClick:function(){return n("rename")}})}),(0,o.createComponentVNode)(2,u.LabeledList.Item,{label:"Scan Mode",children:(0,o.createComponentVNode)(2,u.Button,{icon:g?"unlock":"lock",content:g?"AUTO":"MANUAL",color:!g&&"bad",onClick:function(){return n("updating")}})}),(0,o.createComponentVNode)(2,u.LabeledList.Item,{label:"Range",children:(0,o.createComponentVNode)(2,u.Button,{icon:"sync",content:f?"MAXIMUM":"LOCAL",selected:!f,onClick:function(){return n("globalmode")}})})]})}),!!h&&(0,o.createFragment)([(0,o.createComponentVNode)(2,u.Section,{title:"Current Location",children:(0,o.createComponentVNode)(2,u.Box,{fontSize:"18px",children:[p," (",m,")"]})}),(0,o.createComponentVNode)(2,u.Section,{title:"Detected Signals",children:(0,o.createComponentVNode)(2,u.Table,{children:[(0,o.createComponentVNode)(2,u.Table.Row,{bold:!0,children:[(0,o.createComponentVNode)(2,u.Table.Cell,{content:"Name"}),(0,o.createComponentVNode)(2,u.Table.Cell,{collapsing:!0,content:"Direction"}),(0,o.createComponentVNode)(2,u.Table.Cell,{collapsing:!0,content:"Coordinates"})]}),b.map((function(e){return(0,o.createComponentVNode)(2,u.Table.Row,{className:"candystripe",children:[(0,o.createComponentVNode)(2,u.Table.Cell,{bold:!0,color:"label",children:e.entrytag}),(0,o.createComponentVNode)(2,u.Table.Cell,{collapsing:!0,opacity:e.dist!==undefined&&(0,i.clamp)(1.2/Math.log(Math.E+e.dist/20),.4,1),children:[e.degrees!==undefined&&(0,o.createComponentVNode)(2,u.Icon,{mr:1,size:1.2,name:"arrow-up",rotation:e.degrees}),e.dist!==undefined&&e.dist+"m"]}),(0,o.createComponentVNode)(2,u.Table.Cell,{collapsing:!0,children:e.coords})]},e.entrytag+e.coords+e.index)}))]})})],4)],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.GravityGenerator=void 0;var o=n(0),r=n(3),a=n(2);t.GravityGenerator=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.breaker,l=i.charge_count,u=i.charging_state,d=i.on,s=i.operational;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{children:!s&&(0,o.createComponentVNode)(2,a.NoticeBox,{textAlign:"center",children:"No data available"})||(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Breaker",children:(0,o.createComponentVNode)(2,a.Button,{icon:c?"power-off":"times",content:c?"On":"Off",selected:c,disabled:!s,onClick:function(){return n("gentoggle")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Gravity Charge",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:l/100,ranges:{good:[.7,Infinity],average:[.3,.7],bad:[-Infinity,.3]}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Charge Mode",children:[0===u&&(d&&(0,o.createComponentVNode)(2,a.Box,{color:"good",children:"Fully Charged"})||(0,o.createComponentVNode)(2,a.Box,{color:"bad",children:"Not Charging"})),1===u&&(0,o.createComponentVNode)(2,a.Box,{color:"average",children:"Charging"}),2===u&&(0,o.createComponentVNode)(2,a.Box,{color:"average",children:"Discharging"})]})]})}),s&&0!==u&&(0,o.createComponentVNode)(2,a.NoticeBox,{textAlign:"center",children:"WARNING - Radiation detected"}),s&&0===u&&(0,o.createComponentVNode)(2,a.NoticeBox,{textAlign:"center",children:"No radiation detected"})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.GulagTeleporterConsole=void 0;var o=n(0),r=n(3),a=n(2);t.GulagTeleporterConsole=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.teleporter,l=i.teleporter_lock,u=i.teleporter_state_open,d=i.teleporter_location,s=i.beacon,p=i.beacon_location,m=i.id,f=i.id_name,h=i.can_teleport,C=i.goal,g=void 0===C?0:C,b=i.prisoner,N=void 0===b?{}:b;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Teleporter Console",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{content:u?"Open":"Closed",disabled:l,selected:u,onClick:function(){return n("toggle_open")}}),(0,o.createComponentVNode)(2,a.Button,{icon:l?"lock":"unlock",content:l?"Locked":"Unlocked",selected:l,disabled:u,onClick:function(){return n("teleporter_lock")}})],4),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Teleporter Unit",color:c?"good":"bad",buttons:!c&&(0,o.createComponentVNode)(2,a.Button,{content:"Reconnect",onClick:function(){return n("scan_teleporter")}}),children:c?d:"Not Connected"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Receiver Beacon",color:s?"good":"bad",buttons:!s&&(0,o.createComponentVNode)(2,a.Button,{content:"Reconnect",onClick:function(){return n("scan_beacon")}}),children:s?p:"Not Connected"})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Prisoner Details",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Prisoner ID",children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:m?f:"No ID",onClick:function(){return n("handle_id")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Point Goal",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:g,width:"48px",minValue:1,maxValue:1e3,onChange:function(e,t){return n("set_goal",{value:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Occupant",children:N.name?N.name:"No Occupant"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Criminal Status",children:N.crimstat?N.crimstat:"No Status"})]})}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:"Process Prisoner",disabled:!h,textAlign:"center",color:"bad",onClick:function(){return n("teleport")}})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.GulagItemReclaimer=void 0;var o=n(0),r=n(3),a=n(2);t.GulagItemReclaimer=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.mobs||[];return(0,o.createComponentVNode)(2,a.Section,{title:"Stored Items",children:(0,o.createComponentVNode)(2,a.Table,{children:c.map((function(e){return(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{children:e.name}),(0,o.createComponentVNode)(2,a.Table.Cell,{textAlign:"right",children:(0,o.createComponentVNode)(2,a.Button,{content:"Retrieve Items",disabled:!i.can_reclaim,onClick:function(){return n("release_items",{mobref:e.mob})}})})]},e.mob)}))})})}},function(e,t,n){"use strict";t.__esModule=!0,t.Holodeck=void 0;var o=n(0),r=n(3),a=n(2);t.Holodeck=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.can_toggle_safety,l=i.default_programs,u=void 0===l?[]:l,d=i.emag_programs,s=void 0===d?[]:d,p=i.emagged,m=i.program;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Default Programs",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:p?"unlock":"lock",content:"Safeties",color:"bad",disabled:!c,selected:!p,onClick:function(){return n("safety")}}),children:u.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:e.name.substring(11),textAlign:"center",selected:e.type===m,onClick:function(){return n("load_program",{type:e.type})}},e.type)}))}),!!p&&(0,o.createComponentVNode)(2,a.Section,{title:"Dangerous Programs",children:s.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:e.name.substring(11),color:"bad",textAlign:"center",selected:e.type===m,onClick:function(){return n("load_program",{type:e.type})}},e.type)}))})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.HypnoChair=void 0;var o=n(0),r=n(3),a=n(2);t.HypnoChair=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Information",backgroundColor:"#450F44",children:"The Enhanced Interrogation Chamber is designed to induce a deep-rooted trance trigger into the subject. Once the procedure is complete, by using the implanted trigger phrase, the authorities are able to ensure immediate and complete obedience and truthfulness."}),(0,o.createComponentVNode)(2,a.Section,{title:"Occupant Information",textAlign:"center",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Name",children:i.occupant.name?i.occupant.name:"No Occupant"}),!!i.occupied&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Status",color:0===i.occupant.stat?"good":1===i.occupant.stat?"average":"bad",children:0===i.occupant.stat?"Conscious":1===i.occupant.stat?"Unconcious":"Dead"})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Operations",textAlign:"center",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.open?"unlock":"lock",color:i.open?"default":"red",content:i.open?"Open":"Closed",onClick:function(){return n("door")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Phrase",children:(0,o.createComponentVNode)(2,a.Input,{value:i.trigger,onChange:function(e,t){return n("set_phrase",{phrase:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Interrogate Occupant",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"code-branch",content:i.interrogating?"Interrupt Interrogation":"Begin Enhanced Interrogation",onClick:function(){return n("interrogate")}}),1===i.interrogating&&(0,o.createComponentVNode)(2,a.Icon,{name:"cog",color:"orange",spin:!0})]})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.ImplantChair=void 0;var o=n(0),r=n(3),a=n(2);t.ImplantChair=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Occupant Information",textAlign:"center",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Name",children:i.occupant.name?i.occupant.name:"No Occupant"}),!!i.occupied&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Status",color:0===i.occupant.stat?"good":1===i.occupant.stat?"average":"bad",children:0===i.occupant.stat?"Conscious":1===i.occupant.stat?"Unconcious":"Dead"})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Operations",textAlign:"center",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Door",children:(0,o.createComponentVNode)(2,a.Button,{icon:i.open?"unlock":"lock",color:i.open?"default":"red",content:i.open?"Open":"Closed",onClick:function(){return n("door")}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Implant Occupant",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"code-branch",content:i.ready?i.special_name||"Implant":"Recharging",onClick:function(){return n("implant")}}),0===i.ready&&(0,o.createComponentVNode)(2,a.Icon,{name:"cog",color:"orange",spin:!0})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Implants Remaining",children:[i.ready_implants,1===i.replenishing&&(0,o.createComponentVNode)(2,a.Icon,{name:"sync",color:"red",spin:!0})]})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.Intellicard=void 0;var o=n(0),r=n(3),a=n(2);t.Intellicard=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=u||d,l=i.name,u=i.isDead,d=i.isBraindead,s=i.health,p=i.wireless,m=i.radio,f=i.wiping,h=i.laws,C=void 0===h?[]:h;return(0,o.createComponentVNode)(2,a.Section,{title:l||"Empty Card",buttons:!!l&&(0,o.createComponentVNode)(2,a.Button,{icon:"trash",content:f?"Stop Wiping":"Wipe",disabled:u,onClick:function(){return n("wipe")}}),children:!!l&&(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Status",color:c?"bad":"good",children:c?"Offline":"Operation"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Software Integrity",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:s,minValue:0,maxValue:100,ranges:{good:[70,Infinity],average:[50,70],bad:[-Infinity,50]}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Settings",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"signal",content:"Wireless Activity",selected:p,onClick:function(){return n("wireless")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"microphone",content:"Subspace Radio",selected:m,onClick:function(){return n("radio")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Laws",children:C.map((function(e){return(0,o.createComponentVNode)(2,a.BlockQuote,{children:e},e)}))})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.KeycardAuth=void 0;var o=n(0),r=n(3),a=n(2);t.KeycardAuth=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{children:[(0,o.createComponentVNode)(2,a.Box,{children:1===i.waiting&&(0,o.createVNode)(1,"span",null,"Waiting for another device to confirm your request...",16)}),(0,o.createComponentVNode)(2,a.Box,{children:0===i.waiting&&(0,o.createFragment)([!!i.auth_required&&(0,o.createComponentVNode)(2,a.Button,{icon:"check-square",color:"red",textAlign:"center",lineHeight:"60px",fluid:!0,onClick:function(){return n("auth_swipe")},content:"Authorize"}),0===i.auth_required&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"exclamation-triangle",fluid:!0,onClick:function(){return n("red_alert")},content:"Red Alert"}),(0,o.createComponentVNode)(2,a.Button,{icon:"wrench",fluid:!0,onClick:function(){return n("emergency_maint")},content:"Emergency Maintenance Access"}),(0,o.createComponentVNode)(2,a.Button,{icon:"meteor",fluid:!0,onClick:function(){return n("bsa_unlock")},content:"Bluespace Artillery Unlock"})],4)],0)})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.LaborClaimConsole=void 0;var o=n(0),r=n(23),a=n(3),i=n(2);t.LaborClaimConsole=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.can_go_home,u=c.id_points,d=c.ores,s=c.status_info,p=c.unclaimed_points;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Status",children:s}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Shuttle controls",children:(0,o.createComponentVNode)(2,i.Button,{content:"Move shuttle",disabled:!l,onClick:function(){return n("move_shuttle")}})}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Points",children:u}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Unclaimed points",buttons:(0,o.createComponentVNode)(2,i.Button,{content:"Claim points",disabled:!p,onClick:function(){return n("claim_points")}}),children:p})]})}),(0,o.createComponentVNode)(2,i.Section,{title:"Material values",children:(0,o.createComponentVNode)(2,i.Table,{children:[(0,o.createComponentVNode)(2,i.Table.Row,{header:!0,children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:"Material"}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:"Value"})]}),d.map((function(e){return(0,o.createComponentVNode)(2,i.Table.Row,{children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:(0,r.toTitleCase)(e.ore)}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:(0,o.createComponentVNode)(2,i.Box,{color:"label",inline:!0,children:e.value})})]},e.ore)}))]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.LanguageMenu=void 0;var o=n(0),r=n(3),a=n(2);t.LanguageMenu=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.admin_mode,l=i.is_living,u=i.omnitongue,d=i.languages,s=void 0===d?[]:d,p=i.unknown_languages,m=void 0===p?[]:p;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Known Languages",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:s.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.name,buttons:(0,o.createFragment)([!!l&&(0,o.createComponentVNode)(2,a.Button,{content:e.is_default?"Default Language":"Select as Default",disabled:!e.can_speak,selected:e.is_default,onClick:function(){return n("select_default",{language_name:e.name})}}),!!c&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{content:"Grant",onClick:function(){return n("grant_language",{language_name:e.name})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Remove",onClick:function(){return n("remove_language",{language_name:e.name})}})],4)],0),children:[e.desc," ","Key: ,",e.key," ",e.can_understand?"Can understand.":"Cannot understand."," ",e.can_speak?"Can speak.":"Cannot speak."]},e.name)}))})}),!!c&&(0,o.createComponentVNode)(2,a.Section,{title:"Unknown Languages",buttons:(0,o.createComponentVNode)(2,a.Button,{content:"Omnitongue "+(u?"Enabled":"Disabled"),selected:u,onClick:function(){return n("toggle_omnitongue")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:m.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.name,buttons:(0,o.createComponentVNode)(2,a.Button,{content:"Grant",onClick:function(){return n("grant_language",{language_name:e.name})}}),children:[e.desc," ","Key: ,",e.key," ",e.can_understand?"Can understand.":"Cannot understand."," ",e.can_speak?"Can speak.":"Cannot speak."]},e.name)}))})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.LaunchpadConsole=t.LaunchpadRemote=t.LaunchpadControl=t.LaunchpadButtonPad=void 0;var o=n(0),r=n(3),a=n(2),i=function(e){var t=(0,r.useBackend)(e).act;return(0,o.createComponentVNode)(2,a.Grid,{width:"1px",children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:[(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-left",iconRotation:45,mb:1,onClick:function(){return t("move_pos",{x:-1,y:1})}}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-left",mb:1,onClick:function(){return t("move_pos",{x:-1})}}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-down",iconRotation:45,mb:1,onClick:function(){return t("move_pos",{x:-1,y:-1})}})]}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:[(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-up",mb:1,onClick:function(){return t("move_pos",{y:1})}}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:"R",mb:1,onClick:function(){return t("set_pos",{x:0,y:0})}}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-down",mb:1,onClick:function(){return t("move_pos",{y:-1})}})]}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:[(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-up",iconRotation:45,mb:1,onClick:function(){return t("move_pos",{x:1,y:1})}}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-right",mb:1,onClick:function(){return t("move_pos",{x:1})}}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"arrow-right",iconRotation:45,mb:1,onClick:function(){return t("move_pos",{x:1,y:-1})}})]})]})};t.LaunchpadButtonPad=i;var c=function(e){var t=e.topLevel,n=(0,r.useBackend)(e),c=n.act,l=n.data,u=l.x,d=l.y,s=l.pad_name,p=l.range;return(0,o.createComponentVNode)(2,a.Section,{title:(0,o.createComponentVNode)(2,a.Input,{value:s,width:"170px",onChange:function(e,t){return c("rename",{name:t})}}),level:t?1:2,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"times",content:"Remove",color:"bad",onClick:function(){return c("remove")}}),children:[(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Controls",level:2,children:(0,o.createComponentVNode)(2,i,{state:e.state})})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Target",level:2,children:(0,o.createComponentVNode)(2,a.Box,{fontSize:"26px",children:[(0,o.createComponentVNode)(2,a.Box,{mb:1,children:[(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,mr:1,children:"X:"}),(0,o.createComponentVNode)(2,a.NumberInput,{value:u,minValue:-p,maxValue:p,lineHeight:"30px",fontSize:"26px",width:"90px",height:"30px",stepPixelSize:10,onChange:function(e,t){return c("set_pos",{x:t})}})]}),(0,o.createComponentVNode)(2,a.Box,{children:[(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,mr:1,children:"Y:"}),(0,o.createComponentVNode)(2,a.NumberInput,{value:d,minValue:-p,maxValue:p,stepPixelSize:10,lineHeight:"30px",fontSize:"26px",width:"90px",height:"30px",onChange:function(e,t){return c("set_pos",{y:t})}})]})]})})})]}),(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"upload",content:"Launch",textAlign:"center",onClick:function(){return c("launch")}})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"download",content:"Pull",textAlign:"center",onClick:function(){return c("pull")}})})]})]})};t.LaunchpadControl=c;t.LaunchpadRemote=function(e){var t=(0,r.useBackend)(e).data,n=t.has_pad,i=t.pad_closed;return n?i?(0,o.createComponentVNode)(2,a.NoticeBox,{children:"Launchpad Closed"}):(0,o.createComponentVNode)(2,c,{topLevel:!0,state:e.state}):(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No Launchpad Connected"})};t.LaunchpadConsole=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,l=i.launchpads,u=void 0===l?[]:l,d=i.selected_id;return u.length<=0?(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No Pads Connected"}):(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{size:.6,children:(0,o.createComponentVNode)(2,a.Box,{style:{"border-right":"2px solid rgba(255, 255, 255, 0.1)"},minHeight:"190px",mr:1,children:u.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:e.name,selected:d===e.id,color:"transparent",onClick:function(){return n("select_pad",{id:e.id})}},e.name)}))})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:d?(0,o.createComponentVNode)(2,c,{state:e.state}):(0,o.createComponentVNode)(2,a.Box,{children:"Please select a pad"})})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.MechBayPowerConsole=void 0;var o=n(0),r=n(3),a=n(2);t.MechBayPowerConsole=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data.recharge_port,c=i&&i.mech,l=c&&c.cell;return(0,o.createComponentVNode)(2,a.Section,{title:"Mech status",textAlign:"center",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"sync",content:"Sync",onClick:function(){return n("reconnect")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Integrity",children:!i&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No power port detected. Please re-sync."})||!c&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No mech detected."})||(0,o.createComponentVNode)(2,a.ProgressBar,{value:c.health/c.maxhealth,ranges:{good:[.7,Infinity],average:[.3,.7],bad:[-Infinity,.3]}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power",children:!i&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No power port detected. Please re-sync."})||!c&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No mech detected."})||!l&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No cell is installed."})||(0,o.createComponentVNode)(2,a.ProgressBar,{value:l.charge/l.maxcharge,ranges:{good:[.7,Infinity],average:[.3,.7],bad:[-Infinity,.3]},children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:l.charge})," / "+l.maxcharge]})})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.NaniteChamberControl=void 0;var o=n(0),r=n(3),a=n(2);t.NaniteChamberControl=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.status_msg,l=i.locked,u=i.occupant_name,d=i.has_nanites,s=i.nanite_volume,p=i.regen_rate,m=i.safety_threshold,f=i.cloud_id,h=i.scan_level;if(c)return(0,o.createComponentVNode)(2,a.NoticeBox,{textAlign:"center",children:c});var C=i.mob_programs||[];return(0,o.createComponentVNode)(2,a.Section,{title:"Chamber: "+u,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:l?"lock":"lock-open",content:l?"Locked":"Unlocked",color:l?"bad":"default",onClick:function(){return n("toggle_lock")}}),children:d?(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Status",level:2,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"exclamation-triangle",content:"Destroy Nanites",color:"bad",onClick:function(){return n("remove_nanites")}}),children:(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Nanite Volume",children:s}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Growth Rate",children:p})]})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Safety Threshold",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:m,minValue:0,maxValue:500,width:"39px",onChange:function(e,t){return n("set_safety",{value:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Cloud ID",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:f,minValue:0,maxValue:100,step:1,stepPixelSize:3,width:"39px",onChange:function(e,t){return n("set_cloud",{value:t})}})})]})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Programs",level:2,children:C.map((function(e){var t=e.extra_settings||[],n=e.rules||[];return(0,o.createComponentVNode)(2,a.Collapsible,{title:e.name,children:(0,o.createComponentVNode)(2,a.Section,{children:[(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:e.desc}),h>=2&&(0,o.createComponentVNode)(2,a.Grid.Column,{size:.6,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Activation Status",children:(0,o.createComponentVNode)(2,a.Box,{color:e.activated?"good":"bad",children:e.activated?"Active":"Inactive"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Nanites Consumed",children:[e.use_rate,"/s"]})]})})]}),h>=2&&(0,o.createComponentVNode)(2,a.Grid,{children:[!!e.can_trigger&&(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Triggers",level:2,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Cost",children:e.trigger_cost}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Cooldown",children:e.trigger_cooldown}),!!e.timer_trigger_delay&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Delay",children:[e.timer_trigger_delay," s"]}),!!e.timer_trigger&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Repeat Timer",children:[e.timer_trigger," s"]})]})})}),!(!e.timer_restart&&!e.timer_shutdown)&&(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[e.timer_restart&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Restart Timer",children:[e.timer_restart," s"]}),e.timer_shutdown&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Shutdown Timer",children:[e.timer_shutdown," s"]})]})})})]}),h>=3&&!!e.has_extra_settings&&(0,o.createComponentVNode)(2,a.Section,{title:"Extra Settings",level:2,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:t.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.name,children:e.value},e.name)}))})}),h>=4&&(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Codes",level:2,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[!!e.activation_code&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Activation",children:e.activation_code}),!!e.deactivation_code&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Deactivation",children:e.deactivation_code}),!!e.kill_code&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Kill",children:e.kill_code}),!!e.can_trigger&&!!e.trigger_code&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger",children:e.trigger_code})]})})}),e.has_rules&&(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Rules",level:2,children:n.map((function(e){return(0,o.createFragment)([e.display,(0,o.createVNode)(1,"br")],0,e.display)}))})})]})]})},e.name)}))})],4):(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{bold:!0,color:"bad",textAlign:"center",fontSize:"30px",mb:1,children:"No Nanites Detected"}),(0,o.createComponentVNode)(2,a.Button,{fluid:!0,bold:!0,icon:"syringe",content:" Implant Nanites",color:"green",textAlign:"center",fontSize:"30px",lineHeight:"50px",onClick:function(){return n("nanite_injection")}})],4)})}},function(e,t,n){"use strict";t.__esModule=!0,t.NaniteCloudControl=t.NaniteCloudBackupDetails=t.NaniteCloudBackupList=t.NaniteInfoBox=t.NaniteDiskBox=void 0;var o=n(0),r=n(3),a=n(2),i=function(e){var t=e.state.data,n=t.has_disk,r=t.has_program,i=t.disk;return n?r?(0,o.createComponentVNode)(2,c,{program:i}):(0,o.createComponentVNode)(2,a.NoticeBox,{children:"Inserted disk has no program"}):(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No disk inserted"})};t.NaniteDiskBox=i;var c=function(e){var t=e.program,n=t.name,r=t.desc,i=t.activated,c=t.use_rate,l=t.can_trigger,u=t.trigger_cost,d=t.trigger_cooldown,s=t.activation_code,p=t.deactivation_code,m=t.kill_code,f=t.trigger_code,h=t.timer_restart,C=t.timer_shutdown,g=t.timer_trigger,b=t.timer_trigger_delay,N=t.extra_settings||[];return(0,o.createComponentVNode)(2,a.Section,{title:n,level:2,buttons:(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,color:i?"good":"bad",children:i?"Activated":"Deactivated"}),children:[(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{mr:1,children:r}),(0,o.createComponentVNode)(2,a.Grid.Column,{size:.5,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Use Rate",children:c}),!!l&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Cost",children:u}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Cooldown",children:d})],4)]})})]}),(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Codes",level:3,mr:1,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Activation",children:s}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Deactivation",children:p}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Kill",children:m}),!!l&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger",children:f})]})})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.Section,{title:"Delays",level:3,mr:1,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Restart",children:[h," s"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Shutdown",children:[C," s"]}),!!l&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger",children:[g," s"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Delay",children:[b," s"]})],4)]})})})]}),(0,o.createComponentVNode)(2,a.Section,{title:"Extra Settings",level:3,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:N.map((function(e){var t={number:(0,o.createFragment)([e.value,e.unit],0),text:e.value,type:e.value,boolean:e.value?e.true_text:e.false_text};return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.name,children:t[e.type]},e.name)}))})})]})};t.NaniteInfoBox=c;var l=function(e){var t=(0,r.useBackend)(e),n=t.act;return(t.data.cloud_backups||[]).map((function(e){return(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:"Backup #"+e.cloud_id,textAlign:"center",onClick:function(){return n("set_view",{view:e.cloud_id})}},e.cloud_id)}))};t.NaniteCloudBackupList=l;var u=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,l=i.current_view,u=i.disk,d=i.has_program,s=i.cloud_backup,p=u&&u.can_rule||!1;if(!s)return(0,o.createComponentVNode)(2,a.NoticeBox,{children:"ERROR: Backup not found"});var m=i.cloud_programs||[];return(0,o.createComponentVNode)(2,a.Section,{title:"Backup #"+l,level:2,buttons:!!d&&(0,o.createComponentVNode)(2,a.Button,{icon:"upload",content:"Upload From Disk",color:"good",onClick:function(){return n("upload_program")}}),children:m.map((function(e){var t=e.rules||[];return(0,o.createComponentVNode)(2,a.Collapsible,{title:e.name,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"minus-circle",color:"bad",onClick:function(){return n("remove_program",{program_id:e.id})}}),children:(0,o.createComponentVNode)(2,a.Section,{children:[(0,o.createComponentVNode)(2,c,{program:e}),!!p&&(0,o.createComponentVNode)(2,a.Section,{mt:-2,title:"Rules",level:2,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"plus",content:"Add Rule from Disk",color:"good",onClick:function(){return n("add_rule",{program_id:e.id})}}),children:e.has_rules?t.map((function(t){return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"minus-circle",color:"bad",onClick:function(){return n("remove_rule",{program_id:e.id,rule_id:t.id})}}),t.display],0,t.display)})):(0,o.createComponentVNode)(2,a.Box,{color:"bad",children:"No Active Rules"})})]})},e.name)}))})};t.NaniteCloudBackupDetails=u;t.NaniteCloudControl=function(e){var t=e.state,n=(0,r.useBackend)(e),c=n.act,d=n.data,s=d.has_disk,p=d.current_view,m=d.new_backup_id;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Program Disk",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",disabled:!s,onClick:function(){return c("eject")}}),children:(0,o.createComponentVNode)(2,i,{state:t})}),(0,o.createComponentVNode)(2,a.Section,{title:"Cloud Storage",buttons:p?(0,o.createComponentVNode)(2,a.Button,{icon:"arrow-left",content:"Return",onClick:function(){return c("set_view",{view:0})}}):(0,o.createFragment)(["New Backup: ",(0,o.createComponentVNode)(2,a.NumberInput,{value:m,minValue:1,maxValue:100,stepPixelSize:4,width:"39px",onChange:function(e,t){return c("update_new_backup_value",{value:t})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",onClick:function(){return c("create_backup")}})],0),children:d.current_view?(0,o.createComponentVNode)(2,u,{state:t}):(0,o.createComponentVNode)(2,l,{state:t})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.NaniteProgramHub=void 0;var o=n(0),r=n(24),a=n(3),i=n(2);t.NaniteProgramHub=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.detail_view,u=c.disk,d=c.has_disk,s=c.has_program,p=c.programs,m=void 0===p?{}:p;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{title:"Program Disk",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Button,{icon:"eject",content:"Eject",onClick:function(){return n("eject")}}),(0,o.createComponentVNode)(2,i.Button,{icon:"minus-circle",content:"Delete Program",onClick:function(){return n("clear")}})],4),children:d?s?(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Program Name",children:u.name}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Description",children:u.desc})]}):(0,o.createComponentVNode)(2,i.NoticeBox,{children:"No Program Installed"}):(0,o.createComponentVNode)(2,i.NoticeBox,{children:"Insert Disk"})}),(0,o.createComponentVNode)(2,i.Section,{title:"Programs",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Button,{icon:l?"info":"list",content:l?"Detailed":"Compact",onClick:function(){return n("toggle_details")}}),(0,o.createComponentVNode)(2,i.Button,{icon:"sync",content:"Sync Research",onClick:function(){return n("refresh")}})],4),children:null!==m?(0,o.createComponentVNode)(2,i.Tabs,{vertical:!0,children:(0,r.map)((function(e,t){var r=e||[],a=t.substring(0,t.length-8);return(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:a,children:l?r.map((function(e){return(0,o.createComponentVNode)(2,i.Section,{title:e.name,level:2,buttons:(0,o.createComponentVNode)(2,i.Button,{icon:"download",content:"Download",disabled:!d,onClick:function(){return n("download",{program_id:e.id})}}),children:e.desc},e.id)})):(0,o.createComponentVNode)(2,i.LabeledList,{children:r.map((function(e){return(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:e.name,buttons:(0,o.createComponentVNode)(2,i.Button,{icon:"download",content:"Download",disabled:!d,onClick:function(){return n("download",{program_id:e.id})}})},e.id)}))})},t)}))(m)}):(0,o.createComponentVNode)(2,i.NoticeBox,{children:"No nanite programs are currently researched."})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.NaniteProgrammer=t.NaniteExtraBoolean=t.NaniteExtraType=t.NaniteExtraText=t.NaniteExtraNumber=t.NaniteExtraEntry=t.NaniteDelays=t.NaniteCodes=void 0;var o=n(0),r=n(3),a=n(2),i=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{title:"Codes",level:3,mr:1,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Activation",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.activation_code,width:"47px",minValue:0,maxValue:9999,onChange:function(e,t){return n("set_code",{target_code:"activation",code:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Deactivation",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.deactivation_code,width:"47px",minValue:0,maxValue:9999,onChange:function(e,t){return n("set_code",{target_code:"deactivation",code:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Kill",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.kill_code,width:"47px",minValue:0,maxValue:9999,onChange:function(e,t){return n("set_code",{target_code:"kill",code:t})}})}),!!i.can_trigger&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.trigger_code,width:"47px",minValue:0,maxValue:9999,onChange:function(e,t){return n("set_code",{target_code:"trigger",code:t})}})})]})})};t.NaniteCodes=i;var c=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{title:"Delays",level:3,ml:1,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Restart Timer",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.timer_restart,unit:"s",width:"57px",minValue:0,maxValue:3600,onChange:function(e,t){return n("set_restart_timer",{delay:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Shutdown Timer",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.timer_shutdown,unit:"s",width:"57px",minValue:0,maxValue:3600,onChange:function(e,t){return n("set_shutdown_timer",{delay:t})}})}),!!i.can_trigger&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Repeat Timer",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.timer_trigger,unit:"s",width:"57px",minValue:0,maxValue:3600,onChange:function(e,t){return n("set_trigger_timer",{delay:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Delay",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:i.timer_trigger_delay,unit:"s",width:"57px",minValue:0,maxValue:3600,onChange:function(e,t){return n("set_timer_trigger_delay",{delay:t})}})})],4)]})})};t.NaniteDelays=c;var l=function(e){var t=e.act,n=e.extra_setting,r=n.name,i=n.type,c={number:(0,o.createComponentVNode)(2,u,{act:t,extra_setting:n}),text:(0,o.createComponentVNode)(2,d,{act:t,extra_setting:n}),type:(0,o.createComponentVNode)(2,s,{act:t,extra_setting:n}),boolean:(0,o.createComponentVNode)(2,p,{act:t,extra_setting:n})};return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:r,children:c[i]})};t.NaniteExtraEntry=l;var u=function(e){var t=e.act,n=e.extra_setting,r=n.name,i=n.value,c=n.min,l=n.max,u=n.unit;return(0,o.createComponentVNode)(2,a.NumberInput,{value:i,width:"64px",minValue:c,maxValue:l,unit:u,onChange:function(e,n){return t("set_extra_setting",{target_setting:r,value:n})}})};t.NaniteExtraNumber=u;var d=function(e){var t=e.act,n=e.extra_setting,r=n.name,i=n.value;return(0,o.createComponentVNode)(2,a.Input,{value:i,width:"200px",onInput:function(e,n){return t("set_extra_setting",{target_setting:r,value:n})}})};t.NaniteExtraText=d;var s=function(e){var t=e.act,n=e.extra_setting,r=n.name,i=n.value,c=n.types;return(0,o.createComponentVNode)(2,a.Dropdown,{over:!0,selected:i,width:"150px",options:c,onSelected:function(e){return t("set_extra_setting",{target_setting:r,value:e})}})};t.NaniteExtraType=s;var p=function(e){var t=e.act,n=e.extra_setting,r=n.name,i=n.value,c=n.true_text,l=n.false_text;return(0,o.createComponentVNode)(2,a.Button.Checkbox,{content:i?c:l,checked:i,onClick:function(){return t("set_extra_setting",{target_setting:r})}})};t.NaniteExtraBoolean=p;t.NaniteProgrammer=function(e){var t=(0,r.useBackend)(e),n=t.act,u=t.data,d=u.has_disk,s=u.has_program,p=u.name,m=u.desc,f=u.use_rate,h=u.can_trigger,C=u.trigger_cost,g=u.trigger_cooldown,b=u.activated,N=u.has_extra_settings,v=u.extra_settings,V=void 0===v?{}:v;return d?s?(0,o.createComponentVNode)(2,a.Section,{title:p,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",onClick:function(){return n("eject")}}),children:[(0,o.createComponentVNode)(2,a.Section,{title:"Info",level:2,children:(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:m}),(0,o.createComponentVNode)(2,a.Grid.Column,{size:.7,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Use Rate",children:f}),!!h&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Cost",children:C}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Trigger Cooldown",children:g})],4)]})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Settings",level:2,buttons:(0,o.createComponentVNode)(2,a.Button,{icon:b?"power-off":"times",content:b?"Active":"Inactive",selected:b,color:"bad",bold:!0,onClick:function(){return n("toggle_active")}}),children:[(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,i,{state:e.state})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,c,{state:e.state})})]}),!!N&&(0,o.createComponentVNode)(2,a.Section,{title:"Special",level:3,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:V.map((function(e){return(0,o.createComponentVNode)(2,l,{act:n,extra_setting:e},e.name)}))})})]})]}):(0,o.createComponentVNode)(2,a.Section,{title:"Blank Disk",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",onClick:function(){return n("eject")}})}):(0,o.createComponentVNode)(2,a.NoticeBox,{textAlign:"center",children:"Insert a nanite program disk"})}},function(e,t,n){"use strict";t.__esModule=!0,t.NaniteRemote=void 0;var o=n(0),r=n(3),a=n(2);t.NaniteRemote=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.code,l=i.locked,u=i.mode,d=i.program_name,s=i.relay_code,p=i.comms,m=i.message,f=i.saved_settings,h=void 0===f?[]:f;return l?(0,o.createComponentVNode)(2,a.NoticeBox,{children:"This interface is locked."}):(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Nanite Control",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"lock",content:"Lock Interface",onClick:function(){return n("lock")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Name",children:[(0,o.createComponentVNode)(2,a.Input,{value:d,maxLength:14,width:"130px",onChange:function(e,t){return n("update_name",{name:t})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"save",content:"Save",onClick:function(){return n("save")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:p?"Comm Code":"Signal Code",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:c,minValue:0,maxValue:9999,width:"47px",step:1,stepPixelSize:2,onChange:function(e,t){return n("set_code",{code:t})}})}),!!p&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Message",children:(0,o.createComponentVNode)(2,a.Input,{value:m,width:"270px",onChange:function(e,t){return n("set_message",{value:t})}})}),"Relay"===u&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Relay Code",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:s,minValue:0,maxValue:9999,width:"47px",step:1,stepPixelSize:2,onChange:function(e,t){return n("set_relay_code",{code:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Signal Mode",children:["Off","Local","Targeted","Area","Relay"].map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e,selected:u===e,onClick:function(){return n("select_mode",{mode:e})}},e)}))})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Saved Settings",children:h.length>0?(0,o.createComponentVNode)(2,a.Table,{children:[(0,o.createComponentVNode)(2,a.Table.Row,{header:!0,children:[(0,o.createComponentVNode)(2,a.Table.Cell,{width:"35%",children:"Name"}),(0,o.createComponentVNode)(2,a.Table.Cell,{width:"20%",children:"Mode"}),(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,children:"Code"}),(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,children:"Relay"})]}),h.map((function(e){return(0,o.createComponentVNode)(2,a.Table.Row,{className:"candystripe",children:[(0,o.createComponentVNode)(2,a.Table.Cell,{bold:!0,color:"label",children:[e.name,":"]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:e.mode}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:e.code}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:"Relay"===e.mode&&e.relay_code}),(0,o.createComponentVNode)(2,a.Table.Cell,{textAlign:"right",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"upload",color:"good",onClick:function(){return n("load",{save_id:e.id})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"minus",color:"bad",onClick:function(){return n("remove_save",{save_id:e.id})}})]})]},e.id)}))]}):(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No settings currently saved"})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.Mule=void 0;var o=n(0),r=n(3),a=n(2),i=n(69);t.Mule=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.locked&&!c.siliconUser,u=c.siliconUser,d=c.on,s=c.cell,p=c.cellPercent,m=c.load,f=c.mode,h=c.modeStatus,C=c.haspai,g=c.autoReturn,b=c.autoPickup,N=c.reportDelivery,v=c.destination,V=c.home,y=c.id,_=c.destinations,k=void 0===_?[]:_;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.InterfaceLockNoticeBox,{siliconUser:u,locked:l}),(0,o.createComponentVNode)(2,a.Section,{title:"Status",minHeight:"110px",buttons:!l&&(0,o.createComponentVNode)(2,a.Button,{icon:d?"power-off":"times",content:d?"On":"Off",selected:d,onClick:function(){return n("power")}}),children:[(0,o.createComponentVNode)(2,a.ProgressBar,{value:s?p/100:0,color:s?"good":"bad"}),(0,o.createComponentVNode)(2,a.Grid,{mt:1,children:[(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Mode",color:h,children:f})})}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Load",color:m?"good":"average",children:m||"None"})})})]})]}),!l&&(0,o.createComponentVNode)(2,a.Section,{title:"Controls",buttons:(0,o.createFragment)([!!m&&(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Unload",onClick:function(){return n("unload")}}),!!C&&(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject PAI",onClick:function(){return n("ejectpai")}})],0),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"ID",children:(0,o.createComponentVNode)(2,a.Input,{value:y,onChange:function(e,t){return n("setid",{value:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Destination",children:[(0,o.createComponentVNode)(2,a.Dropdown,{over:!0,selected:v||"None",options:k,width:"150px",onSelected:function(e){return n("destination",{value:e})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"stop",content:"Stop",onClick:function(){return n("stop")}}),(0,o.createComponentVNode)(2,a.Button,{icon:"play",content:"Go",onClick:function(){return n("go")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Home",children:[(0,o.createComponentVNode)(2,a.Dropdown,{over:!0,selected:V,options:k,width:"150px",onSelected:function(e){return n("destination",{value:e})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"home",content:"Go Home",onClick:function(){return n("home")}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Settings",children:[(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:g,content:"Auto-Return",onClick:function(){return n("autored")}}),(0,o.createVNode)(1,"br"),(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:b,content:"Auto-Pickup",onClick:function(){return n("autopick")}}),(0,o.createVNode)(1,"br"),(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:N,content:"Report Delivery",onClick:function(){return n("report")}})]})]})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.NotificationPreferences=void 0;var o=n(0),r=n(3),a=n(2);t.NotificationPreferences=function(e){var t=(0,r.useBackend)(e),n=t.act,i=(t.data.ignore||[]).sort((function(e,t){var n=e.desc.toLowerCase(),o=t.desc.toLowerCase();return no?1:0}));return(0,o.createComponentVNode)(2,a.Section,{title:"Ghost Role Notifications",children:i.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:e.enabled?"times":"check",content:e.desc,color:e.enabled?"bad":"good",onClick:function(){return n("toggle_ignore",{key:e.key})}},e.key)}))})}},function(e,t,n){"use strict";t.__esModule=!0,t.NtnetRelay=void 0;var o=n(0),r=n(3),a=n(2);t.NtnetRelay=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.enabled,l=i.dos_capacity,u=i.dos_overload,d=i.dos_crashed;return(0,o.createComponentVNode)(2,a.Section,{title:"Network Buffer",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"power-off",selected:c,content:c?"ENABLED":"DISABLED",onClick:function(){return n("toggle")}}),children:d?(0,o.createComponentVNode)(2,a.Box,{fontFamily:"monospace",children:[(0,o.createComponentVNode)(2,a.Box,{fontSize:"20px",children:"NETWORK BUFFER OVERFLOW"}),(0,o.createComponentVNode)(2,a.Box,{fontSize:"16px",children:"OVERLOAD RECOVERY MODE"}),(0,o.createComponentVNode)(2,a.Box,{children:"This system is suffering temporary outage due to overflow of traffic buffers. Until buffered traffic is processed, all further requests will be dropped. Frequent occurences of this error may indicate insufficient hardware capacity of your network. Please contact your network planning department for instructions on how to resolve this issue."}),(0,o.createComponentVNode)(2,a.Box,{fontSize:"20px",color:"bad",children:"ADMINISTRATOR OVERRIDE"}),(0,o.createComponentVNode)(2,a.Box,{fontSize:"16px",color:"bad",children:"CAUTION - DATA LOSS MAY OCCUR"}),(0,o.createComponentVNode)(2,a.Button,{icon:"signal",content:"PURGE BUFFER",mt:1,color:"bad",onClick:function(){return n("restart")}})]}):(0,o.createComponentVNode)(2,a.ProgressBar,{value:u,minValue:0,maxValue:l,children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:u})," GQ"," / ",l," GQ"]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosArcade=void 0;var o=n(0),r=n(3),a=n(2);t.NtosArcade=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{title:"Outbomb Cuban Pete Ultra",textAlign:"center",children:[(0,o.createComponentVNode)(2,a.Box,{children:[(0,o.createComponentVNode)(2,a.Grid,{children:[(0,o.createComponentVNode)(2,a.Grid.Column,{size:2,children:[(0,o.createComponentVNode)(2,a.Box,{m:1}),(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Player Health",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.PlayerHitpoints,minValue:0,maxValue:30,ranges:{olive:[31,Infinity],good:[20,31],average:[10,20],bad:[-Infinity,10]},children:[i.PlayerHitpoints,"HP"]})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Player Magic",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.PlayerMP,minValue:0,maxValue:10,ranges:{purple:[11,Infinity],violet:[3,11],bad:[-Infinity,3]},children:[i.PlayerMP,"MP"]})})]}),(0,o.createComponentVNode)(2,a.Box,{my:1,mx:4}),(0,o.createComponentVNode)(2,a.Section,{backgroundColor:1===i.PauseState?"#1b3622":"#471915",children:i.Status})]}),(0,o.createComponentVNode)(2,a.Grid.Column,{children:[(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.Hitpoints/45,minValue:0,maxValue:45,ranges:{good:[30,Infinity],average:[5,30],bad:[-Infinity,5]},children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:i.Hitpoints}),"HP"]}),(0,o.createComponentVNode)(2,a.Box,{m:1}),(0,o.createComponentVNode)(2,a.Section,{inline:!0,width:26,textAlign:"center",children:(0,o.createVNode)(1,"img",null,null,1,{src:i.BossID})})]})]}),(0,o.createComponentVNode)(2,a.Box,{my:1,mx:4}),(0,o.createComponentVNode)(2,a.Button,{icon:"fist-raised",tooltip:"Go in for the kill!",tooltipPosition:"top",disabled:0===i.GameActive||1===i.PauseState,onClick:function(){return n("Attack")},content:"Attack!"}),(0,o.createComponentVNode)(2,a.Button,{icon:"band-aid",tooltip:"Heal yourself!",tooltipPosition:"top",disabled:0===i.GameActive||1===i.PauseState,onClick:function(){return n("Heal")},content:"Heal!"}),(0,o.createComponentVNode)(2,a.Button,{icon:"magic",tooltip:"Recharge your magic!",tooltipPosition:"top",disabled:0===i.GameActive||1===i.PauseState,onClick:function(){return n("Recharge_Power")},content:"Recharge!"})]}),(0,o.createComponentVNode)(2,a.Box,{children:[(0,o.createComponentVNode)(2,a.Button,{icon:"sync-alt",tooltip:"One more game couldn't hurt.",tooltipPosition:"top",disabled:1===i.GameActive,onClick:function(){return n("Start_Game")},content:"Begin Game"}),(0,o.createComponentVNode)(2,a.Button,{icon:"ticket-alt",tooltip:"Claim at your local Arcade Computer for Prizes!",tooltipPosition:"top",disabled:1===i.GameActive,onClick:function(){return n("Dispense_Tickets")},content:"Claim Tickets"})]}),(0,o.createComponentVNode)(2,a.Box,{color:i.TicketCount>=1?"good":"normal",children:["Earned Tickets: ",i.TicketCount]})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosConfiguration=void 0;var o=n(0),r=n(3),a=n(2);t.NtosConfiguration=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.power_usage,l=i.battery_exists,u=i.battery,d=void 0===u?{}:u,s=i.disk_size,p=i.disk_used,m=i.hardware,f=void 0===m?[]:m;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Power Supply",buttons:(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,mr:1,children:["Power Draw: ",c,"W"]}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Battery Status",color:!l&&"average",children:l?(0,o.createComponentVNode)(2,a.ProgressBar,{value:d.charge,minValue:0,maxValue:d.max,ranges:{good:[d.max/2,Infinity],average:[d.max/4,d.max/2],bad:[-Infinity,d.max/4]},children:[d.charge," / ",d.max]}):"Not Available"})})}),(0,o.createComponentVNode)(2,a.Section,{title:"File System",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:p,minValue:0,maxValue:s,color:"good",children:[p," GQ / ",s," GQ"]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Hardware Components",children:f.map((function(e){return(0,o.createComponentVNode)(2,a.Section,{title:e.name,level:2,buttons:(0,o.createFragment)([!e.critical&&(0,o.createComponentVNode)(2,a.Button.Checkbox,{content:"Enabled",checked:e.enabled,mr:1,onClick:function(){return n("PC_toggle_component",{name:e.name})}}),(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,mr:1,children:["Power Usage: ",e.powerusage,"W"]})],0),children:e.desc},e.name)}))})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosMain=void 0;var o=n(0),r=n(3),a=n(2),i={compconfig:"cog",ntndownloader:"download",filemanager:"folder",smmonitor:"radiation",alarmmonitor:"bell",cardmod:"id-card",arcade:"gamepad",ntnrc_client:"comment-alt",nttransfer:"exchange-alt",powermonitor:"plug"};t.NtosMain=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.programs,u=void 0===l?[]:l,d=c.has_light,s=c.light_on,p=c.comp_light_color;return(0,o.createFragment)([!!d&&(0,o.createComponentVNode)(2,a.Section,{children:[(0,o.createComponentVNode)(2,a.Button,{width:"144px",icon:"lightbulb",selected:s,onClick:function(){return n("PC_toggle_light")},children:["Flashlight: ",s?"ON":"OFF"]}),(0,o.createComponentVNode)(2,a.Button,{ml:1,onClick:function(){return n("PC_light_color")},children:["Color:",(0,o.createComponentVNode)(2,a.ColorBox,{ml:1,color:p})]})]}),(0,o.createComponentVNode)(2,a.Section,{title:"Programs",children:(0,o.createComponentVNode)(2,a.Table,{children:u.map((function(e){return(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{children:(0,o.createComponentVNode)(2,a.Button,{fluid:!0,lineHeight:"24px",color:"transparent",icon:i[e.name]||"window-maximize-o",content:e.desc,onClick:function(){return n("PC_runprogram",{name:e.name})}})}),(0,o.createComponentVNode)(2,a.Table.Cell,{collapsing:!0,width:3,children:!!e.running&&(0,o.createComponentVNode)(2,a.Button,{lineHeight:"24px",color:"transparent",icon:"times",tooltip:"Close program",tooltipPosition:"left",onClick:function(){return n("PC_killprogram",{name:e.name})}})})]},e.name)}))})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosNetChat=void 0;var o=n(0),r=n(3),a=n(2);(0,n(51).createLogger)("ntos chat");t.NtosNetChat=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.can_admin,l=i.adminmode,u=i.authed,d=i.username,s=i.active_channel,p=i.is_operator,m=i.all_channels,f=void 0===m?[]:m,h=i.clients,C=void 0===h?[]:h,g=i.messages,b=void 0===g?[]:g,N=null!==s,v=u||l;return(0,o.createComponentVNode)(2,a.Section,{height:"600px",children:(0,o.createComponentVNode)(2,a.Table,{height:"580px",children:(0,o.createComponentVNode)(2,a.Table.Row,{children:[(0,o.createComponentVNode)(2,a.Table.Cell,{verticalAlign:"top",style:{width:"200px"},children:[(0,o.createComponentVNode)(2,a.Box,{height:"537px",overflowY:"scroll",children:[(0,o.createComponentVNode)(2,a.Button.Input,{fluid:!0,content:"New Channel...",onCommit:function(e,t){return n("PRG_newchannel",{new_channel_name:t})}}),f.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{fluid:!0,content:e.chan,selected:e.id===s,color:"transparent",onClick:function(){return n("PRG_joinchannel",{id:e.id})}},e.chan)}))]}),(0,o.createComponentVNode)(2,a.Button.Input,{fluid:!0,mt:1,content:d+"...",currentValue:d,onCommit:function(e,t){return n("PRG_changename",{new_name:t})}}),!!c&&(0,o.createComponentVNode)(2,a.Button,{fluid:!0,bold:!0,content:"ADMIN MODE: "+(l?"ON":"OFF"),color:l?"bad":"good",onClick:function(){return n("PRG_toggleadmin")}})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{children:[(0,o.createComponentVNode)(2,a.Box,{height:"560px",overflowY:"scroll",children:N&&(v?b.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{children:e.msg},e.msg)})):(0,o.createComponentVNode)(2,a.Box,{textAlign:"center",children:[(0,o.createComponentVNode)(2,a.Icon,{name:"exclamation-triangle",mt:4,fontSize:"40px"}),(0,o.createComponentVNode)(2,a.Box,{mt:1,bold:!0,fontSize:"18px",children:"THIS CHANNEL IS PASSWORD PROTECTED"}),(0,o.createComponentVNode)(2,a.Box,{mt:1,children:"INPUT PASSWORD TO ACCESS"})]}))}),(0,o.createComponentVNode)(2,a.Input,{fluid:!0,selfClear:!0,mt:1,onEnter:function(e,t){return n("PRG_speak",{message:t})}})]}),(0,o.createComponentVNode)(2,a.Table.Cell,{verticalAlign:"top",style:{width:"150px"},children:[(0,o.createComponentVNode)(2,a.Box,{height:"477px",overflowY:"scroll",children:C.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{children:e.name},e.name)}))}),N&&v&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button.Input,{fluid:!0,content:"Save log...",defaultValue:"new_log",onCommit:function(e,t){return n("PRG_savelog",{log_name:t})}}),(0,o.createComponentVNode)(2,a.Button.Confirm,{fluid:!0,content:"Leave Channel",onClick:function(){return n("PRG_leavechannel")}})],4),!!p&&u&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button.Confirm,{fluid:!0,content:"Delete Channel",onClick:function(){return n("PRG_deletechannel")}}),(0,o.createComponentVNode)(2,a.Button.Input,{fluid:!0,content:"Rename Channel...",onCommit:function(e,t){return n("PRG_renamechannel",{new_name:t})}}),(0,o.createComponentVNode)(2,a.Button.Input,{fluid:!0,content:"Set Password...",onCommit:function(e,t){return n("PRG_setpassword",{new_password:t})}})],4)]})]})})})}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosNetDownloader=void 0;var o=n(0),r=n(3),a=n(2);t.NtosNetDownloader=function(e){var t=e.state,n=(0,r.useBackend)(e),c=n.act,l=n.data,u=l.disk_size,d=l.disk_used,s=l.downloadable_programs,p=void 0===s?[]:s,m=l.error,f=l.hacked_programs,h=void 0===f?[]:f,C=l.hackedavailable;return(0,o.createFragment)([!!m&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:[(0,o.createComponentVNode)(2,a.Box,{mb:1,children:m}),(0,o.createComponentVNode)(2,a.Button,{content:"Reset",onClick:function(){return c("PRG_reseterror")}})]}),(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Disk usage",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:d,minValue:0,maxValue:u,children:d+" GQ / "+u+" GQ"})})})}),(0,o.createComponentVNode)(2,a.Section,{children:p.map((function(e){return(0,o.createComponentVNode)(2,i,{state:t,program:e},e.filename)}))}),!!C&&(0,o.createComponentVNode)(2,a.Section,{title:"UNKNOWN Software Repository",children:[(0,o.createComponentVNode)(2,a.NoticeBox,{mb:1,children:"Please note that Nanotrasen does not recommend download of software from non-official servers."}),h.map((function(e){return(0,o.createComponentVNode)(2,i,{state:t,program:e},e.filename)}))]})],0)};var i=function(e){var t=e.program,n=(0,r.useBackend)(e),i=n.act,c=n.data,l=c.disk_size,u=c.disk_used,d=c.downloadcompletion,s=c.downloading,p=c.downloadname,m=c.downloadsize,f=l-u;return(0,o.createComponentVNode)(2,a.Box,{mb:3,children:[(0,o.createComponentVNode)(2,a.Flex,{align:"baseline",children:[(0,o.createComponentVNode)(2,a.Flex.Item,{bold:!0,grow:1,children:t.filedesc}),(0,o.createComponentVNode)(2,a.Flex.Item,{color:"label",nowrap:!0,children:[t.size," GQ"]}),(0,o.createComponentVNode)(2,a.Flex.Item,{ml:2,width:"94px",textAlign:"center",children:t.filename===p&&(0,o.createComponentVNode)(2,a.ProgressBar,{color:"green",minValue:0,maxValue:m,value:d})||(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"download",content:"Download",disabled:s||t.size>f,onClick:function(){return i("PRG_downloadfile",{filename:t.filename})}})})]}),"Compatible"!==t.compatibility&&(0,o.createComponentVNode)(2,a.Box,{mt:1,italic:!0,fontSize:"12px",position:"relative",children:[(0,o.createComponentVNode)(2,a.Icon,{mx:1,color:"red",name:"times"}),"Incompatible!"]}),t.size>f&&(0,o.createComponentVNode)(2,a.Box,{mt:1,italic:!0,fontSize:"12px",position:"relative",children:[(0,o.createComponentVNode)(2,a.Icon,{mx:1,color:"red",name:"times"}),"Not enough disk space!"]}),(0,o.createComponentVNode)(2,a.Box,{mt:1,italic:!0,color:"label",fontSize:"12px",children:t.fileinfo})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosSupermatterMonitor=void 0;var o=n(0),r=n(24),a=n(70),i=n(17),c=n(3),l=n(2),u=n(32),d=function(e){return Math.log2(16+Math.max(0,e))-4};t.NtosSupermatterMonitor=function(e){var t=e.state,n=(0,c.useBackend)(e),p=n.act,m=n.data,f=m.active,h=m.SM_integrity,C=m.SM_power,g=m.SM_ambienttemp,b=m.SM_ambientpressure;if(!f)return(0,o.createComponentVNode)(2,s,{state:t});var N=(0,a.flow)([function(e){return e.filter((function(e){return e.amount>=.01}))},(0,r.sortBy)((function(e){return-e.amount}))])(m.gases||[]),v=Math.max.apply(Math,[1].concat(N.map((function(e){return e.amount}))));return(0,o.createComponentVNode)(2,l.Flex,{spacing:1,children:[(0,o.createComponentVNode)(2,l.Flex.Item,{width:"270px",children:(0,o.createComponentVNode)(2,l.Section,{title:"Metrics",children:(0,o.createComponentVNode)(2,l.LabeledList,{children:[(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:"Integrity",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:h/100,ranges:{good:[.9,Infinity],average:[.5,.9],bad:[-Infinity,.5]}})}),(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:"Relative EER",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:C,minValue:0,maxValue:5e3,ranges:{good:[-Infinity,5e3],average:[5e3,7e3],bad:[7e3,Infinity]},children:(0,i.toFixed)(C)+" MeV/cm3"})}),(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:"Temperature",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:d(g),minValue:0,maxValue:d(1e4),ranges:{teal:[-Infinity,d(80)],good:[d(80),d(373)],average:[d(373),d(1e3)],bad:[d(1e3),Infinity]},children:(0,i.toFixed)(g)+" K"})}),(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:"Pressure",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:d(b),minValue:0,maxValue:d(5e4),ranges:{good:[d(1),d(300)],average:[-Infinity,d(1e3)],bad:[d(1e3),+Infinity]},children:(0,i.toFixed)(b)+" kPa"})})]})})}),(0,o.createComponentVNode)(2,l.Flex.Item,{grow:1,children:(0,o.createComponentVNode)(2,l.Section,{title:"Gases",buttons:(0,o.createComponentVNode)(2,l.Button,{icon:"arrow-left",content:"Back",onClick:function(){return p("PRG_clear")}}),children:(0,o.createComponentVNode)(2,l.Box.Forced,{height:24*N.length+"px",children:(0,o.createComponentVNode)(2,l.LabeledList,{children:N.map((function(e){return(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:(0,u.getGasLabel)(e.name),children:(0,o.createComponentVNode)(2,l.ProgressBar,{color:(0,u.getGasColor)(e.name),value:e.amount,minValue:0,maxValue:v,children:(0,i.toFixed)(e.amount,2)+"%"})},e.name)}))})})})})]})};var s=function(e){var t=(0,c.useBackend)(e),n=t.act,r=t.data.supermatters,a=void 0===r?[]:r;return(0,o.createComponentVNode)(2,l.Section,{title:"Detected Supermatters",buttons:(0,o.createComponentVNode)(2,l.Button,{icon:"sync",content:"Refresh",onClick:function(){return n("PRG_refresh")}}),children:(0,o.createComponentVNode)(2,l.Table,{children:a.map((function(e){return(0,o.createComponentVNode)(2,l.Table.Row,{children:[(0,o.createComponentVNode)(2,l.Table.Cell,{children:e.uid+". "+e.area_name}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,color:"label",children:"Integrity:"}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,width:"120px",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:e.integrity/100,ranges:{good:[.9,Infinity],average:[.5,.9],bad:[-Infinity,.5]}})}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,children:(0,o.createComponentVNode)(2,l.Button,{content:"Details",onClick:function(){return n("PRG_set",{target:e.uid})}})})]},e.uid)}))})})}},function(e,t,n){"use strict";t.__esModule=!0,t.NtosWrapper=void 0;var o=n(0),r=n(3),a=n(2),i=n(116);t.NtosWrapper=function(e){var t=e.children,n=(0,r.useBackend)(e),c=n.act,l=n.data,u=l.PC_batteryicon,d=l.PC_showbatteryicon,s=l.PC_batterypercent,p=l.PC_ntneticon,m=l.PC_apclinkicon,f=l.PC_stationtime,h=l.PC_programheaders,C=void 0===h?[]:h,g=l.PC_showexitprogram;return(0,o.createVNode)(1,"div","NtosWrapper",[(0,o.createVNode)(1,"div","NtosWrapper__header NtosHeader",[(0,o.createVNode)(1,"div","NtosHeader__left",[(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,mr:2,children:f}),(0,o.createComponentVNode)(2,a.Box,{inline:!0,italic:!0,mr:2,opacity:.33,children:"NtOS"})],4),(0,o.createVNode)(1,"div","NtosHeader__right",[C.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{inline:!0,mr:1,children:(0,o.createVNode)(1,"img","NtosHeader__icon",null,1,{src:e.icon})},e.icon)})),(0,o.createComponentVNode)(2,a.Box,{inline:!0,children:p&&(0,o.createVNode)(1,"img","NtosHeader__icon",null,1,{src:p})}),!!d&&u&&(0,o.createComponentVNode)(2,a.Box,{inline:!0,mr:1,children:[u&&(0,o.createVNode)(1,"img","NtosHeader__icon",null,1,{src:u}),s&&s]}),m&&(0,o.createComponentVNode)(2,a.Box,{inline:!0,mr:1,children:(0,o.createVNode)(1,"img","NtosHeader__icon",null,1,{src:m})}),!!g&&(0,o.createComponentVNode)(2,a.Button,{width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"window-minimize-o",tooltip:"Minimize",tooltipPosition:"bottom",onClick:function(){return c("PC_minimize")}}),!!g&&(0,o.createComponentVNode)(2,a.Button,{mr:"-3px",width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"window-close-o",tooltip:"Close",tooltipPosition:"bottom-left",onClick:function(){return c("PC_exit")}}),!g&&(0,o.createComponentVNode)(2,a.Button,{mr:"-3px",width:"26px",lineHeight:"22px",textAlign:"center",color:"transparent",icon:"power-off",tooltip:"Power off",tooltipPosition:"bottom-left",onClick:function(){return c("PC_shutdown")}})],0)],4,{onMouseDown:function(){(0,i.refocusLayout)()}}),(0,o.createVNode)(1,"div","NtosWrapper__content",t,0)],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.NuclearBomb=void 0;var o=n(0),r=n(11),a=n(3),i=n(2),c=function(e){var t=(0,a.useBackend)(e).act;return(0,o.createComponentVNode)(2,i.Box,{width:"185px",children:(0,o.createComponentVNode)(2,i.Grid,{width:"1px",children:[["1","4","7","C"],["2","5","8","0"],["3","6","9","E"]].map((function(e){return(0,o.createComponentVNode)(2,i.Grid.Column,{children:e.map((function(e){return(0,o.createComponentVNode)(2,i.Button,{fluid:!0,bold:!0,mb:1,content:e,textAlign:"center",fontSize:"40px",lineHeight:"50px",width:"55px",className:(0,r.classes)(["NuclearBomb__Button","NuclearBomb__Button--keypad","NuclearBomb__Button--"+e]),onClick:function(){return t("keypad",{digit:e})}},e)}))},e[0])}))})})};t.NuclearBomb=function(e){var t=e.state,n=(0,a.useBackend)(e),r=n.act,l=n.data,u=(l.anchored,l.disk_present,l.status1),d=l.status2;return(0,o.createComponentVNode)(2,i.Box,{m:1,children:[(0,o.createComponentVNode)(2,i.Box,{mb:1,className:"NuclearBomb__displayBox",children:u}),(0,o.createComponentVNode)(2,i.Flex,{mb:1.5,children:[(0,o.createComponentVNode)(2,i.Flex.Item,{grow:1,children:(0,o.createComponentVNode)(2,i.Box,{className:"NuclearBomb__displayBox",children:d})}),(0,o.createComponentVNode)(2,i.Flex.Item,{children:(0,o.createComponentVNode)(2,i.Button,{icon:"eject",fontSize:"24px",lineHeight:"23px",textAlign:"center",width:"43px",ml:1,mr:"3px",mt:"3px",className:"NuclearBomb__Button NuclearBomb__Button--keypad",onClick:function(){return r("eject_disk")}})})]}),(0,o.createComponentVNode)(2,i.Flex,{ml:"3px",children:[(0,o.createComponentVNode)(2,i.Flex.Item,{children:(0,o.createComponentVNode)(2,c,{state:t})}),(0,o.createComponentVNode)(2,i.Flex.Item,{ml:1,width:"129px",children:(0,o.createComponentVNode)(2,i.Box,{children:[(0,o.createComponentVNode)(2,i.Button,{fluid:!0,bold:!0,content:"ARM",textAlign:"center",fontSize:"28px",lineHeight:"32px",mb:1,className:"NuclearBomb__Button NuclearBomb__Button--C",onClick:function(){return r("arm")}}),(0,o.createComponentVNode)(2,i.Button,{fluid:!0,bold:!0,content:"ANCHOR",textAlign:"center",fontSize:"28px",lineHeight:"32px",className:"NuclearBomb__Button NuclearBomb__Button--E",onClick:function(){return r("anchor")}}),(0,o.createComponentVNode)(2,i.Box,{textAlign:"center",color:"#9C9987",fontSize:"80px",children:(0,o.createComponentVNode)(2,i.Icon,{name:"radiation"})}),(0,o.createComponentVNode)(2,i.Box,{height:"80px",className:"NuclearBomb__NTIcon"})]})})]})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.OperatingComputer=void 0;var o=n(0),r=n(3),a=n(2);t.OperatingComputer=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.table,l=i.surgeries,u=void 0===l?[]:l,d=i.procedures,s=void 0===d?[]:d,p=i.patient,m=void 0===p?{}:p;return(0,o.createComponentVNode)(2,a.Tabs,{children:[(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:"Patient State",children:[!c&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"No Table Detected"}),(0,o.createComponentVNode)(2,a.Section,{children:[(0,o.createComponentVNode)(2,a.Section,{title:"Patient State",level:2,children:m?(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"State",color:m.statstate,children:m.stat}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Blood Type",children:m.blood_type}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Health",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:m.health,minValue:m.minHealth,maxValue:m.maxHealth,color:m.health>=0?"good":"average",content:(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:m.health})})}),[{label:"Brute",type:"bruteLoss"},{label:"Burn",type:"fireLoss"},{label:"Toxin",type:"toxLoss"},{label:"Respiratory",type:"oxyLoss"}].map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.label,children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:m[e.type]/m.maxHealth,color:"bad",content:(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:m[e.type]})})},e.type)}))]}):"No Patient Detected"}),(0,o.createComponentVNode)(2,a.Section,{title:"Initiated Procedures",level:2,children:s.length?s.map((function(e){return(0,o.createComponentVNode)(2,a.Section,{title:e.name,level:3,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Next Step",children:[e.next_step,e.chems_needed&&(0,o.createFragment)([(0,o.createVNode)(1,"b",null,"Required Chemicals:",16),(0,o.createVNode)(1,"br"),e.chems_needed],0)]}),!!i.alternative_step&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Alternative Step",children:[e.alternative_step,e.alt_chems_needed&&(0,o.createFragment)([(0,o.createVNode)(1,"b",null,"Required Chemicals:",16),(0,o.createVNode)(1,"br"),e.alt_chems_needed],0)]})]})},e.name)})):"No Active Procedures"})]})]},"state"),(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:"Surgery Procedures",children:(0,o.createComponentVNode)(2,a.Section,{title:"Advanced Surgery Procedures",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"download",content:"Sync Research Database",onClick:function(){return n("sync")}}),u.map((function(e){return(0,o.createComponentVNode)(2,a.Section,{title:e.name,level:2,children:e.desc},e.name)}))]})},"procedures")]})}},function(e,t,n){"use strict";t.__esModule=!0,t.OreBox=void 0;var o=n(0),r=n(23),a=n(16),i=n(2);t.OreBox=function(e){var t=e.state,n=t.config,c=t.data,l=n.ref,u=c.materials;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{title:"Ores",buttons:(0,o.createComponentVNode)(2,i.Button,{content:"Empty",onClick:function(){return(0,a.act)(l,"removeall")}}),children:(0,o.createComponentVNode)(2,i.Table,{children:[(0,o.createComponentVNode)(2,i.Table.Row,{header:!0,children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:"Ore"}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:"Amount"})]}),u.map((function(e){return(0,o.createComponentVNode)(2,i.Table.Row,{children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:(0,r.toTitleCase)(e.name)}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:(0,o.createComponentVNode)(2,i.Box,{color:"label",inline:!0,children:e.amount})})]},e.type)}))]})}),(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.Box,{children:["All ores will be placed in here when you are wearing a mining stachel on your belt or in a pocket while dragging the ore box.",(0,o.createVNode)(1,"br"),"Gibtonite is not accepted."]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.OreRedemptionMachine=void 0;var o=n(0),r=n(23),a=n(3),i=n(2);t.OreRedemptionMachine=function(e){var t=(0,a.useBackend)(e),n=t.act,r=t.data,l=r.unclaimedPoints,u=r.materials,d=r.alloys,s=r.diskDesigns,p=r.hasDisk;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{children:[(0,o.createComponentVNode)(2,i.BlockQuote,{mb:1,children:["This machine only accepts ore.",(0,o.createVNode)(1,"br"),"Gibtonite and Slag are not accepted."]}),(0,o.createComponentVNode)(2,i.Box,{children:[(0,o.createComponentVNode)(2,i.Box,{inline:!0,color:"label",mr:1,children:"Unclaimed points:"}),l,(0,o.createComponentVNode)(2,i.Button,{ml:2,content:"Claim",disabled:0===l,onClick:function(){return n("Claim")}})]})]}),(0,o.createComponentVNode)(2,i.Section,{children:p&&(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Box,{mb:1,children:(0,o.createComponentVNode)(2,i.Button,{icon:"eject",content:"Eject design disk",onClick:function(){return n("diskEject")}})}),(0,o.createComponentVNode)(2,i.Table,{children:s.map((function(e){return(0,o.createComponentVNode)(2,i.Table.Row,{children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:["File ",e.index,": ",e.name]}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,children:(0,o.createComponentVNode)(2,i.Button,{disabled:!e.canupload,content:"Upload",onClick:function(){return n("diskUpload",{design:e.index})}})})]},e.index)}))})],4)||(0,o.createComponentVNode)(2,i.Button,{icon:"save",content:"Insert design disk",onClick:function(){return n("diskInsert")}})}),(0,o.createComponentVNode)(2,i.Section,{title:"Materials",children:(0,o.createComponentVNode)(2,i.Table,{children:u.map((function(e){return(0,o.createComponentVNode)(2,c,{material:e,onRelease:function(t){return n("Release",{id:e.id,sheets:t})}},e.id)}))})}),(0,o.createComponentVNode)(2,i.Section,{title:"Alloys",children:(0,o.createComponentVNode)(2,i.Table,{children:d.map((function(e){return(0,o.createComponentVNode)(2,c,{material:e,onRelease:function(t){return n("Smelt",{id:e.id,sheets:t})}},e.id)}))})})],4)};var c=function(e){var t,n;function a(){var t;return(t=e.call(this)||this).state={amount:1},t}return n=e,(t=a).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,a.prototype.render=function(){var e=this,t=this.state.amount,n=this.props,a=n.material,c=n.onRelease,l=Math.floor(a.amount);return(0,o.createComponentVNode)(2,i.Table.Row,{children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:(0,r.toTitleCase)(a.name).replace("Alloy","")}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:(0,o.createComponentVNode)(2,i.Box,{mr:2,color:"label",inline:!0,children:a.value&&a.value+" cr"})}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:(0,o.createComponentVNode)(2,i.Box,{mr:2,color:"label",inline:!0,children:[l," sheets"]})}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,children:[(0,o.createComponentVNode)(2,i.NumberInput,{width:"32px",step:1,stepPixelSize:5,minValue:1,maxValue:50,value:t,onChange:function(t,n){return e.setState({amount:n})}}),(0,o.createComponentVNode)(2,i.Button,{disabled:l<1,content:"Release",onClick:function(){return c(t)}})]})]})},a}(o.Component)},function(e,t,n){"use strict";t.__esModule=!0,t.Pandemic=t.PandemicAntibodyDisplay=t.PandemicSymptomDisplay=t.PandemicDiseaseDisplay=t.PandemicBeakerDisplay=void 0;var o=n(0),r=n(24),a=n(3),i=n(2),c=function(e){var t=(0,a.useBackend)(e),n=t.act,r=t.data,c=r.has_beaker,l=r.beaker_empty,u=r.has_blood,d=r.blood,s=!c||l;return(0,o.createComponentVNode)(2,i.Section,{title:"Beaker",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Button,{icon:"times",content:"Empty and Eject",color:"bad",disabled:s,onClick:function(){return n("empty_eject_beaker")}}),(0,o.createComponentVNode)(2,i.Button,{icon:"trash",content:"Empty",disabled:s,onClick:function(){return n("empty_beaker")}}),(0,o.createComponentVNode)(2,i.Button,{icon:"eject",content:"Eject",disabled:!c,onClick:function(){return n("eject_beaker")}})],4),children:c?l?(0,o.createComponentVNode)(2,i.Box,{color:"bad",children:"Beaker is empty"}):u?(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Blood DNA",children:d&&d.dna||"Unknown"}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Blood Type",children:d&&d.type||"Unknown"})]}):(0,o.createComponentVNode)(2,i.Box,{color:"bad",children:"No blood detected"}):(0,o.createComponentVNode)(2,i.NoticeBox,{children:"No beaker loaded"})})};t.PandemicBeakerDisplay=c;var l=function(e){var t=(0,a.useBackend)(e),n=t.act,r=t.data,c=r.is_ready;return(r.viruses||[]).map((function(e){var t=e.symptoms||[];return(0,o.createComponentVNode)(2,i.Section,{title:e.can_rename?(0,o.createComponentVNode)(2,i.Input,{value:e.name,onChange:function(t,o){return n("rename_disease",{index:e.index,name:o})}}):e.name,buttons:(0,o.createComponentVNode)(2,i.Button,{icon:"flask",content:"Create culture bottle",disabled:!c,onClick:function(){return n("create_culture_bottle",{index:e.index})}}),children:[(0,o.createComponentVNode)(2,i.Grid,{children:[(0,o.createComponentVNode)(2,i.Grid.Column,{children:e.description}),(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Agent",children:e.agent}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Spread",children:e.spread}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Possible Cure",children:e.cure})]})})]}),!!e.is_adv&&(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{title:"Statistics",level:2,children:(0,o.createComponentVNode)(2,i.Grid,{children:[(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Resistance",children:e.resistance}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Stealth",children:e.stealth})]})}),(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Stage speed",children:e.stage_speed}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Transmissibility",children:e.transmission})]})})]})}),(0,o.createComponentVNode)(2,i.Section,{title:"Symptoms",level:2,children:t.map((function(e){return(0,o.createComponentVNode)(2,i.Collapsible,{title:e.name,children:(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,u,{symptom:e})})},e.name)}))})],4)]},e.name)}))};t.PandemicDiseaseDisplay=l;var u=function(e){var t=e.symptom,n=t.name,a=t.desc,c=t.stealth,l=t.resistance,u=t.stage_speed,d=t.transmission,s=t.level,p=t.neutered,m=(0,r.map)((function(e,t){return{desc:e,label:t}}))(t.threshold_desc||{});return(0,o.createComponentVNode)(2,i.Section,{title:n,level:2,buttons:!!p&&(0,o.createComponentVNode)(2,i.Box,{bold:!0,color:"bad",children:"Neutered"}),children:[(0,o.createComponentVNode)(2,i.Grid,{children:[(0,o.createComponentVNode)(2,i.Grid.Column,{size:2,children:a}),(0,o.createComponentVNode)(2,i.Grid.Column,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Level",children:s}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Resistance",children:l}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Stealth",children:c}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Stage Speed",children:u}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Transmission",children:d})]})})]}),m.length>0&&(0,o.createComponentVNode)(2,i.Section,{title:"Thresholds",level:3,children:(0,o.createComponentVNode)(2,i.LabeledList,{children:m.map((function(e){return(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:e.label,children:e.desc},e.label)}))})})]})};t.PandemicSymptomDisplay=u;var d=function(e){var t=(0,a.useBackend)(e),n=t.act,r=t.data,c=r.resistances||[];return(0,o.createComponentVNode)(2,i.Section,{title:"Antibodies",children:c.length>0?(0,o.createComponentVNode)(2,i.LabeledList,{children:c.map((function(e){return(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:e.name,children:(0,o.createComponentVNode)(2,i.Button,{icon:"eye-dropper",content:"Create vaccine bottle",disabled:!r.is_ready,onClick:function(){return n("create_vaccine_bottle",{index:e.id})}})},e.name)}))}):(0,o.createComponentVNode)(2,i.Box,{bold:!0,color:"bad",mt:1,children:"No antibodies detected."})})};t.PandemicAntibodyDisplay=d;t.Pandemic=function(e){var t=(0,a.useBackend)(e).data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,c,{state:e.state}),!!t.has_blood&&(0,o.createFragment)([(0,o.createComponentVNode)(2,l,{state:e.state}),(0,o.createComponentVNode)(2,d,{state:e.state})],4)],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.PortableGenerator=void 0;var o=n(0),r=n(3),a=n(2);t.PortableGenerator=function(e){var t,n=(0,r.useBackend)(e),i=n.act,c=n.data;return t=c.stack_percent>50?"good":c.stack_percent>15?"average":"bad",(0,o.createFragment)([!c.anchored&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"Generator not anchored."}),(0,o.createComponentVNode)(2,a.Section,{title:"Status",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power switch",children:(0,o.createComponentVNode)(2,a.Button,{icon:c.active?"power-off":"times",onClick:function(){return i("toggle_power")},disabled:!c.ready_to_boot,children:c.active?"On":"Off"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:c.sheet_name+" sheets",children:[(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:t,children:c.sheets}),c.sheets>=1&&(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"eject",disabled:c.active,onClick:function(){return i("eject")},children:"Eject"})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current sheet level",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:c.stack_percent/100,ranges:{good:[.1,Infinity],average:[.01,.1],bad:[-Infinity,.01]}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Heat level",children:c.current_heat<100?(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"good",children:"Nominal"}):c.current_heat<200?(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"average",children:"Caution"}):(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"bad",children:"DANGER"})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Output",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current output",children:c.power_output}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Adjust output",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"minus",onClick:function(){return i("lower_power")},children:c.power_generated}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",onClick:function(){return i("higher_power")},children:c.power_generated})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power available",children:(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:!c.connected&&"bad",children:c.connected?c.power_available:"Unconnected"})})]})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.PortableScrubber=t.PortablePump=t.PortableBasicInfo=void 0;var o=n(0),r=n(3),a=n(2),i=n(32),c=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.connected,l=i.holding,u=i.on,d=i.pressure;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Status",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:u?"power-off":"times",content:u?"On":"Off",selected:u,onClick:function(){return n("power")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure",children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:d})," kPa"]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Port",color:c?"good":"average",children:c?"Connected":"Not Connected"})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Holding Tank",minHeight:"82px",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject",disabled:!l,onClick:function(){return n("eject")}}),children:l?(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Label",children:l.name}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure",children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:l.pressure})," kPa"]})]}):(0,o.createComponentVNode)(2,a.Box,{color:"average",children:"No holding tank"})})],4)};t.PortableBasicInfo=c;t.PortablePump=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,l=i.direction,u=(i.holding,i.target_pressure),d=i.default_pressure,s=i.min_pressure,p=i.max_pressure;return(0,o.createFragment)([(0,o.createComponentVNode)(2,c,{state:e.state}),(0,o.createComponentVNode)(2,a.Section,{title:"Pump",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:l?"sign-in-alt":"sign-out-alt",content:l?"In":"Out",selected:l,onClick:function(){return n("direction")}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Output",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:u,unit:"kPa",width:"75px",minValue:s,maxValue:p,step:10,onChange:function(e,t){return n("pressure",{pressure:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Presets",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"minus",disabled:u===s,onClick:function(){return n("pressure",{pressure:"min"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"sync",disabled:u===d,onClick:function(){return n("pressure",{pressure:"reset"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"plus",disabled:u===p,onClick:function(){return n("pressure",{pressure:"max"})}})]})]})})],4)};t.PortableScrubber=function(e){var t=(0,r.useBackend)(e),n=t.act,l=t.data.filter_types||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,c,{state:e.state}),(0,o.createComponentVNode)(2,a.Section,{title:"Filters",children:l.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{icon:e.enabled?"check-square-o":"square-o",content:(0,i.getGasLabel)(e.gas_id,e.gas_name),selected:e.enabled,onClick:function(){return n("toggle_filter",{val:e.gas_id})}},e.id)}))})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.PowerMonitor=void 0;var o=n(0),r=n(24),a=n(70),i=n(17),c=n(11),l=n(2);var u=5e5,d=function(e){var t=String(e.split(" ")[1]).toLowerCase();return["w","kw","mw","gw"].indexOf(t)},s=function(e){var t,n;function c(){var t;return(t=e.call(this)||this).state={sortByField:null},t}return n=e,(t=c).prototype=Object.create(n.prototype),t.prototype.constructor=t,t.__proto__=n,c.prototype.render=function(){var e=this,t=this.props.state.data,n=t.history,c=this.state.sortByField,s=n.supply[n.supply.length-1]||0,f=n.demand[n.demand.length-1]||0,h=n.supply.map((function(e,t){return[t,e]})),C=n.demand.map((function(e,t){return[t,e]})),g=Math.max.apply(Math,[u].concat(n.supply,n.demand)),b=(0,a.flow)([(0,r.map)((function(e,t){return Object.assign({},e,{id:e.name+t})})),"name"===c&&(0,r.sortBy)((function(e){return e.name})),"charge"===c&&(0,r.sortBy)((function(e){return-e.charge})),"draw"===c&&(0,r.sortBy)((function(e){return-d(e.load)}),(function(e){return-parseFloat(e.load)}))])(t.areas);return(0,o.createFragment)([(0,o.createComponentVNode)(2,l.Flex,{spacing:1,children:[(0,o.createComponentVNode)(2,l.Flex.Item,{width:"200px",children:(0,o.createComponentVNode)(2,l.Section,{children:(0,o.createComponentVNode)(2,l.LabeledList,{children:[(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:"Supply",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:s,minValue:0,maxValue:g,color:"teal",content:(0,i.toFixed)(s/1e3)+" kW"})}),(0,o.createComponentVNode)(2,l.LabeledList.Item,{label:"Draw",children:(0,o.createComponentVNode)(2,l.ProgressBar,{value:f,minValue:0,maxValue:g,color:"pink",content:(0,i.toFixed)(f/1e3)+" kW"})})]})})}),(0,o.createComponentVNode)(2,l.Flex.Item,{grow:1,children:(0,o.createComponentVNode)(2,l.Section,{position:"relative",height:"100%",children:[(0,o.createComponentVNode)(2,l.Chart.Line,{fillPositionedParent:!0,data:h,rangeX:[0,h.length-1],rangeY:[0,g],strokeColor:"rgba(0, 181, 173, 1)",fillColor:"rgba(0, 181, 173, 0.25)"}),(0,o.createComponentVNode)(2,l.Chart.Line,{fillPositionedParent:!0,data:C,rangeX:[0,C.length-1],rangeY:[0,g],strokeColor:"rgba(224, 57, 151, 1)",fillColor:"rgba(224, 57, 151, 0.25)"})]})})]}),(0,o.createComponentVNode)(2,l.Section,{children:[(0,o.createComponentVNode)(2,l.Box,{mb:1,children:[(0,o.createComponentVNode)(2,l.Box,{inline:!0,mr:2,color:"label",children:"Sort by:"}),(0,o.createComponentVNode)(2,l.Button.Checkbox,{checked:"name"===c,content:"Name",onClick:function(){return e.setState({sortByField:"name"!==c&&"name"})}}),(0,o.createComponentVNode)(2,l.Button.Checkbox,{checked:"charge"===c,content:"Charge",onClick:function(){return e.setState({sortByField:"charge"!==c&&"charge"})}}),(0,o.createComponentVNode)(2,l.Button.Checkbox,{checked:"draw"===c,content:"Draw",onClick:function(){return e.setState({sortByField:"draw"!==c&&"draw"})}})]}),(0,o.createComponentVNode)(2,l.Table,{children:[(0,o.createComponentVNode)(2,l.Table.Row,{header:!0,children:[(0,o.createComponentVNode)(2,l.Table.Cell,{children:"Area"}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,children:"Charge"}),(0,o.createComponentVNode)(2,l.Table.Cell,{textAlign:"right",children:"Draw"}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,title:"Equipment",children:"Eqp"}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,title:"Lighting",children:"Lgt"}),(0,o.createComponentVNode)(2,l.Table.Cell,{collapsing:!0,title:"Environment",children:"Env"})]}),b.map((function(e,t){return(0,o.createVNode)(1,"tr","Table__row candystripe",[(0,o.createVNode)(1,"td",null,e.name,0),(0,o.createVNode)(1,"td","Table__cell text-right text-nowrap",(0,o.createComponentVNode)(2,p,{charging:e.charging,charge:e.charge}),2),(0,o.createVNode)(1,"td","Table__cell text-right text-nowrap",e.load,0),(0,o.createVNode)(1,"td","Table__cell text-center text-nowrap",(0,o.createComponentVNode)(2,m,{status:e.eqp}),2),(0,o.createVNode)(1,"td","Table__cell text-center text-nowrap",(0,o.createComponentVNode)(2,m,{status:e.lgt}),2),(0,o.createVNode)(1,"td","Table__cell text-center text-nowrap",(0,o.createComponentVNode)(2,m,{status:e.env}),2)],4,null,e.id)}))]})]})],4)},c}(o.Component);t.PowerMonitor=s;var p=function(e){var t=e.charging,n=e.charge;return(0,o.createFragment)([(0,o.createComponentVNode)(2,l.Icon,{width:"18px",textAlign:"center",name:0===t&&(n>50?"battery-half":"battery-quarter")||1===t&&"bolt"||2===t&&"battery-full",color:0===t&&(n>50?"yellow":"red")||1===t&&"yellow"||2===t&&"green"}),(0,o.createComponentVNode)(2,l.Box,{inline:!0,width:"36px",textAlign:"right",children:(0,i.toFixed)(n)+"%"})],4)};p.defaultHooks=c.pureComponentHooks;var m=function(e){var t=e.status,n=Boolean(2&t),r=Boolean(1&t),a=(n?"On":"Off")+" ["+(r?"auto":"manual")+"]";return(0,o.createComponentVNode)(2,l.ColorBox,{color:n?"good":"bad",content:r?undefined:"M",title:a})};m.defaultHooks=c.pureComponentHooks},function(e,t,n){"use strict";t.__esModule=!0,t.Radio=void 0;var o=n(0),r=n(24),a=n(17),i=n(3),c=n(2),l=n(32);t.Radio=function(e){var t=(0,i.useBackend)(e),n=t.act,u=t.data,d=u.freqlock,s=u.frequency,p=u.minFrequency,m=u.maxFrequency,f=u.listening,h=u.broadcasting,C=u.command,g=u.useCommand,b=u.subspace,N=u.subspaceSwitchable,v=l.RADIO_CHANNELS.find((function(e){return e.freq===s})),V=(0,r.map)((function(e,t){return{name:t,status:!!e}}))(u.channels);return(0,o.createComponentVNode)(2,c.Section,{children:(0,o.createComponentVNode)(2,c.LabeledList,{children:[(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Frequency",children:[d&&(0,o.createComponentVNode)(2,c.Box,{inline:!0,color:"light-gray",children:(0,a.toFixed)(s/10,1)+" kHz"})||(0,o.createComponentVNode)(2,c.NumberInput,{animate:!0,unit:"kHz",step:.2,stepPixelSize:10,minValue:p/10,maxValue:m/10,value:s/10,format:function(e){return(0,a.toFixed)(e,1)},onDrag:function(e,t){return n("frequency",{adjust:t-s/10})}}),v&&(0,o.createComponentVNode)(2,c.Box,{inline:!0,color:v.color,ml:2,children:["[",v.name,"]"]})]}),(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Audio",children:[(0,o.createComponentVNode)(2,c.Button,{textAlign:"center",width:"37px",icon:f?"volume-up":"volume-mute",selected:f,onClick:function(){return n("listen")}}),(0,o.createComponentVNode)(2,c.Button,{textAlign:"center",width:"37px",icon:h?"microphone":"microphone-slash",selected:h,onClick:function(){return n("broadcast")}}),!!C&&(0,o.createComponentVNode)(2,c.Button,{ml:1,icon:"bullhorn",selected:g,content:"High volume "+(g?"ON":"OFF"),onClick:function(){return n("command")}}),!!N&&(0,o.createComponentVNode)(2,c.Button,{ml:1,icon:"bullhorn",selected:b,content:"Subspace Tx "+(b?"ON":"OFF"),onClick:function(){return n("subspace")}})]}),!!b&&(0,o.createComponentVNode)(2,c.LabeledList.Item,{label:"Channels",children:[0===V.length&&(0,o.createComponentVNode)(2,c.Box,{inline:!0,color:"bad",children:"No encryption keys installed."}),V.map((function(e){return(0,o.createComponentVNode)(2,c.Box,{children:(0,o.createComponentVNode)(2,c.Button,{icon:e.status?"check-square-o":"square-o",selected:e.status,content:e.name,onClick:function(){return n("channel",{channel:e.name})}})},e.name)}))]})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.RapidPipeDispenser=void 0;var o=n(0),r=n(11),a=n(3),i=n(2),c=["Atmospherics","Disposals","Transit Tubes"],l={Atmospherics:"wrench",Disposals:"trash-alt","Transit Tubes":"bus",Pipes:"grip-lines","Disposal Pipes":"grip-lines",Devices:"microchip","Heat Exchange":"thermometer-half","Station Equipment":"microchip"},u={grey:"#bbbbbb",amethyst:"#a365ff",blue:"#4466ff",brown:"#b26438",cyan:"#48eae8",dark:"#808080",green:"#1edd00",orange:"#ffa030",purple:"#b535ea",red:"#ff3333",violet:"#6e00f6",yellow:"#ffce26"},d=[{name:"Dispense",bitmask:1},{name:"Connect",bitmask:2},{name:"Destroy",bitmask:4},{name:"Paint",bitmask:8}];t.RapidPipeDispenser=function(e){var t=(0,a.useBackend)(e),n=t.act,s=t.data,p=s.category,m=s.categories,f=void 0===m?[]:m,h=s.selected_color,C=s.piping_layer,g=s.mode,b=s.preview_rows.flatMap((function(e){return e.previews}));return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Category",children:c.map((function(e,t){return(0,o.createComponentVNode)(2,i.Button,{selected:p===t,icon:l[e],color:"transparent",content:e,onClick:function(){return n("category",{category:t})}},e)}))}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Modes",children:d.map((function(e){return(0,o.createComponentVNode)(2,i.Button.Checkbox,{checked:g&e.bitmask,content:e.name,onClick:function(){return n("mode",{mode:e.bitmask})}},e.bitmask)}))}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Color",children:[(0,o.createComponentVNode)(2,i.Box,{inline:!0,width:"64px",color:u[h],content:h}),Object.keys(u).map((function(e){return(0,o.createComponentVNode)(2,i.ColorBox,{ml:1,color:u[e],onClick:function(){return n("color",{paint_color:e})}},e)}))]})]})}),(0,o.createComponentVNode)(2,i.Flex,{m:-.5,children:[(0,o.createComponentVNode)(2,i.Flex.Item,{m:.5,children:(0,o.createComponentVNode)(2,i.Section,{children:[0===p&&(0,o.createComponentVNode)(2,i.Box,{mb:1,children:[1,2,3].map((function(e){return(0,o.createComponentVNode)(2,i.Button.Checkbox,{fluid:!0,checked:e===C,content:"Layer "+e,onClick:function(){return n("piping_layer",{piping_layer:e})}},e)}))}),(0,o.createComponentVNode)(2,i.Box,{width:"108px",children:b.map((function(e){return(0,o.createComponentVNode)(2,i.Button,{title:e.dir_name,selected:e.selected,style:{width:"48px",height:"48px",padding:0},onClick:function(){return n("setdir",{dir:e.dir,flipped:e.flipped})},children:(0,o.createComponentVNode)(2,i.Box,{className:(0,r.classes)(["pipes32x32",e.dir+"-"+e.icon_state]),style:{transform:"scale(1.5) translate(17%, 17%)"}})},e.dir)}))})]})}),(0,o.createComponentVNode)(2,i.Flex.Item,{m:.5,grow:1,children:(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.Tabs,{children:f.map((function(e){return(0,o.createComponentVNode)(2,i.Tabs.Tab,{fluid:!0,icon:l[e.cat_name],label:e.cat_name,children:function(){return e.recipes.map((function(t){return(0,o.createComponentVNode)(2,i.Button.Checkbox,{fluid:!0,ellipsis:!0,checked:t.selected,content:t.pipe_name,title:t.pipe_name,onClick:function(){return n("pipe_type",{pipe_type:t.pipe_index,category:e.cat_name})}},t.pipe_index)}))}},e.cat_name)}))})})})]})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.SatelliteControl=void 0;var o=n(0),r=n(3),a=n(2),i=n(163);t.SatelliteControl=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.satellites||[];return(0,o.createFragment)([c.meteor_shield&&(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,i.LabeledListItem,{label:"Coverage",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:c.meteor_shield_coverage/c.meteor_shield_coverage_max,content:100*c.meteor_shield_coverage/c.meteor_shield_coverage_max+"%",ranges:{good:[1,Infinity],average:[.3,1],bad:[-Infinity,.3]}})})})}),(0,o.createComponentVNode)(2,a.Section,{title:"Satellite Controls",children:(0,o.createComponentVNode)(2,a.Box,{mr:-1,children:l.map((function(e){return(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:e.active,content:"#"+e.id+" "+e.mode,onClick:function(){return n("toggle",{id:e.id})}},e.id)}))})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.ScannerGate=void 0;var o=n(0),r=n(3),a=n(2),i=n(69),c=["Positive","Harmless","Minor","Medium","Harmful","Dangerous","BIOHAZARD"],l=[{name:"Human",value:"human"},{name:"Lizardperson",value:"lizard"},{name:"Flyperson",value:"fly"},{name:"Felinid",value:"felinid"},{name:"Plasmaman",value:"plasma"},{name:"Mothperson",value:"moth"},{name:"Jellyperson",value:"jelly"},{name:"Podperson",value:"pod"},{name:"Golem",value:"golem"},{name:"Zombie",value:"zombie"}],u=[{name:"Starving",value:150},{name:"Obese",value:600}];t.ScannerGate=function(e){var t=e.state,n=(0,r.useBackend)(e),a=n.act,c=n.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,i.InterfaceLockNoticeBox,{locked:c.locked,onLockedStatusChange:function(){return a("toggle_lock")}}),!c.locked&&(0,o.createComponentVNode)(2,s,{state:t})],0)};var d={Off:{title:"Scanner Mode: Off",component:function(){return p}},Wanted:{title:"Scanner Mode: Wanted",component:function(){return m}},Guns:{title:"Scanner Mode: Guns",component:function(){return f}},Mindshield:{title:"Scanner Mode: Mindshield",component:function(){return h}},Disease:{title:"Scanner Mode: Disease",component:function(){return C}},Species:{title:"Scanner Mode: Species",component:function(){return g}},Nutrition:{title:"Scanner Mode: Nutrition",component:function(){return b}},Nanites:{title:"Scanner Mode: Nanites",component:function(){return N}}},s=function(e){var t=e.state,n=(0,r.useBackend)(e),i=n.act,c=n.data.scan_mode,l=d[c]||d.off,u=l.component();return(0,o.createComponentVNode)(2,a.Section,{title:l.title,buttons:"Off"!==c&&(0,o.createComponentVNode)(2,a.Button,{icon:"arrow-left",content:"back",onClick:function(){return i("set_mode",{new_mode:"Off"})}}),children:(0,o.createComponentVNode)(2,u,{state:t})})},p=function(e){var t=(0,r.useBackend)(e).act;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:"Select a scanning mode below."}),(0,o.createComponentVNode)(2,a.Box,{children:[(0,o.createComponentVNode)(2,a.Button,{content:"Wanted",onClick:function(){return t("set_mode",{new_mode:"Wanted"})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Guns",onClick:function(){return t("set_mode",{new_mode:"Guns"})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Mindshield",onClick:function(){return t("set_mode",{new_mode:"Mindshield"})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Disease",onClick:function(){return t("set_mode",{new_mode:"Disease"})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Species",onClick:function(){return t("set_mode",{new_mode:"Species"})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Nutrition",onClick:function(){return t("set_mode",{new_mode:"Nutrition"})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Nanites",onClick:function(){return t("set_mode",{new_mode:"Nanites"})}})]})],4)},m=function(e){var t=e.state,n=(0,r.useBackend)(e).data.reverse;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned ",n?"does not have":"has"," ","any warrants for their arrest."]}),(0,o.createComponentVNode)(2,v,{state:t})],4)},f=function(e){var t=e.state,n=(0,r.useBackend)(e).data.reverse;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned ",n?"does not have":"has"," ","any guns."]}),(0,o.createComponentVNode)(2,v,{state:t})],4)},h=function(e){var t=e.state,n=(0,r.useBackend)(e).data.reverse;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned ",n?"does not have":"has"," ","a mindshield."]}),(0,o.createComponentVNode)(2,v,{state:t})],4)},C=function(e){var t=e.state,n=(0,r.useBackend)(e),i=n.act,l=n.data,u=l.reverse,d=l.disease_threshold;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned ",u?"does not have":"has"," ","a disease equal or worse than ",d,"."]}),(0,o.createComponentVNode)(2,a.Box,{mb:2,children:c.map((function(e){return(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:e===d,content:e,onClick:function(){return i("set_disease_threshold",{new_threshold:e})}},e)}))}),(0,o.createComponentVNode)(2,v,{state:t})],4)},g=function(e){var t=e.state,n=(0,r.useBackend)(e),i=n.act,c=n.data,u=c.reverse,d=c.target_species,s=l.find((function(e){return e.value===d}));return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned is ",u?"not":""," ","of the ",s.name," species.","zombie"===d&&" All zombie types will be detected, including dormant zombies."]}),(0,o.createComponentVNode)(2,a.Box,{mb:2,children:l.map((function(e){return(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:e.value===d,content:e.name,onClick:function(){return i("set_target_species",{new_species:e.value})}},e.value)}))}),(0,o.createComponentVNode)(2,v,{state:t})],4)},b=function(e){var t=e.state,n=(0,r.useBackend)(e),i=n.act,c=n.data,l=c.reverse,d=c.target_nutrition,s=u.find((function(e){return e.value===d}));return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned ",l?"does not have":"has"," ","the ",s.name," nutrition level."]}),(0,o.createComponentVNode)(2,a.Box,{mb:2,children:u.map((function(e){return(0,o.createComponentVNode)(2,a.Button.Checkbox,{checked:e.value===d,content:e.name,onClick:function(){return i("set_target_nutrition",{new_nutrition:e.name})}},e.name)}))}),(0,o.createComponentVNode)(2,v,{state:t})],4)},N=function(e){var t=e.state,n=(0,r.useBackend)(e),i=n.act,c=n.data,l=c.reverse,u=c.nanite_cloud;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Box,{mb:2,children:["Trigger if the person scanned ",l?"does not have":"has"," ","nanite cloud ",u,"."]}),(0,o.createComponentVNode)(2,a.Box,{mb:2,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Cloud ID",children:(0,o.createComponentVNode)(2,a.NumberInput,{value:u,width:"65px",minValue:1,maxValue:100,stepPixelSize:2,onChange:function(e,t){return i("set_nanite_cloud",{new_cloud:t})}})})})}),(0,o.createComponentVNode)(2,v,{state:t})],4)},v=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data.reverse;return(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Scanning Mode",children:(0,o.createComponentVNode)(2,a.Button,{content:i?"Inverted":"Default",icon:i?"random":"long-arrow-alt-right",onClick:function(){return n("toggle_reverse")},color:i?"bad":"good"})})})}},function(e,t,n){"use strict";t.__esModule=!0,t.ShuttleManipulator=void 0;var o=n(0),r=n(24),a=n(3),i=n(2);t.ShuttleManipulator=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.shuttles||[],u=c.templates||{},d=c.selected||{},s=c.existing_shuttle||{};return(0,o.createComponentVNode)(2,i.Tabs,{children:[(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Status",children:function(){return(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.Table,{children:l.map((function(e){return(0,o.createComponentVNode)(2,i.Table.Row,{children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:(0,o.createComponentVNode)(2,i.Button,{content:"JMP",onClick:function(){return n("jump_to",{type:"mobile",id:e.id})}},e.id)}),(0,o.createComponentVNode)(2,i.Table.Cell,{children:(0,o.createComponentVNode)(2,i.Button,{content:"Fly",disabled:!e.can_fly,onClick:function(){return n("fly",{id:e.id})}},e.id)}),(0,o.createComponentVNode)(2,i.Table.Cell,{children:e.name}),(0,o.createComponentVNode)(2,i.Table.Cell,{children:e.id}),(0,o.createComponentVNode)(2,i.Table.Cell,{children:e.status}),(0,o.createComponentVNode)(2,i.Table.Cell,{children:[e.mode,!!e.timer&&(0,o.createFragment)([(0,o.createTextVNode)("("),e.timeleft,(0,o.createTextVNode)(")"),(0,o.createComponentVNode)(2,i.Button,{content:"Fast Travel",disabled:!e.can_fast_travel,onClick:function(){return n("fast_travel",{id:e.id})}},e.id)],0)]})]},e.id)}))})})}},"status"),(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Templates",children:function(){return(0,o.createComponentVNode)(2,i.Section,{children:(0,o.createComponentVNode)(2,i.Tabs,{children:(0,r.map)((function(e,t){var r=e.templates||[];return(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:e.port_id,children:r.map((function(e){var t=e.shuttle_id===d.shuttle_id;return(0,o.createComponentVNode)(2,i.Section,{title:e.name,level:2,buttons:(0,o.createComponentVNode)(2,i.Button,{content:t?"Selected":"Select",selected:t,onClick:function(){return n("select_template",{shuttle_id:e.shuttle_id})}}),children:(!!e.description||!!e.admin_notes)&&(0,o.createComponentVNode)(2,i.LabeledList,{children:[!!e.description&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Description",children:e.description}),!!e.admin_notes&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Admin Notes",children:e.admin_notes})]})},e.shuttle_id)}))},t)}))(u)})})}},"templates"),(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Modification",children:(0,o.createComponentVNode)(2,i.Section,{children:d?(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Section,{level:2,title:d.name,children:(!!d.description||!!d.admin_notes)&&(0,o.createComponentVNode)(2,i.LabeledList,{children:[!!d.description&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Description",children:d.description}),!!d.admin_notes&&(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Admin Notes",children:d.admin_notes})]})}),s?(0,o.createComponentVNode)(2,i.Section,{level:2,title:"Existing Shuttle: "+s.name,children:(0,o.createComponentVNode)(2,i.LabeledList,{children:(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Status",buttons:(0,o.createComponentVNode)(2,i.Button,{content:"Jump To",onClick:function(){return n("jump_to",{type:"mobile",id:s.id})}}),children:[s.status,!!s.timer&&(0,o.createFragment)([(0,o.createTextVNode)("("),s.timeleft,(0,o.createTextVNode)(")")],0)]})})}):(0,o.createComponentVNode)(2,i.Section,{level:2,title:"Existing Shuttle: None"}),(0,o.createComponentVNode)(2,i.Section,{level:2,title:"Status",children:[(0,o.createComponentVNode)(2,i.Button,{content:"Preview",onClick:function(){return n("preview",{shuttle_id:d.shuttle_id})}}),(0,o.createComponentVNode)(2,i.Button,{content:"Load",color:"bad",onClick:function(){return n("load",{shuttle_id:d.shuttle_id})}})]})],0):"No shuttle selected"})},"modification")]})}},function(e,t,n){"use strict";t.__esModule=!0,t.Sleeper=void 0;var o=n(0),r=n(3),a=n(2);t.Sleeper=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.occupied,l=i.open,u=i.occupant,d=void 0===u?[]:u,s=(i.chems||[]).sort((function(e,t){var n=e.name.toLowerCase(),o=t.name.toLowerCase();return no?1:0})),p=(i.synthchems||[]).sort((function(e,t){var n=e.name.toLowerCase(),o=t.name.toLowerCase();return no?1:0}));return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:d.name?d.name:"No Occupant",minHeight:"210px",buttons:!!d.stat&&(0,o.createComponentVNode)(2,a.Box,{inline:!0,bold:!0,color:d.statstate,children:d.stat}),children:!!c&&(0,o.createFragment)([(0,o.createComponentVNode)(2,a.ProgressBar,{value:d.health,minValue:d.minHealth,maxValue:d.maxHealth,ranges:{good:[50,Infinity],average:[0,50],bad:[-Infinity,0]}}),(0,o.createComponentVNode)(2,a.Box,{mt:1}),(0,o.createComponentVNode)(2,a.LabeledList,{children:[[{label:"Brute",type:"bruteLoss"},{label:"Burn",type:"fireLoss"},{label:"Toxin",type:"toxLoss"},{label:"Oxygen",type:"oxyLoss"}].map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:e.label,children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:d[e.type],minValue:0,maxValue:d.maxHealth,color:"bad"})},e.type)})),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Blood",children:[(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.blood_levels/100,color:"bad",children:(0,o.createComponentVNode)(2,a.AnimatedNumber,{value:i.blood_levels})}),i.blood_status]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Cells",color:d.cloneLoss?"bad":"good",children:d.cloneLoss?"Damaged":"Healthy"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Brain",color:d.brainLoss?"bad":"good",children:d.brainLoss?"Abnormal":"Healthy"})]})],4)}),(0,o.createComponentVNode)(2,a.Section,{title:"Chemical Analysis",children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Chemical Contents",children:i.chemical_list.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{color:"good",children:[e.volume," units of ",e.name]},e.id)}))})}),(0,o.createComponentVNode)(2,a.Section,{title:"Inject Chemicals",minHeight:"105px",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:l?"door-open":"door-closed",content:l?"Open":"Closed",onClick:function(){return n("door")}}),children:s.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{icon:"flask",content:e.name,disabled:!(c&&e.allowed),width:"140px",onClick:function(){return n("inject",{chem:e.id})}},e.name)}))}),(0,o.createComponentVNode)(2,a.Section,{title:"Synthesize Chemicals",children:p.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e.name,width:"140px",onClick:function(){return n("synth",{chem:e.id})}},e.name)}))}),(0,o.createComponentVNode)(2,a.Section,{title:"Purge Chemicals",children:s.map((function(e){return(0,o.createComponentVNode)(2,a.Button,{content:e.name,disabled:!e.allowed,width:"140px",onClick:function(){return n("purge",{chem:e.id})}},e.name)}))})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.SlimeBodySwapper=t.BodyEntry=void 0;var o=n(0),r=n(3),a=n(2),i=function(e){var t=e.body,n=e.swapFunc;return(0,o.createComponentVNode)(2,a.Section,{title:(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:t.htmlcolor,children:t.name}),level:2,buttons:(0,o.createComponentVNode)(2,a.Button,{content:{owner:"You Are Here",stranger:"Occupied",available:"Swap"}[t.occupied],selected:"owner"===t.occupied,color:"stranger"===t.occupied&&"bad",onClick:function(){return n()}}),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Status",bold:!0,color:{Dead:"bad",Unconscious:"average",Conscious:"good"}[t.status],children:t.status}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Jelly",children:t.exoticblood}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Location",children:t.area})]})})};t.BodyEntry=i;t.SlimeBodySwapper=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data.bodies,l=void 0===c?[]:c;return(0,o.createComponentVNode)(2,a.Section,{children:l.map((function(e){return(0,o.createComponentVNode)(2,i,{body:e,swapFunc:function(){return n("swap",{ref:e.ref})}},e.name)}))})}},function(e,t,n){"use strict";t.__esModule=!0,t.Signaler=void 0;var o=n(0),r=n(2),a=n(3),i=n(17);t.Signaler=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data,l=c.code,u=c.frequency,d=c.minFrequency,s=c.maxFrequency;return(0,o.createComponentVNode)(2,r.Section,{children:[(0,o.createComponentVNode)(2,r.Grid,{children:[(0,o.createComponentVNode)(2,r.Grid.Column,{size:1.4,color:"label",children:"Frequency:"}),(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.NumberInput,{animate:!0,unit:"kHz",step:.2,stepPixelSize:6,minValue:d/10,maxValue:s/10,value:u/10,format:function(e){return(0,i.toFixed)(e,1)},width:13,onDrag:function(e,t){return n("freq",{freq:t})}})}),(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.Button,{ml:1.3,icon:"sync",content:"Reset",onClick:function(){return n("reset",{reset:"freq"})}})})]}),(0,o.createComponentVNode)(2,r.Grid,{mt:.6,children:[(0,o.createComponentVNode)(2,r.Grid.Column,{size:1.4,color:"label",children:"Code:"}),(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.NumberInput,{animate:!0,step:1,stepPixelSize:6,minValue:1,maxValue:100,value:l,width:13,onDrag:function(e,t){return n("code",{code:t})}})}),(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.Button,{ml:1.3,icon:"sync",content:"Reset",onClick:function(){return n("reset",{reset:"code"})}})})]}),(0,o.createComponentVNode)(2,r.Grid,{mt:.8,children:(0,o.createComponentVNode)(2,r.Grid.Column,{children:(0,o.createComponentVNode)(2,r.Button,{mb:-.1,fluid:!0,icon:"arrow-up",content:"Send Signal",textAlign:"center",onClick:function(){return n("signal")}})})})]})}},function(e,t,n){"use strict";t.__esModule=!0,t.SmartVend=void 0;var o=n(0),r=n(24),a=n(3),i=n(2);t.SmartVend=function(e){var t=(0,a.useBackend)(e),n=t.act,c=t.data;return(0,o.createComponentVNode)(2,i.Section,{title:"Storage",buttons:!!c.isdryer&&(0,o.createComponentVNode)(2,i.Button,{icon:c.drying?"stop":"tint",onClick:function(){return n("Dry")},children:c.drying?"Stop drying":"Dry"}),children:0===c.contents.length&&(0,o.createComponentVNode)(2,i.NoticeBox,{children:["Unfortunately, this ",c.name," is empty."]})||(0,o.createComponentVNode)(2,i.Table,{children:[(0,o.createComponentVNode)(2,i.Table.Row,{header:!0,children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:"Item"}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"center",children:c.verb?c.verb:"Dispense"})]}),(0,r.map)((function(e,t){return(0,o.createComponentVNode)(2,i.Table.Row,{children:[(0,o.createComponentVNode)(2,i.Table.Cell,{children:e.name}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,textAlign:"right",children:e.amount}),(0,o.createComponentVNode)(2,i.Table.Cell,{collapsing:!0,children:[(0,o.createComponentVNode)(2,i.Button,{content:"One",disabled:e.amount<1,onClick:function(){return n("Release",{name:e.name,amount:1})}}),(0,o.createComponentVNode)(2,i.Button,{content:"Many",disabled:e.amount<=1,onClick:function(){return n("Release",{name:e.name})}})]})]},t)}))(c.contents)]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.Smes=void 0;var o=n(0),r=n(3),a=n(2);t.Smes=function(e){var t,n,i=(0,r.useBackend)(e),c=i.act,l=i.data;return t=l.capacityPercent>=100?"good":l.inputting?"average":"bad",n=l.outputting?"good":l.charge>0?"average":"bad",(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Stored Energy",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:.01*l.capacityPercent,ranges:{good:[.5,Infinity],average:[.15,.5],bad:[-Infinity,.15]}})}),(0,o.createComponentVNode)(2,a.Section,{title:"Input",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Charge Mode",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:l.inputAttempt?"sync-alt":"times",selected:l.inputAttempt,onClick:function(){return c("tryinput")},children:l.inputAttempt?"Auto":"Off"}),children:(0,o.createComponentVNode)(2,a.Box,{color:t,children:l.capacityPercent>=100?"Fully Charged":l.inputting?"Charging":"Not Charging"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Target Input",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:l.inputLevel/l.inputLevelMax,content:l.inputLevel_text})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Adjust Input",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"fast-backward",disabled:0===l.inputLevel,onClick:function(){return c("input",{target:"min"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"backward",disabled:0===l.inputLevel,onClick:function(){return c("input",{adjust:-1e4})}}),(0,o.createComponentVNode)(2,a.NumberInput,{value:Math.round(l.inputLevel/1e3),unit:"kW",width:"65px",minValue:0,maxValue:l.inputLevelMax/1e3,onChange:function(e,t){return c("input",{target:1e3*t})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"forward",disabled:l.inputLevel===l.inputLevelMax,onClick:function(){return c("input",{adjust:1e4})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"fast-forward",disabled:l.inputLevel===l.inputLevelMax,onClick:function(){return c("input",{target:"max"})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Available",children:l.inputAvailable})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Output",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Output Mode",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:l.outputAttempt?"power-off":"times",selected:l.outputAttempt,onClick:function(){return c("tryoutput")},children:l.outputAttempt?"On":"Off"}),children:(0,o.createComponentVNode)(2,a.Box,{color:n,children:l.outputting?"Sending":l.charge>0?"Not Sending":"No Charge"})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Target Output",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:l.outputLevel/l.outputLevelMax,content:l.outputLevel_text})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Adjust Output",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"fast-backward",disabled:0===l.outputLevel,onClick:function(){return c("output",{target:"min"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"backward",disabled:0===l.outputLevel,onClick:function(){return c("output",{adjust:-1e4})}}),(0,o.createComponentVNode)(2,a.NumberInput,{value:Math.round(l.outputLevel/1e3),unit:"kW",width:"65px",minValue:0,maxValue:l.outputLevelMax/1e3,onChange:function(e,t){return c("output",{target:1e3*t})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"forward",disabled:l.outputLevel===l.outputLevelMax,onClick:function(){return c("output",{adjust:1e4})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"fast-forward",disabled:l.outputLevel===l.outputLevelMax,onClick:function(){return c("output",{target:"max"})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Outputting",children:l.outputUsed})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.SmokeMachine=void 0;var o=n(0),r=n(3),a=n(2);t.SmokeMachine=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.TankContents,l=(i.isTankLoaded,i.TankCurrentVolume),u=i.TankMaxVolume,d=i.active,s=i.setting,p=(i.screen,i.maxSetting),m=void 0===p?[]:p;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Dispersal Tank",buttons:(0,o.createComponentVNode)(2,a.Button,{icon:d?"power-off":"times",selected:d,content:d?"On":"Off",onClick:function(){return n("power")}}),children:[(0,o.createComponentVNode)(2,a.ProgressBar,{value:l/u,ranges:{bad:[-Infinity,.3]},children:[(0,o.createComponentVNode)(2,a.AnimatedNumber,{initial:0,value:l||0})," / "+u]}),(0,o.createComponentVNode)(2,a.Box,{mt:1,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Range",children:[1,2,3,4,5].map((function(e){return(0,o.createComponentVNode)(2,a.Button,{selected:s===e,icon:"plus",content:3*e,disabled:m0?"good":"bad",children:m})]})}),(0,o.createComponentVNode)(2,a.Grid.Column,{size:1.5,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Power output",children:(0,o.createComponentVNode)(2,a.ProgressBar,{ranges:{good:[.66,Infinity],average:[.33,.66],bad:[-Infinity,.33]},minValue:0,maxValue:1,value:l,content:c+" W"})})})})]})}),(0,o.createComponentVNode)(2,a.Section,{title:"Controls",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Tracking",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"times",content:"Off",selected:0===p,onClick:function(){return n("tracking",{mode:0})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"clock-o",content:"Timed",selected:1===p,onClick:function(){return n("tracking",{mode:1})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"sync",content:"Auto",selected:2===p,disabled:!f,onClick:function(){return n("tracking",{mode:2})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Azimuth",children:[(0===p||1===p)&&(0,o.createComponentVNode)(2,a.NumberInput,{width:"52px",unit:"\xb0",step:1,stepPixelSize:2,minValue:-360,maxValue:720,value:u,onDrag:function(e,t){return n("azimuth",{value:t})}}),1===p&&(0,o.createComponentVNode)(2,a.NumberInput,{width:"80px",unit:"\xb0/m",step:.01,stepPixelSize:1,minValue:-s-.01,maxValue:s+.01,value:d,format:function(e){return(Math.sign(e)>0?"+":"-")+Math.abs(e)},onDrag:function(e,t){return n("azimuth_rate",{value:t})}}),2===p&&(0,o.createComponentVNode)(2,a.Box,{inline:!0,color:"label",mt:"3px",children:[u+" \xb0"," (auto)"]})]})]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.SpaceHeater=void 0;var o=n(0),r=n(3),a=n(2);t.SpaceHeater=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Power",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"eject",content:"Eject Cell",disabled:!i.hasPowercell||!i.open,onClick:function(){return n("eject")}}),(0,o.createComponentVNode)(2,a.Button,{icon:i.on?"power-off":"times",content:i.on?"On":"Off",selected:i.on,disabled:!i.hasPowercell,onClick:function(){return n("power")}})],4),children:(0,o.createComponentVNode)(2,a.LabeledList,{children:(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Cell",color:!i.hasPowercell&&"bad",children:i.hasPowercell&&(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.powerLevel/100,content:i.powerLevel+"%",ranges:{good:[.6,Infinity],average:[.3,.6],bad:[-Infinity,.3]}})||"None"})})}),(0,o.createComponentVNode)(2,a.Section,{title:"Thermostat",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Current Temperature",children:(0,o.createComponentVNode)(2,a.Box,{fontSize:"18px",color:Math.abs(i.targetTemp-i.currentTemp)>50?"bad":Math.abs(i.targetTemp-i.currentTemp)>20?"average":"good",children:[i.currentTemp,"\xb0C"]})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Target Temperature",children:i.open&&(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.targetTemp),width:"65px",unit:"\xb0C",minValue:i.minTemp,maxValue:i.maxTemp,onChange:function(e,t){return n("target",{target:t})}})||i.targetTemp+"\xb0C"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Mode",children:i.open?(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{icon:"thermometer-half",content:"Auto",selected:"auto"===i.mode,onClick:function(){return n("mode",{mode:"auto"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"fire-alt",content:"Heat",selected:"heat"===i.mode,onClick:function(){return n("mode",{mode:"heat"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"fan",content:"Cool",selected:"cool"===i.mode,onClick:function(){return n("mode",{mode:"cool"})}})],4):"Auto"}),(0,o.createComponentVNode)(2,a.LabeledList.Divider)]})})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.SpawnersMenu=void 0;var o=n(0),r=n(3),a=n(2);t.SpawnersMenu=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data.spawners||[];return(0,o.createComponentVNode)(2,a.Section,{children:i.map((function(e){return(0,o.createComponentVNode)(2,a.Section,{title:e.name+" ("+e.amount_left+" left)",level:2,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{content:"Jump",onClick:function(){return n("jump",{name:e.name})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Spawn",onClick:function(){return n("spawn",{name:e.name})}})],4),children:[(0,o.createComponentVNode)(2,a.Box,{bold:!0,mb:1,fontSize:"20px",children:e.short_desc}),(0,o.createComponentVNode)(2,a.Box,{children:e.flavor_text}),!!e.important_info&&(0,o.createComponentVNode)(2,a.Box,{mt:1,bold:!0,color:"bad",fontSize:"26px",children:e.important_info})]},e.name)}))})}},function(e,t,n){"use strict";t.__esModule=!0,t.StationAlertConsole=void 0;var o=n(0),r=n(3),a=n(2);t.StationAlertConsole=function(e){var t=(0,r.useBackend)(e).data.alarms||[],n=t.Fire||[],i=t.Atmosphere||[],c=t.Power||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{title:"Fire Alarms",children:(0,o.createVNode)(1,"ul",null,[0===n.length&&(0,o.createVNode)(1,"li","color-good","Systems Nominal",16),n.map((function(e){return(0,o.createVNode)(1,"li","color-average",e,0,null,e)}))],0)}),(0,o.createComponentVNode)(2,a.Section,{title:"Atmospherics Alarms",children:(0,o.createVNode)(1,"ul",null,[0===i.length&&(0,o.createVNode)(1,"li","color-good","Systems Nominal",16),i.map((function(e){return(0,o.createVNode)(1,"li","color-average",e,0,null,e)}))],0)}),(0,o.createComponentVNode)(2,a.Section,{title:"Power Alarms",children:(0,o.createVNode)(1,"ul",null,[0===c.length&&(0,o.createVNode)(1,"li","color-good","Systems Nominal",16),c.map((function(e){return(0,o.createVNode)(1,"li","color-average",e,0,null,e)}))],0)})],4)}},function(e,t,n){"use strict";t.__esModule=!0,t.SuitStorageUnit=void 0;var o=n(0),r=n(3),a=n(2);t.SuitStorageUnit=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.locked,l=i.open,u=i.safeties,d=i.uv_active,s=i.occupied,p=i.suit,m=i.helmet,f=i.mask,h=i.storage;return(0,o.createFragment)([!(!s||!u)&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"Biological entity detected in suit chamber. Please remove before continuing with operation."}),d&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:"Contents are currently being decontaminated. Please wait."})||(0,o.createComponentVNode)(2,a.Section,{title:"Storage",minHeight:"260px",buttons:(0,o.createFragment)([!l&&(0,o.createComponentVNode)(2,a.Button,{icon:c?"unlock":"lock",content:c?"Unlock":"Lock",onClick:function(){return n("lock")}}),!c&&(0,o.createComponentVNode)(2,a.Button,{icon:l?"sign-out-alt":"sign-in-alt",content:l?"Close":"Open",onClick:function(){return n("door")}})],0),children:c&&(0,o.createComponentVNode)(2,a.Box,{mt:6,bold:!0,textAlign:"center",fontSize:"40px",children:[(0,o.createComponentVNode)(2,a.Box,{children:"Unit Locked"}),(0,o.createComponentVNode)(2,a.Icon,{name:"lock"})]})||l&&(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Helmet",children:(0,o.createComponentVNode)(2,a.Button,{icon:m?"square":"square-o",content:m||"Empty",disabled:!m,onClick:function(){return n("dispense",{item:"helmet"})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Suit",children:(0,o.createComponentVNode)(2,a.Button,{icon:p?"square":"square-o",content:p||"Empty",disabled:!p,onClick:function(){return n("dispense",{item:"suit"})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Mask",children:(0,o.createComponentVNode)(2,a.Button,{icon:f?"square":"square-o",content:f||"Empty",disabled:!f,onClick:function(){return n("dispense",{item:"mask"})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Storage",children:(0,o.createComponentVNode)(2,a.Button,{icon:h?"square":"square-o",content:h||"Empty",disabled:!h,onClick:function(){return n("dispense",{item:"storage"})}})})]})||(0,o.createComponentVNode)(2,a.Button,{fluid:!0,icon:"recycle",content:"Decontaminate",disabled:s&&u,textAlign:"center",onClick:function(){return n("uv")}})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.Tank=void 0;var o=n(0),r=n(3),a=n(2);t.Tank=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure",children:(0,o.createComponentVNode)(2,a.ProgressBar,{value:i.tankPressure/1013,content:i.tankPressure+" kPa",ranges:{good:[.35,Infinity],average:[.15,.35],bad:[-Infinity,.15]}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Pressure Regulator",children:[(0,o.createComponentVNode)(2,a.Button,{icon:"fast-backward",disabled:i.ReleasePressure===i.minReleasePressure,onClick:function(){return n("pressure",{pressure:"min"})}}),(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.releasePressure),width:"65px",unit:"kPa",minValue:i.minReleasePressure,maxValue:i.maxReleasePressure,onChange:function(e,t){return n("pressure",{pressure:t})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"fast-forward",disabled:i.ReleasePressure===i.maxReleasePressure,onClick:function(){return n("pressure",{pressure:"max"})}}),(0,o.createComponentVNode)(2,a.Button,{icon:"undo",content:"",disabled:i.ReleasePressure===i.defaultReleasePressure,onClick:function(){return n("pressure",{pressure:"reset"})}})]})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.TeleLogBrowser=void 0;var o=n(0),r=n(3),a=n(2);t.TeleLogBrowser=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.notice,l=i.network,u=void 0===l?"NULL":l,d=i.servers,s=i.selected,p=void 0===s?null:s,m=i.selected_logs,f=p&&p.status;return(0,o.createFragment)([!!c&&(0,o.createComponentVNode)(2,a.NoticeBox,{children:c}),(0,o.createComponentVNode)(2,a.Section,{title:"Network Control",children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Network",children:(0,o.createComponentVNode)(2,a.Input,{value:u,width:"150px",maxLength:15,onChange:function(e,t){return n("network",{value:t})}})}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Memory",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{content:"Flush Buffer",icon:"minus-circle",disabled:!d.length||!!p,onClick:function(){return n("release")}}),(0,o.createComponentVNode)(2,a.Button,{content:"Probe Network",icon:"sync",disabled:p,onClick:function(){return n("probe")}})],4),children:d?d.length+" currently probed and buffered":"Buffer is empty!"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Selected Server",buttons:(0,o.createComponentVNode)(2,a.Button,{content:"Disconnect",disabled:!p,onClick:function(){return n("mainmenu")}}),children:p?p.name+" ("+p.id+")":"None (None)"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Recorded Traffic",children:p?p.traffic<=1024?p.traffic+" Gigabytes":Math.round(p.traffic/1024)+" Terrabytes":"0 Gigabytes"}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Server Status",color:f?"good":"bad",children:f?"Running":"Server down!"})]})}),(0,o.createComponentVNode)(2,a.Tabs,{children:[(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:"Servers",children:(0,o.createComponentVNode)(2,a.Section,{children:d&&d.length?(0,o.createComponentVNode)(2,a.LabeledList,{children:d.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:""+e.ref,buttons:(0,o.createComponentVNode)(2,a.Button,{content:"Connect",selected:i.selected&&e.ref===i.selected.ref,onClick:function(){return n("viewmachine",{value:e.id})}}),children:e.name+" ("+e.id+")"},e.name)}))}):"404 Servers not found. Have you tried scanning the network?"})},"servers"),(0,o.createComponentVNode)(2,a.Tabs.Tab,{label:"Messages",disabled:!f,children:(0,o.createComponentVNode)(2,a.Section,{title:"Logs",children:f&&m?m.map((function(e){return(0,o.createComponentVNode)(2,a.Section,{level:4,children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Filename",buttons:(0,o.createComponentVNode)(2,a.Button,{content:"Delete",onClick:function(){return n("delete",{value:e.ref})}}),children:e.name}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Data type",children:e.input_type}),e.source&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Source",children:"["+e.source.name+"] (Job: ["+e.source.job+"])"}),e.race&&(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Class",children:e.race}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Contents",children:e.message})]})},e.ref)})):"No server selected!"})},"messages")]})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.Telemonitor=void 0;var o=n(0),r=n(3),a=n(32),i=n(2);t.Telemonitor=function(e){var t=(0,r.useBackend)(e),n=t.act,c=t.data,l=c.notice,u=c.network,d=void 0===u?"NULL":u,s=c.servers,p=c.selected,m=void 0===p?null:p,f=c.selected_servers,h=m&&m.status;return(0,o.createFragment)([!!l&&(0,o.createComponentVNode)(2,i.NoticeBox,{children:l}),(0,o.createComponentVNode)(2,i.Section,{title:"Network Control",children:(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Network",children:(0,o.createComponentVNode)(2,i.Input,{value:d,width:"150px",maxLength:15,onChange:function(e,t){return n("network",{value:t})}})}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Memory",buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,i.Button,{content:"Flush Buffer",icon:"minus-circle",disabled:!s.length||!!m,onClick:function(){return n("release")}}),(0,o.createComponentVNode)(2,i.Button,{content:"Probe Network",icon:"sync",disabled:m,onClick:function(){return n("probe")}})],4),children:m?f?f.length+" currently probed and buffered":"Connected devices is empty!":s?s.length+" currently probed and buffered":"Buffer is empty!"}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Selected Entity",buttons:(0,o.createComponentVNode)(2,i.Button,{content:"Disconnect",icon:"minus-circle",disabled:!m,onClick:function(){return n("mainmenu")}}),children:m?m.name+" ("+m.id+")":"None (None)"})]})}),(0,o.createComponentVNode)(2,i.Tabs,{children:[(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Network Entities",children:(0,o.createComponentVNode)(2,i.Section,{title:"Detected Network Entities",children:s&&s.length?(0,o.createComponentVNode)(2,i.LabeledList,{children:s.map((function(e){return(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:e.ref,buttons:(0,o.createComponentVNode)(2,i.Button,{content:"Connect",selected:m&&e.ref===m.ref,onClick:function(){return n("viewmachine",{value:e.id})}}),children:e.name+" ("+e.id+")"},e.name)}))}):"404 Servers not found. Have you tried scanning the network?"})}),(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:"Entity Status",disabled:!m,children:(0,o.createComponentVNode)(2,i.Section,{title:"Network Entity Status",children:[(0,o.createComponentVNode)(2,i.LabeledList,{children:[(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Status",color:h?"good":"bad",children:h?"Running":"Server down!"}),(0,o.createComponentVNode)(2,i.LabeledList.Item,{label:"Network Traffic",color:h&&m.netspeed0?"good":"bad",children:[s," TC"]}),buttons:(0,o.createFragment)([(0,o.createTextVNode)("Search"),(0,o.createComponentVNode)(2,i.Input,{value:C,onInput:function(t,n){return e.setSearchText(n)},ml:1,mr:1}),(0,o.createComponentVNode)(2,i.Button,{icon:u?"list":"info",content:u?"Compact":"Detailed",onClick:function(){return(0,a.act)(c,"compact_toggle")}}),!!d&&(0,o.createComponentVNode)(2,i.Button,{icon:"lock",content:"Lock",onClick:function(){return(0,a.act)(c,"lock")}})],0),children:C.length>0?(0,o.createVNode)(1,"table","Table",(0,o.createComponentVNode)(2,l,{compact:!0,items:m.flatMap((function(e){return e.items||[]})).filter((function(e){var t=C.toLowerCase();return String(e.name+e.desc).toLowerCase().includes(t)})),hoveredItem:h,onBuyMouseOver:function(t){return e.setHoveredItem(t)},onBuyMouseOut:function(t){return e.setHoveredItem({})},onBuy:function(e){return(0,a.act)(c,"buy",{item:e.name})}}),2):(0,o.createComponentVNode)(2,i.Tabs,{vertical:!0,children:m.map((function(t){var n=t.name,r=t.items;if(null!==r)return(0,o.createComponentVNode)(2,i.Tabs.Tab,{label:n+" ("+r.length+")",children:function(){return(0,o.createComponentVNode)(2,l,{compact:u,items:r,hoveredItem:h,telecrystals:s,onBuyMouseOver:function(t){return e.setHoveredItem(t)},onBuyMouseOut:function(t){return e.setHoveredItem({})},onBuy:function(e){return(0,a.act)(c,"buy",{item:e.name})}})}},n)}))})})},r}(o.Component);t.Uplink=c;var l=function(e){var t=e.items,n=e.hoveredItem,a=e.telecrystals,c=e.compact,l=e.onBuy,u=e.onBuyMouseOver,d=e.onBuyMouseOut,s=n&&n.cost||0;return c?(0,o.createComponentVNode)(2,i.Table,{children:t.map((function(e){var t=n&&n.name!==e.name,c=a-sl.user.cash),content:t?"FREE":c,onClick:function(){return(0,r.act)(u,"vend",{ref:e.ref})}})})]},e.name)}))})})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.Wires=void 0;var o=n(0),r=n(3),a=n(2);t.Wires=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data,c=i.wires||[],l=i.status||[];return(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:c.map((function(e){return(0,o.createComponentVNode)(2,a.LabeledList.Item,{className:"candystripe",label:e.color,labelColor:e.color,color:e.color,buttons:(0,o.createFragment)([(0,o.createComponentVNode)(2,a.Button,{content:e.cut?"Mend":"Cut",onClick:function(){return n("cut",{wire:e.color})}}),(0,o.createComponentVNode)(2,a.Button,{content:"Pulse",onClick:function(){return n("pulse",{wire:e.color})}}),(0,o.createComponentVNode)(2,a.Button,{content:e.attached?"Detach":"Attach",onClick:function(){return n("attach",{wire:e.color})}})],4),children:!!e.wire&&(0,o.createVNode)(1,"i",null,[(0,o.createTextVNode)("("),e.wire,(0,o.createTextVNode)(")")],0)},e.color)}))})}),!!l.length&&(0,o.createComponentVNode)(2,a.Section,{children:l.map((function(e){return(0,o.createComponentVNode)(2,a.Box,{children:e},e)}))})],0)}},function(e,t,n){"use strict";t.__esModule=!0,t.AtmosRelief=void 0;var o=n(0),r=n(3),a=n(2);t.AtmosRelief=function(e){var t=(0,r.useBackend)(e),n=t.act,i=t.data;return(0,o.createComponentVNode)(2,a.Section,{children:(0,o.createComponentVNode)(2,a.LabeledList,{children:[(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Open Pressure",children:[(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.open_pressure),unit:"kPa",width:"75px",minValue:0,maxValue:4500,step:10,onChange:function(e,t){return n("open_pressure",{open_pressure:t})}}),(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"plus",content:"Max",disabled:i.open_pressure===i.max_pressure,onClick:function(){return n("open_pressure",{open_pressure:"max"})}})]}),(0,o.createComponentVNode)(2,a.LabeledList.Item,{label:"Close Pressure",children:[(0,o.createComponentVNode)(2,a.NumberInput,{animated:!0,value:parseFloat(i.close_pressure),unit:"kPa",width:"75px",minValue:0,maxValue:i.open_pressure,step:10,onChange:function(e,t){return n("close_pressure",{close_pressure:t})}}),(0,o.createComponentVNode)(2,a.Button,{ml:1,icon:"plus",content:"Max",disabled:i.close_pressure===i.open_pressure,onClick:function(){return n("close_pressure",{close_pressure:"max"})}})]})]})})}},function(e,t,n){"use strict";t.__esModule=!0,t.createStore=void 0;var o=n(70),r=n(514),a=n(3),i=n(117),c=n(115);(0,n(51).createLogger)("store");t.createStore=function(){var e=(0,o.flow)([function(e,t){return void 0===e&&(e={}),e},a.backendReducer,i.toastReducer,c.hotKeyReducer]),t=[c.hotKeyMiddleware];return(0,r.createStore)(e,r.applyMiddleware.apply(void 0,t))}},function(e,t,n){"use strict";t.__esModule=!0,t.applyMiddleware=t.createStore=void 0;var o=n(70);t.createStore=function r(e,t){if(t)return t(r)(e);var n,o=[],a=function(t){n=e(n,t),o.forEach((function(e){return e()}))};return a({type:"@@INIT"}),{dispatch:a,subscribe:function(e){o.push(e)},getState:function(){return n}}};t.applyMiddleware=function(){for(var e=arguments.length,t=new Array(e),n=0;n1?r-1:0),i=1;i1?t-1:0),o=1;o { - // IE8: Focus method is seemingly fucked. - if (tridentVersion <= 4) { - return; - } - const element = document.getElementById('Layout__content'); - if (element) { - element.focus(); - } -}; diff --git a/tgui-next/packages/tgui/routes.js b/tgui-next/packages/tgui/routes.js deleted file mode 100644 index 87b382dae4..0000000000 --- a/tgui-next/packages/tgui/routes.js +++ /dev/null @@ -1,590 +0,0 @@ -import { Achievements } from './interfaces/Achievements'; -import { AiAirlock } from './interfaces/AiAirlock'; -import { AirAlarm } from './interfaces/AirAlarm'; -import { AirlockElectronics } from './interfaces/AirlockElectronics'; -import { Apc } from './interfaces/Apc'; -import { AtmosAlertConsole } from './interfaces/AtmosAlertConsole'; -import { AtmosControlConsole } from './interfaces/AtmosControlConsole'; -import { AtmosFilter } from './interfaces/AtmosFilter'; -import { AtmosMixer } from './interfaces/AtmosMixer'; -import { AtmosPump } from './interfaces/AtmosPump'; -import { BankMachine } from './interfaces/BankMachine'; -import { BluespaceArtillery } from './interfaces/BluespaceArtillery'; -import { Bepis } from './interfaces/Bepis'; -import { BorgPanel } from './interfaces/BorgPanel'; -import { BrigTimer } from './interfaces/BrigTimer'; -import { Canvas } from './interfaces/Canvas'; -import { Canister } from './interfaces/Canister'; -import { Cargo, CargoExpress } from './interfaces/Cargo'; -import { CellularEmporium } from './interfaces/CellularEmporium'; -import { CentcomPodLauncher } from './interfaces/CentcomPodLauncher'; -import { ChemAcclimator } from './interfaces/ChemAcclimator'; -import { ChemDebugSynthesizer } from './interfaces/ChemDebugSynthesizer'; -import { ChemDispenser } from './interfaces/ChemDispenser'; -import { ChemFilter } from './interfaces/ChemFilter'; -import { ChemHeater } from './interfaces/ChemHeater'; -import { ChemMaster } from './interfaces/ChemMaster'; -import { ChemPress } from './interfaces/ChemPress'; -import { ChemReactionChamber } from './interfaces/ChemReactionChamber'; -import { ChemSplitter } from './interfaces/ChemSplitter'; -import { ChemSynthesizer } from './interfaces/ChemSynthesizer'; -import { CodexGigas } from './interfaces/CodexGigas'; -import { ComputerFabricator } from './interfaces/ComputerFabricator'; -import { Crayon } from './interfaces/Crayon'; -import { CrewConsole } from './interfaces/CrewConsole'; -import { Cryo } from './interfaces/Cryo'; -import { PersonalCrafting } from './interfaces/PersonalCrafting'; -import { DecalPainter } from './interfaces/DecalPainter'; -import { DisposalUnit } from './interfaces/DisposalUnit'; -import { DnaVault } from './interfaces/DnaVault'; -import { EightBallVote } from './interfaces/EightBallVote'; -import { EmergencyShuttleConsole } from './interfaces/EmergencyShuttleConsole'; -import { EngravedMessage } from './interfaces/EngravedMessage'; -import { Gps } from './interfaces/Gps'; -import { GravityGenerator } from './interfaces/GravityGenerator'; -import { GulagTeleporterConsole } from './interfaces/GulagTeleporterConsole'; -import { GulagItemReclaimer } from './interfaces/GulagItemReclaimer'; -import { Holodeck } from './interfaces/Holodeck'; -import { HypnoChair } from './interfaces/HypnoChair'; -import { ImplantChair } from './interfaces/ImplantChair'; -import { Intellicard } from './interfaces/Intellicard'; -import { KeycardAuth } from './interfaces/KeycardAuth'; -import { LaborClaimConsole } from './interfaces/LaborClaimConsole'; -import { LanguageMenu } from './interfaces/LanguageMenu'; -import { LaunchpadConsole, LaunchpadRemote } from './interfaces/Launchpad'; -import { MechBayPowerConsole } from './interfaces/MechBayPowerConsole'; -import { NaniteChamberControl } from './interfaces/NaniteChamberControl'; -import { NaniteCloudControl } from './interfaces/NaniteCloudControl'; -import { NaniteProgramHub } from './interfaces/NaniteProgramHub'; -import { NaniteProgrammer } from './interfaces/NaniteProgrammer'; -import { NaniteRemote } from './interfaces/NaniteRemote'; -import { Mule } from './interfaces/Mule'; -import { NotificationPreferences } from './interfaces/NotificationPreferences'; -import { NtnetRelay } from './interfaces/NtnetRelay'; -import { NtosArcade } from './interfaces/NtosArcade'; -import { NtosConfiguration } from './interfaces/NtosConfiguration'; -import { NtosMain } from './interfaces/NtosMain'; -import { NtosNetChat } from './interfaces/NtosNetChat'; -import { NtosNetDownloader } from './interfaces/NtosNetDownloader'; -import { NtosSupermatterMonitor } from './interfaces/NtosSupermatterMonitor'; -import { NtosWrapper } from './interfaces/NtosWrapper'; -import { NuclearBomb } from './interfaces/NuclearBomb'; -import { OperatingComputer } from './interfaces/OperatingComputer'; -import { OreBox } from './interfaces/OreBox'; -import { OreRedemptionMachine } from './interfaces/OreRedemptionMachine'; -import { Pandemic } from './interfaces/Pandemic'; -import { PortableGenerator } from './interfaces/PortableGenerator'; -import { PortablePump, PortableScrubber } from './interfaces/PortableAtmos'; -import { PowerMonitor } from './interfaces/PowerMonitor'; -import { Radio } from './interfaces/Radio'; -import { RapidPipeDispenser } from './interfaces/RapidPipeDispenser'; -import { SatelliteControl } from './interfaces/SatelliteControl'; -import { ScannerGate } from './interfaces/ScannerGate'; -import { ShuttleManipulator } from './interfaces/ShuttleManipulator'; -import { Sleeper } from './interfaces/Sleeper'; -import { SlimeBodySwapper } from './interfaces/SlimeBodySwapper'; -import { Signaler } from './interfaces/Signaler'; -import { SmartVend } from './interfaces/SmartVend'; -import { Smes } from './interfaces/Smes'; -import { SmokeMachine } from './interfaces/SmokeMachine'; -import { SolarControl } from './interfaces/SolarControl'; -import { SpaceHeater } from './interfaces/SpaceHeater'; -import { SpawnersMenu } from './interfaces/SpawnersMenu'; -import { StationAlertConsole } from './interfaces/StationAlertConsole'; -import { SuitStorageUnit } from './interfaces/SuitStorageUnit'; -import { Tank } from './interfaces/Tank'; -import { TeleLogBrowser } from './interfaces/TelecommsLogBrowser'; -import { Telemonitor } from './interfaces/TelecommsMonitor'; -import { TelePDALog } from './interfaces/TelecommsPDALog'; -import { TeleInteract } from './interfaces/TelecommsInteraction'; -import { TankDispenser } from './interfaces/TankDispenser'; -import { Teleporter } from './interfaces/Teleporter'; -import { ThermoMachine } from './interfaces/ThermoMachine'; -import { TurbineComputer } from './interfaces/TurbineComputer'; -import { Uplink } from './interfaces/Uplink'; -import { VaultController } from './interfaces/VaultController'; -import { Vending } from './interfaces/Vending'; -import { Wires } from './interfaces/Wires'; -import { AtmosRelief } from './interfaces/AtmosRelief'; - -const ROUTES = { - achievements: { - component: () => Achievements, - scrollable: true, - }, - ai_airlock: { - component: () => AiAirlock, - scrollable: false, - }, - airalarm: { - component: () => AirAlarm, - scrollable: true, - }, - airlock_electronics: { - component: () => AirlockElectronics, - scrollable: false, - }, - apc: { - component: () => Apc, - scrollable: false, - }, - atmos_alert: { - component: () => AtmosAlertConsole, - scrollable: true, - }, - atmos_control: { - component: () => AtmosControlConsole, - scrollable: true, - }, - atmos_filter: { - component: () => AtmosFilter, - scrollable: false, - }, - atmos_mixer: { - component: () => AtmosMixer, - scrollable: false, - }, - atmos_pump: { - component: () => AtmosPump, - scrollable: false, - }, - atmos_relief: { - component: () => AtmosRelief, - scrollable: false, - }, - bepis: { - component: () => Bepis, - scrollable: false, - }, - bank_machine: { - component: () => BankMachine, - scrollable: false, - }, - borgopanel: { - component: () => BorgPanel, - scrollable: true, - }, - brig_timer: { - component: () => BrigTimer, - scrollable: false, - }, - bsa: { - component: () => BluespaceArtillery, - scrollable: false, - }, - canvas: { - component: () => Canvas, - scrollable: false, - }, - canister: { - component: () => Canister, - scrollable: false, - }, - cargo: { - component: () => Cargo, - scrollable: true, - }, - cargo_express: { - component: () => CargoExpress, - scrollable: true, - }, - cellular_emporium: { - component: () => CellularEmporium, - scrollable: true, - }, - centcom_podlauncher: { - component: () => CentcomPodLauncher, - scrollable: false, - }, - acclimator: { - component: () => ChemAcclimator, - scrollable: false, - }, - chem_dispenser: { - component: () => ChemDispenser, - scrollable: true, - }, - chemical_filter: { - component: () => ChemFilter, - scrollable: true, - }, - chem_heater: { - component: () => ChemHeater, - scrollable: true, - }, - chem_master: { - component: () => ChemMaster, - scrollable: true, - }, - chem_press: { - component: () => ChemPress, - scrollable: false, - }, - reaction_chamber: { - component: () => ChemReactionChamber, - scrollable: true, - }, - chem_splitter: { - component: () => ChemSplitter, - scrollable: false, - }, - chem_synthesizer: { - component: () => ChemDebugSynthesizer, - scrollable: false, - }, - synthesizer: { - component: () => ChemSynthesizer, - scrollable: false, - }, - codex_gigas: { - component: () => CodexGigas, - scrollable: false, - }, - computer_fabricator: { - component: () => ComputerFabricator, - scrollable: false, - }, - crayon: { - component: () => Crayon, - scrollable: true, - }, - crew: { - component: () => CrewConsole, - scrollable: true, - }, - cryo: { - component: () => Cryo, - scrollable: false, - }, - decal_painter: { - component: () => DecalPainter, - scrollable: false, - }, - disposal_unit: { - component: () => DisposalUnit, - scrollable: false, - }, - dna_vault: { - component: () => DnaVault, - scrollable: false, - }, - eightball: { - component: () => EightBallVote, - scrollable: false, - }, - emergency_shuttle_console: { - component: () => EmergencyShuttleConsole, - scrollable: false, - }, - engraved_message: { - component: () => EngravedMessage, - scrollable: false, - }, - gps: { - component: () => Gps, - scrollable: true, - }, - gravity_generator: { - component: () => GravityGenerator, - scrollable: false, - }, - gulag_console: { - component: () => GulagTeleporterConsole, - scrollable: false, - }, - gulag_item_reclaimer: { - component: () => GulagItemReclaimer, - scrollable: true, - }, - holodeck: { - component: () => Holodeck, - scrollable: true, - }, - hypnochair: { - component: () => HypnoChair, - scrollable: false, - }, - implantchair: { - component: () => ImplantChair, - scrollable: false, - }, - intellicard: { - component: () => Intellicard, - scrollable: true, - }, - keycard_auth: { - component: () => KeycardAuth, - scrollable: false, - }, - labor_claim_console: { - component: () => LaborClaimConsole, - scrollable: false, - }, - language_menu: { - component: () => LanguageMenu, - scrollable: true, - }, - launchpad_console: { - component: () => LaunchpadConsole, - scrollable: true, - }, - launchpad_remote: { - component: () => LaunchpadRemote, - scrollable: false, - theme: 'syndicate', - }, - mech_bay_power_console: { - component: () => MechBayPowerConsole, - scrollable: false, - }, - nanite_chamber_control: { - component: () => NaniteChamberControl, - scrollable: true, - }, - nanite_cloud_control: { - component: () => NaniteCloudControl, - scrollable: true, - }, - nanite_program_hub: { - component: () => NaniteProgramHub, - scrollable: true, - }, - nanite_programmer: { - component: () => NaniteProgrammer, - scrollable: true, - }, - nanite_remote: { - component: () => NaniteRemote, - scrollable: true, - }, - mulebot: { - component: () => Mule, - scrollable: false, - }, - notificationpanel: { - component: () => NotificationPreferences, - scrollable: true, - }, - ntnet_relay: { - component: () => NtnetRelay, - scrollable: false, - }, - ntos_arcade: { - component: () => NtosArcade, - wrapper: () => NtosWrapper, - scrollable: false, - theme: 'ntos', - }, - ntos_configuration: { - component: () => NtosConfiguration, - wrapper: () => NtosWrapper, - scrollable: true, - theme: 'ntos', - }, - ntos_main: { - component: () => NtosMain, - wrapper: () => NtosWrapper, - scrollable: true, - theme: 'ntos', - }, - ntos_net_chat: { - component: () => NtosNetChat, - wrapper: () => NtosWrapper, - scrollable: false, - theme: 'ntos', - }, - ntos_net_downloader: { - component: () => NtosNetDownloader, - wrapper: () => NtosWrapper, - scrollable: true, - theme: 'ntos', - }, - ntos_power_monitor: { - component: () => PowerMonitor, - wrapper: () => NtosWrapper, - scrollable: true, - theme: 'ntos', - }, - ntos_supermatter_monitor: { - component: () => NtosSupermatterMonitor, - wrapper: () => NtosWrapper, - scrollable: true, - theme: 'ntos', - }, - nuclear_bomb: { - component: () => NuclearBomb, - scrollable: false, - theme: 'retro', - }, - ore_redemption_machine: { - component: () => OreRedemptionMachine, - scrollable: true, - }, - ore_box: { - component: () => OreBox, - scrollable: true, - }, - operating_computer: { - component: () => OperatingComputer, - scrollable: true, - }, - pandemic: { - component: () => Pandemic, - scrollable: true, - }, - portable_generator: { - component: () => PortableGenerator, - scrollable: false, - }, - personal_crafting: { - component: () => PersonalCrafting, - scrollable: true, - }, - portable_pump: { - component: () => PortablePump, - scrollable: false, - }, - portable_scrubber: { - component: () => PortableScrubber, - scrollable: false, - }, - power_monitor: { - component: () => PowerMonitor, - scrollable: true, - }, - radio: { - component: () => Radio, - scrollable: false, - }, - rpd: { - component: () => RapidPipeDispenser, - scrollable: true, - }, - sat_control: { - component: () => SatelliteControl, - scrollable: false, - }, - scanner_gate: { - component: () => ScannerGate, - scrollable: true, - }, - shuttle_manipulator: { - component: () => ShuttleManipulator, - scrollable: true, - }, - sleeper: { - component: () => Sleeper, - scrollable: false, - }, - slime_swap_body: { - component: () => SlimeBodySwapper, - scrollable: true, - }, - signaler: { - component: () => Signaler, - scrollable: false, - }, - smartvend: { - component: () => SmartVend, - scrollable: true, - }, - smes: { - component: () => Smes, - scrollable: false, - }, - smoke_machine: { - component: () => SmokeMachine, - scrollable: false, - }, - solar_control: { - component: () => SolarControl, - scrollable: false, - }, - space_heater: { - component: () => SpaceHeater, - scrollable: false, - }, - spawners_menu: { - component: () => SpawnersMenu, - scrollable: true, - }, - station_alert: { - component: () => StationAlertConsole, - scrollable: true, - }, - suit_storage_unit: { - component: () => SuitStorageUnit, - scrollable: false, - }, - tcommsserver: { - component: () => TeleLogBrowser, - scrollable: true, - theme: 'ntos', - }, - telemonitor: { - component: () => Telemonitor, - scrollable: true, - theme: 'ntos', - }, - telepdalog: { - component: () => TelePDALog, - scrollable: true, - theme: 'ntos', - }, - teleinteract: { - component: () => TeleInteract, - scrollable: true, - }, - tanks: { - component: () => Tank, - scrollable: false, - }, - tank_dispenser: { - component: () => TankDispenser, - scrollable: false, - }, - teleporter: { - component: () => Teleporter, - scrollable: false, - }, - thermomachine: { - component: () => ThermoMachine, - scrollable: false, - }, - turbine_computer: { - component: () => TurbineComputer, - scrollable: false, - }, - uplink: { - component: () => Uplink, - scrollable: true, - theme: 'syndicate', - }, - vault_controller: { - component: () => VaultController, - scrollable: false, - }, - vending: { - component: () => Vending, - scrollable: true, - }, - wires: { - component: () => Wires, - scrollable: false, - }, -}; - -export const getRoute = state => { - if (process.env.NODE_ENV !== 'production') { - // Show a kitchen sink - if (state.showKitchenSink) { - const { KitchenSink } = require('./interfaces/KitchenSink'); - return { - component: () => KitchenSink, - scrollable: true, - }; - } - } - // Refer to the routing table - return ROUTES[state.config && state.config.interface]; -}; diff --git a/tgui-next/packages/tgui/store.js b/tgui-next/packages/tgui/store.js deleted file mode 100644 index 5d4afbf82b..0000000000 --- a/tgui-next/packages/tgui/store.js +++ /dev/null @@ -1,30 +0,0 @@ -import { flow } from 'common/fp'; -import { applyMiddleware, createStore as createReduxStore } from 'common/redux'; -import { backendReducer } from './backend'; -import { toastReducer } from './components/Toast'; -import { hotKeyMiddleware, hotKeyReducer } from './hotkeys'; -import { createLogger } from './logging'; - -const logger = createLogger('store'); - -// const loggingMiddleware = store => next => action => { -// const { type, payload } = action; -// logger.log('dispatching', type); -// next(action); -// }; - -export const createStore = () => { - const reducer = flow([ - // State initializer - (state = {}, action) => state, - // Global state reducers - backendReducer, - toastReducer, - hotKeyReducer, - ]); - const middleware = [ - // loggingMiddleware, - hotKeyMiddleware, - ]; - return createReduxStore(reducer, applyMiddleware(...middleware)); -}; diff --git a/tgui-next/packages/tgui/styles/atomic/candystripe.scss b/tgui-next/packages/tgui/styles/atomic/candystripe.scss deleted file mode 100644 index 66ae30f512..0000000000 --- a/tgui-next/packages/tgui/styles/atomic/candystripe.scss +++ /dev/null @@ -1,3 +0,0 @@ -.candystripe:nth-child(odd) { - background-color: rgba(0, 0, 0, 0.25); -} diff --git a/tgui-next/packages/tgui/styles/components/BlockQuote.scss b/tgui-next/packages/tgui/styles/components/BlockQuote.scss deleted file mode 100644 index 9ab1de08e2..0000000000 --- a/tgui-next/packages/tgui/styles/components/BlockQuote.scss +++ /dev/null @@ -1,10 +0,0 @@ -@use '../base.scss'; -@use '../colors.scss'; - -$color-default: colors.fg(colors.$label) !default; - -.BlockQuote { - color: $color-default; - border-left: 2px solid $color-default; - padding-left: 6px; -} diff --git a/tgui-next/packages/tgui/styles/components/ColorBox.scss b/tgui-next/packages/tgui/styles/components/ColorBox.scss deleted file mode 100644 index afe0069b04..0000000000 --- a/tgui-next/packages/tgui/styles/components/ColorBox.scss +++ /dev/null @@ -1,7 +0,0 @@ -.ColorBox { - display: inline-block; - width: 12px; - height: 12px; - line-height: 12px; - text-align: center; -} diff --git a/tgui-next/packages/tgui/styles/components/Dropdown.scss b/tgui-next/packages/tgui/styles/components/Dropdown.scss deleted file mode 100644 index a76e15a1bb..0000000000 --- a/tgui-next/packages/tgui/styles/components/Dropdown.scss +++ /dev/null @@ -1,49 +0,0 @@ -.Dropdown { - position: relative; -} - -.Dropdown__control { - position: relative; - display: inline-block; - font-family: Verdana, sans-serif; - font-size: 12px; - width: 100px; - line-height: 17px; - user-select: none; -} - -.Dropdown__arrow-button { - float: right; - padding-left: 6px; - border-left: 1px solid #000; - border-left: 1px solid rgba(0, 0, 0, 0.25); -} - -.Dropdown__menu { - position: absolute; - overflow-y: auto; - z-index: 5; - width: 100px; - max-height: 200px; - overflow-y: scroll; - border-radius: 0 0 2px 2px; - background-color: #000; - background-color: rgba(0, 0, 0, 0.75); -} - -.Dropdown__menuentry { - padding: 2px 4px; - font-family: Verdana, sans-serif; - font-size: 12px; - line-height: 17px; - transition: background-color 100ms; - &:hover { - background-color: #444; - transition: background-color 0ms; - } -} - -.Dropdown__over { - top: auto; - bottom: 100% -} diff --git a/tgui-next/packages/tgui/styles/components/Flex.scss b/tgui-next/packages/tgui/styles/components/Flex.scss deleted file mode 100644 index 49156bd9c6..0000000000 --- a/tgui-next/packages/tgui/styles/components/Flex.scss +++ /dev/null @@ -1,15 +0,0 @@ -.Flex { - display: -ms-flexbox; - display: flex; -} - -@for $i from 1 through 2 { - .Flex--spacing--#{$i} { - margin: -3px * $i; - margin-bottom: 3px * $i; - - & > .Flex__item { - margin: 3px * $i; - } - } -} diff --git a/tgui-next/packages/tgui/styles/components/Layout.scss b/tgui-next/packages/tgui/styles/components/Layout.scss deleted file mode 100644 index adae2534e0..0000000000 --- a/tgui-next/packages/tgui/styles/components/Layout.scss +++ /dev/null @@ -1,114 +0,0 @@ -@use 'sass:color'; -@use '../base.scss'; -@use '../functions.scss' as *; - -.Layout { - position: fixed; - top: 0; - bottom: 0; - left: 0; - right: 0; - color: base.$color-fg; - background-color: base.$color-bg; - background-image: linear-gradient(to bottom, - base.$color-bg-start 0%, - base.$color-bg-end 100%); -} - -.Layout__titleBar { - position: fixed; - z-index: 1; - top: 0; - left: 0; - width: 100%; - height: 32px; -} - -.Layout__content { - position: fixed; - top: 32px; - bottom: 0; - left: 0; - right: 0; - overflow-x: hidden; - overflow-y: hidden; - margin-bottom: -6px; - - // Fancy scrollbar - scrollbar-base-color: color.scale( - base.$color-bg, - $lightness: -25%); - scrollbar-face-color: color.scale( - base.$color-bg, - $lightness: 10%); - scrollbar-3dlight-color: color.scale( - base.$color-bg, - $lightness: 0%); - scrollbar-highlight-color: color.scale( - base.$color-bg, - $lightness: 0%); - scrollbar-track-color: color.scale( - base.$color-bg, - $lightness: -25%); - scrollbar-arrow-color: color.scale( - base.$color-bg, - $lightness: 50%); - scrollbar-shadow-color: color.scale( - base.$color-bg, - $lightness: 10%); -} - -.Layout__content--scrollable { - overflow-y: scroll; - margin-bottom: 0; -} - -.Layout__dimmer { - position: fixed; - top: 32px; - bottom: 0; - left: 0; - right: 0; - background-color: rgba(lighten(base.$color-bg, 30%), 0.25); - pointer-events: none; -} - -.Layout__toast { - position: fixed; - bottom: 0; - left: 0; - right: 0; - font-size: 12px; - height: 40px; - line-height: 39px; - padding: 0 12px; - background-color: color.scale(base.$color-bg, $lightness: -50%); - color: rgba(255, 255, 255, 0.8); -} - -.Layout__resizeHandle__se { - position: fixed; - bottom: 0; - right: 0; - width: 20px; - height: 20px; - cursor: se-resize; -} - -.Layout__resizeHandle__s { - position: fixed; - bottom: 0; - left: 0; - right: 0; - height: 6px; - cursor: s-resize; -} - -.Layout__resizeHandle__e { - position: fixed; - top: 0; - bottom: 0; - right: 0; - width: 3px; - cursor: e-resize; -} diff --git a/tgui-next/packages/tgui/styles/components/NoticeBox.scss b/tgui-next/packages/tgui/styles/components/NoticeBox.scss deleted file mode 100644 index 048904ed75..0000000000 --- a/tgui-next/packages/tgui/styles/components/NoticeBox.scss +++ /dev/null @@ -1,28 +0,0 @@ -@use '../functions.scss' as *; - -// NoticeBox -$color-first: #bb9b68 !default; -$color-second: #b1905d !default; -$color-border: #272727 !default; - -.NoticeBox { - // Adapt text color to background luminance to ensure high contast - $luminance: luminance($color-first); - $text-color: if($luminance > 0.35, - rgba(0, 0, 0, 1), - rgba(255, 255, 255, 1)); - - padding: 4px 6px; - margin-bottom: 6px; - box-shadow: none; - font-weight: bold; - font-style: italic; - color: $text-color; - background-color: $color-first; - background-image: repeating-linear-gradient( - -45deg, - $color-first, - $color-first 10px, - $color-second 10px, - $color-second 20px); -} diff --git a/tgui-next/packages/tgui/styles/components/NtosHeader.scss b/tgui-next/packages/tgui/styles/components/NtosHeader.scss deleted file mode 100644 index 15db60c66a..0000000000 --- a/tgui-next/packages/tgui/styles/components/NtosHeader.scss +++ /dev/null @@ -1,15 +0,0 @@ -.NtosHeader__left { - position: absolute; - left: 12px; -} - -.NtosHeader__right { - position: absolute; - right: 12px; -} - -.NtosHeader__icon { - margin-top: -9px; - margin-bottom: -6px; - vertical-align: middle; -} diff --git a/tgui-next/packages/tgui/styles/components/NtosWrapper.scss b/tgui-next/packages/tgui/styles/components/NtosWrapper.scss deleted file mode 100644 index 590d55a54b..0000000000 --- a/tgui-next/packages/tgui/styles/components/NtosWrapper.scss +++ /dev/null @@ -1,19 +0,0 @@ -.NtosWrapper__header { - position: absolute; - top: 32px; - left: 0; - right: 0; - height: 28px; - line-height: 27px; - background-color: rgba(0, 0, 0, 0.5); - font-family: Consolas, monospace; - font-size: 14px; - user-select: none; - -ms-user-select: none; -} - -.NtosWrapper__content .Layout__content { - margin-top: 28px; - font-family: Consolas, monospace; - font-size: 14px; -} diff --git a/tgui-next/packages/tgui/styles/components/Tabs.scss b/tgui-next/packages/tgui/styles/components/Tabs.scss deleted file mode 100644 index d195b5ac58..0000000000 --- a/tgui-next/packages/tgui/styles/components/Tabs.scss +++ /dev/null @@ -1,39 +0,0 @@ -.Tabs__content { - padding-top: 6px; - border-top: 2px solid rgba(255, 255, 255, 0.1); -} - -.Tabs--vertical { - display: table-row; -} - -// NOTE: These selectors have to be specific in order to stop cascading -// from influencing nested tabs. -.Tabs--vertical > .Tabs__content { - display: table-cell; - width: 100%; - padding-top: 0; - padding-left: 9px; - border-top: 0; -} - -.Tabs--vertical > .Tabs__tabBox { - display: table-cell; - // padding-right: 2px; - border-right: 2px solid rgba(255, 255, 255, 0.1); - // Disable baseline alignment when doing vertical tabs - vertical-align: top; -} - -.Tabs--vertical > .Tabs__tabBox > .Tabs__tab { - // Force display block because Button theme overrides it via cascading. - display: block !important; - margin-right: 0; - margin-bottom: 0; - padding: 1px 9px 0px 6px; - border-bottom: 2px solid rgba(255, 255, 255, 0.1); - - &:last-child { - border-bottom: 0; - } -} diff --git a/tgui/.babelrc b/tgui/.babelrc deleted file mode 100644 index 3c078e9f99..0000000000 --- a/tgui/.babelrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "presets": [ - "es2015" - ] -} diff --git a/tgui-next/.editorconfig b/tgui/.editorconfig similarity index 100% rename from tgui-next/.editorconfig rename to tgui/.editorconfig diff --git a/tgui-next/.eslintignore b/tgui/.eslintignore similarity index 100% rename from tgui-next/.eslintignore rename to tgui/.eslintignore diff --git a/tgui-next/.eslintrc-harder.yml b/tgui/.eslintrc-harder.yml similarity index 100% rename from tgui-next/.eslintrc-harder.yml rename to tgui/.eslintrc-harder.yml diff --git a/tgui-next/.eslintrc.yml b/tgui/.eslintrc.yml similarity index 98% rename from tgui-next/.eslintrc.yml rename to tgui/.eslintrc.yml index 4bff333295..9fd4db9fd2 100644 --- a/tgui-next/.eslintrc.yml +++ b/tgui/.eslintrc.yml @@ -8,6 +8,8 @@ env: es6: true browser: true node: true +globals: + Byond: readonly plugins: - react settings: @@ -305,7 +307,13 @@ rules: ## Enforce or disallow capitalization of the first letter of a comment # capitalized-comments: error ## Require or disallow trailing commas - comma-dangle: [error, always-multiline] + comma-dangle: [error, { + arrays: always-multiline, + objects: always-multiline, + imports: always-multiline, + exports: always-multiline, + functions: only-multiline, ## Optional on functions + }] ## Enforce consistent spacing before and after commas comma-spacing: [error, { before: false, after: true }] ## Enforce consistent comma style @@ -382,7 +390,7 @@ rules: ## Enforce a particular style for multiline comments # multiline-comment-style: error ## Enforce newlines between operands of ternary expressions - multiline-ternary: [error, always-multiline] + # multiline-ternary: [error, always-multiline] ## Require constructor names to begin with a capital letter # new-cap: error ## Enforce or disallow parentheses when invoking a constructor with no @@ -625,7 +633,7 @@ rules: ## Prevent invalid characters from appearing in markup react/no-unescaped-entities: error ## Prevent usage of unknown DOM property (fixable) - react/no-unknown-property: error + # react/no-unknown-property: error ## Prevent usage of unsafe lifecycle methods react/no-unsafe: error ## Prevent definitions of unused prop types @@ -705,7 +713,7 @@ rules: ## Validate JSX has key prop when in array or iterator react/jsx-key: error ## Validate JSX maximum depth - react/jsx-max-depth: [error, { max: 6 }] ## Generous + react/jsx-max-depth: [error, { max: 10 }] ## Generous ## Limit maximum of props on a single line in JSX (fixable) # react/jsx-max-props-per-line: error ## Prevent usage of .bind() and arrow functions in JSX props diff --git a/tgui/.gitattributes b/tgui/.gitattributes index 6da3dcfc2d..9382416e69 100644 --- a/tgui/.gitattributes +++ b/tgui/.gitattributes @@ -1 +1,19 @@ -assets/* binary +* text=auto + +## Enforce text mode and LF line breaks +*.js text eol=lf +*.jsx text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.css text eol=lf +*.scss text eol=lf +*.html text eol=lf +*.json text eol=lf +*.yml text eol=lf +*.md text eol=lf +*.bat text eol=lf +yarn.lock text eol=lf +bin/tgui text eol=lf + +## Treat bundles as binary and ignore them during conflicts +*.bundle.* binary merge=tgui-merge-bundle diff --git a/tgui/.gitignore b/tgui/.gitignore index 71b051e887..416ca3768d 100644 --- a/tgui/.gitignore +++ b/tgui/.gitignore @@ -1,2 +1,7 @@ -npm-debug.log -node_modules/ +node_modules +*.log +package-lock.json + +/packages/tgui/public/.tmp/**/* +/packages/tgui/public/**/*.hot-update.* +/packages/tgui/public/**/*.map diff --git a/tgui/LICENSE.md b/tgui/LICENSE.md deleted file mode 100644 index 0ddc16bf39..0000000000 --- a/tgui/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -MIT license - -Copyright (c) 2016 Bjorn Neergaard (neersighted), tgui contributors - -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/tgui/README.md b/tgui/README.md index e3ed2a20ee..9eab0196de 100644 --- a/tgui/README.md +++ b/tgui/README.md @@ -1,139 +1,191 @@ - - -- [tgui](#tgui) - - [Concepts](#concepts) - - [Using It](#using-it) - - [Copypasta](#copypasta) - - - # tgui -tgui is the user interface library of /tg/station. It is rendered clientside, based on JSON data sent from the server. Clicks are processed on the server, in a similar method to native BYOND `Topic()`. -Basic tgui consists of defining a few procs. In these procs you will handle a request to open or update a UI (typically by updating a UI if it exists or setting up and opening it if it does not), a request for data, in which you build a list to be passed as JSON to the UI, and an action handler, which handles any user input. In addition, you will write a HTML template file which renders your data and provides actionable inputs. +## Introduction -tgui is very different from most UIs you will encounter in BYOND programming, and is heavily reliant of Javascript and web technologies as opposed to DM. However, if you are familiar with NanoUI (a library which can be found on almost every other SS13 codebase), tgui should be fairly easy to pick up. +tgui is a robust user interface framework of /tg/station. -tgui is a fork of NanoUI. The server-side code (DM) is similar and derived from NanoUI, while the clientside is a wholly new project with no code in common. +tgui is very different from most UIs you will encounter in BYOND programming. +It is heavily reliant on Javascript and web technologies as opposed to DM. +If you are familiar with NanoUI (a library which can be found on almost +every other SS13 codebase), tgui should be fairly easy to pick up. -## Concepts -tgui is loosely based a MVVM architecture. MVVM stands for model, view, view model. -- A model is the object that a UI represents. This is the atom a UI corresponds to in the game world in most cases, and is known as the `src_object` in tgui. -- The view model is how data is represented in terms of the view. In tgui, this is the `ui_data` proc which munges whatever complex data your `src_object` has into a list. -- The view is how the data is rendered. This is the template, a HTML (plus mustaches and other goodies) file which is compiled into the tgui blob that the browser executes. +## Learn tgui -Not included in the MVVM model are other important concepts: -- The action/topic handler, `ui_act`, is what recieves input from the user and acts on it. -- The request/update proc, `ui_interact` is where you open your UI and set options like title, size, autoupdate, theme, and more. -- Finally, `ui_state`s (set in `ui_interact`) dictate under what conditions a UI may be interacted with. This may be the standard checks that check if you are in range and conscious, or more. +People come to tgui from different backgrounds and with different +learning styles. Whether you prefer a more theoretical or a practical +approach, we hope you’ll find this section helpful. -States are easy to write and extend, and what make tgui interactions so powerful. Because states can over overridden from other procs, you can build powerful interactions for embedded objects or remote access. +### Practical Tutorial -## Using It -All these examples and abstracts sound great, you might say. But you also might say, "How do I use it?" +If you are completely new to frontend and prefer to **learn by doing**, +start with our [practical tutorial](docs/tutorial-and-examples.md). -Examples can be as simple or as complex as you would like. Let's start with a very basic hello world. +### Guides -```DM -/obj/machinery/my_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "my_machine", name, 300, 300, master_ui, state) - ui.open() +This project uses **Inferno** - a very fast UI rendering engine with a similar +API to React. Take your time to read these guides: + +- [React guide](https://reactjs.org/docs/hello-world.html) +- [Inferno documentation](https://infernojs.org/docs/guides/components) - +highlights differences with React. + +If you were already familiar with an older, Ractive-based tgui, and want +to translate concepts between old and new tgui, read this +[interface conversion guide](docs/converting-old-tgui-interfaces.md). + +## Pre-requisites + +You will need these programs to start developing in tgui: + +- [Node v12.13+](https://nodejs.org/en/download/) +- [Yarn v1.19+](https://yarnpkg.com/en/docs/install) +- [MSys2](https://www.msys2.org/) (optional) + +> MSys2 closely replicates a unix-like environment which is necessary for +> the `bin/tgui` script to run. It comes with a robust "mintty" terminal +> emulator which is better than any standard Windows shell, it supports +> "git" out of the box (almost like Git for Windows, but better), has +> a "pacman" package manager, and you can install a text editor like "vim" +> for a full boomer experience. + +## Usage + +**For MSys2, Git Bash, WSL, Linux or macOS users:** + +First and foremost, change your directory to `tgui`. + +Run `bin/tgui --install-git-hooks` (optional) to install merge drivers +which will assist you in conflict resolution when rebasing your branches. + +Run one of the following: + +- `bin/tgui` - build the project in production mode. +- `bin/tgui --dev` - launch a development server. + - tgui development server provides you with incremental compilation, + hot module replacement and logging facilities in all running instances + of tgui. In short, this means that you will instantly see changes in the + game as you code it. Very useful, highly recommended. + - In order to use it, you should start the game server first, connect to it + and wait until the world has been properly loaded and you are no longer + in the lobby. Start tgui dev server, and once it has finished building, + press F5 on any tgui window. You'll know that it's hooked correctly if + you see a green bug icon in titlebar and data gets dumped to the console. +- `bin/tgui --dev --reload` - reload byond cache once. +- `bin/tgui --dev --debug` - run server with debug logging enabled. +- `bin/tgui --dev --no-hot` - disable hot module replacement (helps when +doing development on IE8). +- `bin/tgui --lint` - show problems with the code. +- `bin/tgui --lint --fix` - auto-fix problems with the code. +- `bin/tgui --analyze` - run a bundle analyzer. +- `bin/tgui --clean` - clean up project repo. +- `bin/tgui [webpack options]` - build the project with custom webpack +options. + +**For everyone else:** + +If you haven't opened the console already, you can do that by holding +Shift and right clicking on the `tgui` folder, then pressing +either `Open command window here` or `Open PowerShell window here`. + +Run `yarn install` to install npm dependencies, then one of the following: + +- `yarn run build` - build the project in production mode. +- `yarn run watch` - launch a development server. +- `yarn run lint` - show problems with the code. +- `yarn run lint --fix` - auto-fix problems with the code. +- `yarn run analyze` - run a bundle analyzer. + +We also got some batch files in store, for those who don't like fiddling +with the console: + +- `bin/tgui-build.bat` - build the project in production mode. +- `bin/tgui-dev-server.bat` - launch a development server. + +> Remember to always run a full build before submitting a PR. It creates +> a compressed javascript bundle which is then referenced from DM code. +> We prefer to keep it version controlled, so that people could build the +> game just by using Dream Maker. + +## Troubleshooting + +**Development server doesn't find my BYOND cache!** + +This happens if your Documents folder in Windows has a custom location, for +example in `E:\Libraries\Documents`. Development server has no knowledge +of these non-standard locations, therefore you have to run the dev server +with an additional environmental variable, with a full path to BYOND cache. + +``` +export BYOND_CACHE="E:/Libraries/Documents/BYOND/cache" +bin/tgui --dev ``` -This is the proc that defines our interface. There's a bit going on here, so let's break it down. First, we override the ui_interact proc on our object. This will be called by `interact` for you, which is in turn called by `attack_hand` (or `attack_self` for items). `ui_interact` is also called to update a UI (hence the `try_update_ui`), so we accept an existing UI to update. The `state` is a default argument so that a caller can overload it with named arguments (`ui_interact(state = overloaded_state)`) if needed. +Note that in Windows, you have to go through Advanced System Settings, +System Properties and then open Environment Variables window to do the +same thing. You may need to reboot after this. -Inside the `if(!ui)` block (which means we are creating a new UI), we choose our template, title, and size; we can also set various options like `style` (for themes), or autoupdate. These options will be elaborated on later (as will `ui_state`s). +## Developer Tools -After `ui_interact`, we need to define `ui_data`. This just returns a list of data for our object to use. Let's imagine our object has a few vars: +When developing with `tgui-dev-server`, you will have access to certain +development only features. -```DM -/obj/machinery/my_machine/ui_data(mob/user) - var/list/data = list() - data["health"] = health - data["color"] = color +**Debug Logs.** +When running server via `bin/tgui --dev --debug`, server will print debug +logs and time spent on rendering. Use this information to optimize your +code, and try to keep re-renders below 16ms. - return data -``` +**Kitchen Sink.** +Press `F12` to open the KitchenSink interface. This interface is a +playground to test various tgui components. -The `ui_data` proc is what people often find the hardest about tgui, but its really quite simple! You just need to represent your object as numbers, strings, and lists, instead of atoms and datums. +**Layout Debugger.** +Press `F11` to toggle the *layout debugger*. It will show outlines of +all tgui elements, which makes it easy to understand how everything comes +together, and can reveal certain layout bugs which are not normally visible. -Finally, the `ui_act` proc is called by the interface whenever the user used an input. The input's `action` and `params` are passed to the proc. +## Project Structure -```DM -/obj/machinery/my_machine/ui_act(action, params) - if(..()) - return - switch(action) - if("change_color") - var/new_color = params["color"] - if(!(color in allowed_coors)) - return - color = new_color - . = TRUE - update_icon() -``` +- `/packages` - Each folder here represents a self-contained Node module. +- `/packages/common` - Helper functions +- `/packages/tgui/index.js` - Application entry point. +- `/packages/tgui/components` - Basic UI building blocks. +- `/packages/tgui/interfaces` - Actual in-game interfaces. +Interface takes data via the `state` prop and outputs an html-like stucture, +which you can build using existing UI components. +- `/packages/tgui/layouts` - Root level UI components, that affect the final +look and feel of the browser window. They usually hold various window +elements, like the titlebar and resize handlers, and control the UI theme. +- `/packages/tgui/routes.js` - This is where tgui decides which interface to +pull and render. +- `/packages/tgui/layout.js` - A root-level component, holding the +window elements, like the titlebar, buttons, resize handlers. Calls +`routes.js` to decide which component to render. +- `/packages/tgui/styles/main.scss` - CSS entry point. +- `/packages/tgui/styles/functions.scss` - Useful SASS functions. +Stuff like `lighten`, `darken`, `luminance` are defined here. +- `/packages/tgui/styles/atomic` - Atomic CSS classes. +These are very simple, tiny, reusable CSS classes which you can use and +combine to change appearance of your elements. Keep them small. +- `/packages/tgui/styles/components` - CSS classes which are used +in UI components. These stylesheets closely follow the +[BEM](https://en.bem.info/methodology/) methodology. +- `/packages/tgui/styles/interfaces` - Custom stylesheets for your interfaces. +Add stylesheets here if you really need a fine control over your UI styles. +- `/packages/tgui/styles/layouts` - Layout-related styles. +- `/packages/tgui/styles/themes` - Contains all the various themes you can +use in tgui. Each theme must be registered in `webpack.config.js` file. -The `..()` (parent call) is very important here, as it is how we check that the user is allowed to use this interface (to avoid so-called href exploits). It is also very important to clamp and sanitize all input here. Always assume the user is attempting to exploit the game. +## Component Reference -Also note the use of `. = TRUE` (or `FALSE`), which is used to notify the UI that this input caused an update. This is especially important for UIs that do not auto-update, as otherwise the user will never see their change. +See: [Component Reference](docs/component-reference.md). -Finally, you have a template. This is also a source of confusion for many new users. Some basic HTML knowledge will get you a long way, however. +## License -A template is regular HTML, with mustache for logic and built-in components to quickly build UIs. Here's how we might show some data (components will be elaborated on later). +Source code is covered by /tg/station's parent license - **AGPL-3.0** +(see the main [README](../README.md)), unless otherwise indicated. -In a template there are a few special values. `config` is always the same and is part of core tgui (it will be explained later), `data` is the data returned from `ui_data`, and `adata` is the same, but with certain values (numbers at this time) interpolated in order to allow animation. +Some files are annotated with a copyright header, which explicitly states +the copyright holder and license of the file. Most of the core tgui +source code is available under the **MIT** license. -```html - - - {{data.health}} - - - {{data.color}} - - -``` - -Templates can be very confusing at first, as ternary operators, computed properties, and iterators are used quite a bit in more complex interfaces. Start with the basics, and work your way up. Much of the complexity stems from performance concerns. If in doubt, take the simpler approach and refactor if performance becomes an issue. - -## Copypasta -We all do it, even the best of us. If you just want to make a tgui **fast**, here's what you need (note that you'll probably be forced to clean your shit up upon code review): - -```DM -/obj/copypasta/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) // Remember to use the appropriate state. - ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) - if(!ui) - ui = new(user, src, ui_key, "copypasta", name, 300, 300, master_ui, state) - ui.open() - -/obj/copypasta/ui_data(mob/user) - var/list/data = list() - data["var"] = var - - return data - -/obj/copypasta/ui_act(action, params) - if(..()) - return - switch(action) - if("copypasta") - var/newvar = params["var"] - var = Clamp(newvar, min_val, max_val) // Just a demo of proper input sanitation. - . = TRUE - update_icon() // Not applicable to all objects. -``` - -And the template: - -```html - - - {{data.var}} - - - {{adata.var}} - - -``` +The Authors retain all copyright to their respective work here submitted. diff --git a/tgui/assets/tgui.css b/tgui/assets/tgui.css deleted file mode 100644 index f98e093ba2..0000000000 --- a/tgui/assets/tgui.css +++ /dev/null @@ -1 +0,0 @@ -@charset "utf-8";body,html{box-sizing:border-box;height:100%;margin:0}html{overflow:hidden;cursor:default}body{overflow:auto;font-family:Verdana,Geneva,sans-serif;font-size:12px;color:#fff;background-color:#2a2a2a;background-image:linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}*,:after,:before{box-sizing:inherit}h1,h2,h3,h4{display:inline-block;margin:0;padding:6px 0}h1{font-size:18px}h2{font-size:16px}h3{font-size:14px}h4{font-size:12px}body.clockwork{background:linear-gradient(180deg,#b18b25 0,#5f380e);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ffb18b25",endColorstr="#ff5f380e",GradientType=0)}body.clockwork .normal{color:#b18b25}body.clockwork .good{color:#cfba47}body.clockwork .average{color:#896b19}body.clockwork .bad{color:#5f380e}body.clockwork .highlight{color:#b18b25}body.clockwork main{display:block;margin-top:32px;padding:2px 6px 0}body.clockwork hr{height:2px;background-color:#b18b25;border:none}body.clockwork .hidden{display:none}body.clockwork .bar .barText,body.clockwork span.button{color:#b18b25;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.clockwork .bold{font-weight:700}body.clockwork .italic{font-style:italic}body.clockwork [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.clockwork div[data-tooltip],body.clockwork span[data-tooltip]{position:relative}body.clockwork div[data-tooltip]:after,body.clockwork span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #170800;background-color:#2d1400}body.clockwork div[data-tooltip]:hover:after,body.clockwork span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";opacity:1}body.clockwork div[data-tooltip].tooltip-top:after,body.clockwork span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-top:hover:after,body.clockwork span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:after,body.clockwork span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.clockwork div[data-tooltip].tooltip-bottom:hover:after,body.clockwork span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.clockwork div[data-tooltip].tooltip-left:after,body.clockwork span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-left:hover:after,body.clockwork span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:after,body.clockwork span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.clockwork div[data-tooltip].tooltip-right:hover:after,body.clockwork span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.clockwork .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #170800;background:#2d1400}body.clockwork .bar .barText{position:absolute;top:0;right:3px}body.clockwork .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#b18b25}body.clockwork .bar .barFill.good{background-color:#cfba47}body.clockwork .bar .barFill.average{background-color:#896b19}body.clockwork .bar .barFill.bad{background-color:#5f380e}body.clockwork span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #170800}body.clockwork span.button .fa{padding-right:2px}body.clockwork span.button.normal{transition:background-color .5s;background-color:#5f380e}body.clockwork span.button.normal.active:focus,body.clockwork span.button.normal.active:hover{transition:background-color .25s;background-color:#704211;outline:0}body.clockwork span.button.normal:not(.active){background-image:repeating-linear-gradient(-45deg,#5f380e,#5f380e 1px,#2d1400 0,#2d1400 2px)}body.clockwork span.button.disabled{transition:background-color .5s;background-color:#2d1400}body.clockwork span.button.disabled.active:focus,body.clockwork span.button.disabled.active:hover{transition:background-color .25s;background-color:#441e00;outline:0}body.clockwork span.button.selected{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.selected.active:focus,body.clockwork span.button.selected.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.selected:not(.active){background-image:repeating-linear-gradient(-45deg,#cfba47,#cfba47 1px,#2d1400 0,#2d1400 2px)}body.clockwork span.button.toggle{transition:background-color .5s;background-color:#cfba47}body.clockwork span.button.toggle.active:focus,body.clockwork span.button.toggle.active:hover{transition:background-color .25s;background-color:#d1bd50;outline:0}body.clockwork span.button.toggle:not(.active){background-image:repeating-linear-gradient(-45deg,#cfba47,#cfba47 1px,#2d1400 0,#2d1400 2px)}body.clockwork span.button.caution{transition:background-color .5s;background-color:#be6209}body.clockwork span.button.caution.active:focus,body.clockwork span.button.caution.active:hover{transition:background-color .25s;background-color:#cd6a0a;outline:0}body.clockwork span.button.caution:not(.active){background-image:repeating-linear-gradient(-45deg,#be6209,#be6209 1px,#2d1400 0,#2d1400 2px)}body.clockwork span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.clockwork span.button.danger.active:focus,body.clockwork span.button.danger.active:hover{transition:background-color .25s;background-color:#abaf00;outline:0}body.clockwork span.button.danger:not(.active){background-image:repeating-linear-gradient(-45deg,#9a9d00,#9a9d00 1px,#2d1400 0,#2d1400 2px)}body.clockwork span.button.gridable{width:125px;margin:2px 0}body.clockwork span.button.gridable.center{text-align:center;width:75px}body.clockwork span.button+span:not(.button),body.clockwork span:not(.button)+span.button{margin-left:5px}body.clockwork div.display{width:100%;padding:4px;margin:6px 0;background-color:#2d1400;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#e62d1400,endColorStr=#e62d1400);background-color:rgba(45,20,0,.9);box-shadow:inset 0 0 5px rgba(0,0,0,.3)}body.clockwork div.display.tabular{padding:0;margin:0}body.clockwork div.display header,body.clockwork div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#cfba47;border-bottom:2px solid #b18b25}body.clockwork div.display header .buttonRight,body.clockwork div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.clockwork div.display article,body.clockwork div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.clockwork input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#b18b25;background-color:#cfba47;border:1px solid #272727}body.clockwork input.number{width:35px}body.clockwork input:-ms-input-placeholder{color:#999}body.clockwork input::placeholder{color:#999}body.clockwork input::-ms-clear{display:none}body.clockwork svg.linegraph{overflow:hidden}body.clockwork div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#2d1400;font-weight:700;font-style:italic;background-color:#000;background-image:repeating-linear-gradient(-45deg,#000,#000 10px,#170800 0,#170800 20px)}body.clockwork div.notice .label{color:#2d1400}body.clockwork div.notice .content:only-of-type{padding:0}body.clockwork div.notice hr{background-color:#896b19}body.clockwork div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-color:transparent transparent #5f380e;border-style:solid;border-width:0 0 45px 45px;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.clockwork section .cell,body.clockwork section .content,body.clockwork section .label,body.clockwork section .line,body.nanotrasen section .cell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.clockwork section{display:table-row;width:100%}body.clockwork section:not(:first-child){padding-top:4px}body.clockwork section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.clockwork section .label{width:1%;padding-right:32px;white-space:nowrap;color:#b18b25}body.clockwork section .content:not(:last-child){padding-right:16px}body.clockwork section .line{width:100%}body.clockwork section .cell:not(:first-child){text-align:center;padding-top:0}body.clockwork section .cell span.button{width:75px}body.clockwork section:not(:last-child){padding-right:4px}body.clockwork div.subdisplay{width:100%;margin:0}body.clockwork header.titlebar .close,body.clockwork header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#cfba47}body.clockwork header.titlebar .close:hover,body.clockwork header.titlebar .minimize:hover{color:#d1bd50}body.clockwork header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#5f380e;border-bottom:1px solid #170800;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.clockwork header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.clockwork header.titlebar .title{position:absolute;top:6px;left:46px;color:#cfba47;font-size:16px;white-space:nowrap}body.clockwork header.titlebar .minimize{position:absolute;top:6px;right:46px}body.clockwork header.titlebar .close{position:absolute;top:4px;right:12px}body.clockwork header.titlebar .statusicon.no-icons{font-size:20px}body.clockwork header.titlebar .statusicon.no-icons:after{content:"O"}body.clockwork header.titlebar .minimize.no-icons{top:-2px;font-size:20px}body.clockwork header.titlebar .minimize.no-icons:after{content:"—"}body.clockwork header.titlebar .close.no-icons{font-size:20px}body.clockwork header.titlebar .close.no-icons:after{content:"X"}body.clockwork.airlock_electronics table{width:100%;border-spacing:2px}body.clockwork.airlock_electronics th{text-align:left}body.clockwork.airlock_electronics td{vertical-align:top}body.clockwork.airlock_electronics td .button{margin-top:4px}body.nanotrasen{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDQyNSAyMDAiIG9wYWNpdHk9Ii4zMyI+PHBhdGggZD0iTTE3OC4wMDQuMDM5SDEwNi44YTYuNzYxIDYuMDI2IDAgMCAwLTYuNzYxIDYuMDI1djE4Ny44NzJhNi43NjEgNi4wMjYgMCAwIDAgNi43NjEgNi4wMjVoNTMuMTA3YTYuNzYxIDYuMDI2IDAgMCAwIDYuNzYyLTYuMDI1VjkyLjM5Mmw3Mi4yMTYgMTA0LjdhNi43NjEgNi4wMjYgMCAwIDAgNS43NiAyLjg3SDMxOC4yYTYuNzYxIDYuMDI2IDAgMCAwIDYuNzYxLTYuMDI2VjYuMDY0QTYuNzYxIDYuMDI2IDAgMCAwIDMxOC4yLjA0aC01NC43MTdhNi43NjEgNi4wMjYgMCAwIDAtNi43NiA2LjAyNXYxMDIuNjJMMTgzLjc2MyAyLjkwOWE2Ljc2MSA2LjAyNiAwIDAgMC01Ljc2LTIuODd6TTQuODQ1IDIyLjEwOUExMy40MTIgMTIuNTAyIDAgMCAxIDEzLjQ3OC4wMzloNjYuMTE4QTUuMzY1IDUgMCAwIDEgODQuOTYgNS4wNHY3OS44OHpNNDIwLjE1NSAxNzcuODkxYTEzLjQxMiAxMi41MDIgMCAwIDEtOC42MzMgMjIuMDdoLTY2LjExOGE1LjM2NSA1IDAgMCAxLTUuMzY1LTUuMDAxdi03OS44OHoiLz48L3N2Zz4=") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#2a2a2a 0,#202020);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff2a2a2a",endColorstr="#ff202020",GradientType=0)}body.nanotrasen .normal{color:#40628a}body.nanotrasen .good{color:#537d29}body.nanotrasen .average{color:#be6209}body.nanotrasen .bad{color:#b00e0e}body.nanotrasen .highlight{color:#8ba5c4}body.nanotrasen main{display:block;margin-top:32px;padding:2px 6px 0}body.nanotrasen hr{height:2px;background-color:#40628a;border:none}body.nanotrasen .hidden{display:none}body.nanotrasen .bar .barText,body.nanotrasen span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.nanotrasen .bold{font-weight:700}body.nanotrasen .italic{font-style:italic}body.nanotrasen [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.nanotrasen div[data-tooltip],body.nanotrasen span[data-tooltip]{position:relative}body.nanotrasen div[data-tooltip]:after,body.nanotrasen span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.nanotrasen div[data-tooltip]:hover:after,body.nanotrasen span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";opacity:1}body.nanotrasen div[data-tooltip].tooltip-top:after,body.nanotrasen span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-top:hover:after,body.nanotrasen span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:after,body.nanotrasen span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.nanotrasen div[data-tooltip].tooltip-bottom:hover:after,body.nanotrasen span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.nanotrasen div[data-tooltip].tooltip-left:after,body.nanotrasen span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-left:hover:after,body.nanotrasen span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:after,body.nanotrasen span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.nanotrasen div[data-tooltip].tooltip-right:hover:after,body.nanotrasen span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.nanotrasen .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #40628a;background:#272727}body.nanotrasen .bar .barText{position:absolute;top:0;right:3px}body.nanotrasen .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#40628a}body.nanotrasen .bar .barFill.good{background-color:#537d29}body.nanotrasen .bar .barFill.average{background-color:#be6209}body.nanotrasen .bar .barFill.bad{background-color:#b00e0e}body.nanotrasen span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.nanotrasen span.button .fa{padding-right:2px}body.nanotrasen span.button.normal{transition:background-color .5s;background-color:#40628a}body.nanotrasen span.button.normal.active:focus,body.nanotrasen span.button.normal.active:hover{transition:background-color .25s;background-color:#4f78aa;outline:0}body.nanotrasen span.button.normal:not(.active){background-image:repeating-linear-gradient(-45deg,#40628a,#40628a 1px,#999 0,#999 2px)}body.nanotrasen span.button.disabled{transition:background-color .5s;background-color:#999}body.nanotrasen span.button.disabled.active:focus,body.nanotrasen span.button.disabled.active:hover{transition:background-color .25s;background-color:#a8a8a8;outline:0}body.nanotrasen span.button.selected{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.selected.active:focus,body.nanotrasen span.button.selected.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.selected:not(.active){background-image:repeating-linear-gradient(-45deg,#2f943c,#2f943c 1px,#999 0,#999 2px)}body.nanotrasen span.button.toggle{transition:background-color .5s;background-color:#2f943c}body.nanotrasen span.button.toggle.active:focus,body.nanotrasen span.button.toggle.active:hover{transition:background-color .25s;background-color:#3ab84b;outline:0}body.nanotrasen span.button.toggle:not(.active){background-image:repeating-linear-gradient(-45deg,#2f943c,#2f943c 1px,#999 0,#999 2px)}body.nanotrasen span.button.caution{transition:background-color .5s;background-color:#9a9d00}body.nanotrasen span.button.caution.active:focus,body.nanotrasen span.button.caution.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.nanotrasen span.button.caution:not(.active){background-image:repeating-linear-gradient(-45deg,#9a9d00,#9a9d00 1px,#999 0,#999 2px)}body.nanotrasen span.button.danger{transition:background-color .5s;background-color:#9d0808}body.nanotrasen span.button.danger.active:focus,body.nanotrasen span.button.danger.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.nanotrasen span.button.danger:not(.active){background-image:repeating-linear-gradient(-45deg,#9d0808,#9d0808 1px,#999 0,#999 2px)}body.nanotrasen span.button.gridable{width:125px;margin:2px 0}body.nanotrasen span.button.gridable.center{text-align:center;width:75px}body.nanotrasen span.button+span:not(.button),body.nanotrasen span:not(.button)+span.button{margin-left:5px}body.nanotrasen div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000);background-color:rgba(0,0,0,.33);box-shadow:inset 0 0 5px rgba(0,0,0,.5)}body.nanotrasen div.display.tabular{padding:0;margin:0}body.nanotrasen div.display header,body.nanotrasen div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #40628a}body.nanotrasen div.display header .buttonRight,body.nanotrasen div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.nanotrasen div.display article,body.nanotrasen div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.nanotrasen input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#000;background-color:#fff;border:1px solid #272727}body.nanotrasen input.number{width:35px}body.nanotrasen input:-ms-input-placeholder{color:#999}body.nanotrasen input::placeholder{color:#999}body.nanotrasen input::-ms-clear{display:none}body.nanotrasen svg.linegraph{overflow:hidden}body.nanotrasen div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#bb9b68;background-image:repeating-linear-gradient(-45deg,#bb9b68,#bb9b68 10px,#b1905d 0,#b1905d 20px)}body.nanotrasen div.notice .label{color:#000}body.nanotrasen div.notice .content:only-of-type{padding:0}body.nanotrasen div.notice hr{background-color:#272727}body.nanotrasen div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-color:transparent transparent #363636;border-style:solid;border-width:0 0 45px 45px;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.nanotrasen section .cell,body.nanotrasen section .content,body.nanotrasen section .label,body.nanotrasen section .line,body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.nanotrasen section{display:table-row;width:100%}body.nanotrasen section:not(:first-child){padding-top:4px}body.nanotrasen section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.nanotrasen section .label{width:1%;padding-right:32px;white-space:nowrap;color:#8ba5c4}body.nanotrasen section .content:not(:last-child){padding-right:16px}body.nanotrasen section .line{width:100%}body.nanotrasen section .cell:not(:first-child){text-align:center;padding-top:0}body.nanotrasen section .cell span.button{width:75px}body.nanotrasen section:not(:last-child){padding-right:4px}body.nanotrasen div.subdisplay{width:100%;margin:0}body.nanotrasen header.titlebar .close,body.nanotrasen header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#8ba5c4}body.nanotrasen header.titlebar .close:hover,body.nanotrasen header.titlebar .minimize:hover{color:#9cb2cd}body.nanotrasen header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.nanotrasen header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.nanotrasen header.titlebar .title{position:absolute;top:6px;left:46px;color:#8ba5c4;font-size:16px;white-space:nowrap}body.nanotrasen header.titlebar .minimize{position:absolute;top:6px;right:46px}body.nanotrasen header.titlebar .close{position:absolute;top:4px;right:12px}body.nanotrasen header.titlebar .statusicon.no-icons{font-size:20px}body.nanotrasen header.titlebar .statusicon.no-icons:after{content:"O"}body.nanotrasen header.titlebar .minimize.no-icons{top:-2px;font-size:20px}body.nanotrasen header.titlebar .minimize.no-icons:after{content:"—"}body.nanotrasen header.titlebar .close.no-icons{font-size:20px}body.nanotrasen header.titlebar .close.no-icons:after{content:"X"}body.nanotrasen.airlock_electronics table{width:100%;border-spacing:2px}body.nanotrasen.airlock_electronics th{text-align:left}body.nanotrasen.airlock_electronics td{vertical-align:top}body.nanotrasen.airlock_electronics td .button{margin-top:4px}body.syndicate{background:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMCIgdmlld0JveD0iMCAwIDIwMCAyODkuNzQyIiBvcGFjaXR5PSIuMzMiPjxwYXRoIGQ9Ik05My41MzggMGMtMTguMTEzIDAtMzQuMjIgMy4xMTItNDguMzI0IDkuMzM0LTEzLjk2NSA2LjIyMi0yNC42MTIgMTUuMDcyLTMxLjk0IDI2LjU0N0M2LjA4NCA0Ny4yMiAyLjk3MiA2MC42MzEgMi45NzIgNzYuMTE2YzAgMTAuNjQ3IDIuNzI1IDIwLjQ2NSA4LjE3NSAyOS40NTMgNS42MTYgOC45ODcgMTQuMDM5IDE3LjM1MiAyNS4yNyAyNS4wOTQgMTEuMjMgNy42MDYgMjYuNTA3IDE1LjQxOSA0NS44MyAyMy40MzggMTkuOTg0IDguMjk2IDM0Ljg0OSAxNS41NTUgNDQuNTkzIDIxLjc3NiA5Ljc0NCA2LjIyMyAxNi43NjEgMTIuODU5IDIxLjA1NSAxOS45MSA0LjI5NSA3LjA1MiA2LjQ0MiAxNS43NjQgNi40NDIgMjYuMTM0IDAgMTYuMTc4LTUuMjAyIDI4LjQ4My0xNS42MDYgMzYuOTE3LTEwLjI0IDguNDM1LTI1LjAyMiAxMi42NTMtNDQuMzQ1IDEyLjY1My0xNC4wMzkgMC0yNS41MTYtMS42Ni0zNC40MzQtNC45NzgtOC45MTgtMy40NTctMTYuMTg2LTguNzExLTIxLjgtMTUuNzYzLTUuNjE2LTcuMDUyLTEwLjA3Ni0xNi42NjEtMTMuMzc5LTI4LjgyOUgwdjU2LjgyN2MzMy44NTcgNy4zMjggNjMuNzQ5IDEwLjk5NCA4OS42NzggMTAuOTk0IDE2LjAyIDAgMzAuNzItMS4zODMgNDQuMDk4LTQuMTQ4IDEzLjU0Mi0yLjkwNCAyNS4xMDQtNy40NjcgMzQuNjgzLTEzLjY5IDkuNzQ0LTYuMzU5IDE3LjM0LTE0LjUxOSAyMi43OS0yNC40NzQgNS40NS0xMC4wOTMgOC4xNzUtMjIuNCA4LjE3NS0zNi45MTcgMC0xMi45OTctMy4zMDItMjQuMzM1LTkuOTA4LTM0LjAxNC02LjQ0LTkuODE4LTE1LjUyNS0xOC41MjctMjcuMjUxLTI2LjEzMi0xMS41NjEtNy42MDQtMjcuOTExLTE1LjgzMS00OS4wNTEtMjQuNjgtMTcuNTA2LTcuMTktMzAuNzItMTMuNjktMzkuNjM4LTE5LjQ5N1M1NC45NjkgOTMuNzU2IDQ5LjQ3OSA4Ny4zMTZjLTUuNDI2LTYuMzY2LTkuNjU4LTE1LjA3LTkuNjU4LTI0Ljg4NyAwLTkuMjY0IDIuMDc1LTE3LjIxNCA2LjIyMy0yMy44NUM1Ny4xNDIgMjQuMTggODcuMzMxIDM2Ljc4MiA5MS4xMiA2Mi45MjVjNC44NCA2Ljc3NSA4Ljg1IDE2LjI0NyAxMi4wMyAyOC40MTVoMjAuNTMydi01NmMtNC40NzktNS45MjQtOS45NTUtMTAuNjMxLTE1LjkwOS0xNC4zNzMgMS42NC40NzkgMy4xOSAxLjAyMyA0LjYzOSAxLjY0IDYuNDk4IDIuNjI2IDEyLjE2OCA3LjMyNyAxNy4wMDcgMTQuMTAzIDQuODQgNi43NzUgOC44NSAxNi4yNDYgMTIuMDMgMjguNDE0IDAgMCA4LjQ4LS4xMjkgOC40OS0uMDAyLjQxNyA2LjQxNS0xLjc1NCA5LjQ1My00LjEyNCAxMi41NjEtMi40MTcgMy4xNy01LjE0NSA2Ljc5LTQuMDAzIDEzLjAwMyAxLjUwOCA4LjIwMyAxMC4xODQgMTAuNTk3IDE0LjYyMiA5LjMxMi0zLjMxOC0uNS01LjMxOC0xLjc1LTUuMzE4LTEuNzVzMS44NzYuOTk5IDUuNjUtMS4zNmMtMy4yNzYuOTU2LTEwLjcwNC0uNzk3LTExLjgtNi43NjMtLjk1OC01LjIwOC45NDYtNy4yOTUgMy40LTEwLjUxNCAyLjQ1NS0zLjIyIDUuMjg1LTYuOTU5IDQuNjg1LTE0LjQ4OWwuMDAzLjAwMmg4LjkyN3YtNTZjLTE1LjA3Mi0zLjg3MS0yNy42NTMtNi4zNi0zNy43NDctNy40NjVDMTE0LjI3OS41NTIgMTA0LjA0NiAwIDkzLjUzNyAwem03MC4zMjEgMTcuMzA5bC4yMzggNDAuMzA1YzEuMzE4IDEuMjI2IDIuNDQgMi4yNzggMy4zNDEgMy4xMDYgNC44NCA2Ljc3NSA4Ljg1IDE2LjI0NiAxMi4wMyAyOC40MTRIMjAwdi01NmMtNi42NzctNC41OTQtMTkuODM2LTEwLjQ3My0zNi4xNC0xNS44MjV6bS0yOC4xMiA1LjYwNWw4LjU2NSAxNy43MTdjLTExLjk3LTYuNDY3LTEzLjg0Ny05LjcxNy04LjU2NS0xNy43MTd6bTIyLjc5NyAwYzIuNzcxIDggMS43ODcgMTEuMjUtNC40OTQgMTcuNzE3bDQuNDk0LTE3LjcxN3ptMTUuMjIyIDI0LjAwOWw4LjU2NSAxNy43MTZjLTExLjk3LTYuNDY2LTEzLjg0Ny05LjcxNy04LjU2NS0xNy43MTZ6bTIyLjc5NyAwYzIuNzcxIDggMS43ODcgMTEuMjUtNC40OTQgMTcuNzE2bDQuNDk0LTE3LjcxNnpNOTcuNDQgNDkuMTNsOC41NjUgMTcuNzE2Yy0xMS45Ny02LjQ2Ny0xMy44NDctOS43MTctOC41NjUtMTcuNzE2em0yMi43OTUgMGMyLjc3MiA3Ljk5OSAxLjc4OCAxMS4yNS00LjQ5MyAxNy43MTZsNC40OTMtMTcuNzE2eiIvPjwvc3ZnPg==") no-repeat fixed 50%/70% 70%,linear-gradient(180deg,#750000 0,#340404);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#ff750000",endColorstr="#ff340404",GradientType=0)}body.syndicate .normal{color:#40628a}body.syndicate .good{color:#73e573}body.syndicate .average{color:#be6209}body.syndicate .bad{color:#b00e0e}body.syndicate .highlight{color:#000}body.syndicate main{display:block;margin-top:32px;padding:2px 6px 0}body.syndicate hr{height:2px;background-color:#272727;border:none}body.syndicate .hidden{display:none}body.syndicate .bar .barText,body.syndicate span.button{color:#fff;font-size:12px;font-weight:400;font-style:normal;text-decoration:none}body.syndicate .bold{font-weight:700}body.syndicate .italic{font-style:italic}body.syndicate [unselectable=on]{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body.syndicate div[data-tooltip],body.syndicate span[data-tooltip]{position:relative}body.syndicate div[data-tooltip]:after,body.syndicate span[data-tooltip]:after{position:absolute;display:block;z-index:2;width:250px;padding:10px;-ms-transform:translateX(-50%);transform:translateX(-50%);pointer-events:none;visibility:hidden;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;white-space:normal;text-align:left;content:attr(data-tooltip);transition:all .5s;border:1px solid #272727;background-color:#363636}body.syndicate div[data-tooltip]:hover:after,body.syndicate span[data-tooltip]:hover:after{pointer-events:none;visibility:visible;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";opacity:1}body.syndicate div[data-tooltip].tooltip-top:after,body.syndicate span[data-tooltip].tooltip-top:after{bottom:100%;left:50%;-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-top:hover:after,body.syndicate span[data-tooltip].tooltip-top:hover:after{-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:after,body.syndicate span[data-tooltip].tooltip-bottom:after{top:100%;left:50%;-ms-transform:translateX(-50%) translateY(-8px);transform:translateX(-50%) translateY(-8px)}body.syndicate div[data-tooltip].tooltip-bottom:hover:after,body.syndicate span[data-tooltip].tooltip-bottom:hover:after{-ms-transform:translateX(-50%) translateY(8px);transform:translateX(-50%) translateY(8px)}body.syndicate div[data-tooltip].tooltip-left:after,body.syndicate span[data-tooltip].tooltip-left:after{top:50%;right:100%;-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-left:hover:after,body.syndicate span[data-tooltip].tooltip-left:hover:after{-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:after,body.syndicate span[data-tooltip].tooltip-right:after{top:50%;left:100%;-ms-transform:translateX(-8px) translateY(-50%);transform:translateX(-8px) translateY(-50%)}body.syndicate div[data-tooltip].tooltip-right:hover:after,body.syndicate span[data-tooltip].tooltip-right:hover:after{-ms-transform:translateX(8px) translateY(-50%);transform:translateX(8px) translateY(-50%)}body.syndicate .bar{display:inline-block;position:relative;vertical-align:middle;width:100%;height:20px;line-height:17px;padding:1px;border:1px solid #000;background:#272727}body.syndicate .bar .barText{position:absolute;top:0;right:3px}body.syndicate .bar .barFill{display:block;height:100%;transition:background-color 1s;background-color:#000}body.syndicate .bar .barFill.good{background-color:#73e573}body.syndicate .bar .barFill.average{background-color:#be6209}body.syndicate .bar .barFill.bad{background-color:#b00e0e}body.syndicate span.button{display:inline-block;vertical-align:middle;min-height:20px;line-height:17px;padding:0 5px;white-space:nowrap;border:1px solid #272727}body.syndicate span.button .fa{padding-right:2px}body.syndicate span.button.normal{transition:background-color .5s;background-color:#397439}body.syndicate span.button.normal.active:focus,body.syndicate span.button.normal.active:hover{transition:background-color .25s;background-color:#4a964a;outline:0}body.syndicate span.button.normal:not(.active){background-image:repeating-linear-gradient(-45deg,#397439,#397439 1px,#363636 0,#363636 2px)}body.syndicate span.button.disabled{transition:background-color .5s;background-color:#363636}body.syndicate span.button.disabled.active:focus,body.syndicate span.button.disabled.active:hover{transition:background-color .25s;background-color:#545454;outline:0}body.syndicate span.button.selected{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.selected.active:focus,body.syndicate span.button.selected.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.selected:not(.active){background-image:repeating-linear-gradient(-45deg,#9d0808,#9d0808 1px,#363636 0,#363636 2px)}body.syndicate span.button.toggle{transition:background-color .5s;background-color:#9d0808}body.syndicate span.button.toggle.active:focus,body.syndicate span.button.toggle.active:hover{transition:background-color .25s;background-color:#ce0b0b;outline:0}body.syndicate span.button.toggle:not(.active){background-image:repeating-linear-gradient(-45deg,#9d0808,#9d0808 1px,#363636 0,#363636 2px)}body.syndicate span.button.caution{transition:background-color .5s;background-color:#be6209}body.syndicate span.button.caution.active:focus,body.syndicate span.button.caution.active:hover{transition:background-color .25s;background-color:#eb790b;outline:0}body.syndicate span.button.caution:not(.active){background-image:repeating-linear-gradient(-45deg,#be6209,#be6209 1px,#363636 0,#363636 2px)}body.syndicate span.button.danger{transition:background-color .5s;background-color:#9a9d00}body.syndicate span.button.danger.active:focus,body.syndicate span.button.danger.active:hover{transition:background-color .25s;background-color:#ced200;outline:0}body.syndicate span.button.danger:not(.active){background-image:repeating-linear-gradient(-45deg,#9a9d00,#9a9d00 1px,#363636 0,#363636 2px)}body.syndicate span.button.gridable{width:125px;margin:2px 0}body.syndicate span.button.gridable.center{text-align:center;width:75px}body.syndicate span.button+span:not(.button),body.syndicate span:not(.button)+span.button{margin-left:5px}body.syndicate div.display{width:100%;padding:4px;margin:6px 0;background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#80000000,endColorStr=#80000000);background-color:rgba(0,0,0,.5);box-shadow:inset 0 0 5px rgba(0,0,0,.75)}body.syndicate div.display.tabular{padding:0;margin:0}body.syndicate div.display header,body.syndicate div.subdisplay header{display:block;position:relative;width:100%;padding:0 4px;margin-bottom:6px;color:#fff;border-bottom:2px solid #272727}body.syndicate div.display header .buttonRight,body.syndicate div.subdisplay header .buttonRight{position:absolute;bottom:6px;right:4px}body.syndicate div.display article,body.syndicate div.subdisplay article{display:table;width:100%;border-collapse:collapse}body.syndicate input{display:inline-block;vertical-align:middle;height:20px;line-height:17px;padding:0 5px;white-space:nowrap;color:#fff;background-color:#9d0808;border:1px solid #272727}body.syndicate input.number{width:35px}body.syndicate input:-ms-input-placeholder{color:#999}body.syndicate input::placeholder{color:#999}body.syndicate input::-ms-clear{display:none}body.syndicate svg.linegraph{overflow:hidden}body.syndicate div.notice{margin:8px 0;padding:4px;box-shadow:none;color:#000;font-weight:700;font-style:italic;background-color:#750000;background-image:repeating-linear-gradient(-45deg,#750000,#750000 10px,#910101 0,#910101 20px)}body.syndicate div.notice .label{color:#000}body.syndicate div.notice .content:only-of-type{padding:0}body.syndicate div.notice hr{background-color:#272727}body.syndicate div.resize{position:fixed;bottom:0;right:0;width:0;height:0;border-color:transparent transparent #363636;border-style:solid;border-width:0 0 45px 45px;-ms-transform:rotate(1turn);transform:rotate(1turn)}body.syndicate section .cell,body.syndicate section .content,body.syndicate section .label,body.syndicate section .line{display:table-cell;margin:0;text-align:left;vertical-align:middle;padding:3px 2px}body.syndicate section{display:table-row;width:100%}body.syndicate section:not(:first-child){padding-top:4px}body.syndicate section.candystripe:nth-child(2n){background-color:#000;-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000)";filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#33000000,endColorStr=#33000000);background-color:rgba(0,0,0,.2)}body.syndicate section .label{width:1%;padding-right:32px;white-space:nowrap;color:#fff}body.syndicate section .content:not(:last-child){padding-right:16px}body.syndicate section .line{width:100%}body.syndicate section .cell:not(:first-child){text-align:center;padding-top:0}body.syndicate section .cell span.button{width:75px}body.syndicate section:not(:last-child){padding-right:4px}body.syndicate div.subdisplay{width:100%;margin:0}body.syndicate header.titlebar .close,body.syndicate header.titlebar .minimize{display:inline-block;position:relative;padding:7px;margin:-7px;color:#e74242}body.syndicate header.titlebar .close:hover,body.syndicate header.titlebar .minimize:hover{color:#eb5e5e}body.syndicate header.titlebar{position:fixed;z-index:1;top:0;left:0;width:100%;height:32px;background-color:#363636;border-bottom:1px solid #161616;box-shadow:0 3px 3px rgba(0,0,0,.1)}body.syndicate header.titlebar .statusicon{position:absolute;top:4px;left:12px;transition:color .5s}body.syndicate header.titlebar .title{position:absolute;top:6px;left:46px;color:#e74242;font-size:16px;white-space:nowrap}body.syndicate header.titlebar .minimize{position:absolute;top:6px;right:46px}body.syndicate header.titlebar .close{position:absolute;top:4px;right:12px}body.syndicate header.titlebar .statusicon.no-icons{font-size:20px}body.syndicate header.titlebar .statusicon.no-icons:after{content:"O"}body.syndicate header.titlebar .minimize.no-icons{top:-2px;font-size:20px}body.syndicate header.titlebar .minimize.no-icons:after{content:"—"}body.syndicate header.titlebar .close.no-icons{font-size:20px}body.syndicate header.titlebar .close.no-icons:after{content:"X"}body.syndicate.airlock_electronics table{width:100%;border-spacing:2px}body.syndicate.airlock_electronics th{text-align:left}body.syndicate.airlock_electronics td{vertical-align:top}body.syndicate.airlock_electronics td .button{margin-top:4px} \ No newline at end of file diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js deleted file mode 100644 index a80e21a6ae..0000000000 --- a/tgui/assets/tgui.js +++ /dev/null @@ -1 +0,0 @@ -require=function a(o,s,p){function u(e,t){if(!s[e]){if(!o[e]){var n="function"==typeof require&&require;if(!t&&n)return n(e,!0);if(c)return c(e,!0);var r=new Error("Cannot find module '"+e+"'");throw r.code="MODULE_NOT_FOUND",r}var i=s[e]={exports:{}};o[e][0].call(i.exports,function(t){return u(o[e][1][t]||t)},i,i.exports,a,o,s,p)}return s[e].exports}for(var c="function"==typeof require&&require,t=0;to;)i.call(t,a=r[o++])&&e.push(a);return e}},{78:78,81:81,82:82}],34:[function(t,e,n){var m=t(41),g=t(24),b=t(43),v=t(92),y=t(26),_="prototype",x=function(t,e,n){var a,r,i,o,s=t&x.F,p=t&x.G,u=t&x.S,c=t&x.P,l=t&x.B,d=p?m:u?m[e]||(m[e]={}):(m[e]||{})[_],f=p?g:g[e]||(g[e]={}),h=f[_]||(f[_]={});for(a in p&&(n=e),n)i=((r=!s&&d&&d[a]!==undefined)?d:n)[a],o=l&&r?y(i,m):c&&"function"==typeof i?y(Function.call,i):i,d&&v(d,a,i,t&x.U),f[a]!=i&&b(f,a,o),c&&h[a]!=i&&(h[a]=i)};m.core=g,x.F=1,x.G=2,x.S=4,x.P=8,x.B=16,x.W=32,x.U=64,x.R=128,e.exports=x},{24:24,26:26,41:41,43:43,92:92}],35:[function(t,e,n){var r=t(127)("match");e.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[r]=!1,!"/./"[t](e)}catch(a){}}return!0}},{127:127}],36:[function(t,e,n){e.exports=function(t){try{return!!t()}catch(e){return!0}}},{}],37:[function(t,e,n){"use strict";var s=t(43),p=t(92),u=t(36),c=t(29),l=t(127);e.exports=function(e,t,n){var a=l(e),r=n(c,a,""[e]),i=r[0],o=r[1];u(function(){var t={};return t[a]=function(){return 7},7!=""[e](t)})&&(p(String.prototype,e,i),s(RegExp.prototype,a,2==t?function(t,e){return o.call(t,this,e)}:function(t){return o.call(t,this)}))}},{127:127,29:29,36:36,43:43,92:92}],38:[function(t,e,n){"use strict";var a=t(8);e.exports=function(){var t=a(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},{8:8}],39:[function(t,e,n){"use strict";var f=t(50),h=t(52),m=t(116),g=t(26),b=t(127)("isConcatSpreadable");e.exports=function v(t,e,n,a,r,i,o,s){for(var p,u,c=r,l=0,d=!!o&&g(o,s,3);ldocument.F=Object<\/script>"),t.close(),c=t.F;n--;)delete c[u][s[n]];return c()};t.exports=Object.create||function(t,e){var n;return null!==t?(r[u]=i(t),n=new r,r[u]=null,n[p]=t):n=c(),e===undefined?n:o(n,e)}},{100:100,31:31,32:32,44:44,73:73,8:8}],72:[function(t,e,n){var r=t(8),i=t(45),o=t(118),s=Object.defineProperty;n.f=t(30)?Object.defineProperty:function(t,e,n){if(r(t),e=o(e,!0),r(n),i)try{return s(t,e,n)}catch(a){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},{118:118,30:30,45:45,8:8}],73:[function(t,e,n){var o=t(72),s=t(8),p=t(81);e.exports=t(30)?Object.defineProperties:function(t,e){s(t);for(var n,a=p(e),r=a.length,i=0;ir;)o(a,n=e[r++])&&(~p(i,n)||i.push(n));return i}},{100:100,115:115,12:12,42:42}],81:[function(t,e,n){var a=t(80),r=t(32);e.exports=Object.keys||function(t){return a(t,r)}},{32:32,80:80}],82:[function(t,e,n){n.f={}.propertyIsEnumerable},{}],83:[function(t,e,n){var r=t(34),i=t(24),o=t(36);e.exports=function(t,e){var n=(i.Object||{})[t]||Object[t],a={};a[t]=e(n),r(r.S+r.F*o(function(){n(1)}),"Object",a)}},{24:24,34:34,36:36}],84:[function(t,e,n){var p=t(81),u=t(115),c=t(82).f;e.exports=function(s){return function(t){for(var e,n=u(t),a=p(n),r=a.length,i=0,o=[];i>>0||(o.test(n)?16:10))}:a},{109:109,110:110,41:41}],88:[function(t,e,n){e.exports=function(t){try{return{e:!1,v:t()}}catch(e){return{e:!0,v:e}}}},{}],89:[function(t,e,n){var a=t(8),r=t(52),i=t(69);e.exports=function(t,e){if(a(t),r(e)&&e.constructor===t)return e;var n=i.f(t);return(0,n.resolve)(e),n.promise}},{52:52,69:69,8:8}],90:[function(t,e,n){e.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},{}],91:[function(t,e,n){var r=t(92);e.exports=function(t,e,n){for(var a in e)r(t,a,e[a],n);return t}},{92:92}],92:[function(t,e,n){var i=t(41),o=t(43),s=t(42),p=t(122)("src"),a="toString",r=Function[a],u=(""+r).split(a);t(24).inspectSource=function(t){return r.call(t)},(e.exports=function(t,e,n,a){var r="function"==typeof n;r&&(s(n,"name")||o(n,"name",e)),t[e]!==n&&(r&&(s(n,p)||o(n,p,t[e]?""+t[e]:u.join(String(e)))),t===i?t[e]=n:a?t[e]?t[e]=n:o(t,e,n):(delete t[e],o(t,e,n)))})(Function.prototype,a,function(){return"function"==typeof this&&this[p]||r.call(this)})},{122:122,24:24,41:41,42:42,43:43}],93:[function(t,e,n){e.exports=function(e,n){var a=n===Object(n)?function(t){return n[t]}:n;return function(t){return String(t).replace(e,a)}}},{}],94:[function(t,e,n){e.exports=Object.is||function(t,e){return t===e?0!==t||1/t==1/e:t!=t&&e!=e}},{}],95:[function(t,e,n){"use strict";var a=t(34),o=t(4),s=t(26),p=t(40);e.exports=function(t){a(a.S,t,{from:function(t){var e,n,a,r,i=arguments[1];return o(this),(e=i!==undefined)&&o(i),t==undefined?new this:(n=[],e?(a=0,r=s(i,arguments[2],2),p(t,!1,function(t){n.push(r(t,a++))})):p(t,!1,n.push,n),new this(n))}})}},{26:26,34:34,4:4,40:40}],96:[function(t,e,n){"use strict";var a=t(34);e.exports=function(t){a(a.S,t,{of:function(){for(var t=arguments.length,e=new Array(t);t--;)e[t]=arguments[t];return new this(e)}})}},{34:34}],97:[function(r,t,e){function i(t,e){if(a(t),!n(e)&&null!==e)throw TypeError(e+": can't set as prototype!")}var n=r(52),a=r(8);t.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(t,n,a){try{(a=r(26)(Function.call,r(75).f(Object.prototype,"__proto__").set,2))(t,[]),n=!(t instanceof Array)}catch(e){n=!0}return function(t,e){return i(t,e),n?t.__proto__=e:a(t,e),t}}({},!1):undefined),check:i}},{26:26,52:52,75:75,8:8}],98:[function(t,e,n){"use strict";var a=t(41),r=t(72),i=t(30),o=t(127)("species");e.exports=function(t){var e=a[t];i&&e&&!e[o]&&r.f(e,o,{configurable:!0,get:function(){return this}})}},{127:127,30:30,41:41,72:72}],99:[function(t,e,n){var a=t(72).f,r=t(42),i=t(127)("toStringTag");e.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,i)&&a(t,i,{configurable:!0,value:e})}},{127:127,42:42,72:72}],100:[function(t,e,n){var a=t(101)("keys"),r=t(122);e.exports=function(t){return a[t]||(a[t]=r(t))}},{101:101,122:122}],101:[function(t,e,n){var a=t(24),r=t(41),i="__core-js_shared__",o=r[i]||(r[i]={});(e.exports=function(t,e){return o[t]||(o[t]=e!==undefined?e:{})})("versions",[]).push({version:a.version,mode:t(60)?"pure":"global",copyright:"© 2018 Denis Pushkarev (zloirock.ru)"})},{24:24,41:41,60:60}],102:[function(t,e,n){var r=t(8),i=t(4),o=t(127)("species");e.exports=function(t,e){var n,a=r(t).constructor;return a===undefined||(n=r(a)[o])==undefined?e:i(n)}},{127:127,4:4,8:8}],103:[function(t,e,n){"use strict";var a=t(36);e.exports=function(t,e){return!!t&&a(function(){e?t.call(null,function(){},1):t.call(null)})}},{36:36}],104:[function(t,e,n){var p=t(114),u=t(29);e.exports=function(s){return function(t,e){var n,a,r=String(u(t)),i=p(e),o=r.length;return i<0||o<=i?s?"":undefined:(n=r.charCodeAt(i))<55296||56319"+r+""}var r=t(34),i=t(36),o=t(29),s=/"/g;e.exports=function(e,t){var n={};n[e]=t(a),r(r.P+r.F*i(function(){var t=""[e]('"');return t!==t.toLowerCase()||3p&&(u=u.slice(0,p)),a?u+r:r+u}},{108:108,116:116,29:29}],108:[function(t,e,n){"use strict";var r=t(114),i=t(29);e.exports=function(t){var e=String(i(this)),n="",a=r(t);if(a<0||a==Infinity)throw RangeError("Count can't be negative");for(;0>>=1)&&(e+=e))1&a&&(n+=e);return n}},{114:114,29:29}],109:[function(t,e,n){function a(t,e,n){var a={},r=s(function(){return!!p[t]()||"​…"!="​…"[t]()}),i=a[t]=r?e(l):p[t];n&&(a[n]=i),o(o.P+o.F*r,"String",a)}var o=t(34),r=t(29),s=t(36),p=t(110),i="["+p+"]",u=RegExp("^"+i+i+"*"),c=RegExp(i+i+"*$"),l=a.trim=function(t,e){return t=String(r(t)),1&e&&(t=t.replace(u,"")),2&e&&(t=t.replace(c,"")),t};e.exports=a},{110:110,29:29,34:34,36:36}],110:[function(t,e,n){e.exports="\t\n\x0B\f\r   ᠎ â€â€‚         âŸã€€\u2028\u2029\ufeff"},{}],111:[function(t,e,n){function a(){var t=+this;if(y.hasOwnProperty(t)){var e=y[t];delete y[t],e()}}function r(t){a.call(t.data)}var i,o,s,p=t(26),u=t(47),c=t(44),l=t(31),d=t(41),f=d.process,h=d.setImmediate,m=d.clearImmediate,g=d.MessageChannel,b=d.Dispatch,v=0,y={},_="onreadystatechange";h&&m||(h=function(t){for(var e=[],n=1;n>1,c=23===e?O(2,-24)-O(2,-77):0,l=0,d=t<0||0===t&&1/t<0?1:0;for((t=A(t))!=t||t===C?(r=t!=t?1:0,a=p):(a=T(R(t)/M),t*(i=O(2,-a))<1&&(a--,i*=2),2<=(t+=1<=a+u?c/i:c*O(2,1-u))*i&&(a++,i/=2),p<=a+u?(r=0,a=p):1<=a+u?(r=(t*i-1)*O(2,e),a+=u):(r=t*O(2,u-1)*O(2,e),a=0));8<=e;o[l++]=255&r,r/=256,e-=8);for(a=a<>1,s=r-7,p=n-1,u=t[p--],c=127&u;for(u>>=7;0>=-s,s+=e;0>8&255]}function G(t){return[255&t,t>>8&255,t>>16&255,t>>24&255]}function z(t){return F(t,52,8)}function W(t){return F(t,23,4)}function H(t,e,n){m(t[_],e,{get:function(){return this[n]}})}function K(t,e,n,a){var r=f(+n);if(r+e>t[N])throw E(x);var i=t[D]._b,o=r+t[I],s=i.slice(o,o+e);return a?s:s.reverse()}function Q(t,e,n,a,r,i){var o=f(+n);if(o+e>t[N])throw E(x);for(var s=t[D]._b,p=o+t[I],u=a(+r),c=0;cJ;)(Y=X[J++])in w||s(w,Y,P[Y]);i||($.constructor=w)}var Z=new k(new w(2)),tt=k[_].setInt8;Z.setInt8(0,2147483648),Z.setInt8(1,2147483649),!Z.getInt8(0)&&Z.getInt8(1)||p(k[_],{setInt8:function(t,e){tt.call(this,t,e<<24>>24)},setUint8:function(t,e){tt.call(this,t,e<<24>>24)}},!0)}else w=function(t){c(this,w,v);var e=f(t);this._b=g.call(new Array(e),0),this[N]=e},k=function(t,e,n){c(this,k,y),c(t,w,y);var a=t[N],r=l(e);if(r<0||a>24},getUint8:function(t){return K(this,1,t)[0]},getInt16:function(t){var e=K(this,2,t,arguments[1]);return(e[1]<<8|e[0])<<16>>16},getUint16:function(t){var e=K(this,2,t,arguments[1]);return e[1]<<8|e[0]},getInt32:function(t){return q(K(this,4,t,arguments[1]))},getUint32:function(t){return q(K(this,4,t,arguments[1]))>>>0},getFloat32:function(t){return B(K(this,4,t,arguments[1]),23,4)},getFloat64:function(t){return B(K(this,8,t,arguments[1]),52,8)},setInt8:function(t,e){Q(this,1,t,V,e)},setUint8:function(t,e){Q(this,1,t,V,e)},setInt16:function(t,e){Q(this,2,t,U,e,arguments[2])},setUint16:function(t,e){Q(this,2,t,U,e,arguments[2])},setInt32:function(t,e){Q(this,4,t,G,e,arguments[2])},setUint32:function(t,e){Q(this,4,t,G,e,arguments[2])},setFloat32:function(t,e){Q(this,4,t,W,e,arguments[2])},setFloat64:function(t,e){Q(this,8,t,z,e,arguments[2])}});b(w,v),b(k,y),s(k[_],o.VIEW,!0),n[v]=w,n[y]=k},{10:10,113:113,114:114,116:116,121:121,30:30,36:36,41:41,43:43,60:60,7:7,72:72,77:77,91:91,99:99}],121:[function(t,e,n){for(var a,r=t(41),i=t(43),o=t(122),s=o("typed_array"),p=o("view"),u=!(!r.ArrayBuffer||!r.DataView),c=u,l=0,d="Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array".split(",");l<9;)(a=r[d[l++]])?(i(a.prototype,s,!0),i(a.prototype,p,!0)):c=!1;e.exports={ABV:u,CONSTR:c,TYPED:s,VIEW:p}},{122:122,41:41,43:43}],122:[function(t,e,n){var a=0,r=Math.random();e.exports=function(t){return"Symbol(".concat(t===undefined?"":t,")_",(++a+r).toString(36))}},{}],123:[function(t,e,n){var a=t(41).navigator;e.exports=a&&a.userAgent||""},{41:41}],124:[function(t,e,n){var a=t(52);e.exports=function(t,e){if(!a(t)||t._t!==e)throw TypeError("Incompatible receiver, "+e+" required!");return t}},{52:52}],125:[function(t,e,n){var a=t(41),r=t(24),i=t(60),o=t(126),s=t(72).f;e.exports=function(t){var e=r.Symbol||(r.Symbol=i?{}:a.Symbol||{});"_"==t.charAt(0)||t in e||s(e,t,{value:o.f(t)})}},{126:126,24:24,41:41,60:60,72:72}],126:[function(t,e,n){n.f=t(127)},{127:127}],127:[function(t,e,n){var a=t(101)("wks"),r=t(122),i=t(41).Symbol,o="function"==typeof i;(e.exports=function(t){return a[t]||(a[t]=o&&i[t]||(o?i:r)("Symbol."+t))}).store=a},{101:101,122:122,41:41}],128:[function(t,e,n){var a=t(18),r=t(127)("iterator"),i=t(59);e.exports=t(24).getIteratorMethod=function(t){if(t!=undefined)return t[r]||t["@@iterator"]||i[a(t)]}},{127:127,18:18,24:24,59:59}],129:[function(t,e,n){var a=t(34),r=t(93)(/[\\^$*+?.()|[\]{}]/g,"\\$&");a(a.S,"RegExp",{escape:function(t){return r(t)}})},{34:34,93:93}],130:[function(t,e,n){var a=t(34);a(a.P,"Array",{copyWithin:t(9)}),t(6)("copyWithin")},{34:34,6:6,9:9}],131:[function(t,e,n){"use strict";var a=t(34),r=t(13)(4);a(a.P+a.F*!t(103)([].every,!0),"Array",{every:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],132:[function(t,e,n){var a=t(34);a(a.P,"Array",{fill:t(10)}),t(6)("fill")},{10:10,34:34,6:6}],133:[function(t,e,n){"use strict";var a=t(34),r=t(13)(2);a(a.P+a.F*!t(103)([].filter,!0),"Array",{filter:function(t){return r(this,t,arguments[1])}})},{103:103,13:13,34:34}],134:[function(t,e,n){"use strict";var a=t(34),r=t(13)(6),i="findIndex",o=!0;i in[]&&Array(1)[i](function(){o=!1}),a(a.P+a.F*o,"Array",{findIndex:function(t){return r(this,t,1=t.length?(this._t=undefined,r(1)):r(0,"keys"==e?n:"values"==e?t[n]:[n,t[n]])},"values"),i.Arguments=i.Array,a("keys"),a("values"),a("entries")},{115:115,56:56,58:58,59:59,6:6}],141:[function(t,e,n){"use strict";var a=t(34),r=t(115),i=[].join;a(a.P+a.F*(t(48)!=Object||!t(103)(i)),"Array",{join:function(t){return i.call(r(this),t===undefined?",":t)}})},{103:103,115:115,34:34,48:48}],142:[function(t,e,n){"use strict";var a=t(34),r=t(115),i=t(114),o=t(116),s=[].lastIndexOf,p=!!s&&1/[1].lastIndexOf(1,-0)<0;a(a.P+a.F*(p||!t(103)(s)),"Array",{lastIndexOf:function(t){if(p)return s.apply(this,arguments)||0;var e=r(this),n=o(e.length),a=n-1;for(1>>=0)?31-Math.floor(Math.log(t+.5)*Math.LOG2E):32}})},{34:34}],165:[function(t,e,n){var a=t(34),r=Math.exp;a(a.S,"Math",{cosh:function(t){return(r(t=+t)+r(-t))/2}})},{34:34}],166:[function(t,e,n){var a=t(34),r=t(61);a(a.S+a.F*(r!=Math.expm1),"Math",{expm1:r})},{34:34,61:61}],167:[function(t,e,n){var a=t(34);a(a.S,"Math",{fround:t(62)})},{34:34,62:62}],168:[function(t,e,n){var a=t(34),p=Math.abs;a(a.S,"Math",{hypot:function(t,e){for(var n,a,r=0,i=0,o=arguments.length,s=0;i>>16)*o+i*(n&r>>>16)<<16>>>0)}})},{34:34,36:36}],170:[function(t,e,n){var a=t(34);a(a.S,"Math",{log10:function(t){return Math.log(t)*Math.LOG10E}})},{34:34}],171:[function(t,e,n){var a=t(34);a(a.S,"Math",{log1p:t(63)})},{34:34,63:63}],172:[function(t,e,n){var a=t(34);a(a.S,"Math",{log2:function(t){return Math.log(t)/Math.LN2}})},{34:34}],173:[function(t,e,n){var a=t(34);a(a.S,"Math",{sign:t(65)})},{34:34,65:65}],174:[function(t,e,n){var a=t(34),r=t(61),i=Math.exp;a(a.S+a.F*t(36)(function(){return-2e-17!=!Math.sinh(-2e-17)}),"Math",{sinh:function(t){return Math.abs(t=+t)<1?(r(t)-r(-t))/2:(i(t-1)-i(-t-1))*(Math.E/2)}})},{34:34,36:36,61:61}],175:[function(t,e,n){var a=t(34),r=t(61),i=Math.exp;a(a.S,"Math",{tanh:function(t){var e=r(t=+t),n=r(-t);return e==Infinity?1:n==Infinity?-1:(e-n)/(i(t)+i(-t))}})},{34:34,61:61}],176:[function(t,e,n){var a=t(34);a(a.S,"Math",{trunc:function(t){return(0w;w++)i(g,_=x[w])&&!i(m,_)&&d(m,_,l(g,_));(m.prototype=b).constructor=m,t(92)(r,h,m)}},{109:109,118:118,19:19,30:30,36:36,41:41,42:42,46:46,71:71,72:72,75:75,77:77,92:92}],178:[function(t,e,n){var a=t(34);a(a.S,"Number",{EPSILON:Math.pow(2,-52)})},{34:34}],179:[function(t,e,n){var a=t(34),r=t(41).isFinite;a(a.S,"Number",{isFinite:function(t){return"number"==typeof t&&r(t)}})},{34:34,41:41}],180:[function(t,e,n){var a=t(34);a(a.S,"Number",{isInteger:t(51)})},{34:34,51:51}],181:[function(t,e,n){var a=t(34);a(a.S,"Number",{isNaN:function(t){return t!=t}})},{34:34}],182:[function(t,e,n){var a=t(34),r=t(51),i=Math.abs;a(a.S,"Number",{isSafeInteger:function(t){return r(t)&&i(t)<=9007199254740991}})},{34:34,51:51}],183:[function(t,e,n){var a=t(34);a(a.S,"Number",{MAX_SAFE_INTEGER:9007199254740991})},{34:34}],184:[function(t,e,n){var a=t(34);a(a.S,"Number",{MIN_SAFE_INTEGER:-9007199254740991})},{34:34}],185:[function(t,e,n){var a=t(34),r=t(86);a(a.S+a.F*(Number.parseFloat!=r),"Number",{parseFloat:r})},{34:34,86:86}],186:[function(t,e,n){var a=t(34),r=t(87);a(a.S+a.F*(Number.parseInt!=r),"Number",{parseInt:r})},{34:34,87:87}],187:[function(t,e,n){"use strict";function u(t,e){for(var n=-1,a=e;++n<6;)a+=t*o[n],o[n]=a%1e7,a=i(a/1e7)}function c(t){for(var e=6,n=0;0<=--e;)n+=o[e],o[e]=i(n/t),n=n%t*1e7}function l(){for(var t=6,e="";0<=--t;)if(""!==e||0===t||0!==o[t]){var n=String(o[t]);e=""===e?n:e+h.call("0",7-n.length)+n}return e}var a=t(34),d=t(114),f=t(5),h=t(108),r=1..toFixed,i=Math.floor,o=[0,0,0,0,0,0],m="Number.toFixed: incorrect invocation!",g=function(t,e,n){return 0===e?n:e%2==1?g(t,e-1,n*t):g(t*t,e/2,n)};a(a.P+a.F*(!!r&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==(0xde0b6b3a7640080).toFixed(0))||!t(36)(function(){r.call({})})),"Number",{toFixed:function(t){var e,n,a,r,i=f(this,m),o=d(t),s="",p="0";if(o<0||20t;)e(a[t++]);l._c=[],l._n=!1,n&&!l._h&&N(l)})}}function o(t){var e=this;e._d||(e._d=!0,(e=e._w||e)._v=t,e._s=2,e._a||(e._a=e._c.slice()),i(e,!0))}var n,s,p,u,c=a(60),l=a(41),f=a(26),h=a(18),m=a(34),g=a(52),b=a(4),v=a(7),y=a(40),_=a(102),x=a(111).set,w=a(68)(),k=a(69),S=a(88),E=a(123),C=a(89),P="Promise",A=l.TypeError,O=l.process,T=O&&O.versions,R=T&&T.v8||"",M=l[P],L="process"==h(O),j=s=k.f,D=!!function(){try{var t=M.resolve(1),e=(t.constructor={})[a(127)("species")]=function(t){t(r,r)};return(L||"function"==typeof PromiseRejectionEvent)&&t.then(r)instanceof e&&0!==R.indexOf("6.6")&&-1===E.indexOf("Chrome/66")}catch(n){}}(),N=function(i){x.call(l,function(){var t,e,n,a=i._v,r=I(i);if(r&&(t=S(function(){L?O.emit("unhandledRejection",a,i):(e=l.onunhandledrejection)?e({promise:i,reason:a}):(n=l.console)&&n.error&&n.error("Unhandled promise rejection",a)}),i._h=L||I(i)?2:1),i._a=undefined,r&&t.e)throw t.v})},I=function(t){return 1!==t._h&&0===(t._a||t._c).length},F=function(e){x.call(l,function(){var t;L?O.emit("rejectionHandled",e):(t=l.onrejectionhandled)&&t({promise:e,reason:e._v})})},B=function(n){var a,r=this;if(!r._d){r._d=!0,r=r._w||r;try{if(r===n)throw A("Promise can't be resolved itself");(a=d(n))?w(function(){var t={_w:r,_d:!1};try{a.call(n,f(B,t,1),f(o,t,1))}catch(e){o.call(t,e)}}):(r._v=n,r._s=1,i(r,!1))}catch(t){o.call({_w:r,_d:!1},t)}}};D||(M=function(t){v(this,M,P,"_h"),b(t),n.call(this);try{t(f(B,this,1),f(o,this,1))}catch(e){o.call(this,e)}},(n=function(t){this._c=[],this._a=undefined,this._s=0,this._d=!1,this._v=undefined,this._h=0,this._n=!1}).prototype=a(91)(M.prototype,{then:function(t,e){var n=j(_(this,M));return n.ok="function"!=typeof t||t,n.fail="function"==typeof e&&e,n.domain=L?O.domain:undefined,this._c.push(n),this._a&&this._a.push(n),this._s&&i(this,!1),n.promise},"catch":function(t){return this.then(undefined,t)}}),p=function(){var t=new n;this.promise=t,this.resolve=f(B,t,1),this.reject=f(o,t,1)},k.f=j=function(t){return t===M||t===u?new p(t):s(t)}),m(m.G+m.W+m.F*!D,{Promise:M}),a(99)(M,P),a(98)(P),u=a(24)[P],m(m.S+m.F*!D,P,{reject:function(t){var e=j(this);return(0,e.reject)(t),e.promise}}),m(m.S+m.F*(c||!D),P,{resolve:function(t){return C(c&&this===u?M:this,t)}}),m(m.S+m.F*!(D&&a(57)(function(t){M.all(t)["catch"](r)})),P,{all:function(t){var o=this,e=j(o),s=e.resolve,p=e.reject,n=S(function(){var a=[],r=0,i=1;y(t,!1,function(t){var e=r++,n=!1;a.push(undefined),i++,o.resolve(t).then(function(t){n||(n=!0,a[e]=t,--i||s(a))},p)}),--i||s(a)});return n.e&&p(n.v),e.promise},race:function(t){var e=this,n=j(e),a=n.reject,r=S(function(){y(t,!1,function(t){e.resolve(t).then(n.resolve,a)})});return r.e&&a(r.v),n.promise}})},{102:102,111:111,123:123,127:127,18:18,24:24,26:26,34:34,4:4,40:40,41:41,52:52,57:57,60:60,68:68,69:69,7:7,88:88,89:89,91:91,98:98,99:99}],209:[function(t,e,n){var a=t(34),i=t(4),o=t(8),s=(t(41).Reflect||{}).apply,p=Function.apply;a(a.S+a.F*!t(36)(function(){s(function(){})}),"Reflect",{apply:function(t,e,n){var a=i(t),r=o(n);return s?s(a,e,r):p.call(a,e,r)}})},{34:34,36:36,4:4,41:41,8:8}],210:[function(t,e,n){var a=t(34),s=t(71),p=t(4),u=t(8),c=t(52),r=t(36),l=t(17),d=(t(41).Reflect||{}).construct,f=r(function(){function t(){}return!(d(function(){},[],t)instanceof t)}),h=!r(function(){d(function(){})});a(a.S+a.F*(f||h),"Reflect",{construct:function(t,e){p(t),u(e);var n=arguments.length<3?t:p(arguments[2]);if(h&&!f)return d(t,e,n);if(t==n){switch(e.length){case 0:return new t;case 1:return new t(e[0]);case 2:return new t(e[0],e[1]);case 3:return new t(e[0],e[1],e[2]);case 4:return new t(e[0],e[1],e[2],e[3])}var a=[null];return a.push.apply(a,e),new(l.apply(t,a))}var r=n.prototype,i=s(c(r)?r:Object.prototype),o=Function.apply.call(t,i,e);return c(o)?o:i}})},{17:17,34:34,36:36,4:4,41:41,52:52,71:71,8:8}],211:[function(t,e,n){var r=t(72),a=t(34),i=t(8),o=t(118);a(a.S+a.F*t(36)(function(){Reflect.defineProperty(r.f({},1,{value:1}),1,{value:2})}),"Reflect",{defineProperty:function(t,e,n){i(t),e=o(e,!0),i(n);try{return r.f(t,e,n),!0}catch(a){return!1}}})},{118:118,34:34,36:36,72:72,8:8}],212:[function(t,e,n){var a=t(34),r=t(75).f,i=t(8);a(a.S,"Reflect",{deleteProperty:function(t,e){var n=r(i(t),e);return!(n&&!n.configurable)&&delete t[e]}})},{34:34,75:75,8:8}],213:[function(t,e,n){"use strict";function a(t){this._t=i(t),this._i=0;var e,n=this._k=[];for(e in t)n.push(e)}var r=t(34),i=t(8);t(55)(a,"Object",function(){var t,e=this._k;do{if(this._i>=e.length)return{value:undefined,done:!0}}while(!((t=e[this._i++])in this._t));return{value:t,done:!1}}),r(r.S,"Reflect",{enumerate:function(t){return new a(t)}})},{34:34,55:55,8:8}],214:[function(t,e,n){var a=t(75),r=t(34),i=t(8);r(r.S,"Reflect",{getOwnPropertyDescriptor:function(t,e){return a.f(i(t),e)}})},{34:34,75:75,8:8}],215:[function(t,e,n){var a=t(34),r=t(79),i=t(8);a(a.S,"Reflect",{getPrototypeOf:function(t){return r(i(t))}})},{34:34,79:79,8:8}],216:[function(t,e,n){var i=t(75),o=t(79),s=t(42),a=t(34),p=t(52),u=t(8);a(a.S,"Reflect",{get:function c(t,e){var n,a,r=arguments.length<3?t:arguments[2];return u(t)===r?t[e]:(n=i.f(t,e))?s(n,"value")?n.value:n.get!==undefined?n.get.call(r):undefined:p(a=o(t))?c(a,e,r):void 0}})},{34:34,42:42,52:52,75:75,79:79,8:8}],217:[function(t,e,n){var a=t(34);a(a.S,"Reflect",{has:function(t,e){return e in t}})},{34:34}],218:[function(t,e,n){var a=t(34),r=t(8),i=Object.isExtensible;a(a.S,"Reflect",{isExtensible:function(t){return r(t),!i||i(t)}})},{34:34,8:8}],219:[function(t,e,n){var a=t(34);a(a.S,"Reflect",{ownKeys:t(85)})},{34:34,85:85}],220:[function(t,e,n){var a=t(34),r=t(8),i=Object.preventExtensions;a(a.S,"Reflect",{preventExtensions:function(t){r(t);try{return i&&i(t),!0}catch(e){return!1}}})},{34:34,8:8}],221:[function(t,e,n){var a=t(34),r=t(97);r&&a(a.S,"Reflect",{setPrototypeOf:function(t,e){r.check(t,e);try{return r.set(t,e),!0}catch(n){return!1}}})},{34:34,97:97}],222:[function(t,e,n){var s=t(72),p=t(75),u=t(79),c=t(42),a=t(34),l=t(90),d=t(8),f=t(52);a(a.S,"Reflect",{set:function h(t,e,n){var a,r,i=arguments.length<4?t:arguments[3],o=p.f(d(t),e);if(!o){if(f(r=u(t)))return h(r,e,n,i);o=l(0)}if(c(o,"value")){if(!1===o.writable||!f(i))return!1;if(a=p.f(i,e)){if(a.get||a.set||!1===a.writable)return!1;a.value=n,s.f(i,e,a)}else s.f(i,e,l(0,n));return!0}return o.set!==undefined&&(o.set.call(i,n),!0)}})},{34:34,42:42,52:52,72:72,75:75,79:79,8:8,90:90}],223:[function(t,e,n){var a=t(41),i=t(46),r=t(72).f,o=t(77).f,s=t(53),p=t(38),u=a.RegExp,c=u,l=u.prototype,d=/a/g,f=/a/g,h=new u(d)!==d;if(t(30)&&(!h||t(36)(function(){return f[t(127)("match")]=!1,u(d)!=d||u(f)==f||"/a/i"!=u(d,"i")}))){u=function(t,e){var n=this instanceof u,a=s(t),r=e===undefined;return!n&&a&&t.constructor===u&&r?t:i(h?new c(a&&!r?t.source:t,e):c((a=t instanceof u)?t.source:t,a&&r?p.call(t):e),n?this:l,u)};function m(e){e in u||r(u,e,{configurable:!0,get:function(){return c[e]},set:function(t){c[e]=t}})}for(var g=o(c),b=0;g.length>b;)m(g[b++]);(l.constructor=u).prototype=l,t(92)(a,"RegExp",u)}t(98)("RegExp")},{127:127,30:30,36:36,38:38,41:41,46:46,53:53,72:72,77:77,92:92,98:98}],224:[function(t,e,n){t(30)&&"g"!=/./g.flags&&t(72).f(RegExp.prototype,"flags",{configurable:!0,get:t(38)})},{30:30,38:38,72:72}],225:[function(t,e,n){t(37)("match",1,function(a,r,t){return[function(t){"use strict";var e=a(this),n=t==undefined?undefined:t[r];return n!==undefined?n.call(t,e):new RegExp(t)[r](String(e))},t]})},{37:37}],226:[function(t,e,n){t(37)("replace",2,function(r,i,o){return[function(t,e){"use strict";var n=r(this),a=t==undefined?undefined:t[i];return a!==undefined?a.call(t,n,e):o.call(String(n),t,e)},o]})},{37:37}],227:[function(t,e,n){t(37)("search",1,function(a,r,t){return[function(t){"use strict";var e=a(this),n=t==undefined?undefined:t[r];return n!==undefined?n.call(t,e):new RegExp(t)[r](String(e))},t]})},{37:37}],228:[function(e,t,n){e(37)("split",2,function(r,i,o){"use strict";var f=e(53),h=o,m=[].push,t="split",g="length",b="lastIndex";if("c"=="abbc"[t](/(b)*/)[1]||4!="test"[t](/(?:)/,-1)[g]||2!="ab"[t](/(?:ab)*/)[g]||4!="."[t](/(.?)(.?)/)[g]||1<"."[t](/()()/)[g]||""[t](/.?/)[g]){var v=/()??/.exec("")[1]===undefined;o=function(t,e){var n=String(this);if(t===undefined&&0===e)return[];if(!f(t))return h.call(n,t,e);var a,r,i,o,s,p=[],u=(t.ignoreCase?"i":"")+(t.multiline?"m":"")+(t.unicode?"u":"")+(t.sticky?"y":""),c=0,l=e===undefined?4294967295:e>>>0,d=new RegExp(t.source,u+"g");for(v||(a=new RegExp("^"+d.source+"$(?!\\s)",u));(r=d.exec(n))&&!(c<(i=r.index+r[0][g])&&(p.push(n.slice(c,r.index)),!v&&1=l));)d[b]===r.index&&d[b]++;return c===n[g]?!o&&d.test("")||p.push(""):p.push(n.slice(c)),p[g]>l?p.slice(0,l):p}}else"0"[t](undefined,0)[g]&&(o=function(t,e){return t===undefined&&0===e?[]:h.call(this,t,e)});return[function(t,e){var n=r(this),a=t==undefined?undefined:t[i];return a!==undefined?a.call(t,n,e):o.call(String(n),t,e)},o]})},{37:37,53:53}],229:[function(e,t,n){"use strict";e(224);function a(t){e(92)(RegExp.prototype,s,t,!0)}var r=e(8),i=e(38),o=e(30),s="toString",p=/./[s];e(36)(function(){return"/a/b"!=p.call({source:"a",flags:"b"})})?a(function(){var t=r(this);return"/".concat(t.source,"/","flags"in t?t.flags:!o&&t instanceof RegExp?i.call(t):undefined)}):p.name!=s&&a(function(){return p.call(this)})},{224:224,30:30,36:36,38:38,8:8,92:92}],230:[function(t,e,n){"use strict";var a=t(20),r=t(124);e.exports=t(23)("Set",function(t){return function(){return t(this,0>10),e%1024+56320))}return n.join("")}})},{112:112,34:34}],241:[function(t,e,n){"use strict";var a=t(34),r=t(105),i="includes";a(a.P+a.F*t(35)(i),"String",{includes:function(t){return!!~r(this,t,i).indexOf(t,1=e.length?{value:undefined,done:!0}:(t=a(e,n),this._i+=t.length,{value:t,done:!1})})},{104:104,56:56}],244:[function(t,e,n){"use strict";t(106)("link",function(e){return function(t){return e(this,"a","href",t)}})},{106:106}],245:[function(t,e,n){var a=t(34),o=t(115),s=t(116);a(a.S,"String",{raw:function(t){for(var e=o(t.raw),n=s(e.length),a=arguments.length,r=[],i=0;ir;)c(W,e=n[r++])||e==V||e==h||a.push(e);return a}function p(t){for(var e,n=t===K,a=N(n?H:C(t)),r=[],i=0;a.length>i;)!c(W,e=a[i++])||n&&!c(K,e)||r.push(W[e]);return r}var u=t(41),c=t(42),l=t(30),d=t(34),f=t(92),h=t(66).KEY,m=t(36),g=t(101),b=t(99),v=t(122),y=t(127),_=t(126),x=t(125),w=t(33),k=t(50),S=t(8),E=t(52),C=t(115),P=t(118),A=t(90),O=t(71),T=t(76),R=t(75),M=t(72),L=t(81),j=R.f,D=M.f,N=T.f,I=u.Symbol,F=u.JSON,B=F&&F.stringify,q="prototype",V=y("_hidden"),U=y("toPrimitive"),G={}.propertyIsEnumerable,z=g("symbol-registry"),W=g("symbols"),H=g("op-symbols"),K=Object[q],Q="function"==typeof I,Y=u.QObject,$=!Y||!Y[q]||!Y[q].findChild,X=l&&m(function(){return 7!=O(D({},"a",{get:function(){return D(this,"a",{value:7}).a}})).a})?function(t,e,n){var a=j(K,e);a&&delete K[e],D(t,e,n),a&&t!==K&&D(K,e,a)}:D,J=Q&&"symbol"==typeof I.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof I},Z=function(t,e,n){return t===K&&Z(H,e,n),S(t),e=P(e,!0),S(n),c(W,e)?(n.enumerable?(c(t,V)&&t[V][e]&&(t[V][e]=!1),n=O(n,{enumerable:A(0,!1)})):(c(t,V)||D(t,V,A(1,{})),t[V][e]=!0),X(t,e,n)):D(t,e,n)};Q||(f((I=function(){if(this instanceof I)throw TypeError("Symbol is not a constructor!");var e=v(0et;)y(tt[et++]);for(var nt=L(y.store),at=0;nt.length>at;)x(nt[at++]);d(d.S+d.F*!Q,"Symbol",{"for":function(t){return c(z,t+="")?z[t]:z[t]=I(t)},keyFor:function(t){if(!J(t))throw TypeError(t+" is not a symbol!");for(var e in z)if(z[e]===t)return e},useSetter:function(){$=!0},useSimple:function(){$=!1}}),d(d.S+d.F*!Q,"Object",{create:function(t,e){return e===undefined?O(t):r(O(t),e)},defineProperty:Z,defineProperties:r,getOwnPropertyDescriptor:o,getOwnPropertyNames:s,getOwnPropertySymbols:p}),F&&d(d.S+d.F*(!Q||m(function(){var t=I();return"[null]"!=B([t])||"{}"!=B({a:t})||"{}"!=B(Object(t))})),"JSON",{stringify:function(t){for(var e,n,a=[t],r=1;r>>0,i=n>>>0;return(e>>>0)+(a>>>0)+((r&i|(r|i)&~(r+i>>>0))>>>31)|0}})},{34:34}],281:[function(t,e,n){var a=t(34);a(a.S,"Math",{imulh:function(t,e){var n=+t,a=+e,r=65535&n,i=65535&a,o=n>>16,s=a>>16,p=(o*i>>>0)+(r*i>>>16);return o*s+(p>>16)+((r*s>>>0)+(65535&p)>>16)}})},{34:34}],282:[function(t,e,n){var a=t(34);a(a.S,"Math",{isubh:function(t,e,n,a){var r=t>>>0,i=n>>>0;return(e>>>0)-(a>>>0)-((~r&i|~(r^i)&r-i>>>0)>>>31)|0}})},{34:34}],283:[function(t,e,n){var a=t(34);a(a.S,"Math",{RAD_PER_DEG:180/Math.PI})},{34:34}],284:[function(t,e,n){var a=t(34),r=Math.PI/180;a(a.S,"Math",{radians:function(t){return t*r}})},{34:34}],285:[function(t,e,n){var a=t(34);a(a.S,"Math",{scale:t(64)})},{34:34,64:64}],286:[function(t,e,n){var a=t(34);a(a.S,"Math",{signbit:function(t){return(t=+t)!=t?t:0==t?1/t==Infinity:0>>16,s=a>>>16,p=(o*i>>>0)+(r*i>>>16);return o*s+(p>>>16)+((r*s>>>0)+(65535&p)>>>16)}})},{34:34}],288:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(4),o=t(72);t(30)&&a(a.P+t(74),"Object",{__defineGetter__:function(t,e){o.f(r(this),t,{get:i(e),enumerable:!0,configurable:!0})}})},{117:117,30:30,34:34,4:4,72:72,74:74}],289:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(4),o=t(72);t(30)&&a(a.P+t(74),"Object",{__defineSetter__:function(t,e){o.f(r(this),t,{set:i(e),enumerable:!0,configurable:!0})}})},{117:117,30:30,34:34,4:4,72:72,74:74}],290:[function(t,e,n){var a=t(34),r=t(84)(!0);a(a.S,"Object",{entries:function(t){return r(t)}})},{34:34,84:84}],291:[function(t,e,n){var a=t(34),p=t(85),u=t(115),c=t(75),l=t(25);a(a.S,"Object",{getOwnPropertyDescriptors:function(t){for(var e,n,a=u(t),r=c.f,i=p(a),o={},s=0;i.length>s;)(n=r(a,e=i[s++]))!==undefined&&l(o,e,n);return o}})},{115:115,25:25,34:34,75:75,85:85}],292:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118),o=t(79),s=t(75).f;t(30)&&a(a.P+t(74),"Object",{__lookupGetter__:function(t){var e,n=r(this),a=i(t,!0);do{if(e=s(n,a))return e.get}while(n=o(n))}})},{117:117,118:118,30:30,34:34,74:74,75:75,79:79}],293:[function(t,e,n){"use strict";var a=t(34),r=t(117),i=t(118),o=t(79),s=t(75).f;t(30)&&a(a.P+t(74),"Object",{__lookupSetter__:function(t){var e,n=r(this),a=i(t,!0);do{if(e=s(n,a))return e.set}while(n=o(n))}})},{117:117,118:118,30:30,34:34,74:74,75:75,79:79}],294:[function(t,e,n){var a=t(34),r=t(84)(!1);a(a.S,"Object",{values:function(t){return r(t)}})},{34:34,84:84}],295:[function(t,e,n){"use strict";function i(t){return null==t?undefined:f(t)}function o(t){var e=t._c;e&&(t._c=undefined,e())}function s(t){return t._o===undefined}function p(t){s(t)||(t._o=undefined,o(t))}function a(t,e){h(t),this._c=undefined,this._o=t,t=new _(this);try{var n=e(t),a=n;null!=n&&("function"==typeof n.unsubscribe?n=function(){a.unsubscribe()}:f(n),this._c=n)}catch(r){return void t.error(r)}s(this)&&o(this)}var r=t(34),u=t(41),c=t(24),l=t(68)(),d=t(127)("observable"),f=t(4),h=t(8),m=t(7),g=t(91),b=t(43),v=t(40),y=v.RETURN;a.prototype=g({},{unsubscribe:function(){p(this)}});var _=function(t){this._s=t};_.prototype=g({},{next:function(t){var e=this._s;if(!s(e)){var n=e._o;try{var a=i(n.next);if(a)return a.call(n,t)}catch(r){try{p(e)}finally{throw r}}}},error:function(t){var e=this._s;if(s(e))throw t;var n=e._o;e._o=undefined;try{var a=i(n.error);if(!a)throw t;t=a.call(n,t)}catch(r){try{o(e)}finally{throw r}}return o(e),t},complete:function(t){var e=this._s;if(!s(e)){var n=e._o;e._o=undefined;try{var a=i(n.complete);t=a?a.call(n,t):undefined}catch(r){try{o(e)}finally{throw r}}return o(e),t}}});var x=function(t){m(this,x,"Observable","_f")._f=f(t)};g(x.prototype,{subscribe:function(t){return new a(t,this._f)},forEach:function(r){var e=this;return new(c.Promise||u.Promise)(function(t,n){f(r);var a=e.subscribe({next:function(t){try{return r(t)}catch(e){n(e),a.unsubscribe()}},error:n,complete:t})})}}),g(x,{from:function(a){var t="function"==typeof this?this:x,e=i(h(a)[d]);if(e){var n=h(e.call(a));return n.constructor===t?n:new t(function(t){return n.subscribe(t)})}return new t(function(e){var n=!1;return l(function(){if(!n){try{if(v(a,!1,function(t){if(e.next(t),n)return y})===y)return}catch(t){if(n)throw t;return void e.error(t)}e.complete()}}),function(){n=!0}})},of:function(){for(var t=0,e=arguments.length,a=new Array(e);t",a.insertBefore(n.lastChild,a.firstChild)}(t,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),s||function a(e,n){n.cache||(n.cache={},n.createElem=e.createElement,n.createFrag=e.createDocumentFragment,n.frag=n.createFrag()),e.createElement=function(t){return h.shivMethods?d(t,e,n):n.createElem(t)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+c().join().replace(/[\w\-:]+/g,function(t){return n.createElem(t),n.frag.createElement(t),'c("'+t+'")'})+");return n}")(h,n.frag)}(t,e),t}!function(){try{var t=o.createElement("a");t.innerHTML="",n="hidden"in t,s=1==t.childNodes.length||function(){o.createElement("a");var t=o.createDocumentFragment();return"undefined"==typeof t.cloneNode||"undefined"==typeof t.createDocumentFragment||"undefined"==typeof t.createElement}()}catch(e){s=n=!0}}();var h={elements:e.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:"3.7.3-pre",shivCSS:!1!==e.shivCSS,supportsUnknownElements:s,shivMethods:!1!==e.shivMethods,type:"default",shivDocument:f,createElement:d,createDocumentFragment:function m(t,e){if(t=t||o,s)return t.createDocumentFragment();for(var n=(e=e||l(t)).frag.cloneNode(),a=0,r=c(),i=r.length;a=-n&&t.vec[0]*a>=-n;var i=e.vec[0]*t.vec[1]-e.vec[1]*t.vec[0];if(0==i)return!1;var o=(r*e.vec[0]-a*e.vec[1])/i,s=(r*t.vec[0]-a*t.vec[1])/i;return-n<=o&&n<=s||n<=o&&-n<=s},o=function o(t,e){return t.map(function(t){return{x:t.x*e[0]+t.y*e[2]+e[4],y:t.x*e[1]+t.y*e[3]+e[5]}})},v=function v(t,e,n,a){var r=Math.PI/180,i=Math.cos(n*r),o=Math.sin(n*r),s=[t*(a[0]*i+a[2]*o),t*(a[1]*i+a[3]*o),e*(-a[0]*o+a[2]*i),e*(-a[1]*o+a[3]*i)],p=s[0]*s[0]+s[2]*s[2],u=s[1]*s[1]+s[3]*s[3],c=((s[0]-s[3])*(s[0]-s[3])+(s[2]+s[1])*(s[2]+s[1]))*((s[0]+s[3])*(s[0]+s[3])+(s[2]-s[1])*(s[2]-s[1])),l=(p+u)/2;if(c<1e-10*l)return{rx:Math.sqrt(l),ry:Math.sqrt(l),ax:0,isDegenerate:!1};var d=s[0]*s[1]+s[2]*s[3],f=l+(c=Math.sqrt(c))/2,h=l-c/2,m=undefined,g=undefined,b=undefined;return b=0<=(m=Math.abs(d)<1e-10&&Math.abs(f-u)<1e-10?90:180*Math.atan(Math.abs(d)>Math.abs(f-u)?(f-p)/d:d/(f-u))/Math.PI)?(g=Math.sqrt(f),Math.sqrt(h)):(m+=90,g=Math.sqrt(h),Math.sqrt(f)),{rx:g,ry:b,ax:m,isDegenerate:g<1e-10*b||b<1e-10*g}};n["default"]={distPointToPoint:c,distPointToParabol:a,circumCenter:r,parabolsCrossX:i,doHalflinesCross:l,matrixTransform:o,transformEllipse:v},e.exports=n["default"]},{}],333:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var x=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return function u(t,e){var n=[],a=!0,r=!1,i=undefined;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}(t,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")};var w=function a(t){return t&&t.__esModule?t:{"default":t}}(t(334)),k=t(335),S=function S(t,e,n){var a=t.map(e),r=n?a.sort(function(t,e){var n=x(t,2),a=n[0],r=(n[1],x(e,2)),i=r[0];r[1];return a-i}):a,i=r.length,o=r[0][0],s=r[i-1][0],p=(0,k.minBy)(r,function(t){return t[1]}),u=(0,k.maxBy)(r,function(t){return t[1]});return o==s&&(s+=1e-5),p==u&&(u+=1e-5),{points:r,xmin:o,xmax:s,ymin:p,ymax:u}};n["default"]=function(t){var e=t.data,n=t.xaccessor,a=t.yaccessor,r=t.width,i=t.height,o=t.closed,s=t.min,p=t.max,u=t.sort,c=u===undefined||u;n=n||function(t){var e=x(t,2),n=e[0];e[1];return n},a=a||function(t){var e=x(t,2);e[0];return e[1]};var l=function l(t){return[n(t),a(t)]},d=e.map(function(t){return S(t,l,c)}),f=(0,k.minBy)(d,function(t){return t.xmin}),h=(0,k.maxBy)(d,function(t){return t.xmax}),m=null==s?(0,k.minBy)(d,function(t){return t.ymin}):s,g=null==p?(0,k.maxBy)(d,function(t){return t.ymax}):p;o&&(m=Math.min(m,0),g=Math.max(g,0));var b=o?0:m,v=(0,w["default"])([f,h],[0,r]),y=(0,w["default"])([m,g],[i,0]);return{arranged:d,scale:function _(t){var e=x(t,2),n=e[0],a=e[1];return[v(n),y(a)]},xscale:v,yscale:y,base:b}},e.exports=n["default"]},{334:334,335:335}],334:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var u=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return function u(t,e){var n=[],a=!0,r=!1,i=undefined;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}(t,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")},c=function c(t,e){var n=u(t,2),a=n[0],r=n[1],i=u(e,2),o=i[0],s=i[1],p=function p(t){return o+(s-o)*(t-a)/(r-a)};return p.inverse=function(){return c([o,s],[a,r])},p};n["default"]=c,e.exports=n["default"]},{}],335:[function(t,e,n){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=function(t,e){if(Array.isArray(t))return t;if(Symbol.iterator in Object(t))return function u(t,e){var n=[],a=!0,r=!1,i=undefined;try{for(var o,s=t[Symbol.iterator]();!(a=(o=s.next()).done)&&(n.push(o.value),!e||n.length!==e);a=!0);}catch(p){r=!0,i=p}finally{try{!a&&s["return"]&&s["return"]()}finally{if(r)throw i}}return n}(t,e);throw new TypeError("Invalid attempt to destructure non-iterable instance")},a=function a(t){return t.reduce(function(t,e){return t+e},0)},r=function r(t){return t.reduce(function(t,e){return Math.min(t,e)})},i=function i(t){return t.reduce(function(t,e){return Math.max(t,e)})},s=function s(t,n){return t.reduce(function(t,e){return t+n(e)},0)},p=function p(t,n){return t.reduce(function(t,e){return Math.min(t,n(e))},Infinity)},u=function u(t,n){return t.reduce(function(t,e){return Math.max(t,n(e))},-Infinity)},c=function c(t,e){var n=o(t,2),a=n[0],r=n[1],i=o(e,2);return[a+i[0],r+i[1]]},l=function l(t,e){var n=o(t,2),a=n[0],r=n[1],i=o(e,2);return[a-i[0],r-i[1]]},d=function d(t,e){var n=o(e,2);return[t*n[0],t*n[1]]},f=function f(t){var e=o(t,2),n=e[0],a=e[1];return Math.sqrt(n*n+a*a)},h=function h(t){return t.reduce(c,[0,0])},m=function m(t){return d(1/t.length,t.reduce(c))},g=function g(t,e){return d(t,[Math.sin(e),-Math.cos(e)])},b=function b(t,e){var n=t||{};for(var a in n){var r=n[a];e[a]=r(e.index,e.item,e.group)}return e},v=function v(t,e,n){for(var a=[],r=t;r>>0,"function"!=typeof t)throw new TypeError;for(r=0;r "+t);var i=undefined;(i=n.node||a.fragment&&a.fragment.rendered&&a.find("*"))&&e.push(i)}}console.warn.apply(console,["%cRactive.js: %c"+t,"color: rgb(114, 157, 52);","color: rgb(85, 85, 85);"].concat(e))},nt=function(){console.log.apply(console,arguments)}):at=nt=rt=B;var ft='A function was specified for "%s" %s, but no %s was returned',ht=function(t,e){return'Missing "'+t+'" '+e+" plugin. You may need to download a plugin via http://docs.ractivejs.org/latest/plugins#"+e+"s"};function mt(t,e,n){var a=gt(t,e,n);return a?a[t][n]:null}function gt(t,e,n){for(;e;){if(n in e[t])return e;if(e.isolated)return null;e=e.parent}}var bt=function(t,e,n,a){if(t===e)return vt(e);if(a){var r=mt("interpolators",n,a);if(r)return r(t,e)||vt(e);pt(ht(a,"interpolator"))}return yt.number(t,e)||yt.array(t,e)||yt.object(t,e)||vt(e)};function vt(t){return function(){return t}}var yt={number:function(e,t){var n;return tt(e)&&tt(t)?(n=(t=+t)-(e=+e))?function(t){return e+t*n}:function(){return e}:null},array:function(t,e){var n,a,r,i;if(!X(t)||!X(e))return null;for(n=[],a=[],i=r=Math.min(t.length,e.length);i--;)a[i]=bt(t[i],e[i]);for(i=r;i=this.duration?(null!==r&&(ge.start(this.root),this.root.viewmodel.set(r,this.to),ge.end()),this.step&&this.step(1,this.to),this.complete(this.to),-1===(a=this.root._animations.indexOf(this))&<("Animation was not found"),this.root._animations.splice(a,1),this.running=!1):(e=this.easing?this.easing(t/this.duration):t/this.duration,null!==r&&(n=this.interpolator(e),ge.start(this.root),this.root.viewmodel.set(r,n),ge.end()),this.step&&this.step(e,n),!0))},stop:function(){var t;this.running=!1,-1===(t=this.root._animations.indexOf(this))&<("Animation was not found"),this.root._animations.splice(t,1)}};function ke(t,e,n){var a,r,i,o,s,p,u,c,l,d,f,h,m,g;if(a=new Xt(function(t){return r=t}),"object"!=typeof t)return(n=n||{}).complete&&a.then(n.complete),n.complete=r,o=Ce(this,t,e,n),a.stop=function(){return o.stop()},a;for(i in p=(n=e||{}).easing,u=n.duration,s=[],c=n.step,l=n.complete,(c||l)&&(f={},n.step=null,n.complete=null,d=function(n){return function(t,e){f[n]=e}}),t)t.hasOwnProperty(i)&&((c||l)&&(h=d(i),n={easing:p,duration:u},c&&(n.step=h)),n.complete=l?h:B,s.push(Ce(this,i,t[i],n)));return g={easing:p,duration:u},c&&(g.step=function(t){return c(t,f)}),l&&a.then(function(t){return l(t,f)}),g.complete=r,m=Ce(this,null,null,g),s.push(m),a.stop=function(){for(var t;t=s.pop();)t.stop();m&&m.stop()},a}var Se=ye,Ee={stop:B};function Ce(t,e,n,a){var r,i,o,s;return null!==(e=e&&Pt(Tt(e)))&&(s=t.viewmodel.get(e)),we.abort(e,t),Z(s,n)?(a.complete&&a.complete(a.to),Ee):(a.easing&&"function"!=typeof(r="function"==typeof a.easing?a.easing:t.easing[a.easing])&&(r=null),i=a.duration===undefined?400:a.duration,o=new Se({keypath:e,from:s,to:n,root:t,duration:i,easing:r,interpolator:a.interpolator,step:a.step,complete:a.complete}),we.add(o),t._animations.push(o),o)}function Pe(){return this.detached||(this.el&&Wt(this.el.__ractive_instances__,this),this.detached=this.fragment.detach(),Ae.fire(this)),this.detached}var Ae=new Bt("detach");function Oe(t){return this.el?this.fragment.find(t):null}function Te(t,e){if(this._isComponentQuery?!this.selector||t.name===this.selector:t.node?p(t.node,this.selector):null)return this.push(t.node||t.instance),e||this._makeDirty(),!0}function Re(){var t,e,n;t=this._root[this._isComponentQuery?"liveComponentQueries":"liveQueries"],e=this.selector,-1!==(n=t.indexOf(e))&&(t.splice(n,1),t[e]=null)}function Me(t,e){var n,a,r,i,o,s,p,u;for(n=je(t.component||t._ractive.proxy),a=je(e.component||e._ractive.proxy),r=zt(n),i=zt(a);r&&r===i;)n.pop(),a.pop(),o=r,r=zt(n),i=zt(a);if(r=r.component||r,i=i.component||i,(p=r.parentFragment)===(u=i.parentFragment))return p.items.indexOf(r)-u.items.indexOf(i)||n.length-a.length;if(s=o.fragments)return s.indexOf(p)-s.indexOf(u)||n.length-a.length;throw new Error("An unexpected condition was met while comparing the position of two components. Please file an issue at https://github.com/RactiveJS/Ractive/issues - thanks!")}function Le(t){var e;return(e=t.parentFragment)?e.owner:t.component&&(e=t.component.parentFragment)?e.owner:void 0}function je(t){var e,n;for(e=[t],n=Le(t);n;)e.push(n),n=Le(n);return e}function De(t,e){return t.compareDocumentPosition?2&t.compareDocumentPosition(e)?1:-1:Me(t,e)}function Ne(){this.sort(this._isComponentQuery?Me:De),this._dirty=!1}function Ie(){var t=this;this._dirty||(this._dirty=!0,ge.scheduleTask(function(){t._sort()}))}function Fe(t){var e=this.indexOf(this._isComponentQuery?t.instance:t);-1!==e&&this.splice(e,1)}var Be=function Cc(t,e,n,a){var r=[];return W(r,{selector:{value:e},live:{value:n},_isComponentQuery:{value:a},_test:{value:Te}}),n&&W(r,{cancel:{value:Re},_root:{value:t},_sort:{value:Ne},_makeDirty:{value:Ie},_remove:{value:Fe},_dirty:{value:!1,writable:!0}}),r};function qe(t,e){var n,a;return this.el?(e=e||{},n=this._liveQueries,(a=n[t])?e&&e.live?a:a.slice():((a=Be(this,t,!!e.live,!1)).live&&(n.push(t),n["_"+t]=a),this.fragment.findAll(t,a),a)):[]}function Ve(t,e){var n,a;return e=e||{},n=this._liveComponentQueries,(a=n[t])?e&&e.live?a:a.slice():((a=Be(this,t,!!e.live,!0)).live&&(n.push(t),n["_"+t]=a),this.fragment.findAllComponents(t,a),a)}function Ue(t){return this.fragment.findComponent(t)}function Ge(t){return this.container?this.container.component&&this.container.component.name===t?this.container:this.container.findContainer(t):null}function ze(t){return this.parent?this.parent.component&&this.parent.component.name===t?this.parent:this.parent.findParent(t):null}var We={enqueue:function(t,e){t.event&&(t._eventQueue=t._eventQueue||[],t._eventQueue.push(t.event)),t.event=e},dequeue:function(t){t._eventQueue&&t._eventQueue.length?t.event=t._eventQueue.pop():delete t.event}},He=function Pc(t,e){var n=arguments[2]===undefined?{}:arguments[2];if(!e)return;n.event?n.event.name=e:n.event={name:e,_noArg:!0};var a=Pt(e).wildcardMatches();!function u(t,e,n,a){var r=arguments[4]!==undefined&&arguments[4];var i,o,s=!0;We.enqueue(t,n);for(o=e.length;0<=o;o--)(i=t._subs[e[o]])&&(s=Ke(t,i,n,a)&&s);We.dequeue(t);if(t.parent&&s){if(r&&t.component){var p=t.component.name+"."+e[e.length-1];e=Pt(p).wildcardMatches(),n&&(n.component=t)}u(t.parent,e,n,a)}}(t,a,n.event,n.args,!0)};function Ke(t,e,n,a){var r=null,i=!1;n&&!n._noArg&&(a=[n].concat(a));for(var o=0,s=(e=e.slice()).length;o\~:]))+)((?::[^\s\+\>\~\(]+(?:\([^\)]+\))?)?\s*[\s\+\>\~]?)\s*/g,In=/^@media/,Fn=/\[data-ractive-css~="\{[a-z0-9-]+\}"]/g;function Bn(t){return t.trim?t.trim():t.replace(/^\s+/,"").replace(/\s+$/,"")}function qn(t){return t.str}var Vn=1,Un={name:"css",extend:function(t,e,n){if(n.css){var a=Vn++,r=n.noCssTransform?n.css:Ln(n.css,a);e.cssId=a,On.add({id:a,styles:r})}},init:function(){}};var Gn={name:"data",extend:function(t,e,n){var a=undefined,r=undefined;if(n.data&&et(n.data))for(a in n.data)(r=n.data[a])&&"object"==typeof r&&(et(r)||X(r))&<("Passing a `data` option with object and array properties to Ractive.extend() is discouraged, as mutating them is likely to cause bugs. Consider using a data function instead:\n\n // this...\n data: function () {\n return {\n myObject: {}\n };\n })\n\n // instead of this:\n data: {\n myObject: {}\n }");e.data=zn(e.data,n.data)},init:function(t,e,n){var a=zn(t.prototype.data,n.data);return"function"==typeof a&&(a=a.call(e)),a||{}},reset:function(t){var e=this.init(t.constructor,t,t.viewmodel);return t.viewmodel.reset(e),!0}};function zn(t,e){!function r(t){t&&t.constructor!==Object&&("function"==typeof t||("object"!=typeof t?pt("data option must be an object or a function, `"+t+"` is not valid"):lt("If supplied, options.data should be a plain JavaScript object - using a non-POJO as the root object may work, but is discouraged")))}(e);var n="function"==typeof t,a="function"==typeof e;return e||n||(e={}),n||a?function(){return Hn(a?Wn(e,this):e,n?Wn(t,this):t)}:Hn(e,t)}function Wn(t,e){var n=t.call(e);if(n)return"object"!=typeof n&&pt("Data function must return an object"),n.constructor!==Object&&dt("Data function returned something other than a plain JavaScript object. This might work, but is strongly discouraged"),n}function Hn(t,e){if(t&&e){for(var n in e)n in t||(t[n]=e[n]);return t}return t||e}var Kn=null,Qn=["preserveWhitespace","sanitize","stripComments","delimiters","tripleDelimiters","interpolate"],Yn={fromId:function Mc(t,e){var n;if(!a){if(e&&e.noThrow)return;throw new Error("Cannot retrieve template #"+t+" as Ractive is not running in a browser.")}Xn(t)&&(t=t.substring(1));if(!(n=document.getElementById(t))){if(e&&e.noThrow)return;throw new Error("Could not find template element with id #"+t)}if("SCRIPT"===n.tagName.toUpperCase())return"textContent"in n?n.textContent:n.innerHTML;if(e&&e.noThrow)return;throw new Error("Template element with id #"+t+", must be a + + + + + + + + + + + +
    + + + + + + + + diff --git a/tgui/packages/tgui/routes.js b/tgui/packages/tgui/routes.js new file mode 100644 index 0000000000..d01340eae2 --- /dev/null +++ b/tgui/packages/tgui/routes.js @@ -0,0 +1,64 @@ +/** + * @file + * @copyright 2020 Aleksej Komarov + * @license MIT + */ + +import { selectBackend } from './backend'; +import { selectDebug } from './debug'; +import { Window } from './layouts'; + +const requireInterface = require.context('./interfaces', false, /\.js$/); + +const routingError = (type, name) => () => { + return ( + + + {type === 'notFound' && ( +
    Interface {name} was not found.
    + )} + {type === 'missingExport' && ( +
    Interface {name} is missing an export.
    + )} +
    +
    + ); +}; + +const SuspendedWindow = () => { + return ( + + + + ); +}; + +export const getRoutedComponent = state => { + const { suspended, config } = selectBackend(state); + if (suspended) { + return SuspendedWindow; + } + if (process.env.NODE_ENV !== 'production') { + const debug = selectDebug(state); + // Show a kitchen sink + if (debug.kitchenSink) { + return require('./debug/KitchenSink').KitchenSink; + } + } + const name = config?.interface; + let esModule; + try { + esModule = requireInterface(`./${name}.js`); + } + catch (err) { + if (err.code === 'MODULE_NOT_FOUND') { + return routingError('notFound', name); + } + throw err; + } + const Component = esModule[name]; + if (!Component) { + return routingError('missingExport', name); + } + return Component; +}; diff --git a/tgui/packages/tgui/store.js b/tgui/packages/tgui/store.js new file mode 100644 index 0000000000..27419e85e1 --- /dev/null +++ b/tgui/packages/tgui/store.js @@ -0,0 +1,61 @@ +/** + * @file + * @copyright 2020 Aleksej Komarov + * @license MIT + */ + +import { flow } from 'common/fp'; +import { applyMiddleware, combineReducers, createStore as createReduxStore } from 'common/redux'; +import { Component } from 'inferno'; +import { backendMiddleware, backendReducer } from './backend'; +import { debugReducer } from './debug'; +import { hotKeyMiddleware } from './hotkeys'; +import { createLogger } from './logging'; +import { assetMiddleware } from './assets'; + +const logger = createLogger('store'); + +export const createStore = () => { + const reducer = flow([ + // State initializer + (state = {}, action) => state, + combineReducers({ + debug: debugReducer, + backend: backendReducer, + }), + ]); + const middleware = [ + process.env.NODE_ENV !== 'production' && loggingMiddleware, + assetMiddleware, + hotKeyMiddleware, + backendMiddleware, + ]; + return createReduxStore(reducer, + applyMiddleware(...middleware.filter(Boolean))); +}; + +const loggingMiddleware = store => next => action => { + const { type, payload } = action; + if (type === 'backend/update') { + logger.debug('action', { type }); + } + else { + logger.debug('action', action); + } + return next(action); +}; + +export class StoreProvider extends Component { + getChildContext() { + const { store } = this.props; + return { store }; + } + + render() { + return this.props.children; + } +} + +export const useDispatch = context => { + return context.store.dispatch; +}; diff --git a/tgui/packages/tgui/styles/atomic/candystripe.scss b/tgui/packages/tgui/styles/atomic/candystripe.scss new file mode 100644 index 0000000000..30159bf99c --- /dev/null +++ b/tgui/packages/tgui/styles/atomic/candystripe.scss @@ -0,0 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +.candystripe:nth-child(odd) { + background-color: rgba(0, 0, 0, 0.25); +} diff --git a/tgui-next/packages/tgui/styles/atomic/color.scss b/tgui/packages/tgui/styles/atomic/color.scss similarity index 80% rename from tgui-next/packages/tgui/styles/atomic/color.scss rename to tgui/packages/tgui/styles/atomic/color.scss index 53f96c358a..e2563f86fa 100644 --- a/tgui-next/packages/tgui/styles/atomic/color.scss +++ b/tgui/packages/tgui/styles/atomic/color.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use '../colors.scss'; $fg-map: colors.$fg-map !default; diff --git a/tgui/packages/tgui/styles/atomic/debug-layout.scss b/tgui/packages/tgui/styles/atomic/debug-layout.scss new file mode 100644 index 0000000000..a3e2150acc --- /dev/null +++ b/tgui/packages/tgui/styles/atomic/debug-layout.scss @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +.debug-layout, +.debug-layout *:not(g):not(path) { + color: rgba(255, 255, 255, 0.9) !important; + background: transparent !important; + outline: 1px solid rgba(255, 255, 255, 0.5) !important; + box-shadow: none !important; + filter: none !important; + + &:hover { + outline-color: rgba(255, 255, 255, 0.8) !important; + } +} diff --git a/tgui-next/packages/tgui/styles/atomic/display.scss b/tgui/packages/tgui/styles/atomic/display.scss similarity index 67% rename from tgui-next/packages/tgui/styles/atomic/display.scss rename to tgui/packages/tgui/styles/atomic/display.scss index 49311a97a7..0d65466af2 100644 --- a/tgui-next/packages/tgui/styles/atomic/display.scss +++ b/tgui/packages/tgui/styles/atomic/display.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + .display-none { display: none; } diff --git a/tgui-next/packages/tgui/styles/atomic/margin.scss b/tgui/packages/tgui/styles/atomic/margin.scss similarity index 83% rename from tgui-next/packages/tgui/styles/atomic/margin.scss rename to tgui/packages/tgui/styles/atomic/margin.scss index 2fa0b0e941..6f555b4100 100644 --- a/tgui-next/packages/tgui/styles/atomic/margin.scss +++ b/tgui/packages/tgui/styles/atomic/margin.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @for $i from 0 through 2 { .m-#{$i} { margin: 6px * $i; diff --git a/tgui/packages/tgui/styles/atomic/outline.scss b/tgui/packages/tgui/styles/atomic/outline.scss new file mode 100644 index 0000000000..a91625de9c --- /dev/null +++ b/tgui/packages/tgui/styles/atomic/outline.scss @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../colors.scss'; + +.outline-dotted { + outline-style: dotted !important; +} + +.outline-dashed { + outline-style: dashed !important; +} + +.outline-solid { + outline-style: solid !important; +} + +.outline-double { + outline-style: double !important; +} + +.outline-groove { + outline-style: groove !important; +} + +.outline-ridge { + outline-style: ridge !important; +} + +.outline-inset { + outline-style: inset !important; +} + +.outline-outset { + outline-style: outset !important; +} + +$fg-map: colors.$fg-map !default; +$bg-map: colors.$bg-map !default; + +@each $color-name, $color-value in $fg-map { + .outline-color-#{$color-name} { + outline: 0.167rem solid $color-value !important; + } +} diff --git a/tgui-next/packages/tgui/styles/atomic/position.scss b/tgui/packages/tgui/styles/atomic/position.scss similarity index 68% rename from tgui-next/packages/tgui/styles/atomic/position.scss rename to tgui/packages/tgui/styles/atomic/position.scss index d0869a5e65..7d572fca10 100644 --- a/tgui-next/packages/tgui/styles/atomic/position.scss +++ b/tgui/packages/tgui/styles/atomic/position.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + .position-relative { position: relative; } diff --git a/tgui-next/packages/tgui/styles/atomic/text.scss b/tgui/packages/tgui/styles/atomic/text.scss similarity index 83% rename from tgui-next/packages/tgui/styles/atomic/text.scss rename to tgui/packages/tgui/styles/atomic/text.scss index 8964129978..4889041e6a 100644 --- a/tgui-next/packages/tgui/styles/atomic/text.scss +++ b/tgui/packages/tgui/styles/atomic/text.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + .text-left { text-align: left; } diff --git a/tgui-next/packages/tgui/styles/base.scss b/tgui/packages/tgui/styles/base.scss similarity index 52% rename from tgui-next/packages/tgui/styles/base.scss rename to tgui/packages/tgui/styles/base.scss index c3fcb65ffe..5c1a20278f 100644 --- a/tgui-next/packages/tgui/styles/base.scss +++ b/tgui/packages/tgui/styles/base.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; $color-fg: #ffffff !default; @@ -7,4 +12,15 @@ $color-bg-start: color.adjust( $color-bg, $lightness: $color-bg-grad-spread) !default; $color-bg-end: color.adjust( $color-bg, $lightness: -$color-bg-grad-spread) !default; -$border-radius: 2px !default; + +$unit: 12px; +$font-size: 1 * $unit !default; +$border-radius: 0.16em !default; + +@function em($px) { + @return 1em * ($px / $unit); +} + +@function rem($px) { + @return 1rem * ($px / $unit); +} diff --git a/tgui-next/packages/tgui/styles/colors.scss b/tgui/packages/tgui/styles/colors.scss similarity index 95% rename from tgui-next/packages/tgui/styles/colors.scss rename to tgui/packages/tgui/styles/colors.scss index 9fde2689af..eef558968c 100644 --- a/tgui-next/packages/tgui/styles/colors.scss +++ b/tgui/packages/tgui/styles/colors.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; @use 'sass:map'; @use 'sass:meta'; diff --git a/tgui/packages/tgui/styles/components/BlockQuote.scss b/tgui/packages/tgui/styles/components/BlockQuote.scss new file mode 100644 index 0000000000..4e54030e5b --- /dev/null +++ b/tgui/packages/tgui/styles/components/BlockQuote.scss @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; +@use '../colors.scss'; + +$color-default: colors.fg(colors.$label) !default; + +.BlockQuote { + color: $color-default; + border-left: base.em(2px) solid $color-default; + padding-left: 0.5em; + margin-bottom: 0.5em; + + &:last-child { + margin-bottom: 0; + } +} diff --git a/tgui-next/packages/tgui/styles/components/Button.scss b/tgui/packages/tgui/styles/components/Button.scss similarity index 86% rename from tgui-next/packages/tgui/styles/components/Button.scss rename to tgui/packages/tgui/styles/components/Button.scss index 5b7d4ce811..3634b908ab 100644 --- a/tgui-next/packages/tgui/styles/components/Button.scss +++ b/tgui/packages/tgui/styles/components/Button.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use '../base.scss'; @use '../colors.scss'; @use '../functions.scss' as *; @@ -8,7 +13,7 @@ $color-selected: colors.bg(colors.$green) !default; $color-caution: colors.bg(colors.$yellow) !default; $color-danger: colors.bg(colors.$red) !default; $color-transparent-text: rgba(255, 255, 255, 0.5) !default; -$border-radius: 0 !default; +$border-radius: base.$border-radius !default; $bg-map: colors.$bg-map !default; @mixin button-color($color) { @@ -40,13 +45,13 @@ $bg-map: colors.$bg-map !default; .Button { position: relative; display: inline-block; - line-height: 20px; - padding: 0 6px; - margin-right: 2px; + line-height: base.em(20px); + padding: 0 0.5em; + margin-right: base.em(2px); white-space: nowrap; outline: 0; border-radius: $border-radius; - margin-bottom: 2px; + margin-bottom: base.em(2px); // Disable selection in buttons user-select: none; -ms-user-select: none; @@ -56,9 +61,9 @@ $bg-map: colors.$bg-map !default; } .fa, .fas, .far { - margin-left: -3px; - margin-right: -3px; - min-width: 16px; + margin-left: -0.25em; + margin-right: -0.25em; + min-width: base.em(16px); text-align: center; } } @@ -66,7 +71,7 @@ $bg-map: colors.$bg-map !default; .Button--hasContent { // Add a margin to the icon to keep it separate from the text .fa, .fas, .far { - margin-right: 3px; + margin-right: 0.25em; } } diff --git a/tgui/packages/tgui/styles/components/ColorBox.scss b/tgui/packages/tgui/styles/components/ColorBox.scss new file mode 100644 index 0000000000..739cacee0e --- /dev/null +++ b/tgui/packages/tgui/styles/components/ColorBox.scss @@ -0,0 +1,12 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +.ColorBox { + display: inline-block; + width: 1em; + height: 1em; + line-height: 1em; + text-align: center; +} diff --git a/tgui/packages/tgui/styles/components/Dimmer.scss b/tgui/packages/tgui/styles/components/Dimmer.scss new file mode 100644 index 0000000000..19d478c9d6 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Dimmer.scss @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +.Dimmer { + // Align everything in the middle. + // A fat middle finger for anything less than IE11. + display: flex; + justify-content: center; + align-items: center; + // Fill positioned parent + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + // Dim everything around it + background-color: rgba(0, 0, 0, 0.75); + z-index: 1; +} diff --git a/tgui/packages/tgui/styles/components/Divider.scss b/tgui/packages/tgui/styles/components/Divider.scss new file mode 100644 index 0000000000..e4df190e62 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Divider.scss @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + +$color: rgba(255, 255, 255, 0.1) !default; +$thickness: base.em(2px) !default; +$spacing: 0.5em; + +.Divider--horizontal { + margin: $spacing 0; + + &:not(.Divider--hidden) { + border-top: $thickness solid $color; + } +} + +.Divider--vertical { + height: 100%; + margin: 0 $spacing; + + &:not(.Divider--hidden) { + border-left: $thickness solid $color; + } +} diff --git a/tgui/packages/tgui/styles/components/Dropdown.scss b/tgui/packages/tgui/styles/components/Dropdown.scss new file mode 100644 index 0000000000..eafbbd2968 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Dropdown.scss @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + +.Dropdown { + position: relative; +} + +.Dropdown__control { + position: relative; + display: inline-block; + font-family: Verdana, sans-serif; + font-size: base.em(12px); + width: base.em(100px); + line-height: base.em(17px); + user-select: none; +} + +.Dropdown__arrow-button { + float: right; + padding-left: 0.5em; + border-left: base.em(1px) solid #000; + border-left: base.em(1px) solid rgba(0, 0, 0, 0.25); +} + +.Dropdown__menu { + position: absolute; + overflow-y: auto; + z-index: 5; + width: base.em(100px); + max-height: base.em(200px); + overflow-y: scroll; + border-radius: 0 0 base.em(2px) base.em(2px); + background-color: #000; + background-color: rgba(0, 0, 0, 0.75); +} + +.Dropdown__menu-noscroll { + position: absolute; + overflow-y: auto; + z-index: 5; + width: base.em(100px); + max-height: base.em(200px); + border-radius: 0 0 base.em(2px) base.em(2px); + background-color: #000; + background-color: rgba(0, 0, 0, 0.75); +} + +.Dropdown__menuentry { + padding: base.em(2px) base.em(4px); + font-family: Verdana, sans-serif; + font-size: base.em(12px); + line-height: base.em(17px); + transition: background-color 100ms; + &:hover { + background-color: #444; + transition: background-color 0ms; + } +} + +.Dropdown__over { + top: auto; + bottom: 100% +} diff --git a/tgui-next/packages/tgui/styles/components/FatalError.scss b/tgui/packages/tgui/styles/components/FatalError.scss similarity index 94% rename from tgui-next/packages/tgui/styles/components/FatalError.scss rename to tgui/packages/tgui/styles/components/FatalError.scss index d9722fd7e8..293b7f0285 100644 --- a/tgui-next/packages/tgui/styles/components/FatalError.scss +++ b/tgui/packages/tgui/styles/components/FatalError.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + .FatalError { display: block !important; position: absolute; diff --git a/tgui/packages/tgui/styles/components/Flex.scss b/tgui/packages/tgui/styles/components/Flex.scss new file mode 100644 index 0000000000..cc34ea6746 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Flex.scss @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +.Flex { + display: -ms-flexbox; + display: flex; +} + +.Flex--inline { + display: inline-flex; +} + +.Flex--iefix { + display: table !important; +} + +.Flex--iefix--column { + display: block !important; + + & > .Flex__item { + display: block !important; + margin-left: 0.5em; + margin-right: 0.5em; + } +} + +.Flex__item--iefix { + display: table-cell !important; +} + +@for $i from 1 through 2 { + .Flex--spacing--#{$i} { + margin: 0 -0.25em * $i; + + & > .Flex__item { + margin: 0 0.25em * $i; + } + } +} diff --git a/tgui-next/packages/tgui/styles/components/Input.scss b/tgui/packages/tgui/styles/components/Input.scss similarity index 67% rename from tgui-next/packages/tgui/styles/components/Input.scss rename to tgui/packages/tgui/styles/components/Input.scss index e74226fdc5..1aaefeec2e 100644 --- a/tgui-next/packages/tgui/styles/components/Input.scss +++ b/tgui/packages/tgui/styles/components/Input.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use '../base.scss'; @use '../functions.scss' as *; @@ -7,16 +12,16 @@ $border-radius: base.$border-radius !default; .Input { position: relative; display: inline-block; - width: 120px; - border: 1px solid $border-color; - border: 1px solid rgba($border-color, 0.75); + width: base.em(120px); + border: base.em(1px) solid $border-color; + border: base.em(1px) solid rgba($border-color, 0.75); border-radius: $border-radius; color: #fff; background-color: #000; background-color: rgba(0, 0, 0, 0.75); - padding: 0 4px; - margin-right: 2px; - line-height: 17px; + padding: 0 base.em(4px); + margin-right: base.em(2px); + line-height: base.em(17px); overflow: visible; } @@ -40,11 +45,11 @@ $border-radius: base.$border-radius !default; border: 0; outline: 0; width: 100%; - font-size: 12px; - line-height: 17px; - height: 17px; + font-size: base.em(12px); + line-height: base.em(17px); + height: base.em(17px); margin: 0; - padding: 0 6px; + padding: 0 0.5em; font-family: Verdana, sans-serif; background-color: transparent; color: #fff; diff --git a/tgui/packages/tgui/styles/components/Knob.scss b/tgui/packages/tgui/styles/components/Knob.scss new file mode 100644 index 0000000000..962b4175d4 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Knob.scss @@ -0,0 +1,126 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; +@use '../colors.scss'; +@use '../functions.scss' as *; + +$bg-map: colors.$bg-map !default; +$fg-map: colors.$fg-map !default; +$ring-color: #6a96c9 !default; +$knob-color: #333333 !default; + +$inner-padding: 0.1em; + +.Knob { + position: relative; + font-size: 1rem; + width: 2.6em; + height: 2.6em; + margin: 0 auto; + margin-bottom: -0.2em; + cursor: n-resize; + + // Adjusts a baseline in a way, that makes knob middle-aligned + // when it flows with the text. + &:after { + content: '.'; + color: transparent; + line-height: 2.5em; + } +} + +.Knob__circle { + position: absolute; + top: $inner-padding; + bottom: $inner-padding; + left: $inner-padding; + right: $inner-padding; + margin: 0.3em; + background-color: $knob-color; + background-image: linear-gradient(to bottom, + rgba(255, 255, 255, 0.15) 0%, + rgba(255, 255, 255, 0) 100%); + border-radius: 50%; + box-shadow: 0 0.05em 0.5em 0 rgba(0, 0, 0, 0.5); +} + +.Knob__cursorBox { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; +} + +.Knob__cursor { + position: relative; + top: 0.05em; + margin: 0 auto; + width: 0.2em; + height: 0.8em; + background-color: rgba(255, 255, 255, 0.9); +} + +.Knob__popupValue { + position: absolute; + top: -2rem; + right: 50%; + font-size: 1rem; + text-align: center; + padding: 0.25rem 0.5rem; + background-color: #000; + transform: translateX(50%); + white-space: nowrap; +} + +.Knob__ring { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + padding: $inner-padding; +} + +$pi: 3.1416; + +.Knob__ringTrackPivot { + transform: rotateZ(135deg); +} + +.Knob__ringTrack { + // transform-origin: 50% 50%; + fill: transparent; + stroke: rgba(255, 255, 255, 0.1); + stroke-width: 8; + stroke-linecap: round; + stroke-dasharray: 75 * $pi; +} + +.Knob__ringFillPivot { + transform: rotateZ(135deg); +} + +.Knob--bipolar .Knob__ringFillPivot { + transform: rotateZ(270deg); +} + +.Knob__ringFill { + fill: transparent; + stroke: $ring-color; + stroke-width: 8; + stroke-linecap: round; + stroke-dasharray: 100 * $pi; + transition: stroke 50ms; +} + +@each $color-name, $color-value in $fg-map { + .Knob--color--#{$color-name} { + .Knob__ringFill { + stroke: $color-value; + } + } +} diff --git a/tgui-next/packages/tgui/styles/components/LabeledList.scss b/tgui/packages/tgui/styles/components/LabeledList.scss similarity index 72% rename from tgui-next/packages/tgui/styles/components/LabeledList.scss rename to tgui/packages/tgui/styles/components/LabeledList.scss index 596645176f..bbda277c90 100644 --- a/tgui-next/packages/tgui/styles/components/LabeledList.scss +++ b/tgui/packages/tgui/styles/components/LabeledList.scss @@ -1,12 +1,19 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + .LabeledList { display: table; // IE8: Does not support calc width: 100%; // Compensate for negative margin - width: calc(100% + 12px); + width: calc(100% + 1em); border-collapse: collapse; border-spacing: 0; - margin: -3px -6px; + margin: -0.25em -0.5em; margin-bottom: 0; padding: 0; } @@ -22,7 +29,7 @@ .LabeledList__cell { display: table-cell; margin: 0; - padding: 3px 6px; + padding: 0.25em 0.5em; border: 0; text-align: left; vertical-align: baseline; @@ -31,13 +38,13 @@ .LabeledList__label { width: 1%; white-space: nowrap; - min-width: 60px; + min-width: 5em; } .LabeledList__buttons { width: 0.1%; white-space: nowrap; text-align: right; - padding-top: 1px; + padding-top: base.em(1px); padding-bottom: 0; } diff --git a/tgui/packages/tgui/styles/components/Modal.scss b/tgui/packages/tgui/styles/components/Modal.scss new file mode 100644 index 0000000000..173ecfa24d --- /dev/null +++ b/tgui/packages/tgui/styles/components/Modal.scss @@ -0,0 +1,14 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + +$color-background: base.$color-bg !default; + +.Modal { + background-color: $color-background; + max-width: calc(100% - 1rem); + padding: 1rem; +} diff --git a/tgui/packages/tgui/styles/components/NoticeBox.scss b/tgui/packages/tgui/styles/components/NoticeBox.scss new file mode 100644 index 0000000000..ac4116d634 --- /dev/null +++ b/tgui/packages/tgui/styles/components/NoticeBox.scss @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use '../base.scss'; +@use '../colors.scss'; +@use '../functions.scss' as *; + +// NoticeBox +$color-background: #bb9b68 !default; +$color-stripes: rgba(0, 0, 0, 0.1) !default; +$color-border: #272727 !default; +$bg-map: colors.$bg-map !default; + +.NoticeBox { + // Adapt text color to background luminance to ensure high contast + $luminance: luminance($color-background); + $text-color: if($luminance > 0.35, + rgba(0, 0, 0, 1), + rgba(255, 255, 255, 1)); + + padding: 0.33em 0.5em; + margin-bottom: 0.5em; + box-shadow: none; + font-weight: bold; + font-style: italic; + color: $text-color; + background-color: $color-background; + background-image: repeating-linear-gradient( + -45deg, + transparent, + transparent base.em(10px), + $color-stripes base.em(10px), + $color-stripes base.em(20px)); +} + +@mixin box-color($color) { + $luminance: luminance($color); + $text-color: if($luminance > 0.35, + rgba(0, 0, 0, 1), + rgba(255, 255, 255, 1)); + color: $text-color; + background-color: color.adjust( + $color, + $saturation: -15%, + $lightness: -15%); +} + +@each $color-name, $color-value in $bg-map { + .NoticeBox--color--#{$color-name} { + @include box-color($color-value) + } +} + +.NoticeBox--type--info { + @include box-color(colors.$blue); +} + +.NoticeBox--type--success { + @include box-color(colors.$green); +} + +.NoticeBox--type--warning { + @include box-color(colors.$orange); +} + +.NoticeBox--type--danger { + @include box-color(colors.$red); +} diff --git a/tgui-next/packages/tgui/styles/components/NumberInput.scss b/tgui/packages/tgui/styles/components/NumberInput.scss similarity index 62% rename from tgui-next/packages/tgui/styles/components/NumberInput.scss rename to tgui/packages/tgui/styles/components/NumberInput.scss index 35a99019cb..8787a00ec1 100644 --- a/tgui-next/packages/tgui/styles/components/NumberInput.scss +++ b/tgui/packages/tgui/styles/components/NumberInput.scss @@ -1,4 +1,10 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; +@use '../base.scss'; @use '../functions.scss' as *; @use './Input.scss'; @@ -8,15 +14,15 @@ $border-radius: Input.$border-radius !default; .NumberInput { position: relative; display: inline-block; - border: 1px solid $border-color; - border: 1px solid rgba($border-color, 0.75); + border: base.em(1px) solid $border-color; + border: base.em(1px) solid rgba($border-color, 0.75); border-radius: $border-radius; color: $border-color; background-color: #000; background-color: rgba(0, 0, 0, 0.75); - padding: 0 4px; - margin-right: 2px; - line-height: 17px; + padding: 0 base.em(4px); + margin-right: base.em(2px); + line-height: base.em(17px); text-align: right; overflow: visible; cursor: n-resize; @@ -27,23 +33,23 @@ $border-radius: Input.$border-radius !default; } .NumberInput__content { - margin-left: 6px; + margin-left: 0.5em; } .NumberInput__barContainer { position: absolute; - top: 2px; - bottom: 2px; - left: 2px; + top: base.em(2px); + bottom: base.em(2px); + left: base.em(2px); } .NumberInput__bar { position: absolute; bottom: 0; left: 0; - width: 3px; + width: base.em(3px); box-sizing: border-box; - border-bottom: 1px solid $border-color; + border-bottom: base.em(1px) solid $border-color; background-color: $border-color; } @@ -57,11 +63,11 @@ $border-radius: Input.$border-radius !default; border: 0; outline: 0; width: 100%; - font-size: 12px; - line-height: 17px; - height: 17px; + font-size: base.em(12px); + line-height: base.em(17px); + height: base.em(17px); margin: 0; - padding: 0 6px; + padding: 0 0.5em; font-family: Verdana, sans-serif; background-color: #000; color: #fff; diff --git a/tgui-next/packages/tgui/styles/components/ProgressBar.scss b/tgui/packages/tgui/styles/components/ProgressBar.scss similarity index 68% rename from tgui-next/packages/tgui/styles/components/ProgressBar.scss rename to tgui/packages/tgui/styles/components/ProgressBar.scss index f21b8d8706..fb77fa9c6d 100644 --- a/tgui-next/packages/tgui/styles/components/ProgressBar.scss +++ b/tgui/packages/tgui/styles/components/ProgressBar.scss @@ -1,16 +1,22 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; @use '../colors.scss'; @use '../functions.scss' as *; $color-default: colors.bg(colors.$primary) !default; $color-background: rgba(0, 0, 0, 0) !default; -$border-radius: 0 !default; +$border-radius: base.$border-radius !default; $bg-map: colors.$bg-map !default; .ProgressBar { display: inline-block; position: relative; width: 100%; - padding: 0 6px; + padding: 0 0.5em; border-radius: $border-radius; background-color: $color-background; transition: border-color 500ms; @@ -18,21 +24,24 @@ $bg-map: colors.$bg-map !default; .ProgressBar__fill { position: absolute; - top: 0; - left: 0; - bottom: 0; + top: -0.5px; + left: 0px; + bottom: -0.5px; +} + +.ProgressBar__fill--animated { transition: background-color 500ms, width 500ms; } .ProgressBar__content { position: relative; - line-height: 17px; + line-height: base.em(17px); width: 100%; text-align: right; } .ProgressBar--color--default { - border: 1px solid $color-default; + border: base.em(1px) solid $color-default; .ProgressBar__fill { background-color: $color-default; @@ -41,7 +50,7 @@ $bg-map: colors.$bg-map !default; @each $color-name, $color-value in $bg-map { .ProgressBar--color--#{$color-name} { - border: 1px solid $color-value !important; + border: base.em(1px) solid $color-value !important; .ProgressBar__fill { background-color: $color-value; diff --git a/tgui-next/packages/tgui/styles/components/Section.scss b/tgui/packages/tgui/styles/components/Section.scss similarity index 62% rename from tgui-next/packages/tgui/styles/components/Section.scss rename to tgui/packages/tgui/styles/components/Section.scss index f9c1d72925..1e2ad798fd 100644 --- a/tgui-next/packages/tgui/styles/components/Section.scss +++ b/tgui/packages/tgui/styles/components/Section.scss @@ -1,4 +1,10 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; +@use '../base.scss'; @use '../colors.scss'; $color-title: #ffffff !default; @@ -8,7 +14,7 @@ $color-separator: colors.$primary !default; .Section { position: relative; - margin-bottom: 6px; + margin-bottom: 0.5em; // IE8: Does not support rgba colors background-color: color.adjust( $color-background, @@ -25,42 +31,52 @@ $color-separator: colors.$primary !default; .Section__title { position: relative; - padding: 6px; - border-bottom: 2px solid $color-separator; + padding: 0.5em; + border-bottom: base.em(2px) solid $color-separator; } .Section__titleText { - font-size: 14px; + font-size: base.em(14px); font-weight: bold; } .Section__buttons { position: absolute; display: inline-block; - right: 6px; - margin-top: -1px; + right: 0.5em; + margin-top: base.em(-1px); } .Section__content { - padding: 8px 6px; + padding: 0.66em 0.5em; +} + +.Section--fill { + display: flex; + flex-direction: column; + height: 100%; +} + +.Section--fill .Section__content { + flex-grow: 1; } .Section--level--1 .Section__titleText { - font-size: 14px; + font-size: base.em(14px); } .Section--level--2 .Section__titleText { - font-size: 13px; + font-size: base.em(13px); } .Section--level--3 .Section__titleText { - font-size: 12px; + font-size: base.em(12px); } .Section--level--2, .Section--level--3 { background-color: transparent; box-shadow: none; - margin-left: -6px; - margin-right: -6px; + margin-left: -0.5em; + margin-right: -0.5em; } diff --git a/tgui/packages/tgui/styles/components/Slider.scss b/tgui/packages/tgui/styles/components/Slider.scss new file mode 100644 index 0000000000..4644129c32 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Slider.scss @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + +.Slider { + cursor: e-resize; +} + +.Slider__cursorOffset { + position: absolute; + top: 0; + left: 0; + bottom: 0; + transition: none !important; +} + +.Slider__cursor { + position: absolute; + top: 0; + right: base.em(-1px); + bottom: 0; + width: 0; + border-left: base.em(2px) solid #fff; +} + +.Slider__pointer { + position: absolute; + right: base.em(-5px); + bottom: base.em(-4px); + width: 0; + height: 0; + border-left: base.em(5px) solid transparent; + border-right: base.em(5px) solid transparent; + border-bottom: base.em(5px) solid #fff; +} + +.Slider__popupValue { + position: absolute; + right: 0; + top: -2rem; + font-size: 1rem; + padding: 0.25rem 0.5rem; + background-color: #000; + transform: translateX(50%); + white-space: nowrap; +} diff --git a/tgui-next/packages/tgui/styles/components/Table.scss b/tgui/packages/tgui/styles/components/Table.scss similarity index 78% rename from tgui-next/packages/tgui/styles/components/Table.scss rename to tgui/packages/tgui/styles/components/Table.scss index c4ba75b562..ecc47e5ba9 100644 --- a/tgui-next/packages/tgui/styles/components/Table.scss +++ b/tgui/packages/tgui/styles/components/Table.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + .Table { display: table; width: 100%; @@ -16,7 +21,7 @@ .Table__cell { display: table-cell; - padding: 0 3px; + padding: 0 0.25em; &:first-child { padding-left: 0; @@ -30,7 +35,7 @@ .Table__row--header .Table__cell, .Table__cell--header { font-weight: bold; - padding-bottom: 6px; + padding-bottom: 0.5em; } .Table__cell--collapsing { diff --git a/tgui/packages/tgui/styles/components/Tabs.scss b/tgui/packages/tgui/styles/components/Tabs.scss new file mode 100644 index 0000000000..6e8a6bcb68 --- /dev/null +++ b/tgui/packages/tgui/styles/components/Tabs.scss @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + +$border-radius: base.$border-radius !default; + +.Tabs--horizontal { + border-bottom: base.em(2px) solid rgba(255, 255, 255, 0.1); + margin-bottom: 0.5em; + + .Tabs__tab--altSelection::after { + content: ''; + position: absolute; + bottom: 0; + right: 0; + left: 0; + height: base.em(2px); + width: 100%; + background-color: #fff; + border-radius: $border-radius; + } +} + +.Tabs--vertical { + margin-right: 0.75em; + + .Tabs__tabBox { + border-right: base.em(2px) solid rgba(255, 255, 255, 0.1); + // Disable baseline alignment when doing vertical tabs + vertical-align: top; + } + + .Tabs__tab { + // Force display block because Button theme overrides it via cascading. + display: block !important; + // Override to stop themed buttons from taking priority over it. + margin-right: 0 !important; + margin-bottom: 0; + padding: base.em(1px) base.em(9px) 0px 0.5em; + border-bottom: base.em(2px) solid rgba(255, 255, 255, 0.1); + + &:last-child { + border-bottom: 0; + } + } + + .Tabs__tab--altSelection::after { + content: ''; + position: absolute; + top: 0; + bottom: 0; + right: 0; + height: 100%; + width: 0.25em; + background-color: #fff; + border-radius: $border-radius; + } +} diff --git a/tgui/packages/tgui/styles/components/TextArea.scss b/tgui/packages/tgui/styles/components/TextArea.scss new file mode 100644 index 0000000000..61597c1623 --- /dev/null +++ b/tgui/packages/tgui/styles/components/TextArea.scss @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; +@use '../functions.scss' as *; + +$text-color: #272727 !default; +$border-color: #88bfff !default; +$border-radius: base.$border-radius !default; +$color-background: #bb9b68 !default; +$color-border: #272727 !default; + +.TextArea { + overflow: hidden; + position: relative; + display: inline-block; + height: "100%"; + border: 1px solid $border-color; + border: 1px solid rgba($border-color, 0.75); + border-radius: $border-radius; + background-color: $color-background; + margin-right: 2px; + line-height: 17px; + overflow: visible; + -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */ + -moz-box-sizing: border-box; /* Firefox, other Gecko */ + box-sizing: border-box; /* Opera/IE 8+ */ + width:100%; + + + +.TextArea_filler { + word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */ + box-sizing: border-box; + padding: 2px; + width: 100%; + + padding-bottom: 1.5em; /* A bit more than one additional line of text. */ + visibility: hidden; +} + +.TextArea--fluid { + display: block; + width: auto; + height: auto; +} + +.TextArea__baseline { + display: inline-block; + color: transparent; +} + +.TextArea__textarea { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + border: 0; + outline: 0; + width: 100%; + height: 100%; + font-size: 12px; + line-height: 17px; + height: 17px; + margin: 0; + padding: 0 6px; + font-family: inherit; + background-color: transparent; + color: inherit; + box-sizing: border-box; + width: 100%; + + /* Cut and paste to auto resize the textarea */ + word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */ + box-sizing: border-box; + -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */ + -moz-box-sizing: border-box; /* Firefox, other Gecko */ + box-sizing: border-box; /* Opera/IE 8+ */ + + padding: 2px; + width: 100%; + + overflow: hidden; + position: absolute; + height: 100%; + + &:-ms-input-placeholder { + font-style: italic; + color: #777; + /* color: rgba(255, 255, 255, 0.45);*/ + } +} + +} diff --git a/tgui-next/packages/tgui/styles/components/Tooltip.scss b/tgui/packages/tgui/styles/components/Tooltip.scss similarity index 63% rename from tgui-next/packages/tgui/styles/components/Tooltip.scss rename to tgui/packages/tgui/styles/components/Tooltip.scss index 8ff9f9b930..505209ac00 100644 --- a/tgui-next/packages/tgui/styles/components/Tooltip.scss +++ b/tgui/packages/tgui/styles/components/Tooltip.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use '../base.scss'; @use '../functions.scss' as *; @@ -18,7 +23,7 @@ $border-radius: base.$border-radius !default; display: block; white-space: nowrap; z-index: 2; - padding: 6px 10px; + padding: 0.5em 0.75em; transform: translateX(-50%); pointer-events: none; visibility: hidden; @@ -27,7 +32,7 @@ $border-radius: base.$border-radius !default; content: attr(data-tooltip); transition: all 150ms; background-color: $color-background; - box-shadow: 1px 1px 15px -1px rgba(0, 0, 0, 0.5); + box-shadow: 0.1em 0.1em 1.25em -0.1em rgba(0, 0, 0, 0.5); border-radius: $border-radius; } @@ -41,7 +46,7 @@ $border-radius: base.$border-radius !default; .Tooltip--long { &::after { - width: 250px; + width: base.em(250px); white-space: normal; } } @@ -49,59 +54,59 @@ $border-radius: base.$border-radius !default; .Tooltip--top::after { bottom: 100%; left: 50%; - transform: translateX(-50%) translateY(8px); + transform: translateX(-50%) translateY(0.5em); } .Tooltip--top:hover::after { - transform: translateX(-50%) translateY(-8px); + transform: translateX(-50%) translateY(-0.5em); } .Tooltip--bottom::after { top: 100%; left: 50%; - transform: translateX(-50%) translateY(-8px); + transform: translateX(-50%) translateY(-0.5em); } .Tooltip--bottom:hover::after { - transform: translateX(-50%) translateY(8px); + transform: translateX(-50%) translateY(0.5em); } .Tooltip--bottom-left::after { top: 100%; right: 50%; - transform: translateX(12px) translateY(-8px); + transform: translateX(12px) translateY(-0.5em); } .Tooltip--bottom-left:hover::after { - transform: translateX(12px) translateY(8px); + transform: translateX(12px) translateY(0.5em); } .Tooltip--bottom-right::after { top: 100%; left: 50%; - transform: translateX(-12px) translateY(-8px); + transform: translateX(-12px) translateY(-0.5em); } .Tooltip--bottom-right:hover::after { - transform: translateX(-12px) translateY(8px); + transform: translateX(-12px) translateY(0.5em); } .Tooltip--left::after { top: 50%; right: 100%; - transform: translateX(8px) translateY(-50%); + transform: translateX(0.5em) translateY(-50%); } .Tooltip--left:hover::after { - transform: translateX(-8px) translateY(-50%); + transform: translateX(-0.5em) translateY(-50%); } .Tooltip--right::after { top: 50%; left: 100%; - transform: translateX(-8px) translateY(-50%); + transform: translateX(-0.5em) translateY(-50%); } .Tooltip--right:hover::after { - transform: translateX(8px) translateY(-50%); + transform: translateX(0.5em) translateY(-50%); } diff --git a/tgui-next/packages/tgui/styles/functions.scss b/tgui/packages/tgui/styles/functions.scss similarity index 53% rename from tgui-next/packages/tgui/styles/functions.scss rename to tgui/packages/tgui/styles/functions.scss index 5ed0da177b..84e3152848 100644 --- a/tgui-next/packages/tgui/styles/functions.scss +++ b/tgui/packages/tgui/styles/functions.scss @@ -1,18 +1,23 @@ /** - * Copyright (c) 2018 Aleksej Komarov - * SPDX-License-Identifier: GPL-2.0-or-later + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT */ +@use 'sass:color'; +@use 'sass:map'; +@use 'sass:math'; +@use 'sass:meta'; + // Type-casting // -------------------------------------------------------- // Get a unit-less numeric value @function num($value) { - @if type-of($value) != number { + @if meta.type-of($value) != number { @error 'Could not convert `#{$value}` - must be `type-of number`'; @return null; } - @if unit($value) == '%' { + @if math.unit($value) == '%' { @return $value / 100%; } @return $value / ($value * 0 + 1); @@ -25,20 +30,20 @@ // Increases perceptual color lightness. @function lighten($color, $percent) { $scaled: hsl( - hue($color), - saturation($color), - lightness($color) * (1 + num($percent))); - $mixed: mix(#ffffff, $color, 100% * num($percent)); - @return mix($scaled, $mixed, 75%); + color.hue($color), + color.saturation($color), + color.lightness($color) * (1 + num($percent))); + $mixed: color.mix(#ffffff, $color, 100% * num($percent)); + @return color.mix($scaled, $mixed, 75%); } // Returns the NTSC luminance of `$color` as a float (between 0 and 1). // 1 is pure white, 0 is pure black. @function luminance($color) { $colors: ( - 'red': red($color), - 'green': green($color), - 'blue': blue($color) + 'red': color.red($color), + 'green': color.green($color), + 'blue': color.blue($color) ); @each $name, $value in $colors { @@ -49,12 +54,12 @@ } @else { $value: ($value + .055) / 1.055; - $value: math-pow($value, 2.4); + $value: math.pow($value, 2.4); } - $colors: map-merge($colors, ($name: $value)); + $colors: map.merge($colors, ($name: $value)); } - @return (map-get($colors, 'red') * .2126) - + (map-get($colors, 'green') * .7152) - + (map-get($colors, 'blue') * .0722); + @return (map.get($colors, 'red') * .2126) + + (map.get($colors, 'green') * .7152) + + (map.get($colors, 'blue') * .0722); } diff --git a/tgui/packages/tgui/styles/interfaces/CameraConsole.scss b/tgui/packages/tgui/styles/interfaces/CameraConsole.scss new file mode 100644 index 0000000000..26fae61bb5 --- /dev/null +++ b/tgui/packages/tgui/styles/interfaces/CameraConsole.scss @@ -0,0 +1,53 @@ +@use '../base.scss'; + +$color-background: rgba(0, 0, 0, 0.33) !default; + +.CameraConsole__left { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: base.em(220px); +} + +.CameraConsole__right { + position: absolute; + top: 0; + bottom: 0; + left: base.em(220px); + right: 0; + background-color: $color-background; +} + +.CameraConsole__toolbar { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2em; + line-height: 2em; + margin: 0.25em 1em 0; +} + +.CameraConsole__toolbarRight { + position: absolute; + top: 0; + right: 0; + height: 2em; + line-height: 2em; + margin: 0.33em 0.5em 0; +} + +.CameraConsole__map { + position: absolute; + top: base.em(26px); + bottom: 0; + left: 0; + right: 0; + margin: 0.5em; + text-align: center; + + .NoticeBox { + margin-top: calc(50% - 2em); + } +} diff --git a/tgui-next/packages/tgui/styles/components/NuclearBomb.scss b/tgui/packages/tgui/styles/interfaces/NuclearBomb.scss similarity index 85% rename from tgui-next/packages/tgui/styles/components/NuclearBomb.scss rename to tgui/packages/tgui/styles/interfaces/NuclearBomb.scss index c0afcfb1f5..255ab7cb3d 100644 --- a/tgui-next/packages/tgui/styles/components/NuclearBomb.scss +++ b/tgui/packages/tgui/styles/interfaces/NuclearBomb.scss @@ -9,11 +9,18 @@ $background-beige: #E8E4C9; .NuclearBomb__displayBox { background-color: #002003; - border: 4px inset $background-beige; + border: 0.167em inset $background-beige; color: #03e017; - font-size: 24px; + font-size: 2em; font-family: monospace; - padding: 6px; + padding: 0.25em; +} + +.NuclearBomb__Button { + outline-width: 0.25rem !important; + border-width: 0.65rem !important; + padding-left: 0 !important; + padding-right: 0 !important; } .NuclearBomb__Button--keypad { diff --git a/tgui/packages/tgui/styles/interfaces/Roulette.scss b/tgui/packages/tgui/styles/interfaces/Roulette.scss new file mode 100644 index 0000000000..04e39db7c6 --- /dev/null +++ b/tgui/packages/tgui/styles/interfaces/Roulette.scss @@ -0,0 +1,100 @@ +@use '../base.scss'; +@use '../colors.scss'; + +.Roulette { + font-family: Palatino; +} + +.Roulette__board { + display: table; + width: 100%; + border-collapse: collapse; + border: 2px solid white; + margin: 0; +} + +.Roulette__board-row { + padding: 0; + margin: 0; +} + +.Roulette__board-cell { + display: table-cell; + padding: 0; + margin: 0; + border: 2px solid white; + font-family: Palatino; + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + } +} + +.Roulette__board-extrabutton { + text-align: center; + font-size: 20px; + font-weight: bold; + height: 28px; + border: none !important; + margin: 0 !important; + padding-top: 4px !important; + color: #FFFFFF !important; +} + +.Roulette__lowertable { + margin-top: 8px; + margin-left: 80px; + margin-right: 80px; + border-collapse: collapse; + border: 2px solid white; + border-spacing: 0; +} + +.Roulette__lowertable--cell { + border: 2px solid white; + padding: 0px; + margin: 0px; +} + +.Roulette__lowertable--betscell { + vertical-align: top; +} + +.Roulette__lowertable--spinresult { + text-align: center; + font-size: 100px; + font-weight: bold; + vertical-align: middle; +} + +.Roulette__lowertable--spinresult-black { + background-color: colors.$black; +} + +.Roulette__lowertable--spinresult-red { + background-color: colors.$red; +} + +.Roulette__lowertable--spinresult-green { + background-color: colors.$green; +} + +.Roulette__lowertable--spinbutton { + margin: 0 !important; + border: none !important; + font-size: 50px; + line-height: 60px !important; + text-align: center; + font-weight: bold; +} + +.Roulette__lowertable--header { + width: 1%; + text-align: center; + font-size: 20px; + font-weight: bold; +} diff --git a/tgui/packages/tgui/styles/layouts/Layout.scss b/tgui/packages/tgui/styles/layouts/Layout.scss new file mode 100644 index 0000000000..7368b24f24 --- /dev/null +++ b/tgui/packages/tgui/styles/layouts/Layout.scss @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use '../base.scss'; + +.Layout, +.Layout * { + // Fancy scrollbar + scrollbar-base-color: color.scale( + base.$color-bg, + $lightness: -25%); + scrollbar-face-color: color.scale( + base.$color-bg, + $lightness: 10%); + scrollbar-3dlight-color: color.scale( + base.$color-bg, + $lightness: 0%); + scrollbar-highlight-color: color.scale( + base.$color-bg, + $lightness: 0%); + scrollbar-track-color: color.scale( + base.$color-bg, + $lightness: -25%); + scrollbar-arrow-color: color.scale( + base.$color-bg, + $lightness: 50%); + scrollbar-shadow-color: color.scale( + base.$color-bg, + $lightness: 10%); +} + +.Layout__content { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + overflow-x: hidden; + overflow-y: hidden; +} + +.Layout__content--scrollable { + overflow-y: scroll; + margin-bottom: 0; +} diff --git a/tgui/packages/tgui/styles/layouts/NtosHeader.scss b/tgui/packages/tgui/styles/layouts/NtosHeader.scss new file mode 100644 index 0000000000..2a429051f5 --- /dev/null +++ b/tgui/packages/tgui/styles/layouts/NtosHeader.scss @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +.NtosHeader__left { + position: absolute; + left: 1em; +} + +.NtosHeader__right { + position: absolute; + right: 1em; +} + +.NtosHeader__icon { + margin-top: -0.75em; + margin-bottom: -0.5em; + vertical-align: middle; +} diff --git a/tgui/packages/tgui/styles/layouts/NtosWindow.scss b/tgui/packages/tgui/styles/layouts/NtosWindow.scss new file mode 100644 index 0000000000..bed4abab53 --- /dev/null +++ b/tgui/packages/tgui/styles/layouts/NtosWindow.scss @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use '../base.scss'; + +.NtosWindow__header { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2em; + line-height: 1.928em; + background-color: rgba(0, 0, 0, 0.5); + font-family: Consolas, monospace; + font-size: base.em(14px); + user-select: none; + -ms-user-select: none; +} + +.NtosWindow__content .Layout__content { + margin-top: 2em; + font-family: Consolas, monospace; + font-size: base.em(14px); +} diff --git a/tgui-next/packages/tgui/styles/components/TitleBar.scss b/tgui/packages/tgui/styles/layouts/TitleBar.scss similarity index 61% rename from tgui-next/packages/tgui/styles/components/TitleBar.scss rename to tgui/packages/tgui/styles/layouts/TitleBar.scss index 08478427e4..4333a54357 100644 --- a/tgui-next/packages/tgui/styles/components/TitleBar.scss +++ b/tgui/packages/tgui/styles/layouts/TitleBar.scss @@ -1,4 +1,11 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; +@use '../base.scss'; +@use '../colors.scss'; $color-text: rgba(255, 255, 255, 0.75) !default; $color-background: #363636 !default; @@ -9,6 +16,7 @@ $color-shadow: rgba(0, 0, 0, 0.1) !default; background-color: $color-background; border-bottom: 1px solid $color-shadow-core; box-shadow: 0 2px 2px $color-shadow; + box-shadow: 0 base.rem(2px) base.rem(2px) $color-shadow; user-select: none; -ms-user-select: none; } @@ -29,9 +37,12 @@ $color-shadow: rgba(0, 0, 0, 0.1) !default; position: absolute; top: 0; left: 46px; + left: base.rem(46px); color: $color-text; font-size: 14px; + font-size: base.rem(14px); line-height: 31px; + line-height: base.rem(31px); white-space: nowrap; } @@ -41,21 +52,19 @@ $color-shadow: rgba(0, 0, 0, 0.1) !default; left: 0; right: 0; height: 32px; + height: base.rem(32px); } .TitleBar__statusIcon { position: absolute; top: 0; left: 12px; + left: base.rem(12px); transition: color 0.5s; font-size: 20px; + font-size: base.rem(20px); line-height: 32px !important; -} - -.TitleBar__minimize { - position: absolute; - top: 6px; - right: 46px; + line-height: base.rem(32px) !important; } .TitleBar__close { @@ -63,8 +72,27 @@ $color-shadow: rgba(0, 0, 0, 0.1) !default; top: -1px; right: 0; width: 45px; + width: base.rem(45px); height: 32px; + height: base.rem(32px); font-size: 20px; + font-size: base.rem(20px); line-height: 31px; + line-height: base.rem(31px); + text-align: center; +} + +.TitleBar__devBuildIndicator { + position: absolute; + top: 6px; + top: base.rem(6px); + right: 52px; + right: base.rem(52px); + min-width: 20px; + min-width: base.rem(20px); + padding: 2px 4px; + padding: base.rem(2px) base.rem(4px); + background-color: rgba(colors.$good, 0.75); + color: #fff; text-align: center; } diff --git a/tgui/packages/tgui/styles/layouts/Window.scss b/tgui/packages/tgui/styles/layouts/Window.scss new file mode 100644 index 0000000000..f67bc7d131 --- /dev/null +++ b/tgui/packages/tgui/styles/layouts/Window.scss @@ -0,0 +1,99 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use '../base.scss'; +@use '../functions.scss' as *; + +.Window { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + color: base.$color-fg; + background-color: base.$color-bg; + background-image: linear-gradient(to bottom, + base.$color-bg-start 0%, + base.$color-bg-end 100%); +} + +.Window__titleBar { + position: fixed; + z-index: 1; + top: 0; + left: 0; + width: 100%; + height: 32px; + height: base.rem(32px); +} + +// Everything after the title bar +.Window__rest { + position: fixed; + top: 32px; + top: base.rem(32px); + bottom: 0; + left: 0; + right: 0; +} + +.Window__contentPadding { + margin: 0.5rem; + // 0.01 is needed to make the scrollbar not appear + // due to rem rendering inaccuracies in IE11. + height: calc(100% - 1.01rem); +} + +.Window__contentPadding:after { + height: 0; +} + +.Layout__content--scrollable .Window__contentPadding:after { + display: block; + content: ''; + height: 0.5rem; +} + +.Window__dimmer { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(lighten(base.$color-bg, 30%), 0.25); + pointer-events: none; +} + +.Window__resizeHandle__se { + position: fixed; + bottom: 0; + right: 0; + width: 20px; + width: base.rem(20px); + height: 20px; + height: base.rem(20px); + cursor: se-resize; +} + +.Window__resizeHandle__s { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 6px; + height: base.rem(6px); + cursor: s-resize; +} + +.Window__resizeHandle__e { + position: fixed; + top: 0; + bottom: 0; + right: 0; + width: 3px; + width: base.rem(3px); + cursor: e-resize; +} diff --git a/tgui-next/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss similarity index 57% rename from tgui-next/packages/tgui/styles/main.scss rename to tgui/packages/tgui/styles/main.scss index 1c46534b6c..060291bce9 100644 --- a/tgui-next/packages/tgui/styles/main.scss +++ b/tgui/packages/tgui/styles/main.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:meta'; @use './base.scss'; @@ -7,33 +12,45 @@ // Atomic classes @include meta.load-css('./atomic/candystripe.scss'); @include meta.load-css('./atomic/color.scss'); -@include meta.load-css('./atomic/display.scss'); -@include meta.load-css('./atomic/margin.scss'); -@include meta.load-css('./atomic/position.scss'); +@include meta.load-css('./atomic/debug-layout.scss'); +@include meta.load-css('./atomic/outline.scss'); @include meta.load-css('./atomic/text.scss'); // Components @include meta.load-css('./components/BlockQuote.scss'); @include meta.load-css('./components/Button.scss'); @include meta.load-css('./components/ColorBox.scss'); +@include meta.load-css('./components/Dimmer.scss'); +@include meta.load-css('./components/Divider.scss'); @include meta.load-css('./components/Dropdown.scss'); @include meta.load-css('./components/FatalError.scss'); @include meta.load-css('./components/Flex.scss'); @include meta.load-css('./components/Input.scss'); +@include meta.load-css('./components/Knob.scss'); @include meta.load-css('./components/LabeledList.scss'); -@include meta.load-css('./components/Layout.scss'); +@include meta.load-css('./components/Modal.scss'); @include meta.load-css('./components/NoticeBox.scss'); -@include meta.load-css('./components/NtosHeader.scss'); -@include meta.load-css('./components/NtosWrapper.scss'); -@include meta.load-css('./components/NuclearBomb.scss'); @include meta.load-css('./components/NumberInput.scss'); @include meta.load-css('./components/ProgressBar.scss'); @include meta.load-css('./components/Section.scss'); +@include meta.load-css('./components/Slider.scss'); @include meta.load-css('./components/Table.scss'); @include meta.load-css('./components/Tabs.scss'); -@include meta.load-css('./components/TitleBar.scss'); +@include meta.load-css('./components/TextArea.scss'); @include meta.load-css('./components/Tooltip.scss'); +// Interfaces +@include meta.load-css('./interfaces/CameraConsole.scss'); +@include meta.load-css('./interfaces/NuclearBomb.scss'); +@include meta.load-css('./interfaces/Roulette.scss'); + +// Layouts +@include meta.load-css('./layouts/Layout.scss'); +@include meta.load-css('./layouts/NtosHeader.scss'); +@include meta.load-css('./layouts/NtosWindow.scss'); +@include meta.load-css('./layouts/TitleBar.scss'); +@include meta.load-css('./layouts/Window.scss'); + // NT Theme .Layout__content { background-image: url('../assets/bg-nanotrasen.svg'); @@ -41,7 +58,3 @@ background-position: center; background-repeat: no-repeat; } - -.action_test { - display: inherit; -} diff --git a/tgui-next/packages/tgui/styles/reset.scss b/tgui/packages/tgui/styles/reset.scss similarity index 68% rename from tgui-next/packages/tgui/styles/reset.scss rename to tgui/packages/tgui/styles/reset.scss index 88c0cc8252..80d2a13780 100644 --- a/tgui-next/packages/tgui/styles/reset.scss +++ b/tgui/packages/tgui/styles/reset.scss @@ -1,7 +1,15 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use './base.scss'; + html, body { box-sizing: border-box; height: 100%; margin: 0; + font-size: base.$font-size; } html { @@ -12,7 +20,6 @@ html { body { overflow: auto; font-family: Verdana, Geneva, sans-serif; - font-size: 12px; } *, *:before, *:after { @@ -23,22 +30,27 @@ h1, h2, h3, h4, h5, h6 { display: block; margin: 0; padding: 6px 0; + padding: 0.5rem 0; } h1 { font-size: 18px; + font-size: 1.5rem; } h2 { font-size: 16px; + font-size: 1.333rem; } h3 { font-size: 14px; + font-size: 1.167rem; } h4 { font-size: 12px; + font-size: 1rem; } td, th { diff --git a/tgui/packages/tgui/styles/themes/abductor.scss b/tgui/packages/tgui/styles/themes/abductor.scss new file mode 100644 index 0000000000..c0d339d264 --- /dev/null +++ b/tgui/packages/tgui/styles/themes/abductor.scss @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use 'sass:meta'; + +@use '../colors.scss' with ( + $primary: #ad2350, + $fg-map-keys: (), + $bg-map-keys: (), +); +@use '../base.scss' with ( + $color-bg: #2a314a, + $color-bg-grad-spread: 6%, + $border-radius: 2px, +); + +.theme-abductor { + // Atomic classes + @include meta.load-css('../atomic/color.scss'); + + // Components + @include meta.load-css('../components/Button.scss', $with: ( + 'color-default': colors.$primary, + 'color-disabled': #363636, + 'color-selected': #465899, + 'color-caution': #be6209, + 'color-danger': #9a9d00, + )); + @include meta.load-css('../components/Input.scss', $with: ( + 'border-color': #404b6e, + )); + @include meta.load-css('../components/NoticeBox.scss', $with: ( + 'color-background': #a82d55, + )); + @include meta.load-css('../components/NumberInput.scss', $with: ( + 'border-color': #404b6e, + )); + @include meta.load-css('../components/ProgressBar.scss', $with: ( + 'color-background': rgba(0, 0, 0, 0.5), + )); + @include meta.load-css('../components/Section.scss'); + @include meta.load-css('../components/Tooltip.scss', $with: ( + 'color-background': #a82d55, + )); + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( + 'color-background': #9e1b46, + )); + + .Layout__content { + background-image: none; + } +} diff --git a/tgui-next/packages/tgui/styles/themes/cardtable.scss b/tgui/packages/tgui/styles/themes/cardtable.scss similarity index 73% rename from tgui-next/packages/tgui/styles/themes/cardtable.scss rename to tgui/packages/tgui/styles/themes/cardtable.scss index 67ae46c220..45427076ba 100644 --- a/tgui-next/packages/tgui/styles/themes/cardtable.scss +++ b/tgui/packages/tgui/styles/themes/cardtable.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; @use 'sass:meta'; @@ -9,7 +14,7 @@ @use '../base.scss' with ( $color-bg: #117039, $color-bg-grad-spread: 0%, - $border-radius: 0px, + $border-radius: 0, ); //Made for the roulette table, probably requires a bunch of manual hacks to work for anything else @@ -25,22 +30,22 @@ 'color-caution': #be6209, 'color-danger': #9a9d00, )); - @include meta.load-css('../components/Layout.scss'); @include meta.load-css('../components/NumberInput.scss', $with: ( - 'border-color': #FFFFFF, + 'border-color': #fff, )); - @include meta.load-css('../components/ProgressBar.scss', $with: ( 'color-background': rgba(0, 0, 0, 0.5), )); @include meta.load-css('../components/Section.scss'); - @include meta.load-css('../components/TitleBar.scss', $with: ( + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( 'color-background': #381608, )); .Button { - border-color: #FFFFFF; - border-width: 2px; - border-style: solid; + border: base.em(2px) solid #fff; } } diff --git a/tgui/packages/tgui/styles/themes/clockcult.scss b/tgui/packages/tgui/styles/themes/clockcult.scss new file mode 100644 index 0000000000..7f3afd74be --- /dev/null +++ b/tgui/packages/tgui/styles/themes/clockcult.scss @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2020 Arturlang + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use 'sass:meta'; + +@use '../colors.scss' with ( + $primary: #B18B25, + $good: #CFBA47, + $average: #5F380E, + $bad: #5F380E, + $fg-map-keys: (), + $bg-map-keys: (), +); +@use '../base.scss' with ( + $color-bg: #c9b12a, + $color-bg-grad-spread: 6%, + $border-radius: 2px, +); + +.theme-clockcult { + // Atomic classes + @include meta.load-css('../atomic/color.scss'); + + // Components + @include meta.load-css('../components/Button.scss', $with: ( + 'color-default': #5F380E, //wrong. + 'color-disabled': #2D1400, + 'color-selected': #CFBA47, + 'color-caution': #FFAE42, //yellow-orange + 'color-danger': #f0ff23, //yellow + )); + @include meta.load-css('../components/Input.scss', $with: ( + 'border-color': #CFBA47, + )); + @include meta.load-css('../components/NoticeBox.scss', $with: ( + 'color-background': #886a09, + )); + @include meta.load-css('../components/NumberInput.scss', $with: ( + 'border-color': #CFBA47, + )); + @include meta.load-css('../components/ProgressBar.scss', $with: ( + 'color-background': #2D1400, // 'border-color': #170800 + )); + @include meta.load-css('../components/Section.scss'); + @include meta.load-css('../components/Tooltip.scss', $with: ( + 'color-background': #2D1400, + )); + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( + 'color-text': #CFBA47, + 'color-background': #2D1400, // 'border-color': #170800 + 'color-shadow-core': #170800, + )); + + .Layout__content { + background-image: none; // fa-gear with a color of #CFBA47 + } +} diff --git a/tgui-next/packages/tgui/styles/themes/hackerman.scss b/tgui/packages/tgui/styles/themes/hackerman.scss similarity index 70% rename from tgui-next/packages/tgui/styles/themes/hackerman.scss rename to tgui/packages/tgui/styles/themes/hackerman.scss index 73745ce6c8..719f35f45f 100644 --- a/tgui-next/packages/tgui/styles/themes/hackerman.scss +++ b/tgui/packages/tgui/styles/themes/hackerman.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; @use 'sass:meta'; @@ -9,7 +14,6 @@ @use '../base.scss' with ( $color-bg: #121b12, $color-bg-grad-spread: 0%, - $border-radius: 2px, ); .theme-hackerman { @@ -25,9 +29,13 @@ @include meta.load-css('../components/Input.scss', $with: ( 'border-color': colors.$primary, )); - @include meta.load-css('../components/Layout.scss'); + @include meta.load-css('../components/Modal.scss'); @include meta.load-css('../components/Section.scss'); - @include meta.load-css('../components/TitleBar.scss', $with: ( + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( 'color-background': #223d22, )); @@ -37,10 +45,10 @@ .Button { font-family: monospace; - border-width: 2px; + border-width: base.em(2px); border-style: outset; border-color: #00AA00; - outline: 1px solid rgb(0, 122, 0); + outline: base.em(1px) solid rgb(0, 122, 0); } .candystripe:nth-child(odd) { diff --git a/tgui/packages/tgui/styles/themes/malfunction.scss b/tgui/packages/tgui/styles/themes/malfunction.scss new file mode 100644 index 0000000000..3389785491 --- /dev/null +++ b/tgui/packages/tgui/styles/themes/malfunction.scss @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use 'sass:meta'; + +@use '../colors.scss' with ( + $primary: #910101, + $fg-map-keys: (), + $bg-map-keys: (), +); +@use '../base.scss' with ( + $color-bg: #1b3443, + $color-bg-grad-spread: 6%, +); + +.theme-malfunction { + // Atomic classes + @include meta.load-css('../atomic/color.scss'); + + // Components + @include meta.load-css('../components/Button.scss', $with: ( + 'color-default': colors.$primary, + 'color-disabled': #363636, + 'color-selected': #1e5881, + 'color-caution': #be6209, + 'color-danger': #9a9d00, + )); + @include meta.load-css('../components/Input.scss', $with: ( + 'border-color': #910101, + )); + @include meta.load-css('../components/NoticeBox.scss', $with: ( + 'color-background': #1a3f57, + )); + @include meta.load-css('../components/NumberInput.scss', $with: ( + 'border-color': #910101, + )); + @include meta.load-css('../components/ProgressBar.scss', $with: ( + 'color-background': rgba(0, 0, 0, 0.5), + )); + @include meta.load-css('../components/Section.scss'); + @include meta.load-css('../components/Tooltip.scss', $with: ( + 'color-background': #235577, + )); + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( + 'color-background': #1a3f57, + )); + + .Layout__content { + background-image: none; + } +} diff --git a/tgui/packages/tgui/styles/themes/neutral.scss b/tgui/packages/tgui/styles/themes/neutral.scss new file mode 100644 index 0000000000..05eab7537c --- /dev/null +++ b/tgui/packages/tgui/styles/themes/neutral.scss @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + + @use 'sass:color'; + @use 'sass:meta'; + + $neutral: #ffb300; + + @use '../colors.scss' with ( + $primary: $neutral, + $fg-map-keys: (), + $bg-map-keys: (), + ); + @use '../base.scss' with ( + $color-bg: color.scale($neutral, $lightness: -40%), + $color-bg-grad-spread: 6%, + ); + + .theme-neutral { + // Components + @include meta.load-css('../components/Button.scss', $with: ( + 'color-default': color.scale($neutral, $lightness: -30%), + 'color-transparent-text': color.scale($neutral, $lightness: 30%), + )); + @include meta.load-css('../components/ProgressBar.scss', $with: ( + 'color-default': $neutral, + 'color-background': rgba(0, 0, 0, 0.5), + )); + @include meta.load-css('../components/Section.scss'); + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( + 'color-background': color.scale($neutral, $lightness: -25%), + )); + + .Layout__content { + background-image: url('../../assets/bg-neutral.svg'); + } + } diff --git a/tgui-next/packages/tgui/styles/themes/ntos.scss b/tgui/packages/tgui/styles/themes/ntos.scss similarity index 72% rename from tgui-next/packages/tgui/styles/themes/ntos.scss rename to tgui/packages/tgui/styles/themes/ntos.scss index c42664fe76..4891b4d163 100644 --- a/tgui-next/packages/tgui/styles/themes/ntos.scss +++ b/tgui/packages/tgui/styles/themes/ntos.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; @use 'sass:meta'; @@ -9,7 +14,6 @@ $nanotrasen: #384e68; ); @use '../base.scss' with ( $color-bg: color.scale($nanotrasen, $lightness: -45%), - $border-radius: 2px, ); .theme-ntos { @@ -17,16 +21,17 @@ $nanotrasen: #384e68; @include meta.load-css('../components/Button.scss', $with: ( 'color-default': $nanotrasen, 'color-transparent-text': rgba(227, 240, 255, 0.75), - 'border-radius': base.$border-radius, )); - @include meta.load-css('../components/Layout.scss'); @include meta.load-css('../components/ProgressBar.scss', $with: ( 'color-default': $nanotrasen, 'color-background': rgba(0, 0, 0, 0.5), - 'border-radius': base.$border-radius, )); @include meta.load-css('../components/Section.scss'); - @include meta.load-css('../components/TitleBar.scss', $with: ( + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( 'color-background': color.scale($nanotrasen, $lightness: -25%), )); } diff --git a/tgui/packages/tgui/styles/themes/paper.scss b/tgui/packages/tgui/styles/themes/paper.scss new file mode 100644 index 0000000000..cfbe451110 --- /dev/null +++ b/tgui/packages/tgui/styles/themes/paper.scss @@ -0,0 +1,171 @@ +/** + * Copyright (c) 2020 Paul Bruner + * SPDX-License-Identifier: MIT + */ + +@use 'sass:color'; +@use 'sass:meta'; + +@use '../colors.scss' with ( + $primary: #ffffff, + $bg-lightness: -25%, + $fg-lightness: -10%, + // Commenting out color maps will adjust all colors based on the lightness + // settings above, but will add extra 10KB to the theme. + $fg-map-keys: (), + $bg-map-keys: (), +); +@use '../base.scss' with ( + $color-fg: #000000, + $color-bg: #ffffff, + $color-bg-grad-spread: 0%, +); + +$font-size: 24px; + +// A fat warning to anyone who wants to use this: this only half works. +// It was made almost purely for the nuke ui, and requires a good amount of manual hacks to get it working as intended. +.theme-paper { + // Atomic classes + @include meta.load-css('../atomic/color.scss'); + + // Components + @include meta.load-css('../components/Tabs.scss'); + @include meta.load-css('../components/Section.scss', $with: ( + 'color-background': rgba(0, 0, 0, 0.1), + 'color-shadow': rgba(0, 0, 0, 0.2), + )); + @include meta.load-css('../components/Button.scss', $with: ( + 'color-default': #E8E4C9, + 'color-disabled': #363636, + 'color-selected': #9d0808, + 'color-caution': #be6209, + 'color-danger': #9a9d00, + 'color-transparent-text': rgba(0, 0, 0, 0.5), + )); + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( + 'color-text': rgba(0, 0, 0, 0.75), + 'color-background': base.$color-bg, + 'color-shadow-core': rgba(0, 0, 0, 0.25), + )); + + .PaperInput { + position: relative; + display: inline-block; + width: 120px; + border: none; + background: transparent; + border-bottom: 1px solid #000; + outline: none; + background-color:rgba(255, 255, 62, 0.8); + padding: 0 4px; + margin-right: 2px; + line-height: 17px; + overflow: visible; + } + + .PaperInput__baseline { + display: inline-block; + color: transparent; + } + + .PaperInput__input { + display: block; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + border: 0; + outline: 0; + width: 100%; + font-size: 12px; + line-height: 17px; + height: 17px; + margin: 0; + padding: 0 6px; + font-family: Verdana, sans-serif; + background-color: transparent; + color: #fff; + color: inherit; + + &:-ms-input-placeholder { + font-style: italic; + color: #777; + color: rgba(255, 255, 255, 0.45); + } + } + + .Layout__content { + background-image: none; + } + + .Window { + background-image: none; + color: base.$color-fg; + } + + .paper-text { + input:disabled { + position: relative; + display: inline-block; + border: none; + background: transparent; + border-bottom: 1px solid #000; + outline: none; + background-color:rgba(255, 255, 62, 0.8); + padding: 0 4px; + margin-right: 2px; + line-height: 17px; + overflow: visible; + } + + input { + position: relative; + display: inline-block; + border: none; + background: transparent; + border-bottom: 1px solid #000; + outline: none; + background-color:rgba(255, 255, 62, 0.8); + padding: 0 4px; + margin-right: 2px; + line-height: 17px; + overflow: visible; + } + } + + .paper-field { + position: relative; + display: inline-block; + + border: none; + background: transparent; + border-bottom: 1px solid #000; + outline: none; + background-color:rgba(255, 255, 62, 0.8); + padding: 0 4px; + margin-right: 2px; + line-height: 17px; + overflow: visible; + + input:disabled { + position: relative; + display: inline-block; + + border: none; + background: transparent; + border-bottom: 1px solid #000; + outline: none; + background-color:rgba(255, 255, 62, 0.8); + padding: 0 4px; + margin-right: 2px; + line-height: 17px; + overflow: visible; + } + } +} diff --git a/tgui-next/packages/tgui/styles/themes/retro.scss b/tgui/packages/tgui/styles/themes/retro.scss similarity index 74% rename from tgui-next/packages/tgui/styles/themes/retro.scss rename to tgui/packages/tgui/styles/themes/retro.scss index 2c69e1d04d..da666a3638 100644 --- a/tgui-next/packages/tgui/styles/themes/retro.scss +++ b/tgui/packages/tgui/styles/themes/retro.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; @use 'sass:meta'; @@ -9,7 +14,7 @@ @use '../base.scss' with ( $color-bg: #E8E4C9, $color-bg-grad-spread: 0%, - $border-radius: 0px, + $border-radius: 0, ); // A fat warning to anyone who wants to use this: this only half works. @@ -26,22 +31,23 @@ 'color-caution': #be6209, 'color-danger': #9a9d00, )); - @include meta.load-css('../components/Layout.scss'); @include meta.load-css('../components/ProgressBar.scss', $with: ( 'color-background': rgba(0, 0, 0, 0.5), )); @include meta.load-css('../components/Section.scss'); - @include meta.load-css('../components/TitleBar.scss', $with: ( + + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( 'color-background': #585337, )); .Button { font-family: monospace; color: #161613; - border-width: 8px; - border-style: outset; - border-color: #E8E4C9; - outline: 3px solid #161613; + border: base.em(2px) outset #E8E4C9; + outline: base.em(1px) solid #161613; } .Layout__content { diff --git a/tgui-next/packages/tgui/styles/themes/syndicate.scss b/tgui/packages/tgui/styles/themes/syndicate.scss similarity index 80% rename from tgui-next/packages/tgui/styles/themes/syndicate.scss rename to tgui/packages/tgui/styles/themes/syndicate.scss index 35cfedc421..eca28f8aba 100644 --- a/tgui-next/packages/tgui/styles/themes/syndicate.scss +++ b/tgui/packages/tgui/styles/themes/syndicate.scss @@ -1,3 +1,8 @@ +/** + * Copyright (c) 2020 Aleksej Komarov + * SPDX-License-Identifier: MIT + */ + @use 'sass:color'; @use 'sass:meta'; @@ -9,7 +14,6 @@ @use '../base.scss' with ( $color-bg: #550202, $color-bg-grad-spread: 6%, - $border-radius: 2px, ); .theme-syndicate { @@ -27,10 +31,8 @@ @include meta.load-css('../components/Input.scss', $with: ( 'border-color': #87ce87, )); - @include meta.load-css('../components/Layout.scss'); @include meta.load-css('../components/NoticeBox.scss', $with: ( - 'color-first': #750000, - 'color-second': #910101, + 'color-background': #910101, )); @include meta.load-css('../components/NumberInput.scss', $with: ( 'border-color': #87ce87, @@ -39,13 +41,17 @@ 'color-background': rgba(0, 0, 0, 0.5), )); @include meta.load-css('../components/Section.scss'); - @include meta.load-css('../components/TitleBar.scss', $with: ( - 'color-background': #910101, - )); @include meta.load-css('../components/Tooltip.scss', $with: ( 'color-background': #4a0202, )); + // Layouts + @include meta.load-css('../layouts/Layout.scss'); + @include meta.load-css('../layouts/Window.scss'); + @include meta.load-css('../layouts/TitleBar.scss', $with: ( + 'color-background': #910101, + )); + .Layout__content { background-image: url('../../assets/bg-syndicate.svg'); } diff --git a/tgui-next/packages/tgui/webpack.config.js b/tgui/packages/tgui/webpack.config.js similarity index 77% rename from tgui-next/packages/tgui/webpack.config.js rename to tgui/packages/tgui/webpack.config.js index 3389ab3b96..c9ed58e065 100644 --- a/tgui-next/packages/tgui/webpack.config.js +++ b/tgui/packages/tgui/webpack.config.js @@ -1,17 +1,26 @@ +/** + * @file + * @copyright 2020 Aleksej Komarov + * @license MIT + */ + const webpack = require('webpack'); const path = require('path'); const BuildNotifierPlugin = require('webpack-build-notifier'); const ExtractCssChunks = require('extract-css-chunks-webpack-plugin'); -const SASS_FUNCTIONS = { - // Power function polyfill - 'math-pow($number, $exp)': (number, exp) => { - const sass = require('sass'); - return new sass.types.Number(Math.pow( - number.getValue(), - exp.getValue())); - }, -}; +const createStats = verbose => ({ + assets: verbose, + builtAt: verbose, + cached: false, + children: false, + chunks: false, + colors: true, + hash: false, + timings: verbose, + version: verbose, + modules: false, +}); module.exports = (env = {}, argv) => { const config = { @@ -19,12 +28,6 @@ module.exports = (env = {}, argv) => { context: __dirname, entry: { tgui: [ - path.resolve(__dirname, './styles/main.scss'), - path.resolve(__dirname, './styles/themes/cardtable.scss'), - path.resolve(__dirname, './styles/themes/ntos.scss'), - path.resolve(__dirname, './styles/themes/hackerman.scss'), - path.resolve(__dirname, './styles/themes/retro.scss'), - path.resolve(__dirname, './styles/themes/syndicate.scss'), path.resolve(__dirname, './index.js'), ], }, @@ -75,7 +78,7 @@ module.exports = (env = {}, argv) => { { loader: ExtractCssChunks.loader, options: { - hot: argv.hot, + hmr: argv.hot, }, }, { @@ -84,11 +87,7 @@ module.exports = (env = {}, argv) => { }, { loader: 'sass-loader', - options: { - sassOptions: { - functions: SASS_FUNCTIONS, - }, - }, + options: {}, }, ], }, @@ -110,6 +109,7 @@ module.exports = (env = {}, argv) => { hints: false, }, devtool: false, + stats: createStats(true), plugins: [ new webpack.EnvironmentPlugin({ NODE_ENV: env.NODE_ENV || argv.mode || 'development', @@ -142,11 +142,9 @@ module.exports = (env = {}, argv) => { extractComments: false, terserOptions: { ie8: true, - // mangle: false, output: { ascii_only: true, - // beautify: true, - // indent_level: 2, + comments: false, }, }, }), @@ -172,31 +170,20 @@ module.exports = (env = {}, argv) => { if (argv.mode !== 'production') { config.plugins = [ ...config.plugins, - new BuildNotifierPlugin(), + new BuildNotifierPlugin({ + suppressSuccess: true, + }), ]; if (argv.hot) { config.plugins.push(new webpack.HotModuleReplacementPlugin()); } config.devtool = 'cheap-module-source-map'; config.devServer = { - // Informational flags progress: false, quiet: false, noInfo: false, - // Fine-grained logging control clientLogLevel: 'silent', - stats: { - assets: false, - builtAt: false, - cached: false, - children: false, - chunks: false, - colors: true, - hash: false, - timings: false, - version: false, - modules: false, - }, + stats: createStats(false), }; } diff --git a/tgui/reload.bat b/tgui/reload.bat deleted file mode 100644 index d45411f006..0000000000 --- a/tgui/reload.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off -REM Get the documents folder from the registry. -@echo off -for /f "tokens=3*" %%p in ('REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Personal') do ( - set DocumentsFolder=%%p -) -REM Copy to tmp subdirectories -FOR /D %%G in ("%DocumentsFolder%\BYOND\cache\tmp*") DO (cmd /c copy assets\* %%G /y) \ No newline at end of file diff --git a/tgui/src/.babelrc b/tgui/src/.babelrc deleted file mode 100644 index f51992c936..0000000000 --- a/tgui/src/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "presets": [ - "es2015-loose" - ], - "plugins": [ - "external-helpers" - ] -} diff --git a/tgui/src/components/bar.ract b/tgui/src/components/bar.ract deleted file mode 100644 index f4d18125ef..0000000000 --- a/tgui/src/components/bar.ract +++ /dev/null @@ -1,16 +0,0 @@ - - -
    -
    - {{yield}} -
    diff --git a/tgui/src/components/bar.styl b/tgui/src/components/bar.styl deleted file mode 100644 index 0e2b52cda8..0000000000 --- a/tgui/src/components/bar.styl +++ /dev/null @@ -1,32 +0,0 @@ -context = selector() - -.bar - display: inline-block - position: relative - vertical-align: middle - width: 100% - height: 20px - line-height: @height - 3px - padding: 1px - - border: 1px solid bar-color-border - background: bar-color-background - - .barText - @extend {context} $fontReset - position: absolute - top: 0 - right: 3px - - .barFill - display: block - height: 100% - - transition: background-color 1s - background-color: bar-color-normal - &.good - background-color: bar-color-good - &.average - background-color: bar-color-average - &.bad - background-color: bar-color-bad diff --git a/tgui/src/components/button.ract b/tgui/src/components/button.ract deleted file mode 100644 index b918601e3f..0000000000 --- a/tgui/src/components/button.ract +++ /dev/null @@ -1,81 +0,0 @@ - - - - {{#if icon}} - - {{/if}} - {{#if icon_stack}} - {{{iconStackToHTML(icon_stack)}}} - {{/if}} - {{yield}} - diff --git a/tgui/src/components/button.styl b/tgui/src/components/button.styl deleted file mode 100644 index 36574fb30b..0000000000 --- a/tgui/src/components/button.styl +++ /dev/null @@ -1,56 +0,0 @@ -context = selector() - -buttoncolor(selector, color) - &.{selector} - transition: background-color 0.5s - background-color: color - &.active:hover, - &.active:focus - transition: background-color 0.25s - background-color: lighten(color, button-lighten-hover) - outline: 0 - - if selector is not 'disabled' - &:not(.active) - background-image: repeating-linear-gradient( - -45deg, - color, - color 1px, - button-color-disabled 1px, - button-color-disabled 2px - ) - -span.button - @extend {context} $fontReset - display: inline-block - vertical-align: middle - min-height: 20px - line-height: @min-height - 3px - padding: 0 5px - white-space: nowrap - - border: 1px solid button-color-border - - .fa - padding-right: 2px - - buttoncolor(normal, button-color-normal) - buttoncolor(disabled, button-color-disabled) - buttoncolor(selected, button-color-selected) - buttoncolor(toggle, button-color-selected) - buttoncolor(caution, button-color-caution) - buttoncolor(danger, button-color-danger) - - &.gridable - width: 125px - margin: 2px 0 - &.center - text-align: center - width:75px -span:not(.button) + span.button - margin-left: 5px - -span.button + span:not(.button) - margin-left: 5px - - diff --git a/tgui/src/components/display.ract b/tgui/src/components/display.ract deleted file mode 100644 index 2b37a0235d..0000000000 --- a/tgui/src/components/display.ract +++ /dev/null @@ -1,13 +0,0 @@ -
    - {{#if title}} -
    -

    {{title}}

    - {{#if button}} -
    {{yield button}}
    - {{/if}} -
    - {{/if}} -
    - {{yield}} -
    -
    diff --git a/tgui/src/components/display.styl b/tgui/src/components/display.styl deleted file mode 100644 index 3edd9ef100..0000000000 --- a/tgui/src/components/display.styl +++ /dev/null @@ -1,33 +0,0 @@ -div.display - width: 100% - padding: 4px - margin: 6px 0 - - &.tabular - padding 0px - margin 0px - - background-color: display-color-background // Transparent background. - box-shadow: inset 0 0 5px display-color-shadow - - header - display: block - position: relative - width: 100% - padding: 0 4px - margin-bottom: 6px - - color: display-color-title - - border-bottom: rule-size solid rule-color-normal - - .buttonRight - position: absolute - bottom: 6px - right: 4px - - article - display: table - width: 100% - - border-collapse: collapse; diff --git a/tgui/src/components/input.ract b/tgui/src/components/input.ract deleted file mode 100644 index 8114cead81..0000000000 --- a/tgui/src/components/input.ract +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/tgui/src/components/input.styl b/tgui/src/components/input.styl deleted file mode 100644 index c9c491146b..0000000000 --- a/tgui/src/components/input.styl +++ /dev/null @@ -1,19 +0,0 @@ -input - display: inline-block - vertical-align: middle - height: 20px - line-height: @height - 3px - padding: 0 5px - white-space: nowrap - - color: input-color-text - background-color: input-color-background - border: 1px solid input-color-border - - &.number - width: 35px - &::placeholder - color: input-color-placeholder - &::-ms-clear - display: none - diff --git a/tgui/src/components/linegraph.ract b/tgui/src/components/linegraph.ract deleted file mode 100644 index a2c20a0c3b..0000000000 --- a/tgui/src/components/linegraph.ract +++ /dev/null @@ -1,88 +0,0 @@ - - - - - {{#graph({data: points, xaccessor: xaccessor, yaccessor: yaccessor, width: width, height: height})}} - {{#each xaxis}} - - {{#if @index % 2 == 0}} - {{(size - .) * xfactor}} {{xunit}} - {{/if}} - {{/each}} - {{#each yaxis}} - - {{. * yfactor}} {{yunit}} - {{/each}} - {{#each curves:curve}} - - {{/each}} - {{#each curves:curve}} - - {{/each}} - {{#each curves:curve}} - {{#each line.path.points():count}} - - {{/each}} - {{/each}} - {{#each curves:curve}} - {{#each line.path.points():count}} - {{#if selected == count }} - - {{item[count].y * yfactor}} {{yunit}} @ {{(size - item[count].x) * xfactor}} {{xunit}} - - {{/if}} - {{/each}} - {{/each}} - {{#each curves:curve}} - - - {{legend[curve]}} - - {{/each}} - {{/graph}} - - diff --git a/tgui/src/components/linegraph.styl b/tgui/src/components/linegraph.styl deleted file mode 100644 index a3226b28b2..0000000000 --- a/tgui/src/components/linegraph.styl +++ /dev/null @@ -1,2 +0,0 @@ -svg.linegraph - overflow: hidden diff --git a/tgui/src/components/notice.ract b/tgui/src/components/notice.ract deleted file mode 100644 index c23c27b122..0000000000 --- a/tgui/src/components/notice.ract +++ /dev/null @@ -1,3 +0,0 @@ -
    - {{yield}} -
    diff --git a/tgui/src/components/notice.styl b/tgui/src/components/notice.styl deleted file mode 100644 index 10ea60a953..0000000000 --- a/tgui/src/components/notice.styl +++ /dev/null @@ -1,27 +0,0 @@ -div.notice - margin: 8px 0 - padding: 4px - - box-shadow: none - - color: text-color-inverse - font-weight: bold - font-style: italic - - background-color: notice-color-first - background-image: repeating-linear-gradient( - -45deg, - notice-color-first, - notice-color-first 10px, - notice-color-second 10px, - notice-color-second 20px - ) - - .label - color: text-color-inverse - - .content:only-of-type - padding: 0 - - hr - background-color: rule-color-dark diff --git a/tgui/src/components/resize.ract b/tgui/src/components/resize.ract deleted file mode 100644 index f98b3c628f..0000000000 --- a/tgui/src/components/resize.ract +++ /dev/null @@ -1,29 +0,0 @@ - - -{{#if config.fancy}} -
    -{{/if}} diff --git a/tgui/src/components/resize.styl b/tgui/src/components/resize.styl deleted file mode 100644 index f5f5fe37aa..0000000000 --- a/tgui/src/components/resize.styl +++ /dev/null @@ -1,12 +0,0 @@ -div.resize - position: fixed - bottom: 0 - right: 0 - width: 0 - height: 0 - - border-style: solid; - border-width: 0 0 45px 45px; - border-color: transparent transparent resize-color transparent - - transform: rotate(360deg) diff --git a/tgui/src/components/section.ract b/tgui/src/components/section.ract deleted file mode 100644 index d229d2c454..0000000000 --- a/tgui/src/components/section.ract +++ /dev/null @@ -1,12 +0,0 @@ -
    - {{#if label}} - {{label}}: - {{/if}} - {{#if nowrap}} - {{yield}} - {{else}} -
    - {{yield}} -
    - {{/if}} -
    diff --git a/tgui/src/components/section.styl b/tgui/src/components/section.styl deleted file mode 100644 index 6784724b9e..0000000000 --- a/tgui/src/components/section.styl +++ /dev/null @@ -1,44 +0,0 @@ -/$cell - display: table-cell - margin: 0 - text-align: left - vertical-align: middle - padding: 3px 2px - -section - display: table-row - width: 100% - - &:not(:first-child) - padding-top: 4px - - &.candystripe:nth-child(even) - background-color: section-color-candystripe - - .label - @extend $cell - width: 1% - padding-right: 32px - white-space: nowrap - - color: section-color-label - - .content - @extend $cell - &:not(:last-child) - padding-right: 16px - - .line - @extend $cell - width: 100% - - .cell - @extend $cell - &:not(:first-child) - text-align: center - padding-top: 0px - span.button - width: 75px - &:not(:last-child) - padding-right: 4px - \ No newline at end of file diff --git a/tgui/src/components/subdisplay.ract b/tgui/src/components/subdisplay.ract deleted file mode 100644 index 8d6cd641f9..0000000000 --- a/tgui/src/components/subdisplay.ract +++ /dev/null @@ -1,11 +0,0 @@ -
    - {{#if title}} -
    -

    {{title}}

    - {{#if button}}{{yield button}}{{/if}} -
    - {{/if}} -
    - {{yield}} -
    -
    diff --git a/tgui/src/components/subdisplay.styl b/tgui/src/components/subdisplay.styl deleted file mode 100644 index 11420ecba7..0000000000 --- a/tgui/src/components/subdisplay.styl +++ /dev/null @@ -1,11 +0,0 @@ -context = selector() - -div.subdisplay - width: 100% - margin: 0 - - header - @extend {context} div.display header - - article - @extend {context} div.display article diff --git a/tgui/src/components/tabs.ract b/tgui/src/components/tabs.ract deleted file mode 100644 index 2a7db40a51..0000000000 --- a/tgui/src/components/tabs.ract +++ /dev/null @@ -1,27 +0,0 @@ - - - - -
    - {{#each tabs}} - {{.}} - {{/each}} -
    - - {{>content}} - diff --git a/tgui/src/components/tabs/tab.ract b/tgui/src/components/tabs/tab.ract deleted file mode 100644 index b02bba5c20..0000000000 --- a/tgui/src/components/tabs/tab.ract +++ /dev/null @@ -1,3 +0,0 @@ -{{#if shown}} - {{yield}} -{{/if}} diff --git a/tgui/src/components/titlebar.ract b/tgui/src/components/titlebar.ract deleted file mode 100644 index 786479f148..0000000000 --- a/tgui/src/components/titlebar.ract +++ /dev/null @@ -1,78 +0,0 @@ - - -
    - - {{yield}} - {{#if config.fancy}} - - - {{else}} - - - {{/if}} -
    diff --git a/tgui/src/components/titlebar.styl b/tgui/src/components/titlebar.styl deleted file mode 100644 index fd7bb230e1..0000000000 --- a/tgui/src/components/titlebar.styl +++ /dev/null @@ -1,65 +0,0 @@ -context = selector() - -$titleButton - display: inline-block - position: relative - padding: 7px // To make a bigger clickable area. - margin: -7px - - color: titlebar-color-button; - - &:hover - color: lighten(titlebar-color-button, button-lighten-hover) - -header.titlebar - position: fixed; - z-index: 1 - top: 0; - left: 0; - width: 100%; - height: 32px; - - background-color: titlebar-color-background - border-bottom: 1px solid titlebar-color-coreshadow - box-shadow: 0 3px 3px titlebar-color-shadow - - .statusicon - position: absolute - top: 4px - left: 12px - transition: color 0.5s - - .title - position: absolute - top: 6px - left: 46px - - color: titlebar-color-text - font-size: 16px - white-space: nowrap - - .minimize - @extend {context} $titleButton - position: absolute - top: 6px - right: 46px - .close - @extend {context} $titleButton - position: absolute - top: 4px - right: 12px - -header.titlebar - .statusicon.no-icons - font-size: 20px - &::after - content: "O" - .minimize.no-icons - top: -2px - font-size: 20px - &::after - content: "—" - .close.no-icons - font-size: 20px - &::after - content: "X" diff --git a/tgui/src/components/warnings.ract b/tgui/src/components/warnings.ract deleted file mode 100644 index f483123c55..0000000000 --- a/tgui/src/components/warnings.ract +++ /dev/null @@ -1,47 +0,0 @@ - - - -{{#if config.fancy && ie && ie < 11}} - - You have an old (IE{{ie}}), end-of-life (click 'EOL Info' for more information) version of Internet Explorer installed.
    - To upgrade, click 'Upgrade IE' to download IE11 from Microsoft.
    - If you are unable to upgrade directly, click 'IE VMs' to download a VM with IE11 or Edge from Microsoft.
    - Otherwise, click 'No Frills' below to disable potentially incompatible features (and this message). -
    - No Frills - - Upgrade IE - - IE VMs - - EOL Info - Debug Info - {{#if debug}} -
    - Detected: IE{{ie}}
    - User Agent: {{userAgent}} - {{/if}} -
    -{{/if}} diff --git a/tgui/src/images/nanotrasen.svg b/tgui/src/images/nanotrasen.svg deleted file mode 100644 index d21b9f0a2a..0000000000 --- a/tgui/src/images/nanotrasen.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/tgui/src/images/syndicate.svg b/tgui/src/images/syndicate.svg deleted file mode 100644 index c2863b790d..0000000000 --- a/tgui/src/images/syndicate.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/tgui/src/interfaces/ai_airlock.ract b/tgui/src/interfaces/ai_airlock.ract deleted file mode 100644 index 6f6c92967d..0000000000 --- a/tgui/src/interfaces/ai_airlock.ract +++ /dev/null @@ -1,131 +0,0 @@ - - - - - {{data.power.main ? "Online" : "Offline"}} - {{#if !data.wires.main_1 || !data.wires.main_2}} - [ Wires have been cut ] - {{else}} - {{#if data.power.main_timeleft > 0}} - [ {{data.power.main_timeleft}} seconds left ] - {{/if}} - {{/if}} -
    - Disrupt -
    -
    - - {{data.power.backup ? "Online" : "Offline"}} - {{#if !data.wires.backup_1 || !data.wires.backup_2}} - [ Wires have been cut ] - {{else}} - {{#if data.power.backup_timeleft > 0}} - [ {{data.power.backup_timeleft}} seconds left ] - {{/if}} - {{/if}} -
    - Disrupt -
    -
    - - {{data.shock == 2 ? "Safe" : "Electrified"}} - {{#if !data.wires.shock}} - [ Wires have been cut ] - {{else}} - {{#if data.shock_timeleft > 0}} - [ {{data.shock_timeleft}} seconds left ] - {{/if}} - {{#if data.shock_timeleft == -1}} - [ Permanent ] - {{/if}} - {{/if}} -
    - Restore - Set (Temporary) - Set (Permanent) -
    -
    -
    - - - {{#if !data.wires.id_scanner}} - [ Wires have been cut ] - {{/if}} -
    - Enabled - Disabled -
    -
    - -
    - Enabled - Disabled -
    -
    -
    - - {{#if !data.wires.bolts}} - [ Wires have been cut ] - {{/if}} -
    - Raised - Dropped -
    -
    - - {{#if !data.wires.lights}} - [ Wires have been cut ] - {{/if}} -
    - Enabled - Disabled -
    -
    - - {{#if !data.wires.safe}} - [ Wires have been cut ] - {{/if}} -
    - Enabled - Disabled -
    -
    - - {{#if !data.wires.timing}} - [ Wires have been cut ] - {{/if}} -
    - Enabled - Disabled -
    -
    -
    - - {{#if data.locked || data.welded}} - [ Door is {{(data.locked ? "bolted" : "") + (data.locked && data.welded ? " and " : "") + (data.welded ? "welded" : "")}} ] - {{/if}} -
    - Open door - Close door -
    -
    -
    diff --git a/tgui/src/interfaces/airalarm.ract b/tgui/src/interfaces/airalarm.ract deleted file mode 100644 index f1f5002c7c..0000000000 --- a/tgui/src/interfaces/airalarm.ract +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - {{#if data.siliconUser}} - - {{data.locked ? "Engaged" : "Disengaged"}} - - {{else}} - Swipe an ID card to {{data.locked ? "unlock" : "lock"}} this interface. - {{/if}} - - -{{#if !data.locked || data.siliconUser}} - {{#if config.screen == "home"}} - - - Area Atmosphere Alarm - - - Panic Siphon - -
    - - Vent Controls - - - Scrubber Controls - - - Operating Mode - - - Alarm Thresholds - -
    - {{elseif config.screen == "vents"}} - - {{elseif config.screen == "scrubbers"}} - - {{elseif config.screen == "modes"}} - - {{elseif config.screen == "thresholds"}} - - {{/if}} -{{/if}} diff --git a/tgui/src/interfaces/airalarm/back.ract b/tgui/src/interfaces/airalarm/back.ract deleted file mode 100644 index b280ebe329..0000000000 --- a/tgui/src/interfaces/airalarm/back.ract +++ /dev/null @@ -1 +0,0 @@ -Back diff --git a/tgui/src/interfaces/airalarm/modes.ract b/tgui/src/interfaces/airalarm/modes.ract deleted file mode 100644 index 4db7e6663a..0000000000 --- a/tgui/src/interfaces/airalarm/modes.ract +++ /dev/null @@ -1,14 +0,0 @@ - - - - {{#partial button}} - - {{/partial}} - {{#each data.modes}} - - {{name}} - - {{/each}} - diff --git a/tgui/src/interfaces/airalarm/scrubbers.ract b/tgui/src/interfaces/airalarm/scrubbers.ract deleted file mode 100644 index 9f0d56d67a..0000000000 --- a/tgui/src/interfaces/airalarm/scrubbers.ract +++ /dev/null @@ -1,29 +0,0 @@ - - - - - {{#partial button}} - - {{/partial}} - {{#each data.scrubbers}} - - - {{power ? "On" : "Off"}} - - - {{scrubbing ? "Scrubbing" : "Siphoning"}} - - - {{widenet ? "Expanded" : "Normal"}} - - - - - - {{else}} - Error: No scrubbers connected. - {{/each}} - diff --git a/tgui/src/interfaces/airalarm/status.ract b/tgui/src/interfaces/airalarm/status.ract deleted file mode 100644 index 72e2319cc1..0000000000 --- a/tgui/src/interfaces/airalarm/status.ract +++ /dev/null @@ -1,30 +0,0 @@ - - {{#if data.environment_data}} - {{#each adata.environment_data}} - - - {{Math.fixed(value, 2)}}{{unit}} - - - {{/each}} - - - {{data.danger_level == 2 ? "Danger (Internals Required)" : data.danger_level == 1 ? "Caution" : "Optimal"}} - - - - - {{data.atmos_alarm ? "Atmosphere Alarm" : fire_alarm ? "Fire Alarm" : "Nominal"}} - - - {{else}} - - Cannot obtain air sample for analysis. - - {{/if}} - {{#if data.emagged}} - - Safety measures offline. Device may exhibit abnormal behavior. - - {{/if}} - diff --git a/tgui/src/interfaces/airalarm/thresholds.ract b/tgui/src/interfaces/airalarm/thresholds.ract deleted file mode 100644 index 4f3841405a..0000000000 --- a/tgui/src/interfaces/airalarm/thresholds.ract +++ /dev/null @@ -1,31 +0,0 @@ - - - - {{#partial button}} - - {{/partial}} - - - - - - - - - - {{#each data.thresholds}} - - {{#each settings}}{{/each}} - {{/each}} - -
    min2min1max1max2
    {{{name}}} - {{Math.fixed(selected, 2)}} -
    - - - diff --git a/tgui/src/interfaces/airalarm/vents.ract b/tgui/src/interfaces/airalarm/vents.ract deleted file mode 100644 index aa39a1aa1b..0000000000 --- a/tgui/src/interfaces/airalarm/vents.ract +++ /dev/null @@ -1,42 +0,0 @@ - - - - {{#partial button}} - - {{/partial}} - {{#each data.vents}} - - - {{power ? "On" : "Off"}} - - - {{direction == "release" ? "Pressurizing" : "Siphoning"}} - - - Internal - External - - {{#if incheck}} - - {{Math.fixed(internal)}} - Reset - - {{/if}} - {{#if excheck}} - - {{Math.fixed(external)}} - Reset - - {{/if}} - - {{else}} - Error: No vents connected. - {{/each}} - diff --git a/tgui/src/interfaces/airlock_electronics.ract b/tgui/src/interfaces/airlock_electronics.ract deleted file mode 100644 index e084881f85..0000000000 --- a/tgui/src/interfaces/airlock_electronics.ract +++ /dev/null @@ -1,45 +0,0 @@ - - - {{data.oneAccess ? "One" : "All"}} Required - Clear - -
    -
    - - {{#each data.regions}} - - {{/each}} - - - {{#each data.regions}} - - {{/each}} - -
    {{name}}
    {{#each accesses}} - {{name}} -
    - {{/each}}
    -
    - Unrestricted Access: - North - East - South - West -
    - - diff --git a/tgui/src/interfaces/airlock_electronics.styl b/tgui/src/interfaces/airlock_electronics.styl deleted file mode 100644 index abb8fa9885..0000000000 --- a/tgui/src/interfaces/airlock_electronics.styl +++ /dev/null @@ -1,10 +0,0 @@ -&.airlock_electronics - table - width: 100% - border-spacing: 2px - th - text-align: left - td - vertical-align: top - .button - margin-top: 4px \ No newline at end of file diff --git a/tgui/src/interfaces/apc.ract b/tgui/src/interfaces/apc.ract deleted file mode 100644 index a046cbbd71..0000000000 --- a/tgui/src/interfaces/apc.ract +++ /dev/null @@ -1,165 +0,0 @@ - -{{#if data.failTime}} - -

    SYSTEM FAILURE

    - I/O regulators malfunction detected! Waiting for system reboot...
    - Automatic reboot in {{data.failTime}} seconds... - Reboot Now


    -
    -{{else}} - - {{#if data.siliconUser}} - - {{data.locked ? "Engaged" : "Disengaged"}} - - {{else}} - Swipe an ID card to {{data.locked ? "unlock" : "lock"}} this interface. - {{/if}} - - - - {{#if data.locked && !data.siliconUser}} - {{data.isOperating ? "On" : "Off"}} - {{else}} - {{data.isOperating ? "On" : "Off"}} - {{/if}} - - - {{data.externalPower == 2 ? "Good" : data.externalPower == 1 ? "Low" : "None"}} - - - {{#if data.powerCellStatus != null}} - {{Math.fixed(adata.powerCellStatus)}}% - {{else}} - Removed - {{/if}} - - {{#if data.powerCellStatus != null}} - - {{#if data.locked && !data.siliconUser}} - {{data.chargeMode ? "Auto" : "Off"}} - {{else}} - {{data.chargeMode ? "Auto" : "Off"}} - {{/if}} -   - [{{data.chargingStatus == 2 ? "Fully Charged" : data.chargingStatus == 1 ? "Charging" : "Not Charging"}}] - - {{/if}} - - - {{#each data.powerChannels}} - -
    {{adata.powerChannels[@index].powerLoad}}
    -
    {{status >= 2 ? "On" : "Off"}}
    -
    [{{status == 1 || status == 3 ? "Auto" : "Manual"}}]
    -
    - {{#if !data.locked || data.siliconUser}} - Auto - On - Off - {{/if}} -
    -
    - {{/each}} - - {{adata.totalLoad}} - -
    - {{#if data.siliconUser}} - - Overload - {{#if data.malfStatus}} - {{malfButton}} - {{/if}} - - {{/if}} - - - {{#if data.locked && !data.siliconUser}} - {{data.emergencyLights ? "Enabled" : "Disabled"}} - {{else}} - {{data.emergencyLights ? "Enabled" : "Disabled"}} - {{/if}} - - - - - {{#if data.locked && !data.siliconUser && data.lock_nightshift}} - {{data.nightshiftLights ? "Enabled" : "Disabled"}} - {{else}} - {{data.nightshiftLights ? "Enabled" : "Disabled"}} - {{/if}} - - - - - {{#if data.locked && !data.siliconUser}} - {{data.coverLocked ? "Engaged" : "Disengaged"}} - {{else}} - {{data.coverLocked ? "Engaged" : "Disengaged"}} - {{/if}} - - - {{#if data.hijackable}} - - {{#if !data.hijacker}} - Hijack APC - {{else}} - {{#if data.drainavail}} - Drain APC - {{/if}} - {{#if data.lockdownavail}} - Lockdown Room - {{/if}} - {{/if}} - - {{/if}} -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/atmos_alert.ract b/tgui/src/interfaces/atmos_alert.ract deleted file mode 100644 index 05bf9b797d..0000000000 --- a/tgui/src/interfaces/atmos_alert.ract +++ /dev/null @@ -1,14 +0,0 @@ - -
      - {{#each data.priority}} -
    • {{.}}
    • - {{else}} -
    • No Priority Alerts
    • - {{/each}} - {{#each data.minor}} -
    • {{.}}
    • - {{else}} -
    • No Minor Alerts
    • - {{/each}} -
    -
    diff --git a/tgui/src/interfaces/atmos_control.ract b/tgui/src/interfaces/atmos_control.ract deleted file mode 100644 index 36035285c8..0000000000 --- a/tgui/src/interfaces/atmos_control.ract +++ /dev/null @@ -1,40 +0,0 @@ - - {{#each adata.sensors}} - - - {{Math.fixed(pressure, 2)}} kPa - - {{#if temperature}} - - {{Math.fixed(temperature, 2)}} K - - {{/if}} - {{#each gases:id}} - - {{Math.fixed(., 2)}}% - - {{/each}} - - {{/each}} - -{{#if data.tank}} - - {{#partial button}} - Reconnect - {{/partial}} - - - {{data.inputting ? "Injecting": "Off"}} - - - {{Math.fixed(adata.inputRate)}} L/s - - - - {{data.outputting ? "Open": "Closed"}} - - - {{Math.round(adata.outputPressure)}} kPa - - -{{/if}} diff --git a/tgui/src/interfaces/atmos_filter.ract b/tgui/src/interfaces/atmos_filter.ract deleted file mode 100644 index 08699736b2..0000000000 --- a/tgui/src/interfaces/atmos_filter.ract +++ /dev/null @@ -1,17 +0,0 @@ - - - {{data.on ? "On" : "Off"}} - - - Set - Max - {{Math.round(adata.rate)}} L/s - - - {{#each data.filter_types}} - {{name}} - {{/each}} - - diff --git a/tgui/src/interfaces/atmos_mixer.ract b/tgui/src/interfaces/atmos_mixer.ract deleted file mode 100644 index 4f9285dae6..0000000000 --- a/tgui/src/interfaces/atmos_mixer.ract +++ /dev/null @@ -1,33 +0,0 @@ - - - {{data.on ? "On" : "Off"}} - - - Set - Max - {{Math.round(adata.set_pressure)}} kPa - - - - - - - {{Math.round(adata.node1_concentration)}}% - - - - - - - {{Math.round(adata.node2_concentration)}}% - - diff --git a/tgui/src/interfaces/atmos_pump.ract b/tgui/src/interfaces/atmos_pump.ract deleted file mode 100644 index a622ae3f18..0000000000 --- a/tgui/src/interfaces/atmos_pump.ract +++ /dev/null @@ -1,19 +0,0 @@ - - - {{data.on ? "On" : "Off"}} - - {{#if data.max_rate}} - - Set - Max - {{Math.round(adata.rate)}} L/s - - {{else}} - - Set - Max - {{Math.round(adata.pressure)}} kPa - - {{/if}} - diff --git a/tgui/src/interfaces/atmos_relief.ract b/tgui/src/interfaces/atmos_relief.ract deleted file mode 100644 index 4cc0d1fb68..0000000000 --- a/tgui/src/interfaces/atmos_relief.ract +++ /dev/null @@ -1,12 +0,0 @@ - - - Set - Max - {{Math.round(adata.open_pressure)}} kPa - - - Set - Max - {{Math.round(adata.close_pressure)}} kPa - - diff --git a/tgui/src/interfaces/borgopanel.ract b/tgui/src/interfaces/borgopanel.ract deleted file mode 100644 index 7aba4782ad..0000000000 --- a/tgui/src/interfaces/borgopanel.ract +++ /dev/null @@ -1,46 +0,0 @@ - - {{#partial button}} - Rename - {{/partial}} - - Emagged - Locked down - Scrambled codes - - - {{#if !data.cell.missing}} - {{Math.round(data.cell.charge)}} / {{Math.round(data.cell.maxcharge)}} - {{else}} - Cell missing
    - {{/if}} - SetChangeRemove -
    - - {{#each data.channels}} - {{name}} - {{/each}} - - - {{#each data.modules}} - {{name}} - {{/each}} - - - {{#each data.upgrades}} - {{name}} - {{/each}} - - - {{#each data.ais}} - {{name}} - {{/each}} - -
    - - {{#partial button}} - Lawsync - {{/partial}} - {{#each data.laws}} -

    {{this}}

    - {{/each}} -
    diff --git a/tgui/src/interfaces/brig_timer.ract b/tgui/src/interfaces/brig_timer.ract deleted file mode 100644 index f09e99b431..0000000000 --- a/tgui/src/interfaces/brig_timer.ract +++ /dev/null @@ -1,18 +0,0 @@ - - {{#partial button}} - {{data.timing ? "Stop" : "Start"}} - {{data.flash_charging ? "Recharging" : "Flash"}} - {{/partial}} - - - - {{text.zeroPad(data.minutes, 2)}}:{{text.zeroPad(data.seconds, 2)}} - - - - - Short - Medium - Long - - diff --git a/tgui/src/interfaces/bsa.ract b/tgui/src/interfaces/bsa.ract deleted file mode 100644 index 77513966b2..0000000000 --- a/tgui/src/interfaces/bsa.ract +++ /dev/null @@ -1,26 +0,0 @@ -{{#if data.notice}} - - {{data.notice}} - -{{/if}} - - {{#if data.connected}} - - {{data.target}} - - - {{#if !data.unlocked}} - - Bluespace Artillery firing protocols must be globally unlocked from two keycard authentication devices first! - - {{else}} - FIRE! - {{/if}} - - {{/if}} - {{#if !data.connected}} - - Complete Deployment. - - {{/if}} - diff --git a/tgui/src/interfaces/canister.ract b/tgui/src/interfaces/canister.ract deleted file mode 100644 index 63ede83eb2..0000000000 --- a/tgui/src/interfaces/canister.ract +++ /dev/null @@ -1,84 +0,0 @@ - - The regulator {{data.hasHoldingTank ? "is" : "is not"}} connected to a tank. - - - {{#partial button}} - Relabel - {{/partial}} - - {{Math.round(adata.tankPressure)}} kPa - - - {{data.portConnected ? "Connected" : "Not Connected"}} - - {{#if data.isPrototype}} - - {{data.restricted ? "Restricted to Engineering" : "Public"}} - - {{/if}} - - - - {{Math.round(adata.releasePressure)}} kPa - - - Reset - Min - Set - Max - - - {{data.valveOpen ? "Open" : "Closed"}} - -{{#if data.isPrototype}} - - {{^data.timing}} - - Reset - Decrease - Set - Increase - - {{/data.timing}} - - {{data.timing ? "On" : "Off"}} - - - {{data.timing ? data.time_left : data.timer_set}} - - -{{/if}} - - - - {{#partial button}} - {{#if data.hasHoldingTank}} - Eject - {{/if}} - {{/partial}} - {{#if data.hasHoldingTank}} - - {{data.holdingTank.name}} - - - {{Math.round(adata.holdingTank.tankPressure)}} kPa - - {{else}} - - No Holding Tank - - {{/if}} - diff --git a/tgui/src/interfaces/cargo.ract b/tgui/src/interfaces/cargo.ract deleted file mode 100644 index bac920517b..0000000000 --- a/tgui/src/interfaces/cargo.ract +++ /dev/null @@ -1,90 +0,0 @@ - - - - - {{#if data.docked && !data.requestonly}} - {{data.location}} - {{else}} - {{data.location}} - {{/if}} - - - {{Math.floor(adata.points)}} - - - {{data.message}} - - {{#if data.loan && !data.requestonly}} - - {{#if !data.loan_dispatched}} - Loan Shuttle - {{else}} - Loaned to CentCom - {{/if}} - - {{/if}} - -{{#if !data.requestonly}} - - {{#partial button}} - Clear - {{/partial}} - {{#each data.cart}} - -
    #{{id}}
    -
    {{object}}
    -
    {{cost}} Credits
    -
    - -
    -
    - {{else}} - Nothing in Cart - {{/each}} -
    -{{/if}} - - {{#partial button}} - {{#if !data.requestonly}} - Clear - {{/if}} - {{/partial}} - {{#each data.requests}} - -
    #{{id}}
    -
    {{object}}
    -
    {{cost}} Credits
    -
    By {{orderer}}
    -
    Comment: {{reason}}
    - {{#if !data.requestonly}} -
    - - -
    - {{/if}} -
    - {{else}} - No Requests - {{/each}} -
    - - {{#each data.supplies}} - - {{#each packs}} - - {{cost}} Credits - - {{/each}} - - {{/each}} - diff --git a/tgui/src/interfaces/cargo_express.ract b/tgui/src/interfaces/cargo_express.ract deleted file mode 100644 index a32b7725e6..0000000000 --- a/tgui/src/interfaces/cargo_express.ract +++ /dev/null @@ -1,50 +0,0 @@ - - - - - {{#if data.siliconUser }} - - {{data.locked ? "Engaged" : "Disengaged"}} - - {{else}} - Swipe a QM-Level ID card to {{data.locked ? "unlock" : "lock"}} this interface. - {{/if}} - - -{{#if !data.locked }} - - - - Cargo Bay - {{data.beaconzone}} ({{data.beaconName}}) - {{data.printMsg}} - - - - {{Math.floor(adata.points)}} - - - - {{data.message}} - - - - {{#each data.supplies}} - - {{#each packs}} - - {{cost}} Credits {{data.beaconError}} - - {{/each}} - - {{/each}} - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/cellular_emporium.ract b/tgui/src/interfaces/cellular_emporium.ract deleted file mode 100644 index 5aa6213ec1..0000000000 --- a/tgui/src/interfaces/cellular_emporium.ract +++ /dev/null @@ -1,25 +0,0 @@ - - Readapt - - {{data.genetic_points_remaining}} - - - -{{#each data.abilities}} - - {{desc}} - {{helptext}} - Cost: {{dna_cost}} - - {{owned ? "Evolved" : "Evolve"}} - - -{{/each}} -{{^data.abilities}} - No abilities available. -{{/data.abilities}} - diff --git a/tgui/src/interfaces/centcom_podlauncher.ract b/tgui/src/interfaces/centcom_podlauncher.ract deleted file mode 100644 index ecb6753e8f..0000000000 --- a/tgui/src/interfaces/centcom_podlauncher.ract +++ /dev/null @@ -1,157 +0,0 @@ - - To use this, simply spawn the atoms you want in one of the five Centcom Supplypod Bays. Items in the bay will then be launched inside your supplypod, one turf-full at a time! You can optionally use the following buttons to configure how the supplypod acts. - - - - - - - Bay #1 - Bay #2 - Bay #3 - Bay #4 - ERT Bay - - - - - - {{data.bay}} - {{data.oldArea ? data.oldArea : "where you were"}} - - - - - - Launch Clones - - - - Ordered - Random - - - - - - Custom Size - Adminbus - - - - - Custom Damage - Gib - - - - - Stun - Delimb - Yeet Organs - - - - - Bluespace - Stealth - Quiet Landing - Reverse Mode - Missile Mode - Any Descent Angle - Machine Gun Mode - Specific Target - - - - - Custom Name/Desc - Alert Ghosts - - - - - Custom Falling Sound - Custom Landing Sound - Custom Opening Sound - Custom Leaving Sound - Admin Sound Volume - - - - - Custom Falling Duration - Custom Landing Time - Custom Opening Time - Custom Leaving Time - - - - - Standard - Advanced - Syndicate - Deathsquad - Cult Pod - Missile - Syndicate Missile - Supply Crate - HONK - Fruit~ - Invisible - Gondola (alive) - Show Contents (See-Through Pod)! - - - - - - Refresh Pod Bay - Enter Launch Mode - Clear Selected Bay - - \ No newline at end of file diff --git a/tgui/src/interfaces/chem_dispenser.ract b/tgui/src/interfaces/chem_dispenser.ract deleted file mode 100644 index e7f10b5f6a..0000000000 --- a/tgui/src/interfaces/chem_dispenser.ract +++ /dev/null @@ -1,76 +0,0 @@ - - - - - {{Math.fixed(adata.energy)}} Units - - - -{{#if data.recordingRecipe && true}} - - Recording - - - - {{#each data.recordingRecipe: chemical}} - {{adata.recordingRecipe[chemical]}} - {{/each}} - - - Save - Cancel - - -{{/if}} - - - - Record Recipe - Clear Recipes - {{#each data.recipes: recipe_name}} - {{recipe_name}} - {{/each}} - - - - {{#partial button}} - {{#each data.beakerTransferAmounts}} - {{.}} - {{/each}} - {{/partial}} - - {{#each data.chemicals}} - {{title}} - {{/each}} - - - - {{#partial button}} - {{#each data.beakerTransferAmounts}} - {{.}} - {{/each}} - Eject - {{/partial}} - - {{#if data.isBeakerLoaded}} - {{Math.round(adata.beakerCurrentVolume)}}/{{data.beakerMaxVolume}} Units - pH: {{Math.round(adata.beakerCurrentpH*adata.partRating)/adata.partRating}} -
    - {{#each adata.beakerContents}} - {{Math.fixed(volume, 2)}} units of {{name}}
    - {{else}} - Beaker Empty - {{/each}} - {{else}} - No Beaker - {{/if}} -
    -
    diff --git a/tgui/src/interfaces/chem_heater.ract b/tgui/src/interfaces/chem_heater.ract deleted file mode 100644 index ce4924356a..0000000000 --- a/tgui/src/interfaces/chem_heater.ract +++ /dev/null @@ -1,34 +0,0 @@ - - - {{data.isActive ? "On" : "Off"}} - - - {{Math.round(adata.targetTemp)}} K - - - - {{#partial button}} - Eject - {{/partial}} - - {{#if data.isBeakerLoaded}} - Temperature: {{Math.round(adata.currentTemp)}} K -
    - pH: {{Math.round(adata.currentpH*adata.partRating)/adata.partRating}} -
    - {{#each adata.beakerContents}} - {{Math.fixed(volume, 2)}} units of {{name}}
    - {{#if data.showPurity}} - Purity: {{Math.fixed(purity, 2)}}
    - {{/if}} - {{else}} - Beaker Empty - {{/each}} - {{else}} - No Beaker - {{/if}} -
    -
    diff --git a/tgui/src/interfaces/chem_master.ract b/tgui/src/interfaces/chem_master.ract deleted file mode 100644 index 7c7d5402a6..0000000000 --- a/tgui/src/interfaces/chem_master.ract +++ /dev/null @@ -1,147 +0,0 @@ -{{#if data.screen == "home"}} - - {{data.isBeakerLoaded ? "Eject" : "No beaker"}} - - - - {{#if data.isBeakerLoaded}} - {{#each data.beakerContents}} - -
    - 1 - 5 - 10 - All - Custom - Analyze -
    -
    - {{else}} - Beaker Empty - {{/each}} - {{else}} - No Beaker - {{/if}} -
    -
    - - - Destroy - Transfer to Beaker - - {{#each data.bufferContents}} - -
    - 1 - 5 - 10 - All - Custom - Analyze -
    -
    - {{/each}} -
    -
    - - {{#if !data.condi}} - - {{#each data.pillStyles}} - {{{htmltag}}} - {{/each}} -
    - {{#if data.isPillBottleLoaded}} - {{data.isPillBottleLoaded ? "Eject" : "No Pill bottle loaded"}} - {{data.pillBotContent}}/{{data.pillBotMaxContent}} - {{else}} - No Pillbottle - {{/if}} - -
    - Create Pill (max 50µ) -
    - Create Multiple Pills -
    -
    - Create Patch (max 40µ) -
    - Create Multiple Patches -
    -
    - Create Bottle (max 30µ) -
    - Dispense Buffer to Bottles -
    -
    - Create Hypo Vial (max 60µ) -
    - Dispense Buffer to Hypo vials -
    -
    - Create SmartDart (max 20µ) -
    - Create Multiple SmartDarts -
    - -
    - - {{else}} - - Create Pack (max 10µ) -
    -
    - Create Bottle (max 50µ) -
    - {{/if}} -{{elseif data.screen == "analyze"}} - - Description: - {{data.analyzeVars.description}} -
    - Color: - {{data.analyzeVars.color}} -
    - State: - {{data.analyzeVars.state}} -
    - Metabolization Rate: - {{data.analyzeVars.metaRate}}µ/minute -
    - Overdose Threshold: - {{data.analyzeVars.overD}} -
    - Addiction Threshold: - {{data.analyzeVars.addicD}} -
    - {{#if data.fermianalyze}} - Minumum Reaction Temperature: - {{data.analyzeVars.minTemp}}K -
    - Optimal Reaction Temperature: - {{data.analyzeVars.maxTemp}}K -
    - Explosion Reaction Temperature: - {{data.analyzeVars.eTemp}}K -
    - Optimal reaction pH: - {{data.analyzeVars.pHpeak}} -
    - Current Purity: - {{data.analyzeVars.purityF}} -
    - Inverse Purity Threshold: - {{data.analyzeVars.inverseRatioF}} -
    - Explosion Purity Threshold: - {{data.analyzeVars.purityE}} -
    - {{/if}} -
    - Back -
    -{{/if}} - diff --git a/tgui/src/interfaces/chem_synthesizer.ract b/tgui/src/interfaces/chem_synthesizer.ract deleted file mode 100644 index 323eaa0a06..0000000000 --- a/tgui/src/interfaces/chem_synthesizer.ract +++ /dev/null @@ -1,22 +0,0 @@ - - - Eject - Input - {{data.amount}}U - Create Beaker - - - - - {{#if data.isBeakerLoaded}} - {{Math.round(adata.beakerCurrentVolume)}}/{{data.beakerMaxVolume}} Units - {{#each adata.beakerContents}} - {{Math.fixed(volume, 2)}} units of {{name}}
    - {{else}} - Recipient Empty - {{/each}} - {{else}} - No Recipient - {{/if}} -
    -
    diff --git a/tgui/src/interfaces/clockwork_slab.ract b/tgui/src/interfaces/clockwork_slab.ract deleted file mode 100644 index 48f6ae02f6..0000000000 --- a/tgui/src/interfaces/clockwork_slab.ract +++ /dev/null @@ -1,43 +0,0 @@ - - {{data.recollection ? "Recital":"Recollection"}} - -{{#if data.recollection}} - - {{{data.rec_text}}} - {{#each data.recollection_categories}} -
    {{{name}}} - {{{desc}}} - {{/each}} - {{{data.rec_section}}} - {{{data.rec_binds}}} -
    -{{else}} - - - {{{data.power}}} - - - - - Driver - Scripts - Applications -
    {{{data.tier_info}}} -
    - - {{{data.scripturecolors}}} -
    - - {{#each data.scripture}} -
    Recite {{{required}}} - {{#if quickbind}} - {{#if bound}} - Unbind {{{bound}}} - {{else}} - Quickbind - {{/if}} - {{/if}} - {{{name}}} {{{descname}}} {{{invokers}}}
    - {{/each}} -
    -
    -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/codex_gigas.ract b/tgui/src/interfaces/codex_gigas.ract deleted file mode 100644 index 602f67b5b7..0000000000 --- a/tgui/src/interfaces/codex_gigas.ract +++ /dev/null @@ -1,50 +0,0 @@ - - - {{data.name}} - - - Dark - Hellish - Fallen - Fiery - Sinful - Blood - Fluffy - - - Lord - Prelate - Count - Viscount - Vizier - Elder - Adept - - - hal - ve - odr - neit - ci - quon - mya - folth - wren - geyr - hil - niet - twou - phi - coa - - - the Red - the Soulless - the Master - the Lord of all things - jr - - - search - - diff --git a/tgui/src/interfaces/computer_fabricator.ract b/tgui/src/interfaces/computer_fabricator.ract deleted file mode 100644 index b8beb8bd04..0000000000 --- a/tgui/src/interfaces/computer_fabricator.ract +++ /dev/null @@ -1,89 +0,0 @@ - -Clear Order

    -Your new computer device you always dreamed of is just four steps away...
    -{{#if data.state == 0}} -
    -

    Step 1: Select your device type

    - Laptop - LTablet -
    -{{elseif data.state == 1}} -
    -

    Step 2: Personalise your device

    - - - - - - - - - - - - - -
    Current Price: - {{data.totalprice}}C -
    Battery: - Standard - Upgraded - Advanced -
    Hard Drive: - Standard - Upgraded - Advanced -
    Network Card: - None - Standard - Advanced -
    Nano Printer: - None - Standard -
    Card Reader: - None - Standard -
    - - {{#if data.devtype != 2}} {{! No tablets}} - - - - - -
    Processor Unit: - Standard - Advanced -
    Tesla Relay: - None - Standard -
    - {{/if}} - - - -
    Confirm Order: - CONFIRM -
    - -
    - Battery allows your device to operate without external utility power source. Advanced batteries increase battery life.
    - Hard Drive stores file on your device. Advanced drives can store more files, but use more power, shortening battery life.
    - Network Card allows your device to wirelessly connect to stationwide NTNet network. Basic cards are limited to on-station use, while advanced cards can operate anywhere near the station, which includes the asteroid outposts.
    - Processor Unit is critical for your device's functionality. It allows you to run programs from your hard drive. Advanced CPUs use more power, but allow you to run more programs on background at once.
    - Tesla Relay is an advanced wireless power relay that allows your device to connect to nearby area power controller to provide alternative power source. This component is currently unavailable on tablet computers due to size restrictions.
    - Nano Printer is device that allows for various paperwork manipulations, such as, scanning of documents or printing new ones. This device was certified EcoFriendlyPlus and is capable of recycling existing paper for printing purposes.
    - Card Reader adds a slot that allows you to manipulate RFID cards. Please note that this is not necessary to allow the device to read your identification, it is just necessary to manipulate other cards. -
    -{{elseif data.state == 2}} -

    Step 3: Payment

    - Your device is now ready for fabrication..
    - Please ensure the required amount of credits are in the machine, then press purchase.
    - Current credits: {{data.credits}}C
    - Total price: {{data.totalprice}}C

    - PURCHASE - -{{elseif data.state == 3}} -

    Step 4: Thank you for your purchase


    - Should you experience any issues with your new device, contact your local network admin for assistance. -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/crayon.ract b/tgui/src/interfaces/crayon.ract deleted file mode 100644 index 42c4df9a50..0000000000 --- a/tgui/src/interfaces/crayon.ract +++ /dev/null @@ -1,35 +0,0 @@ -{{#if data.has_cap}} - - - - {{data.is_capped ? "On": "Off"}} - - -{{/if}} - - {{!{{{current_colour} - }} -{{#if data.can_change_colour}} - - Select New Colour - -{{/if}} - - - {{#each data.drawables}} - - {{#each items}} - - {{item}} - - {{/each}} - - {{/each}} - - - {{data.text_buffer}} - - New Text - diff --git a/tgui/src/interfaces/crew.ract b/tgui/src/interfaces/crew.ract deleted file mode 100644 index a8130efb06..0000000000 --- a/tgui/src/interfaces/crew.ract +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - - - - - - - {{#if data.link_allowed}} - - {{/if}} - - - - {{#each data.sensors}} - - - - - - {{#if data.link_allowed }} - - {{/if}} - - {{/each}} - -
    NameStatusVitalsPositionTracking
    - - {{name}} ({{assignment}}) - - - {{#if oxydam != null}} - - {{else}} - {{#if life_status}} - - {{else}} - - {{/if}} - {{/if}} - - {{#if oxydam != null}} - - ( - {{oxydam}} - / - {{toxdam}} - / - {{burndam}} - / - {{brutedam}} - ) - - {{else}} - {{#if life_status}} - Alive - {{else}} - Dead - {{/if}} - {{/if}} - - {{#if pos_x != null}} - {{area}} - {{else}} - N/A - {{/if}} - - Track -
    -
    -
    - - \ No newline at end of file diff --git a/tgui/src/interfaces/cryo.ract b/tgui/src/interfaces/cryo.ract deleted file mode 100644 index 619741eaad..0000000000 --- a/tgui/src/interfaces/cryo.ract +++ /dev/null @@ -1,53 +0,0 @@ - - - {{data.occupant.name ? data.occupant.name : "No Occupant"}} - - {{#if data.hasOccupant}} - - {{data.occupant.stat}} - - - {{data.occupant.bodyTemperature}} K - - - {{data.occupant.health}} - - {{#each [{label: "Brute", type: "bruteLoss"}, {label: "Respiratory", type: "oxyLoss"}, {label: "Toxin", type: "toxLoss"}, {label: "Burn", type: "fireLoss"}]}} - - {{data.occupant[type]}} - - {{/each}} - {{/if}} - - - - {{data.isOperating ? "On" : "Off"}} - - - {{data.cellTemperature}} K - - - {{data.isOpen ? "Open" : "Closed"}} - {{data.autoEject ? "Auto" : "Manual"}} - - - - {{#partial button}} - Eject - {{/partial}} - - {{#if data.isBeakerLoaded}} - {{#each adata.beakerContents}} - {{volume}} units of {{name}}
    - {{else}} - Beaker Empty - {{/each}} - {{else}} - No Beaker - {{/if}} -
    -
    diff --git a/tgui/src/interfaces/disposal_unit.ract b/tgui/src/interfaces/disposal_unit.ract deleted file mode 100644 index 47b95ffaaa..0000000000 --- a/tgui/src/interfaces/disposal_unit.ract +++ /dev/null @@ -1,33 +0,0 @@ - - - {{#if data.full_pressure}} - Ready - {{else}} - {{#if data.panel_open}} - Power Disabled - {{else}} - {{#if data.pressure_charging}} - Pressurizing - {{else}} - Off - {{/if}} - {{/if}} - {{/if}} - - - {{data.per}}% - - - - {{data.flush ? "Disengage" : "Engage" }} - - - Eject Contents
    -
    - -
    -
    -
    diff --git a/tgui/src/interfaces/dna_vault.ract b/tgui/src/interfaces/dna_vault.ract deleted file mode 100644 index 53ae38e6e8..0000000000 --- a/tgui/src/interfaces/dna_vault.ract +++ /dev/null @@ -1,22 +0,0 @@ - - - {{data.dna}}/{{data.dna_max}} Samples - - - {{data.plants}}/{{data.plants_max}} Samples - - - {{data.animals}}/{{data.animals_max}} Samples - - -{{#if data.completed && !data.used}} - - - Applicable gene therapy treatments: - - - {{data.choiceA}} - {{data.choiceB}} - - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/dogborg_sleeper.ract b/tgui/src/interfaces/dogborg_sleeper.ract deleted file mode 100644 index 7c9f54da20..0000000000 --- a/tgui/src/interfaces/dogborg_sleeper.ract +++ /dev/null @@ -1,49 +0,0 @@ - - - {{data.occupant.name ? data.occupant.name : "No Occupant"}} - - {{#if data.items}} - - {{data.items}} - - {{/if}} - {{#if data.occupied}} - - {{data.occupant.stat}} - - - {{Math.round(adata.occupant.health)}} - - {{#each [{label: "Brute", type: "bruteLoss"}, {label: "Respiratory", type: "oxyLoss"}, {label: "Toxin", type: "toxLoss"}, {label: "Burn", type: "fireLoss"}]}} - - {{Math.round(adata.occupant[type])}} - - {{/each}} - - {{data.occupant.cloneLoss ? "Damaged" : "Healthy"}} - - - {{data.occupant.brainLoss ? "Abnormal" : "Healthy"}} - - - {{#each adata.occupant.reagents}} - {{Math.fixed(volume, 1)}} units of {{name}}
    - {{else}} - Pure - {{/each}} -
    - {{/if}} -
    - - - {{#each data.chem}} - {{name}}
    - {{/each}} -
    - - Eject Contents - - - Self-Clean Cycle -
    diff --git a/tgui/src/interfaces/eightball.ract b/tgui/src/interfaces/eightball.ract deleted file mode 100644 index f324919f15..0000000000 --- a/tgui/src/interfaces/eightball.ract +++ /dev/null @@ -1,14 +0,0 @@ -{{#if data.shaking}} - - - {{#each data.answers}} - {{answer}} ({{amount}}) - - {{/each}} - - -{{else}} - The eightball is not currently being shaken. -{{/if}} diff --git a/tgui/src/interfaces/emergency_shuttle_console.ract b/tgui/src/interfaces/emergency_shuttle_console.ract deleted file mode 100644 index 96250a5605..0000000000 --- a/tgui/src/interfaces/emergency_shuttle_console.ract +++ /dev/null @@ -1,30 +0,0 @@ - - Time Until Launch: {{data.timer_str}} - - - Engines: {{data.engines_started ? 'Online' : 'Idle'}} - - - Authorizations Remaining: - {{data.emagged ? "ERROR" : data.authorizations_remaining}} - - AUTHORIZE - - - Repeal - - - Repeal All - - - - {{#each data.authorizations}} - {{name}} ({{job}}) - {{else}} - No authorizations. - {{/each}} - diff --git a/tgui/src/interfaces/engraved_message.ract b/tgui/src/interfaces/engraved_message.ract deleted file mode 100644 index 1bd5187d42..0000000000 --- a/tgui/src/interfaces/engraved_message.ract +++ /dev/null @@ -1,29 +0,0 @@ - - - {{data.hidden_message}} - - - {{data.realdate}} - - - {{data.num_likes}} - - {{data.num_dislikes}} - - -{{#if data.admin_mode}} - - {{data.creator_key}} - {{data.creator_name}} - Delete - -{{/if}} diff --git a/tgui/src/interfaces/error.ract b/tgui/src/interfaces/error.ract deleted file mode 100644 index 23d76c2248..0000000000 --- a/tgui/src/interfaces/error.ract +++ /dev/null @@ -1,3 +0,0 @@ - - The requested interface ({{config.interface}}) was not found. Does it exist? - diff --git a/tgui/src/interfaces/exofab - Copia.ract b/tgui/src/interfaces/exofab - Copia.ract deleted file mode 100644 index 141f89ea74..0000000000 --- a/tgui/src/interfaces/exofab - Copia.ract +++ /dev/null @@ -1,50 +0,0 @@ -{{#if data.sync}} - - Currently syncing with the database - -{{else}} - - {{#partial button}} - Eject all - - {{data.show_materials ? "Hide" : "Show"}} - - {{/partial}} - {{#if data.show_materials}} -
    -
    -
    -
    - Mineral -
    -
    - Amount -
    -
    -
    -
    - {{#each data.all_materials}} -
    -
    - {{name}} -
    -
    - {{amount}} -
    -
    - Release amount -
    -
    - Release all -
    -
    - {{/each}} -
    - {{/if}} -
    - - {{#data.categories}} - {{this}} - {{/data.categories}} - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/exonet_node.ract b/tgui/src/interfaces/exonet_node.ract deleted file mode 100644 index 0026a9616a..0000000000 --- a/tgui/src/interfaces/exonet_node.ract +++ /dev/null @@ -1,14 +0,0 @@ - - - - Turn {{data.toggle ? "off" : "on"}} - - - - {{#each data.logs}} - {{.}} - {{/each}} - - \ No newline at end of file diff --git a/tgui/src/interfaces/gps.ract b/tgui/src/interfaces/gps.ract deleted file mode 100644 index e30ea851c5..0000000000 --- a/tgui/src/interfaces/gps.ract +++ /dev/null @@ -1,30 +0,0 @@ - - - {{data.power ? "Enabled" : "Disabled"}} - - - {{data.tag}} - - - {{data.updating ? "AUTO" : "MANUAL"}} - - - {{data.globalmode ? "MAXIMUM" : "LOCAL"}} - - -{{#if data.power}} - - {{data.current}} - - - - {{#each data.signals}} - - {{area}} ({{coord}}) - {{#if direction}} - Dist: {{dist}}m Dir: {{degrees}}° ({{direction}}) - {{/if}} - - {{/each}} - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/gulag_console.ract b/tgui/src/interfaces/gulag_console.ract deleted file mode 100644 index a5bce8a489..0000000000 --- a/tgui/src/interfaces/gulag_console.ract +++ /dev/null @@ -1,49 +0,0 @@ - - - {{data.teleporter ? "Connected" : "Not connected"}} - - {{#if data.teleporter}} - - {{data.teleporter_location}} - - - {{data.teleporter_lock ? "Locked" : "Unlocked"}} - {{data.teleporter_state_open ? "Open" : "Closed"}} - - {{else}} - Scan Teleporter - {{/if}} - - - - {{data.beacon ? "Connected" : "Not connected"}} - - {{#if data.beacon}} - - {{data.beacon_location}} - - {{else}} - Scan Beacon - {{/if}} - - - - {{data.id ? data.id_name : "-------------"}} - - {{#if data.id}} - - {{data.goal}} - - {{/if}} - - {{data.prisoner.name ? data.prisoner.name : "No Occupant"}} - - {{#if data.prisoner}} - - {{data.prisoner.crimstat}} - - {{/if}} - - -
    Process Prisoner
    -
    diff --git a/tgui/src/interfaces/gulag_item_reclaimer.ract b/tgui/src/interfaces/gulag_item_reclaimer.ract deleted file mode 100644 index ac6d5d5165..0000000000 --- a/tgui/src/interfaces/gulag_item_reclaimer.ract +++ /dev/null @@ -1,7 +0,0 @@ - - {{#each data.mobs}} - - Drop Items - - {{/each}} - diff --git a/tgui/src/interfaces/holodeck.ract b/tgui/src/interfaces/holodeck.ract deleted file mode 100644 index 94ea529e9f..0000000000 --- a/tgui/src/interfaces/holodeck.ract +++ /dev/null @@ -1,21 +0,0 @@ - - {{#partial button}} - - Safeties: {{data.emagged ? "OFF" : "ON"}} - - {{/partial}} - {{#each data.default_programs}} - - {{name}} -
    - {{/each}} -
    -{{#if data.emagged}} - - {{#each data.emag_programs}} - - {{name}} -
    - {{/each}} -
    -{{/if}} diff --git a/tgui/src/interfaces/implantchair.ract b/tgui/src/interfaces/implantchair.ract deleted file mode 100644 index 4df87b3c5f..0000000000 --- a/tgui/src/interfaces/implantchair.ract +++ /dev/null @@ -1,40 +0,0 @@ - - - - - {{data.occupant.name ? data.occupant.name : "No Occupant"}} - - {{#if data.occupied}} - - {{data.occupant.stat == 0 ? "Conscious" : data.occupant.stat == 1 ? "Unconcious" : "Dead"}} - - {{/if}} - - - - {{data.open ? "Open" : "Closed"}} - - - {{ data.ready_implants }} - {{#if data.replenishing}} - - {{/if}} - - - - {{ data.ready ? (data.special_name ? data.special_name : "Implant") : "Recharging"}} -
    -
    -
    diff --git a/tgui/src/interfaces/intellicard.ract b/tgui/src/interfaces/intellicard.ract deleted file mode 100644 index f9d52ae3b5..0000000000 --- a/tgui/src/interfaces/intellicard.ract +++ /dev/null @@ -1,42 +0,0 @@ - - -{{#if data.wiping}} - - Wipe in progress! - -{{/if}} - - {{#partial button}} - {{#if data.name}} - {{data.wiping ? "Stop Wiping" : "Wipe"}} AI - {{/if}} - {{/partial}} - {{#if data.name}} - - {{data.isDead || data.isBraindead ? "Offline" : "Operational"}} - - - {{Math.round(adata.health)}}% - - - {{#each data.laws}} - {{.}}
    - {{/each}} -
    - - Wireless Activity - Subspace Radio - - {{/if}} -
    diff --git a/tgui/src/interfaces/keycard_auth.ract b/tgui/src/interfaces/keycard_auth.ract deleted file mode 100644 index cb440346b6..0000000000 --- a/tgui/src/interfaces/keycard_auth.ract +++ /dev/null @@ -1,17 +0,0 @@ -{{#if data.waiting}} - - Waiting for another device to confirm your request... - -{{else}} - - - {{#if data.auth_required}} - Authorize {{data.auth_required}} - {{else}} - Red Alert - Emergency Maintenance Access - Bluespace Artillery Unlock - {{/if}} - - -{{/if}} diff --git a/tgui/src/interfaces/labor_claim_console.ract b/tgui/src/interfaces/labor_claim_console.ract deleted file mode 100644 index 21e69f9aa9..0000000000 --- a/tgui/src/interfaces/labor_claim_console.ract +++ /dev/null @@ -1,20 +0,0 @@ - - {{#each data.ores}} - - {{value}} - - {{/each}} - - - - {{data.unclaimed_points}} - Claim points - - - - Points: {{data.id_points}} - - {{data.status_info}} - Move shuttle - - diff --git a/tgui/src/interfaces/language_menu.ract b/tgui/src/interfaces/language_menu.ract deleted file mode 100644 index 0a4c60a955..0000000000 --- a/tgui/src/interfaces/language_menu.ract +++ /dev/null @@ -1,48 +0,0 @@ - - {{#each data.languages}} - - {{desc}} - Key: ,{{key}} - {{#if shadow}} - (gained from mob) - {{/if}} - {{can_speak ? "Can Speak" : "Cannot Speak"}} - {{#if data.is_living}} - {{is_default ? "Default Language" : "Select as Default"}} - - {{/if}} - {{#if data.admin_mode}} - {{#if shadow}} - Grant - {{else}} - Remove - {{/if}} - {{/if}} - - {{/each}} - -{{#if data.admin_mode}} - {{#if data.is_living}} - Omnitongue {{data.omnitongue ? "Enabled" : "Disabled"}} - - {{/if}} - - {{#each data.unknown_languages}} - - {{desc}} - Key: ,{{key}} - Grant - - {{/each}} - -{{/if}} diff --git a/tgui/src/interfaces/launchpad_remote.ract b/tgui/src/interfaces/launchpad_remote.ract deleted file mode 100644 index c90ebf2e42..0000000000 --- a/tgui/src/interfaces/launchpad_remote.ract +++ /dev/null @@ -1,49 +0,0 @@ - - {{#if data.has_pad}} - {{#if data.pad_closed}} - - Launchpad closed. - - {{else}} - - {{data.pad_name}}
    - Rename - Remove -
    - - - - - - - - - - - - - - - - - - -
    ↖↑↗
    â†R→
    ↙↓↘
    -
    - - {{data.abs_y}} {{data.north_south}}
    - {{data.abs_x}} {{data.east_west}} -
    - - Launch - Pull - - - {{/if}} - - {{else}} - - No launchpad found. Link the remote to a launchpad. - - {{/if}} -
    diff --git a/tgui/src/interfaces/mech_bay_power_console.ract b/tgui/src/interfaces/mech_bay_power_console.ract deleted file mode 100644 index 7455f872cd..0000000000 --- a/tgui/src/interfaces/mech_bay_power_console.ract +++ /dev/null @@ -1,44 +0,0 @@ - - - - {{#if data.recharge_port}} - {{#if data.recharge_port.mech}} - - {{Math.round(adata.recharge_port.mech.health)}}/{{adata.recharge_port.mech.maxhealth}} - - {{#if data.recharge_port.mech.cell}} - {{#if data.recharge_port.mech.cell.critfail}} - Cell Critical Failure - {{else}} - - {{Math.round(adata.recharge_port.mech.cell.charge)}}/{{Math.round(adata.recharge_port.mech.cell.maxcharge)}} - - {{/if}} - {{else}} - Cell Missing - {{/if}} - {{else}} - Mech Not Found - {{/if}} - {{else}} - Recharging Port Not Found - Reconnect - {{/if}} - diff --git a/tgui/src/interfaces/mulebot.ract b/tgui/src/interfaces/mulebot.ract deleted file mode 100644 index 7a98a5489b..0000000000 --- a/tgui/src/interfaces/mulebot.ract +++ /dev/null @@ -1,60 +0,0 @@ - - {{#if data.siliconUser}} - - {{data.locked ? "Engaged" : "Disengaged"}} - - {{else}} - Swipe an ID card to {{data.locked ? "unlock" : "lock"}} this interface. - {{/if}} - - - - {{#if !data.locked || data.siliconUser }} - {{data.on ? "On" : "Off"}} - {{else}} - {{data.on ? "On" : "Off"}} - {{/if}} - - - {{data.cell ? data.cellPercent + "%" : "No Cell"}} - - - {{data.mode}} - - - {{data.load ? data.load : "None"}} - - - {{data.destination ? data.destination : "None"}} - - -{{#if !data.locked || data.siliconUser}} - - {{#partial button}} - {{#if data.load}} - Unload - {{/if}} - {{#if data.haspai}} - Eject PAI - {{/if}} - Set ID - {{/partial}} - - Set Destination - Stop - Go - - - Go Home - Set Home - - - - Auto-Return Home - - Auto-Pickup Crate - - Report Deliveries - - -{{/if}} diff --git a/tgui/src/interfaces/nanite_chamber_control.ract b/tgui/src/interfaces/nanite_chamber_control.ract deleted file mode 100644 index 31060f9430..0000000000 --- a/tgui/src/interfaces/nanite_chamber_control.ract +++ /dev/null @@ -1,109 +0,0 @@ - - -{{#if data.has_disk}} - Eject Disk
    - {{#if data.has_program}} - {{data.disk.name}} - {{data.disk.desc}} - {{data.disk.activated ? "Active" : "Inactive" }} - {{#if data.disk.activation_delay}} - {{data.disk.activation_delay}} - {{/if}} - {{#if data.disk.timer}} - {{data.disk.timer}} - {{data.disk.timer_type}} - {{/if}} - {{#if data.disk.activation_code}} - {{data.disk.activation_code}} - {{/if}} - {{#if data.disk.deactivation_code}} - {{data.disk.deactivation_code}} - {{/if}} - {{#if data.disk.kill_code}} - {{data.disk.kill_code}} - {{/if}} - {{#if data.disk.trigger_code}} - {{data.disk.trigger_code}} - {{/if}} - {{#if data.disk.has_extra_settings}} - {{#each data.disk.extra_settings}} - {{value}} - {{/each}} - {{/if}} - {{else}} - No program detected. - {{/if}} -{{else}} - Insert disk. -{{/if}} -
    -
    -{{#if data.status_msg}} - {{data.status_msg}} -{{else}} - - {{data.locked ? "Unlock" : "Lock" }} Chamber
    - Occupant: {{data.occupant_name}} - {{#if !data.has_nanites}} - No nanites detected. - Implant Nanites - {{else}} - - {{#if data.has_disk}} - Install Program From Disk
    -
    - {{/if}} - - {{data.nanite_volume}} - {{data.regen_rate}} - {{data.safety_threshold}} Set - {{data.cloud_id ? data.cloud_id : "No Cloud" }} Set - - - {{#each data.mob_programs}} - - Uninstall - {{desc}} - {{#if data.scan_level >= 2}} - {{activated ? "Active" : "Inactive" }} - {{use_rate}}/s - {{#if can_trigger}} - {{trigger_cost}} - {{trigger_cooldown}} seconds - {{/if}} - {{#if data.scan_level >= 3}} - {{#if activation_delay}} - {{activation_delay}} - {{/if}} - {{#if timer}} - {{timer}} - {{timer_type}} - {{/if}} - {{#if has_extra_settings}} - {{#each extra_settings}} - {{value}} - {{/each}} - {{/if}} - {{#if data.scan_level >= 4}} - {{#if activation_code}} - {{activation_code}} - {{/if}} - {{#if deactivation_code}} - {{deactivation_code}} - {{/if}} - {{#if kill_code}} - {{kill_code}} - {{/if}} - {{#if trigger_code}} - {{trigger_code}} - {{/if}} - {{/if}} - {{/if}} - {{/if}} - - {{/each}} - -
    - {{/if}} -
    -{{/if}} diff --git a/tgui/src/interfaces/nanite_cloud_control.ract b/tgui/src/interfaces/nanite_cloud_control.ract deleted file mode 100644 index a1c4dbf258..0000000000 --- a/tgui/src/interfaces/nanite_cloud_control.ract +++ /dev/null @@ -1,104 +0,0 @@ - - - {{#if data.has_disk}} - Eject Disk
    - {{#if data.has_program}} - - {{data.disk.name}} - {{data.disk.desc}} - {{data.disk.activated ? "Active" : "Inactive" }} - {{#if data.disk.activation_delay}} - {{data.disk.activation_delay}} - {{/if}} - {{#if data.disk.timer}} - {{data.disk.timer}} - {{data.disk.timer_type}} - {{/if}} - {{#if data.disk.activation_code}} - {{data.disk.activation_code}} - {{/if}} - {{#if data.disk.deactivation_code}} - {{data.disk.deactivation_code}} - {{/if}} - {{#if data.disk.kill_code}} - {{data.disk.kill_code}} - {{/if}} - {{#if data.disk.trigger_code}} - {{data.disk.trigger_code}} - {{/if}} - {{#if data.disk.has_extra_settings}} - {{#each data.disk.extra_settings}} - {{value}} - {{/each}} - {{/if}} - - {{else}} - No program detected. - {{/if}} - {{else}} - Insert disk. - {{/if}} -
    - - {{#if !data.current_view}} - Create New Backup - - {{#each data.cloud_backups}} - Backup #{{cloud_id}} - {{/each}} - - {{else}} - Return - {{#if !data.cloud_backup}} - ERROR: Backup not found. - {{else}} - - {{#if data.has_program}} - Upload Program From Disk
    - {{/if}} - {{#each data.cloud_programs}} -
    - -

    {{name}}

    -
    - Uninstall -
    -
    - - {{desc}} - {{activated ? "Active" : "Inactive" }} - {{use_rate}}/s - {{#if can_trigger}} - {{trigger_cost}}/s - {{trigger_cooldown}}/s - {{/if}} - {{#if activation_delay}} - {{activation_delay}} - {{/if}} - {{#if timer}} - {{timer}} - {{timer_type}} - {{/if}} - {{#if activation_code}} - {{activation_code}} - {{/if}} - {{#if deactivation_code}} - {{deactivation_code}} - {{/if}} - {{#if kill_code}} - {{kill_code}} - {{/if}} - {{#if trigger_code}} - {{trigger_code}} - {{/if}} - {{#if has_extra_settings}} - {{#each extra_settings}} - {{value}} - {{/each}} - {{/if}} - - {{/each}} -
    - {{/if}} - {{/if}} -
    diff --git a/tgui/src/interfaces/nanite_comm_remote.ract b/tgui/src/interfaces/nanite_comm_remote.ract deleted file mode 100644 index 9cdc5fb7f3..0000000000 --- a/tgui/src/interfaces/nanite_comm_remote.ract +++ /dev/null @@ -1,41 +0,0 @@ - -{{#if data.locked}} - The interface is locked. -{{else}} - Lock Interface - Save Current Setting - - {{data.comm_code}} - Set - - - {{data.comm_message}} -
    - Set -
    - {{#if data.mode == "Relay"}} - - {{data.relay_code}} - Set - - {{/if}} - - {{data.mode}} -
    - Off - Local - Targeted - Area - Relay -
    -{{/if}} -
    - - {{#each data.saved_settings}} - {{name}} - {{#if !data.locked}} - Remove - {{/if}} -
    - {{/each}} -
    diff --git a/tgui/src/interfaces/nanite_program_hub.ract b/tgui/src/interfaces/nanite_program_hub.ract deleted file mode 100644 index 780c8ae3fd..0000000000 --- a/tgui/src/interfaces/nanite_program_hub.ract +++ /dev/null @@ -1,49 +0,0 @@ - -{{#if data.has_disk}} - - - Eject Disk - Delete Program - - {{#if data.has_program}} - {{data.disk.name}} - {{data.disk.desc}} - {{else}} - No program installed. - {{/if}} - -{{else}} - Insert disk. -{{/if}} -
    - - - Return - {{data.detail_view ? "Compact View" : "Detailed View" }} - - {{#if data.category == "Main"}} - - {{#each data.categories}} - {{name}} - {{/each}} - - {{else}} - - {{#each data.program_list}} - {{#if data.detail_view}} - - {{name}} - {{desc}} - - - Download - - - - {{else}} - {{name}} - {{/if}} - {{/each}} - - {{/if}} - diff --git a/tgui/src/interfaces/nanite_programmer.ract b/tgui/src/interfaces/nanite_programmer.ract deleted file mode 100644 index 7c23ce08bd..0000000000 --- a/tgui/src/interfaces/nanite_programmer.ract +++ /dev/null @@ -1,54 +0,0 @@ - -{{#if !data.has_disk}} - Insert a nanite program disk. -{{else}} - Eject Disk - {{#if !data.has_program}} - No program detected. - {{else}} - - - {{data.desc}} - - - - - Nanites Consumed: {{data.use_rate}}
    - {{#if data.can_trigger}} - Trigger Cost: {{data.trigger_cost}}u
    - {{/if}} -
    - - - - {{data.activated ? "Active" : "Inactive" }} - - - - - Activation Delay: {{data.activation_delay}}
    - Timer: {{data.timer}}
    - Timer Type: {{data.timer_type}}
    -
    - - - Activation Code: {{data.activation_code}}
    - Deactivation Code: {{data.deactivation_code}}
    - Kill Code: {{data.kill_code}}
    - {{#if data.can_trigger}} - Trigger Code: {{data.trigger_code}}
    - {{/if}} -
    - - {{#if data.has_extra_settings}} - - {{#each data.extra_settings}} - {{name}}: {{value}}
    - {{/each}} -
    - {{/if}} -
    - {{/if}} -{{/if}} diff --git a/tgui/src/interfaces/nanite_remote.ract b/tgui/src/interfaces/nanite_remote.ract deleted file mode 100644 index 6e93529704..0000000000 --- a/tgui/src/interfaces/nanite_remote.ract +++ /dev/null @@ -1,36 +0,0 @@ - -{{#if data.locked}} - The interface is locked. -{{else}} - Lock Interface - Save Current Setting - - {{data.code}} - Set - - {{#if data.mode == "Relay"}} - - {{data.relay_code}} - Set - - {{/if}} - - {{data.mode}} -
    - Off - Local - Targeted - Area - Relay -
    -{{/if}} -
    - - {{#each data.saved_settings}} - {{name}} - {{#if !data.locked}} - Remove - {{/if}} -
    - {{/each}} -
    diff --git a/tgui/src/interfaces/notificationpanel.ract b/tgui/src/interfaces/notificationpanel.ract deleted file mode 100644 index d8dbe2b960..0000000000 --- a/tgui/src/interfaces/notificationpanel.ract +++ /dev/null @@ -1,7 +0,0 @@ - - - {{#each data.ignore}} - {{desc}} - {{/each}} - - diff --git a/tgui/src/interfaces/ntnet_relay.ract b/tgui/src/interfaces/ntnet_relay.ract deleted file mode 100644 index 592d235164..0000000000 --- a/tgui/src/interfaces/ntnet_relay.ract +++ /dev/null @@ -1,22 +0,0 @@ - - {{#if data.dos_crashed}} -

    NETWORK BUFFERS OVERLOADED

    -

    Overload Recovery Mode

    - This system is suffering temporary outage due to overflow of traffic buffers. Until buffered traffic is processed, all further requests will be dropped. Frequent occurences of this error may indicate insufficient hardware capacity of your network. Please contact your network planning department for instructions on how to resolve this issue. -

    ADMINISTRATIVE OVERRIDE

    - CAUTION - Data loss may occur - - Purge buffered traffic - - {{else}} - - - {{data.enabled ? "ENABLED" : "DISABLED"}} - - - - - {{data.dos_overload}} / {{data.dos_capacity}} GQ - - {{/if}} -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_ai_restorer.ract b/tgui/src/interfaces/ntos_ai_restorer.ract deleted file mode 100644 index 97fe80c711..0000000000 --- a/tgui/src/interfaces/ntos_ai_restorer.ract +++ /dev/null @@ -1,78 +0,0 @@ - - - - - -{{#if data.restoring}} - - Reconstruction in progress! - -{{/if}} - - - - -
    -
    - Inserted AI: -
    -
    - {{data.name ? data.name : "---"}} -
    -
    - -{{#if data.error}} - ERROR: {{data.error}} -{{else}} -

    System Status

    -
    -
    - Current AI: -
    -
    - {{data.name}} -
    -
    - Status: -
    -
    - {{#if data.isDead}} - Nonfunctional - {{else}} - Functional - {{/if}} -
    -
    - System Integrity: -
    -
    - {{Math.round(adata.health)}}% -
    -
    - Active Laws: -
    -
    - - {{#each data.ai_laws}} -
    {{.}} - {{/each}} -
    -
    - - Begin Reconstruction - -{{/if}} - - \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_card.ract b/tgui/src/interfaces/ntos_card.ract deleted file mode 100644 index 3d7cbba9b2..0000000000 --- a/tgui/src/interfaces/ntos_card.ract +++ /dev/null @@ -1,228 +0,0 @@ - - - -{{#if data.have_id_slot}} -Access Modification -{{/if}} -Job Management -Crew Manifest -{{#if data.have_printer}} -Print -{{/if}} - -{{#if !data.mmode}} -
    -

    Crew Manifest

    -
    Please use security record computer to modify entries.

    -
    -{{#each data.manifest}} -
    - {{name}} - {{rank}} -
    -{{/each}} - -{{elseif data.mmode == 2}} -
    -

    Job Management

    -
    - - -{{#each data.slots}} - - - -{{/each}} -
    JobSlotsOpen jobClose job
    {{title}}{{current}}/{{total}}{{desc_open}}
    {{desc_close}} -
    - - -{{else}} -
    -

    Access Modification

    -
    - -{{#if !data.has_id}} - Please insert the ID into the terminal to proceed.
    -{{/if}} - -
    -
    - Target Identity: -
    -
    - {{data.id_name}} -
    -
    -
    -
    - Auth Identity: -
    -
    - {{data.auth_name}} -
    -
    -
    - -{{#if data.authenticated}} - {{#if data.has_id}} -
    -

    Details

    -
    - - {{#if data.minor}} -
    -
    - Registered Name: -
    -
    - {{data.id_owner}} -
    -
    -
    -
    - Rank: -
    -
    - {{data.id_rank}} -
    -
    -
    -
    - Demote: -
    -
    - Demote {{data.id_owner}} -
    -
    - {{else}} - -
    -
    - Registered Name: -
    -
    - {{data.id_owner}} -
    -
    - -
    -

    Assignment

    -
    - {{data.assignments ? "Hide assignments" : "Show assignments"}} -
    - - - -
    -
    - {{#if data.assignments}} -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {{#if data.centcom_access}} - - - - - {{/if}} -
    Command - Captain -
    Special - Custom -
    Engineering - {{#each data.engineering_jobs}} - {{display_name}} - {{/each}} -
    Medical - {{#each data.medical_jobs}} - {{display_name}} - {{/each}} -
    Science - {{#each data.science_jobs}} - {{display_name}} - {{/each}} -
    Security - {{#each data.security_jobs}} - {{display_name}} - {{/each}} -
    Cargo - {{#each data.cargo_jobs}} - {{display_name}} - {{/each}} -
    Civilian - {{#each data.civilian_jobs}} - {{display_name}} - {{/each}} -
    CentCom - {{#each data.centcom_jobs}} - {{display_name}} - {{/each}} -
    -
    - {{/if}} -
    - {{/if}} - - {{#if data.centcom_access}} -
    -

    Central Command

    -
    -
    - {{#each data.all_centcom_access}} -
    - {{desc}} -
    - {{/each}} -
    - {{else}} -
    -

    {{data.station_name}}

    -
    -
    - {{#each data.regions}} -
    -
    {{name}}
    -
    - {{#each accesses}} -
    - {{desc}} -
    - {{/each}} -
    - {{/each}} -
    - {{/if}} - {{/if}} -{{/if}} -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_configuration.ract b/tgui/src/interfaces/ntos_configuration.ract deleted file mode 100644 index 30c6a4166c..0000000000 --- a/tgui/src/interfaces/ntos_configuration.ract +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - Welcome to computer configuration utility. Please consult your system administrator if you have any questions about your device.
    - - - {{data.power_usage}}W - - - {{#if data.battery}} - - Active - - - {{data.battery.max}} - - - {{Math.round(adata.battery.charge)}}/{{adata.battery.max}} - - {{else}} - - Not Available - - {{/if}} - - - - - {{Math.round(adata.disk_used)}}GQ / {{adata.disk_size}}GQ - - - - - {{#each data.hardware}} - -
    {{desc}}
    - - - - {{enabled ? "Enabled" : "Disabled"}} - - - - {{#if powerusage}} - - {{powerusage}}W - - {{/if}} -
    -
    - {{/each}} -
    -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_file_manager.ract b/tgui/src/interfaces/ntos_file_manager.ract deleted file mode 100644 index efc3b15cb3..0000000000 --- a/tgui/src/interfaces/ntos_file_manager.ract +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - {{#if data.error}} -

    An error has occurred and this program can not continue.

    - Additional information: {{data.error}}
    - Please try again. If the problem persists contact your system administrator for assistance. - Restart program - {{else}} - {{#if data.filename}} -

    Viewing file {{data.filename}}

    -
    - CLOSE - EDIT - PRINT -

    - {{{data.filedata}}} - {{else}} -

    Available files (local):

    - - - - - - - - {{#each data.files}} - - - - - - - {{/each}} -
    File nameFile typeFile size (GQ)Operations
    {{name}}.{{type}}{{size}}GQ - VIEW - DELETE - RENAME - CLONE - {{#if data.usbconnected}} - EXPORT - {{/if}} -
    - {{#if data.usbconnected}} -

    Available files (portable device):

    - - - - - - - - {{#each data.usbfiles}} - - - - - - - {{/each}} -
    File nameFile typeFile size (GQ)Operations
    {{name}}.{{type}}{{size}}GQ - DELETE - {{#if data.usbconnected}} - IMPORT - {{/if}} -
    - {{/if}} - NEW DATA FILE - {{/if}} - - {{/if}} - -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_main.ract b/tgui/src/interfaces/ntos_main.ract deleted file mode 100644 index 8dd5c8aeec..0000000000 --- a/tgui/src/interfaces/ntos_main.ract +++ /dev/null @@ -1,19 +0,0 @@ - - - - - No program loaded. Please select program from list below. - - {{#each data.programs}} -
    - {{desc}} - - - {{/each}} -
    -

    - {{#if data.has_light}} - Toggle Flashlight
    - Change Flashlight Color     - {{/if}} -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_net_chat.ract b/tgui/src/interfaces/ntos_net_chat.ract deleted file mode 100644 index 7ea9055a4c..0000000000 --- a/tgui/src/interfaces/ntos_net_chat.ract +++ /dev/null @@ -1,71 +0,0 @@ - - - - - {{#if data.adminmode}} -

    ADMINISTRATIVE MODE

    - {{/if}} - - {{#if data.title}} -
    - Current channel: -
    -
    - {{data.title}} -
    -
    - Operator access: -
    -
    - {{#if data.is_operator}} - Enabled - {{else}} - Disabled - {{/if}} -
    -
    - Controls: -
    -
    - -
    Send message -
    Change nickname -
    Toggle administration mode -
    Leave channel -
    Save log to local drive - {{#if data.is_operator}} -
    Rename channel -
    Set password -
    Delete channel - {{/if}} -
    -
    - Chat Window -
    -
    -
    - {{#each data.messages}} - {{msg}}
    - {{/each}} -
    -
    -
    - Connected Users
    - {{#each data.clients}} - {{name}}
    - {{/each}} - {{else}} - Controls: - -
    Change nickname -
    New Channel -
    Toggle administration mode -
    - Available channels: - - {{#each data.all_channels}} -
    {{chan}}
    - {{/each}} -
    - {{/if}} -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_net_dos.ract b/tgui/src/interfaces/ntos_net_dos.ract deleted file mode 100644 index c9505b4e01..0000000000 --- a/tgui/src/interfaces/ntos_net_dos.ract +++ /dev/null @@ -1,26 +0,0 @@ - - - - - {{#if data.error}} - ##SYSTEM ERROR: {{data.error}}RESET - {{elseif data.target}} - ##DoS traffic generator active. Tx: {{data.speed}}GQ/s
    - {{#each data.dos_strings}} - {{nums}}
    - {{/each}} - ABORT - {{else}} - ##DoS traffic generator ready. Select target device.
    - {{#if data.focus}} - Targeted device ID: {{data.focus}} - {{else}} - Targeted device ID: None - {{/if}} - EXECUTE
    - Detected devices on network:
    - {{#each data.relays}} - {{id}} - {{/each}} - {{/if}} -
    diff --git a/tgui/src/interfaces/ntos_net_downloader.ract b/tgui/src/interfaces/ntos_net_downloader.ract deleted file mode 100644 index 41a3011142..0000000000 --- a/tgui/src/interfaces/ntos_net_downloader.ract +++ /dev/null @@ -1,90 +0,0 @@ - - - - - Welcome to software download utility. Please select which software you wish to download.
    - {{#if data.error}} - - - {{data.error}} - - - - RESET - - - - {{else}} - {{#if data.downloadname}} - - Please wait... - - {{data.downloadname}} - - - {{data.downloaddesc}} - - - {{data.downloadsize}}GQ - - - {{data.downloadspeed}} GQ/s - - - {{Math.round(adata.downloadcompletion)}}GQ / {{adata.downloadsize}}GQ - - - {{/if}} - {{/if}} - {{#if !data.downloadname}} - {{#if !data.error}} - - - {{Math.round(adata.disk_used)}}GQ / {{adata.disk_size}}GQ - - - - - {{#each data.downloadable_programs}} - -
    {{fileinfo}}
    - - - {{filename}} ({{size}} GQ) - - - {{compatibility}} - - - DOWNLOAD - -
    -
    - {{/each}} -
    - - {{#if data.hackedavailable}} - - Please note that Nanotrasen does not recommend download of software from non-official servers. - {{#each data.hacked_programs}} - -
    {{fileinfo}}
    - - - {{filename}} ({{size}} GQ) - - - {{compatibility}} - - - DOWNLOAD - -
    -
    - {{/each}} -
    - {{/if}} - {{/if}} - {{/if}} -


    NTOS v2.0.4b Copyright Nanotrasen 2557 - 2559 -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_net_monitor.ract b/tgui/src/interfaces/ntos_net_monitor.ract deleted file mode 100644 index 0aeaba6c34..0000000000 --- a/tgui/src/interfaces/ntos_net_monitor.ract +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - {{data.ntnetrelays}} - - {{#if data.ntnetrelays}} - - {{data.ntnetstatus ? "ENABLED" : "DISABLED"}} - - - - - TOGGLE - - -

    - Caution - Disabling wireless transmitters when using wireless device may prevent you from re-enabling them again! - {{else}} -

    Wireless coverage unavailable, no relays are connected.

    - {{/if}} -
    - - - - - - - - - - -
    PROTOCOL - STATUS - CONTROL -
    Software Downloads - {{data.config_softwaredownload ? 'ENABLED' : 'DISABLED'}} - TOGGLE -
    Peer to Peer Traffic - {{data.config_peertopeer ? 'ENABLED' : 'DISABLED'}} - TOGGLE -
    Communication Systems - {{data.config_communication ? 'ENABLED' : 'DISABLED'}} - TOGGLE -
    Remote System Control - {{data.config_systemcontrol ? 'ENABLED' : 'DISABLED'}} - TOGGLE -
    -
    - - - - {{#if data.idsalarm}} - -

    NETWORK INCURSION DETECTED

    -
    - An abnormal activity has been detected in the network. Please verify system logs for more information - - {{/if}} - - {{data.idsstatus ? 'ENABLED' : 'DISABLED'}} - - - - {{data.ntnetmaxlogs}} - - - - - -
    RESET IDS -
    TOGGLE IDS -
    SET LOG LIMIT -
    PURGE LOGS -
    - - -
    -
    -
    - {{#each data.ntnetlogs}} - {{entry}}
    - {{/each}} -
    -
    -
    -
    - -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_net_transfer.ract b/tgui/src/interfaces/ntos_net_transfer.ract deleted file mode 100644 index 8686952222..0000000000 --- a/tgui/src/interfaces/ntos_net_transfer.ract +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - {{#if data.error}} -
    -

    An error has occurred during operation...

    - Additional information: {{data.error}}
    - Clear -
    - {{elseif data.downloading}} -

    Download in progress...

    -
    - Downloaded file: -
    -
    - {{data.download_name}} -
    -
    - Download progress: -
    -
    - {{data.download_progress}} / {{data.download_size}} GQ -
    -
    - Transfer speed: -
    -
    - {{data.download_netspeed}}GQ/s -
    -
    - Controls: -
    -
    - Abort download -
    - {{elseif data.uploading}} -

    Server enabled

    -
    - Connected clients: -
    -
    - {{data.upload_clients}} -
    -
    - Provided file: -
    -
    - {{data.upload_filename}} -
    -
    - Server password: -
    -
    - {{#if data.upload_haspassword}} - ENABLED - {{else}} - DISABLED - {{/if}} -
    -
    - Commands: -
    -
    - Set password - Exit server -
    - {{elseif data.upload_filelist}} -

    File transfer server ready. Select file to upload:

    - -
    File nameFile sizeControls - {{#each data.upload_filelist}} -
    {{filename}} - {{size}}GQ - Select - {{/each}} -
    -
    - Set password - Return - {{else}} -

    Available files:

    -
    Server UIDFile NameFile SizePassword ProtectionOperations - {{#each data.servers}} -
    {{uid}} - {{filename}} - {{size}}GQ - {{#if haspassword}} - Enabled - {{/if}} - {{#if !haspassword}} - Disabled - {{/if}} - - Download - {{/each}} -
    -
    - Send file - {{/if}} - -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_power_monitor.ract b/tgui/src/interfaces/ntos_power_monitor.ract deleted file mode 100644 index d29551af15..0000000000 --- a/tgui/src/interfaces/ntos_power_monitor.ract +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - {{#if config.fancy}} - - {{else}} - - {{data.supply}} - - - {{data.demand}} - - {{/if}} - - - -
    Area
    -
    Charge
    -
    Load
    -
    Status
    -
    Equipment
    -
    Lighting
    -
    Environment
    -
    - {{#each data.areas}} - -
    {{Math.round(adata.areas[@index].charge)}} %
    -
    {{adata.areas[@index].load}}
    -
    {{chargingMode(charging)}}
    -
    {{channelPower(eqp)}} [{{channelMode(eqp)}}]
    -
    {{channelPower(lgt)}} [{{channelMode(lgt)}}]
    -
    {{channelPower(env)}} [{{channelMode(env)}}]
    -
    - {{/each}} -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_revelation.ract b/tgui/src/interfaces/ntos_revelation.ract deleted file mode 100644 index bae7800348..0000000000 --- a/tgui/src/interfaces/ntos_revelation.ract +++ /dev/null @@ -1,27 +0,0 @@ - - - - -
    -
    - Payload status: -
    -
    - {{#if data.armed}} - ARMED - {{else}} - DISARMED - {{/if}} -
    -
    - Controls: -
    -
    - -
    OBFUSCATE PROGRAM NAME -
    {{data.armed ? "DISARM" : "ARM"}} - ACTIVATE -
    -
    -
    -
    \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_station_alert.ract b/tgui/src/interfaces/ntos_station_alert.ract deleted file mode 100644 index 3b74ee0509..0000000000 --- a/tgui/src/interfaces/ntos_station_alert.ract +++ /dev/null @@ -1,14 +0,0 @@ - - - -{{#each data.alarms:class}} - -
      - {{#each .}} -
    • {{.}}
    • - {{else}} -
    • System Nominal
    • - {{/each}} -
    -
    -{{/each}} \ No newline at end of file diff --git a/tgui/src/interfaces/ntos_supermatter_monitor.ract b/tgui/src/interfaces/ntos_supermatter_monitor.ract deleted file mode 100644 index 4ea61b7430..0000000000 --- a/tgui/src/interfaces/ntos_supermatter_monitor.ract +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - -{{#if data.active}} - Back to Menu
    - - - {{data.SM_integrity}}% - - - {{data.SM_power}} MeV/cm3 - - - {{data.SM_ambienttemp}} K - - - {{data.SM_ambientpressure}} kPa - - -

    - - {{#each data.gases}} - - {{amount}} % - - {{/each}} - -{{else}} - Refresh
    - - {{#each data.supermatters}} - - {{area_name}} - (#{{uid}}) - - - {{integrity}} % - - - View Details - - {{/each}} - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/ntosheader.ract b/tgui/src/interfaces/ntosheader.ract deleted file mode 100644 index 4468f1722a..0000000000 --- a/tgui/src/interfaces/ntosheader.ract +++ /dev/null @@ -1,30 +0,0 @@ -
    - - {{#if data.PC_batteryicon && data.PC_showbatteryicon}} -
    - {{/if}} - {{#if data.PC_batterypercent && data.PC_showbatteryicon}} - {{data.PC_batterypercent}} - {{/if}} - {{#if data.PC_ntneticon}} - - {{/if}} - {{#if data.PC_apclinkicon}} - - {{/if}} - {{#if data.PC_stationtime}} - {{data.PC_stationtime}} - {{/if}} - {{#each data.PC_programheaders}} - - {{/each}} -
    -
    -
    - Shutdown - {{#if data.PC_showexitprogram}} - EXIT PROGRAM - Minimize Program - {{/if}} -
    -
    \ No newline at end of file diff --git a/tgui/src/interfaces/nuclear_bomb.ract b/tgui/src/interfaces/nuclear_bomb.ract deleted file mode 100644 index b326874dcf..0000000000 --- a/tgui/src/interfaces/nuclear_bomb.ract +++ /dev/null @@ -1,68 +0,0 @@ - - {{#if data.disk_present}} - ++++++++++ - {{else}} - ---------- - {{/if}} - - - {{data.status1}}-{{data.status2}} - - - - {{data.timing ? data.time_left : data.timer_set}} - - {{^data.timing}} - - Reset - Decrease - Set - Increase - - {{/data.timing}} - - - {{data.timing ? "On" : "Off"}} - - - - - {{data.anchored ? "Engaged" : "Off"}} - - - - {{data.safety ? "On" : "Off"}} - - - - {{data.message}} - - 1 - 2 - 3 -
    - 4 - 5 - 6 -
    - 7 - 8 - 9 -
    - R - 0 - E -
    -
    diff --git a/tgui/src/interfaces/operating_computer.ract b/tgui/src/interfaces/operating_computer.ract deleted file mode 100644 index ab48c204b3..0000000000 --- a/tgui/src/interfaces/operating_computer.ract +++ /dev/null @@ -1,66 +0,0 @@ -{{#if data.menu == 2}} - Return - - Sync with research database - {{#each data.surgeries}} - - {{name}} - {{desc}} - - {{/each}} - -{{else}} - View Surgery Procedures - {{#unless data.table}} - - No table detected! - - {{/unless}} - - - {{#if data.patient}} - - {{data.patient.stat}} - - - {{data.patient.blood_type}} - - - {{Math.round(adata.patient.health)}} - - {{#each [{label: "Brute", type: "bruteLoss"}, {label: "Burn", type: "fireLoss"}, {label: "Toxin", type: "toxLoss"}, {label: "Respiratory", type: "oxyLoss"}]}} - - {{Math.round(adata.patient[type])}} - - {{/each}} - {{else}} - No patient detected. - {{/if}} - - - {{#if data.procedures}} - {{#each data.procedures}} - - - {{next_step}} - {{#if chems_needed}} - Required chemicals:
    {{chems_needed}}
    - {{/if}} -
    - {{#if alternative_step}} - - {{alternative_step}} - {{#if alt_chems_needed}} - Required chemicals:
    {{chems_needed}}
    - {{/if}} -
    - {{/if}} -
    - {{/each}} - {{else}} - No active procedures. - {{/if}} -
    -
    -{{/if}} diff --git a/tgui/src/interfaces/ore_redemption_machine.ract b/tgui/src/interfaces/ore_redemption_machine.ract deleted file mode 100644 index 650c5ddd5e..0000000000 --- a/tgui/src/interfaces/ore_redemption_machine.ract +++ /dev/null @@ -1,101 +0,0 @@ - - - This machine only accepts ore. Gibtonite and Slag are not accepted. - - - Current unclaimed credits: {{data.unclaimedPoints}} - - Claim - - - - - {{#if data.hasDisk}} - - - Eject Disk - - - {{#each data.diskDesigns}} - - - Upload - - File {{index}}: {{name}} - - {{/each}} - {{else}} - - - Insert Disk - - - {{/if}} - -{{#if data.disconnected}} - - - Warning: {{data.disconnected}}. Please contact the quartermaster. - - -{{/if}} -{{#if data.materials || data.alloys}} -
    -
    -
    - Mineral -
    -
    - Sheets -
    -
    -
    -
    -
    -
    - Ore Value -
    -
    - {{#each data.materials}} -
    -
    - {{name}} -
    -
    - {{amount}} -
    -
    - -
    -
    - = 1) ? null : 'disabled'}} params='{ "id" : {{id}}, "sheets" : {{sheets}} }' > - Release - -
    -
    - {{value}} -
    -
    - {{/each}} - {{#each data.alloys}} -
    -
    - {{name}} -
    -
    - {{amount}} -
    -
    - -
    -
    - = 1) ? null : 'disabled'}} params='{ "id" : {{id}}, "sheets" : {{sheets}} }'> - Smelt - -
    -
    -
    -
    - {{/each}} -
    -{{/if}} diff --git a/tgui/src/interfaces/pandemic.ract b/tgui/src/interfaces/pandemic.ract deleted file mode 100644 index f9bfc0566b..0000000000 --- a/tgui/src/interfaces/pandemic.ract +++ /dev/null @@ -1,113 +0,0 @@ -{{#if data.mode == 1}} - - {{#partial button}} - - Empty and eject - - - Empty - - - Eject - - {{/partial}} - {{#if data.has_beaker}} - - {{#if data.beaker_empty}} - The beaker is empty! - {{else}} - - {{#if data.has_blood}} - {{data.blood.dna}} - {{data.blood.type}} - {{else}} - - No blood sample detected. - - {{/if}} - - {{/if}} - - {{else}} - - No beaker loaded. - - {{/if}} - - {{#if data.has_blood}} - - {{#each data.viruses}} - - {{#partial button}} - {{#if is_adv}} - - Name advanced disease - - {{/if}} - - Create virus culture bottle - - {{/partial}} - {{agent}} - {{description}} - {{spread}} - {{cure}} - {{#if is_adv}} - - {{#each symptoms}} - - {{name}} -
    - {{/each}} -
    - {{resistance}} - {{stealth}} - {{stage_speed}} - {{transmission}} - {{/if}} -
    - {{else}} - - No detectable virus in the blood sample. - - {{/each}} -
    - - {{#each data.resistances}} - - - Create vaccine bottle - - - {{else}} - - No antibodies detected in the blood sample. - - {{/each}} - - {{/if}} -{{else}} - - Back - - {{#with data.symptom}} - - - {{desc}} - {{#if neutered}} -
    - This symptom has been neutered, and has no effect. It will still affect the virus' statistics. - {{/if}} -
    - - {{level}} - {{resistance}} - {{stealth}} - {{stage_speed}} - {{transmission}} - - - {{{threshold_desc}}} - - {{/with}} -{{/if}} diff --git a/tgui/src/interfaces/personal_crafting.ract b/tgui/src/interfaces/personal_crafting.ract deleted file mode 100644 index 962d320c08..0000000000 --- a/tgui/src/interfaces/personal_crafting.ract +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - {{#if data.busy}} - - Crafting... - - {{else}} - - - - - - - - - - {{#if data.subcategory}} - - - {{/if}} - -
    - - {{data.prev_cat}} - - - - {{data.next_cat}} - - - {{#if data.display_craftable_only}} - - Showing Craftable Recipes - - {{else}} - - Showing All Recipes - - {{/if}} - - - Compact - -
    - - {{data.prev_subcat}} - - - - {{data.next_subcat}} - -
    - {{#if config.fancy}} - {{^data.display_compact}} {{! This doesn't work in compact mode, so let's hide it}} - - {{/data.display_compact}} - {{/if}} -
    - {{#if data.display_compact}} - - {{#each data.can_craft}} - - - Craft - - - {{/each}} - {{^data.display_craftable_only}} - {{#each data.cant_craft}} - - - Craft - - - {{/each}} - {{/data.display_craftable_only}} - - {{else}} - {{#each data.can_craft}} - - {{#if req_text}} - - {{req_text}} - - {{/if}} - {{#if catalyst_text}} - - {{catalyst_text}} - - {{/if}} - {{#if tool_text}} - - {{tool_text}} - - {{/if}} - - - Craft - - - - {{/each}} - {{^data.display_craftable_only}} - {{#each data.cant_craft}} - - {{#if req_text}} - - {{req_text}} - - {{/if}} - {{#if catalyst_text}} - - {{catalyst_text}} - - {{/if}} - {{#if tool_text}} - - {{tool_text}} - - {{/if}} - - {{/each}} - {{/data.display_craftable_only}} - {{/if}} - {{/if}} -
    diff --git a/tgui/src/interfaces/point_bank.ract b/tgui/src/interfaces/point_bank.ract deleted file mode 100644 index 837a66427a..0000000000 --- a/tgui/src/interfaces/point_bank.ract +++ /dev/null @@ -1,60 +0,0 @@ - - - Current stored points: {{data.totalPoints}} -
    -
    - - -All - -
    -
    - - -1000 - -
    -
    - - -100 - -
    -
    - - -10 - -
    -
    - - -1 - -
    -
    - Transfer Points -
    -
    - - +1 - -
    -
    - - +10 - -
    -
    - - +100 - -
    -
    - - +1000 - -
    -
    - - +All - -
    -
    -
    -
    diff --git a/tgui/src/interfaces/portable_pump.ract b/tgui/src/interfaces/portable_pump.ract deleted file mode 100644 index c9b780f231..0000000000 --- a/tgui/src/interfaces/portable_pump.ract +++ /dev/null @@ -1,54 +0,0 @@ - - The regulator {{data.holding ? "is" : "is not"}} connected to a tank. - - - - {{Math.round(adata.pressure)}} kPa - - - {{data.connected ? "Connected" : "Not Connected"}} - - - - - {{data.on ? "On" : "Off"}} - - - {{data.direction == "out" ? "Out" : "In"}} - - - {{Math.round(adata.target_pressure)}} kPa - - - Reset - Min - Set - Max - - - - {{#partial button}} - {{#if data.holding}} - Eject - {{/if}} - {{/partial}} - {{#if data.holding}} - - {{data.holding.name}} - - - {{Math.round(adata.holding.pressure)}} kPa - - {{else}} - - No Holding Tank - - {{/if}} - diff --git a/tgui/src/interfaces/portable_scrubber.ract b/tgui/src/interfaces/portable_scrubber.ract deleted file mode 100644 index 3f89775ee2..0000000000 --- a/tgui/src/interfaces/portable_scrubber.ract +++ /dev/null @@ -1,44 +0,0 @@ - - - - The regulator {{data.holding ? "is" : "is not"}} connected to a tank. - - - - {{Math.round(adata.pressure)}} kPa - - - {{data.connected ? "Connected" : "Not Connected"}} - - - - - {{data.on ? "On" : "Off"}} - - - - {{#partial button}} - {{#if data.holding}} - Eject - {{/if}} - {{/partial}} - {{#if data.holding}} - - {{data.holding.name}} - - - {{Math.round(adata.holding.pressure)}} kPa - - {{else}} - - No Holding Tank - - {{/if}} - - - {{#with data}} - - {{/with}} - diff --git a/tgui/src/interfaces/power_monitor.ract b/tgui/src/interfaces/power_monitor.ract deleted file mode 100644 index 856b3ceefa..0000000000 --- a/tgui/src/interfaces/power_monitor.ract +++ /dev/null @@ -1,77 +0,0 @@ - - - - {{#if config.fancy}} - - {{else}} - - {{data.supply}} - - - {{data.demand}} - - {{/if}} - - - -
    Area
    -
    Charge
    -
    Load
    -
    Status
    -
    Equipment
    -
    Lighting
    -
    Environment
    -
    - {{#each data.areas}} - -
    {{Math.round(adata.areas[@index].charge)}} %
    -
    {{adata.areas[@index].load}}
    -
    {{chargingMode(charging)}}
    -
    {{channelPower(eqp)}} [{{channelMode(eqp)}}]
    -
    {{channelPower(lgt)}} [{{channelMode(lgt)}}]
    -
    {{channelPower(env)}} [{{channelMode(env)}}]
    -
    - {{/each}} -
    diff --git a/tgui/src/interfaces/radio.ract b/tgui/src/interfaces/radio.ract deleted file mode 100644 index a07347b940..0000000000 --- a/tgui/src/interfaces/radio.ract +++ /dev/null @@ -1,66 +0,0 @@ - - - - {{#if data.headset}} - - - {{data.listening ? "On": "Off"}} - - {{else}} - - - {{data.broadcasting ? "Engaged": "Disengaged"}} - - - - {{data.listening ? "Engaged": "Disengaged"}} - - {{/if}} - {{#if data.command}} - - - {{data.useCommand ? "On": "Off"}} - - {{/if}} - - - - {{#if data.freqlock}} - {{readableFrequency}} - {{else}} - - - {{readableFrequency}} - - - {{/if}} - - {{#if data.subspaceSwitchable}} - - {{data.subspace ? "Active" : "Inactive"}} - - {{/if}} - {{#if data.subspace && data.channels}} - - {{#each data.channels:channel}} - - {{channel}}
    - {{/each}} -
    - {{/if}} -
    diff --git a/tgui/src/interfaces/rdconsole.ract b/tgui/src/interfaces/rdconsole.ract deleted file mode 100644 index acba78c90e..0000000000 --- a/tgui/src/interfaces/rdconsole.ract +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - -{{#if data.locked}} - - Unlock - -{{/if}} -{{#if !data.locked}} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/rdconsole/circuit.ract b/tgui/src/interfaces/rdconsole/circuit.ract deleted file mode 100644 index c8df6c139c..0000000000 --- a/tgui/src/interfaces/rdconsole/circuit.ract +++ /dev/null @@ -1,57 +0,0 @@ -{{#if data.circuit_linked}} - {{#if data.circuitbusy}} - - {{else}} - - Search Available Designs: - - Search - - Materials: {{data.circuitmats}} / {{data.circuitmaxmats}} - Reagents: {{data.circuitchems}} / {{data.circuitmaxchems}} - - - - - {{#each data.circuitcats}} - {{name}} - {{/each}} - - - {{#each data.circuitdes}} - {{name}}{{matstring}} - Print - - {{/each}} - - - {{#each data.circuitmatch}} - {{name}}{{matstring}} - Print - - {{/each}} - - - {{#each data.circuitmat_list}} - {{name}} : {{amount}} cm3 - - {{#if sheets > 0}} - - Release - {{/if}} - - {{/each}} - - - {{#each data.circuitchem_list}} - {{name}} : {{amount}} - - Purge - - {{/each}} - - - - {{/if}} -{{else}} - -{{/if}} - diff --git a/tgui/src/interfaces/rdconsole/designview.ract b/tgui/src/interfaces/rdconsole/designview.ract deleted file mode 100644 index 1ec2d92a95..0000000000 --- a/tgui/src/interfaces/rdconsole/designview.ract +++ /dev/null @@ -1,48 +0,0 @@ -{{#if data.design_selected}} - - {{data.sdesign_desc}} - - - {{#if (data.sdesign_buildtype & 1)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 2)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 4)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 8)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 16)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 32)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 64)}} - - {{/if}} - {{#if (data.sdesign_buildtype & 128)}} - - {{/if}} - - - {{#each data.sdesign_materials}} - {{matamt}} cm^3 - {{/each}} - -{{/if}} -{{#if !data.design_selected}} - -{{/if}} - - - - - - - - - diff --git a/tgui/src/interfaces/rdconsole/destruct.ract b/tgui/src/interfaces/rdconsole/destruct.ract deleted file mode 100644 index c17e183704..0000000000 --- a/tgui/src/interfaces/rdconsole/destruct.ract +++ /dev/null @@ -1,25 +0,0 @@ - -{{#if data.destroy_linked}} - {{#if data.destroybusy}} - - {{else}} - {{#if !data.destroy_loaded}} - - {{else}} - - {{data.destroy_name}} - - - {{#each data.boost_paths}} - - Deconstruct and Boost - - {{/each}} - - Eject Item - {{/if}} - {{/if}} -{{else}} - -{{/if}} - diff --git a/tgui/src/interfaces/rdconsole/diskopsdesign.ract b/tgui/src/interfaces/rdconsole/diskopsdesign.ract deleted file mode 100644 index ce949b3fb6..0000000000 --- a/tgui/src/interfaces/rdconsole/diskopsdesign.ract +++ /dev/null @@ -1,34 +0,0 @@ - -{{#if !data.ddisk}} - -{{else}} - {{#if data.ddisk_update}} - - {{else}} - {{#if !data.ddisk_upload}} - - Disk Capacity: {{data.ddisk_size}} blueprints. - Upload all designs - WIPE ALL DATA - Eject Disk - - - {{#each data.ddisk_designs}} - #{{pos}}: - {{#if id == "null"}} - Upload to Empty Slot - {{else}} - {{name}} - Delete Slot - {{/if}} - - {{/each}} - - {{else}} - Available Designs: - {{#each data.ddisk_possible_designs}} - {{name}} - {{/each}} - {{/if}} - {{/if}} -{{/if}} diff --git a/tgui/src/interfaces/rdconsole/diskopstech.ract b/tgui/src/interfaces/rdconsole/diskopstech.ract deleted file mode 100644 index de05a67a91..0000000000 --- a/tgui/src/interfaces/rdconsole/diskopstech.ract +++ /dev/null @@ -1,19 +0,0 @@ - -{{#if !data.tdisk}} - -{{else}} - {{#if data.tdisk_update}} - - {{else}} - - Download Research to DiskUpload Research from Disk - WIPE ALL DATA - Eject Disk - - - {{#each data.tdisk_nodes}} - {{display_name}} - {{/each}} - - {{/if}} -{{/if}} diff --git a/tgui/src/interfaces/rdconsole/nodeview.ract b/tgui/src/interfaces/rdconsole/nodeview.ract deleted file mode 100644 index 929c6f1787..0000000000 --- a/tgui/src/interfaces/rdconsole/nodeview.ract +++ /dev/null @@ -1,26 +0,0 @@ -{{#if data.node_selected}} - - Description: {{data.snode_desc}} - Point Cost: {{data.snode_cost}} - Export Price: {{data.snode_export}} - {{data.snode_researched? "Researched" : "Research Node"}} - - - {{#each data.node_prereqs}} - {{display_name}} - {{/each}} - - - {{#each data.node_unlocks}} - {{display_name}} - {{/each}} - - - {{#each data.node_designs}} - {{name}} - {{/each}} - -{{/if}} -{{#if !data.node_selected}} - -{{/if}} diff --git a/tgui/src/interfaces/rdconsole/protolathe.ract b/tgui/src/interfaces/rdconsole/protolathe.ract deleted file mode 100644 index a3a0486643..0000000000 --- a/tgui/src/interfaces/rdconsole/protolathe.ract +++ /dev/null @@ -1,62 +0,0 @@ -{{#if data.protolathe_linked}} - {{#if data.protobusy}} - - {{else}} - - Search Available Designs: - - Search - - Materials: {{data.protomats}} / {{data.protomaxmats}} - Reagents: {{data.protochems}} / {{data.protomaxchems}} - - - - - {{#each data.protocats}} - {{name}} - {{/each}} - - - {{#each data.protodes}} - {{name}}{{matstring}} - {{#if canprint > 1}} - - {{/if}} - Print - - {{/each}} - - - {{#each data.protomatch}} - {{name}}{{matstring}} - {{#if canprint > 1}} - - {{/if}} - Print - - {{/each}} - - - {{#each data.protomat_list}} - {{name}} : {{amount}} cm3 - - {{#if sheets > 0}} - - Release - {{/if}} - - {{/each}} - - - {{#each data.protochem_list}} - {{name}} : {{amount}} - - Purge - - {{/each}} - - - - {{/if}} -{{else}} - -{{/if}} diff --git a/tgui/src/interfaces/rdconsole/rdheader.ract b/tgui/src/interfaces/rdconsole/rdheader.ract deleted file mode 100644 index 72902ce524..0000000000 --- a/tgui/src/interfaces/rdconsole/rdheader.ract +++ /dev/null @@ -1,7 +0,0 @@ - -Nanotrasen R&D Console
    -Available Points: {{data.research_points_stored}} - -Select Page: [Go] - -
    diff --git a/tgui/src/interfaces/rdconsole/settings.ract b/tgui/src/interfaces/rdconsole/settings.ract deleted file mode 100644 index 84ab3e8786..0000000000 --- a/tgui/src/interfaces/rdconsole/settings.ract +++ /dev/null @@ -1,6 +0,0 @@ -Settings

    -RESYNC MACHINERY
    -LOCK -Disconnect Destructive Analyzer -Disconnect Protolathe -Disconnect Circuit Imprinter diff --git a/tgui/src/interfaces/rdconsole/techweb.ract b/tgui/src/interfaces/rdconsole/techweb.ract deleted file mode 100644 index 6f78698db7..0000000000 --- a/tgui/src/interfaces/rdconsole/techweb.ract +++ /dev/null @@ -1,15 +0,0 @@ - - {{#each data.techweb_avail}} - {{display_name}} - {{/each}} - - - {{#each data.techweb_locked}} - {{display_name}} - {{/each}} - - - {{#each data.techweb_researched}} - {{display_name}} - {{/each}} - diff --git a/tgui/src/interfaces/reagentgrinder.ract b/tgui/src/interfaces/reagentgrinder.ract deleted file mode 100644 index b3e2531fbb..0000000000 --- a/tgui/src/interfaces/reagentgrinder.ract +++ /dev/null @@ -1,43 +0,0 @@ -{{#if data.processing}} - - The grinder is currently processing and cannot be used. - -{{/if}} - - {{#partial button}} - Eject Contents - {{/partial}} - - {{data.operating ? "Busy" : "Ready"}} - Activate - - - {{#if data.contents}} - {{#each adata.contentslist}} - The {{name}}
    - {{else}} - No Contents - {{/each}} - {{else}} - No Contents - {{/if}} -
    -
    - - {{#partial button}} - Detach - {{/partial}} - - {{#if data.isBeakerLoaded}} - {{Math.round(adata.beakerCurrentVolume)}}/{{data.beakerMaxVolume}} Units -
    - {{#each adata.beakerContents}} - {{Math.fixed(volume, 2)}} units of {{name}}
    - {{else}} - Container Empty - {{/each}} - {{else}} - No Container - {{/if}} -
    -
    \ No newline at end of file diff --git a/tgui/src/interfaces/rpd.ract b/tgui/src/interfaces/rpd.ract deleted file mode 100644 index 76c5301d28..0000000000 --- a/tgui/src/interfaces/rpd.ract +++ /dev/null @@ -1,60 +0,0 @@ - - {{#each data.preview_rows}} - - {{#each previews}} - - {{/each}} - - {{/each}} - -{{#if data.category == 0}} - - {{#each data.paint_colors}} - {{@key}} - {{/each}} - -{{/if}} - - Build - Wrench - Destroy - {{#if data.category == 0}} - Paint - {{/if}} - - - - Atmospherics - Disposals - Transit Tubes - - {{#if data.category == 0}} - - 1 - 2 - 3 - - {{/if}} - -{{#each data.categories}} - - {{#each recipes}} - - {{pipe_name}} - - {{/each}} - -{{/each}} diff --git a/tgui/src/interfaces/rpd/colorsel.ract b/tgui/src/interfaces/rpd/colorsel.ract deleted file mode 100644 index 2a91b05ca8..0000000000 --- a/tgui/src/interfaces/rpd/colorsel.ract +++ /dev/null @@ -1,6 +0,0 @@ - - {{#each data.paint_colors}} - {{color_name}} - {{/each}} - diff --git a/tgui/src/interfaces/rpd/dirsel.ract b/tgui/src/interfaces/rpd/dirsel.ract deleted file mode 100644 index 603910956c..0000000000 --- a/tgui/src/interfaces/rpd/dirsel.ract +++ /dev/null @@ -1,10 +0,0 @@ - - {{#each data.preview_rows}} - - {{#each previews}} - - {{/each}} - - {{/each}} - diff --git a/tgui/src/interfaces/sat_control.ract b/tgui/src/interfaces/sat_control.ract deleted file mode 100644 index 0b47bde914..0000000000 --- a/tgui/src/interfaces/sat_control.ract +++ /dev/null @@ -1,21 +0,0 @@ -{{#if data.notice}} - - {{data.notice}} - -{{/if}} - - {{#each data.satellites}} - -
    #{{id}}
    -
    {{mode}}
    -
    - {{active ? "Deactivate" : "Activate"}} -
    -
    - {{/each}} -
    -{{#if data.meteor_shield}} - - {{100 * data.meteor_shield_coverage / data.meteor_shield_coverage_max}} % - -{{/if}} \ No newline at end of file diff --git a/tgui/src/interfaces/scrubbing_types.ract b/tgui/src/interfaces/scrubbing_types.ract deleted file mode 100644 index 87247ecdd4..0000000000 --- a/tgui/src/interfaces/scrubbing_types.ract +++ /dev/null @@ -1,4 +0,0 @@ -{{#each filter_types}} - {{gas_name}} -{{/each}} diff --git a/tgui/src/interfaces/shuttle_manipulator.ract b/tgui/src/interfaces/shuttle_manipulator.ract deleted file mode 100644 index 7fae2223cf..0000000000 --- a/tgui/src/interfaces/shuttle_manipulator.ract +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - {{#if data.selected}} - - {{/if}} - {{#if !data.selected}} - No shuttle selected. - {{/if}} - - diff --git a/tgui/src/interfaces/shuttle_manipulator/modification.ract b/tgui/src/interfaces/shuttle_manipulator/modification.ract deleted file mode 100644 index 967628ef42..0000000000 --- a/tgui/src/interfaces/shuttle_manipulator/modification.ract +++ /dev/null @@ -1,38 +0,0 @@ - - {{#if data.selected.description}} - {{data.selected.description}} - {{/if}} - {{#if data.selected.admin_notes}} - {{data.selected.admin_notes}} - {{/if}} - - -{{#if data.existing_shuttle}} - - Status: {{data.existing_shuttle.status}} - {{#if data.existing_shuttle.timer}} - ({{data.existing_shuttle.timeleft}}) - {{/if}} - - Jump To - - -{{/if}} - -{{#if !data.existing_shuttle}} - -{{/if}} - - - Preview - - - Load - - - - diff --git a/tgui/src/interfaces/shuttle_manipulator/status.ract b/tgui/src/interfaces/shuttle_manipulator/status.ract deleted file mode 100644 index e07f067712..0000000000 --- a/tgui/src/interfaces/shuttle_manipulator/status.ract +++ /dev/null @@ -1,33 +0,0 @@ - -{{#each data.shuttles}} - - - - - - - -{{/each}} -
    - - JMP - - - - Fly - - - {{name}} ({{id}}) - - {{status}} - - {{#if mode}} - {{mode}} - {{/if}} - {{#if timer}} - ({{timeleft}}) - - Fast Travel - - {{/if}} -
    diff --git a/tgui/src/interfaces/shuttle_manipulator/templates.ract b/tgui/src/interfaces/shuttle_manipulator/templates.ract deleted file mode 100644 index f84696511e..0000000000 --- a/tgui/src/interfaces/shuttle_manipulator/templates.ract +++ /dev/null @@ -1,24 +0,0 @@ - - {{#each data.templates}} - - {{#each templates}} - - {{#if description}} - {{description}} - {{/if}} - {{#if admin_notes}} - {{admin_notes}} - {{/if}} - - - {{data.selected.shuttle_id == shuttle_id ? "Selected" : "Select"}} - - - - {{/each}} - - {{/each}} - diff --git a/tgui/src/interfaces/sleeper.ract b/tgui/src/interfaces/sleeper.ract deleted file mode 100644 index e17f8aa5ce..0000000000 --- a/tgui/src/interfaces/sleeper.ract +++ /dev/null @@ -1,139 +0,0 @@ - - - {{data.occupant.name ? data.occupant.name : "No Occupant"}} - - {{#if data.occupied}} - - {{data.occupant.stat}} - - - {{Math.round(adata.occupant.health)}} - - {{#each [{label: "Brute", type: "bruteLoss"}, {label: "Respiratory", type: "oxyLoss"}, {label: "Toxin", type: "toxLoss"}, {label: "Burn", type: "fireLoss"}]}} - - {{Math.round(adata.occupant[type])}} - - {{/each}} - {{#if data.occupant.blood}} - - - {{& data.occupant.blood.currentBloodVolume <= data.occupant.blood.dangerBloodVolume ? "LOW" : "OK"}} - {{Math.round(data.occupant.blood.currentBloodVolume)}} cl - - - {{data.occupant.blood.bloodType}} - - - {{/if}} - - {{data.occupant.cloneLoss ? "Damaged" : "Healthy"}} - - - {{data.occupant.brainLoss ? "Abnormal" : "Healthy"}} - - {{#if data.occupant.failing_organs}} - - {{#each data.occupant.failing_organs}} - {{name}} - {{/each}} - - {{/if}} - - {{#each adata.occupant.reagents}} - {{Math.fixed(volume, 1)}} units of {{name}}
    - {{else}} - Pure - {{/each}} -
    - {{/if}} -
    - - - {{data.open ? "Open" : "Closed"}} - - - - {{#each data.synthchems}} - {{name}} - {{/each}} - - - -
    -
    -
    - Name -
    - -
    - Volume -
    - - {{#if data.efficiency >= 4}} -
    - Purity -
    - {{/if}} - - {{#if data.efficiency >= 3}} -
    -
    - {{/if}} - - {{#if data.efficiency >= 2}} -
    -
    - {{/if}} - -
    -
    - -
    -
    - -
    - {{#each data.chems}} -
    -
    - {{name}} -
    - -
    - {{vol}}u -
    - - {{#if data.efficiency >= 4}} -
    - {{purity}} -
    - {{/if}} - - {{#if data.efficiency >= 3}} -
    - 1 -
    - {{/if}} - - {{#if adata.efficiency >= 2}} -
    - 5 -
    - {{/if}} - -
    - 10 -
    - -
    - Purge
    -
    - -
    - {{/each}} -
    -
    - - {{data.current_vol}} - -
    diff --git a/tgui/src/interfaces/slime_swap_body.ract b/tgui/src/interfaces/slime_swap_body.ract deleted file mode 100644 index 5b2c86afd1..0000000000 --- a/tgui/src/interfaces/slime_swap_body.ract +++ /dev/null @@ -1,22 +0,0 @@ -{{#each data.bodies}} - - {{status}} - {{exoticblood}} - {{area}} - - - {{#if occupied == "owner"}} - You Are Here - {{else}} - {{#if occupied == "stranger"}} - Occupied - {{else}} - Swap - {{/if}} - {{/if}} - - - -{{/each}} diff --git a/tgui/src/interfaces/smartvend.ract b/tgui/src/interfaces/smartvend.ract deleted file mode 100644 index ebe02d1235..0000000000 --- a/tgui/src/interfaces/smartvend.ract +++ /dev/null @@ -1,48 +0,0 @@ - - -{{#partial button}} - {{#if data.isdryer}}{{data.drying ? 'Stop drying' : 'Dry'}}{{/if}} -{{/partial}} -{{#if data.contents.length == 0}} - - Unfortunately, this {{data.name}} is empty. - -{{else}} -
    -
    -
    - Item -
    -
    - Quantity -
    -
    - {{#if data.verb}}{{data.verb}}{{else}}Dispense{{/if}} -
    -
    - {{#each data.contents}} -
    -
    - {{name}} -
    -
    - {{amount}} -
    -
    -
    -
    - = 1) ? null : 'disabled'}} params='{ "name" : {{name}}, "amount" : 1 }' > - One - -
    -
    - 1) ? null : 'disabled'}} params='{ "name" : {{name}} }' > - Many - -
    -
    -
    - {{/each}} -
    -{{/if}} -
    \ No newline at end of file diff --git a/tgui/src/interfaces/smes.ract b/tgui/src/interfaces/smes.ract deleted file mode 100644 index 4b08535899..0000000000 --- a/tgui/src/interfaces/smes.ract +++ /dev/null @@ -1,70 +0,0 @@ - - - - - {{Math.fixed(adata.capacityPercent)}}% - - - - - {{data.inputAttempt ? "Auto" : "Off"}} -   - [{{data.capacityPercent >= 100 ? "Fully Charged" : data.inputting ? "Charging" : "Not Charging"}}] - - - {{adata.inputLevel_text}} - - - - - Set - - - - - {{adata.inputAvailable}} - - - - - {{data.outputAttempt ? "On" : "Off"}} -   - [{{data.outputting ? "Sending" : data.charge > 0 ? "Not Sending" : "No Charge"}}] - - - {{adata.outputLevel_text}} - - - - - Set - - - - - {{adata.outputUsed}} - - diff --git a/tgui/src/interfaces/smoke_machine.ract b/tgui/src/interfaces/smoke_machine.ract deleted file mode 100644 index 983e04bce2..0000000000 --- a/tgui/src/interfaces/smoke_machine.ract +++ /dev/null @@ -1,38 +0,0 @@ -{{#if data.screen == "home"}} - - - {{data.active ? "On" : "Off"}} - - - -
    - 3 - 6 - 9 - 12 - 15 -
    -
    - - {{#if data.isTankLoaded}} - {{Math.round(adata.TankCurrentVolume)}}/{{data.TankMaxVolume}} Units -
    -
    - {{#each adata.TankContents}} - {{Math.fixed(volume, 2)}} units of {{name}}
    - {{/each}} - {{else}} - Tank Empty - {{/if}} - {{data.isTankLoaded ? "Purge Contents" : "No chemicals detected"}} - -
    -
    -{{/if}} - diff --git a/tgui/src/interfaces/solar_control.ract b/tgui/src/interfaces/solar_control.ract deleted file mode 100644 index 45af5ba7b0..0000000000 --- a/tgui/src/interfaces/solar_control.ract +++ /dev/null @@ -1,46 +0,0 @@ - - - {{Math.round(adata.generated)}}W - - - {{Math.round(adata.angle)}}° ({{data.direction}}) - - - 15° - - - 15° - - - - - Off - Timed - Auto - - - {{Math.round(adata.tracking_rate)}}°/h ({{data.rotating_way}}) - - - 180° - 30° - - - 30° - 180° - - - - {{#partial button}} - Refresh - {{/partial}} - - {{data.connected_tracker ? "" : "Not "}}Found - - - {{Math.round(adata.connected_panels)}} Panels Connected - - diff --git a/tgui/src/interfaces/space_heater.ract b/tgui/src/interfaces/space_heater.ract deleted file mode 100644 index 9f143d9562..0000000000 --- a/tgui/src/interfaces/space_heater.ract +++ /dev/null @@ -1,45 +0,0 @@ - - {{#partial button}} - {{#if data.open}} - Eject - {{/if}} - {{/partial}} - - {{data.on ? "On" : "Off"}} - - - {{#if data.hasPowercell}} - {{Math.fixed(adata.powerLevel)}}% - {{else}} - No Cell - {{/if}} - - - - - {{Math.round(adata.currentTemp)}}°C - - - {{Math.round(adata.targetTemp)}}°C - - {{#if data.open}} - - - - Set - - - - {{/if}} - - {{#if data.open}} - Heat - Cool - Auto - {{else}} - {{text.titleCase(data.mode)}} - {{/if}} - - diff --git a/tgui/src/interfaces/spawners_menu.ract b/tgui/src/interfaces/spawners_menu.ract deleted file mode 100644 index 14b6d1df95..0000000000 --- a/tgui/src/interfaces/spawners_menu.ract +++ /dev/null @@ -1,18 +0,0 @@ -{{#each data.spawners}} - - {{#partial button}} - - Jump - - - Spawn - - {{/partial}} - - {{{desc}}} - - - {{amount_left}} - - -{{/each}} \ No newline at end of file diff --git a/tgui/src/interfaces/station_alert.ract b/tgui/src/interfaces/station_alert.ract deleted file mode 100644 index 56c20e302f..0000000000 --- a/tgui/src/interfaces/station_alert.ract +++ /dev/null @@ -1,11 +0,0 @@ -{{#each data.alarms:class}} - -
      - {{#each .}} -
    • {{.}}
    • - {{else}} -
    • System Nominal
    • - {{/each}} -
    -
    -{{/each}} diff --git a/tgui/src/interfaces/suit_storage_unit.ract b/tgui/src/interfaces/suit_storage_unit.ract deleted file mode 100644 index d37a7d4b20..0000000000 --- a/tgui/src/interfaces/suit_storage_unit.ract +++ /dev/null @@ -1,41 +0,0 @@ -{{#if data.occupied && data.safeties}} - - Biological entity detected in contents. Please remove. - -{{/if}} -{{#if data.uv_active}} - - Contents are being disinfected. Please wait. - -{{else}} - - {{#partial button}} - {{#if !data.open}}{{data.locked ? 'Unlock' : 'Lock'}}{{/if}} - {{#if !data.locked}}{{data.open ? 'Close' : 'Open'}}{{/if}} - {{/partial}} - {{#if data.locked}} - - Unit Locked - - {{elseif data.open}} - - {{data.helmet || "Empty"}} - - - {{data.suit || "Empty"}} - - - {{data.mask || "Empty"}} - - - {{data.storage || "Empty"}} - - {{else}} - Disinfect - {{/if}} - -{{/if}} diff --git a/tgui/src/interfaces/synd_contract.ract b/tgui/src/interfaces/synd_contract.ract deleted file mode 100644 index e05dfaad23..0000000000 --- a/tgui/src/interfaces/synd_contract.ract +++ /dev/null @@ -1,148 +0,0 @@ - - - - -
    - {{#if data.error}} -
    -
    - {{data.error}} -
    -
    - Confirm -
    -
    - {{/if}} - {{#if data.logged_in}} - {{#if data.page == "CONTRACTS"}} -
    -
    -
    -
    -

    Welcome Agent...

    -
    -

    Current status: Onboard {{data.station_name}}.

    -
    - -

    - We've identified potentional high-value targets that are currently - assigned to your mission area. They are believed to hold valuable information - which could be of immediate importance to our organisation. -

    - -

    - Listed below are all of the contracts available to you. You are to bring the - specified target to the designated drop-off, and contact us via this uplink. We will send - a specialised extraction unit to put the body into. -

    - -

    - We want targets alive - but we will sometimes pay slight amounts if they're not, you just won't - recieve the shown bonus. You can redeem your payment through this uplink in the form of raw telecrystals, - which can be put into your regular Syndicate uplink to purchase whatever you may need. We provide you with - these crystals the moment you send the target up to us, which can be collected at anytime through this system. -

    - -

    - Targets extracted will be ransomed back to the station once their use to us is fulfilled. - You may want to be mindful of them identifying you when they come back. - We provide you with the standard contractor loadout, which will help cover your identity. -

    - -

    - You have {{data.redeemable_tc}} TC to redeem. Collect -

    - {{#if data.ongoing_contract}} -
    - Call Extraction -
    - {{/if}} - - - - - - - - - - {{#each data.contracts}} - {{#if data.ongoing_contract}} - {{#if status == 2 || status == 3 || status == 4}} - - - - - - - {{/if}} - {{else}} - {{#if status != 5 && status != 6}} - - - - - - - {{/if}} - {{/if}} - {{/each}} - -
    TargetPaymentDrop-Off
    -
    {{target}}
    -
    ({{target_rank}})
    -
    {{payout}} (+{{payout_bonus}}) TC{{dropoff}}Cancel
    -
    {{target}}
    -
    ({{target_rank}})
    -
    {{payout}} (+{{payout_bonus}}) TC{{dropoff}}Accept
    - {{#if data.ongoing_contract}} -
    - - Current Location: {{data.current_location}} -
    - Dropoff Location: {{data.dropoff_direction}} -
    -
    - {{/if}} - {{else}} -
    Back
    -
    Contractor Rep: {{data.contract_rep}}
    - -
    -
    - -

    - The items available on the Hub are available only to contractors. They are bought using Contractor Rep, with two Rep being given on the completion of a contract. -

    - -
    - {{#each data.contractor_hub_items}} - {{#if limited != 0}} -
    -
    - {{name}}{{#if cost != 0}} - {{cost}} Rep{{/if}} -
    -
    - -
    -
    -

    {{desc}}

    -
    -
    - {{#if limited != -1}}Purchase - {{limited}} remaining{{else}}Purchase{{/if}} -
    -
    - {{/if}} - {{/each}} -
    - {{/if}} - {{else}} -
    - Assign
    - {{#if data.error}} - {{data.error}} - {{/if}} -
    - {{/if}} -
    -
    \ No newline at end of file diff --git a/tgui/src/interfaces/tank_dispenser.ract b/tgui/src/interfaces/tank_dispenser.ract deleted file mode 100644 index 220bf40e2d..0000000000 --- a/tgui/src/interfaces/tank_dispenser.ract +++ /dev/null @@ -1,8 +0,0 @@ - - - Plasma ({{Math.round(adata.plasma)}}) - Oxygen ({{Math.round(adata.oxygen)}}) - - diff --git a/tgui/src/interfaces/tanks.ract b/tgui/src/interfaces/tanks.ract deleted file mode 100644 index e4d08c8441..0000000000 --- a/tgui/src/interfaces/tanks.ract +++ /dev/null @@ -1,35 +0,0 @@ - - - - The regulator {{data.connected? "is" : "is not"}} connected to a mask. - - - - {{Math.round(adata.tankPressure)}} kPa - - - {{Math.round(adata.releasePressure)}} kPa - - - Reset - Min - Set - Max - - diff --git a/tgui/src/interfaces/thermomachine.ract b/tgui/src/interfaces/thermomachine.ract deleted file mode 100644 index 136284b145..0000000000 --- a/tgui/src/interfaces/thermomachine.ract +++ /dev/null @@ -1,25 +0,0 @@ - - - {{Math.fixed(adata.temperature, 2)}} K - - - {{Math.fixed(adata.pressure, 2)}} kPa - - - - - {{data.on ? "On": "Off"}} - - - - - {{Math.fixed(adata.target, 2)}} - - - - diff --git a/tgui/src/interfaces/turbine_computer.ract b/tgui/src/interfaces/turbine_computer.ract deleted file mode 100644 index 325c5b4581..0000000000 --- a/tgui/src/interfaces/turbine_computer.ract +++ /dev/null @@ -1,51 +0,0 @@ - - - -
    - Reconnect -
    -
    -
    - - - {{#if data.broken}} - Broken - {{else}} - {{data.online && !(data.compressor_broke || data.turbine_broke) ? "Online" : "Offline"}} - {{/if}} -
    - On - Off -
    - {{#if data.compressor_broke}} -
    - [ Compressor is inoperable ] - {{/if}} - {{#if data.turbine_broke}} -
    - [ Turbine is inoperable ] - {{/if}} -
    -
    - - - {{data.broken ? "--" : data.rpm}} RPM - - - {{data.broken ? "--" : data.temp}} K - - - {{data.broken ? "--" : data.power}} - - diff --git a/tgui/src/interfaces/uplink.ract b/tgui/src/interfaces/uplink.ract deleted file mode 100644 index 0bb19183cd..0000000000 --- a/tgui/src/interfaces/uplink.ract +++ /dev/null @@ -1,43 +0,0 @@ - - - - {{#partial button}} - {{#if data.lockable}} - Lock - {{/if}} - {{/partial}} - - {{data.telecrystals}} TC - - -{{#each data.categories}} - - {{name}} - {{#each items}} - - {{cost}} TC - - {{/each}} - -{{/each}} - diff --git a/tgui/src/interfaces/vr_sleeper.ract b/tgui/src/interfaces/vr_sleeper.ract deleted file mode 100644 index 91074a9425..0000000000 --- a/tgui/src/interfaces/vr_sleeper.ract +++ /dev/null @@ -1,56 +0,0 @@ - - - - {{#if data.emagged}} - - Safety restraints disabled. - - {{/if}} - {{#if data.vr_avatar}} - - - {{data.vr_avatar.name}} - - {{#if data.isliving}} - - {{data.vr_avatar.status}} - - - {{Math.round(adata.vr_avatar.health)}}/{{adata.vr_avatar.maxhealth}} - - {{/if}} - - {{else}} - - No Virtual Avatar detected - - {{/if}} - - - {{data.toggle_open ? "Close" : "Open"}} the VR Sleeper - - {{#if data.isoccupant}} - - Connect to VR - - {{/if}} - {{#if data.vr_avatar}} - - Delete Virtual Avatar - - {{/if}} - - - - diff --git a/tgui/src/interfaces/wires.ract b/tgui/src/interfaces/wires.ract deleted file mode 100644 index a0ee953ebd..0000000000 --- a/tgui/src/interfaces/wires.ract +++ /dev/null @@ -1,16 +0,0 @@ - - {{#each data.wires}} - - {{cut ? "Mend" : "Cut"}} - Pulse - {{attached ? "Detach" : "Attach"}} - - {{/each}} - -{{#if data.status}} - - {{#each data.status}} - {{.}} - {{/each}} - -{{/if}} diff --git a/tgui/src/styles/clockwork.styl b/tgui/src/styles/clockwork.styl deleted file mode 100644 index 204f5b1b40..0000000000 --- a/tgui/src/styles/clockwork.styl +++ /dev/null @@ -1,48 +0,0 @@ -body.clockwork - color-normal = #B18B25 - color-good = #CFBA47 - color-average = #896B19 - color-bad = #5F380E - color-highlight = #B18B25 - text-color-normal = #B18B25 - text-color-inverse = #2D1400 - background-color-start = #B18B25 - background-color-end = #5F380E - rule-color-normal = #B18B25 - rule-color-dark = #896B19 - titlebar-color-text = #CFBA47 - titlebar-color-button = #CFBA47 - titlebar-color-background = #5F380E - titlebar-color-coreshadow = #170800 - titlebar-color-shadow = alpha(#000, 0.1) - resize-color = #5F380E - display-color-title = #CFBA47 - display-color-background = alpha(#2D1400, 0.9) - display-color-shadow = alpha(#000, 0.3) - notice-color-first = #000000 - notice-color-second = #170800 - section-color-label = #B18B25 - bar-color-normal = #B18B25 - bar-color-good = #CFBA47 - bar-color-average = #896B19 - bar-color-bad = #5F380E - bar-color-border = #170800 - bar-color-background = #2D1400 - button-color-normal = #5F380E - button-color-disabled = #2D1400 - button-color-selected = #CFBA47 - button-color-caution = yellow-orange - button-color-danger = yellow - button-color-border = #170800 - button-lighten-hover = 5% - input-color-text = #B18B25 - input-color-background = #CFBA47 - tooltip-color-border = #170800 - tooltip-color-background = #2D1400 - - background: linear-gradient(to bottom, - background-color-start 0%, - background-color-end 100%) - @import "util/*" - @import "components/*" - @import "interfaces/*" diff --git a/tgui/src/styles/nanotrasen.styl b/tgui/src/styles/nanotrasen.styl deleted file mode 100644 index 3f3a28cbdf..0000000000 --- a/tgui/src/styles/nanotrasen.styl +++ /dev/null @@ -1,9 +0,0 @@ -body.nanotrasen - background: data-url('images/nanotrasen.svg') no-repeat fixed center/70% 70%, - linear-gradient(to bottom, - background-color-start 0%, - background-color-end 100%) - - @import "util/*" - @import "components/*" - @import "interfaces/*" diff --git a/tgui/src/styles/syndicate.styl b/tgui/src/styles/syndicate.styl deleted file mode 100644 index 531a1a64ca..0000000000 --- a/tgui/src/styles/syndicate.styl +++ /dev/null @@ -1,31 +0,0 @@ -body.syndicate - color-good = pale-green - color-highlight = black - background-color-start = #750000 - background-color-end = #340404 - rule-color-normal = dark-gray - titlebar-color-text = pale-red - titlebar-color-button = pale-red - display-color-background = alpha(#000, 0.5) - display-color-shadow = alpha(#000, 0.75) - notice-color-first = #750000 - notice-color-second = #910101 - section-color-label = white - bar-color-normal = black - bar-color-good = pale-green - bar-color-border = black - button-color-normal = dark-green - button-color-disabled = gray - button-color-selected = dark-red - button-color-caution = yellow-orange - button-color-danger = yellow - input-color-text = white - input-color-background = dark-red - - background: data-url('images/syndicate.svg') no-repeat fixed center/70% 70%, - linear-gradient(to bottom, - background-color-start 0%, - background-color-end 100%) - @import "util/*" - @import "components/*" - @import "interfaces/*" diff --git a/tgui/src/tgui.js b/tgui/src/tgui.js deleted file mode 100644 index cd6884926d..0000000000 --- a/tgui/src/tgui.js +++ /dev/null @@ -1,70 +0,0 @@ -// Temporarily import Ractive first to keep it from detecting ie8's object.defineProperty shim, which it misuses (ractivejs/ractive#2343). -import Ractive from 'ractive' -Ractive.DEBUG = /minified/.test(() => {/* minified */}) - -import 'ie8' -import 'babel-polyfill' -import 'dom4' -import 'html5shiv' - -// Extend the Math builtin with our own utilities. -Object.assign(Math, require('util/math')) - -// Set up the initialize function. This is either called below if JSON is provided -// inline, or called by the server if it was not. -import TGUI from 'tgui.ract' - -// This thing was a part of an old index.html -window.update = window.initialize = dataString => { - const data = JSON.parse(dataString); - // Initialize - if (!window.tgui) { - window.tgui = new TGUI({ - el: '#container', - data () { - const initial = data; - return { - constants: require('util/constants'), - text: require('util/text'), - config: initial.config, - data: initial.data, - adata: initial.data, - }; - }, - }); - } - // Update - if (window.tgui) { - window.tgui.set('config', data.config); - if (typeof data.data !== 'undefined') { - window.tgui.set('data', data.data); - window.tgui.animate('adata', data.data); - } - } -}; - -// Try to find data in the page. If the JSON was inlined, load it. -const holder = document.getElementById('data') -const data = holder.textContent -const ref = holder.getAttribute('data-ref') -if (data !== '{}') { - window.initialize(data) - holder.remove() -} - -// Let the server know we're set up. -// This also sends data if it was not inlined. -// NOTE: This is currently handled by tgui-next. Only initialize if -// we were loaded by tgui-fallback.html. -import { act } from 'util/byond'; -import { loadCSS } from 'fg-loadcss'; - -if (window.tguiFallback) { - act(ref, 'tgui:initialize'); - // Load fonts. - loadCSS('v4shim.css') - loadCSS('font-awesome.css') -} -else { - act(ref, 'tgui:update'); -} diff --git a/tgui/src/tgui.ract b/tgui/src/tgui.ract deleted file mode 100644 index d7f72644f3..0000000000 --- a/tgui/src/tgui.ract +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - -{{{config.title}}} -
    - - -
    -{{#if config.fancy}} - -{{/if}} diff --git a/tgui/src/tgui.styl b/tgui/src/tgui.styl deleted file mode 100644 index 54a1416cf8..0000000000 --- a/tgui/src/tgui.styl +++ /dev/null @@ -1,134 +0,0 @@ -@charset "utf-8" - -white = white -pale-red = #e74242 -red = #b00e0e -dark-red = #9d0808 -yellow-orange = #be6209 -yellow = #9a9d00 -pale-green = #73E573 -green = #2f943c -grass-green = #537d29 -dark-green = #397439 -royal-blue = #40628a -pale-blue = #8ba5c4 -black = black -black-gray = #161616 -dark-gray = #272727 -gray = #363636 -light-gray = #999999 - -// Branding Colors -color-normal = royal-blue -color-good = grass-green -color-average = yellow-orange -color-bad = red -color-highlight = pale-blue - -// Text -text-color-normal = white -text-color-inverse = black - -// Background -background-color-start = #2a2a2a -background-color-end = #202020 - -// Rules (
    etc) -rule-color-normal = royal-blue -rule-color-dark = dark-gray -rule-size = 2px - -// Titlebar -titlebar-color-text = pale-blue -titlebar-color-button = pale-blue -titlebar-color-background = gray -titlebar-color-coreshadow = black-gray -titlebar-color-shadow = alpha(#000, 0.1) - -// Resize -resize-color = gray - -// Display -display-color-title = white -display-color-background = alpha(#000, 0.33) -display-color-shadow = alpha(#000, 0.5) - -// Notice -notice-color-first = #bb9b68 -notice-color-second = #b1905d -notice-color-border = dark-gray - -// Section -section-color-label = pale-blue -section-color-candystripe = alpha(#000, 0.2) - -// Bar -bar-color-normal = color-normal -bar-color-good = color-good -bar-color-average = color-average -bar-color-bad = color-bad -bar-color-border = royal-blue -bar-color-background = dark-gray - -// Buttons -button-color-normal = royal-blue -button-color-disabled = light-gray -button-color-selected = green -button-color-caution = yellow -button-color-danger = dark-red -button-color-border = dark-gray -button-lighten-hover = 15% -button-desaturate-inactive = 50% - -// Input -input-color-text = black -input-color-placeholder = light-gray -input-color-border = dark-gray -input-color-background = white - -// Tooltips -tooltip-color-border = dark-gray -tooltip-color-background = gray - -html, body - box-sizing: border-box - height: 100% - margin: 0 - -html - overflow: hidden - cursor: default // Reset the cursor. - -body - overflow: auto - - font-family: Verdana, Geneva, sans-serif - font-size: 12px - color: text-color-normal - - background-color: background-color-start - background-image: linear-gradient(to bottom, - background-color-start 0%, - background-color-end 100%) - -*, *:before, *:after - box-sizing: inherit - -$h - display: inline-block - margin: 0 - padding: 6px 0 -h1 - @extend $h - font-size: 18px -h2 - @extend $h - font-size: 16px -h3 - @extend $h - font-size: 14px -h4 - @extend $h - font-size: 12px - -@require "styles/*" diff --git a/tgui/src/util/byond.js b/tgui/src/util/byond.js deleted file mode 100644 index ae3724d408..0000000000 --- a/tgui/src/util/byond.js +++ /dev/null @@ -1,70 +0,0 @@ -const encode = encodeURIComponent - -// Helper to generate a BYOND href given 'params' as an object -// (with an optional 'url' for eg winset). -export const href = (url, params = {}) => { - return `byond://${url || ''}?` - + Object.keys(params) - .map(key => `${encode(key)}=${encode(params[key])}`) - .join('&'); -}; - -// Helper to make a BYOND ui_act() call on the UI 'src' given an 'action' -// and optional 'params'. -export const act = (src, action, params = {}) => { - window.location.href = href('', Object.assign({ src, action }, params)) -}; - -/** - * A high-level abstraction of BYJAX. Makes a call to BYOND and returns - * a promise, which (if endpoint has a callback parameter) resolves - * with the return value of that call. - */ -export const callByond = (url, params = {}) => { - // Create a callback array if it doesn't exist yet - window.byondCallbacks = window.byondCallbacks || []; - // Create a Promise and push its resolve function into callback array - const callbackIndex = window.byondCallbacks.length; - const promise = new Promise(resolve => { - // TODO: Fix a potential memory leak - window.byondCallbacks.push(resolve); - }); - // Call BYOND client - window.location.href = href(url || '', Object.assign({}, params, { - callback: `byondCallbacks[${callbackIndex}]`, - })); - // Return promise (awaitable) - return promise; -}; - -export const runCommand = command => callByond('winset', { command }); - -/** - * A simple debug print. - * - * TODO: Find a better way to debug print. - * Right now we just print into the game chat. - */ -export const debugPrint = (...args) => { - const str = args - .map(arg => { - if (typeof arg === 'string') { - return arg - } - return JSON.stringify(arg); - }) - .join(' '); - return runCommand('Me [debugPrint] ' + str); -}; - -export const winget = (win, key) => { - return callByond('winget', { id: win, property: key }) - .then(obj => obj[key]); -}; - -// Helper to make a BYOND winset() call on 'window', setting 'key' to 'value' -export const winset = (win, key, value) => { - window.location.href = href('winset', { - [`${win}.${key}`]: value, - }); -}; diff --git a/tgui/src/util/colors.styl b/tgui/src/util/colors.styl deleted file mode 100644 index d1f17a7768..0000000000 --- a/tgui/src/util/colors.styl +++ /dev/null @@ -1,10 +0,0 @@ -.normal - color: color-normal -.good - color: color-good -.average - color: color-average -.bad - color: color-bad -.highlight - color: color-highlight diff --git a/tgui/src/util/constants.js b/tgui/src/util/constants.js deleted file mode 100644 index b7dac6eb67..0000000000 --- a/tgui/src/util/constants.js +++ /dev/null @@ -1,5 +0,0 @@ -// Constants used in tgui; these are mirrored from the BYOND code. -export const UI_INTERACTIVE = 2 -export const UI_UPDATE = 1 -export const UI_DISABLED = 0 -export const UI_CLOSE = -1 diff --git a/tgui/src/util/dragresize.js b/tgui/src/util/dragresize.js deleted file mode 100644 index 89fee549e9..0000000000 --- a/tgui/src/util/dragresize.js +++ /dev/null @@ -1,59 +0,0 @@ -import {winset} from './byond' - -export function lock (x, y) { - if (x < 0) { // Left - x = 0 - } else if (x + window.innerWidth > window.screen.availWidth) { // Right - x = window.screen.availWidth - window.innerWidth - } - - if (y < 0) { // Top - y = 0 - } else if (y + window.innerHeight > window.screen.availHeight) { // Bottom - y = window.screen.availHeight - window.innerHeight - } - - return {x, y} -} - -export function drag (event) { - event.preventDefault(); - if (!this.get('drag')) { - return; - } - if (this.get('x')) { - let x = event.screenX - + this.get('x') - + this.get('screenOffsetX'); - let y = event.screenY - + this.get('y') - + this.get('screenOffsetY'); - winset(this.get('config.window'), 'pos', `${x},${y}`); - } - else { - this.set({ - x: window.screenLeft - event.screenX, - y: window.screenTop - event.screenY, - }); - } -} - -export function sane (x, y) { - x = Math.clamp(100, window.screen.width, x) - y = Math.clamp(100, window.screen.height, y) - return {x, y} -} - -export function resize (event) { - event.preventDefault() - - if (!this.get('resize')) return - - if (this.get('x')) { - let x = (event.screenX - this.get('x')) + window.innerWidth - let y = (event.screenY - this.get('y')) + window.innerHeight - ;({x, y} = sane(x, y)) - winset(this.get('config.window'), 'size', `${x},${y}`) - } - this.set({ x: event.screenX, y: event.screenY }) -} diff --git a/tgui/src/util/filter.js b/tgui/src/util/filter.js deleted file mode 100644 index 66e9360052..0000000000 --- a/tgui/src/util/filter.js +++ /dev/null @@ -1,22 +0,0 @@ -export function filterMulti (displays, string) { - for (let display of displays) { // First check if the display includes the search term in the first place. - if (display.textContent.toLowerCase().includes(string)) { - display.style.display = '' - filter(display, string) - } else { - display.style.display = 'none' - } - } -} - -export function filter (display, string) { - const items = display.queryAll('section') - const titleMatch = display.query('header').textContent.toLowerCase().includes(string) - for (let item of items) { // Check if the item or its displays title contains the search term. - if (titleMatch || item.textContent.toLowerCase().includes(string)) { - item.style.display = '' - } else { - item.style.display = 'none' - } - } -} diff --git a/tgui/src/util/math.js b/tgui/src/util/math.js deleted file mode 100644 index 39a4b0c424..0000000000 --- a/tgui/src/util/math.js +++ /dev/null @@ -1,9 +0,0 @@ -// Helper to limit a number to be inside 'min' and 'max'. -export function clamp (min, max, number) { - return Math.max(min, Math.min(number, max)) -} - -// Helper to round a number to 'decimals' decimals. -export function fixed (number, decimals = 1) { - return Number(Math.round(number + 'e' + decimals) + 'e-' + decimals) -} diff --git a/tgui/src/util/misc.styl b/tgui/src/util/misc.styl deleted file mode 100644 index 08dd093547..0000000000 --- a/tgui/src/util/misc.styl +++ /dev/null @@ -1,12 +0,0 @@ -main - display: block - margin-top: 32px - padding: 2px 6px 0 - -hr - height: rule-size - background-color: rule-color-normal - border: none - -.hidden - display: none diff --git a/tgui/src/util/text.js b/tgui/src/util/text.js deleted file mode 100644 index 657160b673..0000000000 --- a/tgui/src/util/text.js +++ /dev/null @@ -1,14 +0,0 @@ -export function upperCaseFirst (str) { - return str[0].toUpperCase() + str.slice(1).toLowerCase() -} - -export function titleCase (str) { - return str.replace(/\w\S*/g, upperCaseFirst) -} - -export function zeroPad (str, pad_size) { - str = str.toString() - while(str.length < pad_size) - str = '0' + str - return str -} diff --git a/tgui/src/util/text.styl b/tgui/src/util/text.styl deleted file mode 100644 index 752bb120cc..0000000000 --- a/tgui/src/util/text.styl +++ /dev/null @@ -1,17 +0,0 @@ -// Helper to reset font options to default. -$fontReset - color: text-color-normal - font-size: 12px - font-weight: normal - font-style: normal - text-decoration: none - -// Utility classes to set font styles. -.bold - font-weight: bold -.italic - font-style: italic - -// Make 'unselectable' text unselectable on all browsers. -[unselectable=on] - user-select: none diff --git a/tgui/src/util/tooltip.styl b/tgui/src/util/tooltip.styl deleted file mode 100644 index 1f75061ee1..0000000000 --- a/tgui/src/util/tooltip.styl +++ /dev/null @@ -1,55 +0,0 @@ -div[data-tooltip], span[data-tooltip] - position: relative - - &::after - position: absolute - display: block - z-index: 2 - width: 250px - padding: 10px - transform: translateX(-50%) - pointer-events: none - - visibility: hidden - opacity: 0 - - white-space: normal - text-align: left - content: attr(data-tooltip) - - transition: all .5s - border: 1px solid tooltip-color-border - background-color: tooltip-color-background - - &:hover::after - pointer-events: none - visibility: visible - opacity: 1 - - &.tooltip-top::after - bottom: 100% - left: 50% - transform: translateX(-50%) translateY(8px) - &.tooltip-top:hover::after - transform: translateX(-50%) translateY(-8px) - - &.tooltip-bottom::after - top: 100% - left: 50% - transform: translateX(-50%) translateY(-8px) - &.tooltip-bottom:hover::after - transform: translateX(-50%) translateY(8px) - - &.tooltip-left::after - top: 50% - right: 100% - transform: translateX(8px) translateY(-50%) - &.tooltip-left:hover::after - transform: translateX(-8px) translateY(-50%) - - &.tooltip-right::after - top: 50% - left: 100% - transform: translateX(-8px) translateY(-50%) - &.tooltip-right:hover::after - transform: translateX(8px) translateY(-50%) diff --git a/tgui-next/yarn.lock b/tgui/yarn.lock similarity index 65% rename from tgui-next/yarn.lock rename to tgui/yarn.lock index dd59505ca1..e3781bdc13 100644 --- a/tgui-next/yarn.lock +++ b/tgui/yarn.lock @@ -2,817 +2,970 @@ # yarn lockfile v1 -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.0.0" + "@babel/highlight" "^7.10.4" + +"@babel/compat-data@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.5.tgz#d38425e67ea96b1480a3f50404d1bf85676301a6" + integrity sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw== + dependencies: + browserslist "^4.12.0" + invariant "^2.2.4" + semver "^5.5.0" "@babel/core@^7.6.2": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.5.tgz#ae1323cd035b5160293307f50647e83f8ba62f7e" - integrity sha512-M42+ScN4+1S9iB6f+TL7QBpoQETxbclx+KNoKJABghnKYE+fMzSGqst0BZJc8CpI625bwPwYgUyRvxZ+0mZzpw== + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.10.5.tgz#1f15e2cca8ad9a1d78a38ddba612f5e7cdbbd330" + integrity sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w== dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" - "@babel/helpers" "^7.7.4" - "@babel/parser" "^7.7.5" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.10.5" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.5" + "@babel/types" "^7.10.5" convert-source-map "^1.7.0" debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.13" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" - integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== +"@babel/generator@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.5.tgz#1b903554bc8c583ee8d25f1e8969732e6b829a69" + integrity sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.10.5" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.4.tgz#bb3faf1e74b74bd547e867e48f551fa6b098b6ce" - integrity sha512-2BQmQgECKzYKFPpiycoF9tlb5HA4lrVyAmLLVK177EcQAqjVLciUb2/R+n1boQ9y5ENV3uz2ZqiNw7QMBBw1Og== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.4.tgz#5f73f2b28580e224b5b9bd03146a4015d6217f5f" - integrity sha512-Biq/d/WtvfftWZ9Uf39hbPBYDUo986m5Bb4zhkeYDGUllF43D+nUe5M6Vuo6/8JDK/0YX/uBdeoQpyaNhNugZQ== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-call-delegate@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.7.4.tgz#621b83e596722b50c0066f9dc37d3232e461b801" - integrity sha512-8JH9/B7J7tCYJ2PpWVpw9JhPuEVHztagNVuQAFBVFYluRMlpG7F1CgKEgGeL6KFqcsIa92ZYVj6DSc0XwmN1ZA== - dependencies: - "@babel/helper-hoist-variables" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-create-regexp-features-plugin@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.4.tgz#6d5762359fd34f4da1500e4cff9955b5299aaf59" - integrity sha512-Mt+jBKaxL0zfOIWrfQpnfYCN7/rS6GKx6CCCfuoqVVd+17R8zNDlzVYmIi9qyb2wOk002NsmSTDymkIygDUH7A== - dependencies: - "@babel/helper-regex" "^7.4.4" - regexpu-core "^4.6.0" - -"@babel/helper-define-map@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.7.4.tgz#2841bf92eb8bd9c906851546fe6b9d45e162f176" - integrity sha512-v5LorqOa0nVQUvAUTUF3KPastvUt/HzByXNamKQ6RdJRTV7j8rLL+WB5C/MzzWAwOomxDhYFb1wLLxHqox86lg== - dependencies: - "@babel/helper-function-name" "^7.7.4" - "@babel/types" "^7.7.4" - lodash "^4.17.13" - -"@babel/helper-explode-assignable-expression@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.4.tgz#fa700878e008d85dc51ba43e9fb835cddfe05c84" - integrity sha512-2/SicuFrNSXsZNBxe5UGdLr+HZg+raWBLE9vC98bdYOKX/U6PY0mdGlYUJdtTDPSU0Lw0PNbKKDpwYHJLn2jLg== - dependencies: - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-function-name@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" - integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== - dependencies: - "@babel/helper-get-function-arity" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-get-function-arity@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" - integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-hoist-variables@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.4.tgz#612384e3d823fdfaaf9fce31550fe5d4db0f3d12" - integrity sha512-wQC4xyvc1Jo/FnLirL6CEgPgPCa8M74tOdjWpRhQYapz5JC7u3NYU1zCVoVAGCE3EaIP9T1A3iW0WLJ+reZlpQ== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-member-expression-to-functions@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.4.tgz#356438e2569df7321a8326644d4b790d2122cb74" - integrity sha512-9KcA1X2E3OjXl/ykfMMInBK+uVdfIVakVe7W7Lg3wfXUNyS3Q1HWLFRwZIjhqiCGbslummPDnmb7vIekS0C1vw== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-module-imports@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" - integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-module-transforms@^7.7.4", "@babel/helper-module-transforms@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.7.5.tgz#d044da7ffd91ec967db25cd6748f704b6b244835" - integrity sha512-A7pSxyJf1gN5qXVcidwLWydjftUN878VkalhXX5iQDuGyiGK3sOrrKKHF4/A4fwHtnsotv/NipwAeLzY4KQPvw== - dependencies: - "@babel/helper-module-imports" "^7.7.4" - "@babel/helper-simple-access" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/types" "^7.7.4" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.4.tgz#034af31370d2995242aa4df402c3b7794b2dcdf2" - integrity sha512-VB7gWZ2fDkSuqW6b1AKXkJWO5NyNI3bFL/kK79/30moK57blr6NbH8xcl2XcKCwOmJosftWunZqfO84IGq3ZZg== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-regex@^7.0.0", "@babel/helper-regex@^7.4.4": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.5.5.tgz#0aa6824f7100a2e0e89c1527c23936c152cab351" - integrity sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw== - dependencies: - lodash "^4.17.13" - -"@babel/helper-remap-async-to-generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.4.tgz#c68c2407350d9af0e061ed6726afb4fff16d0234" - integrity sha512-Sk4xmtVdM9sA/jCI80f+KS+Md+ZHIpjuqmYPk1M7F/upHou5e4ReYmExAiu6PVe65BhJPZA2CY9x9k4BqE5klw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.7.4" - "@babel/helper-wrap-function" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-replace-supers@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.7.4.tgz#3c881a6a6a7571275a72d82e6107126ec9e2cdd2" - integrity sha512-pP0tfgg9hsZWo5ZboYGuBn/bbYT/hdLPVSS4NMmiRJdwWhP0IznPwN9AE1JwyGsjSPLC364I0Qh5p+EPkGPNpg== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.7.4" - "@babel/helper-optimise-call-expression" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-simple-access@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.7.4.tgz#a169a0adb1b5f418cfc19f22586b2ebf58a9a294" - integrity sha512-zK7THeEXfan7UlWsG2A6CI/L9jVnI5+xxKZOdej39Y0YtDYKx9raHk5F2EtK9K8DHRTihYwg20ADt9S36GR78A== - dependencies: - "@babel/template" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-split-export-declaration@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" - integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-wrap-function@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.7.4.tgz#37ab7fed5150e22d9d7266e830072c0cdd8baace" - integrity sha512-VsfzZt6wmsocOaVU0OokwrIytHND55yvyT4BPB9AIIgwr8+x7617hetdJTsuGwygN5RC6mxA9EJztTjuwm2ofg== - dependencies: - "@babel/helper-function-name" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helpers@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" - integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== - dependencies: - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.0.0", "@babel/parser@^7.7.4", "@babel/parser@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" - integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== - -"@babel/plugin-proposal-async-generator-functions@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.4.tgz#0351c5ac0a9e927845fffd5b82af476947b7ce6d" - integrity sha512-1ypyZvGRXriY/QP668+s8sFr2mqinhkRDMPSQLNghCQE+GAkFtp+wkHVvg2+Hdki8gwP+NFzJBJ/N1BfzCCDEw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.7.4" - "@babel/plugin-syntax-async-generators" "^7.7.4" - -"@babel/plugin-proposal-dynamic-import@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.4.tgz#dde64a7f127691758cbfed6cf70de0fa5879d52d" - integrity sha512-StH+nGAdO6qDB1l8sZ5UBV8AC3F2VW2I8Vfld73TMKyptMU9DY5YsJAS8U81+vEtxcH3Y/La0wG0btDrhpnhjQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-dynamic-import" "^7.7.4" - -"@babel/plugin-proposal-json-strings@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.7.4.tgz#7700a6bfda771d8dc81973249eac416c6b4c697d" - integrity sha512-wQvt3akcBTfLU/wYoqm/ws7YOAQKu8EVJEvHip/mzkNtjaclQoCCIqKXFP5/eyfnfbQCDV3OLRIK3mIVyXuZlw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-json-strings" "^7.7.4" - -"@babel/plugin-proposal-object-rest-spread@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.7.4.tgz#cc57849894a5c774214178c8ab64f6334ec8af71" - integrity sha512-rnpnZR3/iWKmiQyJ3LKJpSwLDcX/nSXhdLk4Aq/tXOApIvyu7qoabrige0ylsAJffaUC51WiBu209Q0U+86OWQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-object-rest-spread" "^7.7.4" - -"@babel/plugin-proposal-optional-catch-binding@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.7.4.tgz#ec21e8aeb09ec6711bc0a39ca49520abee1de379" - integrity sha512-DyM7U2bnsQerCQ+sejcTNZh8KQEUuC3ufzdnVnSiUv/qoGJp2Z3hanKL18KDhsBT5Wj6a7CMT5mdyCNJsEaA9w== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" - -"@babel/plugin-proposal-unicode-property-regex@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.4.tgz#7c239ccaf09470dbe1d453d50057460e84517ebb" - integrity sha512-cHgqHgYvffluZk85dJ02vloErm3Y6xtH+2noOBOJ2kXOJH3aVCDnj5eR/lVNlTnYu4hndAPJD3rTFjW3qee0PA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-async-generators@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.7.4.tgz#331aaf310a10c80c44a66b238b6e49132bd3c889" - integrity sha512-Li4+EjSpBgxcsmeEF8IFcfV/+yJGxHXDirDkEoyFjumuwbmfCVHUt0HuowD/iGM7OhIRyXJH9YXxqiH6N815+g== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-dynamic-import@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.7.4.tgz#29ca3b4415abfe4a5ec381e903862ad1a54c3aec" - integrity sha512-jHQW0vbRGvwQNgyVxwDh4yuXu4bH1f5/EICJLAhl1SblLs2CDhrsmCk+v5XLdE9wxtAFRyxx+P//Iw+a5L/tTg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-json-strings@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.7.4.tgz#86e63f7d2e22f9e27129ac4e83ea989a382e86cc" - integrity sha512-QpGupahTQW1mHRXddMG5srgpHWqRLwJnJZKXTigB9RPFCCGbDGCgBeM/iC82ICXp414WeYx/tD54w7M2qRqTMg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-jsx@^7": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.7.4.tgz#dab2b56a36fb6c3c222a1fbc71f7bf97f327a9ec" - integrity sha512-wuy6fiMe9y7HeZBWXYCGt2RGxZOj0BImZ9EyXJVnVGBKO/Br592rbR3rtIQn0eQhAk9vqaKP5n8tVqEFBQMfLg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-object-rest-spread@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" - integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.7.4.tgz#a3e38f59f4b6233867b4a92dcb0ee05b2c334aa6" - integrity sha512-4ZSuzWgFxqHRE31Glu+fEr/MirNZOMYmD/0BhBWyLyOOQz/gTAl7QmWm2hX1QxEIXsr2vkdlwxIzTyiYRC4xcQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-syntax-top-level-await@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.7.4.tgz#bd7d8fa7b9fee793a36e4027fd6dd1aa32f946da" - integrity sha512-wdsOw0MvkL1UIgiQ/IFr3ETcfv1xb8RMM0H9wbiDyLaJFyiDg5oZvDLCXosIXmFeIlweML5iOBXAkqddkYNizg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-arrow-functions@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.7.4.tgz#76309bd578addd8aee3b379d809c802305a98a12" - integrity sha512-zUXy3e8jBNPiffmqkHRNDdZM2r8DWhCB7HhcoyZjiK1TxYEluLHAvQuYnTT+ARqRpabWqy/NHkO6e3MsYB5YfA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-async-to-generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.4.tgz#694cbeae6d613a34ef0292713fa42fb45c4470ba" - integrity sha512-zpUTZphp5nHokuy8yLlyafxCJ0rSlFoSHypTUWgpdwoDXWQcseaect7cJ8Ppk6nunOM6+5rPMkod4OYKPR5MUg== - dependencies: - "@babel/helper-module-imports" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-remap-async-to-generator" "^7.7.4" - -"@babel/plugin-transform-block-scoped-functions@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.7.4.tgz#d0d9d5c269c78eaea76227ace214b8d01e4d837b" - integrity sha512-kqtQzwtKcpPclHYjLK//3lH8OFsCDuDJBaFhVwf8kqdnF6MN4l618UDlcA7TfRs3FayrHj+svYnSX8MC9zmUyQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-block-scoping@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.7.4.tgz#200aad0dcd6bb80372f94d9e628ea062c58bf224" - integrity sha512-2VBe9u0G+fDt9B5OV5DQH4KBf5DoiNkwFKOz0TCvBWvdAN2rOykCTkrL+jTLxfCAm76l9Qo5OqL7HBOx2dWggg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - lodash "^4.17.13" - -"@babel/plugin-transform-classes@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.4.tgz#c92c14be0a1399e15df72667067a8f510c9400ec" - integrity sha512-sK1mjWat7K+buWRuImEzjNf68qrKcrddtpQo3swi9j7dUcG6y6R6+Di039QN2bD1dykeswlagupEmpOatFHHUg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.7.4" - "@babel/helper-define-map" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-optimise-call-expression" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.7.4.tgz#e856c1628d3238ffe12d668eb42559f79a81910d" - integrity sha512-bSNsOsZnlpLLyQew35rl4Fma3yKWqK3ImWMSC/Nc+6nGjC9s5NFWAer1YQ899/6s9HxO2zQC1WoFNfkOqRkqRQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-destructuring@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.7.4.tgz#2b713729e5054a1135097b6a67da1b6fe8789267" - integrity sha512-4jFMXI1Cu2aXbcXXl8Lr6YubCn6Oc7k9lLsu8v61TZh+1jny2BWmdtvY9zSUlLdGUvcy9DMAWyZEOqjsbeg/wA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-dotall-regex@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.4.tgz#f7ccda61118c5b7a2599a72d5e3210884a021e96" - integrity sha512-mk0cH1zyMa/XHeb6LOTXTbG7uIJ8Rrjlzu91pUx/KS3JpcgaTDwMS8kM+ar8SLOvlL2Lofi4CGBAjCo3a2x+lw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-duplicate-keys@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.7.4.tgz#3d21731a42e3f598a73835299dd0169c3b90ac91" - integrity sha512-g1y4/G6xGWMD85Tlft5XedGaZBCIVN+/P0bs6eabmcPP9egFleMAo65OOjlhcz1njpwagyY3t0nsQC9oTFegJA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-exponentiation-operator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.7.4.tgz#dd30c0191e3a1ba19bcc7e389bdfddc0729d5db9" - integrity sha512-MCqiLfCKm6KEA1dglf6Uqq1ElDIZwFuzz1WH5mTf8k2uQSxEJMbOIEh7IZv7uichr7PMfi5YVSrr1vz+ipp7AQ== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-for-of@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.7.4.tgz#248800e3a5e507b1f103d8b4ca998e77c63932bc" - integrity sha512-zZ1fD1B8keYtEcKF+M1TROfeHTKnijcVQm0yO/Yu1f7qoDoxEIc/+GX6Go430Bg84eM/xwPFp0+h4EbZg7epAA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-function-name@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.4.tgz#75a6d3303d50db638ff8b5385d12451c865025b1" - integrity sha512-E/x09TvjHNhsULs2IusN+aJNRV5zKwxu1cpirZyRPw+FyyIKEHPXTsadj48bVpc1R5Qq1B5ZkzumuFLytnbT6g== - dependencies: - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-jscript@^7.2.0": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-jscript/-/plugin-transform-jscript-7.7.4.tgz#c44778475e82213c9add7d46cb2223e5ee1c6c1d" - integrity sha512-ctCBKIcV5rZoYntbXtuE8XmBH0RgGk0lyQYJzsU6j2vKMr0dAf9QFyDjRlvR0xKqOPcAdrVEVdI5k2qVTicNoQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.7.4.tgz#27fe87d2b5017a2a5a34d1c41a6b9f6a6262643e" - integrity sha512-X2MSV7LfJFm4aZfxd0yLVFrEXAgPqYoDG53Br/tCKiKYfX0MjVjQeWPIhPHHsCqzwQANq+FLN786fF5rgLS+gw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-member-expression-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.7.4.tgz#aee127f2f3339fc34ce5e3055d7ffbf7aa26f19a" - integrity sha512-9VMwMO7i69LHTesL0RdGy93JU6a+qOPuvB4F4d0kR0zyVjJRVJRaoaGjhtki6SzQUu8yen/vxPKN6CWnCUw6bA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-modules-amd@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.7.5.tgz#39e0fb717224b59475b306402bb8eedab01e729c" - integrity sha512-CT57FG4A2ZUNU1v+HdvDSDrjNWBrtCmSH6YbbgN3Lrf0Di/q/lWRxZrE72p3+HCCz9UjfZOEBdphgC0nzOS6DQ== - dependencies: - "@babel/helper-module-transforms" "^7.7.5" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.5.tgz#1d27f5eb0bcf7543e774950e5b2fa782e637b345" - integrity sha512-9Cq4zTFExwFhQI6MT1aFxgqhIsMWQWDVwOgLzl7PTWJHsNaqFvklAU+Oz6AQLAS0dJKTwZSOCo20INwktxpi3Q== - dependencies: - "@babel/helper-module-transforms" "^7.7.5" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-simple-access" "^7.7.4" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-systemjs@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.4.tgz#cd98152339d3e763dfe838b7d4273edaf520bb30" - integrity sha512-y2c96hmcsUi6LrMqvmNDPBBiGCiQu0aYqpHatVVu6kD4mFEXKjyNxd/drc18XXAf9dv7UXjrZwBVmTTGaGP8iw== - dependencies: - "@babel/helper-hoist-variables" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-umd@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.4.tgz#1027c355a118de0aae9fee00ad7813c584d9061f" - integrity sha512-u2B8TIi0qZI4j8q4C51ktfO7E3cQ0qnaXFI1/OXITordD40tt17g/sXqgNNCcMTcBFKrUPcGDx+TBJuZxLx7tw== - dependencies: - "@babel/helper-module-transforms" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.4.tgz#fb3bcc4ee4198e7385805007373d6b6f42c98220" - integrity sha512-jBUkiqLKvUWpv9GLSuHUFYdmHg0ujC1JEYoZUfeOOfNydZXp1sXObgyPatpcwjWgsdBGsagWW0cdJpX/DO2jMw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.4" - -"@babel/plugin-transform-new-target@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.7.4.tgz#4a0753d2d60639437be07b592a9e58ee00720167" - integrity sha512-CnPRiNtOG1vRodnsyGX37bHQleHE14B9dnnlgSeEs3ek3fHN1A1SScglTCg1sfbe7sRQ2BUcpgpTpWSfMKz3gg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-object-super@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.7.4.tgz#48488937a2d586c0148451bf51af9d7dda567262" - integrity sha512-ho+dAEhC2aRnff2JCA0SAK7V2R62zJd/7dmtoe7MHcso4C2mS+vZjn1Pb1pCVZvJs1mgsvv5+7sT+m3Bysb6eg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-replace-supers" "^7.7.4" - -"@babel/plugin-transform-parameters@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.7.4.tgz#da4555c97f39b51ac089d31c7380f03bca4075ce" - integrity sha512-VJwhVePWPa0DqE9vcfptaJSzNDKrWU/4FbYCjZERtmqEs05g3UMXnYMZoXja7JAJ7Y7sPZipwm/pGApZt7wHlw== - dependencies: - "@babel/helper-call-delegate" "^7.7.4" - "@babel/helper-get-function-arity" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-property-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.7.4.tgz#2388d6505ef89b266103f450f9167e6bd73f98c2" - integrity sha512-MatJhlC4iHsIskWYyawl53KuHrt+kALSADLQQ/HkhTjX954fkxIEh4q5slL4oRAnsm/eDoZ4q0CIZpcqBuxhJQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-regenerator@^7.7.5": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.5.tgz#3a8757ee1a2780f390e89f246065ecf59c26fce9" - integrity sha512-/8I8tPvX2FkuEyWbjRCt4qTAgZK0DVy8QRguhA524UH48RfGJy94On2ri+dCuwOpcerPRl9O4ebQkRcVzIaGBw== - dependencies: - regenerator-transform "^0.14.0" - -"@babel/plugin-transform-reserved-words@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.7.4.tgz#6a7cf123ad175bb5c69aec8f6f0770387ed3f1eb" - integrity sha512-OrPiUB5s5XvkCO1lS7D8ZtHcswIC57j62acAnJZKqGGnHP+TIc/ljQSrgdX/QyOTdEK5COAhuc820Hi1q2UgLQ== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-shorthand-properties@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.7.4.tgz#74a0a9b2f6d67a684c6fbfd5f0458eb7ba99891e" - integrity sha512-q+suddWRfIcnyG5YiDP58sT65AJDZSUhXQDZE3r04AuqD6d/XLaQPPXSBzP2zGerkgBivqtQm9XKGLuHqBID6Q== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-spread@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.7.4.tgz#aa673b356fe6b7e70d69b6e33a17fef641008578" - integrity sha512-8OSs0FLe5/80cndziPlg4R0K6HcWSM0zyNhHhLsmw/Nc5MaA49cAsnoJ/t/YZf8qkG7fD+UjTRaApVDB526d7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-sticky-regex@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.7.4.tgz#ffb68c05090c30732076b1285dc1401b404a123c" - integrity sha512-Ls2NASyL6qtVe1H1hXts9yuEeONV2TJZmplLONkMPUG158CtmnrzW5Q5teibM5UVOFjG0D3IC5mzXR6pPpUY7A== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/helper-regex" "^7.0.0" - -"@babel/plugin-transform-template-literals@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.7.4.tgz#1eb6411736dd3fe87dbd20cc6668e5121c17d604" - integrity sha512-sA+KxLwF3QwGj5abMHkHgshp9+rRz+oY9uoRil4CyLtgEuE/88dpkeWgNk5qKVsJE9iSfly3nvHapdRiIS2wnQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-typeof-symbol@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.7.4.tgz#3174626214f2d6de322882e498a38e8371b2140e" - integrity sha512-KQPUQ/7mqe2m0B8VecdyaW5XcQYaePyl9R7IsKd+irzj6jvbhoGnRE+M0aNkyAzI07VfUQ9266L5xMARitV3wg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-unicode-regex@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.4.tgz#a3c0f65b117c4c81c5b6484f2a5e7b95346b83ae" - integrity sha512-N77UUIV+WCvE+5yHw+oks3m18/umd7y392Zv7mYTpFqHtkpcc+QUz+gLJNTWVlWROIWeLqY0f3OjZxV5TcXnRw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/preset-env@^7.6.2": - version "7.7.6" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.7.6.tgz#39ac600427bbb94eec6b27953f1dfa1d64d457b2" - integrity sha512-k5hO17iF/Q7tR9Jv8PdNBZWYW6RofxhnxKjBMc0nG4JTaWvOTiPoO/RLFwAKcA4FpmuBFm6jkoqaRJLGi0zdaQ== - dependencies: - "@babel/helper-module-imports" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-async-generator-functions" "^7.7.4" - "@babel/plugin-proposal-dynamic-import" "^7.7.4" - "@babel/plugin-proposal-json-strings" "^7.7.4" - "@babel/plugin-proposal-object-rest-spread" "^7.7.4" - "@babel/plugin-proposal-optional-catch-binding" "^7.7.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.7.4" - "@babel/plugin-syntax-async-generators" "^7.7.4" - "@babel/plugin-syntax-dynamic-import" "^7.7.4" - "@babel/plugin-syntax-json-strings" "^7.7.4" - "@babel/plugin-syntax-object-rest-spread" "^7.7.4" - "@babel/plugin-syntax-optional-catch-binding" "^7.7.4" - "@babel/plugin-syntax-top-level-await" "^7.7.4" - "@babel/plugin-transform-arrow-functions" "^7.7.4" - "@babel/plugin-transform-async-to-generator" "^7.7.4" - "@babel/plugin-transform-block-scoped-functions" "^7.7.4" - "@babel/plugin-transform-block-scoping" "^7.7.4" - "@babel/plugin-transform-classes" "^7.7.4" - "@babel/plugin-transform-computed-properties" "^7.7.4" - "@babel/plugin-transform-destructuring" "^7.7.4" - "@babel/plugin-transform-dotall-regex" "^7.7.4" - "@babel/plugin-transform-duplicate-keys" "^7.7.4" - "@babel/plugin-transform-exponentiation-operator" "^7.7.4" - "@babel/plugin-transform-for-of" "^7.7.4" - "@babel/plugin-transform-function-name" "^7.7.4" - "@babel/plugin-transform-literals" "^7.7.4" - "@babel/plugin-transform-member-expression-literals" "^7.7.4" - "@babel/plugin-transform-modules-amd" "^7.7.5" - "@babel/plugin-transform-modules-commonjs" "^7.7.5" - "@babel/plugin-transform-modules-systemjs" "^7.7.4" - "@babel/plugin-transform-modules-umd" "^7.7.4" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.7.4" - "@babel/plugin-transform-new-target" "^7.7.4" - "@babel/plugin-transform-object-super" "^7.7.4" - "@babel/plugin-transform-parameters" "^7.7.4" - "@babel/plugin-transform-property-literals" "^7.7.4" - "@babel/plugin-transform-regenerator" "^7.7.5" - "@babel/plugin-transform-reserved-words" "^7.7.4" - "@babel/plugin-transform-shorthand-properties" "^7.7.4" - "@babel/plugin-transform-spread" "^7.7.4" - "@babel/plugin-transform-sticky-regex" "^7.7.4" - "@babel/plugin-transform-template-literals" "^7.7.4" - "@babel/plugin-transform-typeof-symbol" "^7.7.4" - "@babel/plugin-transform-unicode-regex" "^7.7.4" - "@babel/types" "^7.7.4" - browserslist "^4.6.0" - core-js-compat "^3.4.7" - invariant "^2.2.2" - js-levenshtein "^1.1.3" +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-compilation-targets@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== + dependencies: + "@babel/compat-data" "^7.10.4" + browserslist "^4.12.0" + invariant "^2.2.4" + levenary "^1.1.1" semver "^5.5.0" -"@babel/template@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" - integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" - integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + regexpu-core "^4.7.0" + +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz#40a1cd917bff1288f699a94a75b37a1a2dbd8c7c" + integrity sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A== + dependencies: + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz#172f56e7a63e78112f3a04055f24365af702e7ee" + integrity sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA== + dependencies: + "@babel/types" "^7.10.5" + +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz#120c271c0b3353673fcdfd8c053db3c544a260d6" + integrity sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== + dependencies: + lodash "^4.17.19" + +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz#fce8bea4e9690bbe923056ded21e54b4e8b68ed5" + integrity sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-split-export-declaration@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz#2c70576eaa3b5609b24cb99db2888cc3fc4251d1" + integrity sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.10.4", "@babel/parser@^7.10.5", "@babel/parser@^7.7.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.5.tgz#e7c6bf5a7deff957cec9f04b551e2762909d826b" + integrity sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ== + +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz#50129ac216b9a6a55b3853fdd923e74bf553a4c0" + integrity sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.10.4" + +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz#750f1255e930a1f82d8cdde45031f81a0d0adff7" + integrity sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz#39abaae3cbf710c4373d8429484e6ba21340166c" + integrity sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" + +"@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-block-scoping@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz#b81b8aafefbfe68f0f65f7ef397b9ece68a6037d" + integrity sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-jscript@^7.2.0": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-jscript/-/plugin-transform-jscript-7.10.4.tgz#8ad6be0d283c8773bbbea68e53be3c2d3ad4a676" + integrity sha512-CVMP07FAysZPhPVtwb4PH30JHcNrLpjyDL7nrIuc0d4ENhl4V0ojXjBPwz86HJ2q9Er6OPwNwsW4HXzLQsyhAA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== + dependencies: + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== + dependencies: + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== + dependencies: + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + +"@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz#4e2c85ea0d6abaee1b24dcfbbae426fe8d674cff" + integrity sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-env@^7.6.2": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.10.4.tgz#fbf57f9a803afd97f4f32e4f798bb62e4b2bef5f" + integrity sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw== + dependencies: + "@babel/compat-data" "^7.10.4" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.10.4" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.10.4" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.10.4" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.10.4" + browserslist "^4.12.0" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.3.tgz#13242b53b5ef8c883c3cf7dddd55b36ce80fbc72" + integrity sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/runtime@^7.8.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.5.tgz#303d8bd440ecd5a491eae6117fd3367698674c5c" + integrity sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/traverse@^7.10.4", "@babel/traverse@^7.10.5", "@babel/traverse@^7.7.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.5.tgz#77ce464f5b258be265af618d8fddf0536f20b564" + integrity sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.10.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + "@babel/parser" "^7.10.5" + "@babel/types" "^7.10.5" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/types@^7", "@babel/types@^7.0.0", "@babel/types@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" - integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== +"@babel/types@^7", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.4.4", "@babel/types@^7.7.0": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.5.tgz#d88ae7e2fde86bfbfe851d4d81afa70a997b5d15" + integrity sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q== dependencies: - esutils "^2.0.2" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" +"@npmcli/move-file@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" + integrity sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw== + dependencies: + mkdirp "^1.0.4" + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/json-schema@^7.0.4": + version "7.0.5" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" + integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== + "@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" + integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" + "@webassemblyjs/ast" "1.9.0" -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" "@xtuc/ieee754@^1.2.0": @@ -825,11 +978,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - accepts@~1.3.7: version "1.3.7" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" @@ -838,25 +986,25 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -acorn-jsx@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" - integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn-jsx@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe" + integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ== -acorn-walk@^6.1.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" - integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn@^6.0.7, acorn@^6.2.1: - version "6.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" - integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" - integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== +acorn@^7.1.1, acorn@^7.2.0: + version "7.3.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" + integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== aggregate-error@^3.0.0: version "3.0.1" @@ -872,16 +1020,16 @@ ajv-errors@^1.0.0: integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + version "3.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.1.tgz#b83ca89c5d42d69031f424cad49aada0236c6957" + integrity sha512-KWcq3xN8fDjSB+IMoh2VaXVhRI0BBGxoYp3rx7Pkb6z0cFjYR9Q9l4yZqqals0/zsioCmocC5H6UvsGD4MoIBA== -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2: + version "6.12.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" + integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" @@ -891,22 +1039,10 @@ alphanum-sort@^1.0.0: resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= -ansi-escapes@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" - integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== - dependencies: - type-fest "^0.8.1" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^4.1.0: version "4.1.0" @@ -925,6 +1061,14 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -941,19 +1085,11 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.0.3, aproba@^1.1.1: +aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -976,24 +1112,39 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= -array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= +array-includes@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" + integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" + define-properties "^1.1.3" + es-abstract "^1.17.0" + is-string "^1.0.5" array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flatmap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" + integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1011,6 +1162,16 @@ assert@^1.1.1: object-assign "^4.1.1" util "0.10.3" +assert@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" + integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== + dependencies: + es6-object-assign "^1.1.0" + is-nan "^1.2.1" + object-is "^1.0.1" + util "^0.12.0" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1026,49 +1187,57 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async-limiter@^1.0.0, async-limiter@~1.0.0: +async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" + integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== + dependencies: + array-filter "^1.0.0" + babel-eslint@^10.0.3: - version "10.0.3" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" - integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== dependencies: "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.0.0" - "@babel/traverse" "^7.0.0" - "@babel/types" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" eslint-visitor-keys "^1.0.0" resolve "^1.12.0" babel-loader@^8.0.6: - version "8.0.6" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" - integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" + integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" pify "^4.0.1" + schema-utils "^2.6.5" -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" babel-plugin-inferno@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/babel-plugin-inferno/-/babel-plugin-inferno-6.1.0.tgz#5fb0e1fb21848e1014f2753c3c99df1d2ac94b34" - integrity sha512-hY2Bi66RAJOumYP9OZA3r8FbWwBnCmvJ+bzN8FSdvJiWJd+Ss/yS8GRzoF53ri4QCZu07ERxilphTPVeB7tf+g== + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-inferno/-/babel-plugin-inferno-6.1.1.tgz#15c6bfb9fff75a6669e9f6410bb36512eae8ba54" + integrity sha512-uyFJZ1gMRokXA2gFCQhxM9V0V9daOpgCiMj8Qp/gkJN0zW471ozPoTPppt+pmm+soxWyU7UmLMxa3/cqsBGm+Q== dependencies: "@babel/plugin-syntax-jsx" "^7" "@babel/types" "^7" @@ -1122,19 +1291,31 @@ binary-extensions@^1.0.0: integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: + version "4.11.9" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== + +bn.js@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0" + integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA== body-parser@1.19.0: version "1.19.0" @@ -1224,7 +1405,7 @@ browserify-des@^1.0.0: inherits "^2.0.1" safe-buffer "^5.1.2" -browserify-rsa@^4.0.0: +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= @@ -1233,17 +1414,19 @@ browserify-rsa@^4.0.0: randombytes "^2.0.1" browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + version "4.2.0" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.0.tgz#545d0b1b07e6b2c99211082bf1b12cce7a0b0e11" + integrity sha512-hEZC1KEeYuoHRqhGhTy6gWrpJA3ZDjFWv0DE61643ZnOXAKJb3u7yWcrU0mMc9SwAqK1n7myPGndkp0dFG7NFA== dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.2" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" browserify-zlib@^0.2.0: version "0.2.0" @@ -1252,14 +1435,15 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.2.tgz#b45720ad5fbc8713b7253c20766f701c9a694289" - integrity sha512-+M4oeaTplPm/f1pXDw84YohEv7B1i/2Aisei8s4s6k3QsoSHa7i5sz8u/cGQkkatCPxMASKxPualR4wwYgVboA== +browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5: + version "4.13.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" + integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== dependencies: - caniuse-lite "^1.0.30001015" - electron-to-chromium "^1.3.322" - node-releases "^1.1.42" + caniuse-lite "^1.0.30001093" + electron-to-chromium "^1.3.488" + escalade "^3.0.1" + node-releases "^1.1.58" buffer-from@^1.0.0: version "1.1.1" @@ -1291,9 +1475,9 @@ bytes@3.1.0: integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== cacache@^12.0.2: - version "12.0.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" - integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== dependencies: bluebird "^3.5.5" chownr "^1.1.1" @@ -1311,28 +1495,27 @@ cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^13.0.1: - version "13.0.1" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" - integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w== +cacache@^15.0.4: + version "15.0.5" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" + integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== dependencies: - chownr "^1.1.2" - figgy-pudding "^3.5.1" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" fs-minipass "^2.0.0" glob "^7.1.4" - graceful-fs "^4.2.2" infer-owner "^1.0.4" - lru-cache "^5.1.1" - minipass "^3.0.0" + lru-cache "^6.0.0" + minipass "^3.1.1" minipass-collect "^1.0.2" minipass-flush "^1.0.5" minipass-pipeline "^1.2.2" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - p-map "^3.0.0" + mkdirp "^1.0.3" + p-map "^4.0.0" promise-inflight "^1.0.1" - rimraf "^2.7.1" - ssri "^7.0.0" + rimraf "^3.0.2" + ssri "^8.0.0" + tar "^6.0.2" unique-filename "^1.1.1" cache-base@^1.0.1: @@ -1389,12 +1572,12 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001015: - version "1.0.30001015" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0" - integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001093: + version "1.0.30001100" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001100.tgz#2a58615e0c01cf716ab349b20ca4d86ef944aa4e" + integrity sha512-0eYdp1+wFCnMlCj2oudciuQn2B9xAFq3WpgpcBIZTxk/1HNA/O2YA7rpeYhnOqsqAJq1AHUgx6i1jtafg7m2zA== -chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1403,20 +1586,23 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" check-types@^8.0.3: version "8.0.3" resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== -"chokidar@>=2.0.0 <4.0.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.0.tgz#b30611423ce376357c765b9b8f904b9fba3c0be8" + integrity sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -1424,11 +1610,11 @@ check-types@^8.0.3: is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.2.0" + readdirp "~3.4.0" optionalDependencies: - fsevents "~2.1.1" + fsevents "~2.1.2" -chokidar@^2.0.2: +chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== @@ -1447,10 +1633,15 @@ chokidar@^2.0.2: optionalDependencies: fsevents "^1.2.7" -chownr@^1.1.1, chownr@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== chrome-trace-event@^1.0.2: version "1.0.2" @@ -1482,18 +1673,6 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -1503,15 +1682,6 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - coa@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" @@ -1521,11 +1691,6 @@ coa@^2.0.2: chalk "^2.4.1" q "^1.1.2" -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -1541,12 +1706,19 @@ color-convert@^1.9.0, color-convert@^1.9.1: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-name@^1.0.0: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== @@ -1602,11 +1774,6 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -1658,18 +1825,18 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.4.7: - version "3.4.8" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.4.8.tgz#f72e6a4ed76437ea710928f44615f926a81607d5" - integrity sha512-l3WTmnXHV2Sfu5VuD7EHE2w7y+K68+kULKt5RJg8ZJk3YhHF1qLD4O8v8AmNq+8vbOwnPFFDvds25/AoEvMqlQ== +core-js-compat@^3.6.2: + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" + integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== dependencies: - browserslist "^4.8.2" - semver "^6.3.0" + browserslist "^4.8.5" + semver "7.0.0" core-js@^3.2.1: - version "3.4.8" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.4.8.tgz#e0fc0c61f2ef90cbc10c531dbffaa46dfb7152dd" - integrity sha512-b+BBmCZmVgho8KnBUOXpvlqEMguko+0P+kXCwD4vIprsXC6ht1qgPxtb1OK6XgSlrySF71wkwBQ0Hv695bk9gQ== + version "3.6.5" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" + integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== core-util-is@~1.0.0: version "1.0.2" @@ -1694,7 +1861,7 @@ create-ecdh@^4.0.0: bn.js "^4.1.0" elliptic "^6.0.0" -create-hash@^1.1.0, create-hash@^1.1.2: +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== @@ -1705,7 +1872,7 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -1717,7 +1884,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -1728,6 +1895,15 @@ cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -1759,22 +1935,23 @@ css-declaration-sorter@^4.0.1: timsort "^0.3.0" css-loader@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.3.0.tgz#65f889807baec3197313965d6cda9899f936734d" - integrity sha512-x9Y1vvHe5RR+4tzwFdWExPueK00uqFTCw7mZy+9aE/X1SKWOArm5luaOrtJ4d05IpOwJ6S86b/tVcIdhw1Bu4A== + version "3.6.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== dependencies: camelcase "^5.3.1" cssesc "^3.0.0" icss-utils "^4.1.1" loader-utils "^1.2.3" normalize-path "^3.0.0" - postcss "^7.0.23" + postcss "^7.0.32" postcss-modules-extract-imports "^2.0.0" postcss-modules-local-by-default "^3.0.2" - postcss-modules-scope "^2.1.1" + postcss-modules-scope "^2.2.0" postcss-modules-values "^3.0.0" - postcss-value-parser "^4.0.2" - schema-utils "^2.6.0" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" + semver "^6.3.0" css-select-base-adapter@^0.1.1: version "0.1.1" @@ -1799,20 +1976,18 @@ css-tree@1.0.0-alpha.37: mdn-data "2.0.4" source-map "^0.6.1" -css-unit-converter@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" - integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= +css-tree@1.0.0-alpha.39: + version "1.0.0-alpha.39" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.39.tgz#2bff3ffe1bb3f776cf7eefd91ee5cba77a149eeb" + integrity sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA== + dependencies: + mdn-data "2.0.6" + source-map "^0.6.1" css-what@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" - integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== - -cssesc@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" - integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.3.0.tgz#10fec696a9ece2e591ac772d759aacabac38cd39" + integrity sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg== cssesc@^3.0.0: version "3.0.0" @@ -1888,11 +2063,11 @@ cssnano@^4.1.10: postcss "^7.0.0" csso@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" - integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== + version "4.0.3" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.3.tgz#0d9985dc852c7cc2b2cacfbbe1079014d1a8e903" + integrity sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ== dependencies: - css-tree "1.0.0-alpha.37" + css-tree "1.0.0-alpha.39" cyclist@^1.0.1: version "1.0.1" @@ -1906,13 +2081,6 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@^4.0.1, debug@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -1930,12 +2098,7 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@~0.1.3: +deep-is@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -1969,11 +2132,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -1997,11 +2155,6 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -2055,6 +2208,11 @@ domelementtype@^2.0.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== +dompurify@^2.0.11: + version "2.0.12" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.12.tgz#284a2b041e1c60b8e72d7b4d2fadad36141254ae" + integrity sha512-Fl8KseK1imyhErHypFPA8qpq9gPzlsJ/EukA6yk9o0gX23p1TzC+rh9LqNg1qvErRTc0UNMYlKxEGSfSh43NDg== + domutils@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -2063,12 +2221,12 @@ domutils@^1.7.0: dom-serializer "0" domelementtype "1" -dot-prop@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== +dot-prop@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" + integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A== dependencies: - is-obj "^1.0.0" + is-obj "^2.0.0" duplexer@^0.1.1: version "0.1.1" @@ -2095,15 +2253,15 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.322: - version "1.3.322" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" - integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA== +electron-to-chromium@^1.3.488: + version "1.3.498" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.498.tgz#fd7188c8a49d6d0b5df1df55a1f1a4bf2c177457" + integrity sha512-W1hGwaQEU8j9su2jeAr3aabkPuuXw+j8t73eajGAkEJWbfWiwbxBwQN/8Qmv2qCy3uCDm2rOAaZneYQM8VGC4w== -elliptic@^6.0.0: - version "6.5.2" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" - integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== +elliptic@^6.0.0, elliptic@^6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" brorand "^1.0.1" @@ -2118,15 +2276,10 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== encodeurl@~1.0.2: version "1.0.2" @@ -2140,28 +2293,26 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - tapable "^1.0.0" - -enhanced-resolve@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== +enhanced-resolve@^4.1.0, enhanced-resolve@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" tapable "^1.0.0" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" - integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== errno@^0.1.3, errno@~0.1.7: version "0.1.7" @@ -2177,21 +2328,22 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.12.0, es-abstract@^1.15.0, es-abstract@^1.5.1, es-abstract@^1.7.0: - version "1.16.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.3.tgz#52490d978f96ff9f89ec15b5cf244304a5bca161" - integrity sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw== +es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.4, es-abstract@^1.17.5: + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.4" - is-regex "^1.0.4" + is-callable "^1.2.0" + is-regex "^1.1.0" object-inspect "^1.7.0" object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" + object.assign "^4.1.0" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -2202,6 +2354,16 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-object-assign@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" + integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= + +escalade@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" + integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -2212,26 +2374,22 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-plugin-eslint-plugin@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz#a7a00f15a886957d855feacaafee264f039e62d5" - integrity sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg== - eslint-plugin-react@^7.17.0: - version "7.17.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz#a31b3e134b76046abe3cd278e7482bd35a1d12d7" - integrity sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A== + version "7.20.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" + integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== dependencies: - array-includes "^3.0.3" + array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" doctrine "^2.1.0" - eslint-plugin-eslint-plugin "^2.1.0" has "^1.0.3" - jsx-ast-utils "^2.2.3" - object.entries "^1.1.0" - object.fromentries "^2.0.1" - object.values "^1.1.0" + jsx-ast-utils "^2.4.1" + object.entries "^1.1.2" + object.fromentries "^2.0.2" + object.values "^1.1.1" prop-types "^15.7.2" - resolve "^1.13.1" + resolve "^1.17.0" + string.prototype.matchall "^4.0.2" eslint-scope@^4.0.3: version "4.0.3" @@ -2241,42 +2399,43 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-scope@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== +eslint-utils@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint@^6.7.2: - version "6.7.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" - integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== +eslint@^7.4.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.4.0.tgz#4e35a2697e6c1972f9d6ef2b690ad319f80f206f" + integrity sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.0" + eslint-utils "^2.0.0" + eslint-visitor-keys "^1.2.0" + espree "^7.1.0" + esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" @@ -2285,45 +2444,43 @@ eslint@^6.7.2: ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" + levn "^0.4.1" lodash "^4.17.14" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" table "^5.2.3" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== +espree@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c" + integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw== dependencies: - acorn "^7.1.0" - acorn-jsx "^5.1.0" - eslint-visitor-keys "^1.1.0" + acorn "^7.2.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.2.0" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" esrecurse@^4.1.0: version "4.2.1" @@ -2332,11 +2489,16 @@ esrecurse@^4.1.0: dependencies: estraverse "^4.1.0" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.0, estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== +estraverse@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" + integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2348,9 +2510,9 @@ etag@~1.8.1: integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" @@ -2360,19 +2522,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -2444,15 +2593,6 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -2468,27 +2608,27 @@ extglob@^2.0.4: to-regex "^3.0.1" extract-css-chunks-webpack-plugin@^4.6.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/extract-css-chunks-webpack-plugin/-/extract-css-chunks-webpack-plugin-4.7.1.tgz#8bfb94463a8d31c80d88b9c419507c472d810657" - integrity sha512-dpcOJA3wQk4rbgbOGRXyK3Gjl+/Ng8miD162/0uol31Ld4PLnQqIMbKV6ju/gi+uwfZIQcBW3KW1pmfU0epmDg== + version "4.7.5" + resolved "https://registry.yarnpkg.com/extract-css-chunks-webpack-plugin/-/extract-css-chunks-webpack-plugin-4.7.5.tgz#d85ebf0aaf3366f942502eced275711d72bd4ba9" + integrity sha512-7XlPj/OW+vpIdMcm1H/mo5hgJubMKXlWF5Pgq9F/db39b19A+XlRWppyAZHNaJChC8kJKQl5n8PbfwouIl9AJQ== dependencies: - loader-utils "^1.1.0" + loader-utils "^2.0.0" normalize-url "1.9.1" schema-utils "^1.0.0" - webpack-external-import "^0.3.0-beta.0" + webpack-external-import "^2.2.4" webpack-sources "^1.1.0" -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= @@ -2499,16 +2639,9 @@ fg-loadcss@^2.1.0: integrity sha512-HpvR2uRoKvrYAEwimw+k4Fr2NVHYPfld5Lc/f9uy3mKeUTXhS5urL24XA2rqyq5b2i410EXCLir4Uhsb8J1QaQ== figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== - -figures@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" - integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== - dependencies: - escape-string-regexp "^1.0.5" + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== file-entry-cache@^5.0.1: version "5.0.1" @@ -2517,13 +2650,18 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-loader@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-5.0.2.tgz#7f3d8b4ac85a5e8df61338cfec95d7405f971caa" - integrity sha512-QMiQ+WBkGLejKe81HU8SZ9PovsU/5uaLo0JdTCEXOYv7i7jfAjHZi1tcwp9tSASJPOmmHZtbdCervFmXMH/Dcg== +file-loader@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.0.0.tgz#97bbfaab7a2460c07bcbd72d3a6922407f67649f" + integrity sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ== dependencies: - loader-utils "^1.2.3" - schema-utils "^2.5.0" + loader-utils "^2.0.0" + schema-utils "^2.6.5" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filesize@^3.6.1: version "3.6.1" @@ -2560,7 +2698,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: +find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== @@ -2569,13 +2707,13 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.1.0.tgz#9935894999debef4cf9f677fdf646d002c4cdecb" - integrity sha512-zw+EFiNBNPgI2NTrKkDd1xd7q0cs6wr/iWnr/oUkI0yF9K9GqQ+riIt4aiyFaaqpaWbxPrJXHI+QvmNUQbX+0Q== +find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" - make-dir "^3.0.0" + make-dir "^3.0.2" pkg-dir "^4.1.0" find-up@^3.0.0: @@ -2593,7 +2731,7 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" -findup-sync@3.0.0: +findup-sync@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== @@ -2613,9 +2751,9 @@ flat-cache@^2.0.1: write "1.0.3" flatted@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== flush-write-stream@^1.0.0: version "1.1.1" @@ -2630,6 +2768,11 @@ for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -2664,17 +2807,10 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - fs-minipass@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.0.0.tgz#a6415edab02fae4b9e9230bc87ee2e4472003cd1" - integrity sha512-40Qz+LFXmd9tzYVnnBmZvFfvAADfUA14TXPK1s7IfElJTIZ97rA8w4Kin7Wt5JBrC3ShnnFJO/5vPjPEeJIq9A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" @@ -2694,17 +2830,17 @@ fs.realpath@^1.0.0: integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: + bindings "^1.5.0" nan "^2.12.1" - node-pre-gyp "^0.12.0" -fsevents@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" - integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== function-bind@^1.1.1: version "1.1.1" @@ -2716,32 +2852,16 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -2756,9 +2876,9 @@ glob-parent@^3.1.0: path-dirname "^1.0.0" glob-parent@^5.0.0, glob-parent@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" @@ -2774,13 +2894,6 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -global-modules@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - global-modules@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" @@ -2790,6 +2903,13 @@ global-modules@^1.0.0: is-windows "^1.0.1" resolve-dir "^1.0.0" +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + global-prefix@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" @@ -2816,16 +2936,16 @@ globals@^11.1.0: integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^12.1.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" - integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== dependencies: type-fest "^0.8.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== growly@^1.3.0: version "1.3.0" @@ -2845,16 +2965,16 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -2886,7 +3006,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.0, has@^1.0.1, has@^1.0.3: +has@^1.0.0, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -2894,12 +3014,13 @@ has@^1.0.0, has@^1.0.1, has@^1.0.3: function-bind "^1.1.1" hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" @@ -2977,7 +3098,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: +iconv-lite@0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3001,13 +3122,6 @@ iferr@^0.1.5: resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -3029,7 +3143,7 @@ import-fresh@^3.0.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@2.0.0: +import-local@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== @@ -3057,23 +3171,23 @@ infer-owner@^1.0.3, infer-owner@^1.0.4: resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== -inferno-shared@7.3.3: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inferno-shared/-/inferno-shared-7.3.3.tgz#aa4b70a38d1f37498766f31c6a99f5c5dfc58b63" - integrity sha512-OPpYFEHLA6grY8phbdG21ST7mjkUNXjZMpfZKgHrPUORFxnnn+u+i57QDpht5RtUZgVpHIKNxNQypq6+/m4LEA== +inferno-shared@7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/inferno-shared/-/inferno-shared-7.4.2.tgz#400cf6d19a077af9e5e852e1f189726391efa273" + integrity sha512-SULfgzj/PuyMd3rHThEXkeEdZorjcr/q+kaqbwr7C2XhIPCk4e5jcRKZujI6YCSahGA9WFwP2Mft1v5PsaaNeg== -inferno-vnode-flags@7.3.3: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inferno-vnode-flags/-/inferno-vnode-flags-7.3.3.tgz#aebaddea1569dd16512f44b92bf587837328db9d" - integrity sha512-LzLIRVrpv3OoH5gwWXOrHmgx3vMysI1fEG9PUBEc7Alz+vnD9rRBu9sP5AvGRN7Nxli7iLo6WcqF1nDIANGL7Q== +inferno-vnode-flags@7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/inferno-vnode-flags/-/inferno-vnode-flags-7.4.2.tgz#54982dabe34f308853ba17de7de4241e23769135" + integrity sha512-sV4KqqvZH4MW9/dNbC9blHInnpQSqMWouU5VlanbJ+NhJ8ufPwsDy0/+jiA2aODpg2HFHwVMJFF1fsewPqNtLQ== inferno@^7.3.2: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inferno/-/inferno-7.3.3.tgz#4098d5313c53281e44a857619764e74ab4438415" - integrity sha512-FlTMi77+uF0dR3HDfrhysCmOPE6cj9/2jDLQzUSx0KciewVQq7N2KdsfsA0HVSzVb9Do1pjcRtnAIDXmfKzGfA== + version "7.4.2" + resolved "https://registry.yarnpkg.com/inferno/-/inferno-7.4.2.tgz#833cc423ee7b939fad705c59ea41924f31c92453" + integrity sha512-RsmuN8F7lAWTTuy2juf3Tqn/BihkRNdy0WZN+vuyryuEySKHBA1fruyq6K0covF3Ja8mAdha5NNISZz9ltgcug== dependencies: - inferno-shared "7.3.3" - inferno-vnode-flags "7.3.3" + inferno-shared "7.4.2" + inferno-vnode-flags "7.4.2" opencollective-postinstall "^2.0.2" inflight@^1.0.4: @@ -3084,7 +3198,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3099,51 +3213,36 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: +ini@^1.3.4, ini@^1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" - integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== +internal-slot@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" + integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== dependencies: - ansi-escapes "^4.2.1" - chalk "^2.4.2" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^4.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" + es-abstract "^1.17.0-next.1" + has "^1.0.3" + side-channel "^1.0.2" -interpret@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== +interpret@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -invariant@^2.2.2: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" -invert-kv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== - -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== is-absolute-url@^2.0.0: version "2.1.0" @@ -3164,6 +3263,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -3193,10 +3297,10 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== is-color-stop@^1.0.0: version "1.1.0" @@ -3225,9 +3329,9 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" @@ -3252,6 +3356,11 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= +is-docker@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" + integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -3269,22 +3378,15 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-function@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" + integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== is-glob@^3.1.0: version "3.1.0" @@ -3300,6 +3402,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-nan@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.0.tgz#85d1f5482f7051c2019f5673ccebdb06f3b0db03" + integrity sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ== + dependencies: + define-properties "^1.1.3" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3312,10 +3421,10 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-plain-obj@^1.0.0: version "1.1.0" @@ -3329,27 +3438,22 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= +is-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" + integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== dependencies: - has "^1.0.1" + has-symbols "^1.0.1" is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== is-svg@^3.0.0: version "3.0.0" @@ -3365,6 +3469,16 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.1" +is-typed-array@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d" + integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ== + dependencies: + available-typed-arrays "^1.0.0" + es-abstract "^1.17.4" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -3376,9 +3490,11 @@ is-wsl@^1.1.0: integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= is-wsl@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.1.1.tgz#4a1c152d429df3d441669498e2486d3596ebaf1d" - integrity sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog== + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" @@ -3402,18 +3518,13 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -jest-worker@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" - integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== +jest-worker@^26.0.0: + version "26.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.1.0.tgz#65d5641af74e08ccd561c240e7db61284f82f33d" + integrity sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ== dependencies: merge-stream "^2.0.0" - supports-color "^6.1.0" - -js-levenshtein@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" - integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== + supports-color "^7.0.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" @@ -3421,9 +3532,9 @@ js-levenshtein@^1.1.3: integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -3460,12 +3571,12 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" - integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== dependencies: - minimist "^1.2.0" + minimist "^1.2.5" jsonfile@^4.0.0: version "4.0.0" @@ -3474,12 +3585,12 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsx-ast-utils@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz#8a9364e402448a3ce7f14d357738310d9248054f" - integrity sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA== +jsx-ast-utils@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" + integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== dependencies: - array-includes "^3.0.3" + array-includes "^3.1.1" object.assign "^4.1.0" kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: @@ -3502,9 +3613,14 @@ kind-of@^5.0.0: integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klona@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/klona/-/klona-1.1.2.tgz#a79e292518a5a5412ec8d097964bff1571a64db0" + integrity sha512-xf88rTeHiXk+XE2Vhi6yj8Wm3gMZrygGdKjJqN8HkV+PwF/t50/LdAKHoHpPcxFAlmQszTZ1CugrK25S7qDRLA== last-call-webpack-plugin@^3.0.0: version "3.0.0" @@ -3514,39 +3630,53 @@ last-call-webpack-plugin@^3.0.0: lodash "^4.17.5" webpack-sources "^1.1.0" -lcid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== - dependencies: - invert-kv "^2.0.0" +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" + leven "^3.1.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" loader-runner@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== -loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== +loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: big.js "^5.2.2" - emojis-list "^2.0.0" + emojis-list "^3.0.0" json5 "^1.0.1" -loadjs@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/loadjs/-/loadjs-3.6.1.tgz#1e756ccd4f4c5ed4988085b330e1b4ad9b6a8340" - integrity sha512-AZEBw2GWdJk2IzBgQ+Wohoao5j+t0rajqK8dJu8jQqgYxDTxhmCt0ayMo/vCa0ZAMvZxnJcam6uLICfnVd8KAw== +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +loadjs@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/loadjs/-/loadjs-4.2.0.tgz#2a0336376397a6a43edf98c9ec3229ddd5abb6f6" + integrity sha512-AgQGZisAlTPbTEzrHPb6q+NYBMD+DP9uvGSIjSUM5uG+0jG15cb8axWpxuOIqrmQjn6scaaH8JwloiP27b2KXA== locate-path@^3.0.0: version "3.0.0" @@ -3573,10 +3703,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5: + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== loose-envify@^1.0.0, loose-envify@^1.4.0: version "1.4.0" @@ -3592,6 +3722,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + make-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -3600,19 +3737,14 @@ make-dir@^2.0.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" - integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== +make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== - -map-age-cleaner@^0.1.1: +map-age-cleaner@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== @@ -3631,6 +3763,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +marked@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/marked/-/marked-1.1.1.tgz#e5d61b69842210d5df57b05856e0c91572703e6a" + integrity sha512-mJzT8D2yPxoPh7h0UXkB+dBj4FykPJ2OIfxAWeIHrvoHDkFxukV/29QxoFQoPM6RLEwhIFdJpmKBlqVM3s2ZIw== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -3645,21 +3782,25 @@ mdn-data@2.0.4: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== +mdn-data@2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.6.tgz#852dc60fcaa5daa2e8cf6c9189c440ed3e042978" + integrity sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA== + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -mem@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" - integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== +mem@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-6.1.0.tgz#846eca0bd4708a8f04b9c3f3cd769e194ae63c5c" + integrity sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg== dependencies: - map-age-cleaner "^0.1.1" - mimic-fn "^2.0.0" - p-is-promise "^2.0.0" + map-age-cleaner "^0.1.3" + mimic-fn "^3.0.0" -memory-fs@^0.4.0, memory-fs@^0.4.1: +memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= @@ -3717,32 +3858,27 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.42.0: - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== -mime-types@~2.1.24: - version "2.1.25" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" - integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== +mime-types@^2.1.26, mime-types@~2.1.24: + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== dependencies: - mime-db "1.42.0" + mime-db "1.44.0" mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" - integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== - -mimic-fn@^2.0.0, mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b" + integrity sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ== minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" @@ -3761,15 +3897,10 @@ minimatch@^3.0.4: dependencies: brace-expansion "^1.1.7" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== minipass-collect@^1.0.2: version "1.0.2" @@ -3786,33 +3917,26 @@ minipass-flush@^1.0.5: minipass "^3.0.0" minipass-pipeline@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz#3dcb6bb4a546e32969c7ad710f2c79a86abba93a" - integrity sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA== + version "1.2.3" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.3.tgz#55f7839307d74859d6e8ada9c3ebe72cec216a34" + integrity sha512-cFOknTvng5vqnwOpDsZTWhNll6Jf8o2x+/diplafmxpuIymAjzoOolZG0VvQf3V2HgqzJNhnuKHYp2BqDgz8IQ== dependencies: minipass "^3.0.0" -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - minipass@^3.0.0, minipass@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" - integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w== + version "3.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== dependencies: yallist "^4.0.0" -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== +minizlib@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" + integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA== dependencies: - minipass "^2.9.0" + minipass "^3.0.0" + yallist "^4.0.0" mississippi@^3.0.0: version "3.0.0" @@ -3838,12 +3962,17 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= +mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: - minimist "0.0.8" + minimist "^1.2.5" + +mkdirp@^1.0.3, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== move-concurrently@^1.0.1: version "1.0.1" @@ -3872,15 +4001,10 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - nan@^2.12.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + version "2.14.1" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" + integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== nanomatch@^1.2.9: version "1.2.13" @@ -3904,24 +4028,15 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.5.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" @@ -3957,47 +4072,22 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-notifier@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-6.0.0.tgz#cea319e06baa16deec8ce5cd7f133c4a46b68e12" - integrity sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw== +node-notifier@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-7.0.1.tgz#a355e33e6bebacef9bf8562689aed0f4230ca6f9" + integrity sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg== dependencies: growly "^1.3.0" is-wsl "^2.1.1" - semver "^6.3.0" + semver "^7.2.1" shellwords "^0.1.1" - which "^1.3.1" + uuid "^7.0.3" + which "^2.0.2" -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -node-releases@^1.1.42: - version "1.1.42" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.42.tgz#a999f6a62f8746981f6da90627a8d2fc090bbad7" - integrity sha512-OQ/ESmUqGawI2PRX+XIRao44qWYBBfN54ImQYdWVTQqUckuejOg76ysSqDBK8NG3zwySRVnX36JwDQ6x+9GxzA== - dependencies: - semver "^6.3.0" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" +node-releases@^1.1.58: + version "1.1.59" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.59.tgz#4d648330641cec704bff10f8e4fe28e453ab8e8e" + integrity sha512-H3JrdUczbdiwxN5FuJPyCHnGHIFqQ0wWxo+9j1kAXAzqNMAHlo+4I/sYYxpyK0irQ73HgdiyzD32oqQDcU2Osw== normalize-path@^2.1.1: version "2.1.1" @@ -4026,43 +4116,6 @@ normalize-url@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^1.1.6: - version "1.4.7" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" - integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -4070,11 +4123,6 @@ nth-check@^1.0.2: dependencies: boolbase "~1.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -4090,9 +4138,17 @@ object-copy@^0.1.0: kind-of "^3.0.3" object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== + +object-is@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" + integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -4116,33 +4172,32 @@ object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" -object.entries@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.0.tgz#2024fc6d6ba246aee38bdb0ffd5cfbcf371b7519" - integrity sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA== +object.entries@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" + integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.5" + has "^1.0.3" + +object.fromentries@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" + integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" -object.fromentries@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.1.tgz#050f077855c7af8ae6649f45c80b16ee2d31e704" - integrity sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA== +object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== dependencies: define-properties "^1.1.3" - es-abstract "^1.15.0" - function-bind "^1.1.1" - has "^1.0.3" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" + es-abstract "^1.17.0-next.1" object.pick@^1.3.0: version "1.3.0" @@ -4151,13 +4206,13 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== +object.values@^1.1.0, object.values@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -4175,17 +4230,10 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - opencollective-postinstall@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" - integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" + integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== opener@^1.5.1: version "1.5.1" @@ -4200,69 +4248,39 @@ optimize-css-assets-webpack-plugin@^5.0.3: cssnano "^4.1.10" last-call-webpack-plugin "^3.0.0" -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" os-browserify@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" - integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== - dependencies: - execa "^1.0.0" - lcid "^2.0.0" - mem "^4.0.0" - -os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-is-promise@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" - integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== - p-limit@^2.0.0, p-limit@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== dependencies: p-try "^2.0.0" @@ -4280,10 +4298,10 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" @@ -4293,9 +4311,9 @@ p-try@^2.0.0: integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pako@~1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parallel-transform@^1.1.0: version "1.2.0" @@ -4313,7 +4331,7 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0: +parse-asn1@^5.0.0, parse-asn1@^5.1.5: version "5.1.5" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== @@ -4373,11 +4391,16 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.0, path-key@^2.0.1: +path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -4389,9 +4412,9 @@ path-to-regexp@0.1.7: integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= pbkdf2@^3.0.3: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== dependencies: create-hash "^1.1.2" create-hmac "^1.1.4" @@ -4399,10 +4422,10 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -picomatch@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" - integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^4.0.1: version "4.0.1" @@ -4423,20 +4446,26 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" - integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + version "7.0.2" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" + integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== dependencies: - css-unit-converter "^1.1.1" - postcss "^7.0.5" - postcss-selector-parser "^5.0.0-rc.4" - postcss-value-parser "^3.3.1" + postcss "^7.0.27" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.2" postcss-colormin@^4.0.3: version "4.0.3" @@ -4564,10 +4593,10 @@ postcss-modules-local-by-default@^3.0.2: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.0.0" -postcss-modules-scope@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz#33d4fc946602eb5e9355c4165d68a10727689dba" - integrity sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ== +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: postcss "^7.0.6" postcss-selector-parser "^6.0.0" @@ -4691,20 +4720,11 @@ postcss-reduce-transforms@^4.0.2: postcss-value-parser "^3.0.0" postcss-selector-parser@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" - integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= + version "3.1.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz#b310f5c4c0fdaf76f94902bbaa30db6aa84f5270" + integrity sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA== dependencies: - dot-prop "^4.1.1" - indexes-of "^1.0.1" - uniq "^1.0.1" - -postcss-selector-parser@^5.0.0-rc.4: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" - integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== - dependencies: - cssesc "^2.0.0" + dot-prop "^5.2.0" indexes-of "^1.0.1" uniq "^1.0.1" @@ -4736,40 +4756,35 @@ postcss-unique-selectors@^4.0.1: postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: +postcss-value-parser@^3.0.0: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" - integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.23, postcss@^7.0.5, postcss@^7.0.6: - version "7.0.24" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.24.tgz#972c3c5be431b32e40caefe6c81b5a19117704c2" - integrity sha512-Xl0XvdNWg+CblAXzNvbSOUvgJXwSjmbAKORqyw9V2AlHrm1js2gFw9y3jibBAhpKZi8b5JzJCVh/FyzPsTtgTA== +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= -private@^0.1.6: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -4800,12 +4815,12 @@ prop-types@^15.7.2: react-is "^16.8.1" proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== + version "2.0.6" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== dependencies: forwarded "~0.1.2" - ipaddr.js "1.9.0" + ipaddr.js "1.9.1" prr@~1.0.1: version "1.0.1" @@ -4892,7 +4907,7 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== @@ -4922,25 +4937,15 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-is@^16.8.1: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" - integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -4950,6 +4955,15 @@ react-is@^16.8.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" @@ -4959,36 +4973,36 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== dependencies: - picomatch "^2.0.4" + picomatch "^2.2.1" -regenerate-unicode-properties@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" - integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== dependencies: regenerate "^1.4.0" regenerate@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + version "1.4.1" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" + integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== -regenerator-runtime@^0.13.3: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== +regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== -regenerator-transform@^0.14.0: - version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" - integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: - private "^0.1.6" + "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" @@ -4998,32 +5012,40 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexp.prototype.flags@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" -regexpu-core@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" - integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== +regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + +regexpu-core@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" + integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== dependencies: regenerate "^1.4.0" - regenerate-unicode-properties "^8.1.0" - regjsgen "^0.5.0" - regjsparser "^0.6.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.1.0" + unicode-match-property-value-ecmascript "^1.2.0" -regjsgen@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" - integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== +regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== -regjsparser@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.0.tgz#f1e6ae8b7da2bae96c99399b868cd6c933a2ba9c" - integrity sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ== +regjsparser@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" + integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== dependencies: jsesc "~0.5.0" @@ -5082,21 +5104,13 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2: - version "1.13.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" - integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== +resolve@^1.12.0, resolve@^1.17.0, resolve@^1.3.2: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -5124,13 +5138,20 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1: +rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -5139,13 +5160,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -5153,22 +5167,15 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.4.0: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== - dependencies: - tslib "^1.9.0" - safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-regex@^1.1.0: version "1.1.0" @@ -5182,25 +5189,25 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-loader@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.0.tgz#e7b07a3e357f965e6b03dd45b016b0a9746af797" - integrity sha512-+qeMu563PN7rPdit2+n5uuYVR0SSVwm0JsOUsaJXzgYcClWSlmX0iHDnmeOobPkf5kUglVot3QS6SyLyaQoJ4w== +sass-loader@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-9.0.2.tgz#847c9b4c95328ddc8c7d35cf28c9d6e54e59a90b" + integrity sha512-nphcum3jNI442njnrZ5wJgSNX5lfEOHOKHCLf+PrTIaleploKqAMUuT9CVKjf+lyi6c2MCGPHh1vb9nGsjnZJA== dependencies: - clone-deep "^4.0.1" - loader-utils "^1.2.3" + klona "^1.1.1" + loader-utils "^2.0.0" neo-async "^2.6.1" - schema-utils "^2.1.0" - semver "^6.3.0" + schema-utils "^2.7.0" + semver "^7.3.2" sass@^1.22.12: - version "1.23.7" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.23.7.tgz#090254e006af1219d442f1bff31e139d5e085dff" - integrity sha512-cYgc0fanwIpi0rXisGxl+/wadVQ/HX3RhpdRcjLdj2o2ye/sxUTpAxIhbmJy3PLQgRFbf6Pn8Jsrta2vdXcoOQ== + version "1.26.10" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.10.tgz#851d126021cdc93decbf201d1eca2a20ee434760" + integrity sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw== dependencies: chokidar ">=2.0.0 <4.0.0" -sax@^1.2.4, sax@~1.2.4: +sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -5214,24 +5221,35 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.5.0, schema-utils@^2.6.0, schema-utils@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.1.tgz#eb78f0b945c7bcfa2082b3565e8db3548011dc4f" - integrity sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg== +schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== dependencies: - ajv "^6.10.2" + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" ajv-keywords "^3.4.1" -semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -5251,10 +5269,19 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serialize-javascript@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" - integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== +serialize-javascript@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" + integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== + dependencies: + randombytes "^2.1.0" + +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" serve-static@1.14.1: version "1.14.1" @@ -5266,7 +5293,7 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -5299,13 +5326,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -5313,20 +5333,35 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + shellwords@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= +side-channel@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" simple-swizzle@^0.2.2: version "0.2.2" @@ -5387,20 +5422,20 @@ source-list-map@^2.0.0: integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" source-map-support@~0.5.12: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -5444,12 +5479,11 @@ ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" -ssri@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" - integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g== +ssri@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808" + integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA== dependencies: - figgy-pudding "^3.5.1" minipass "^3.1.1" stable@^0.1.8: @@ -5458,9 +5492,9 @@ stable@^0.1.8: integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== stacktrace-parser@^0.1.7: - version "0.1.8" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.8.tgz#28b0272bd9aeb41636f0c8265c03ba270c865e1b" - integrity sha512-ig5rHJSdJrAsVqdb3oAI/8C6aQ7dEwJXoy/TIEIOTzdJHssmn12o6RsFoeQSLHoKjq0lX+kqhmnLDpyQTuWiJA== + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== dependencies: type-fest "^0.7.1" @@ -5505,32 +5539,15 @@ stream-http@^2.7.2: xtend "^4.0.0" stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -5540,32 +5557,35 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.matchall@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" + integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.0" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimend@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" -string_decoder@^1.0.0: +string.prototype.trimstart@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -5579,20 +5599,6 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -5607,28 +5613,18 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== style-loader@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.0.1.tgz#aec6d4c61d0ed8d0a442faed741d4dfc6573888a" - integrity sha512-CnpEkSR1C+REjudiTWCv4+ssP7SCiuaQZJTZDWBRwTJoS90mdqkB8uOGMHKgVeUzpaU7IfLWoyQbvvs5Joj3Xw== + version "1.2.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.2.1.tgz#c5cbbfbf1170d076cfdd86e0109c5bba114baa1a" + integrity sha512-ByHSTQvHLkWE9Ir5+lGbVOXhxX10fbprhLvdg96wedFZb4NDekDPxVKv5Fwmio+QcMlkkNfuK+5W1peQ5CUhZg== dependencies: - loader-utils "^1.2.3" - schema-utils "^2.0.1" + loader-utils "^2.0.0" + schema-utils "^2.6.6" stylehacks@^4.0.0: version "4.0.3" @@ -5639,13 +5635,6 @@ stylehacks@^4.0.0: postcss "^7.0.0" postcss-selector-parser "^3.0.0" -supports-color@6.1.0, supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5653,6 +5642,20 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + svgo@^1.0.0: version "1.3.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" @@ -5687,52 +5690,52 @@ tapable@^1.0.0, tapable@^1.1.3: resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== -tar@^4: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== +tar@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" + integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.0" + mkdirp "^1.0.3" + yallist "^4.0.0" -terser-webpack-plugin@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.2.tgz#e23c0d554587d1f473bd0cf68627720e733890a4" - integrity sha512-fdEb91kR2l+BVgES77N/NTXWZlpX6vX+pYPjnX5grcDYBF2CMnzJiXX4NNlna4l04lvCW39lZ+O/jSvUhHH/ew== +terser-webpack-plugin@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" + integrity sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^2.1.1" + serialize-javascript "^3.1.0" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser-webpack-plugin@^2.1.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.2.2.tgz#2a6e00237125564a455ad69b22e08ee59420473a" - integrity sha512-/CHMNswPMAwuD2kd++qys8UmBRmsshPSzHw4BlDwurPtK9YjeK93OV89YWkJulHk972cs07K/7Z92V6PNjWF8A== +terser-webpack-plugin@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-3.0.6.tgz#db0a108bbdd3680d72c9b491fbabad09ba207b99" + integrity sha512-z3HLOOPUHkCNGkeEHqqiMAIy1pjpHwS1o+i6Zn0Ws3EAvHJj46737efNNEvJ0Vx9BdDQM83d56qySDJOSORA0A== dependencies: - cacache "^13.0.1" - find-cache-dir "^3.1.0" - jest-worker "^24.9.0" - schema-utils "^2.6.1" - serialize-javascript "^2.1.1" + cacache "^15.0.4" + find-cache-dir "^3.3.1" + jest-worker "^26.0.0" + p-limit "^3.0.1" + schema-utils "^2.6.6" + serialize-javascript "^4.0.0" source-map "^0.6.1" - terser "^4.4.2" + terser "^4.8.0" webpack-sources "^1.4.3" -terser@^4.1.2, terser@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.2.tgz#448fffad0245f4c8a277ce89788b458bfd7706e8" - integrity sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ== +terser@^4.1.2, terser@^4.8.0: + version "4.8.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.0.tgz#63056343d7c70bb29f3af665865a46fe03a0df17" + integrity sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -5751,11 +5754,6 @@ through2@^2.0.0: readable-stream "~2.3.6" xtend "~4.0.1" -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - timers-browserify@^2.0.4: version "2.0.11" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" @@ -5768,13 +5766,6 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -5828,21 +5819,21 @@ tryer@^1.0.1: integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: - prelude-ls "~1.1.2" + prelude-ls "^1.2.1" type-fest@^0.7.1: version "0.7.1" @@ -5880,15 +5871,15 @@ unicode-match-property-ecmascript@^1.0.4: unicode-canonical-property-names-ecmascript "^1.0.4" unicode-property-aliases-ecmascript "^1.0.4" -unicode-match-property-value-ecmascript@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" - integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== unicode-property-aliases-ecmascript@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" - integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== union-value@^1.0.0: version "1.0.1" @@ -5964,14 +5955,14 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= -url-loader@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-3.0.0.tgz#9f1f11b371acf6e51ed15a50db635e02eec18368" - integrity sha512-a84JJbIA5xTFTWyjjcPdnsu+41o/SNE8SpXMdUvXs6Q+LuhCD9E2+0VCiuDWqgo3GGXVlFHzArDmBpj9PgWn4A== +url-loader@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-4.1.0.tgz#c7d6b0d6b0fccd51ab3ffc58a78d32b8d89a7be2" + integrity sha512-IzgAAIC8wRrg6NYkFIJY09vtktQcsvU8V6HhtQj9PTefbYImzLB1hufqo4m+RyM5N3mLx5BqJKccgxJS+W3kqw== dependencies: - loader-utils "^1.2.3" - mime "^2.4.4" - schema-utils "^2.5.0" + loader-utils "^2.0.0" + mime-types "^2.1.26" + schema-utils "^2.6.5" url@^0.11.0: version "0.11.0" @@ -5986,18 +5977,20 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util.promisify@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" util@0.10.3: version "0.10.3" @@ -6013,20 +6006,32 @@ util@^0.11.0: dependencies: inherits "2.0.3" +util@^0.12.0: + version "0.12.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.3.tgz#971bb0292d2cc0c892dab7c6a5d37c2bec707888" + integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= -v8-compile-cache@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe" - integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w== +uuid@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" + integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== +v8-compile-cache@^2.0.3, v8-compile-cache@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" + integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== vary@~1.1.2: version "1.1.2" @@ -6034,39 +6039,48 @@ vary@~1.1.2: integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= vendors@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.3.tgz#a6467781abd366217c050f8202e7e50cc9eef8c0" - integrity sha512-fOi47nsJP5Wqefa43kyWSg80qF+Q3XA6MUkgi7Hp1HQaKDQW4cQrK2D0P7mmbFtsV1N89am55Yru/nyEwRubcw== + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== -watchpack@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.6.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.2.tgz#c02e4d4d49913c3e7e122c3325365af9d331e9aa" + integrity sha512-ymVbbQP40MFTp+cNMvpyBpBtygHnPzPkHqoIwRRj/0B8KhqQwV8LaKjtbaxF2lK4vl8zN9wCxS46IFCU5K4W0g== dependencies: - chokidar "^2.0.2" graceful-fs "^4.1.2" neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.0" + watchpack-chokidar2 "^2.0.0" webpack-build-notifier@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/webpack-build-notifier/-/webpack-build-notifier-2.0.0.tgz#4e2012f939dd3124d397fb881dbf3dc973596065" - integrity sha512-0UquMIN02i05ZlEEKe4QRvqlDHSYx79YLcXu3XP7PjMFCIZxNCotfQO1mv+6uGske26f0lhai8X9umTI9RcRpg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/webpack-build-notifier/-/webpack-build-notifier-2.1.0.tgz#fb20adbfa0b1bbbc44c616519605b2b53afff1a2" + integrity sha512-szOijap/Ztk99ghCYFtxNOPOwVoJcczaL7UNAt5+WBgYtyEUPd/ZzC45zvOZick9Y83g81eINrB/208XvAHc+w== dependencies: - node-notifier "6.0.0" - strip-ansi "^5.2.0" + node-notifier "7.0.1" + strip-ansi "^6.0.0" webpack-bundle-analyzer@^3.5.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz#39b3a8f829ca044682bc6f9e011c95deb554aefd" - integrity sha512-orUfvVYEfBMDXgEKAKVvab5iQ2wXneIEorGNsyuOyVYpjYrI7CUOhhXNDd3huMwQ3vNNWWlGP+hzflMFYNzi2g== + version "3.8.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.8.0.tgz#ce6b3f908daf069fd1f7266f692cbb3bded9ba16" + integrity sha512-PODQhAYVEourCcOuU+NiYI7WdR8QyELZGgPvB1y2tjbUpbmcQOt5Q7jEK+ttd5se0KSBKD9SXHCEozS++Wllmw== dependencies: - acorn "^6.0.7" - acorn-walk "^6.1.1" + acorn "^7.1.1" + acorn-walk "^7.1.1" bfj "^6.1.1" chalk "^2.4.1" commander "^2.18.0" @@ -6080,30 +6094,34 @@ webpack-bundle-analyzer@^3.5.1: ws "^6.0.0" webpack-cli@^3.3.9: - version "3.3.10" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.10.tgz#17b279267e9b4fb549023fae170da8e6e766da13" - integrity sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg== + version "3.3.12" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" + integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== dependencies: - chalk "2.4.2" - cross-spawn "6.0.5" - enhanced-resolve "4.1.0" - findup-sync "3.0.0" - global-modules "2.0.0" - import-local "2.0.0" - interpret "1.2.0" - loader-utils "1.2.3" - supports-color "6.1.0" - v8-compile-cache "2.0.3" - yargs "13.2.4" + chalk "^2.4.2" + cross-spawn "^6.0.5" + enhanced-resolve "^4.1.1" + findup-sync "^3.0.0" + global-modules "^2.0.0" + import-local "^2.0.0" + interpret "^1.4.0" + loader-utils "^1.4.0" + supports-color "^6.1.0" + v8-compile-cache "^2.1.1" + yargs "^13.3.2" -webpack-external-import@^0.3.0-beta.0: - version "0.3.0-beta.0" - resolved "https://registry.yarnpkg.com/webpack-external-import/-/webpack-external-import-0.3.0-beta.0.tgz#bceccdafb9572931ee93ffa84e39eea9f6d15dca" - integrity sha512-58uSxZEi1Y2HGktQficlwSVHcvml1p6fpXrFEMEgi8nR/eLWlHcoYyILGRzZFSq8jfFqhAbHlm4fcnAIVA5Epg== +webpack-external-import@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/webpack-external-import/-/webpack-external-import-2.2.4.tgz#954c0a43f27af5e01db0c6454eee8232cebce8a5" + integrity sha512-yJUHeu/UaZ8o0gCQyor6nsjEVdgc3ao8w7E6j28Dh1BanMxnqm0PumdElh2C5z/DMTcw1knQbpEArRo6/knNog== dependencies: + assert "^2.0.0" dimport "^1.0.0" fs-extra "^8.1.0" - loadjs "^3.6.1" + loadjs "^4.2.0" + mem "^6.0.1" + pkg-up "^3.1.0" + tapable "^1.1.3" webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" @@ -6114,15 +6132,15 @@ webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack- source-map "~0.6.1" webpack@^4.40.2: - version "4.41.2" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.2.tgz#c34ec76daa3a8468c9b61a50336d8e3303dce74e" - integrity sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A== + version "4.43.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" + integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.2.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" @@ -6133,13 +6151,13 @@ webpack@^4.40.2: loader-utils "^1.2.3" memory-fs "^0.4.1" micromatch "^3.1.10" - mkdirp "^0.5.1" + mkdirp "^0.5.3" neo-async "^2.6.1" node-libs-browser "^2.2.1" schema-utils "^1.0.0" tapable "^1.1.3" - terser-webpack-plugin "^1.4.1" - watchpack "^1.6.0" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.1" webpack-sources "^1.4.1" which-module@^2.0.0: @@ -6147,6 +6165,18 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-typed-array@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" + integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== + dependencies: + available-typed-arrays "^1.0.2" + es-abstract "^1.17.5" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" + which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -6154,14 +6184,14 @@ which@^1.2.14, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: - string-width "^1.0.2 || 2" + isexe "^2.0.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -6202,11 +6232,9 @@ ws@^6.0.0: async-limiter "~1.0.0" ws@^7.1.2: - version "7.2.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.0.tgz#422eda8c02a4b5dba7744ba66eebbd84bcef0ec7" - integrity sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg== - dependencies: - async-limiter "^1.0.0" + version "7.3.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" + integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" @@ -6218,7 +6246,7 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== @@ -6228,27 +6256,26 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^13.1.0: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs@13.2.4: - version "13.2.4" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" - integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" find-up "^3.0.0" get-caller-file "^2.0.1" - os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.1.0" + yargs-parser "^13.1.2" diff --git a/tools/WebhookProcessor/github_webhook_processor.php b/tools/WebhookProcessor/github_webhook_processor.php index 0739c7182c..b2bcaeb884 100644 --- a/tools/WebhookProcessor/github_webhook_processor.php +++ b/tools/WebhookProcessor/github_webhook_processor.php @@ -392,12 +392,14 @@ function handle_pr($payload) { set_labels($payload, $labels, $remove); if($no_changelog) check_dismiss_changelog_review($payload); + /* if(get_pr_code_friendliness($payload) <= 0){ $balances = pr_balances(); $author = $payload['pull_request']['user']['login']; if(isset($balances[$author]) && $balances[$author] < 0 && !is_maintainer($payload, $author)) create_comment($payload, 'You currently have a negative Fix/Feature pull request delta of ' . $balances[$author] . '. Maintainers may close this PR at will. Fixing issues or improving the codebase will improve this score.'); } + */ break; case 'edited': check_dismiss_changelog_review($payload); diff --git a/tools/deploy.sh b/tools/deploy.sh index a4795ea06a..8a4c4d4c79 100755 --- a/tools/deploy.sh +++ b/tools/deploy.sh @@ -29,6 +29,7 @@ cp -r sound/chatter/* $1/sound/chatter/ cp -r sound/voice/complionator/* $1/sound/voice/complionator/ cp -r sound/instruments/* $1/sound/instruments/ cp -r strings/* $1/strings/ +cp *byond-extools.* $1/ || true #remove .dm files from _maps diff --git a/tools/hooks/install.sh b/tools/hooks/install.sh index 6dfc15a2fa..899b85b941 100644 --- a/tools/hooks/install.sh +++ b/tools/hooks/install.sh @@ -12,7 +12,7 @@ for f in *.merge; do done echo "Installing tgui hooks" -../../tgui-next/bin/tgui --install-git-hooks +../../tgui/bin/tgui --install-git-hooks echo "Installing Python dependencies" ./python.sh -m pip install -r ../mapmerge2/requirements.txt diff --git a/tools/travis/build_tgui.sh b/tools/travis/build_tgui.sh index b3973468e1..0684f451bb 100755 --- a/tools/travis/build_tgui.sh +++ b/tools/travis/build_tgui.sh @@ -16,9 +16,4 @@ fi echo "Building 'tgui'" cd "${base_dir}/tgui" -npm ci -node node_modules/gulp/bin/gulp.js --min - -echo "Building 'tgui-next'" -cd "${base_dir}/tgui-next" bin/tgui --ci