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..817626d228 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.
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/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/LavaRuins/lavaland_surface_alien_nest.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
index 6feb378515..eab08815f3 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_alien_nest.dmm
@@ -227,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{
@@ -241,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,
@@ -251,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,
@@ -262,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,
@@ -272,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,
@@ -286,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,
@@ -303,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,
@@ -336,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{
@@ -352,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{
@@ -383,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{
@@ -416,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{
@@ -430,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{
@@ -441,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{
@@ -451,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{
@@ -461,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{
@@ -475,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,
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 74bdc9a7b8..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,
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/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/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 791aac277d..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,
@@ -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 5da534a08e..3e5c80253d 100644
--- a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm
+++ b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm
@@ -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" = (
diff --git a/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm b/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm
index 56967b0c37..1bc497d4f9 100644
--- a/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm
+++ b/_maps/RandomRuins/SpaceRuinsStation/roid6.dmm
@@ -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/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/away_mission/Academy.dmm b/_maps/RandomZLevels/away_mission/Academy.dmm
index 832e4f23fa..37b0098fd2 100644
--- a/_maps/RandomZLevels/away_mission/Academy.dmm
+++ b/_maps/RandomZLevels/away_mission/Academy.dmm
@@ -3594,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{
@@ -3634,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,
@@ -3737,7 +3691,7 @@
/area/awaymission/academy/academyaft)
"kI" = (
/obj/structure/cable,
-/obj/machinery/gateway/centeraway,
+/obj/machinery/gateway/away,
/turf/open/floor/plating,
/area/awaymission/academy/academygate)
"kJ" = (
@@ -13173,10 +13127,10 @@ jZ
kb
ke
kj
-km
-kp
-ks
-Ao
+kk
+kf
+kf
+kf
kf
ky
kf
@@ -13305,8 +13259,8 @@ jW
Ao
kn
kI
-kt
-Ao
+kf
+kf
kf
ky
mF
@@ -13432,11 +13386,11 @@ jV
jY
kc
jW
-Ao
-ko
-kr
-ku
-Ao
+kf
+kf
+kf
+kf
+kf
kf
ky
kf
diff --git a/_maps/RandomZLevels/away_mission/SnowCabin.dmm b/_maps/RandomZLevels/away_mission/SnowCabin.dmm
index cd6cefc8ad..249cb68b5d 100644
--- a/_maps/RandomZLevels/away_mission/SnowCabin.dmm
+++ b/_maps/RandomZLevels/away_mission/SnowCabin.dmm
@@ -633,24 +633,6 @@
/obj/machinery/processor,
/turf/open/floor/plasteel/freezer,
/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
@@ -733,20 +715,8 @@
"cn" = (
/turf/open/lava,
/area/awaymission/cabin/caves/mountain)
-"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
- },
+/obj/machinery/gateway/away,
/turf/open/floor/wood,
/area/awaymission/cabin)
"cr" = (
@@ -787,23 +757,6 @@
},
/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,
-/obj/effect/mapping_helpers/network_builder/power_cable/yellow/auto,
-/turf/open/floor/wood,
-/area/awaymission/cabin)
-"cy" = (
-/obj/machinery/gateway{
- dir = 6
- },
-/turf/open/floor/wood,
-/area/awaymission/cabin)
"cz" = (
/obj/machinery/light{
dir = 1
@@ -35769,9 +35722,9 @@ an
bk
bJ
an
-cb
-co
-cw
+aq
+aq
+aq
aq
cH
cQ
@@ -36026,9 +35979,9 @@ an
nU
an
an
-cc
+aq
cp
-cx
+eg
eg
eg
cQ
@@ -36283,9 +36236,9 @@ an
jf
ay
an
-cd
-cq
-cy
+aq
+aq
+aq
aq
cH
hH
diff --git a/_maps/RandomZLevels/away_mission/TheBeach.dmm b/_maps/RandomZLevels/away_mission/TheBeach.dmm
index 68eb5c164f..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)
@@ -6896,9 +6820,9 @@ ak
ak
ak
ak
-aL
-aP
-aU
+bf
+bp
+bx
ak
ak
ba
@@ -7003,9 +6927,9 @@ ak
ak
ak
ak
-aM
+bg
aQ
-aV
+by
ba
ba
ba
@@ -7110,9 +7034,9 @@ ak
ak
ak
ak
-aN
-aR
-aW
+bh
+br
+bz
ak
ak
ak
diff --git a/_maps/RandomZLevels/away_mission/caves.dmm b/_maps/RandomZLevels/away_mission/caves.dmm
index 159559d0af..33aca48f29 100644
--- a/_maps/RandomZLevels/away_mission/caves.dmm
+++ b/_maps/RandomZLevels/away_mission/caves.dmm
@@ -71,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{
@@ -394,50 +389,8 @@
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"
},
@@ -448,24 +401,7 @@
initial_gas_mix = "n2=23;o2=14"
},
/area/awaymission/caves/BMP_asteroid/level_four)
-"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{
- 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"
},
@@ -1390,12 +1326,6 @@
/mob/living/simple_animal/hostile/mining_drone,
/turf/open/floor/plating,
/area/awaymission/caves/listeningpost)
-"el" = (
-/obj/machinery/gateway{
- dir = 9
- },
-/turf/open/floor/plasteel,
-/area/awaymission/caves/listeningpost)
"em" = (
/obj/structure/closet/secure_closet/personal,
/turf/open/floor/wood{
@@ -1492,12 +1422,6 @@
/obj/item/stack/sheet/mineral/plasma,
/turf/open/floor/plasteel,
/area/awaymission/caves/listeningpost)
-"eB" = (
-/obj/machinery/gateway{
- dir = 1
- },
-/turf/open/floor/plasteel,
-/area/awaymission/caves/listeningpost)
"eC" = (
/obj/structure/table,
/obj/item/gps/mining,
@@ -1513,12 +1437,6 @@
/obj/item/extinguisher/mini,
/turf/open/floor/plasteel,
/area/awaymission/caves/listeningpost)
-"eE" = (
-/obj/machinery/gateway{
- dir = 5
- },
-/turf/open/floor/plasteel,
-/area/awaymission/caves/listeningpost)
"eF" = (
/turf/closed/wall,
/area/awaymission/caves/listeningpost)
@@ -1704,15 +1622,6 @@
initial_gas_mix = "n2=23;o2=14"
},
/area/awaymission/caves/BMP_asteroid/level_two)
-"fk" = (
-/obj/machinery/gateway{
- dir = 8
- },
-/obj/machinery/light{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/awaymission/caves/listeningpost)
"fl" = (
/obj/effect/decal/remains/human,
/turf/open/floor/plating/asteroid/basalt{
@@ -1792,12 +1701,10 @@
},
/area/awaymission/caves/BMP_asteroid/level_two)
"fw" = (
-/obj/machinery/gateway/centeraway{
- calibrated = 0
- },
/obj/structure/cable{
icon_state = "0-2"
},
+/obj/machinery/gateway/away,
/turf/open/floor/plasteel,
/area/awaymission/caves/listeningpost)
"fx" = (
@@ -2038,9 +1945,6 @@
/turf/open/floor/plasteel,
/area/awaymission/caves/BMP_asteroid)
"gk" = (
-/obj/machinery/gateway{
- dir = 4
- },
/obj/machinery/light{
dir = 4
},
@@ -2281,12 +2185,6 @@
/obj/effect/baseturf_helper/asteroid/basalt,
/turf/closed/wall,
/area/awaymission/caves/northblock)
-"tk" = (
-/obj/machinery/gateway{
- dir = 6
- },
-/turf/open/floor/plasteel,
-/area/awaymission/caves/listeningpost)
"CY" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -2301,7 +2199,6 @@
/turf/open/floor/plasteel,
/area/awaymission/caves/listeningpost)
"Hp" = (
-/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-2"
},
@@ -2310,12 +2207,6 @@
},
/turf/open/floor/plasteel,
/area/awaymission/caves/listeningpost)
-"If" = (
-/obj/machinery/gateway{
- dir = 10
- },
-/turf/open/floor/plasteel,
-/area/awaymission/caves/listeningpost)
(1,1,1) = {"
aa
@@ -10730,9 +10621,9 @@ bL
bM
bM
eF
-el
-fk
-If
+eJ
+eq
+eJ
eJ
eF
ey
@@ -10987,7 +10878,7 @@ bL
bL
bM
eG
-eB
+eJ
fw
Hp
CY
@@ -11244,9 +11135,9 @@ bL
bL
bM
eG
-eE
+eJ
gk
-tk
+eJ
eJ
eG
eA
@@ -53527,11 +53418,11 @@ ai
ai
ai
ai
-ao
+br
ai
ai
-ao
-ao
+br
+br
ai
ai
ai
@@ -53780,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
@@ -54035,7 +53926,7 @@ ad
ad
ai
ai
-ao
+br
ai
ai
ai
@@ -54048,8 +53939,8 @@ ai
ai
ai
ai
-ao
-ao
+br
+br
ai
ai
ad
@@ -54289,9 +54180,9 @@ ad
ad
ad
ai
-ao
-ao
-ao
+br
+br
+br
ai
ax
ad
@@ -54306,7 +54197,7 @@ ai
ad
ad
ai
-ao
+br
ai
ai
ad
@@ -54545,7 +54436,7 @@ ad
ad
ai
ai
-ao
+br
am
ai
ad
@@ -54802,7 +54693,7 @@ ai
ai
ai
ai
-ao
+br
ai
ai
ad
@@ -54817,9 +54708,9 @@ ad
ad
ad
ax
-ao
+br
ai
-ao
+br
ai
ai
ai
@@ -55016,10 +54907,10 @@ ad
ad
al
am
-ao
-ao
+br
+br
ap
-ao
+br
am
ai
al
@@ -55055,7 +54946,7 @@ aV
aV
ax
aA
-ao
+br
ax
ax
ai
@@ -55073,7 +54964,7 @@ ad
ad
ad
ad
-ao
+br
ai
ai
ai
@@ -55273,11 +55164,11 @@ ad
ad
al
am
-ao
+br
ar
as
ar
-ao
+br
am
al
ad
@@ -55290,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
@@ -55330,7 +55221,7 @@ ad
ad
ad
ax
-ao
+br
ai
ai
ai
@@ -55545,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
@@ -55586,8 +55477,8 @@ ad
ad
ad
ad
-ao
-ao
+br
+br
ai
ai
ai
@@ -55787,11 +55678,11 @@ ad
ad
al
am
-ao
+br
ar
as
ar
-ao
+br
am
al
ad
@@ -55802,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
@@ -55843,7 +55734,7 @@ ad
ad
ad
ad
-ao
+br
ai
am
at
@@ -56044,10 +55935,10 @@ ad
ad
al
am
-ao
-ao
+br
+br
ap
-ao
+br
am
ai
al
@@ -56059,8 +55950,8 @@ ad
ad
ad
ad
-ao
-ao
+br
+br
ad
ad
ad
@@ -56083,8 +55974,8 @@ aV
aV
ax
aR
-ao
-ao
+br
+br
ax
ai
ai
@@ -56100,7 +55991,7 @@ ad
ad
ad
ax
-ao
+br
ai
ai
ai
@@ -56302,8 +56193,8 @@ ad
ai
al
am
-ao
-ao
+br
+br
am
ai
al
@@ -56316,9 +56207,9 @@ ad
ad
ad
ad
-ao
-ao
-ao
+br
+br
+br
ad
ad
ad
@@ -56339,9 +56230,9 @@ ai
ad
ad
ax
-ao
-ao
-ao
+br
+br
+br
ax
ai
ai
@@ -56357,8 +56248,8 @@ ad
ad
ad
ax
-ao
-ao
+br
+br
ai
ai
ai
@@ -56560,7 +56451,7 @@ ad
ai
al
al
-ao
+br
al
al
ai
@@ -56573,9 +56464,9 @@ ax
ax
ax
ax
-ao
-ao
-ao
+br
+br
+br
ad
ad
ai
@@ -56596,9 +56487,9 @@ ax
ad
ai
ax
-ao
-ao
-ao
+br
+br
+br
ax
ai
ai
@@ -56615,12 +56506,12 @@ ad
ad
ad
ax
-ao
+br
am
ai
ai
ad
-ao
+br
ai
ai
ai
@@ -56817,7 +56708,7 @@ ad
ai
aq
ai
-ao
+br
ai
ai
ad
@@ -56827,12 +56718,12 @@ ad
ad
ax
ay
-ao
+br
aD
ax
-ao
-ao
-ao
+br
+br
+br
ad
ad
ai
@@ -56846,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
@@ -56873,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
@@ -57084,12 +56975,12 @@ ad
ad
ax
az
-ao
-ao
+br
+br
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -57097,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
@@ -57132,14 +57023,14 @@ ad
ad
ax
ax
-ao
+br
ax
ad
ad
ai
ai
ai
-ao
+br
ai
ad
ad
@@ -57340,13 +57231,13 @@ ad
ad
ad
ax
-ao
-ao
+br
+br
av
aF
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -57354,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
@@ -57380,10 +57271,10 @@ ad
ai
ai
ax
-ao
-ao
-ao
-ao
+br
+br
+br
+br
aR
aR
ad
@@ -57397,8 +57288,8 @@ ad
ad
ai
ai
-ao
-ao
+br
+br
ad
ad
ad
@@ -57588,7 +57479,7 @@ ad
an
ai
ai
-ao
+br
ai
ai
ai
@@ -57597,13 +57488,13 @@ ad
ad
ad
ax
-ao
+br
av
-ao
+br
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -57611,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
@@ -57636,13 +57527,13 @@ ad
ad
ai
aR
-ao
-ao
+br
+br
bf
-ao
-ao
-ao
-ao
+br
+br
+br
+br
aR
ad
ad
@@ -57655,7 +57546,7 @@ ad
ad
ad
ax
-ao
+br
ad
ad
ad
@@ -57845,8 +57736,8 @@ ad
ai
ai
ai
-ao
-ao
+br
+br
ai
ai
ai
@@ -57858,9 +57749,9 @@ aA
ax
ax
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -57868,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
@@ -57892,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
@@ -57911,7 +57802,7 @@ ad
ad
ad
aR
-ao
+br
ai
ad
ad
@@ -58102,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
@@ -58168,7 +58059,7 @@ ad
ad
ad
ax
-ao
+br
ai
ai
ad
@@ -58361,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
@@ -58382,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
@@ -58424,8 +58315,8 @@ ad
ad
ad
ax
-ao
-ao
+br
+br
am
ai
ai
@@ -58619,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
@@ -58681,8 +58572,8 @@ ad
ad
ad
ax
-ao
-ao
+br
+br
ai
ai
ai
@@ -58877,7 +58768,7 @@ ai
ai
ai
ai
-ao
+br
ai
ai
ai
@@ -58886,9 +58777,9 @@ ax
ax
ax
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -58896,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
@@ -58921,14 +58812,14 @@ ax
ax
aR
aR
-ao
+br
bf
ap
bf
-ao
-ao
-ao
-ao
+br
+br
+br
+br
ax
ai
ai
@@ -59139,13 +59030,13 @@ ai
ai
ad
ax
-ao
-ao
-ao
+br
+br
+br
ax
-ao
-ao
-ao
+br
+br
+br
ad
ai
ai
@@ -59154,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
@@ -59179,12 +59070,12 @@ ai
ad
ad
aR
-ao
+br
bf
-ao
-ao
-ao
-ao
+br
+br
+br
+br
aR
ai
ai
@@ -59194,7 +59085,7 @@ ad
ad
ad
ax
-ao
+br
am
ai
bs
@@ -59396,13 +59287,13 @@ ad
ad
ad
ax
-ao
-ao
-ao
+br
+br
+br
aF
-ao
-ao
-ao
+br
+br
+br
ad
ai
ai
@@ -59410,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
@@ -59436,11 +59327,11 @@ ai
ad
ad
aR
-ao
-ao
-ao
-ao
-ao
+br
+br
+br
+br
+br
aR
ai
ai
@@ -59451,7 +59342,7 @@ ad
ad
ad
aR
-ao
+br
ai
ai
ai
@@ -59653,13 +59544,13 @@ ad
ad
ad
ax
-ao
-ao
-ao
+br
+br
+br
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -59667,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
@@ -59694,9 +59585,9 @@ ad
ad
ai
ax
-ao
-ao
-ao
+br
+br
+br
ax
ai
ai
@@ -59708,7 +59599,7 @@ ad
ad
ad
ax
-ao
+br
ai
ai
ai
@@ -59911,12 +59802,12 @@ ad
ad
ax
aC
-ao
+br
aE
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -59926,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
@@ -59964,8 +59855,8 @@ ad
ad
ad
ad
-ao
-ao
+br
+br
ai
ai
ai
@@ -60171,9 +60062,9 @@ ax
ax
ax
ax
-ao
-ao
-ao
+br
+br
+br
ai
ai
ai
@@ -60187,7 +60078,7 @@ ai
ai
ai
ax
-ao
+br
aR
aR
ax
@@ -60195,7 +60086,7 @@ ad
ai
ax
aw
-ao
+br
aR
ax
ai
@@ -60221,8 +60112,8 @@ ad
ad
ax
ax
-ao
-ao
+br
+br
am
ai
ad
@@ -60428,9 +60319,9 @@ ad
ad
ad
ad
-ao
-ao
-ao
+br
+br
+br
ad
ai
ai
@@ -60451,9 +60342,9 @@ ai
ad
ai
ax
-ao
+br
aw
-ao
+br
ax
ai
ai
@@ -60465,7 +60356,7 @@ ad
ad
ad
al
-ao
+br
al
ad
ad
@@ -60477,8 +60368,8 @@ ad
ax
al
ai
-ao
-ao
+br
+br
ai
ai
ai
@@ -60686,8 +60577,8 @@ ad
ad
ad
ad
-ao
-ao
+br
+br
ad
ai
ai
@@ -60696,7 +60587,7 @@ ai
ai
ax
aS
-ao
+br
aS
ax
ax
@@ -60708,9 +60599,9 @@ ax
ad
ad
ax
-ao
+br
av
-ao
+br
ax
ai
ai
@@ -60721,7 +60612,7 @@ ad
ad
ad
ai
-ao
+br
ai
ax
ad
@@ -60731,8 +60622,8 @@ ad
ad
ad
ad
-ao
-ao
+br
+br
ai
ai
ai
@@ -60943,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
@@ -60978,7 +60869,7 @@ ad
ad
ad
ai
-ao
+br
ai
ad
ad
@@ -60988,8 +60879,8 @@ ad
ad
ad
ad
-ao
-ao
+br
+br
ai
ai
ai
@@ -61201,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
@@ -61245,7 +61136,7 @@ ai
ad
ax
ai
-ao
+br
ai
ai
ad
@@ -61463,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
@@ -61494,13 +61385,13 @@ ad
ai
ai
ai
-ao
+br
ai
ai
ai
ai
-ao
-ao
+br
+br
ai
ai
ai
@@ -61751,10 +61642,10 @@ ad
ad
ad
ai
-ao
-ao
-ao
-ao
+br
+br
+br
+br
ai
ai
ai
@@ -64051,7 +63942,7 @@ ad
ai
ai
aY
-ao
+br
aZ
ai
ad
@@ -64307,9 +64198,9 @@ ad
ad
ad
an
-ao
+br
ba
-ao
+br
an
ad
ad
@@ -64565,7 +64456,7 @@ ad
ad
ai
aZ
-ao
+br
aY
ad
ad
diff --git a/_maps/RandomZLevels/away_mission/challenge.dmm b/_maps/RandomZLevels/away_mission/challenge.dmm
index 91b209ae9b..7342f7ffe6 100644
--- a/_maps/RandomZLevels/away_mission/challenge.dmm
+++ b/_maps/RandomZLevels/away_mission/challenge.dmm
@@ -866,21 +866,10 @@
},
/area/awaymission/challenge/start)
"cS" = (
-/obj/machinery/gateway{
- dir = 9
- },
-/turf/open/floor/bluespace,
-/area/awaymission/challenge/start)
-"cT" = (
-/obj/machinery/gateway{
- dir = 1
- },
+/obj/machinery/gateway/away,
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
"cV" = (
-/obj/machinery/gateway{
- dir = 5
- },
/obj/structure/cable{
icon_state = "1-2"
},
@@ -894,24 +883,12 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/challenge/end)
"cX" = (
-/obj/machinery/gateway{
- dir = 8
- },
/obj/machinery/light{
dir = 8
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
-"cY" = (
-/obj/machinery/gateway/centeraway{
- calibrated = 0
- },
-/turf/open/floor/bluespace,
-/area/awaymission/challenge/start)
"cZ" = (
-/obj/machinery/gateway{
- dir = 4
- },
/obj/structure/cable{
icon_state = "1-2"
},
@@ -920,18 +897,11 @@
},
/turf/open/floor/bluespace,
/area/awaymission/challenge/start)
-"da" = (
-/obj/machinery/gateway{
- dir = 10
- },
-/turf/open/floor/bluespace,
-/area/awaymission/challenge/start)
"db" = (
/obj/structure/window/reinforced,
/turf/open/floor/circuit,
/area/awaymission/challenge/end)
"dc" = (
-/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-4"
},
@@ -996,9 +966,6 @@
/turf/open/floor/plasteel/dark,
/area/awaymission/challenge/end)
"dn" = (
-/obj/machinery/gateway{
- dir = 6
- },
/obj/structure/cable{
icon_state = "1-8"
},
@@ -28109,9 +28076,9 @@ aa
ab
ab
ab
-cS
+dq
cX
-da
+dq
ab
ab
at
@@ -28366,8 +28333,8 @@ aa
ab
aB
ab
-cT
-cY
+dq
+cS
dc
dq
dq
diff --git a/_maps/RandomZLevels/away_mission/moonoutpost19.dmm b/_maps/RandomZLevels/away_mission/moonoutpost19.dmm
index 83d1227c5e..ff2db79c83 100644
--- a/_maps/RandomZLevels/away_mission/moonoutpost19.dmm
+++ b/_maps/RandomZLevels/away_mission/moonoutpost19.dmm
@@ -191,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{
@@ -291,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
},
@@ -377,9 +285,6 @@
},
/area/awaymission/moonoutpost19/syndicate)
"aW" = (
-/obj/machinery/gateway{
- dir = 10
- },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -395,7 +300,6 @@
},
/area/awaymission/moonoutpost19/syndicate)
"aX" = (
-/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-2"
},
@@ -414,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
@@ -41927,8 +41828,8 @@ ac
ac
at
az
-aG
-aO
+aW
+aW
aW
aV
br
@@ -42184,7 +42085,7 @@ ac
ac
at
aA
-aH
+aW
aP
aX
bg
@@ -42441,8 +42342,8 @@ ac
ac
at
aB
-aI
-aQ
+aW
+aW
aY
bh
bt
diff --git a/_maps/RandomZLevels/away_mission/research.dmm b/_maps/RandomZLevels/away_mission/research.dmm
index d2b6099eb1..4710d9829b 100644
--- a/_maps/RandomZLevels/away_mission/research.dmm
+++ b/_maps/RandomZLevels/away_mission/research.dmm
@@ -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
},
@@ -5395,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" = (
diff --git a/_maps/RandomZLevels/away_mission/snowdin.dmm b/_maps/RandomZLevels/away_mission/snowdin.dmm
index c6b675acf6..00530695e9 100644
--- a/_maps/RandomZLevels/away_mission/snowdin.dmm
+++ b/_maps/RandomZLevels/away_mission/snowdin.dmm
@@ -2514,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,
@@ -2894,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)
@@ -3263,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"
@@ -3283,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,
@@ -26601,8 +26560,8 @@ bE
az
en
fh
-fG
-gw
+gy
+hl
hl
hR
iA
@@ -26858,7 +26817,7 @@ bE
dK
eo
fh
-fH
+gy
gx
hm
hS
@@ -27115,7 +27074,7 @@ dk
dK
ep
fh
-fI
+gy
gy
hn
hT
diff --git a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
index 10992c70bf..78a656128c 100644
--- a/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
+++ b/_maps/RandomZLevels/away_mission/undergroundoutpost45.dmm
@@ -3324,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{
@@ -3634,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
},
@@ -3958,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"
},
@@ -3996,9 +3885,6 @@
},
/area/awaymission/undergroundoutpost45/gateway)
"ia" = (
-/obj/machinery/gateway{
- dir = 6
- },
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -33198,9 +33084,9 @@ ad
ad
gv
gJ
-gR
-ht
-hY
+ia
+ia
+ia
it
iO
jh
@@ -33455,7 +33341,7 @@ ad
ad
gv
gJ
-gS
+ia
hu
hZ
iu
@@ -33712,8 +33598,8 @@ ad
ad
gw
gJ
-gT
-hv
+ia
+ia
ia
iv
iQ
diff --git a/_maps/RandomZLevels/away_mission/wildwest.dmm b/_maps/RandomZLevels/away_mission/wildwest.dmm
index ef4eabdc65..77d11a4552 100644
--- a/_maps/RandomZLevels/away_mission/wildwest.dmm
+++ b/_maps/RandomZLevels/away_mission/wildwest.dmm
@@ -63,72 +63,11 @@
/obj/structure/destructible/cult/pylon,
/turf/open/floor/circuit/green/off,
/area/awaymission/wildwest/vault)
-"ar" = (
-/obj/machinery/gateway{
- dir = 9
- },
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
-"as" = (
-/obj/machinery/gateway{
- dir = 1
- },
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
-"at" = (
-/obj/machinery/gateway{
- dir = 5
- },
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
-"au" = (
-/obj/machinery/gateway{
- dir = 8
- },
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
-"av" = (
-/obj/machinery/gateway/centeraway{
- calibrated = 0
- },
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
"aw" = (
-/obj/machinery/gateway{
- dir = 4
- },
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
-"ax" = (
-/obj/machinery/gateway{
- dir = 10
- },
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
-"ay" = (
-/obj/machinery/gateway,
-/turf/open/floor/plating/ironsand{
- icon_state = "ironsand1"
- },
-/area/awaymission/wildwest/mines)
+ })
"az" = (
-/obj/machinery/gateway{
- dir = 6
- },
/turf/open/floor/plating/ironsand{
icon_state = "ironsand1"
},
@@ -32745,9 +32684,9 @@ aT
aN
aN
aT
-ar
-au
-ax
+aT
+aT
+aT
aT
aT
aT
@@ -33002,9 +32941,9 @@ aT
aN
aN
aT
-as
-av
-ay
+aT
+aT
+aT
aT
aT
aT
@@ -33259,7 +33198,7 @@ aT
aN
aN
aT
-at
+aT
aw
az
aT
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index ed4a150e09..264fdb1058 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" = (
@@ -4879,6 +4879,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" = (
@@ -5103,7 +5107,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
@@ -6467,6 +6471,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"
@@ -8069,6 +8079,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)
@@ -9381,6 +9398,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 +9448,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 +9506,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 +11895,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 +12372,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 +12728,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 +12742,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 +12756,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"aBZ" = (
-/obj/machinery/gateway,
/obj/structure/cable{
icon_state = "0-2"
},
@@ -13425,7 +13454,6 @@
pixel_y = 32
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/machinery/button/door{
@@ -13795,8 +13823,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 +14339,6 @@
pixel_y = 32
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/machinery/button/door{
@@ -21797,7 +21823,6 @@
pixel_y = 32
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/machinery/button/door{
@@ -24549,12 +24574,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 +28311,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 +28799,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 +28831,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 +29333,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 +29340,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
@@ -30970,7 +30941,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 +31264,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 +33007,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
@@ -53516,6 +53463,7 @@
"dfh" = (
/obj/machinery/power/apc{
areastring = "/area/science/circuit";
+ dir = 4;
name = "Circuitry Lab APC";
pixel_x = 30
},
@@ -53760,9 +53708,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
@@ -53815,7 +53760,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,
@@ -54444,7 +54389,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 +54411,7 @@
/obj/structure/chair/office/dark{
dir = 1
},
+/obj/effect/landmark/start/atmospheric_technician,
/turf/open/floor/plasteel,
/area/engine/atmos)
"fMp" = (
@@ -54601,19 +54547,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 +54703,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 +54788,6 @@
dir = 8
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/structure/mirror{
@@ -54949,7 +54881,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 +54939,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,
@@ -56091,6 +56023,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,
@@ -56653,7 +56589,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)
@@ -57154,6 +57089,7 @@
dir = 4;
pixel_y = 5
},
+/obj/item/clothing/head/hardhat/cakehat,
/turf/open/floor/wood,
/area/crew_quarters/bar)
"oby" = (
@@ -57277,7 +57213,6 @@
dir = 8
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/structure/mirror{
@@ -57369,7 +57304,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 +57861,6 @@
pixel_y = 32
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/turf/open/floor/mineral/titanium/blue,
@@ -57989,7 +57923,6 @@
pixel_y = 32
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/machinery/light/small{
@@ -58210,7 +58143,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 +58154,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 +58430,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 +58687,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 +58803,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{
@@ -59092,7 +59026,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
@@ -59505,7 +59439,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,
@@ -60604,7 +60538,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 +60686,6 @@
pixel_y = 32
},
/obj/structure/sink{
- dir = 1;
pixel_y = 25
},
/obj/machinery/button/door{
@@ -66838,11 +66771,11 @@ aaa
aaa
aaa
aaa
-ghq
+xLX
aaa
aaa
aaa
-ghq
+xLX
aaa
aaa
aaa
@@ -67089,9 +67022,9 @@ aaa
aaa
aaa
aaa
-ghq
+xLX
aaa
-ghq
+xLX
aaa
aaa
aaa
@@ -67103,9 +67036,9 @@ gXs
aaa
aaa
aaa
-ghq
+xLX
aaa
-ghq
+xLX
aaa
aaa
aaa
@@ -76654,7 +76587,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aaa
aaa
@@ -76911,7 +76844,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aaa
aaa
@@ -77168,7 +77101,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aaa
aaa
@@ -77425,7 +77358,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aaa
aaa
@@ -77682,7 +77615,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aaa
aaa
@@ -77939,7 +77872,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aaa
aaa
@@ -78196,7 +78129,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aoV
bZm
@@ -78453,13 +78386,13 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aoV
bVz
aaf
aaf
-sQX
+aoV
aaa
aaS
aaf
@@ -78710,7 +78643,7 @@ aaa
aaa
aaa
aaa
-aag
+aaa
aaa
aag
bVz
@@ -78967,7 +78900,7 @@ aaa
aaa
aaa
aaa
-aag
+gJi
aaa
aaf
bVz
@@ -79224,7 +79157,7 @@ aaa
aaa
aaa
aaa
-aag
+gJi
aaa
aaf
bVz
@@ -84053,8 +83986,8 @@ esK
awb
axt
ayG
-azJ
-aBd
+aBY
+aBf
aBX
aDi
aEQ
@@ -84274,7 +84207,7 @@ aaa
aaa
gXs
gXs
-dVU
+aaH
abc
abu
abu
@@ -84310,7 +84243,7 @@ arP
awb
axt
ayG
-azM
+aBf
aBg
aBZ
aDx
@@ -84567,7 +84500,7 @@ arP
vgJ
hSl
ayG
-azL
+aBX
aBf
aBY
aDw
@@ -85409,7 +85342,7 @@ bVI
bTA
xgk
bHE
-bHE
+kEm
bHE
bHE
bHE
@@ -92315,7 +92248,7 @@ btJ
buV
bws
bqH
-aJq
+asY
aJq
byW
bCv
@@ -94366,8 +94299,8 @@ bfF
bfF
bfF
bfF
-bqM
-brV
+asT
+asV
bof
bwv
bvj
@@ -94623,8 +94556,8 @@ bmF
bob
bnB
bfF
-bqR
-brX
+asU
+asX
bof
bwx
bvj
@@ -95131,7 +95064,7 @@ aYV
bfF
bhc
bip
-bgP
+alX
bjL
bkL
bmT
@@ -95397,7 +95330,7 @@ bpF
bqS
brY
bwz
-bwy
+asG
bvj
bza
bxb
@@ -95653,10 +95586,10 @@ bpt
bfF
bqV
bEe
+bhh
bBL
-bwA
bvj
-bAl
+asM
bAl
bvh
bzS
@@ -96171,7 +96104,7 @@ bvh
ajv
bxN
bze
-bAp
+asL
bvh
bCG
bBd
@@ -98219,7 +98152,7 @@ bjX
blp
bmO
bhi
-bpy
+apI
bwz
brg
btZ
@@ -104354,7 +104287,7 @@ anf
anf
alP
alP
-anf
+rtU
alP
alP
alP
diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm
index 5f79f64c57..8bf6d0e32b 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" = (
@@ -22362,6 +22362,9 @@
/obj/effect/turf_decal/tile/yellow{
dir = 4
},
+/obj/machinery/computer/gateway_control{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark/side{
dir = 4
},
@@ -22381,12 +22384,6 @@
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating,
/area/maintenance/department/eva)
-"aWr" = (
-/obj/machinery/gateway{
- dir = 10
- },
-/turf/open/floor/engine,
-/area/gateway)
"aWs" = (
/obj/machinery/light{
dir = 8;
@@ -22840,10 +22837,6 @@
},
/turf/open/floor/plasteel,
/area/hallway/primary/central)
-"aXm" = (
-/obj/machinery/gateway,
-/turf/open/floor/engine,
-/area/gateway)
"aXn" = (
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
@@ -22883,12 +22876,6 @@
"aXr" = (
/turf/open/floor/plasteel,
/area/ai_monitored/storage/eva)
-"aXs" = (
-/obj/machinery/gateway{
- dir = 6
- },
-/turf/open/floor/engine,
-/area/gateway)
"aXt" = (
/obj/effect/spawner/structure/window/reinforced,
/obj/structure/sign/warning/securearea,
@@ -30329,12 +30316,6 @@
},
/turf/open/floor/plasteel,
/area/science/mixing)
-"bnl" = (
-/obj/machinery/gateway{
- dir = 9
- },
-/turf/open/floor/engine,
-/area/gateway)
"bnm" = (
/obj/machinery/atmospherics/pipe/manifold/orange/hidden{
dir = 4
@@ -34660,9 +34641,6 @@
c_tag = "Research - Gateway Chamber";
network = list("ss13","rd")
},
-/obj/machinery/gateway{
- dir = 1
- },
/turf/open/floor/engine,
/area/gateway)
"bwL" = (
@@ -34672,12 +34650,6 @@
},
/turf/open/floor/plating,
/area/router)
-"bwM" = (
-/obj/machinery/gateway{
- dir = 5
- },
-/turf/open/floor/engine,
-/area/gateway)
"bwN" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 4
@@ -36403,12 +36375,6 @@
/area/medical/medbay/zone2{
name = "Medbay Treatment Center"
})
-"bAz" = (
-/obj/machinery/gateway{
- dir = 8
- },
-/turf/open/floor/engine,
-/area/gateway)
"bAA" = (
/obj/structure/lattice,
/obj/structure/cable{
@@ -36566,12 +36532,6 @@
/area/medical/medbay/zone2{
name = "Medbay Treatment Center"
})
-"bAN" = (
-/obj/machinery/gateway{
- dir = 4
- },
-/turf/open/floor/engine,
-/area/gateway)
"bAO" = (
/obj/machinery/atmospherics/pipe/simple/supplymain/hidden{
dir = 4
@@ -62112,7 +62072,6 @@
departmentType = 2;
name = "Chemistry RC";
pixel_x = 30;
- pixel_y = 0;
receive_ore_updates = 1
},
/turf/open/floor/plasteel/white,
@@ -99510,9 +99469,9 @@ aaa
aaa
aaa
aUk
-bnl
-bAz
-aWr
+bmG
+bmG
+bmG
cDN
bmG
aUk
@@ -99769,7 +99728,7 @@ aaa
aUk
bwK
bAF
-aXm
+bmG
cDN
bmG
aUk
@@ -100024,9 +99983,9 @@ aaa
aaa
aaa
aUk
-bwM
-bAN
-aXs
+bmG
+bmG
+bmG
cDN
bmG
aUk
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index 0d3665c58d..1b7b9c7414 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,
@@ -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
@@ -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;
@@ -13899,32 +14767,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"
@@ -19546,7 +20388,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
@@ -20242,7 +21084,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
},
@@ -30275,6 +31117,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" = (
@@ -63652,8 +64499,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
@@ -64841,7 +65688,6 @@
pixel_x = -26
},
/obj/structure/sign/painting/library{
- pixel_x = 0;
pixel_y = -32
},
/turf/open/floor/wood,
@@ -72672,7 +73518,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
},
@@ -75577,9 +76423,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 +76438,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cyF" = (
-/obj/machinery/gateway{
- dir = 1
- },
/obj/machinery/status_display/evac{
pixel_y = 32
},
@@ -75616,9 +76456,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{
@@ -76575,26 +77412,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 +77423,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{
@@ -77428,9 +78246,6 @@
/turf/closed/wall,
/area/gateway)
"cBD" = (
-/obj/machinery/gateway{
- dir = 10
- },
/obj/machinery/light{
dir = 8
},
@@ -77449,7 +78264,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"cBE" = (
-/obj/machinery/gateway,
/obj/structure/cable/white{
icon_state = "0-2"
},
@@ -77471,9 +78285,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";
@@ -78596,6 +79407,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 5
},
+/obj/machinery/computer/gateway_control{
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/gateway)
"cDj" = (
@@ -92030,6 +92844,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" = (
@@ -94085,27 +94902,6 @@
/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/kirbyplants/random,
/obj/effect/turf_decal/tile/neutral,
@@ -94731,7 +95527,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
},
@@ -97420,28 +98216,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{
@@ -98454,20 +99228,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 +99245,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,
@@ -99911,41 +100647,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 +101577,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 +101811,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" = (
@@ -101766,11 +102451,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{
@@ -104182,36 +104862,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{
@@ -105172,22 +105822,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
@@ -106023,13 +106657,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)
@@ -107639,16 +108266,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"
@@ -108410,12 +109027,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,
@@ -112756,6 +113367,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/light/small,
/turf/open/floor/plasteel/dark/telecomms,
/area/science/server)
"dKg" = (
@@ -116361,7 +116973,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" = (
@@ -122603,7 +123215,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)
@@ -124992,6 +125604,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
@@ -125387,7 +126013,6 @@
/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)
@@ -125456,7 +126081,6 @@
/area/chapel/office)
"iNK" = (
/obj/structure/sign/painting/library{
- pixel_x = 0;
pixel_y = -32
},
/turf/open/floor/wood,
@@ -125760,6 +126384,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
@@ -126418,6 +127049,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 +127121,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{
@@ -126712,6 +127366,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{
@@ -127182,8 +127854,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 +127935,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{
@@ -161357,7 +162045,7 @@ bvL
cjw
bYU
bvL
-bvL
+aar
bvL
bun
bvL
@@ -163350,7 +164038,7 @@ aof
aky
aky
aky
-arD
+kqo
asZ
aui
avF
@@ -169589,7 +170277,7 @@ cur
cvC
cvz
cyE
-cAi
+cAk
cBD
cDk
cEY
@@ -172869,7 +173557,7 @@ ayD
ayD
hdH
azD
-aEg
+aaq
azD
kam
aHV
@@ -178109,7 +178797,7 @@ dCX
dEj
dFq
dGJ
-dGJ
+pok
dJy
dGJ
dGJ
@@ -178613,7 +179301,7 @@ dnR
dpG
dpG
dpG
-dpG
+abz
dpG
dxu
dyQ
@@ -179132,7 +179820,7 @@ dvO
dxw
dyS
dmh
-dBz
+abK
dCV
dEk
dFt
@@ -179632,22 +180320,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 +180577,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 +180833,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 +181090,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 +181347,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 +181602,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 +181860,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 +182117,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 +182374,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,18 +182631,18 @@ 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
@@ -182201,17 +182889,17 @@ cYv
dah
cTe
dbJ
-cuM
-aad
-ajr
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
-aaa
+aaA
+aaH
+aaV
+aaN
+aaN
+aaN
+aaN
+aaN
+abW
+aci
+aaA
aaa
aaa
ajr
@@ -182458,19 +183146,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 +183403,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 +183660,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 +183917,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 +184174,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 +184433,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 +184691,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
@@ -184262,12 +184950,12 @@ aaa
aaa
aaa
aaa
-hZh
-hZh
-hZh
-hZh
-hZh
-hZh
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
ajr
@@ -184519,12 +185207,12 @@ aaa
aaa
aaa
aaa
-hZh
-hZh
-hZh
-hZh
-hZh
-hZh
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -184776,12 +185464,12 @@ aaa
aaa
aaa
aaa
-hZh
-hZh
-hZh
-hZh
-hZh
-hZh
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -185033,12 +185721,12 @@ aaa
aaa
aaa
aaa
-hZh
-hZh
-hZh
-hZh
-hZh
-hZh
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -185290,12 +185978,12 @@ aaa
aaa
aaa
aaa
-hZh
-hZh
-hZh
-hZh
-hZh
-hZh
+aaa
+aaa
+aaa
+aaa
+aaa
+aaa
aaa
aaa
aaa
@@ -185547,12 +186235,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 b4c6b0c12d..e848fd87d1 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -7205,9 +7205,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
@@ -13179,6 +13176,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 +13604,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 +13848,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" = (
@@ -30479,6 +30475,7 @@
/obj/machinery/light{
dir = 1
},
+/obj/machinery/airalarm/directional/north,
/turf/open/floor/plasteel/dark,
/area/science/research)
"aXx" = (
@@ -43680,10 +43677,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
@@ -57353,9 +57346,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{
@@ -58573,9 +58564,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,
@@ -58938,7 +58927,7 @@
dir = 8
},
/obj/machinery/power/apc{
- areastring = "/area/janitor";
+ areastring = "/area/vacant_room/commissary";
dir = 4;
name = "Vacant Commissary APC";
pixel_x = 27;
@@ -61293,9 +61282,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 +61562,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{
@@ -62896,9 +62881,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)
@@ -68002,9 +67987,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 +68012,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{
@@ -68888,9 +68867,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,
@@ -76334,9 +76311,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 +76377,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";
@@ -77551,9 +77522,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 +77541,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 +77553,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 +77562,9 @@
dir = 8;
pixel_x = 32
},
+/obj/machinery/computer/gateway_control{
+ dir = 8
+ },
/turf/open/floor/plasteel/dark,
/area/gateway)
"cvR" = (
@@ -77635,7 +77601,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 +77617,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)
@@ -78536,6 +78498,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 +80492,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{
@@ -80919,9 +80880,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
@@ -84701,9 +84659,6 @@
},
/area/security/vacantoffice)
"fyr" = (
-/obj/machinery/light{
- dir = 4
- },
/obj/effect/decal/cleanable/cobweb/cobweb2,
/turf/closed/mineral/random/labormineral,
/area/space/nearstation)
@@ -84946,10 +84901,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 +84918,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,
@@ -85287,7 +85241,6 @@
icon_state = "1-2"
},
/obj/structure/table/wood,
-/obj/item/folder/paperwork,
/turf/open/floor/wood,
/area/security/vacantoffice)
"ppP" = (
@@ -85401,9 +85354,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{
@@ -119989,7 +119940,7 @@ ckw
cmw
xON
axa
-jPE
+aeu
aeu
aeU
dQe
@@ -121773,7 +121724,7 @@ clM
axW
cnk
coo
-ayn
+axU
aLH
aLx
aLz
@@ -122293,7 +122244,7 @@ aLF
aag
aag
aag
-bsm
+aLF
cuA
cuW
bYI
@@ -125083,7 +125034,7 @@ bAP
bCf
bhQ
bhQ
-bAM
+jGN
bGH
bOc
bHZ
diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm
index 4d2d8cb624..47d8dd9cb4 100644
--- a/_maps/map_files/LambdaStation/lambda.dmm
+++ b/_maps/map_files/LambdaStation/lambda.dmm
@@ -44383,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"
@@ -80286,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
@@ -82039,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"
@@ -107579,7 +107587,7 @@ aaA
abY
ayy
acw
-acw
+vDO
acw
acw
aeG
@@ -135198,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 a143bf9bdf..16659f3e7a 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -922,7 +922,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" = (
@@ -2292,8 +2292,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,
@@ -3116,9 +3115,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 +3184,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 +3672,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 +4285,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 +4804,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 +4833,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 +4943,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 +5041,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 +5067,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 +6941,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 +6989,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
@@ -10300,6 +10324,7 @@
/turf/open/floor/carpet,
/area/crew_quarters/dorms)
"atd" = (
+/mob/living/simple_animal/opossum,
/turf/open/floor/plating{
icon_state = "panelscorched"
},
@@ -15603,7 +15628,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" = (
@@ -21182,7 +21207,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" = (
@@ -24081,9 +24106,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{
@@ -31733,28 +31759,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 +31834,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 +31852,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 +31874,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 +32682,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 +32859,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 +32884,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 +32894,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 +32908,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 +32921,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 +32934,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 +32946,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 +32962,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 +32974,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 +33851,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 +33863,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 +33878,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 +34959,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 +34980,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 +36123,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 +36206,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 +36219,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 +36231,7 @@
/obj/structure/cable/yellow{
icon_state = "1-2"
},
+/obj/effect/turf_decal/tile/neutral,
/turf/open/floor/plasteel,
/area/hallway/primary/port)
"bsw" = (
@@ -37020,29 +37004,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 +37683,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" = (
@@ -37847,26 +37821,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 +37849,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" = (
@@ -38677,28 +38649,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 +38698,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 +39220,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 +39240,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 +39257,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 +39273,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 +39286,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 +39305,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 +39318,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 +39331,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 +39584,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 +40183,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 +40254,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,
@@ -41039,33 +40985,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 +41016,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 +41054,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 +41063,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 +41700,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 +42374,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 +42600,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 +42714,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 +42749,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 +43346,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 +43373,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
@@ -44151,9 +44063,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 +44104,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 +44134,6 @@
/obj/item/radio/intercom{
pixel_x = -29
},
-/obj/machinery/light/small{
- dir = 8
- },
/turf/open/floor/wood,
/area/security/vacantoffice)
"bJu" = (
@@ -44250,8 +44157,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 +44169,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 +44480,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 +44497,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 +44664,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" = (
@@ -44993,15 +44856,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 +45165,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 +45399,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" = (
@@ -45785,7 +45626,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 +45889,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 +45941,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 +46027,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 +46041,6 @@
/turf/open/floor/plasteel/dark,
/area/gateway)
"bNq" = (
-/obj/machinery/gateway,
/obj/structure/cable/yellow{
icon_state = "0-2"
},
@@ -46231,9 +46058,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 +46208,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 +46658,9 @@
/obj/effect/turf_decal/stripes/line{
dir = 5
},
+/obj/machinery/computer/gateway_control{
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/gateway)
"bOJ" = (
@@ -47769,9 +47601,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" = (
@@ -65072,10 +64901,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 +64933,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 +64944,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 +64976,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 +64994,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 +65405,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 +66090,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 +66813,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 +67002,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 +67973,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 +68365,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" = (
@@ -69038,9 +68851,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 +70081,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" = (
@@ -79185,13 +78993,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 +79074,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 +79114,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 +79129,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 +79522,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" = (
@@ -79910,20 +79706,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 +80244,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 +81108,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 +81124,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
@@ -81440,6 +81237,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"
@@ -81516,6 +81319,13 @@
},
/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{
@@ -81649,12 +81459,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;
@@ -81722,15 +81545,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 +81588,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,
@@ -81849,15 +81687,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 +81744,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" = (
@@ -81980,31 +81824,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 +81863,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
@@ -82057,19 +81910,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 +82150,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 +82220,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 +82268,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 +82289,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 +82375,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 +82435,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" = (
@@ -82615,15 +82515,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 +82576,10 @@
},
/turf/open/floor/plasteel/dark,
/area/crew_quarters/cryopod)
+"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 +82588,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 +82605,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 +82635,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,
@@ -82867,6 +82767,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,10 +82833,21 @@
/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,
@@ -82981,7 +82904,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,13 +82922,21 @@
/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" = (
@@ -83081,26 +83015,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)
@@ -96375,7 +96305,7 @@ bxL
bvJ
bxB
bCQ
-bBd
+bCH
bCH
bEn
dic
@@ -96628,18 +96558,18 @@ bjV
bnK
bqb
bbI
-btT
+bJr
bvK
bxC
-bEp
-bJp
-rbE
alK
alK
alK
alK
alK
alK
+dQg
+alK
+alK
alK
bPF
asa
@@ -96882,7 +96812,7 @@ bgv
biv
bjW
blT
-bnL
+bso
bqc
bso
bso
@@ -96893,9 +96823,9 @@ tre
bCI
bEo
bJj
-xTV
+bbL
bJq
-bKX
+bbL
bbL
bbL
bPG
@@ -97139,20 +97069,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
@@ -97395,21 +97325,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 +97583,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 +97840,13 @@ bgy
biz
bka
blX
-baE
-afQ
-afQ
-afQ
-afQ
-afQ
-baE
+bnR
+ahT
+ahT
+bKX
+jPu
+rbE
+xTV
bBf
bCL
bEq
@@ -98165,19 +98095,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 +98354,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 +98611,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 +98869,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 +99125,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
@@ -99456,12 +99386,12 @@ bnS
bqj
bsu
btY
-bqj
-bsu
-bEt
-nhy
-mcS
-bvW
+maP
+xLL
+bzx
+bzx
+bzx
+bzx
bzx
bzx
bzx
@@ -99715,7 +99645,7 @@ bsv
btZ
bvV
bxN
-bGj
+bvW
dhZ
bCP
bvW
@@ -99973,9 +99903,9 @@ baE
bvW
bxO
bvW
-bvW
-bvW
-bvW
+dhZ
+fDG
+jdf
bGm
bHO
bvW
@@ -100233,7 +100163,7 @@ bzA
bBm
bCR
bvW
-syk
+bvW
bvW
bvW
bLd
@@ -100256,7 +100186,7 @@ csT
dux
cxQ
ckS
-cmi
+pbc
cnk
ckP
cmi
@@ -100489,7 +100419,7 @@ bxQ
bzB
bBn
bCS
-eiS
+bBn
bQN
dih
bvW
@@ -113599,8 +113529,8 @@ bDj
bFb
bGQ
bGM
-bJY
-bLD
+bNr
+bLF
bNp
bOK
bQu
@@ -114113,7 +114043,7 @@ bDw
bFd
bGS
bGM
-bKa
+bNp
bLF
bNr
bOM
@@ -117230,16 +117160,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 +117423,9 @@ cBC
cyK
cyK
cyK
-dvY
-dyc
-cub
+cyK
+cyK
+cyK
diP
dvY
cJZ
@@ -117751,9 +117681,9 @@ cCD
uun
rSL
dvY
-cEz
-dxQ
dyc
+gGH
+pVL
dvY
cKa
cKO
@@ -136463,9 +136393,9 @@ bnw
bpJ
brW
aRy
-bvt
-aaa
-aTU
+aRy
+aRy
+jQK
aaa
aaa
aaa
@@ -136719,9 +136649,9 @@ blC
bnx
bpK
bsf
-aRy
-aRy
-aRy
+bGh
+nix
+bGh
aRy
aRy
aRy
@@ -136978,7 +136908,7 @@ bpL
brY
btL
btL
-btL
+txh
btL
btL
bCD
@@ -137235,7 +137165,7 @@ bpM
brZ
btL
bvu
-bGh
+bxq
bzn
bAU
bCD
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index a4315eb699..e07873089a 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -4294,8 +4294,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";
@@ -5282,16 +5281,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
@@ -5560,21 +5551,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,
@@ -5660,23 +5658,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{
@@ -6169,21 +6164,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,
@@ -7141,8 +7123,7 @@
},
/obj/effect/turf_decal/tile/red,
/obj/machinery/status_display{
- pixel_x = 32;
- pixel_y = 0
+ pixel_x = 32
},
/turf/open/floor/plasteel,
/area/security/brig)
@@ -10487,21 +10468,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{
@@ -10589,17 +10557,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,
@@ -12704,24 +12670,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,
@@ -13298,7 +13254,6 @@
dir = 9
},
/obj/machinery/computer/security/wooden_tv{
- pixel_x = 0;
pixel_y = 4
},
/turf/open/floor/wood,
@@ -14006,15 +13961,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,
@@ -14671,11 +14627,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
@@ -14711,27 +14672,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
@@ -14759,11 +14739,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"
@@ -15026,69 +15010,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{
@@ -15365,22 +15352,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{
@@ -15530,12 +15515,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{
@@ -15552,19 +15536,17 @@
/turf/closed/wall,
/area/hallway/secondary/exit)
"axX" = (
-/obj/effect/landmark/xeno_spawn,
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 1
- },
-/turf/open/floor/wood,
-/area/maintenance/port)
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
+/turf/closed/wall/r_wall/rust,
+/area/maintenance/port/aft)
"axY" = (
-/obj/machinery/atmospherics/pipe/simple/supply/hidden{
- dir = 4
+/obj/structure/cable/white{
+ icon_state = "1-2"
},
-/obj/item/cigbutt,
+/obj/machinery/atmospherics/pipe/simple/supply/hidden,
+/obj/effect/landmark/event_spawn,
/turf/open/floor/plating,
-/area/maintenance/port)
+/area/maintenance/port/aft)
"axZ" = (
/turf/closed/wall/r_wall/rust,
/area/security/prison)
@@ -17492,6 +17474,13 @@
},
/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"
@@ -18185,6 +18174,12 @@
/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
@@ -18208,6 +18203,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;
@@ -18609,6 +18613,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"
@@ -18651,12 +18662,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{
@@ -19132,6 +19221,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{
@@ -19789,6 +19978,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
@@ -19799,6 +19999,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
@@ -19822,6 +20037,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
@@ -19841,6 +20060,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,
@@ -20195,6 +20433,13 @@
/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
@@ -20350,6 +20595,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,
@@ -20383,9 +20632,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
@@ -20442,6 +20710,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{
@@ -20607,6 +20898,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";
@@ -20634,6 +20938,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"
@@ -20912,6 +21234,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{
@@ -20926,6 +21339,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";
@@ -20948,6 +21370,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"
@@ -21081,6 +21514,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"
@@ -21284,6 +21722,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
@@ -21311,6 +21780,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,
@@ -21447,6 +21935,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,
@@ -22062,7 +22567,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
@@ -22086,6 +22591,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
@@ -22193,6 +22758,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"
@@ -22239,6 +22818,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;
@@ -22247,6 +22840,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"
@@ -22269,6 +22873,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,
@@ -22485,6 +23105,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
@@ -22722,6 +23364,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;
@@ -22758,6 +23453,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{
@@ -22900,6 +23607,25 @@
},
/turf/open/floor/engine,
/area/engine/supermatter)
+"aKB" = (
+/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)
"aKC" = (
/obj/machinery/atmospherics/components/binary/pump{
name = "Gas to Chamber"
@@ -22918,6 +23644,16 @@
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel/dark,
/area/engine/engineering)
+"aKF" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/structure/sign/warning/vacuum{
+ pixel_x = -32;
+ pixel_y = 32
+ },
+/turf/open/floor/plating,
+/area/maintenance/port/aft)
"aKG" = (
/obj/structure/cable/white{
icon_state = "1-2"
@@ -22965,6 +23701,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{
@@ -23180,6 +23922,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,
@@ -23434,6 +24179,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
@@ -23444,6 +24239,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{
@@ -23541,6 +24407,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"
@@ -23635,6 +24507,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
@@ -23815,6 +24692,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"
@@ -23934,6 +24817,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
@@ -23996,6 +24921,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)
@@ -24060,6 +25035,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";
@@ -24118,6 +25109,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"
@@ -24300,6 +25302,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,
@@ -24517,6 +25556,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{
@@ -24609,6 +25736,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";
@@ -24622,6 +25785,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";
@@ -24637,6 +25823,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,
@@ -24663,6 +25867,19 @@
/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/kirbyplants{
icon_state = "plant-21"
@@ -24736,6 +25953,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,
@@ -24826,6 +26050,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
@@ -24852,6 +26094,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"
@@ -24873,60 +26131,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
@@ -24965,49 +26264,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,
@@ -25026,92 +26325,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
@@ -25194,6 +26478,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
@@ -25397,6 +26696,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
@@ -25435,10 +26762,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"
@@ -25500,89 +26958,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{
@@ -25699,16 +27137,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;
@@ -25733,6 +27173,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{
@@ -25915,6 +27388,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
@@ -25953,6 +27514,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{
@@ -25972,6 +27546,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
@@ -26013,6 +27598,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
@@ -26041,9 +27634,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)
@@ -26086,30 +27709,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)
@@ -26141,6 +27751,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{
@@ -26156,6 +27771,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,
@@ -26217,6 +27870,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";
@@ -26239,6 +27906,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,
@@ -26251,6 +27950,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"
@@ -26394,14 +28097,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,
@@ -26430,6 +28131,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
@@ -26521,44 +28239,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)
@@ -26585,26 +28290,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/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)
@@ -26618,6 +28308,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{
@@ -26632,6 +28335,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,
@@ -26764,10 +28515,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";
@@ -26813,6 +28597,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,
@@ -26912,12 +28712,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
@@ -26948,7 +28751,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
},
@@ -26991,96 +28794,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,
@@ -27095,11 +28892,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" = (
@@ -27120,6 +28918,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{
@@ -27328,6 +29139,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
@@ -27362,6 +29179,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
@@ -27424,13 +29275,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";
@@ -27481,74 +29342,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,
@@ -27566,27 +29467,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" = (
@@ -27725,6 +29640,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"
@@ -27827,18 +29809,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,
@@ -27863,117 +29849,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{
@@ -27984,16 +29962,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{
@@ -28182,6 +30155,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
@@ -28197,14 +30203,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,
@@ -28248,9 +30254,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{
@@ -28290,22 +30302,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,
@@ -28317,24 +30322,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
},
@@ -28346,19 +30345,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{
@@ -28367,123 +30386,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{
@@ -28501,21 +30475,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,
@@ -28630,6 +30622,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,
@@ -28692,12 +30724,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{
@@ -28716,68 +30749,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{
@@ -28945,6 +30982,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,
@@ -28969,13 +31027,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{
@@ -29106,6 +31170,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
@@ -29190,6 +31269,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
@@ -29316,53 +31408,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
@@ -29459,6 +31519,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,
@@ -29805,85 +31871,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{
@@ -30092,6 +32150,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
@@ -30191,62 +32257,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
@@ -30287,88 +32371,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{
@@ -30429,6 +32544,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{
@@ -30777,113 +32907,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,
@@ -31281,101 +33304,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
@@ -31689,92 +33617,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,
@@ -32099,129 +33941,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{
@@ -32673,160 +34392,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{
@@ -33237,148 +34802,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,
@@ -33515,93 +34942,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{
@@ -33735,22 +35075,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
@@ -33763,122 +35087,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{
@@ -34161,22 +35379,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
@@ -34503,21 +35705,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)
@@ -37918,14 +39105,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
@@ -38349,22 +39528,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
@@ -40088,9 +41251,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
@@ -40828,6 +41988,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"
@@ -41066,12 +42236,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"
@@ -41905,10 +43069,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)
@@ -41969,9 +43129,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)
@@ -42049,33 +43206,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
@@ -42088,11 +43225,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)
@@ -44083,6 +45215,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
@@ -72664,10 +73800,10 @@ aad
aad
aad
aad
-baj
-aqo
-baj
-baj
+aKm
+aKo
+aKm
+aKm
aaa
aaa
aaa
@@ -72922,9 +74058,9 @@ aMJ
aMJ
sJV
aMJ
-aqx
-awH
-baj
+aKr
+aLz
+aKm
aaa
aaa
aaa
@@ -73179,9 +74315,9 @@ buJ
buO
sKn
aMJ
-atE
-sKx
-baj
+aKB
+aLs
+aKm
aac
aaa
aaa
@@ -73436,8 +74572,8 @@ buK
sKj
buR
aMJ
-avB
-aOH
+aKF
+aqo
aad
aac
aaa
@@ -73693,8 +74829,8 @@ buL
buP
buS
aMJ
-awB
-baj
+aKJ
+aKm
aad
aad
aaa
@@ -73950,8 +75086,8 @@ buK
sKj
buR
aMJ
-awB
-baj
+aKJ
+aKm
aad
aad
aaa
@@ -74207,8 +75343,8 @@ buN
buQ
buU
sJV
-awB
-aOH
+aKJ
+aqo
aad
aaa
aaa
@@ -74464,9 +75600,9 @@ sJV
aMJ
aMJ
sJV
-awB
-aOH
-sKx
+aKJ
+aqo
+aLs
aac
aaa
aaa
@@ -74720,10 +75856,10 @@ bvo
aad
bvo
aad
-baj
-awE
-awL
-baj
+aKm
+aLp
+aLB
+aKm
aac
aac
aac
@@ -74977,10 +76113,10 @@ aUQ
aVK
aUQ
aXc
-baj
-aOH
-axY
-awG
+aKm
+aqo
+aLC
+aLv
aac
aac
aac
@@ -75235,9 +76371,9 @@ aVL
aUR
aUQ
bvo
-sKx
-awB
-baj
+aLs
+aKJ
+aKm
aac
aad
aac
@@ -75492,9 +76628,9 @@ aUU
aWz
aVL
bvo
-aOH
-axh
-baj
+aqo
+aLL
+aKm
aad
aad
aad
@@ -75749,10 +76885,10 @@ aUU
aWz
aUQ
bvg
-baj
-awB
-baj
-baj
+aKm
+aKJ
+aKm
+aKm
aad
aad
aad
@@ -76006,10 +77142,10 @@ aUU
aWz
aVL
bvg
-awG
-awB
-axj
-baj
+aLv
+aKJ
+aME
+aKm
aad
aad
aad
@@ -76263,17 +77399,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
@@ -76520,21 +77656,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
@@ -76777,21 +77913,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
@@ -77034,21 +78170,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
@@ -77291,21 +78427,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
@@ -77548,23 +78684,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
@@ -77805,23 +78941,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
@@ -78051,34 +79187,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
@@ -78308,34 +79444,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
@@ -78565,8 +79701,8 @@ apt
aLZ
aNb
aEt
-bbg
-aPQ
+atE
+axh
aQW
aQW
aQW
@@ -78579,20 +79715,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
@@ -78822,8 +79958,8 @@ aKK
aMa
aNc
aEt
-bbg
-aPR
+atE
+axk
aQW
aRT
aRU
@@ -78836,23 +79972,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
@@ -79079,8 +80215,8 @@ aKL
aMb
aNd
sHV
-aOL
-aPS
+avB
+axl
sJI
aSc
aTc
@@ -79093,23 +80229,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
@@ -79336,8 +80472,8 @@ aKM
aMa
aNe
aEt
-aYA
-aPT
+awB
+axn
aQW
amH
aTd
@@ -79350,23 +80486,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
@@ -79593,8 +80729,8 @@ aKN
aMc
aNf
aEt
-aOM
-aPU
+awE
+axL
aQW
aRW
aTe
@@ -79607,23 +80743,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
@@ -79850,37 +80986,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
@@ -80117,16 +81253,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
@@ -80135,9 +81271,9 @@ bhZ
biF
bjf
bfu
-aad
-aad
-aac
+aZr
+aZp
+aLv
aac
aaa
aaa
@@ -80373,17 +81509,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
@@ -80392,9 +81528,9 @@ bia
biG
bjg
bfu
-aad
-aad
-aac
+aZs
+aZz
+aKm
aaa
aaa
aaa
@@ -80631,16 +81767,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
@@ -80651,7 +81787,7 @@ bjh
bfu
sLf
bfu
-aac
+aKm
aaa
aaa
aaa
@@ -80878,27 +82014,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
@@ -81135,26 +82271,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
@@ -81392,7 +82528,7 @@ aKQ
aMf
aNk
aOf
-aOT
+aDp
aQb
aRa
aSd
@@ -81402,16 +82538,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
@@ -81651,25 +82787,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
@@ -81906,26 +83042,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
@@ -82163,26 +83299,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
@@ -82420,27 +83556,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
@@ -82677,16 +83813,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
@@ -82696,7 +83832,7 @@ bcf
bcW
blt
ooX
-aOL
+avB
bfA
bfX
bgI
@@ -82934,15 +84070,15 @@ aKX
lyp
bIJ
aOj
-aOZ
+aEm
bxQ
sJJ
-aSh
-aTm
-aUo
-aVg
-aWc
-aWK
+ail
+aGF
+aJO
+aNL
+aNo
+aNP
aXm
aXS
aYK
@@ -82953,7 +84089,7 @@ bcg
bcX
bdS
aSh
-aOL
+avB
bfy
bfY
bgJ
@@ -83194,12 +84330,12 @@ aHM
aPa
aQb
aKg
-aSh
-aTn
-aUp
-aVh
-aWd
-aWL
+ail
+aHc
+aKk
+aNM
+aOB
+aNQ
aXn
bxT
aYL
@@ -83210,7 +84346,7 @@ aUn
aWb
bdT
aSh
-bbg
+atE
bfA
bfZ
bgK
@@ -83451,12 +84587,12 @@ aOh
vsL
aQd
sJK
-aSi
-aTo
-aUq
-aVi
-aWe
-aWM
+aFm
+aHd
+aJd
+aNN
+aOR
+aNR
aXo
aXT
aYM
@@ -83467,7 +84603,7 @@ bch
bcY
bdU
beE
-beZ
+aVe
bfC
bga
bgL
@@ -83723,8 +84859,8 @@ bbq
bbq
bbq
bdV
-beF
-bfa
+aUM
+aVf
bfA
bgb
bgM
@@ -83969,7 +85105,7 @@ aSj
aTq
aUs
aVj
-aWf
+aWg
aTp
aXq
aXV
@@ -83981,7 +85117,7 @@ bci
bcZ
bdW
aSh
-bbg
+atE
bfA
bfu
bfu
@@ -84222,25 +85358,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
@@ -84481,24 +85617,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
@@ -84743,7 +85879,7 @@ aVm
aWi
aWN
aXt
-aiQ
+aOY
aYR
aZN
ajO
@@ -84752,9 +85888,9 @@ bcj
bdb
bdY
aSh
-sKW
-bfF
-aZo
+aVi
+aWd
+aMG
bgP
bhB
bir
@@ -84996,8 +86132,8 @@ aRg
aSn
aTu
aUw
-aVn
-aWj
+aWf
+aZA
aWO
aXu
aXZ
@@ -85009,9 +86145,9 @@ bck
bdc
bdZ
aSh
-bfd
-bfG
-bgd
+aVk
+aWe
+aWH
bgP
bhC
bis
@@ -85266,9 +86402,9 @@ aSh
aWK
bea
beG
-sKE
-bfH
-baj
+aUi
+aWv
+aKm
bgQ
bhD
bit
@@ -91404,7 +92540,7 @@ aSD
aRz
aRz
aRz
-sGY
+saI
aRz
sIb
bsD
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index ca155d6e94..e6f14badd9 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -334,8 +334,8 @@
/area/crew_quarters/fitness/pool)
"aaM" = (
/turf/open/floor/plasteel/yellowsiding/corner{
- icon_state = "yellowcornersiding";
- dir = 8
+ dir = 8;
+ icon_state = "yellowcornersiding"
},
/area/crew_quarters/fitness/pool)
"aaN" = (
@@ -354,8 +354,8 @@
/area/crew_quarters/fitness/pool)
"aaP" = (
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 8
+ dir = 8;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"aaQ" = (
@@ -433,8 +433,8 @@
/area/crew_quarters/fitness/pool)
"aaW" = (
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 1
+ dir = 1;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"aaX" = (
@@ -550,8 +550,8 @@
"abm" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 4
+ dir = 4;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"abn" = (
@@ -580,8 +580,8 @@
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 4
+ dir = 4;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"abr" = (
@@ -595,8 +595,8 @@
"abt" = (
/obj/structure/pool/Rboard,
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 8
+ dir = 8;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"abu" = (
@@ -659,8 +659,8 @@
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/plasteel/yellowsiding/corner{
- icon_state = "yellowcornersiding";
- dir = 4
+ dir = 4;
+ icon_state = "yellowcornersiding"
},
/area/crew_quarters/fitness/pool)
"abB" = (
@@ -670,21 +670,21 @@
pixel_y = -27
},
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 1
+ dir = 1;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"abC" = (
/obj/machinery/light,
/turf/open/floor/plasteel/yellowsiding{
- icon_state = "yellowsiding";
- dir = 1
+ dir = 1;
+ icon_state = "yellowsiding"
},
/area/crew_quarters/fitness/pool)
"abD" = (
/turf/open/floor/plasteel/yellowsiding/corner{
- icon_state = "yellowcornersiding";
- dir = 1
+ dir = 1;
+ icon_state = "yellowcornersiding"
},
/area/crew_quarters/fitness/pool)
"abE" = (
@@ -2190,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)
@@ -6313,27 +6313,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
},
@@ -6350,23 +6330,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,
@@ -6692,44 +6655,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
@@ -6916,9 +6845,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
@@ -6933,7 +6859,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
@@ -6948,9 +6873,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
@@ -7876,32 +7798,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" = (
@@ -8904,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" = (
@@ -10736,7 +10659,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" = (
@@ -22136,6 +22059,9 @@
/obj/item/kirbyplants{
icon_state = "plant-05"
},
+/obj/machinery/light/small{
+ dir = 1
+ },
/turf/open/floor/plasteel/dark,
/area/crew_quarters/bar)
"aYZ" = (
@@ -39039,7 +38965,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
},
@@ -40074,12 +39999,6 @@
/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
},
@@ -47270,7 +47189,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{
@@ -50401,9 +50320,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,
@@ -52990,7 +52911,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" = (
@@ -54125,6 +54046,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
@@ -55661,11 +55596,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"
@@ -57735,10 +57670,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{
@@ -57901,7 +57833,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{
@@ -58004,10 +57936,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,
@@ -58730,6 +58659,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"
@@ -59529,14 +59462,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"
@@ -60135,7 +60067,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" = (
@@ -60664,10 +60595,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,
@@ -61096,13 +61024,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
@@ -61617,12 +61538,6 @@
},
/turf/open/floor/plating,
/area/maintenance/department/crew_quarters/bar)
-"wDe" = (
-/obj/effect/spawner/structure/window/reinforced,
-/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,
@@ -62035,10 +61950,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,
@@ -75863,8 +75775,8 @@ aaa
bGI
bNs
cfN
-cqW
-cqW
+cfN
+cfN
cfN
cfN
bZY
@@ -76376,7 +76288,7 @@ aaa
aaa
bGI
bNs
-cqW
+cfN
bOw
cfN
bOw
@@ -80474,7 +80386,7 @@ aaa
aht
aqG
bGE
-bKf
+cqW
bKf
bMw
bNy
@@ -80731,8 +80643,8 @@ aht
aht
aqG
bGE
-bKf
-bKf
+izF
+ros
bMx
bNz
bHM
@@ -80988,7 +80900,7 @@ aaa
aaa
aqG
bGE
-wDe
+bGE
bHM
bHM
bNA
@@ -83560,7 +83472,7 @@ bHP
bJb
bJb
bJb
-bJb
+fgS
bJb
bJb
bPp
@@ -97881,8 +97793,8 @@ aaa
aaa
aaa
lcZ
-aoA
-apq
+apW
+apV
apU
aqQ
arX
@@ -98395,8 +98307,8 @@ aiT
aiS
aaa
lcZ
-aoC
-aps
+apU
+apV
apW
aqS
arZ
@@ -99929,7 +99841,7 @@ akh
alc
alR
amF
-alb
+pzF
alb
anm
ajv
@@ -107720,7 +107632,7 @@ aht
bwm
ikB
iVJ
-izF
+lWy
typ
bwm
aht
@@ -108230,7 +108142,7 @@ bwm
svN
bIQ
uek
-izF
+lWy
bwm
qnT
lJr
@@ -108485,9 +108397,9 @@ dMO
lWy
rxQ
lWy
-ros
-izF
-izF
+bIQ
+lWy
+lWy
mES
lWy
lWy
@@ -108744,7 +108656,7 @@ bwm
nzD
uoj
bwm
-izF
+lWy
bwm
dMI
lWy
@@ -108998,7 +108910,7 @@ bkF
bwm
bwm
bwm
-ros
+bIQ
bwm
bwm
bwm
@@ -109255,8 +109167,8 @@ bkF
qIO
jXA
bwm
-ros
-vpz
+bIQ
+hXt
bwm
aht
bwm
diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm
index 2c0ee99d77..f7aca9baf2 100644
--- a/_maps/map_files/Snaxi/Snaxi.dmm
+++ b/_maps/map_files/Snaxi/Snaxi.dmm
@@ -1,4 +1,309 @@
//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"
+ },
+/obj/structure/sign/directions/evac{
+ pixel_y = 40
+ },
+/obj/structure/sign/directions/security{
+ pixel_y = 32
+ },
+/obj/structure/sign/directions/command{
+ pixel_y = 24
+ },
+/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 +316,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 +515,24 @@
},
/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"
+ },
+/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/quartermaster/miningdock)
"aaO" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 9
@@ -36,13 +547,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 +705,308 @@
},
/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/reagent_dispensers/watertank,
+/obj/item/radio/intercom{
+ pixel_y = -26
+ },
+/obj/structure/sign/departments/xenobio{
+ pixel_x = 32
+ },
+/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 +1014,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 +1177,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 +1213,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 +1229,38 @@
},
/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" = (
+/obj/structure/sign/poster/official/science{
+ pixel_y = -32
+ },
+/turf/open/floor/plasteel/white,
+/area/science/mixing)
+"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 +1270,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,
@@ -772,16 +1941,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 +2074,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 +2704,7 @@
/turf/open/floor/plasteel/white,
/area/science/lab)
"ayu" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-16"
},
/obj/effect/turf_decal/tile/purple{
@@ -2950,24 +4106,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 +4161,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" = (
@@ -3545,8 +4683,8 @@
name = "supply dock loading door"
},
/obj/machinery/conveyor{
- id = "QMLoad2";
- dir = 1
+ dir = 1;
+ id = "QMLoad2"
},
/turf/open/floor/plating,
/area/quartermaster/storage)
@@ -4937,13 +6075,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"
@@ -6489,10 +7620,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"
@@ -7161,15 +8288,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"
@@ -7757,7 +8875,7 @@
/obj/structure/cable{
icon_state = "4-8"
},
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/carpet,
@@ -8466,15 +9584,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
@@ -8829,18 +9938,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,
@@ -9031,7 +10128,7 @@
/obj/structure/cable{
icon_state = "2-8"
},
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/plasteel/dark,
@@ -9409,7 +10506,7 @@
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
"dij" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/carpet,
@@ -9806,14 +10903,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"
@@ -10028,19 +11117,6 @@
/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{
@@ -10876,15 +11952,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,
@@ -11361,7 +12428,7 @@
/turf/open/floor/plasteel,
/area/janitor)
"eue" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-04"
},
/obj/effect/turf_decal/tile/blue{
@@ -11404,13 +12471,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 +12693,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 +12722,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 +13134,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 +13414,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 +13428,8 @@
/area/bridge/meeting_room)
"eZU" = (
/obj/machinery/conveyor{
- id = "QMLoad2";
- dir = 1
+ dir = 1;
+ id = "QMLoad2"
},
/turf/open/floor/plating,
/area/quartermaster/storage)
@@ -12854,14 +13884,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 +13967,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 +14099,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";
@@ -13696,13 +14695,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,
@@ -15078,18 +16070,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{
@@ -15274,19 +16254,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{
@@ -15586,13 +16553,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"
@@ -16187,31 +17147,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,
@@ -16873,12 +17808,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
@@ -17391,7 +18320,7 @@
/obj/machinery/light{
dir = 4
},
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/wood,
@@ -17873,14 +18802,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"
@@ -17991,6 +18912,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"
@@ -19711,19 +20636,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
@@ -19924,7 +20836,6 @@
/obj/structure/cable{
icon_state = "0-2"
},
-/obj/machinery/gateway,
/obj/effect/turf_decal/bot_white,
/turf/open/floor/plasteel/dark,
/area/teleporter)
@@ -20463,10 +21374,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
@@ -20693,13 +21600,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{
@@ -21094,8 +21994,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)
@@ -22199,19 +23099,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,
@@ -22647,7 +23534,7 @@
/turf/open/floor/engine,
/area/engine/engineering)
"lfs" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-08"
},
/turf/open/floor/plasteel,
@@ -23170,6 +24057,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"
@@ -24386,24 +25277,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"
@@ -24804,13 +25677,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
@@ -25367,22 +26233,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;
@@ -26129,12 +26979,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,
@@ -26167,14 +27011,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,
@@ -26793,34 +27629,6 @@
},
/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,
@@ -26891,7 +27699,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{
@@ -27641,9 +28449,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)
@@ -27761,9 +28566,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"
@@ -27866,7 +28668,7 @@
/turf/open/floor/carpet,
/area/quartermaster/miningoffice)
"old" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "applebush"
},
/turf/open/floor/wood,
@@ -28539,7 +29341,7 @@
/turf/open/floor/carpet,
/area/crew_quarters/heads/hop)
"oGU" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/wood,
@@ -28743,23 +29545,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"
@@ -29580,13 +30365,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"
@@ -29610,7 +30388,7 @@
c_tag = "Courtroom East";
dir = 8
},
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "applebush"
},
/turf/open/floor/wood,
@@ -30311,20 +31089,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
@@ -30917,12 +31681,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"
@@ -31091,15 +31849,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
@@ -31885,13 +32634,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
@@ -32098,8 +32840,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";
@@ -32161,7 +32903,7 @@
/turf/open/floor/carpet,
/area/crew_quarters/dorms)
"qHO" = (
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-21"
},
/turf/open/floor/plasteel,
@@ -32351,7 +33093,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" = (
@@ -32969,7 +33711,7 @@
dir = 4
},
/obj/effect/turf_decal/tile/neutral,
-/obj//obj/item/kirbyplants,
+/obj/item/kirbyplants,
/turf/open/floor/plasteel,
/area/crew_quarters/fitness)
"rhX" = (
@@ -33785,35 +34527,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
@@ -34306,10 +35019,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
@@ -34354,7 +35063,7 @@
/area/engine/engineering)
"saN" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/plasteel,
@@ -34527,16 +35236,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
@@ -34793,15 +35492,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
@@ -34845,7 +35535,7 @@
dir = 8
},
/obj/effect/turf_decal/tile/blue,
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/plasteel/dark,
@@ -35310,16 +36000,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,
@@ -35403,9 +36083,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
@@ -36248,7 +36925,7 @@
/obj/effect/turf_decal/tile/red{
dir = 4
},
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/turf/open/floor/plasteel/dark,
@@ -36573,9 +37250,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;
@@ -37171,18 +37848,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";
@@ -37441,24 +38106,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{
@@ -37705,11 +38352,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"
@@ -38023,23 +38665,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"
@@ -39247,8 +39872,8 @@
name = "supply dock loading door"
},
/obj/machinery/conveyor{
- id = "QMLoad2";
- dir = 1
+ dir = 1;
+ id = "QMLoad2"
},
/turf/open/floor/plating,
/area/quartermaster/storage)
@@ -39695,8 +40320,8 @@
/area/security/checkpoint/supply)
"vgX" = (
/obj/machinery/conveyor{
- id = "QMLoad2";
- dir = 1
+ dir = 1;
+ id = "QMLoad2"
},
/turf/open/floor/plasteel,
/area/quartermaster/storage)
@@ -39824,16 +40449,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
@@ -40096,9 +40711,6 @@
/turf/open/floor/plasteel,
/area/engine/engineering)
"vse" = (
-/obj/machinery/gateway{
- dir = 10
- },
/obj/machinery/light{
dir = 8
},
@@ -41638,13 +42250,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)
@@ -42940,9 +43545,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)
@@ -42999,24 +43601,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
@@ -43143,9 +43727,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{
@@ -43206,7 +43787,7 @@
/obj/structure/cable{
icon_state = "0-4"
},
-/obj//obj/item/kirbyplants{
+/obj/item/kirbyplants{
icon_state = "plant-10"
},
/obj/machinery/power/apc{
@@ -43225,20 +43806,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,
@@ -43342,11 +43909,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{
@@ -43520,18 +44082,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"
@@ -43705,10 +44255,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
@@ -43874,9 +44420,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)
@@ -44338,10 +44881,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,
@@ -44396,10 +44935,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
@@ -56913,7 +57448,7 @@ avT
avT
gLH
xHk
-jPP
+xcd
vse
mSs
qQH
@@ -57169,7 +57704,7 @@ bBh
avT
avT
gLH
-wie
+xcd
ePa
jrR
nTQ
@@ -58978,8 +59513,8 @@ ash
ash
nQr
ash
-ash
-ash
+tmO
+tmO
wje
ahC
nOK
@@ -59235,9 +59770,9 @@ rbW
aoR
apO
ash
-arG
-ash
-qbh
+abq
+tmO
+abu
auY
hEf
eGO
@@ -59492,8 +60027,8 @@ rRV
aoT
pWz
ash
-xCr
-ash
+abr
+abt
lxF
rbo
ioG
@@ -59746,11 +60281,11 @@ tUi
ash
tVS
anm
-jiV
-ash
-ash
+abH
ash
ash
+tmO
+tmO
dXR
hOA
irg
@@ -60010,7 +60545,7 @@ arI
syN
atr
rbo
-jwo
+aaF
azq
azq
azq
@@ -60249,7 +60784,7 @@ ash
cxX
sXJ
sXJ
-hnB
+aal
qhU
vCE
gIm
@@ -61309,7 +61844,7 @@ aPB
oqL
aLG
aNk
-aOl
+abM
aPA
avT
avT
@@ -62563,7 +63098,7 @@ vvH
vvH
fsA
gZX
-xlg
+abE
jUu
xGP
anm
@@ -63346,7 +63881,7 @@ mAx
ndm
rQN
aoX
-soN
+aaB
ojv
oTu
oTu
@@ -64629,7 +65164,7 @@ aoX
ali
yds
yds
-aon
+abI
aoX
rJw
tkr
@@ -64864,10 +65399,10 @@ avT
avT
xUL
rTG
-sIn
+abC
kxU
sdH
-sIn
+abD
kxU
pyw
nYZ
@@ -65145,7 +65680,7 @@ yds
yds
qWL
aoX
-gsM
+abJ
tkr
iPX
rQJ
@@ -65670,7 +66205,7 @@ ayA
sNK
xmo
rqW
-mzB
+abL
rQJ
szG
aHG
@@ -66417,7 +66952,7 @@ xUL
xUL
xUL
tmO
-fYx
+aaA
oDm
tmO
rhX
@@ -66687,7 +67222,7 @@ nrJ
iAR
rik
xWq
-aAL
+abK
gxi
wEP
wJH
@@ -67716,7 +68251,7 @@ xWq
xWq
xWq
tmO
-wje
+aaC
wje
tmO
ydp
@@ -68230,7 +68765,7 @@ xUL
xUL
xUL
tmO
-wje
+aaD
iPX
tmO
tmO
@@ -68488,7 +69023,7 @@ xUL
xUL
usE
buO
-wje
+aaE
cpC
tmO
ydp
@@ -71356,7 +71891,7 @@ avT
kfv
kfv
ilb
-ifQ
+aam
rlG
wSb
wav
@@ -72138,7 +72673,7 @@ wDk
pmK
dbB
nxv
-eZn
+abW
xBv
nQM
lZi
@@ -74711,7 +75246,7 @@ oJF
piv
nre
bWR
-xdr
+aan
uKb
fKC
rVN
@@ -75231,7 +75766,7 @@ cBD
bQj
gCG
sdN
-xXX
+acd
ubL
diH
uPJ
@@ -75481,7 +76016,7 @@ bDr
alG
fmt
cBD
-cbz
+aca
jae
bNS
pST
@@ -75746,7 +76281,7 @@ giT
bZF
xkT
bVR
-rYN
+acf
qOb
bSd
bXO
@@ -77261,7 +77796,7 @@ xZg
xZg
xZg
uBa
-eeh
+abN
grV
cTD
cTD
@@ -77271,7 +77806,7 @@ cTD
grV
lbp
knn
-eOK
+aaW
bBz
lbp
cBD
@@ -77491,7 +78026,7 @@ gky
ptY
cgH
ktw
-xZL
+aaG
lzB
avT
avT
@@ -77526,30 +78061,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
@@ -78262,7 +78797,7 @@ cPI
kxP
vAs
ktw
-xZL
+aaI
lzB
avT
avT
@@ -78277,7 +78812,7 @@ wxT
bUP
fLK
rmN
-oLT
+aaK
ljL
uBa
uBa
@@ -78298,19 +78833,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
@@ -78322,7 +78857,7 @@ ceA
vun
lhQ
lhQ
-ceA
+abm
bPc
ceA
bUL
@@ -78546,7 +79081,7 @@ piX
hJw
kop
uBa
-fuy
+abO
bwx
bwx
bwx
@@ -79060,7 +79595,7 @@ fWE
wbE
wbE
uBa
-rcH
+abP
bwx
iSo
bpM
@@ -80606,8 +81141,8 @@ tHU
bBL
guv
bpO
-bDR
-gfF
+aaL
+abR
bDR
jOl
bBL
@@ -80845,13 +81380,13 @@ iaO
dnm
hHC
dnm
-unA
+aaJ
unA
unA
unA
unA
dnm
-unA
+aaJ
dnm
unA
unA
@@ -80868,7 +81403,7 @@ bsx
bLT
bLT
bLT
-xhH
+aaV
rle
cSG
bCQ
@@ -81123,7 +81658,7 @@ vAs
vAs
vAs
bLT
-fnu
+aaN
bxR
mPM
ohK
@@ -81143,7 +81678,7 @@ bQC
gsK
wuB
pyI
-bXW
+acg
eqZ
wpN
vOV
@@ -81301,7 +81836,7 @@ dvs
mtP
naE
mtP
-mtP
+aaU
nOY
mtP
naE
@@ -81380,7 +81915,7 @@ vAs
vAs
vAs
bLT
-xou
+aaQ
jkL
fcJ
cqd
@@ -81553,7 +82088,7 @@ ydp
avT
avT
iHM
-iHM
+pgp
pgp
pgp
pgp
@@ -81808,11 +82343,11 @@ xUL
ydp
ydp
ydp
-avT
bmX
avT
pgp
-pCj
+aab
+dZV
dZV
gLk
pgp
@@ -81898,7 +82433,7 @@ bEi
bEi
lbp
bAs
-nmY
+aaZ
bCL
bDW
gpp
@@ -82067,9 +82602,9 @@ ydp
ydp
ydp
avT
-avT
pgp
-hGM
+aac
+gLk
gLk
gLk
pgp
@@ -82323,10 +82858,10 @@ ydp
ydp
ydp
ydp
-ydp
avT
pgp
-vlz
+aab
+aad
gLk
fBs
pgp
@@ -82417,11 +82952,11 @@ aGl
bEa
pHl
aaw
-gKB
+abh
qJV
fjU
fjU
-fjU
+acb
qJV
fuG
qJV
@@ -82581,7 +83116,7 @@ ydp
ydp
ydp
avT
-avT
+pgp
pgp
pgp
pgp
@@ -82840,7 +83375,7 @@ ydp
avT
ydp
pgp
-ugr
+aae
pBh
gLk
pgp
@@ -82939,7 +83474,7 @@ tRe
tRe
tRe
bWf
-bVa
+ihL
kXG
sqx
owj
@@ -83099,7 +83634,7 @@ ydp
pgp
pgp
pgp
-eEa
+aaf
pgp
pgp
pgp
@@ -83372,8 +83907,8 @@ skZ
mSt
geO
cQv
-nGa
-fpW
+aaj
+aak
oyf
dzS
dSQ
@@ -83620,7 +84155,7 @@ mWy
pgp
uEG
dKn
-gEz
+abA
pax
sdq
iux
@@ -83704,13 +84239,13 @@ dFp
wTK
tDY
oXn
-cSg
+abY
tRe
egg
cbQ
iXG
bWf
-bVa
+acc
bVa
bWf
ftV
@@ -84205,7 +84740,7 @@ bvq
oCZ
lxV
dGP
-evr
+abS
lxV
hJE
cmC
@@ -84649,7 +85184,7 @@ iML
kFr
vuO
vaj
-rTv
+aau
mSt
dWt
fyr
@@ -85400,7 +85935,7 @@ xUL
xUL
xUL
kVO
-bQf
+aao
qgm
qgm
qgm
@@ -85417,7 +85952,7 @@ xJB
hyK
vVN
qeL
-oiX
+abn
trU
knI
oIb
@@ -85659,7 +86194,7 @@ xUL
qaO
gct
sGE
-tJL
+aaq
ixf
ixf
giv
@@ -86192,7 +86727,7 @@ iqZ
seG
tYT
qKA
-cSv
+aav
pJS
pJS
tQG
@@ -86442,7 +86977,7 @@ mKv
sAh
sAh
sAh
-urI
+aar
uEz
uEz
hrS
@@ -86685,7 +87220,7 @@ xUL
xUL
xUL
kVO
-qAq
+aap
acq
fJc
lfy
@@ -87206,7 +87741,7 @@ wAx
wuQ
vnM
wAx
-mQo
+abv
mbE
qss
sYv
@@ -87483,7 +88018,7 @@ mhq
bNF
wIA
hTO
-noB
+aai
wIA
kti
nrg
@@ -88489,7 +89024,7 @@ hAw
skK
vKa
gdg
-pkh
+aaa
loM
vKa
nsv
@@ -88510,7 +89045,7 @@ pJS
leq
qxT
wIA
-iCO
+abp
pJS
pJS
pJS
@@ -89014,12 +89549,12 @@ fTy
jvb
xZp
dVr
-gRS
+abx
msK
cKk
dNB
rmV
-dDf
+abB
gaf
pMD
shN
@@ -89272,7 +89807,7 @@ stW
iKV
hFj
oNv
-guV
+abz
cKk
meG
mcU
@@ -90305,7 +90840,7 @@ jHT
rkd
mcU
rNS
-vyf
+aax
vyf
hLQ
nsf
@@ -90322,7 +90857,7 @@ gwY
pdD
hMM
qKP
-tQd
+abF
jIt
avT
avT
@@ -90568,7 +91103,7 @@ vkk
qSi
vkk
vkk
-pUz
+aay
pqj
mcU
pqj
@@ -91061,7 +91596,7 @@ pCU
ixf
kcn
llu
-xve
+abw
gJP
eGi
mIe
@@ -91339,7 +91874,7 @@ uqy
yes
iqH
iqH
-iqH
+aaz
iqH
yes
iqH
@@ -92095,10 +92630,10 @@ gcY
xop
fbq
lFv
-dvh
+aag
gkl
eOt
-eFy
+aby
rYc
hbb
rkd
@@ -92358,7 +92893,7 @@ cKk
cKk
cKk
cKk
-mkm
+aat
lpl
xcA
srk
@@ -93902,7 +94437,7 @@ fPd
eYu
xOj
jKF
-jKb
+abo
wdR
sda
pAC
@@ -94927,7 +95462,7 @@ wTe
sPt
iBL
bnU
-fNd
+aas
bDg
fKE
bnU
@@ -96980,7 +97515,7 @@ ulr
jJb
xfH
puE
-rFQ
+aah
iiY
piR
tty
@@ -97497,7 +98032,7 @@ xUL
xUL
dKF
ijZ
-ijZ
+lwl
bnU
oJa
cNE
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index ba1711d0ed..a123ccab55 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -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" = (
@@ -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,
@@ -17249,6 +17249,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)
@@ -58911,7 +58915,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/shuttles/arrival_delta.dmm b/_maps/shuttles/arrival_delta.dmm
index 16fc34e62b..c7d331e368 100644
--- a/_maps/shuttles/arrival_delta.dmm
+++ b/_maps/shuttles/arrival_delta.dmm
@@ -307,7 +307,7 @@
"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)
diff --git a/_maps/shuttles/arrival_omega.dmm b/_maps/shuttles/arrival_omega.dmm
index decb5f9d52..9285a4a716 100644
--- a/_maps/shuttles/arrival_omega.dmm
+++ b/_maps/shuttles/arrival_omega.dmm
@@ -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/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/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index c9e03389f1..035563627f 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"
@@ -140,6 +142,11 @@
#define CUSTOM_SKINTONE 24 //adds a "_g" suffix to bodypart overlays icon states if a custom skintone is used.
#define HORNCOLOR 25
#define WINGCOLOR 26
+#define CAN_SCAR 27 // If this species can be scarred (fleshy)
+
+/// Used for determining which wounds are applicable to this species.
+#define HAS_FLESH 28 /// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD)
+#define HAS_BONE 29 /// if we have bones (can suffer bone wounds)
//organ slots
#define ORGAN_SLOT_BRAIN "brain"
@@ -184,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 7daf9fa8a3..0734feaa42 100644
--- a/code/__DEFINES/_flags/_flags.dm
+++ b/code/__DEFINES/_flags/_flags.dm
@@ -138,10 +138,6 @@ 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)
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 b3b65bcf59..26e764c45b 100644
--- a/code/__DEFINES/_flags/item_flags.dm
+++ b/code/__DEFINES/_flags/item_flags.dm
@@ -52,4 +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<<5) //is a snack? :D
\ No newline at end of file
+#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/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 dff52f4748..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.
@@ -281,7 +281,7 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
/// 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
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 5c28694005..6900f36a33 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -32,6 +32,8 @@
#define COMSIG_ELEMENT_DETACH "element_detach"
// /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)
@@ -207,6 +209,8 @@
#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)
#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client)
@@ -250,7 +254,14 @@
#define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
-// /mob/living/carbon signals
+// /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
@@ -347,10 +358,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
@@ -360,6 +371,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)
@@ -442,6 +454,9 @@
#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/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 90c7c34f8d..d66521d945 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -65,9 +65,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))
@@ -75,13 +74,12 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismush(A) (is_species(A, /datum/species/mush))
#define isshadow(A) (is_species(A, /datum/species/shadow))
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
+#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))
@@ -202,21 +200,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..71de692410 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -38,6 +38,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/misc.dm b/code/__DEFINES/misc.dm
index 2ec21c83b3..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
@@ -434,6 +435,9 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#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.
@@ -534,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 42139cdeda..782095f883 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,6 +59,7 @@
#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'
@@ -103,12 +106,14 @@
#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
@@ -171,6 +176,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
@@ -279,6 +293,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
@@ -305,6 +320,7 @@
#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
@@ -315,4 +331,4 @@
#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
\ No newline at end of file
+#define EXAMINE_MORE_TIME 1 SECONDS
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/pool.dm b/code/__DEFINES/pool.dm
index 1e66109dc7..64bbd20b19 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.
))
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/status_effects.dm b/code/__DEFINES/status_effects.dm
index 4225581018..9a3b5d55f4 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,11 @@
#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
+
+/// 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/subsystems.dm b/code/__DEFINES/subsystems.dm
index bf76f8a523..7a188281d0 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
@@ -152,14 +153,17 @@
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();\
+ A.add_overlays = null;\
}\
if(LAZYLEN(po)){\
A.overlays |= po;\
}\
+ else{\
+ A.priority_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 eb86c52301..e8f584cf75 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -178,6 +178,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"
@@ -202,7 +203,7 @@
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
#define TRAIT_MUTATION_STASIS "mutation_stasis" //Prevents processed genetics mutations from processing.
#define TRAIT_FAST_PUMP "fast_pump"
-#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)
@@ -228,7 +229,7 @@
#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"
diff --git a/code/__DEFINES/vv.dm b/code/__DEFINES/vv.dm
index 889e1bb1c0..101330cc8b 100644
--- a/code/__DEFINES/vv.dm
+++ b/code/__DEFINES/vv.dm
@@ -76,6 +76,13 @@
#define VV_HK_ADDCOMPONENT "addcomponent"
#define VV_HK_MODIFY_TRAITS "modtraits"
+// /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"
#define VV_HK_ADD_REAGENT "addreagent"
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/_logging.dm b/code/__HELPERS/_logging.dm
index 1935dcc8a5..62e6c4daf9 100644
--- a/code/__HELPERS/_logging.dm
+++ b/code/__HELPERS/_logging.dm
@@ -81,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"]")
@@ -118,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]")
@@ -131,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]")
@@ -190,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 dce4d554b7..a688d20451 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)
@@ -125,3 +119,20 @@ GLOBAL_VAR_INIT(cmp_field, "name")
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_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]")
\ No newline at end of file
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/game.dm b/code/__HELPERS/game.dm
index 8d7941fdf8..b9f180ac4a 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -53,6 +53,27 @@
for(var/I in adjacent_turfs)
. |= get_area(I)
+/**
+ * Get a bounding box of a list of atoms.
+ *
+ * Arguments:
+ * - atoms - List of atoms. Can accept output of view() and range() procs.
+ *
+ * Returns: list(x1, y1, x2, y2)
+ */
+/proc/get_bbox_of_atoms(list/atoms)
+ var/list/list_x = list()
+ var/list/list_y = list()
+ for(var/_a in atoms)
+ var/atom/a = _a
+ list_x += a.x
+ list_y += a.y
+ return list(
+ min(list_x),
+ min(list_y),
+ max(list_x),
+ max(list_y))
+
// Like view but bypasses luminosity check
/proc/get_hear(range, atom/source)
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 0b5c60a95a..d66e83d651 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -90,7 +90,6 @@
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()
- INVOKE_ASYNC(GLOBAL_PROC, /proc/setupGenetics)
//creates every subtype of prototype (excluding prototype) and adds it to list L.
//if no list/L is provided, one is created.
@@ -117,24 +116,3 @@
GLOB.coin_values[path] = C.value
qdel(C)
-/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)
- 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
\ No newline at end of file
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index f8f6bca31a..c4964022e5 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -145,9 +145,9 @@
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))
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/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/_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 4c912b9c1e..a25381f266 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -116,15 +116,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"
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/logging.dm b/code/_globalvars/logging.dm
index 3bce9c560a..e9f98f836e 100644
--- a/code/_globalvars/logging.dm
+++ b/code/_globalvars/logging.dm
@@ -32,6 +32,8 @@ 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)
@@ -49,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/_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 01261677d9..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(mob_transforming)
- 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 0088dde15a..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)
@@ -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..ce7bc96c96 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)
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 bef06a69e9..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.
@@ -126,18 +149,18 @@
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,25 +189,21 @@
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
@@ -197,8 +215,18 @@
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)
@@ -210,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 059f9d518e..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,8 +126,8 @@
/*
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)
SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_ANIMAL, user)
@@ -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/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 f95ebf82b5..f8a14b8c30 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -123,7 +123,8 @@
. = ..()
if(!target || !user)
return
-
+ if(!user.CheckActionCooldown(CLICK_CD_MELEE))
+ return
if(!focus)
focus_object(target)
return
@@ -145,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 7e8b1c8f38..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
@@ -216,7 +216,7 @@
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
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/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/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 bbeb0683f0..ba2794d00f 100644
--- a/code/controllers/subsystem/chat.dm
+++ b/code/controllers/subsystem/chat.dm
@@ -31,19 +31,13 @@ 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]")
- if (trailing_newline)
- 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
@@ -55,6 +49,17 @@ SUBSYSTEM_DEF(chat)
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
@@ -74,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/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..97addfa131 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -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/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/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 765f0c8382..0bc4e6665a 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -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/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/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 ff04ceead9..a00b341b82 100644
--- a/code/datums/brain_damage/magic.dm
+++ b/code/datums/brain_damage/magic.dm
@@ -94,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/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/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/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/recipes/recipes_clothing.dm b/code/datums/components/crafting/recipes/recipes_clothing.dm
index 7a7379c834..2a24c0b451 100644
--- a/code/datums/components/crafting/recipes/recipes_clothing.dm
+++ b/code/datums/components/crafting/recipes/recipes_clothing.dm
@@ -263,6 +263,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 86d1e77661..0cb0547978 100644
--- a/code/datums/components/crafting/recipes/recipes_misc.dm
+++ b/code/datums/components/crafting/recipes/recipes_misc.dm
@@ -126,7 +126,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 +135,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)
@@ -324,6 +324,13 @@
result = /obj/item/toy/sword/cx
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/edible.dm b/code/datums/components/edible.dm
index 47e60a1ee1..dc2e490fe4 100644
--- a/code/datums/components/edible.dm
+++ b/code/datums/components/edible.dm
@@ -51,7 +51,8 @@ Behavior that's still missing from this component that original food items had t
var/atom/owner = parent
- owner.create_reagents(volume, INJECTABLE)
+ 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)
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 137a1bb864..51098756d3 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
@@ -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////////////////
////////////////////////////////////////
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/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/radioactive.dm b/code/datums/components/radioactive.dm
index f12e8bf007..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
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/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/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
index 77a9a79bf4..bcbf979101 100644
--- a/code/datums/components/twohanded.dm
+++ b/code/datums/components/twohanded.dm
@@ -105,6 +105,8 @@
/// 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
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index dde8961482..460a73bf5a 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)
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,18 @@ 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)
+ 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 +162,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 +183,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 +206,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 +224,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 +272,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 +289,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 +326,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/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/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/dna.dm b/code/datums/dna.dm
index 80059bece7..de5c1ece91 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,9 +133,9 @@
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)
L[DNA_MUTANTTAIL_BLOCK] = construct_block(GLOB.mam_tails_list.Find(features["mam_tail"]), GLOB.mam_tails_list.len)
@@ -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)
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/elements/embed.dm b/code/datums/elements/embed.dm
index 8a7acde9cb..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,7 +68,7 @@
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
@@ -79,13 +79,13 @@
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)
@@ -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..dc9569a4d5 100644
--- a/code/datums/explosion.dm
+++ b/code/datums/explosion.dm
@@ -196,14 +196,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/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/looping_sounds/_looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm
index f110d5e8ed..8bee4f3d1c 100644
--- a/code/datums/looping_sounds/_looping_sound.dm
+++ b/code/datums/looping_sounds/_looping_sound.dm
@@ -60,6 +60,7 @@
output_atoms -= remove_thing
if(init_timerid)
deltimer(init_timerid)
+ init_timerid = null
if(!timerid)
return
on_stop()
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/krav_maga.dm b/code/datums/martial/krav_maga.dm
index c2fe24a20d..3691b2fccc 100644
--- a/code/datums/martial/krav_maga.dm
+++ b/code/datums/martial/krav_maga.dm
@@ -223,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 a2a9e376e1..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!")
diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm
index 18fd8e7b18..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)
@@ -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)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index d02249fb38..cb99fdc5a3 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -66,6 +66,9 @@
/// 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(src)
src.key = key
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index f5692c297a..787d6375a7 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))
@@ -270,3 +274,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..8f98917ed3 100644
--- a/code/datums/mood_events/generic_positive_events.dm
+++ b/code/datums/mood_events/generic_positive_events.dm
@@ -196,3 +196,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 7e6d567cfa..bd9ecaeeaa 100644
--- a/code/datums/mutations/actions.dm
+++ b/code/datums/mutations/actions.dm
@@ -410,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/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/shuttles.dm b/code/datums/shuttles.dm
index d275684bba..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
diff --git a/code/datums/skills/_check_skills.dm b/code/datums/skills/_check_skills.dm
index d02a716b8a..91b36a123f 100644
--- a/code/datums/skills/_check_skills.dm
+++ b/code/datums/skills/_check_skills.dm
@@ -14,11 +14,14 @@
mind.skill_holder.ui_interact(src)
-/datum/skill_holder/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/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, ui_key, "skillpanel", "[owner.name]'s Skills", 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 = new(user, src, "SkillPanel", "[owner.name]'s Skills")
+ ui.set_autoupdate(FALSE)
ui.open()
else if(need_static_data_update)
update_static_data(user)
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 faed65e9c4..6e59d4fa2c 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -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."
@@ -144,7 +159,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.
@@ -173,13 +187,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
@@ -430,10 +440,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)
@@ -543,8 +562,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)
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index 12c223f500..461ae9c65d 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -90,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 //
////////////////
@@ -279,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 40b71eec0a..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")
@@ -337,10 +337,8 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
dumb_thing = FALSE //only once per life
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))
@@ -452,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..6cef7ac50f 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -53,11 +53,10 @@
/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
@@ -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)
@@ -135,21 +131,17 @@
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 +162,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 +173,5 @@
A.lights = mend
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
- if(usr)
- A.shock(usr, 50)
+ if(isliving(usr))
+ A.shock(usr, 50)
\ No newline at end of file
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 5d29ef1598..dfa9776489 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -70,6 +70,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()
@@ -101,6 +104,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)
@@ -142,6 +147,11 @@
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)
return ..()
@@ -217,7 +227,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)
@@ -741,7 +751,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()
@@ -930,6 +940,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)
@@ -950,15 +962,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)
@@ -982,6 +995,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)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 9736f473e8..0238529195 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
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..406e142a25 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,7 +223,6 @@ 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.")
@@ -278,7 +276,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 +303,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.\
- \
-
You're in a place called Reebe right now. The crew can't get here normally.
\
-
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.
\
-
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.
\
-
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.
\
- \
- \
- 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.
"
- 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 8a91c266a0..4fb39c04e1 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -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/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 2faf76ca94..4ba8d9f3d3 100644
--- a/code/game/machinery/computer/atmos_control.dm
+++ b/code/game/machinery/computer/atmos_control.dm
@@ -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/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("
"
- 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, "
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.
"
- 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)
@@ -164,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 += "
\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,54 +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/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)")
-
+
+ scan_turf(user, location)
+
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
. = ..()
@@ -666,7 +708,7 @@ GENETICS SCANNER
var/total_moles = air_contents.total_moles()
var/pressure = air_contents.return_pressure()
- var/volume = air_contents.return_volume()
+ var/volume = air_contents.return_volume() //could just do mixture.volume... but safety, I guess?
var/temperature = air_contents.return_temperature()
var/cached_scan_results = air_contents.analyzer_results
@@ -693,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
@@ -878,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 9d5b6d5b6c..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
@@ -186,11 +188,10 @@
tank_one.air_contents.merge(temp)
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
index 8c7049c713..e5e97d2b2b 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -23,6 +23,8 @@
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?
@@ -103,7 +105,7 @@
to_chat(user, "You lack the grace to wield this!")
return COMPONENT_TWOHANDED_BLOCK_WIELD
wielded = TRUE
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
w_class = w_class_on
total_mass = total_mass_on
hitsound = 'sound/weapons/blade1.ogg'
@@ -340,12 +342,30 @@
name = "divine lightblade"
desc = "A giant blade of bright and holy light, said to cut down the wicked with ease."
force = 5
- block_chance = 50
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, \
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
index 8d1fe4ebd1..9750994c87 100644
--- a/code/game/objects/items/electrostaff.dm
+++ b/code/game/objects/items/electrostaff.dm
@@ -15,6 +15,7 @@
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
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
index 41c1cbe915..6fb7b89262 100644
--- a/code/game/objects/items/fireaxe.dm
+++ b/code/game/objects/items/fireaxe.dm
@@ -13,10 +13,12 @@
slot_flags = ITEM_SLOT_BACK
attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut")
hitsound = 'sound/weapons/bladeslice.ogg'
- 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" = 30)
resistance_flags = FIRE_PROOF
+ wound_bonus = -15
+ bare_wound_bonus = 20
var/wielded = FALSE // track wielded status on item
/obj/item/fireaxe/Initialize()
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index f293e6579a..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)
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index 4ad71f7c46..609cc3b719 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
@@ -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.
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/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 d6396f9902..58146be20f 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -225,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
@@ -351,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")
@@ -451,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()
@@ -574,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
@@ -593,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
@@ -644,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
@@ -656,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()
@@ -696,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'
@@ -751,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")
@@ -779,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/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 20960da7c6..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
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index c6aa9f7bf4..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)
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..a7f7e3152c 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,14 +36,15 @@
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)
@@ -153,6 +156,51 @@
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/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(obj/choice,mob/living/M)
+ to_chat(M, "The box opens, revealing the [choice]!")
+ 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
+ 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/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/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 8b322d20cb..c6b5a7e224 100644
--- a/code/game/objects/items/pet_carrier.dm
+++ b/code/game/objects/items/pet_carrier.dm
@@ -24,6 +24,7 @@
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?
@@ -106,8 +107,9 @@
if(user == target)
to_chat(user, "Why would you ever do that?")
return
- if(ishostile(target) && !allows_hostiles && target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers
+ 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)
@@ -128,13 +130,18 @@
/obj/item/pet_carrier/container_resist(mob/living/user)
//don't do the whole resist timer thing if it's open!
if(open)
- loc.visible_message("[user] climbs out of [src]!", \
- "[user] jumps out of [src]!")
- remove_occupant(user)
- return
+ 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
- user.changeNext_move(CLICK_CD_BREAKOUT)
- user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.mob_size <= MOB_SIZE_SMALL)
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]!")
@@ -147,7 +154,7 @@
update_icon()
else
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 20 seconds.)")
+ 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)
@@ -180,21 +187,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, load_time))
- return
+ 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))
@@ -230,7 +238,8 @@
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 = 10 //half the time of a bluespace bodybag
+ escape_time = 200 //equal to the time of a bluespace bodybag
+ alternate_escape_time = 100
var/datum/gas_mixture/occupant_gas_supply
/obj/item/pet_carrier/bluespace/update_icon_state()
@@ -253,7 +262,8 @@
occupant_gas_supply = new
if(isanimal(occupant))
var/mob/living/simple_animal/animal = occupant
- occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature when their turf isnt a location
+ 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
else
if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside
ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist")
@@ -270,10 +280,15 @@
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/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
index 49d0b64498..b296e2d0cb 100644
--- a/code/game/objects/items/pitchfork.dm
+++ b/code/game/objects/items/pitchfork.dm
@@ -9,7 +9,7 @@
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("attacked", "impaled", "pierced")
hitsound = 'sound/weapons/bladeslice.ogg'
- 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" = 30)
resistance_flags = FIRE_PROOF
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 70426eac1c..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
@@ -755,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 1f69cdae2e..6513b53e1d 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -746,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"
@@ -755,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
@@ -792,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
@@ -812,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"
@@ -907,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 d33ecedf0a..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)
. = ..()
@@ -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)
. = ..()
@@ -566,7 +576,7 @@
/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 6bf0b27fb4..fc19e61cd6 100644
--- a/code/game/objects/items/sharpener.dm
+++ b/code/game/objects/items/sharpener.dm
@@ -39,7 +39,7 @@
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.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 154714b13f..4952c93928 100644
--- a/code/game/objects/items/shields.dm
+++ b/code/game/objects/items/shields.dm
@@ -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)
@@ -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/spear.dm b/code/game/objects/items/spear.dm
index 376362d7c3..f40c774551 100644
--- a/code/game/objects/items/spear.dm
+++ b/code/game/objects/items/spear.dm
@@ -15,13 +15,15 @@
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
+ 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()
. = ..()
@@ -177,7 +179,7 @@
custom_materials = null
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "poked", "jabbed", "torn", "gored")
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
icon_prefix = "bone_spear"
/obj/item/spear/bonespear/ComponentInitialize()
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..9ea8c9c689 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,51 @@
/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
-/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 +171,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 +189,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 +214,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 +225,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 +268,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 +312,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 +361,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 +377,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 +391,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/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index d4baea2487..29b4dea6d8 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -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/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 3ca7137548..5f6341ea21 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( \
@@ -244,8 +244,10 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
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), \
@@ -287,7 +289,7 @@ 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.
@@ -349,7 +351,7 @@ GLOBAL_LIST_INIT(bamboo_recipes, list ( \
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()
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 16b46567c7..3e2bb675fa 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -25,9 +25,18 @@
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
@@ -224,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)]")
@@ -389,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/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/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 2831311eff..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
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index 4fa742df46..3c554aa58e 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,
@@ -181,7 +182,8 @@
/obj/item/implant,
/obj/item/implanter,
/obj/item/pinpointer/crew,
- /obj/item/reagent_containers/chem_pack
+ /obj/item/reagent_containers/chem_pack,
+ /obj/item/stack/sticky_tape //surgical tape
))
/obj/item/storage/belt/medical/surgery_belt_adv
@@ -444,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()
. = ..()
@@ -467,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,
@@ -488,7 +491,8 @@
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()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
@@ -811,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 5d5f0eaa24..7532aacbfa 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -104,7 +104,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!")
@@ -238,11 +238,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/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 927a29407c..cde6f5bd5a 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -168,13 +168,19 @@
. += "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.")
@@ -398,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 d7065df0f0..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)
@@ -416,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,
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 fd50bd022f..ed0ee8ad07 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -20,6 +20,8 @@ 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"
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index 3b66e32d0a..442228ef31 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -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/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index e69b2b6272..08b91332ef 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -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
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/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 9560f7fab3..2e12a2ab8c 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 bf1eca01f9..4e82df2452 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -447,7 +447,7 @@
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/dualsaber/toy/ComponentInitialize()
AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg')
@@ -466,7 +466,7 @@
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
slowdown_wielded = 0
- sharpness = IS_BLUNT
+ sharpness = SHARP_NONE
/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')
@@ -574,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)
@@ -811,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)
@@ -1234,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/weaponry.dm b/code/game/objects/items/weaponry.dm
index 7524bb93e1..e7dc636cf3 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,174 @@ 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."
+ 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/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 = 9
+ 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 = 100
+ 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.5 // 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)
+
+/obj/item/melee/bokken/attack_self(mob/user)
+ harm = !harm
+ if(harm)
+ force -= 2
+ 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 += 2
+ 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,6 +428,7 @@ 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))
@@ -297,13 +466,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 +485,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 +522,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 +530,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 +631,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
@@ -574,6 +743,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 +760,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 +797,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 +878,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."
@@ -772,7 +1030,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
block_chance = 40
throwforce = 20
throw_speed = 4
- sharpness = IS_SHARP
+ sharpness = SHARP_EDGED
attack_verb = list("cut", "sliced", "diced")
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm
index 1203c5a1df..14017ffb2d 100644
--- a/code/game/objects/obj_defense.dm
+++ b/code/game/objects/obj_defense.dm
@@ -105,15 +105,19 @@
/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
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index ba3eba9bd3..79dd13b0ae 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()
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index d30f617919..b758317fe2 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].")
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 299ba7b659..1316f45530 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -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!")
@@ -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))
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index a4ee2f16e2..45cac650b8 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -311,10 +311,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..043232e9e3 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)
@@ -458,10 +459,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 +504,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 +512,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/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/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 bcf1016c1e..412730910f 100644
--- a/code/game/objects/structures/fireaxe.dm
+++ b/code/game/objects/structures/fireaxe.dm
@@ -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 ce78b92f38..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
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/grille.dm b/code/game/objects/structures/grille.dm
index 20151a0bdb..36e4f825da 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
@@ -99,11 +101,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,8 +112,9 @@
take_damage(rand(5,10), BRUTE, "melee", 1)
/obj/structure/grille/attack_alien(mob/living/user)
+ if(!user.CheckActionCooldown(CLICK_CD_MELEE))
+ return
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)
@@ -134,7 +136,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 65d930e08b..6aed11701d 100644
--- a/code/game/objects/structures/headpike.dm
+++ b/code/game/objects/structures/headpike.dm
@@ -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 c49159a992..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)
@@ -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 dc4a741b8b..10a9f2afd4 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -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/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/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 777be608b5..a553e63b0f 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]...")
@@ -138,6 +143,22 @@
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)
@@ -191,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)
@@ -553,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)
@@ -577,7 +600,7 @@
buildstack = /obj/item/stack/tile/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)
@@ -606,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].")
@@ -635,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)
. = ..()
@@ -676,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 ba23878168..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)
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 36539ae1e4..cf68341b2c 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
@@ -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.")
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index acb88fbb1d..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))
@@ -167,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
@@ -174,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
@@ -492,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
@@ -707,8 +705,7 @@
icon_state = "puddle"
resistance_flags = UNACIDABLE
-//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"
@@ -784,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 17031a51df..3373278c0c 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
@@ -836,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
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index 65b487bd05..b78826b23b 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -83,7 +83,7 @@
. = ..()
if(.)
switch(var_name)
- if("icon")
+ if(NAMEOF(src, icon))
SStitle.icon = icon
/turf/closed/indestructible/riveted
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index bdca384bd0..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)
diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm
index f940761ff8..946401ba18 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)
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..8e0230a2b0 100644
--- a/code/game/turfs/simulated/floor/mineral_floor.dm
+++ b/code/game/turfs/simulated/floor/mineral_floor.dm
@@ -149,7 +149,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 +202,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/plating.dm b/code/game/turfs/simulated/floor/plating.dm
index f26a4b827a..ac80bddd00 100644
--- a/code/game/turfs/simulated/floor/plating.dm
+++ b/code/game/turfs/simulated/floor/plating.dm
@@ -124,7 +124,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/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/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm
index a5f0d5e824..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()
. = ..()
@@ -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/reinf_walls.dm b/code/game/turfs/simulated/wall/reinf_walls.dm
index a1d2c1757c..6b41f41763 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))
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index b01a1df2c0..b020ab87c9 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
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index b131a1ed70..0e028ed4af 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -133,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
@@ -170,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 b1a10c72ce..55d945535d 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -122,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)
diff --git a/code/game/world.dm b/code/game/world.dm
index db193f31b0..55333fb3e6 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -131,11 +131,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
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..718f9d4246 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*/
diff --git a/code/modules/admin/chat_commands.dm b/code/modules/admin/chat_commands.dm
index 7664d85b7d..bab74300f5 100644
--- a/code/modules/admin/chat_commands.dm
+++ b/code/modules/admin/chat_commands.dm
@@ -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/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 += "
"
+ 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 044016698c..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
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 14cf0d7ee2..b93c8dabf1 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -371,8 +371,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..68b9a8e341 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 = stripped_multiline_input(src,"Message:", "Private message to [key_name(C, 0, 0)]")
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 = stripped_multiline_input(src,"Message:", "Private message to Administrator")
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 = stripped_multiline_input(src,"Message:", "Private message to [key_name(recipient, 0, 0)]")
msg = trim(msg)
if(!msg)
return
@@ -191,7 +191,7 @@
spawn() //so we don't hold the caller proc up
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 = stripped_multiline_input(recipient, msg,"Admin PM from-[sendername]", "") //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/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index b3bea2201c..6f8e9e703f 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -22,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/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index 9fa8145339..8bff37ab03 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -23,6 +23,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
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/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 += "
"
- 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..9a82bb546b 100644
--- a/code/modules/antagonists/blob/blob.dm
+++ b/code/modules/antagonists/blob/blob.dm
@@ -2,6 +2,7 @@
name = "Blob"
roundend_category = "blobs"
antagpanel_category = "Blob"
+ show_to_ghosts = TRUE
job_rank = ROLE_BLOB
threat = 20
var/datum/action/innate/blobpop/pop_action
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..a81f702a75 100644
--- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
+++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm
@@ -10,26 +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)
+/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
FreeAllVassals() // Free my Vassals! (if I haven't yet)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -272,13 +270,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
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/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/mesmerize.dm b/code/modules/antagonists/bloodsucker/powers/mesmerize.dm
index fccef4fb0c..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.mob_transforming = 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.mob_transforming = 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 cad3eeb88b..56b72a562e 100644
--- a/code/modules/antagonists/bloodsucker/powers/trespass.dm
+++ b/code/modules/antagonists/bloodsucker/powers/trespass.dm
@@ -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.mob_transforming = 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.mob_transforming = FALSE
user.density = 1
user.invisibility = invis_was
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 3267f2bdc1..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
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/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/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_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/_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 3bc237fc56..79b919b1e9 100644
--- a/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
+++ b/code/modules/antagonists/clockcult/clock_mobs/clockwork_marauder.dm
@@ -124,3 +124,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..00c4d73428 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 = 15 // 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.
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"
@@ -192,43 +191,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 +232,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,7 +251,7 @@
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
@@ -293,3 +279,50 @@
sort_priority = 11
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 = 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)
\ 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..8819544928 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."
@@ -487,3 +459,26 @@
invoker.light_range = 0
invoker.update_light()
return ..()
+
+//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 = 1
+ 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
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/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 5b2dd7d007..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")
@@ -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"
@@ -254,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
@@ -704,7 +708,7 @@
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
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/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index 7d7031dad4..272b154828 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -144,7 +144,7 @@
/mob/living/carbon/true_devil/resist_fire()
//They're immune to fire.
-/mob/living/carbon/true_devil/attack_hand(mob/living/carbon/human/M)
+/mob/living/carbon/true_devil/on_attack_hand(mob/living/carbon/human/M)
. = ..()
if(.)
switch(M.a_intent)
diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm
index 7de0330ad6..b8e906064c 100644
--- a/code/modules/antagonists/disease/disease_datum.dm
+++ b/code/modules/antagonists/disease/disease_datum.dm
@@ -2,6 +2,7 @@
name = "Sentient Disease"
roundend_category = "diseases"
antagpanel_category = "Disease"
+ show_to_ghosts = TRUE
var/disease_name = ""
/datum/antagonist/disease/on_gain()
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index e876beb5dc..6a05d07b38 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -291,16 +291,19 @@ the new instance inside the host to be updated to the template's stats.
/mob/camera/disease/ClickOn(var/atom/A, params)
if(freemove && ishuman(A))
- var/mob/living/carbon/human/H = A
- 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.")
+ 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/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 d0ef5a83ce..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
@@ -112,7 +113,7 @@
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
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..3ae9cfcfb0 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -34,8 +34,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 +46,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 +73,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..b7503f4b22 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
@@ -158,10 +158,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 +400,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 +487,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 +498,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 +518,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/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 2701a2d006..d8a8e9a1be 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -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)
diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm
index ab043ef1c9..d4d117f8ee 100644
--- a/code/modules/antagonists/wizard/equipment/spellbook.dm
+++ b/code/modules/antagonists/wizard/equipment/spellbook.dm
@@ -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."
@@ -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
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index 70adafd3fb..7263793f7f 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()
diff --git a/code/modules/antagonists/xeno/xeno.dm b/code/modules/antagonists/xeno/xeno.dm
index 7c4c5351df..2cc8e34b99 100644
--- a/code/modules/antagonists/xeno/xeno.dm
+++ b/code/modules/antagonists/xeno/xeno.dm
@@ -12,6 +12,7 @@
name = "Xenomorph"
job_rank = ROLE_ALIEN
show_in_antagpanel = FALSE
+ show_to_ghosts = TRUE
var/datum/team/xeno/xeno_team
threat = 3
diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm
index 4d2e5e6fef..8f88076af9 100644
--- a/code/modules/arousal/genitals.dm
+++ b/code/modules/arousal/genitals.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/assembly/bomb.dm b/code/modules/assembly/bomb.dm
index 36c444f02d..1c814fa193 100644
--- a/code/modules/assembly/bomb.dm
+++ b/code/modules/assembly/bomb.dm
@@ -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
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 += "