diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index c00e2688f1..e14c5d1624 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -111,6 +111,9 @@ The use of the : operator to override type safety checks is not allowed. You mus
### Type paths must begin with a /
eg: `/datum/thing`, not `datum/thing`
+### Type paths must be lowercase
+eg: `/datum/thing/blue`, not `datum/thing/BLUE` or `datum/thing/Blue`
+
### Datum type paths must began with "datum"
In DM, this is optional, but omitting it makes finding definitions harder.
@@ -240,6 +243,8 @@ This prevents nesting levels from getting deeper then they need to be.
* Queries must never specify the database, be it in code, or in text files in the repo.
+* Primary keys are inherently immutable and you must never do anything to change the primary key of a row or entity. This includes preserving auto increment numbers of rows when copying data to a table in a conversion script. No amount of bitching about gaps in ids or out of order ids will save you from this policy.
+
### Mapping Standards
* TGM Format & Map Merge
* All new maps submitted to the repo through a pull request must be in TGM format (unless there is a valid reason present to have it in the default BYOND format.) This is done using the [Map Merge](https://github.com/tgstation/tgstation/wiki/Map-Merger) utility included in the repo to convert the file to TGM format.
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
deleted file mode 100644
index 949f1c4c44..0000000000
--- a/.github/ISSUE_TEMPLATE.md
+++ /dev/null
@@ -1,9 +0,0 @@
-[Round ID]: # (If you discovered this issue from playing tgstation hosted servers:)
-[Round ID]: # (**INCLUDE THE ROUND ID**)
-[Round ID]: # (It can be found in the Status panel or retrieved from https://atlantaned.space/statbus/round.php ! The round id let's us look up valuable information and logs for the round the bug happened.)
-
-[Testmerges]: # (If you believe the issue to be caused by a test merge [OOC tab -> Show Server Revision], report it in the pull request's comment section instead.)
-
-[Reproduction]: # (Explain your issue in detail, including the steps to reproduce it. Issues without proper reproduction steps or explanation are open to being ignored/closed by maintainers.)
-
-[For Admins]: # (Oddities induced by var-edits and other admin tools are not necessarily bugs. Verify that your issues occur under regular circumstances before reporting them.)
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000000..09f99f6c85
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,20 @@
+---
+name: Bug report
+about: Create a report to help reproduce and fix the issue
+---
+
+## Round ID:
+
+
+
+## Testmerges:
+
+
+
+## Reproduction:
+
+
+
+
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000..2c9eb90c72
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,7 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+
+---
+
+Please be aware that feature discussions most often take place on the Citadel Station Discord and should not be requested here.
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 7855fd5782..f204eb0a72 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,6 +1,16 @@
-[Changelogs]: # (Your PR should contain a detailed changelog of notable changes, titled and categorized appropriately. This includes, new features, sprites, sounds, balance changes, admin tools, map edits, removals, big refactors, config changes, hosting changes and important fixes. An example changelog has been provided below for you to edit. If you need additional help, read https://github.com/tgstation/tgstation/wiki/Changelogs)
+
+
-:cl: optional name here
+## About The Pull Request
+
+
+
+## Why It's Good For The Game
+
+
+
+## Changelog
+:cl:
add: Added new things
add: Added more things
del: Removed old things
@@ -19,4 +29,5 @@ admin: messed with admin stuff
server: something server ops should know
/:cl:
-[why]: # (Please add a short description [two lines down] of why you think these changes would benefit the game. If you can't justify it in words, it might not be worth adding.)
+
+
diff --git a/.travis.yml b/.travis.yml
index 7138b23354..bef3a69ad7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
language: generic
sudo: false
+dist: xenial
branches:
except:
- ___TGS3TempBranch
@@ -14,6 +15,7 @@ matrix:
packages:
- python3
- python3-pip
+ - python3-setuptools
cache:
directories:
- tgui/node_modules
@@ -43,7 +45,8 @@ matrix:
- gcc-multilib
- g++-7
- g++-7-multilib
- - libmariadbclient-dev:i386
+ - libmariadb-client-lgpl-dev:i386
+ - libmariadbd-dev
cache:
directories:
- $HOME/.cargo
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
index b3a0289761..738148c948 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm
@@ -209,6 +209,8 @@
dir = 8
},
/obj/item/malf_upgrade,
+/obj/item/disk/tech_disk/illegal,
+/obj/structure/safe,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/ruin/unpowered/ash_walkers)
"aB" = (
diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
index ba291fc258..945ea515c7 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_seed_vault.dmm
@@ -272,7 +272,13 @@
/obj/machinery/light,
/turf/open/floor/plasteel/freezer,
/area/ruin/powered/seedvault)
-
+"Z" = (
+/obj/item/disk/design_disk/plant_disk,
+/obj/machinery/autolathe/hacked{
+ desc = "This autolathe seems to have its safety light off."
+ },
+/turf/open/floor/plasteel/freezer,
+/area/ruin/powered/seedvault)
(1,1,1) = {"
a
a
@@ -375,7 +381,7 @@ h
h
u
R
-u
+Z
Q
a
a
diff --git a/_maps/RandomRuins/SpaceRuins/arcade.dmm b/_maps/RandomRuins/SpaceRuins/arcade.dmm
new file mode 100644
index 0000000000..771c33c55b
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/arcade.dmm
@@ -0,0 +1,711 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/turf/open/floor/plating/asteroid,
+/area/ruin/powered)
+"c" = (
+/turf/closed/mineral/random/high_chance,
+/area/ruin/powered)
+"d" = (
+/turf/closed/wall/mineral/titanium/survival/pod,
+/area/ruin/powered)
+"e" = (
+/obj/machinery/computer/arcade,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"f" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/vending/coffee,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"g" = (
+/obj/item/coin,
+/obj/item/toy/plush/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"h" = (
+/obj/effect/mob_spawn/human/corpse/assistant,
+/obj/effect/decal/cleanable/blood,
+/obj/item/toy/plush/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"i" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/obj/item/toy/plush/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"j" = (
+/obj/machinery/light{
+ dir = 8
+ },
+/turf/open/floor/engine,
+/area/ruin/powered)
+"k" = (
+/obj/item/coin/gold,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"l" = (
+/turf/open/floor/engine,
+/area/ruin/powered)
+"m" = (
+/obj/item/coin/iron,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"n" = (
+/obj/item/toy/plush/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"o" = (
+/obj/item/kitchen/knife{
+ pixel_x = 5;
+ pixel_y = 11
+ },
+/obj/item/toy/plush/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"p" = (
+/turf/closed/wall/mineral/titanium/survival/nodiagonal,
+/area/ruin/powered)
+"q" = (
+/turf/open/floor/light/colour_cycle/dancefloor_b,
+/area/ruin/powered)
+"r" = (
+/turf/open/floor/light/colour_cycle/dancefloor_a,
+/area/ruin/powered)
+"s" = (
+/obj/machinery/door/airlock/external/glass,
+/obj/structure/fans/tiny,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"t" = (
+/obj/item/trash/chips,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"u" = (
+/obj/item/trash/cheesie,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"v" = (
+/obj/item/coin,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"w" = (
+/obj/item/coin/diamond,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"x" = (
+/obj/machinery/jukebox/disco/indestructible,
+/turf/open/floor/light/colour_cycle/dancefloor_b,
+/area/ruin/powered)
+"y" = (
+/obj/machinery/light,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"z" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/turf/open/floor/engine,
+/area/ruin/powered)
+"A" = (
+/obj/machinery/door/airlock/external/glass,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"B" = (
+/obj/machinery/vending/cola/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"C" = (
+/obj/machinery/vending/snack/random,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"D" = (
+/obj/item/trash/can,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"E" = (
+/obj/item/trash/sosjerky,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"F" = (
+/obj/structure/closet/crate/trashcart,
+/turf/open/floor/plating/asteroid,
+/area/ruin/powered)
+"G" = (
+/obj/structure/chair/sofa/right,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"H" = (
+/obj/structure/chair/sofa/left,
+/obj/item/bedsheet/ian,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"I" = (
+/obj/item/aiModule/toyAI,
+/turf/open/floor/engine,
+/area/ruin/powered)
+"J" = (
+/obj/item/twohanded/dualsaber/toy,
+/turf/open/floor/light/colour_cycle/dancefloor_b,
+/area/ruin/powered)
+"K" = (
+/obj/item/gun/energy/pumpaction/toy,
+/turf/open/floor/engine,
+/area/ruin/powered)
+
+(1,1,1) = {"
+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
+b
+b
+b
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(3,1,1) = {"
+a
+a
+a
+b
+b
+b
+b
+b
+b
+b
+b
+a
+a
+a
+b
+b
+b
+b
+a
+a
+"}
+(4,1,1) = {"
+a
+a
+a
+b
+b
+b
+b
+b
+b
+b
+b
+a
+a
+b
+b
+b
+b
+b
+b
+a
+"}
+(5,1,1) = {"
+a
+a
+a
+b
+b
+c
+c
+c
+c
+b
+b
+b
+b
+b
+b
+c
+c
+c
+b
+b
+"}
+(6,1,1) = {"
+a
+a
+a
+b
+c
+c
+c
+c
+c
+b
+b
+b
+b
+c
+c
+c
+c
+c
+c
+b
+"}
+(7,1,1) = {"
+a
+a
+a
+b
+c
+c
+d
+d
+d
+d
+d
+d
+d
+d
+d
+d
+c
+c
+c
+b
+"}
+(8,1,1) = {"
+a
+a
+a
+b
+c
+c
+d
+e
+j
+l
+l
+K
+j
+G
+B
+d
+c
+c
+b
+b
+"}
+(9,1,1) = {"
+a
+a
+a
+b
+c
+c
+d
+e
+k
+l
+v
+l
+l
+H
+C
+d
+c
+c
+b
+a
+"}
+(10,1,1) = {"
+a
+a
+b
+b
+c
+c
+d
+e
+l
+I
+l
+l
+l
+k
+B
+d
+c
+c
+b
+a
+"}
+(11,1,1) = {"
+a
+a
+b
+c
+c
+c
+d
+e
+l
+l
+w
+l
+y
+d
+d
+p
+c
+b
+b
+a
+"}
+(12,1,1) = {"
+a
+a
+b
+c
+c
+c
+d
+e
+m
+J
+r
+q
+l
+A
+l
+s
+b
+b
+b
+a
+"}
+(13,1,1) = {"
+a
+b
+b
+c
+c
+c
+d
+f
+l
+r
+x
+r
+l
+d
+d
+d
+b
+b
+b
+a
+"}
+(14,1,1) = {"
+a
+b
+b
+c
+c
+c
+d
+e
+l
+q
+r
+q
+D
+A
+l
+s
+b
+b
+b
+a
+"}
+(15,1,1) = {"
+a
+b
+b
+b
+c
+c
+d
+e
+t
+u
+l
+E
+y
+d
+d
+p
+b
+b
+b
+a
+"}
+(16,1,1) = {"
+a
+b
+b
+b
+c
+c
+d
+e
+g
+n
+t
+k
+l
+l
+B
+d
+c
+b
+b
+a
+"}
+(17,1,1) = {"
+a
+b
+b
+c
+c
+c
+d
+e
+h
+o
+D
+l
+D
+l
+C
+d
+c
+c
+b
+b
+"}
+(18,1,1) = {"
+a
+a
+b
+c
+c
+c
+d
+e
+i
+n
+E
+l
+z
+m
+B
+d
+c
+c
+c
+b
+"}
+(19,1,1) = {"
+a
+a
+b
+c
+c
+c
+d
+d
+d
+d
+d
+d
+d
+d
+d
+d
+c
+c
+c
+b
+"}
+(20,1,1) = {"
+a
+a
+b
+b
+c
+c
+c
+c
+c
+c
+b
+F
+b
+c
+c
+c
+c
+c
+c
+b
+"}
+(21,1,1) = {"
+a
+a
+a
+b
+c
+c
+c
+c
+c
+c
+b
+b
+b
+c
+c
+c
+c
+c
+b
+b
+"}
+(22,1,1) = {"
+a
+a
+a
+b
+b
+c
+c
+c
+c
+b
+b
+b
+b
+b
+b
+c
+c
+b
+b
+a
+"}
+(23,1,1) = {"
+a
+a
+a
+a
+b
+b
+b
+b
+b
+b
+a
+b
+b
+b
+b
+b
+b
+b
+a
+a
+"}
+(24,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+b
+b
+b
+b
+b
+a
+a
+a
+"}
+(25,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+b
+b
+a
+a
+a
+a
+"}
diff --git a/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm b/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
new file mode 100644
index 0000000000..c64050ce3a
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/augmentationfacility.dmm
@@ -0,0 +1,731 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/turf/open/floor/plating/asteroid,
+/area/ruin/powered)
+"c" = (
+/turf/closed/mineral/random/high_chance,
+/area/ruin/powered)
+"d" = (
+/turf/closed/wall/r_wall/rust,
+/area/ruin/powered)
+"e" = (
+/obj/machinery/mecha_part_fabricator,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"f" = (
+/turf/closed/wall/rust,
+/area/ruin/powered)
+"g" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/stack/sheet/glass/fifty,
+/obj/item/stack/sheet/metal/fifty,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"h" = (
+/obj/machinery/mecha_part_fabricator,
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"i" = (
+/obj/structure/table,
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/item/stack/sheet/glass/fifty,
+/obj/item/stack/sheet/metal/fifty,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"j" = (
+/obj/structure/chair/sofa/right,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"k" = (
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"l" = (
+/obj/structure/chair/sofa/left,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"m" = (
+/obj/machinery/computer/rdconsole/production{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"n" = (
+/obj/effect/decal/cleanable/oil/streak,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"o" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"p" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"q" = (
+/obj/machinery/light{
+ dir = 8
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/aug_manipulator,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"r" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/organ/cyberimp/chest/reviver,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"s" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/organ/cyberimp/arm/surgery,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"t" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/storage/backpack/duffelbag/med/surgery,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"u" = (
+/obj/machinery/light{
+ dir = 4
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"v" = (
+/obj/machinery/porta_turret/syndicate/energy{
+ mode = 1
+ },
+/turf/closed/wall/r_wall/rust,
+/area/ruin/powered)
+"w" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/computer/mech_bay_power_console{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"x" = (
+/obj/effect/decal/cleanable/oil,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"y" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer1,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"z" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/storage/belt/utility/full,
+/obj/item/clothing/glasses/welding,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"A" = (
+/obj/structure/table,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/mmi/posibrain{
+ pixel_y = 9
+ },
+/obj/item/mmi,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"B" = (
+/obj/structure/table/optable,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"C" = (
+/obj/machinery/mech_bay_recharge_port,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"D" = (
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/mech_bay_recharge_floor,
+/area/ruin/powered)
+"E" = (
+/obj/machinery/computer/operating{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"F" = (
+/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....";
+ uses = 1
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"G" = (
+/obj/machinery/light,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/airalarm{
+ dir = 1;
+ pixel_y = -22
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"H" = (
+/obj/effect/decal/cleanable/oil,
+/obj/machinery/light,
+/obj/effect/decal/cleanable/dirt,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"I" = (
+/obj/machinery/door/airlock/external/glass,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"J" = (
+/obj/machinery/atmospherics/components/unary/outlet_injector/on/layer1{
+ dir = 4
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/powered)
+"K" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{
+ dir = 4
+ },
+/turf/closed/mineral/random/high_chance,
+/area/ruin/powered)
+"L" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{
+ dir = 4
+ },
+/turf/closed/wall/r_wall/rust,
+/area/ruin/powered)
+"M" = (
+/obj/structure/mecha_wreckage/ripley,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"N" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{
+ dir = 4
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"O" = (
+/obj/machinery/turretid{
+ lethal = 1;
+ pixel_y = -25;
+ req_access = null
+ },
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden{
+ dir = 5
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"P" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"Q" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{
+ dir = 1
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"R" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/cyan/hidden,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"S" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer1{
+ dir = 9
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"T" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/machinery/atmospherics/components/unary/tank/air{
+ dir = 8
+ },
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"U" = (
+/obj/machinery/door/airlock/external/glass,
+/obj/structure/fans/tiny,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+"V" = (
+/obj/effect/decal/cleanable/dirt,
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plasteel,
+/area/ruin/powered)
+
+(1,1,1) = {"
+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
+b
+b
+b
+b
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(3,1,1) = {"
+a
+a
+a
+a
+b
+b
+c
+c
+c
+c
+J
+b
+b
+a
+a
+a
+a
+a
+a
+a
+"}
+(4,1,1) = {"
+a
+a
+a
+b
+c
+c
+c
+c
+c
+c
+K
+c
+b
+b
+b
+a
+a
+a
+a
+a
+"}
+(5,1,1) = {"
+a
+a
+b
+c
+c
+d
+d
+d
+d
+d
+L
+d
+c
+c
+b
+a
+a
+a
+a
+a
+"}
+(6,1,1) = {"
+a
+a
+b
+c
+d
+d
+m
+q
+w
+C
+M
+d
+d
+c
+b
+a
+a
+a
+a
+a
+"}
+(7,1,1) = {"
+a
+b
+b
+c
+d
+e
+n
+o
+x
+D
+N
+f
+d
+v
+b
+a
+a
+a
+a
+a
+"}
+(8,1,1) = {"
+a
+b
+c
+c
+d
+g
+o
+o
+y
+Q
+S
+I
+k
+U
+b
+a
+a
+a
+a
+a
+"}
+(9,1,1) = {"
+a
+b
+c
+c
+d
+h
+p
+r
+z
+o
+G
+f
+f
+d
+b
+a
+a
+a
+a
+a
+"}
+(10,1,1) = {"
+a
+b
+c
+c
+d
+i
+p
+s
+A
+o
+H
+f
+f
+d
+b
+a
+a
+a
+a
+a
+"}
+(11,1,1) = {"
+a
+b
+c
+c
+d
+j
+p
+t
+F
+o
+p
+I
+k
+U
+b
+a
+a
+a
+a
+a
+"}
+(12,1,1) = {"
+a
+b
+c
+c
+d
+l
+p
+p
+P
+R
+O
+f
+d
+v
+b
+b
+a
+a
+a
+a
+"}
+(13,1,1) = {"
+a
+b
+b
+c
+d
+d
+V
+u
+B
+E
+T
+d
+d
+c
+c
+b
+a
+a
+a
+a
+"}
+(14,1,1) = {"
+a
+a
+b
+c
+c
+d
+d
+d
+d
+d
+d
+d
+c
+c
+c
+b
+a
+a
+a
+a
+"}
+(15,1,1) = {"
+a
+a
+a
+b
+c
+c
+c
+c
+c
+c
+c
+c
+c
+c
+b
+b
+a
+a
+a
+a
+"}
+(16,1,1) = {"
+a
+a
+a
+b
+b
+b
+b
+c
+c
+c
+c
+b
+b
+b
+b
+a
+a
+a
+a
+a
+"}
+(17,1,1) = {"
+a
+a
+a
+a
+a
+a
+b
+b
+b
+b
+b
+b
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(18,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(19,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(20,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
diff --git a/_maps/RandomRuins/SpaceRuins/bigape.dmm b/_maps/RandomRuins/SpaceRuins/bigape.dmm
new file mode 100644
index 0000000000..09e85e129d
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/bigape.dmm
@@ -0,0 +1,196 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/template_noop,
+/area/template_noop)
+"b" = (
+/obj/structure/lattice,
+/turf/template_noop,
+/area/template_noop)
+"c" = (
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"d" = (
+/obj/structure/fans/tiny/invisible,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"e" = (
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/obj/item/reagent_containers/food/snacks/grown/banana,
+/obj/structure/fans/tiny/invisible,
+/obj/structure/closet/secure_closet/freezer,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"f" = (
+/obj/structure/chair/sofa/left{
+ dir = 4
+ },
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"g" = (
+/obj/item/flashlight/lamp/bananalamp{
+ brightness_on = 10
+ },
+/obj/structure/table/wood,
+/obj/structure/fans/tiny/invisible,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"h" = (
+/obj/structure/table/wood,
+/obj/machinery/computer/security/wooden_tv,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"i" = (
+/obj/structure/chair/sofa/right{
+ dir = 4
+ },
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"j" = (
+/obj/structure/sink/puddle,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"k" = (
+/obj/structure/chair/sofa{
+ dir = 4
+ },
+/mob/living/simple_animal/hostile/gorilla{
+ AIStatus = null;
+ desc = "There is no need to be upset.";
+ dir = 4;
+ name = "Familiar Gorilla"
+ },
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"l" = (
+/obj/effect/overlay/palmtree_r,
+/obj/structure/fans/tiny/invisible,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+"m" = (
+/obj/item/grown/bananapeel,
+/turf/open/floor/plating/beach/sand,
+/area/ruin/powered)
+
+(1,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+b
+a
+"}
+(2,1,1) = {"
+a
+a
+b
+b
+b
+b
+b
+b
+a
+a
+"}
+(3,1,1) = {"
+a
+a
+b
+b
+g
+d
+d
+b
+b
+a
+"}
+(4,1,1) = {"
+a
+a
+b
+d
+f
+k
+i
+d
+d
+b
+"}
+(5,1,1) = {"
+a
+a
+b
+e
+c
+c
+m
+j
+d
+b
+"}
+(6,1,1) = {"
+a
+a
+b
+d
+c
+h
+c
+l
+d
+b
+"}
+(7,1,1) = {"
+a
+b
+b
+b
+d
+d
+d
+b
+b
+a
+"}
+(8,1,1) = {"
+a
+b
+a
+a
+b
+b
+b
+b
+b
+b
+"}
+(9,1,1) = {"
+a
+b
+a
+a
+a
+b
+a
+a
+a
+b
+"}
+(10,1,1) = {"
+a
+a
+a
+a
+a
+b
+a
+a
+a
+a
+"}
diff --git a/_maps/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
index ef36495c58..e820b06f61 100644
--- a/_maps/RandomRuins/SpaceRuins/oldstation.dmm
+++ b/_maps/RandomRuins/SpaceRuins/oldstation.dmm
@@ -2183,9 +2183,7 @@
/obj/effect/turf_decal/tile/purple{
dir = 8
},
-/turf/open/floor/plasteel/white{
- icon_state = "whitepurple"
- },
+/turf/open/floor/plasteel/white,
/area/ruin/space/has_grav/ancientstation/rnd)
"fU" = (
/obj/effect/decal/cleanable/dirt,
diff --git a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
index 624aa03d7c..2945a06b25 100644
--- a/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
+++ b/_maps/RandomRuins/SpaceRuins/originalcontent.dmm
@@ -742,6 +742,7 @@
/turf/open/indestructible/paper,
/area/ruin/powered)
"cc" = (
+/obj/item/book/granter/action/origami,
/mob/living/simple_animal/hostile/boss/paper_wizard,
/turf/open/indestructible/paper,
/area/ruin/powered)
@@ -912,6 +913,10 @@
},
/turf/open/indestructible/paper,
/area/ruin/powered)
+"Ns" = (
+/obj/item/paper/secretrecipe,
+/turf/open/indestructible/paper,
+/area/ruin/powered)
(1,1,1) = {"
aa
@@ -2246,7 +2251,7 @@ ap
az
af
al
-aA
+Ns
bW
ca
af
diff --git a/_maps/RandomRuins/SpaceRuins/spacehermit.dmm b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm
new file mode 100644
index 0000000000..341dcf7b99
--- /dev/null
+++ b/_maps/RandomRuins/SpaceRuins/spacehermit.dmm
@@ -0,0 +1,2941 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aa" = (
+/turf/template_noop,
+/area/template_noop)
+"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,
+/area/ruin/unpowered)
+"ae" = (
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"af" = (
+/obj/effect/spawner/structure/window/shuttle,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ag" = (
+/obj/structure/shuttle/engine/propulsion/right{
+ dir = 4
+ },
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"ah" = (
+/obj/structure/table/wood,
+/obj/item/shovel,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ai" = (
+/obj/structure/lattice,
+/turf/template_noop,
+/area/template_noop)
+"aj" = (
+/obj/machinery/computer/cryopod,
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"ak" = (
+/obj/structure/fluff/empty_cryostasis_sleeper,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"al" = (
+/obj/machinery/status_display/shuttle,
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"am" = (
+/obj/item/circuitboard/computer/rdconsole,
+/obj/item/circuitboard/machine/protolathe/department/science,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"an" = (
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ao" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 8
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ap" = (
+/obj/machinery/light{
+ dir = 1
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"aq" = (
+/obj/machinery/computer{
+ desc = "A computer long since rendered non-functional due to lack of maintenance. Spitting out error messages.";
+ dir = 4;
+ name = "Broken Computer"
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"ar" = (
+/obj/machinery/door/airlock/titanium{
+ name = "Escape Pod Airlock"
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"as" = (
+/obj/machinery/light,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"at" = (
+/obj/structure/shuttle/engine/propulsion/left{
+ dir = 4
+ },
+/turf/closed/wall/mineral/titanium,
+/area/ruin/powered)
+"au" = (
+/obj/item/seeds/tower,
+/obj/item/seeds/tower,
+/obj/item/seeds/tower,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"av" = (
+/obj/structure/table/wood,
+/obj/item/paper/crumpled{
+ info = " Crew Management: Hire a New Crewmember (-10FU, -10FO) You cannot afford a new crewmember. Sell Crew for Fuel and Food (+7FU, +7FO) You have no other crew to sell. Spare Parts: You cannot afford engine parts."
-
- //Hull plates
- if(fuel > 5)
- eventdat += " You cannot afford hull plates."
-
- //Electronics
- if(fuel > 5)
- eventdat += " You cannot afford spare electronics."
-
- //Trade
- if(fuel > 5)
- eventdat += " Trade Fuel for Food (-5FU,+5FO) You don't have 5FU to trade. Trade Food for Fuel (+5FU,-5FO) You don't have 5FO to trade.
So this is it, I guess.. Always thought I'd go out doing something stupid, but.. not like this.
Should anyone find this note, tell Jeremy Clarke he can kiss my ass. Launching the pod unprepared like that..
Well. Now that I'm keeling over here, I guess I should write how I came to be the last one standing here.
Four of us took this pod.. only three of us woke up though.. fourth pod is locked from the inside, we couldn't figure out how to get it open.
Me and the clown set up a farm s'we can survive at least a while.. though, he didn't seem to understand that man cannot live on banana alone.
Had a bunch of circuits on him for some reason when he eventually passed, whispered to me something about a chem dispenser.. I.. don't know what he meant by that. I was never good with machinary. Maybe he wanted space lube?
The assistant that we gave the space suit to go out and find help never came back.. I'm betting he found salvation and left us behind.. never can trust those grubby greytiders."
+ },
+/obj/item/pen,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aw" = (
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/obj/item/stack/sheet/mineral/wood,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ax" = (
+/obj/item/twohanded/spear,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"ay" = (
+/obj/item/grown/log,
+/obj/item/grown/log,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"az" = (
+/obj/structure/table/wood,
+/obj/item/storage/bag/plants/portaseeder,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aA" = (
+/turf/open/floor/plating/asteroid/airless,
+/area/ruin/unpowered)
+"aB" = (
+/obj/item/seeds/banana,
+/obj/item/seeds/banana,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aC" = (
+/obj/effect/mob_spawn/human/clown/corpse,
+/obj/structure/fans/tiny/invisible,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aD" = (
+/obj/item/mining_scanner,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aE" = (
+/obj/machinery/status_display/shuttle,
+/turf/closed/wall/mineral/titanium,
+/area/ruin/unpowered)
+"aF" = (
+/obj/item/pickaxe/emergency,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aG" = (
+/obj/structure/sink/puddle,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aH" = (
+/obj/structure/table/wood,
+/obj/item/storage/firstaid/regular,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aI" = (
+/obj/effect/mob_spawn/human/corpse/assistant,
+/turf/template_noop,
+/area/template_noop)
+"aJ" = (
+/obj/structure/table/wood,
+/obj/item/storage/bag/ore,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aK" = (
+/obj/structure/reagent_dispensers/fueltank,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aL" = (
+/obj/structure/table/wood,
+/obj/item/storage/toolbox/mechanical,
+/obj/item/clothing/head/welding,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aM" = (
+/mob/living/simple_animal/hostile/carp,
+/turf/template_noop,
+/area/template_noop)
+"aN" = (
+/obj/structure/mineral_door/sandstone,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aO" = (
+/mob/living/simple_animal/hostile/carp,
+/turf/open/floor/plating/asteroid/airless,
+/area/ruin/unpowered)
+"aP" = (
+/obj/item/stack/ore/gold,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aQ" = (
+/obj/item/stack/ore/gold,
+/obj/item/stack/ore/gold,
+/obj/item/stack/ore/gold,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aR" = (
+/obj/item/stack/ore/iron,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aS" = (
+/turf/closed/wall/mineral/iron,
+/area/ruin/unpowered)
+"aT" = (
+/obj/item/stack/ore/iron,
+/obj/item/stack/ore/iron,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aU" = (
+/obj/item/flashlight/lamp,
+/obj/structure/table/wood,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"aV" = (
+/obj/item/clothing/suit/space/orange,
+/turf/template_noop,
+/area/template_noop)
+"aW" = (
+/obj/item/clothing/head/helmet/space/orange,
+/turf/template_noop,
+/area/template_noop)
+"aX" = (
+/mob/living/simple_animal/hostile/carp/megacarp,
+/turf/template_noop,
+/area/template_noop)
+"aY" = (
+/obj/effect/mob_spawn/human/hermit{
+ flavour_text = "You've been late to awaken from your cryo slumber. Blasted machine, you set it to 10 days not 10 weeks! Where have the others gone while we were out? Did they manage to survive? These thoughts are dispelled by yet another recollection of how you got here... ";
+ job_description = "Space Hermit"
+ },
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"aZ" = (
+/turf/closed/wall/mineral/titanium,
+/area/ruin/unpowered)
+"ba" = (
+/obj/effect/spawner/structure/window/shuttle,
+/turf/open/floor/mineral/titanium,
+/area/ruin/unpowered)
+"bb" = (
+/obj/structure/shuttle/engine/propulsion/left{
+ dir = 4
+ },
+/turf/closed/wall/mineral/titanium,
+/area/ruin/unpowered)
+"bc" = (
+/obj/item/circuitboard/machine/circuit_imprinter,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bd" = (
+/obj/item/grown/bananapeel,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"be" = (
+/obj/effect/mob_spawn/human/corpse/cargo_tech,
+/obj/structure/fans/tiny/invisible,
+/obj/effect/decal/cleanable/vomit,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bf" = (
+/obj/item/clothing/glasses/meson,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bg" = (
+/obj/item/stock_parts/matter_bin,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bh" = (
+/obj/item/circuitboard/machine/autolathe,
+/turf/open/floor/mineral/titanium,
+/area/ruin/powered)
+"bi" = (
+/obj/item/stock_parts/manipulator,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bj" = (
+/obj/item/holosign_creator/atmos,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bk" = (
+/obj/structure/holosign/barrier/atmos,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bl" = (
+/obj/machinery/power/floodlight,
+/obj/structure/cable{
+ icon_state = "0-2"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bm" = (
+/obj/structure/cable{
+ icon_state = "1-4"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bn" = (
+/obj/structure/cable{
+ icon_state = "2-8"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bo" = (
+/obj/structure/cable{
+ icon_state = "1-2"
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bp" = (
+/obj/item/stack/ore/iron,
+/obj/item/stack/ore/iron,
+/obj/item/stack/ore/iron,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bq" = (
+/obj/structure/cable,
+/obj/machinery/power/port_gen/pacman{
+ active = 1;
+ anchored = 1;
+ sheets = 10
+ },
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"br" = (
+/obj/item/stack/ore/iron,
+/obj/item/stack/sheet/mineral/plasma,
+/obj/item/stack/sheet/mineral/plasma,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+"bs" = (
+/obj/item/flashlight/lamp/bananalamp,
+/turf/open/floor/plating/asteroid,
+/area/ruin/unpowered)
+
+(1,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+aO
+aA
+aA
+aA
+aA
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(2,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+"}
+(3,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+aa
+aa
+aa
+aa
+aW
+aa
+aM
+aa
+"}
+(4,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aV
+aI
+aX
+aa
+aa
+"}
+(5,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(6,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aM
+aa
+aa
+aa
+"}
+(7,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+"}
+(8,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ae
+af
+ae
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+"}
+(9,1,1) = {"
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+aq
+af
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(10,1,1) = {"
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ae
+ae
+ao
+ae
+ae
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(11,1,1) = {"
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+an
+an
+an
+af
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(12,1,1) = {"
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ae
+ae
+bh
+an
+an
+ae
+aZ
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(13,1,1) = {"
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+aY
+ao
+ao
+ao
+ak
+ba
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(14,1,1) = {"
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+al
+aj
+ap
+an
+as
+aj
+aE
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(15,1,1) = {"
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+aA
+aa
+aa
+aa
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+af
+ak
+ao
+ao
+ao
+ak
+ba
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(16,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ah
+az
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aR
+ae
+ae
+an
+an
+an
+ae
+aZ
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aM
+"}
+(17,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aR
+ag
+ag
+af
+ar
+af
+at
+bb
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(18,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+ac
+ac
+ac
+ac
+ab
+aH
+aJ
+aL
+ab
+ab
+aT
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+aR
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(19,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+au
+ac
+aB
+am
+ac
+ac
+ac
+ac
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+bg
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(20,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+aw
+bs
+aC
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(21,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+ax
+ac
+aD
+aF
+ac
+ac
+ac
+ab
+ab
+ab
+aU
+bd
+ac
+ac
+bl
+bm
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(22,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ad
+ay
+ac
+ac
+ac
+aG
+ac
+ac
+ab
+ab
+ab
+av
+be
+ac
+ac
+ac
+bn
+bo
+bo
+bq
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+"}
+(23,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+bc
+bf
+ac
+ac
+ac
+ac
+ac
+ac
+br
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(24,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ab
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+"}
+(25,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+aN
+ac
+ac
+ac
+ac
+aR
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+"}
+(26,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+"}
+(27,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aK
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+bp
+ac
+ac
+aR
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aM
+"}
+(28,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aP
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+ac
+aR
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+"}
+(29,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aQ
+aP
+ac
+ac
+aR
+ac
+ac
+ac
+ac
+ab
+ac
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+"}
+(30,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+aP
+ac
+bg
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+"}
+(31,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+ac
+ac
+ac
+ac
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+ab
+aA
+"}
+(32,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+bg
+ac
+ac
+ac
+ac
+ac
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aO
+ab
+ab
+"}
+(33,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ac
+ac
+bj
+ac
+ac
+ac
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aA
+ab
+ab
+ab
+"}
+(34,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aS
+bi
+ac
+ac
+ac
+aS
+aS
+ab
+ab
+ab
+ab
+aA
+aa
+aA
+ab
+ab
+aA
+"}
+(35,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aS
+ac
+ac
+ac
+ac
+aS
+aS
+ab
+ab
+ab
+aA
+aa
+aa
+aA
+ab
+ab
+ab
+"}
+(36,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aS
+aS
+aS
+bk
+bk
+aS
+aS
+aS
+aS
+ab
+ab
+aA
+aa
+aa
+aa
+ab
+ab
+ab
+"}
+(37,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+aA
+aS
+aS
+aS
+bk
+aS
+aS
+aS
+aA
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aA
+aA
+"}
+(38,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aA
+ai
+ai
+ai
+ai
+ai
+ai
+ai
+ai
+aA
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(39,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aA
+aa
+aa
+aa
+ai
+ai
+ai
+aa
+ai
+aa
+aa
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(40,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+ai
+aa
+aa
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(41,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(42,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+aA
+aA
+aA
+aA
+ab
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+"}
+(43,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aA
+aA
+aA
+ab
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+"}
+(44,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+aa
+aa
+aa
+"}
+(45,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+ac
+ab
+ac
+aa
+aa
+"}
+(46,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aM
+ab
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+aa
+aa
+"}
+(47,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+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
+aa
+aa
+aa
+aa
+ab
+ab
+ab
+aa
+aa
+"}
+(48,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+ab
+ab
+ab
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+ab
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+ab
+ac
+aa
+aa
+"}
+(49,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aA
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aA
+aa
+aa
+aa
+aa
+aM
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ac
+aa
+aa
+aa
+aa
+"}
+(50,1,1) = {"
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+aa
+ab
+aa
+aa
+aa
+aa
+"}
diff --git a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm
index 99f7f19621..c64a73eada 100644
--- a/_maps/RandomRuins/SpaceRuins/spacehotel.dmm
+++ b/_maps/RandomRuins/SpaceRuins/spacehotel.dmm
@@ -509,7 +509,9 @@
/obj/machinery/button/door{
id = "a3";
name = "privacy button";
- pixel_y = -24
+ normaldoorcontrol = 1;
+ pixel_y = -24;
+ specialfunctions = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
@@ -557,7 +559,9 @@
/obj/machinery/button/door{
id = "a4";
name = "privacy button";
- pixel_y = -24
+ normaldoorcontrol = 1;
+ pixel_y = -24;
+ specialfunctions = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
@@ -605,7 +609,9 @@
/obj/machinery/button/door{
id = "a5";
name = "privacy button";
- pixel_y = -24
+ normaldoorcontrol = 1;
+ pixel_y = -24;
+ specialfunctions = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
@@ -653,7 +659,9 @@
/obj/machinery/button/door{
id = "a6";
name = "privacy button";
- pixel_y = -24
+ normaldoorcontrol = 1;
+ pixel_y = -24;
+ specialfunctions = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
@@ -1097,7 +1105,9 @@
/obj/machinery/button/door{
id = "a2";
name = "privacy button";
- pixel_y = 24
+ normaldoorcontrol = 1;
+ pixel_y = 24;
+ specialfunctions = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
@@ -1159,7 +1169,9 @@
/obj/machinery/button/door{
id = "a1";
name = "privacy button";
- pixel_y = 24
+ normaldoorcontrol = 1;
+ pixel_y = 24;
+ specialfunctions = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/open/floor/wood,
@@ -1807,7 +1819,9 @@
/area/ruin/space/has_grav/hotel/bar)
"fE" = (
/obj/machinery/vending/boozeomat{
- req_access_txt = "200"
+ extended_inventory = 1;
+ req_access_txt = "200";
+ scan_id = 0
},
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
@@ -4496,7 +4510,6 @@
/turf/closed/wall,
/area/ruin/space/has_grav/hotel/custodial)
"me" = (
-/mob/living/simple_animal/bot/cleanbot,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -4507,6 +4520,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/mob/living/simple_animal/bot/cleanbot,
/turf/open/floor/plasteel,
/area/ruin/space/has_grav/hotel/custodial)
"mf" = (
diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm
index de28ff59fa..4420059f62 100644
--- a/_maps/map_files/BoxStation/BoxStation.dmm
+++ b/_maps/map_files/BoxStation/BoxStation.dmm
@@ -41,6 +41,24 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/bar)
+"aad" = (
+/obj/structure/bed,
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
+/obj/machinery/button/door{
+ id = "Dorm4";
+ name = "Dorm Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
"aae" = (
/obj/effect/landmark/carpspawn,
/turf/open/space,
@@ -515,10 +533,13 @@
/turf/closed/wall,
/area/security/main)
"abq" = (
-/turf/closed/wall,
+/turf/closed/wall/r_wall,
/area/crew_quarters/heads/hos)
"abr" = (
/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/door/poddoor/preopen{
+ id = "hos"
+ },
/turf/open/floor/plating,
/area/crew_quarters/heads/hos)
"abs" = (
@@ -574,6 +595,19 @@
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/turf/closed/wall/r_wall,
/area/security/execution/transfer)
+"abz" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Dorm5";
+ name = "Cabin Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_y = -25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
"abA" = (
/obj/machinery/light,
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
@@ -846,8 +880,13 @@
},
/obj/structure/table/wood,
/obj/item/reagent_containers/food/drinks/bottle/vodka/badminka,
-/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass,
-/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass,
+/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{
+ pixel_x = -5;
+ pixel_y = 5
+ },
+/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass{
+ pixel_x = -5
+ },
/turf/open/floor/carpet,
/area/crew_quarters/heads/hos)
"abX" = (
@@ -1449,6 +1488,9 @@
"adm" = (
/obj/structure/disposalpipe/segment,
/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/door/poddoor/preopen{
+ id = "hos"
+ },
/turf/open/floor/plating,
/area/crew_quarters/heads/hos)
"adn" = (
@@ -1674,6 +1716,11 @@
/obj/structure/cable{
icon_state = "4-8"
},
+/obj/machinery/button/door{
+ id = "hos";
+ name = "HoS Office Shutters";
+ pixel_y = -25
+ },
/turf/open/floor/carpet,
/area/crew_quarters/heads/hos)
"adN" = (
@@ -2053,6 +2100,9 @@
"aex" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/door/poddoor/preopen{
+ id = "hos"
+ },
/turf/open/floor/plating,
/area/crew_quarters/heads/hos)
"aey" = (
@@ -2099,6 +2149,55 @@
},
/turf/open/floor/plating,
/area/maintenance/fore/secondary)
+"aeD" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Dorm6";
+ name = "Cabin Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_y = -25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
+"aeE" = (
+/obj/structure/bed,
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
+/obj/machinery/button/door{
+ id = "Dorm3";
+ name = "Dorm Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
+"aeF" = (
+/obj/structure/bed,
+/obj/machinery/airalarm{
+ pixel_y = 23
+ },
+/obj/machinery/button/door{
+ id = "Dorm2";
+ name = "Dorm Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
"aeG" = (
/obj/structure/cable,
/obj/machinery/power/solar{
@@ -2475,6 +2574,11 @@
},
/turf/open/floor/plasteel,
/area/security/main)
+"afn" = (
+/obj/structure/bed,
+/obj/item/bedsheet/medical,
+/turf/open/floor/plasteel/white,
+/area/medical/virology)
"afo" = (
/obj/machinery/door/airlock/external{
name = "Escape Pod Three"
@@ -2495,6 +2599,14 @@
},
/turf/open/space/basic,
/area/space)
+"afq" = (
+/obj/structure/bed,
+/obj/item/tank/internals/anesthetic,
+/obj/item/clothing/mask/breath,
+/obj/effect/decal/cleanable/semen,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/plating,
+/area/maintenance/bar)
"aft" = (
/obj/machinery/atmospherics/pipe/simple/general/visible{
dir = 5
@@ -7391,24 +7503,6 @@
},
/turf/open/floor/plating,
/area/maintenance/fore/secondary)
-"aqn" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/airalarm{
- pixel_y = 23
- },
-/obj/machinery/button/door{
- id = "Dorm4";
- name = "Dorm Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"aqo" = (
/obj/structure/chair/stool{
pixel_y = 8
@@ -8189,19 +8283,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/fitness)
-"asu" = (
-/obj/structure/bed,
-/obj/item/bedsheet/red,
-/obj/machinery/button/door{
- id = "Dorm5";
- name = "Cabin Bolt Control";
- normaldoorcontrol = 1;
- pixel_y = -25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"asv" = (
/obj/structure/table,
/obj/effect/spawner/lootdrop/maintenance{
@@ -8293,19 +8374,6 @@
},
/turf/open/floor/plating,
/area/maintenance/port/fore)
-"asL" = (
-/obj/structure/bed,
-/obj/item/bedsheet/red,
-/obj/machinery/button/door{
- id = "Dorm6";
- name = "Cabin Bolt Control";
- normaldoorcontrol = 1;
- pixel_y = -25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"asM" = (
/obj/structure/disposalpipe/segment,
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
@@ -8912,24 +8980,6 @@
},
/turf/open/floor/plasteel/dark,
/area/crew_quarters/fitness)
-"auw" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/airalarm{
- pixel_y = 23
- },
-/obj/machinery/button/door{
- id = "Dorm3";
- name = "Dorm Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"aux" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
@@ -10796,24 +10846,6 @@
},
/turf/open/floor/plasteel,
/area/ai_monitored/storage/eva)
-"ayV" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/airalarm{
- pixel_y = 23
- },
-/obj/machinery/button/door{
- id = "Dorm2";
- name = "Dorm Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"ayW" = (
/turf/closed/wall,
/area/ai_monitored/storage/eva)
@@ -11691,7 +11723,7 @@
/area/maintenance/port/fore)
"aAW" = (
/obj/structure/rack,
-/obj/item/tank/jetpack/carbondioxide,
+/obj/item/tank/jetpack/carbondioxide/eva,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
@@ -11815,7 +11847,7 @@
/obj/machinery/light{
dir = 8
},
-/obj/item/tank/jetpack/carbondioxide,
+/obj/item/tank/jetpack/carbondioxide/eva,
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
@@ -26208,9 +26240,7 @@
/turf/open/floor/plasteel,
/area/quartermaster/office)
"bkx" = (
-/obj/machinery/status_display/supply{
- pixel_y = 2
- },
+/obj/machinery/status_display/supply,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
@@ -27901,8 +27931,8 @@
pixel_x = 30
},
/obj/machinery/light,
-/mob/living/simple_animal/bot/cleanbot{
- name = "C.L.E.A.N."
+/obj/machinery/computer/crew{
+ dir = 1
},
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
@@ -31325,7 +31355,9 @@
id = "QMLoad"
},
/obj/machinery/light,
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_y = -32
+ },
/obj/effect/turf_decal/stripes/line{
dir = 1
},
@@ -31596,7 +31628,7 @@
/area/medical/sleeper)
"bwC" = (
/obj/machinery/computer/med_data{
- dir = 4
+ dir = 3
},
/turf/open/floor/plasteel/white,
/area/medical/sleeper)
@@ -33592,7 +33624,9 @@
name = "Station Intercom (General)";
pixel_y = -35
},
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_x = -32
+ },
/obj/machinery/computer/security/qm{
dir = 4
},
@@ -36664,14 +36698,11 @@
/turf/open/floor/plasteel,
/area/hallway/primary/aft)
"bHT" = (
-/obj/machinery/door/poddoor/preopen{
- id = "medpriv1";
- name = "privacy door"
- },
/obj/effect/spawner/structure/window,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/door/firedoor,
/turf/open/floor/plating,
/area/medical/medbay/central)
"bHU" = (
@@ -37987,22 +38018,23 @@
/turf/open/floor/plating,
/area/maintenance/aft)
"bKM" = (
-/obj/machinery/vending/wallmed{
- pixel_y = 28
- },
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
},
+/obj/machinery/airalarm{
+ pixel_y = 24
+ },
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"bKN" = (
/obj/machinery/door/airlock/medical{
- name = "Patient Room 2";
+ name = "Apothecary";
req_access_txt = "5"
},
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
+/obj/machinery/door/firedoor,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"bKO" = (
@@ -38456,24 +38488,17 @@
/turf/open/floor/plating,
/area/maintenance/aft)
"bLU" = (
-/obj/structure/table,
-/obj/item/folder/white,
-/obj/item/clothing/neck/stethoscope,
/obj/machinery/light/small{
dir = 8
},
+/obj/machinery/chem_dispenser,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"bLV" = (
-/obj/structure/closet/secure_closet/personal/patient,
-/obj/machinery/button/door{
- id = "medpriv1";
- name = "Privacy Shutters";
- pixel_y = -25
- },
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
+/obj/machinery/chem_heater,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"bLW" = (
@@ -39352,11 +39377,6 @@
/obj/machinery/announcement_system,
/turf/open/floor/plasteel,
/area/tcommsat/computer)
-"bOm" = (
-/obj/item/bedsheet,
-/obj/structure/bed,
-/turf/open/floor/plasteel/white,
-/area/medical/virology)
"bOn" = (
/obj/machinery/light{
dir = 1
@@ -42618,11 +42638,6 @@
/obj/effect/spawner/structure/window,
/turf/open/floor/plating,
/area/medical/virology)
-"bWk" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/turf/open/floor/plasteel/white,
-/area/medical/virology)
"bWl" = (
/obj/structure/disposalpipe/segment{
dir = 4
@@ -46031,6 +46046,9 @@
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/obj/effect/turf_decal/delivery,
+/obj/machinery/shower{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"cek" = (
@@ -46039,6 +46057,9 @@
name = "engineering security door"
},
/obj/effect/turf_decal/delivery,
+/obj/machinery/shower{
+ dir = 8
+ },
/turf/open/floor/plasteel,
/area/engine/engineering)
"cel" = (
@@ -56650,6 +56671,12 @@
/obj/item/stock_parts/cell/high,
/turf/open/floor/plasteel/white,
/area/science/circuit)
+"eef" = (
+/obj/machinery/autolathe{
+ name = "public autolathe"
+ },
+/turf/open/floor/plasteel,
+/area/quartermaster/office)
"evR" = (
/turf/open/floor/plating,
/area/maintenance/bar)
@@ -56742,6 +56769,16 @@
/obj/effect/landmark/event_spawn,
/turf/open/floor/plasteel,
/area/science/circuit)
+"fTg" = (
+/obj/machinery/atmospherics/pipe/simple/supply/hidden{
+ dir = 4
+ },
+/obj/machinery/firealarm{
+ dir = 2;
+ pixel_y = 24
+ },
+/turf/open/floor/plasteel/white,
+/area/medical/medbay/central)
"gbq" = (
/obj/structure/cable{
icon_state = "4-8"
@@ -57109,6 +57146,12 @@
},
/turf/open/floor/plating,
/area/construction/mining/aux_base)
+"lKX" = (
+/mob/living/simple_animal/bot/cleanbot{
+ name = "C.L.E.A.N."
+ },
+/turf/open/floor/plasteel/white,
+/area/medical/medbay/central)
"lMg" = (
/obj/effect/turf_decal/stripes/line{
dir = 9
@@ -57340,14 +57383,6 @@
},
/turf/open/floor/plating,
/area/construction)
-"rMN" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/item/tank/internals/anesthetic,
-/obj/item/clothing/mask/breath,
-/obj/effect/decal/cleanable/semen,
-/turf/open/floor/plating,
-/area/maintenance/bar)
"rNc" = (
/obj/effect/turf_decal/stripes/line{
dir = 6
@@ -57499,6 +57534,10 @@
/obj/structure/table/wood,
/turf/open/floor/wood,
/area/maintenance/bar)
+"tRe" = (
+/obj/machinery/chem_master,
+/turf/open/floor/plasteel/white,
+/area/medical/medbay/central)
"tRF" = (
/obj/machinery/light/small{
dir = 8
@@ -79814,7 +79853,7 @@ sAM
imH
evR
evR
-rMN
+afq
bCq
bUs
bLv
@@ -81576,7 +81615,7 @@ cNG
cNJ
bLF
aZK
-bbR
+eef
bbR
bqt
cBq
@@ -88451,7 +88490,7 @@ aaa
aaf
aaf
aaa
-abp
+adR
abP
aco
acO
@@ -88478,13 +88517,13 @@ aoD
aod
aqe
arf
-aqn
+aad
ath
arf
-auw
+aeE
ath
arf
-ayV
+aeF
ath
dgz
aCd
@@ -88965,7 +89004,7 @@ aaa
aaa
aaf
aaa
-abp
+adR
abO
acq
acq
@@ -89479,15 +89518,15 @@ aaa
aaa
aaa
aaf
-abp
+adR
abR
abP
abP
abP
abP
-abp
-abp
-abp
+adR
+adR
+adR
agA
afU
ahF
@@ -90278,7 +90317,7 @@ cSA
aqe
arf
ari
-asu
+abz
aun
auW
avR
@@ -91306,7 +91345,7 @@ apr
aqj
arf
ark
-asL
+aeD
aun
avu
awt
@@ -94171,7 +94210,7 @@ blm
bmL
boi
bpw
-bhh
+lKX
bsx
btX
bvj
@@ -95728,8 +95767,8 @@ bof
bof
bof
bJE
-bof
-bof
+bJE
+bJE
bNd
bIJ
bPo
@@ -95985,7 +96024,7 @@ bof
bGT
bIo
bof
-bIo
+tRe
bLU
bNd
bII
@@ -96499,10 +96538,10 @@ bof
bGU
bqQ
bof
-bCR
+fTg
bLV
bNd
-bOm
+afn
bPp
bQF
bRN
@@ -98308,7 +98347,7 @@ bRQ
bOr
bSQ
bWj
-bWk
+afn
bXc
bYe
bNd
@@ -98822,7 +98861,7 @@ bRQ
bOr
bSQ
bWj
-bWk
+afn
bXc
bYe
bNd
diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index bd159e4e9c..bfc4a60f08 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -124,6 +124,22 @@
},
/turf/open/floor/plating,
/area/crew_quarters/abandoned_gambling_den)
+"aaq" = (
+/obj/structure/bed,
+/obj/machinery/status_display{
+ pixel_y = 32
+ },
+/obj/item/bedsheet/clown,
+/turf/open/floor/plasteel/grimy,
+/area/hallway/secondary/service)
+"aar" = (
+/obj/structure/bed,
+/obj/machinery/status_display{
+ pixel_y = 32
+ },
+/obj/item/bedsheet/mime,
+/turf/open/floor/wood,
+/area/hallway/secondary/service)
"aas" = (
/obj/docking_port/stationary/random{
id = "pod_lavaland1";
@@ -143,6 +159,52 @@
/obj/effect/landmark/xeno_spawn,
/turf/open/space,
/area/solar/starboard/fore)
+"aav" = (
+/obj/structure/bed,
+/obj/machinery/light{
+ dir = 1
+ },
+/obj/machinery/status_display{
+ pixel_y = 32
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
+"aaw" = (
+/obj/structure/bed,
+/obj/effect/decal/cleanable/dirt{
+ desc = "A thin layer of dust coating the floor.";
+ name = "dust"
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
+"aax" = (
+/obj/structure/bed,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
+"aay" = (
+/obj/structure/bed,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/plasteel/grimy,
+/area/crew_quarters/dorms)
+"aaz" = (
+/obj/structure/bed,
+/obj/machinery/light,
+/obj/machinery/status_display{
+ pixel_y = -32
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
+"aaA" = (
+/obj/structure/bed,
+/obj/item/tank/internals/anesthetic,
+/obj/item/clothing/mask/breath,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/plating,
+/area/crew_quarters/abandoned_gambling_den)
"aaE" = (
/obj/structure/lattice/catwalk,
/turf/open/space,
@@ -13706,14 +13768,6 @@
},
/turf/open/floor/plasteel/grimy,
/area/hallway/secondary/service)
-"aDF" = (
-/obj/structure/bed,
-/obj/machinery/status_display{
- pixel_y = 32
- },
-/obj/item/bedsheet/rainbow,
-/turf/open/floor/plasteel/grimy,
-/area/hallway/secondary/service)
"aDG" = (
/turf/open/floor/plasteel/grimy,
/area/hallway/secondary/service)
@@ -16868,14 +16922,6 @@
},
/turf/open/floor/wood,
/area/hallway/secondary/service)
-"aIP" = (
-/obj/structure/bed,
-/obj/machinery/status_display{
- pixel_y = 32
- },
-/obj/item/bedsheet/orange,
-/turf/open/floor/wood,
-/area/hallway/secondary/service)
"aIQ" = (
/obj/structure/dresser,
/turf/open/floor/wood{
@@ -35021,12 +35067,13 @@
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
"blM" = (
-/obj/structure/table,
-/obj/item/storage/box/lights/mixed,
/obj/effect/turf_decal/tile/brown,
/obj/effect/turf_decal/tile/brown{
dir = 8
},
+/obj/machinery/autolathe{
+ name = "public autolathe"
+ },
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
"blN" = (
@@ -35043,6 +35090,7 @@
/obj/effect/turf_decal/tile/brown{
dir = 8
},
+/obj/item/storage/box/lights/mixed,
/turf/open/floor/plasteel,
/area/hallway/primary/fore)
"blO" = (
@@ -78958,17 +79006,6 @@
/obj/structure/dresser,
/turf/open/floor/carpet,
/area/crew_quarters/dorms)
-"cCi" = (
-/obj/structure/bed,
-/obj/machinery/light{
- dir = 1
- },
-/obj/item/bedsheet/red,
-/obj/machinery/status_display{
- pixel_y = 32
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"cCj" = (
/obj/structure/closet/secure_closet/personal/cabinet,
/obj/item/clothing/suit/jacket{
@@ -79373,12 +79410,12 @@
},
/obj/structure/window/reinforced,
/obj/structure/rack,
-/obj/item/tank/jetpack/carbondioxide{
+/obj/item/tank/jetpack/carbondioxide/eva{
pixel_x = 4;
pixel_y = -1
},
-/obj/item/tank/jetpack/carbondioxide,
-/obj/item/tank/jetpack/carbondioxide{
+/obj/item/tank/jetpack/carbondioxide/eva,
+/obj/item/tank/jetpack/carbondioxide/eva{
pixel_x = -4;
pixel_y = 1
},
@@ -80186,11 +80223,11 @@
/area/engine/storage)
"cEi" = (
/obj/structure/table/reinforced,
-/obj/item/tank/jetpack/carbondioxide{
+/obj/item/tank/jetpack/carbondioxide/eva{
pixel_x = 3;
pixel_y = 3
},
-/obj/item/tank/jetpack/carbondioxide,
+/obj/item/tank/jetpack/carbondioxide/eva,
/obj/machinery/power/apc{
dir = 4;
name = "Engineering Storage APC";
@@ -80986,24 +81023,10 @@
icon_state = "wood-broken2"
},
/area/crew_quarters/dorms)
-"cFx" = (
-/obj/structure/bed,
-/obj/item/bedsheet/black,
-/obj/effect/decal/cleanable/dirt{
- desc = "A thin layer of dust coating the floor.";
- name = "dust"
- },
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"cFy" = (
/obj/item/twohanded/required/kirbyplants/random,
/turf/open/floor/wood,
/area/crew_quarters/dorms)
-"cFz" = (
-/obj/structure/bed,
-/obj/item/bedsheet/blue,
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"cFA" = (
/obj/structure/table/wood,
/obj/item/flashlight/lamp/green,
@@ -87800,11 +87823,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/turf/open/floor/plating,
/area/maintenance/starboard/aft)
-"cRs" = (
-/obj/structure/bed,
-/obj/item/bedsheet/clown,
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"cRt" = (
/obj/structure/table/wood,
/obj/item/storage/briefcase{
@@ -88878,11 +88896,6 @@
/obj/structure/chair/office/dark,
/turf/open/floor/wood,
/area/crew_quarters/dorms)
-"cTc" = (
-/obj/structure/bed,
-/obj/item/bedsheet/mime,
-/turf/open/floor/plasteel/grimy,
-/area/crew_quarters/dorms)
"cTd" = (
/obj/structure/table,
/obj/item/storage/fancy/donut_box,
@@ -90079,15 +90092,6 @@
},
/turf/open/floor/wood,
/area/crew_quarters/dorms)
-"cUX" = (
-/obj/structure/bed,
-/obj/machinery/light,
-/obj/item/bedsheet/brown,
-/obj/machinery/status_display{
- pixel_y = -32
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"cUY" = (
/obj/structure/closet/secure_closet/personal/cabinet,
/obj/item/clothing/suit/jacket{
@@ -101814,6 +101818,7 @@
/obj/effect/turf_decal/tile/blue{
dir = 1
},
+/obj/effect/landmark/start/medical_doctor,
/turf/open/floor/plasteel/white,
/area/medical/genetics/cloning)
"dpo" = (
@@ -126296,6 +126301,20 @@
/obj/machinery/atmospherics/pipe/simple/general/visible,
/turf/closed/wall/r_wall,
/area/science/mixing)
+"eLw" = (
+/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/chem_dispenser,
+/turf/open/floor/plasteel/dark,
+/area/medical/medbay/central)
"eMD" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/cable/white{
@@ -126355,6 +126374,22 @@
},
/turf/open/floor/plasteel/white,
/area/science/misc_lab)
+"fhE" = (
+/obj/machinery/door/firedoor,
+/obj/machinery/door/airlock/medical{
+ name = "Apothecary"
+ },
+/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/medical/medbay/central)
"fno" = (
/obj/effect/turf_decal/stripes/line{
dir = 8
@@ -126584,6 +126619,13 @@
/obj/item/restraints/handcuffs/fake,
/turf/open/floor/plating,
/area/crew_quarters/abandoned_gambling_den)
+"hSf" = (
+/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
+ dir = 4
+ },
+/obj/effect/spawner/structure/window/reinforced,
+/turf/open/floor/plating,
+/area/medical/medbay/central)
"iaF" = (
/obj/effect/turf_decal/bot,
/turf/open/floor/plasteel,
@@ -126593,6 +126635,18 @@
/obj/item/reagent_containers/glass/beaker,
/turf/open/floor/plating,
/area/crew_quarters/abandoned_gambling_den)
+"iwL" = (
+/obj/machinery/status_display{
+ pixel_x = 32
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/turf/open/floor/plasteel/white,
+/area/medical/medbay/central)
"ixL" = (
/obj/structure/sign/warning/vacuum{
pixel_x = 32
@@ -126743,6 +126797,23 @@
},
/turf/open/floor/plasteel,
/area/medical/morgue)
+"jOE" = (
+/obj/machinery/newscaster{
+ 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
+ },
+/obj/machinery/chem_master,
+/turf/open/floor/plasteel/dark,
+/area/medical/medbay/central)
"jRy" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
@@ -126853,6 +126924,22 @@
},
/turf/open/floor/engine,
/area/science/mixing)
+"lzF" = (
+/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/firealarm{
+ pixel_y = 26
+ },
+/turf/open/floor/plasteel/dark,
+/area/medical/medbay/central)
"lEl" = (
/obj/effect/turf_decal/stripes/line{
dir = 1
@@ -126909,6 +126996,23 @@
},
/turf/open/floor/plating,
/area/construction/mining/aux_base)
+"lTx" = (
+/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/table,
+/obj/machinery/airalarm{
+ pixel_y = 22
+ },
+/turf/open/floor/plasteel/dark,
+/area/medical/medbay/central)
"lXF" = (
/obj/effect/turf_decal/stripes/line{
dir = 4
@@ -127110,13 +127214,6 @@
dir = 1
},
/area/science/circuit)
-"poI" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/item/tank/internals/anesthetic,
-/obj/item/clothing/mask/breath,
-/turf/open/floor/plating,
-/area/crew_quarters/abandoned_gambling_den)
"psi" = (
/obj/effect/decal/cleanable/dirt,
/obj/structure/bodycontainer/morgue{
@@ -127259,6 +127356,16 @@
dir = 10
},
/area/science/misc_lab)
+"tRT" = (
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/blue{
+ dir = 8
+ },
+/obj/machinery/chem_heater,
+/turf/open/floor/plasteel/white,
+/area/medical/medbay/central)
"upk" = (
/obj/machinery/door/airlock/public/glass{
name = "Holodeck Access"
@@ -151573,7 +151680,7 @@ djm
fow
dod
dod
-poI
+aaA
dfY
ajr
aad
@@ -160727,11 +160834,11 @@ ary
aAf
aBu
aCB
-aDF
+aaq
aEJ
aFV
aDI
-aIP
+aar
aKo
aLE
aMX
@@ -174190,9 +174297,9 @@ dfL
dCM
dEb
cPy
-dfL
-dCM
-dEb
+cNz
+fhE
+hSf
cPy
dhs
dMS
@@ -174447,7 +174554,7 @@ dBo
cSF
dEc
cPy
-dBo
+lzF
cSF
dEc
cPy
@@ -174961,8 +175068,8 @@ dBq
dCN
dEe
cPy
-dBq
-dCN
+lTx
+cSK
dEe
cPy
cMg
@@ -175218,9 +175325,9 @@ dBr
dCO
dEf
cPy
-dBr
+eLw
dCO
-dEf
+tRT
cPy
dLo
dMW
@@ -175475,9 +175582,9 @@ dBs
dCP
dEg
cPy
-dBs
+jOE
dCP
-dEg
+iwL
cPy
dLp
dMV
@@ -178267,7 +178374,7 @@ cyY
cAx
cCd
cDD
-cFx
+aaw
cGU
cAw
cJl
@@ -178275,7 +178382,7 @@ cLa
cMx
cIi
cPR
-cRs
+aax
cDG
cUW
cAw
@@ -179048,7 +179155,7 @@ cNU
cDI
cFB
cDI
-cUX
+aaz
cAw
cYj
cZV
@@ -179295,7 +179402,7 @@ czc
cAw
cCg
cDG
-cFz
+aax
cGW
cIi
cJo
@@ -180064,7 +180171,7 @@ bHq
cxt
coI
cAw
-cCi
+aav
cDI
cFB
cDI
@@ -180332,7 +180439,7 @@ cMB
cIi
cPW
cRv
-cTc
+aay
cVb
cAw
cYp
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 228700580a..4de1657e48 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -2,10 +2,58 @@
"aaa" = (
/turf/open/space/basic,
/area/space)
+"aab" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Cabin3";
+ name = "Cabin Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 25;
+ specialfunctions = 4
+ },
+/obj/effect/decal/cleanable/cobweb/cobweb2,
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
"aac" = (
/obj/effect/landmark/carpspawn,
/turf/open/space,
/area/space)
+"aad" = (
+/obj/machinery/light/small{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/cobweb,
+/obj/machinery/button/door{
+ id = "Cabin4";
+ name = "Cabin Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = -25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
+/obj/structure/bed,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
+"aae" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Cabin2";
+ name = "Cabin Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = 25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_pump/on{
+ dir = 4
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
"aaf" = (
/obj/structure/lattice,
/turf/open/space,
@@ -252,6 +300,19 @@
},
/turf/open/floor/plating,
/area/security/prison)
+"aaM" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Cabin5";
+ name = "Dorm Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = -25;
+ specialfunctions = 4
+ },
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
"aaN" = (
/obj/structure/cable{
icon_state = "0-2"
@@ -294,6 +355,37 @@
},
/turf/open/floor/plasteel,
/area/security/prison)
+"aaU" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Cabin6";
+ name = "Dorm Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = -25;
+ specialfunctions = 4
+ },
+/obj/effect/decal/cleanable/cobweb,
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 8
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
+"aaV" = (
+/obj/machinery/button/door{
+ id = "Cabin7";
+ name = "Door Bolt Control";
+ normaldoorcontrol = 1;
+ pixel_x = -25;
+ specialfunctions = 4
+ },
+/obj/structure/bed,
+/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
+ dir = 8
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
"aaY" = (
/obj/structure/cable{
icon_state = "1-2"
@@ -10141,22 +10233,6 @@
/obj/item/clothing/under/assistantformal,
/turf/open/floor/wood,
/area/crew_quarters/dorms)
-"asV" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/button/door{
- id = "Cabin3";
- name = "Cabin Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 25;
- specialfunctions = 4
- },
-/obj/effect/decal/cleanable/cobweb/cobweb2,
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"asW" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
@@ -10195,23 +10271,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/dorms)
-"ata" = (
-/obj/machinery/light/small{
- dir = 1
- },
-/obj/effect/decal/cleanable/cobweb,
-/obj/machinery/button/door{
- id = "Cabin4";
- name = "Cabin Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = -25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/obj/structure/bed,
-/obj/item/bedsheet,
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"atb" = (
/obj/structure/closet/secure_closet/personal/cabinet,
/obj/machinery/airalarm{
@@ -11892,21 +11951,6 @@
/obj/item/clothing/under/suit_jacket/tan,
/turf/open/floor/carpet,
/area/crew_quarters/dorms)
-"awE" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/button/door{
- id = "Cabin2";
- name = "Cabin Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = 25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_pump/on{
- dir = 4
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"awF" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 4
@@ -11920,19 +11964,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/dorms)
-"awG" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/button/door{
- id = "Cabin5";
- name = "Dorm Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = -25;
- specialfunctions = 4
- },
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"awH" = (
/obj/machinery/newscaster{
pixel_y = 32
@@ -14983,22 +15014,6 @@
},
/turf/open/floor/plasteel,
/area/crew_quarters/dorms)
-"aCJ" = (
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/button/door{
- id = "Cabin6";
- name = "Dorm Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = -25;
- specialfunctions = 4
- },
-/obj/effect/decal/cleanable/cobweb,
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 8
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"aCK" = (
/obj/structure/closet/secure_closet/personal/cabinet,
/obj/machinery/airalarm{
@@ -17575,21 +17590,6 @@
},
/turf/open/floor/plasteel/dark,
/area/crew_quarters/dorms)
-"aHS" = (
-/obj/machinery/button/door{
- id = "Cabin7";
- name = "Door Bolt Control";
- normaldoorcontrol = 1;
- pixel_x = -25;
- specialfunctions = 4
- },
-/obj/structure/bed,
-/obj/item/bedsheet,
-/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
- dir = 8
- },
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"aHT" = (
/obj/structure/chair/wood/normal{
dir = 4
@@ -17692,7 +17692,9 @@
pixel_x = -28;
pixel_y = 23
},
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_y = 32
+ },
/obj/machinery/conveyor{
dir = 5;
id = "QMLoad2"
@@ -21617,7 +21619,9 @@
/obj/structure/table,
/obj/item/clipboard,
/obj/item/stamp/qm,
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_x = 32
+ },
/turf/open/floor/plasteel,
/area/quartermaster/qm)
"aQu" = (
@@ -27037,7 +27041,9 @@
/area/hallway/primary/port)
"baA" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_y = 32
+ },
/obj/structure/table,
/obj/item/folder/yellow,
/obj/effect/turf_decal/tile/brown{
@@ -27920,7 +27926,9 @@
/area/quartermaster/office)
"bbS" = (
/obj/machinery/atmospherics/components/unary/vent_scrubber/on,
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_y = 32
+ },
/obj/effect/turf_decal/tile/brown{
dir = 1
},
@@ -31526,6 +31534,10 @@
/obj/effect/turf_decal/tile/brown{
dir = 8
},
+/obj/structure/closet/crate{
+ icon_state = "crateopen"
+ },
+/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plasteel,
/area/hallway/primary/port)
"biO" = (
@@ -32402,10 +32414,6 @@
/turf/open/floor/plasteel,
/area/quartermaster/office)
"bks" = (
-/obj/structure/closet/crate{
- icon_state = "crateopen"
- },
-/obj/effect/spawner/lootdrop/maintenance,
/obj/effect/turf_decal/tile/brown{
dir = 1
},
@@ -32413,6 +32421,9 @@
/obj/effect/turf_decal/tile/brown{
dir = 8
},
+/obj/machinery/autolathe{
+ name = "public autolathe"
+ },
/turf/open/floor/plasteel,
/area/hallway/primary/port)
"bkt" = (
@@ -47699,12 +47710,12 @@
},
/obj/structure/window/reinforced,
/obj/structure/rack,
-/obj/item/tank/jetpack/carbondioxide{
+/obj/item/tank/jetpack/carbondioxide/eva{
pixel_x = 4;
pixel_y = -1
},
-/obj/item/tank/jetpack/carbondioxide,
-/obj/item/tank/jetpack/carbondioxide{
+/obj/item/tank/jetpack/carbondioxide/eva,
+/obj/item/tank/jetpack/carbondioxide/eva{
pixel_x = -4;
pixel_y = 1
},
@@ -64367,6 +64378,7 @@
/obj/structure/cable/yellow{
icon_state = "1-8"
},
+/obj/effect/landmark/start/medical_doctor,
/turf/open/floor/plasteel/white,
/area/medical/patients_rooms/room_a)
"cum" = (
@@ -65463,24 +65475,9 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"cwo" = (
-/obj/structure/table,
-/obj/item/folder/white{
- pixel_x = 4;
- pixel_y = -3
- },
-/obj/item/clothing/neck/stethoscope,
/obj/machinery/light/small{
dir = 8
},
-/obj/machinery/power/apc{
- dir = 8;
- name = "Patient Room B APC";
- areastring = "/area/medical/patients_rooms/room_b";
- pixel_x = -26
- },
-/obj/structure/cable/yellow{
- icon_state = "0-4"
- },
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden{
dir = 8
},
@@ -65493,31 +65490,24 @@
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/chem_dispenser{
+ layer = 2.7
+ },
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cwp" = (
/obj/structure/chair/office/light{
dir = 8
},
-/obj/structure/cable/yellow{
- icon_state = "2-8"
- },
-/obj/effect/landmark/start/medical_doctor,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/machinery/vending/wallmed{
- pixel_y = 28
+/obj/machinery/airalarm{
+ pixel_y = 23
},
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cwq" = (
-/obj/structure/closet/secure_closet/personal/patient,
-/obj/machinery/button/door{
- id = "isolb";
- name = "Privacy Shutters";
- pixel_y = 25
- },
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
@@ -65525,19 +65515,19 @@
/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/machinery/chem_heater{
+ pixel_x = 4
+ },
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cwr" = (
-/obj/effect/spawner/structure/window,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 4
},
-/obj/machinery/door/poddoor/preopen{
- id = "isolb";
- name = "privacy shutters"
- },
+/obj/effect/spawner/structure/window/reinforced,
+/obj/machinery/door/firedoor,
/turf/open/floor/plating,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cws" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
@@ -65962,65 +65952,53 @@
/turf/open/floor/plating,
/area/maintenance/port/aft)
"cxe" = (
-/obj/structure/bed,
-/obj/item/bedsheet/medical,
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{
dir = 5
},
-/obj/machinery/airalarm{
- dir = 4;
- pixel_x = -23
- },
/obj/effect/turf_decal/tile/blue{
dir = 1
},
/obj/effect/turf_decal/tile/blue{
dir = 8
},
+/obj/machinery/chem_master,
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cxf" = (
-/obj/structure/cable/yellow{
- icon_state = "1-4"
- },
/obj/machinery/atmospherics/components/unary/vent_scrubber/on{
dir = 8
},
+/obj/machinery/firealarm{
+ dir = 1;
+ pixel_y = -24
+ },
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cxg" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 4
},
-/obj/structure/cable/yellow{
- icon_state = "4-8"
- },
/obj/effect/turf_decal/tile/blue,
/obj/effect/turf_decal/tile/blue{
dir = 4
},
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cxh" = (
-/obj/machinery/door/airlock/medical{
- name = "Patient Room B";
- req_access_txt = "5"
- },
-/obj/structure/cable/yellow{
- icon_state = "4-8"
- },
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
+/obj/machinery/door/airlock/medical/glass{
+ name = "Apothecary";
+ req_access_txt = "5"
+ },
+/obj/machinery/door/firedoor,
/turf/open/floor/plasteel/white,
-/area/medical/patients_rooms/room_b)
+/area/medical/medbay/aft)
"cxi" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 4
},
-/obj/structure/cable/yellow{
- icon_state = "4-8"
- },
/obj/effect/turf_decal/tile/blue{
dir = 1
},
@@ -66033,9 +66011,6 @@
/obj/structure/cable/yellow{
icon_state = "1-2"
},
-/obj/structure/cable/yellow{
- icon_state = "1-8"
- },
/turf/open/floor/plasteel/white,
/area/medical/medbay/aft)
"cxk" = (
@@ -105762,8 +105737,8 @@ css
dux
dux
dux
-dux
-dux
+cxU
+cxU
cxU
cyO
czP
@@ -120078,10 +120053,10 @@ agz
aoV
dhs
arB
-asV
+aab
auf
arB
-awE
+aae
axE
arB
dhA
@@ -121620,19 +121595,19 @@ anK
aoZ
aqk
arB
-ata
+aad
aul
avp
-awG
+aaM
axJ
avp
aAj
arB
-aCJ
+aaU
aEe
arB
boS
-aHS
+aaV
aJh
aKt
aLW
diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm
index dbb26f8808..cef0aefc50 100644
--- a/_maps/map_files/OmegaStation/OmegaStation.dmm
+++ b/_maps/map_files/OmegaStation/OmegaStation.dmm
@@ -2833,7 +2833,9 @@
/turf/open/floor/plasteel/dark,
/area/crew_quarters/heads/hop)
"aeP" = (
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_x = -32
+ },
/obj/effect/turf_decal/loading_area,
/turf/open/floor/plasteel,
/area/quartermaster/storage)
diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm
index 4a8eee364c..e03ba4fcd2 100644
--- a/_maps/map_files/PubbyStation/PubbyStation.dmm
+++ b/_maps/map_files/PubbyStation/PubbyStation.dmm
@@ -2,12 +2,44 @@
"aaa" = (
/turf/open/space/basic,
/area/space)
+"aab" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Dorm3Shutters";
+ name = "Privacy Shutters Control";
+ pixel_y = 26
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/wood,
+/area/crew_quarters/dorms)
+"aac" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Dorm2Shutters";
+ name = "Privacy Shutters Control";
+ pixel_y = 26;
+ req_access_txt = "0"
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/carpet,
+/area/crew_quarters/dorms)
"aad" = (
/obj/effect/spawner/lootdrop/maintenance,
/turf/open/floor/plating{
icon_state = "platingdmg3"
},
/area/maintenance/department/science)
+"aae" = (
+/obj/structure/bed,
+/obj/machinery/button/door{
+ id = "Dorm1Shutters";
+ name = "Privacy Shutters Control";
+ pixel_y = 26;
+ req_access_txt = "0"
+ },
+/obj/effect/spawner/lootdrop/bedsheet,
+/turf/open/floor/plasteel/grimy,
+/area/crew_quarters/dorms)
"abf" = (
/obj/structure/bed,
/turf/open/floor/plating,
@@ -8605,16 +8637,6 @@
},
/turf/open/floor/plating,
/area/crew_quarters/dorms)
-"ave" = (
-/obj/structure/bed,
-/obj/item/bedsheet/nanotrasen,
-/obj/machinery/button/door{
- id = "Dorm3Shutters";
- name = "Privacy Shutters Control";
- pixel_y = 26
- },
-/turf/open/floor/wood,
-/area/crew_quarters/dorms)
"avf" = (
/obj/machinery/light/small{
dir = 1
@@ -10058,17 +10080,6 @@
},
/turf/open/floor/plating,
/area/crew_quarters/dorms)
-"ayj" = (
-/obj/structure/bed,
-/obj/item/bedsheet/nanotrasen,
-/obj/machinery/button/door{
- id = "Dorm2Shutters";
- name = "Privacy Shutters Control";
- pixel_y = 26;
- req_access_txt = "0"
- },
-/turf/open/floor/carpet,
-/area/crew_quarters/dorms)
"ayk" = (
/obj/machinery/light/small{
dir = 1
@@ -11516,17 +11527,6 @@
},
/turf/open/floor/plating,
/area/crew_quarters/dorms)
-"aBM" = (
-/obj/structure/bed,
-/obj/item/bedsheet/nanotrasen,
-/obj/machinery/button/door{
- id = "Dorm1Shutters";
- name = "Privacy Shutters Control";
- pixel_y = 26;
- req_access_txt = "0"
- },
-/turf/open/floor/plasteel/grimy,
-/area/crew_quarters/dorms)
"aBN" = (
/obj/machinery/light/small{
dir = 1
@@ -16464,8 +16464,8 @@
/area/storage/eva)
"aNt" = (
/obj/structure/rack,
-/obj/item/tank/jetpack/carbondioxide,
-/obj/item/tank/jetpack/carbondioxide{
+/obj/item/tank/jetpack/carbondioxide/eva,
+/obj/item/tank/jetpack/carbondioxide/eva{
pixel_x = -4;
pixel_y = 1
},
@@ -17294,7 +17294,7 @@
lootcount = 2;
name = "2maintenance loot spawner"
},
-/obj/item/clothing/gloves/color/random,
+/obj/effect/spawner/lootdrop/gloves,
/turf/open/floor/plating,
/area/maintenance/department/crew_quarters/bar)
"aPD" = (
@@ -21743,7 +21743,9 @@
/turf/open/floor/plasteel,
/area/hallway/primary/central)
"aZj" = (
-/obj/machinery/status_display/supply,
+/obj/machinery/status_display/supply{
+ pixel_x = -32
+ },
/obj/machinery/computer/bounty{
dir = 4
},
@@ -35713,13 +35715,13 @@
/obj/structure/extinguisher_cabinet{
pixel_x = -26
},
-/obj/machinery/rnd/production/protolathe/department/medical,
/obj/effect/turf_decal/tile/blue{
dir = 1
},
/obj/effect/turf_decal/tile/blue{
dir = 4
},
+/obj/machinery/rnd/production/techfab/department/medical,
/turf/open/floor/plasteel/white,
/area/medical/medbay/central)
"bEw" = (
@@ -36058,7 +36060,9 @@
/obj/item/folder/white,
/obj/item/pen,
/obj/item/stamp/rd,
-/obj/machinery/status_display/ai,
+/obj/machinery/status_display/ai{
+ pixel_y = -32
+ },
/obj/machinery/camera{
c_tag = "Research Director's Office";
dir = 1;
@@ -44325,7 +44329,9 @@
dir = 1;
pixel_y = -22
},
-/obj/structure/closet/radiation,
+/obj/machinery/shower{
+ dir = 4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bWF" = (
@@ -44352,7 +44358,10 @@
dir = 6
},
/obj/effect/turf_decal/delivery,
-/obj/structure/closet/radiation,
+/obj/machinery/shower{
+ dir = 8;
+ pixel_y = -4
+ },
/turf/open/floor/plasteel,
/area/engine/break_room)
"bWH" = (
@@ -44932,6 +44941,7 @@
/obj/effect/turf_decal/stripes/line{
dir = 1
},
+/obj/structure/closet/radiation,
/turf/open/floor/plasteel,
/area/engine/engineering)
"bYn" = (
@@ -44956,6 +44966,7 @@
/obj/machinery/light{
dir = 4
},
+/obj/structure/closet/radiation,
/turf/open/floor/plasteel,
/area/engine/engineering)
"bYp" = (
@@ -53780,7 +53791,7 @@
"eSB" = (
/obj/machinery/computer/cryopod{
dir = 1;
- pixel_y = -26;
+ pixel_y = -26
},
/turf/open/floor/plasteel/dark,
/area/security/prison)
@@ -99261,13 +99272,13 @@ ale
asb
coe
apX
-ave
+aab
awn
apX
-ayj
+aac
azr
apX
-aBM
+aae
aDb
apX
oFo
diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm
index d005f1eb40..d796330cc8 100644
--- a/_maps/map_files/generic/CentCom.dmm
+++ b/_maps/map_files/generic/CentCom.dmm
@@ -2248,6 +2248,11 @@
},
/turf/open/floor/plasteel,
/area/tdome/arena_source)
+"fR" = (
+/obj/item/paicard,
+/obj/structure/table/wood,
+/turf/open/floor/engine/cult,
+/area/wizard_station)
"fS" = (
/obj/effect/turf_decal/tile/red{
dir = 8
@@ -2935,6 +2940,22 @@
/obj/machinery/capture_the_flag/red,
/turf/open/floor/circuit/green/anim,
/area/ctf)
+"hH" = (
+/obj/structure/table/reinforced,
+/obj/item/flashlight/seclite,
+/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/item/paicard,
+/turf/open/floor/plasteel/dark,
+/area/centcom/ferry)
"hI" = (
/obj/effect/turf_decal/stripes/line{
dir = 10
@@ -11370,21 +11391,6 @@
/obj/structure/table/reinforced,
/turf/open/floor/plasteel/grimy,
/area/centcom/ferry)
-"AL" = (
-/obj/structure/table/reinforced,
-/obj/item/flashlight/seclite,
-/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/centcom/ferry)
"AM" = (
/obj/machinery/shuttle_manipulator,
/turf/open/floor/circuit/green,
@@ -25222,7 +25228,7 @@ lI
lI
lI
Ax
-qZ
+EW
qZ
qZ
Ax
@@ -25480,7 +25486,7 @@ lI
lI
Ax
ra
-qZ
+Bf
qZ
tX
qZ
@@ -25736,7 +25742,7 @@ lI
lI
lI
Ax
-qZ
+fR
qZ
qZ
Ax
@@ -56332,7 +56338,7 @@ yr
sw
sw
Ad
-AL
+hH
Bx
sw
Cv
diff --git a/_maps/shuttles/pirate_default.dmm b/_maps/shuttles/pirate_default.dmm
index 445c29241c..1c8670d5b6 100644
--- a/_maps/shuttles/pirate_default.dmm
+++ b/_maps/shuttles/pirate_default.dmm
@@ -239,6 +239,23 @@
},
/turf/open/floor/plasteel,
/area/shuttle/pirate)
+"as" = (
+/obj/machinery/atmospherics/components/unary/vent_pump/on,
+/obj/structure/closet/secure_closet/personal,
+/obj/effect/decal/cleanable/dirt,
+/obj/item/bedsheet/pirate,
+/turf/open/floor/plasteel,
+/area/shuttle/pirate)
+"at" = (
+/obj/structure/closet/secure_closet/personal,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/obj/item/bedsheet/pirate,
+/turf/open/floor/plasteel,
+/area/shuttle/pirate)
"au" = (
/obj/machinery/door/airlock/hatch{
id_tag = "piratebridgebolt";
@@ -314,6 +331,13 @@
},
/turf/open/floor/plasteel,
/area/shuttle/pirate)
+"aA" = (
+/obj/structure/closet/secure_closet/personal,
+/obj/effect/decal/cleanable/dirt,
+/obj/effect/turf_decal/stripes/line,
+/obj/item/bedsheet/pirate,
+/turf/open/floor/wood,
+/area/shuttle/pirate)
"aB" = (
/obj/machinery/light/small{
dir = 4
@@ -408,12 +432,6 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
/area/shuttle/pirate)
-"aM" = (
-/obj/structure/closet/secure_closet/personal,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/stripes/line,
-/turf/open/floor/wood,
-/area/shuttle/pirate)
"aN" = (
/obj/machinery/light/small,
/obj/machinery/button/door{
@@ -1022,12 +1040,6 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plating,
/area/shuttle/pirate)
-"mD" = (
-/obj/machinery/atmospherics/components/unary/vent_pump/on,
-/obj/structure/closet/secure_closet/personal,
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plasteel,
-/area/shuttle/pirate)
"mU" = (
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
/obj/machinery/door/airlock/engineering{
@@ -1172,15 +1184,6 @@
},
/turf/open/floor/wood,
/area/shuttle/pirate)
-"Ur" = (
-/obj/structure/closet/secure_closet/personal,
-/obj/effect/decal/cleanable/dirt,
-/obj/effect/turf_decal/tile/neutral,
-/obj/effect/turf_decal/tile/neutral{
- dir = 8
- },
-/turf/open/floor/plasteel,
-/area/shuttle/pirate)
(1,1,1) = {"
af
@@ -1231,7 +1234,7 @@ aq
ar
aj
RY
-aM
+aA
ep
aH
af
@@ -1406,9 +1409,9 @@ af
af
af
aj
-mD
+as
bB
-Ur
+at
aj
aj
aj
diff --git a/_maps/shuttles/ruin_pirate_cutter.dmm b/_maps/shuttles/ruin_pirate_cutter.dmm
index 4e36ea9edf..424436f1b3 100644
--- a/_maps/shuttles/ruin_pirate_cutter.dmm
+++ b/_maps/shuttles/ruin_pirate_cutter.dmm
@@ -1,7 +1,81 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"aa" = (
+/obj/structure/bed,
+/obj/machinery/firealarm{
+ dir = 8;
+ pixel_x = -26
+ },
+/obj/item/bedsheet/pirate,
+/turf/open/floor/plasteel/dark/side{
+ dir = 6
+ },
+/area/shuttle/caravan/pirate)
+"ab" = (
+/obj/structure/chair/office/dark{
+ dir = 4
+ },
+/obj/machinery/turretid{
+ icon_state = "control_kill";
+ lethal = 1;
+ locked = 0;
+ pixel_y = -30;
+ req_access = null
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 1
+ },
+/obj/effect/turf_decal/tile/neutral,
+/obj/effect/turf_decal/tile/neutral{
+ dir = 4
+ },
+/obj/effect/turf_decal/tile/neutral{
+ dir = 8
+ },
+/mob/living/simple_animal/hostile/pirate/ranged{
+ environment_smash = 0
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/caravan/pirate)
+"ac" = (
+/obj/structure/bed,
+/obj/machinery/airalarm/all_access{
+ dir = 4;
+ pixel_x = -24
+ },
+/obj/effect/turf_decal/tile/red{
+ dir = 8
+ },
+/obj/item/bedsheet/pirate,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/caravan/pirate)
+"ad" = (
+/obj/effect/decal/cleanable/dirt,
+/mob/living/simple_animal/hostile/pirate/ranged{
+ environment_smash = 0
+ },
+/turf/open/floor/plasteel,
+/area/shuttle/caravan/pirate)
+"ae" = (
+/obj/structure/rack,
+/obj/item/storage/bag/money/vault,
+/obj/effect/turf_decal/tile/blue{
+ dir = 4
+ },
+/mob/living/simple_animal/parrot{
+ faction = list("pirate");
+ name = "Pegwing"
+ },
+/turf/open/floor/plasteel/dark,
+/area/shuttle/caravan/pirate)
"af" = (
/turf/closed/wall/mineral/plastitanium/nodiagonal,
/area/shuttle/caravan/pirate)
+"ag" = (
+/obj/machinery/light/small,
+/obj/structure/bed,
+/obj/item/bedsheet/pirate,
+/turf/open/floor/plasteel/dark,
+/area/shuttle/caravan/pirate)
"aE" = (
/obj/structure/closet{
name = "pirate outfits"
@@ -89,18 +163,6 @@
},
/turf/open/floor/plasteel/dark,
/area/shuttle/caravan/pirate)
-"fS" = (
-/obj/structure/bed,
-/obj/item/bedsheet/brown,
-/obj/machinery/airalarm/all_access{
- dir = 4;
- pixel_x = -24
- },
-/obj/effect/turf_decal/tile/red{
- dir = 8
- },
-/turf/open/floor/plasteel/dark,
-/area/shuttle/caravan/pirate)
"fU" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden,
/obj/effect/turf_decal/tile/red,
@@ -223,18 +285,6 @@
dir = 1
},
/area/shuttle/caravan/pirate)
-"ku" = (
-/obj/structure/rack,
-/obj/item/storage/bag/money/vault,
-/mob/living/simple_animal/parrot{
- faction = list("pirate");
- name = "Pegwing"
- },
-/obj/effect/turf_decal/tile/blue{
- dir = 4
- },
-/turf/open/floor/plasteel/dark,
-/area/shuttle/caravan/pirate)
"kY" = (
/obj/machinery/atmospherics/pipe/manifold/supply/hidden{
dir = 8
@@ -502,13 +552,6 @@
/obj/item/reagent_containers/food/drinks/bottle/rum,
/turf/open/floor/plasteel/dark,
/area/shuttle/caravan/pirate)
-"tM" = (
-/mob/living/simple_animal/hostile/pirate/ranged{
- environment_smash = 0
- },
-/obj/effect/decal/cleanable/dirt,
-/turf/open/floor/plasteel,
-/area/shuttle/caravan/pirate)
"ul" = (
/obj/structure/table,
/obj/item/retractor,
@@ -535,17 +578,6 @@
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/plasteel,
/area/shuttle/caravan/pirate)
-"vq" = (
-/obj/structure/bed,
-/obj/item/bedsheet/brown,
-/obj/machinery/firealarm{
- dir = 8;
- pixel_x = -26
- },
-/turf/open/floor/plasteel/dark/side{
- dir = 6
- },
-/area/shuttle/caravan/pirate)
"vW" = (
/obj/machinery/light/small{
dir = 4
@@ -734,32 +766,6 @@
},
/turf/open/floor/plasteel/dark,
/area/shuttle/caravan/pirate)
-"EB" = (
-/obj/structure/chair/office/dark{
- dir = 4
- },
-/obj/machinery/turretid{
- icon_state = "control_kill";
- lethal = 1;
- locked = 0;
- pixel_y = -30;
- req_access = null
- },
-/mob/living/simple_animal/hostile/pirate/ranged{
- environment_smash = 0
- },
-/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/shuttle/caravan/pirate)
"EK" = (
/obj/machinery/atmospherics/components/unary/vent_pump/on{
dir = 1
@@ -1018,12 +1024,6 @@
},
/turf/open/floor/plasteel/dark,
/area/shuttle/caravan/pirate)
-"Wb" = (
-/obj/machinery/light/small,
-/obj/structure/bed,
-/obj/item/bedsheet/brown,
-/turf/open/floor/plasteel/dark,
-/area/shuttle/caravan/pirate)
"Xq" = (
/obj/structure/table/reinforced,
/obj/machinery/recharger,
@@ -1181,7 +1181,7 @@ su
Ag
af
jo
-tM
+ad
sr
af
af
@@ -1253,9 +1253,9 @@ Jv
af
aE
SF
-vq
+aa
NM
-fS
+ac
RC
oF
af
@@ -1272,7 +1272,7 @@ hZ
wZ
de
iF
-Wb
+ag
af
Jv
Jv
@@ -1286,7 +1286,7 @@ xg
qC
pK
Sk
-ku
+ae
af
qo
Jv
@@ -1374,7 +1374,7 @@ Jv
Jv
Bi
oO
-EB
+ab
bd
Bi
Jv
diff --git a/code/__DEFINES/antagonists.dm b/code/__DEFINES/antagonists.dm
index 4c454aa61a..e35defd485 100644
--- a/code/__DEFINES/antagonists.dm
+++ b/code/__DEFINES/antagonists.dm
@@ -35,3 +35,8 @@
//Overthrow time to update heads obj
#define OBJECTIVE_UPDATING_TIME 300
+
+//Gangshit
+#define NOT_DOMINATING -1
+#define MAX_LEADERS_GANG 3
+#define INITIAL_DOM_ATTEMPTS 3
diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm
index b5ba44d956..928837979c 100644
--- a/code/__DEFINES/atmospherics.dm
+++ b/code/__DEFINES/atmospherics.dm
@@ -1,8 +1,5 @@
//LISTMOS
//indices of values in gas lists.
-#define MOLES 1
-#define ARCHIVE 2
-#define GAS_META 3
#define META_GAS_SPECIFIC_HEAT 1
#define META_GAS_NAME 2
#define META_GAS_MOLES_VISIBLE 3
@@ -242,20 +239,25 @@
//HELPERS
#define THERMAL_ENERGY(gas) (gas.temperature * gas.heat_capacity())
-
-#define ADD_GAS(gas_id, out_list)\
- var/list/tmp_gaslist = GLOB.gaslist_cache[gas_id]; out_list[gas_id] = tmp_gaslist.Copy();
-
-#define ASSERT_GAS(gas_id, gas_mixture) if (!gas_mixture.gases[gas_id]) { ADD_GAS(gas_id, gas_mixture.gases) };
-
+#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
+ once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
//prefer this to gas_mixture/total_moles in performance critical areas
#define TOTAL_MOLES(cached_gases, out_var)\
out_var = 0;\
for(var/total_moles_id in cached_gases){\
- out_var += cached_gases[total_moles_id][MOLES];\
+ out_var += cached_gases[total_moles_id];\
}
+//Unomos - So for whatever reason, garbage collection actually drastically decreases the cost of atmos later in the round. Turning this into a define yields massively improved performance.
+#define GAS_GARBAGE_COLLECT(GASGASGAS)\
+ var/list/CACHE_GAS = GASGASGAS;\
+ for(var/id in CACHE_GAS){\
+ if(QUANTIZE(CACHE_GAS[id]) <= 0)\
+ CACHE_GAS -= id;\
+ }
+
+#define ARCHIVE_TEMPERATURE(gas) gas.temperature_archived = gas.temperature
GLOBAL_LIST_INIT(pipe_paint_colors, list(
"amethyst" = rgb(130,43,255), //supplymain
diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm
index 9f5f52180c..2abe0db04e 100644
--- a/code/__DEFINES/citadel_defines.dm
+++ b/code/__DEFINES/citadel_defines.dm
@@ -33,8 +33,8 @@
#define BALLS_VOLUME_MULT 1
#define BALLS_SIZE_MIN 1
-#define BALLS_SIZE_DEF 3
-#define BALLS_SIZE_MAX 7
+#define BALLS_SIZE_DEF 2
+#define BALLS_SIZE_MAX 3
#define BALLS_SACK_SIZE_MIN 1
#define BALLS_SACK_SIZE_DEF 8
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 15e8048926..7cab82149d 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -79,6 +79,8 @@
#define ATTACK_EFFECT_SMASH "smash"
#define ATTACK_EFFECT_CLAW "claw"
#define ATTACK_EFFECT_DISARM "disarm"
+#define ATTACK_EFFECT_ASS_SLAP "ass_slap"
+#define ATTACK_EFFECT_FACE_SLAP "face_slap"
#define ATTACK_EFFECT_BITE "bite"
#define ATTACK_EFFECT_MECHFIRE "mech_fire"
#define ATTACK_EFFECT_MECHTOXIN "mech_toxin"
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index 3338fc1cda..8d86826ac2 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -130,6 +130,17 @@
#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
+#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
+#define COMSIG_MOB_SAY "mob_say" // from /mob/living/say(): (proc args list)
+ #define COMPONENT_UPPERCASE_SPEECH 1
+ // used to access COMSIG_MOB_SAY argslist
+ #define SPEECH_MESSAGE 1
+ // #define SPEECH_BUBBLE_TYPE 2
+ #define SPEECH_SPANS 3
+ /* #define SPEECH_SANITIZE 4
+ #define SPEECH_LANGUAGE 5
+ #define SPEECH_IGNORE_SPAM 6
+ #define SPEECH_FORCED 7 */
// /mob/living signals
#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)
@@ -142,8 +153,9 @@
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
// /obj signals
-#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
-#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
+#define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled)
+#define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag)
+#define COMSIG_OBJ_SETANCHORED "obj_setanchored" //called in /obj/structure/setAnchored(): (value)
// /obj/item signals
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
diff --git a/code/__DEFINES/construction.dm b/code/__DEFINES/construction.dm
index 9f3d38efa1..ee51fb6909 100644
--- a/code/__DEFINES/construction.dm
+++ b/code/__DEFINES/construction.dm
@@ -102,7 +102,8 @@
#define CAT_SANDWICH "Sandwiches"
#define CAT_SOUP "Soups"
#define CAT_SPAGHETTI "Spaghettis"
-#define CAT_SUSHI "Fish"
+#define CAT_FISH "Fish"
+#define CAT_ICE "Frozen"
#define RCD_FLOORWALL 1
#define RCD_AIRLOCK 2
diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm
index ad9aef5a8b..2fe70961f8 100644
--- a/code/__DEFINES/flags.dm
+++ b/code/__DEFINES/flags.dm
@@ -8,6 +8,7 @@
#define ENABLE_BITFIELD(variable, flag) (variable |= (flag))
#define DISABLE_BITFIELD(variable, flag) (variable &= ~(flag))
#define CHECK_BITFIELD(variable, flag) (variable & flag)
+#define TOGGLE_BITFIELD(variable, flag) (variable ^= (flag))
GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768))
@@ -56,9 +57,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
#define FLYING (1<<1)
#define VENTCRAWLING (1<<2)
-// Flags for reagents
-#define REAGENT_NOREACT (1<<0)
-
//Fire and Acid stuff, for resistance_flags
#define LAVA_PROOF (1<<0)
#define FIRE_PROOF (1<<1) //100% immune to fire damage (but not necessarily to lava or heat)
diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm
index 2c7a66ce40..15c7af5749 100644
--- a/code/__DEFINES/food.dm
+++ b/code/__DEFINES/food.dm
@@ -16,3 +16,4 @@
#define DRINK_GOOD 2
#define DRINK_VERYGOOD 3
#define DRINK_FANTASTIC 4
+#define FOOD_AMAZING 5
diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm
index e66d518644..ef96b83cc8 100644
--- a/code/__DEFINES/footsteps.dm
+++ b/code/__DEFINES/footsteps.dm
@@ -6,6 +6,14 @@
#define FOOTSTEP_GRASS "grass"
#define FOOTSTEP_WATER "water"
#define FOOTSTEP_LAVA "lava"
+//barefoot sounds
+#define FOOTSTEP_WOOD_BAREFOOT "woodbarefoot"
+#define FOOTSTEP_WOOD_CLAW "woodclaw"
+#define FOOTSTEP_HARD_BAREFOOT "hardbarefoot"
+#define FOOTSTEP_HARD_CLAW "hardclaw"
+#define FOOTSTEP_CARPET_BAREFOOT "carpetbarefoot"
+//misc footstep sounds
+#define FOOTSTEP_GENERIC_HEAVY "heavy"
/*
@@ -63,4 +71,104 @@ GLOBAL_LIST_INIT(footstep, list(
'sound/effects/footstep/lava1.ogg',
'sound/effects/footstep/lava2.ogg',
'sound/effects/footstep/lava3.ogg'), 100, 0),
-))
\ No newline at end of file
+))
+
+//bare footsteps lists
+GLOBAL_LIST_INIT(barefootstep, list(
+ FOOTSTEP_WOOD_BAREFOOT = list(list(
+ 'sound/effects/footstep/woodbarefoot1.ogg',
+ 'sound/effects/footstep/woodbarefoot2.ogg',
+ 'sound/effects/footstep/woodbarefoot3.ogg',
+ 'sound/effects/footstep/woodbarefoot4.ogg',
+ 'sound/effects/footstep/woodbarefoot5.ogg'), 80, -1),
+ FOOTSTEP_HARD_BAREFOOT = list(list(
+ 'sound/effects/footstep/hardbarefoot1.ogg',
+ 'sound/effects/footstep/hardbarefoot2.ogg',
+ 'sound/effects/footstep/hardbarefoot3.ogg',
+ 'sound/effects/footstep/hardbarefoot4.ogg',
+ 'sound/effects/footstep/hardbarefoot5.ogg'), 80, -1),
+ FOOTSTEP_CARPET_BAREFOOT = list(list(
+ 'sound/effects/footstep/carpetbarefoot1.ogg',
+ 'sound/effects/footstep/carpetbarefoot2.ogg',
+ 'sound/effects/footstep/carpetbarefoot3.ogg',
+ 'sound/effects/footstep/carpetbarefoot4.ogg',
+ 'sound/effects/footstep/carpetbarefoot5.ogg'), 75, -2),
+ FOOTSTEP_SAND = list(list(
+ 'sound/effects/footstep/asteroid1.ogg',
+ 'sound/effects/footstep/asteroid2.ogg',
+ 'sound/effects/footstep/asteroid3.ogg',
+ 'sound/effects/footstep/asteroid4.ogg',
+ 'sound/effects/footstep/asteroid5.ogg'), 75, 0),
+ FOOTSTEP_GRASS = list(list(
+ 'sound/effects/footstep/grass1.ogg',
+ 'sound/effects/footstep/grass2.ogg',
+ 'sound/effects/footstep/grass3.ogg',
+ 'sound/effects/footstep/grass4.ogg'), 75, 0),
+ FOOTSTEP_WATER = list(list(
+ 'sound/effects/footstep/water1.ogg',
+ 'sound/effects/footstep/water2.ogg',
+ 'sound/effects/footstep/water3.ogg',
+ 'sound/effects/footstep/water4.ogg'), 100, 1),
+ FOOTSTEP_LAVA = list(list(
+ 'sound/effects/footstep/lava1.ogg',
+ 'sound/effects/footstep/lava2.ogg',
+ 'sound/effects/footstep/lava3.ogg'), 100, 0),
+))
+
+//claw footsteps lists
+GLOBAL_LIST_INIT(clawfootstep, list(
+ FOOTSTEP_WOOD_CLAW = list(list(
+ 'sound/effects/footstep/woodclaw1.ogg',
+ 'sound/effects/footstep/woodclaw2.ogg',
+ 'sound/effects/footstep/woodclaw3.ogg',
+ 'sound/effects/footstep/woodclaw2.ogg',
+ 'sound/effects/footstep/woodclaw1.ogg'), 90, 1),
+ FOOTSTEP_HARD_CLAW = list(list(
+ 'sound/effects/footstep/hardclaw1.ogg',
+ 'sound/effects/footstep/hardclaw2.ogg',
+ 'sound/effects/footstep/hardclaw3.ogg',
+ 'sound/effects/footstep/hardclaw4.ogg',
+ 'sound/effects/footstep/hardclaw1.ogg'), 90, 1),
+ FOOTSTEP_CARPET_BAREFOOT = list(list(
+ 'sound/effects/footstep/carpetbarefoot1.ogg',
+ 'sound/effects/footstep/carpetbarefoot2.ogg',
+ 'sound/effects/footstep/carpetbarefoot3.ogg',
+ 'sound/effects/footstep/carpetbarefoot4.ogg',
+ 'sound/effects/footstep/carpetbarefoot5.ogg'), 75, -2),
+ FOOTSTEP_SAND = list(list(
+ 'sound/effects/footstep/asteroid1.ogg',
+ 'sound/effects/footstep/asteroid2.ogg',
+ 'sound/effects/footstep/asteroid3.ogg',
+ 'sound/effects/footstep/asteroid4.ogg',
+ 'sound/effects/footstep/asteroid5.ogg'), 75, 0),
+ FOOTSTEP_GRASS = list(list(
+ 'sound/effects/footstep/grass1.ogg',
+ 'sound/effects/footstep/grass2.ogg',
+ 'sound/effects/footstep/grass3.ogg',
+ 'sound/effects/footstep/grass4.ogg'), 75, 0),
+ FOOTSTEP_WATER = list(list(
+ 'sound/effects/footstep/water1.ogg',
+ 'sound/effects/footstep/water2.ogg',
+ 'sound/effects/footstep/water3.ogg',
+ 'sound/effects/footstep/water4.ogg'), 100, 1),
+ FOOTSTEP_LAVA = list(list(
+ 'sound/effects/footstep/lava1.ogg',
+ 'sound/effects/footstep/lava2.ogg',
+ 'sound/effects/footstep/lava3.ogg'), 100, 0),
+))
+
+//heavy footsteps list
+GLOBAL_LIST_INIT(heavyfootstep, list(
+ FOOTSTEP_GENERIC_HEAVY = list(list(
+ 'sound/effects/footstep/heavy1.ogg',
+ 'sound/effects/footstep/heavy2.ogg'), 100, 2),
+ FOOTSTEP_WATER = list(list(
+ 'sound/effects/footstep/water1.ogg',
+ 'sound/effects/footstep/water2.ogg',
+ 'sound/effects/footstep/water3.ogg',
+ 'sound/effects/footstep/water4.ogg'), 100, 2),
+ FOOTSTEP_LAVA = list(list(
+ 'sound/effects/footstep/lava1.ogg',
+ 'sound/effects/footstep/lava2.ogg',
+ 'sound/effects/footstep/lava3.ogg'), 100, 0),
+))
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 15eaadb2f2..8ff40c3ef9 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -67,7 +67,7 @@
#define islarva(A) (istype(A, /mob/living/carbon/alien/larva))
-#define isalienadult(A) (istype(A, /mob/living/carbon/alien/humanoid))
+#define isalienadult(A) (istype(A, /mob/living/carbon/alien/humanoid) || istype(A, /mob/living/simple_animal/hostile/alien))
#define isalienhunter(A) (istype(A, /mob/living/carbon/alien/humanoid/hunter))
@@ -123,6 +123,47 @@
#define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown))
+GLOBAL_LIST_INIT(shoefootmob, typecacheof(list(
+ /mob/living/carbon/human/,
+ /mob/living/simple_animal/cow,
+ /mob/living/simple_animal/hostile/cat_butcherer,
+ /mob/living/simple_animal/hostile/faithless,
+ /mob/living/simple_animal/hostile/nanotrasen,
+ /mob/living/simple_animal/hostile/pirate,
+ /mob/living/simple_animal/hostile/russian,
+ /mob/living/simple_animal/hostile/syndicate,
+ /mob/living/simple_animal/hostile/wizard,
+ /mob/living/simple_animal/hostile/zombie,
+ /mob/living/simple_animal/hostile/retaliate/clown,
+ /mob/living/simple_animal/hostile/retaliate/spaceman,
+ /mob/living/simple_animal/hostile/retaliate/nanotrasenpeace,
+ /mob/living/simple_animal/hostile/retaliate/goat,
+ /mob/living/carbon/true_devil,
+ )))
+
+GLOBAL_LIST_INIT(clawfootmob, typecacheof(list(
+ /mob/living/carbon/alien/humanoid,
+ /mob/living/simple_animal/hostile/alien,
+ /mob/living/simple_animal/pet/cat,
+ /mob/living/simple_animal/pet/dog,
+ /mob/living/simple_animal/pet/fox,
+ /mob/living/simple_animal/chicken,
+ /mob/living/simple_animal/hostile/bear,
+ /mob/living/simple_animal/hostile/jungle/mega_arachnid
+ )))
+
+GLOBAL_LIST_INIT(barefootmob, typecacheof(list(
+ /mob/living/carbon/monkey,
+ /mob/living/simple_animal/pet/penguin,
+ /mob/living/simple_animal/hostile/gorilla,
+ /mob/living/simple_animal/hostile/jungle/mook
+ )))
+
+GLOBAL_LIST_INIT(heavyfootmob, typecacheof(list(
+ /mob/living/simple_animal/hostile/megafauna,
+ /mob/living/simple_animal/hostile/jungle/leaper
+ )))
+
//Misc mobs
#define isobserver(A) (istype(A, /mob/dead/observer))
@@ -136,6 +177,15 @@
#define iseminence(A) (istype(A, /mob/camera/eminence))
+//Footstep helpers
+#define isshoefoot(A) (is_type_in_typecache(A, GLOB.shoefootmob))
+
+#define isclawfoot(A) (is_type_in_typecache(A, GLOB.clawfootmob))
+
+#define isbarefoot(A) (is_type_in_typecache(A, GLOB.barefootmob))
+
+#define isheavyfoot(A) (is_type_in_typecache(A, GLOB.heavyfootmob))
+
//Objects
#define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs
diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm
index 55131a26ed..8234059a36 100644
--- a/code/__DEFINES/logging.dm
+++ b/code/__DEFINES/logging.dm
@@ -16,6 +16,7 @@
#define INVESTIGATE_EXONET "exonet"
#define INVESTIGATE_NANITES "nanites"
#define INVESTIGATE_CIRCUIT "circuit"
+#define INVESTIGATE_RCD "rcd"
// Logging types for log_message()
#define LOG_ATTACK (1 << 0)
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index be58b64f41..30a7694e5f 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -114,8 +114,9 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s
#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
-#define BE_CLOSE 1 //in the case of a silicon, to select if they need to be next to the atom
-#define NO_DEXTERY 1 //if other mobs (monkeys, aliens, etc) can use this
+#define BE_CLOSE TRUE //in the case of a silicon, to select if they need to be next to the atom
+#define NO_DEXTERY TRUE //if other mobs (monkeys, aliens, etc) can use this
+#define NO_TK TRUE
//used by canUseTopic()
//singularity defines
@@ -218,6 +219,9 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
//Gets the turf this atom inhabits
#define get_turf(A) (get_step(A, 0))
+//Same as above except gets the area instead
+#define get_area(A) (isarea(A) ? A : get_step(A, 0)?.loc)
+
//Ghost orbit types:
#define GHOST_ORBIT_CIRCLE "circle"
#define GHOST_ORBIT_TRIANGLE "triangle"
@@ -262,6 +266,15 @@ GLOBAL_LIST_INIT(ghost_others_options, list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DE
GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
+//pda icon reskins
+#define PDA_SKIN_CLASSIC "Classic"
+#define PDA_SKIN_ALT "Holographic"
+#define PDA_SKIN_RUGGED "Rugged"
+#define PDA_SKIN_MODERN "Modern"
+
+GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_SKIN_ALT = 'icons/obj/pda_alt.dmi',
+ PDA_SKIN_RUGGED = 'icons/obj/pda_rugged.dmi', PDA_SKIN_MODERN = 'icons/obj/pda_modern.dmi'))
+
//Color Defines
#define OOC_COLOR "#002eb8"
#define AOOC_COLOR "#b8002e"
@@ -369,6 +382,7 @@ GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
#define CLOCK_SILICONS 22
#define CLOCK_PROSELYTIZATION 23
#define SHUTTLE_HIJACK 24
+#define GANG_VICTORY 25
#define FIELD_TURF 1
#define FIELD_EDGE 2
@@ -476,4 +490,7 @@ GLOBAL_LIST_INIT(pda_styles, list(MONO, VT, ORBITRON, SHARE))
#define AREASELECT_CORNERA "corner A"
#define AREASELECT_CORNERB "corner B"
-#define PREF_SAVELOAD_COOLDOWN 5
\ No newline at end of file
+#define PREF_SAVELOAD_COOLDOWN 5
+
+#define VOMIT_TOXIC 1
+#define VOMIT_PURPLE 2
\ No newline at end of file
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 4b42595b48..1d1dda6d99 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -54,6 +54,10 @@
#define BODYPART_ORGANIC 1
#define BODYPART_ROBOTIC 2
+#define BODYPART_NOT_DISABLED 0
+#define BODYPART_DISABLED_DAMAGE 1
+#define BODYPART_DISABLED_PARALYSIS 2
+
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
#define DEFAULT_BODYPART_ICON_ROBOTIC 'icons/mob/augmentation/augments.dmi'
diff --git a/code/__DEFINES/obj_flags.dm b/code/__DEFINES/obj_flags.dm
index e6d4fd126b..1c3832001f 100644
--- a/code/__DEFINES/obj_flags.dm
+++ b/code/__DEFINES/obj_flags.dm
@@ -20,12 +20,12 @@
#define FORCE_STRING_OVERRIDE (1<<2) // used for tooltips
#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
#define SLOWS_WHILE_IN_HAND (1<<4)
-#define NO_MAT_REDEMPTION (1<<5) // Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
-#define DROPDEL (1<<6) // When dropped, it calls qdel on itself
+#define NO_MAT_REDEMPTION (1<<5) // Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
+#define DROPDEL (1<<6) // When dropped, it calls qdel on itself
#define NOBLUDGEON (1<<7) // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
-#define NODROP (1<<8) // This flag makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted.
-#define ABSTRACT (1<<9) // for all things that are technically items but used for various different stuff
-#define IMMUTABLE_SLOW (1<<10) //When players should not be able to change the slowdown of the item (Speed potions, ect)
+#define ABSTRACT (1<<8) // for all things that are technically items but used for various different stuff
+#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
+#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
// Flags for the clothing_flags var on /obj/item/clothing
@@ -35,3 +35,5 @@
#define MASKINTERNALS (1<<3) // mask allows internals
#define NOSLIP (1<<4) //prevents from slipping on wet floors, in space etc
#define THICKMATERIAL (1<<5) //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body.
+#define VOICEBOX_TOGGLABLE (1<<6) // The voicebox in this clothing can be toggled.
+#define VOICEBOX_DISABLED (1<<7) // The voicebox is currently turned off.
\ No newline at end of file
diff --git a/code/__DEFINES/reactions.dm b/code/__DEFINES/reactions.dm
index b72a14468f..1c36120a0c 100644
--- a/code/__DEFINES/reactions.dm
+++ b/code/__DEFINES/reactions.dm
@@ -23,6 +23,11 @@
#define STIMULUM_ABSOLUTE_DROP 0.00000335
#define REACTION_OPPRESSION_THRESHOLD 5
#define NOBLIUM_FORMATION_ENERGY 2e9 //1 Mole of Noblium takes the planck energy to condense.
+//Research point amounts
+#define NOBLIUM_RESEARCH_AMOUNT 1000
+#define BZ_RESEARCH_AMOUNT 150
+#define MIASMA_RESEARCH_AMOUNT 160
+#define STIMULUM_RESEARCH_AMOUNT 50
//Plasma fusion properties
#define FUSION_ENERGY_THRESHOLD 3e9 //Amount of energy it takes to start a fusion reaction
#define FUSION_TEMPERATURE_THRESHOLD 1000 //Temperature required to start a fusion reaction
diff --git a/code/__DEFINES/reagents.dm b/code/__DEFINES/reagents.dm
index f8f59a367f..c3682d905d 100644
--- a/code/__DEFINES/reagents.dm
+++ b/code/__DEFINES/reagents.dm
@@ -2,7 +2,7 @@
#define LIQUID 2
#define GAS 3
-// container_type defines
+// reagents_flags defines
#define INJECTABLE (1<<0) // Makes it possible to add reagents through droppers and syringes.
#define DRAWABLE (1<<1) // Makes it possible to remove reagents through syringes.
@@ -11,6 +11,7 @@
#define TRANSPARENT (1<<4) // Used on containers which you want to be able to see the reagents off.
#define AMOUNT_VISIBLE (1<<5) // For non-transparent containers that still have the general amount of reagents in them visible.
+#define NO_REACT (1<<6) // Applied to a reagent holder, the contents will not react with each other.
// Is an open container for all intents and purposes.
#define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT)
diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm
index 9c81305241..0820d63247 100644
--- a/code/__DEFINES/robots.dm
+++ b/code/__DEFINES/robots.dm
@@ -35,6 +35,7 @@
#define CLEAN_BOT (1<<3) // Cleanbots
#define MED_BOT (1<<4) // Medibots
#define HONK_BOT (1<<5) // Honkbots & ED-Honks
+#define FIRE_BOT (1<<6) // Firebots
//AI notification defines
#define NEW_BORG 1
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index 6773d55e53..b316c003a9 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -33,7 +33,8 @@
#define ROLE_DRONE "drone"
#define ROLE_DEATHSQUAD "deathsquad"
#define ROLE_LAVALAND "lavaland"
-#define ROLE_INTERNAL_AFFAIRS "internal affairs agent"
+#define ROLE_INTERNAL_AFFAIRS "internal affairs agent"
+#define ROLE_GANG "gangster"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
@@ -58,7 +59,8 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
ROLE_OVERTHROW = /datum/game_mode/overthrow,
ROLE_INTERNAL_AFFAIRS = /datum/game_mode/traitor/internal_affairs,
- ROLE_SENTIENCE
+ ROLE_SENTIENCE,
+ ROLE_GANG = /datum/game_mode/gang
))
//Job defines for what happens when you fail to qualify for any job during job selection
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index f54a0542f4..19d0540e0e 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -81,7 +81,7 @@
#define INIT_ORDER_STICKY_BAN -10
#define INIT_ORDER_LIGHTING -20
#define INIT_ORDER_SHUTTLE -21
-#define INIT_ORDER_SQUEAK -40
+#define INIT_ORDER_MINOR_MAPPING -40
#define INIT_ORDER_PATH -50
#define INIT_ORDER_PERSISTENCE -100
@@ -102,7 +102,6 @@
#define FIRE_PRIORITY_SPACEDRIFT 30
#define FIRE_PRIORITY_FIELDS 30
#define FIRE_PRIOTITY_SMOOTHING 35
-#define FIRE_PRIORITY_ORBIT 35
#define FIRE_PRIORITY_NETWORKS 40
#define FIRE_PRIORITY_OBJ 40
#define FIRE_PRIORITY_ACID 40
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 805e72cfcb..7bcb4881f0 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -1,3 +1,61 @@
+// trait accessor defines
+#define ADD_TRAIT(target, trait, source) \
+ do { \
+ var/list/_L; \
+ if (!target.status_traits) { \
+ target.status_traits = list(); \
+ _L = target.status_traits; \
+ _L[trait] = list(source); \
+ } else { \
+ _L = target.status_traits; \
+ if (_L[trait]) { \
+ _L[trait] |= list(source); \
+ } else { \
+ _L[trait] = list(source); \
+ } \
+ } \
+ } while (0)
+#define REMOVE_TRAIT(target, trait, sources) \
+ do { \
+ var/list/_L = target.status_traits; \
+ var/list/_S; \
+ if (sources && !islist(sources)) { \
+ _S = list(sources); \
+ } else { \
+ _S = sources\
+ }; \
+ if (_L && _L[trait]) { \
+ for (var/_T in _L[trait]) { \
+ if ((!_S && (_T != ROUNDSTART_TRAIT)) || (_T in _S)) { \
+ _L[trait] -= _T \
+ } \
+ };\
+ if (!length(_L[trait])) { \
+ _L -= trait \
+ }; \
+ if (!length(_L)) { \
+ target.status_traits = null \
+ }; \
+ } \
+ } while (0)
+#define REMOVE_TRAITS_NOT_IN(target, sources) \
+ do { \
+ var/list/_L = target.status_traits; \
+ var/list/_S = sources; \
+ if (_L) { \
+ for (var/_T in _L) { \
+ _L[_T] &= _S;\
+ if (!length(_L[_T])) { \
+ _L -= _T } \
+ };\
+ if (!length(_L)) { \
+ target.status_traits = null\
+ };\
+ }\
+ } while (0)
+#define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE)
+#define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE)
+
//mob traits
#define TRAIT_BLIND "blind"
#define TRAIT_MUTE "mute"
@@ -50,7 +108,20 @@
#define TRAIT_NOHARDCRIT "nohardcrit"
#define TRAIT_NOSOFTCRIT "nosoftcrit"
#define TRAIT_MINDSHIELD "mindshield"
+#define TRAIT_PARALYSIS_L_ARM "para-l-arm" //These are used for brain-based paralysis, where replacing the limb won't fix it
+#define TRAIT_PARALYSIS_R_ARM "para-r-arm"
+#define TRAIT_PARALYSIS_L_LEG "para-l-leg"
+#define TRAIT_PARALYSIS_R_LEG "para-r-leg"
+#define TRAIT_UNINTELLIGIBLE_SPEECH "unintelligible-speech"
+#define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism"
+#define TRAIT_STRONG_GRABBER "strong_grabber"
+#define TRAIT_CALCIUM_HEALER "calcium_healer"
+ //non-mob traits
+#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
+
+// item traits
+#define TRAIT_NODROP "nodrop"
#define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance"
#define TRAIT_AGEUSIA "ageusia"
@@ -71,6 +142,12 @@
#define TRAIT_MUSICIAN "musician"
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
#define TRAIT_NYMPHO "nymphomania"
+#define TRAIT_MASO "masochism"
+#define TRAIT_PARA "paraplegic"
+#define TRAIT_EMPATH "empath"
+#define TRAIT_FRIENDLY "friendly"
+#define TRAIT_ASSBLASTUSA "assblastusa"
+#define TRAIT_CULT_EYES "cult_eyes"
// common trait sources
#define TRAIT_GENERIC "generic"
@@ -81,6 +158,13 @@
#define TRAUMA_TRAIT "trauma"
#define SPECIES_TRAIT "species"
#define ORGAN_TRAIT "organ"
+#define JOB_TRAIT "job"
+#define CYBORG_ITEM_TRAIT "cyborg-item"
+#define ADMIN_TRAIT "admin" // (B)admins only.
+#define CHANGELING_TRAIT "changeling"
+#define CULT_TRAIT "cult"
+#define CURSED_ITEM_TRAIT "cursed-item" // The item is magically cursed
+#define ABSTRACT_ITEM_TRAIT "abstract-item"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
// unique trait sources, still defines
@@ -93,4 +177,24 @@
#define STASIS_MUTE "stasis"
#define GENETICS_SPELL "genetics_spell"
#define EYES_COVERED "eyes_covered"
-#define CULT_EYES "cult_eyes"
+#define CULT_TRAIT "cult"
+#define CLOWN_NUKE_TRAIT "clown-nuke"
+#define STICKY_MOUSTACHE_TRAIT "sticky-moustache"
+#define CHAINSAW_FRENZY_TRAIT "chainsaw-frenzy"
+#define CHRONO_GUN_TRAIT "chrono-gun"
+#define REVERSE_BEAR_TRAP_TRAIT "reverse-bear-trap"
+#define GLUED_ITEM_TRAIT "glued-item"
+#define CURSED_MASK_TRAIT "cursed-mask"
+#define HIS_GRACE_TRAIT "his-grace"
+#define HAND_REPLACEMENT_TRAIT "magic-hand"
+#define HOT_POTATO_TRAIT "hot-potato"
+#define SABRE_SUICIDE_TRAIT "sabre-suicide"
+#define ABDUCTOR_VEST_TRAIT "abductor-vest"
+#define CAPTURE_THE_FLAG_TRAIT "capture-the-flag"
+#define EYE_OF_GOD_TRAIT "eye-of-god"
+#define SHAMEBRERO_TRAIT "shamebrero"
+#define CHRONOSUIT_TRAIT "chronosuit"
+#define FLIGHTSUIT_TRAIT "flightsuit"
+#define LOCKED_HELMET_TRAIT "locked-helmet"
+#define NINJA_SUIT_TRAIT "ninja-suit"
+#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
\ No newline at end of file
diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm
index eb2a564d1b..668b151b6e 100644
--- a/code/__HELPERS/_cit_helpers.dm
+++ b/code/__HELPERS/_cit_helpers.dm
@@ -58,8 +58,11 @@ GLOBAL_LIST_EMPTY(ipc_antennas_list)
//Genitals and Arousal Lists
GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm
GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes.
+GLOBAL_LIST_EMPTY(balls_shapes_list)
+GLOBAL_LIST_EMPTY(balls_shapes_icons)
GLOBAL_LIST_EMPTY(breasts_size_list)
GLOBAL_LIST_EMPTY(breasts_shapes_list)
+GLOBAL_LIST_EMPTY(breasts_shapes_icons)
GLOBAL_LIST_EMPTY(vagina_shapes_list)
GLOBAL_LIST_INIT(cum_into_containers_list, list(/obj/item/reagent_containers/food/snacks/pie)) //Yer fuggin snowflake name list jfc
GLOBAL_LIST_INIT(dick_nouns, list("dick","cock","member","shaft"))
@@ -123,36 +126,36 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
/mob/living/carbon/proc/has_penis()
if(getorganslot("penis"))//slot shared with ovipositor
if(istype(getorganslot("penis"), /obj/item/organ/genital/penis))
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/carbon/proc/has_balls()
if(getorganslot("balls"))
if(istype(getorganslot("balls"), /obj/item/organ/genital/testicles))
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/carbon/proc/has_vagina()
if(getorganslot("vagina"))
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/carbon/proc/has_breasts()
if(getorganslot("breasts"))
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/carbon/proc/has_ovipositor()
if(getorganslot("penis"))//shared slot
if(istype(getorganslot("penis"), /obj/item/organ/genital/ovipositor))
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/carbon/human/proc/has_eggsack()
if(getorganslot("balls"))
if(istype(getorganslot("balls"), /obj/item/organ/genital/eggsack))
- return 1
- return 0
+ return TRUE
+ return FALSE
/mob/living/carbon/human/proc/is_bodypart_exposed(bodypart)
@@ -161,16 +164,16 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
L = get_equipped_items()
for(var/obj/item/I in L)
if(I.body_parts_covered & GROIN)
- return 0
- return 1
+ return FALSE
+ return TRUE
/mob/living/carbon/proc/is_chest_exposed(var/list/L)
if(!L)
L = get_equipped_items()
for(var/obj/item/I in L)
if(I.body_parts_covered & CHEST)
- return 0
- return 1
+ return FALSE
+ return TRUE
////////////////////////
//DANGER | DEBUG PROCS//
@@ -191,40 +194,3 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
H.give_vagina()
H.give_womb()
H.give_breasts()
-
-/client/proc/test_mammal_overlays()
- set name = "Mass Give Mammalitus"
- set category = "Dangerous"
- set desc = "Turns every human into a mammal with tails, ears, etc. WARNING: NOT FOR LIVE SERVER USAGE!!"
-
- log_admin("[src] turned everyone into mammals.")
- message_admins("[src] turned everyone into mammals.")
- for(var/mob/living/carbon/human/H in GLOB.mob_list)
- if(!H.dna)
- continue
- var/datum/dna/hdna = H.dna
- H.set_species(/datum/species/mammal)
- var/subspec = pick("Fox","Wolf","Fennec")
- switch(subspec)
- if("Wolf")
- hdna.features["mam_tail"] = "Wolf"
- hdna.features["mam_ears"] = "Wolf"
- hdna.features["mam_snouts"] = "Wolf"
- hdna.features["mam_body_markings"] = "Wolf"
- hdna.features["mcolor"] = "555"
- hdna.features["mcolor2"] = "999"
- hdna.features["mcolor3"] = "999"
- if("Fox")
- hdna.features["mam_tail"] = "Fox"
- hdna.features["mam_ears"] = "Fox"
- hdna.features["mam_snouts"] = "Fox, Long"
- hdna.features["mam_body_markings"] = "Fox"
- hdna.features["mcolor"] = "f60"
- hdna.features["mcolor2"] = "fff"
- hdna.features["mcolor3"] = "fff"
- if("Fennec")
- hdna.features["mam_tail"] = "Fennec"
- hdna.features["mam_ears"] = "Fennec"
- hdna.features["mam_snouts"] = "Fox, Short"
- hdna.features["mam_body_markings"] = "Fox"
- H.regenerate_icons()
diff --git a/code/__HELPERS/areas.dm b/code/__HELPERS/areas.dm
index f05bf6f3e1..1f5b82f7bf 100644
--- a/code/__HELPERS/areas.dm
+++ b/code/__HELPERS/areas.dm
@@ -86,6 +86,8 @@
newA.contents += thing
thing.change_area(old_area, newA)
+ newA.reg_in_areas_in_z()
+
var/list/firedoors = oldA.firedoors
for(var/door in firedoors)
var/obj/machinery/door/firedoor/FD = door
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 899ef16306..c741a08108 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -8,12 +8,6 @@
#define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL))
#define CULT_POLL_WAIT 2400
-/proc/get_area(atom/A)
- if(isarea(A))
- return A
- var/turf/T = get_turf(A)
- return T ? T.loc : null
-
/proc/get_area_name(atom/X, format_text = FALSE)
var/area/A = isarea(X) ? X : get_area(X)
if(!A)
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index f6ef08fe0d..c8a33959ed 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -8,11 +8,11 @@
//facial hair
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, GLOB.facial_hair_styles_list, GLOB.facial_hair_styles_male_list, GLOB.facial_hair_styles_female_list)
//underwear
- init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/bottom, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
//undershirt
- init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, GLOB.undershirt_list, GLOB.undershirt_m, GLOB.undershirt_f)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/top, GLOB.undershirt_list, GLOB.undershirt_m, GLOB.undershirt_f)
//socks
- init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, GLOB.socks_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/socks, GLOB.socks_list)
//bodypart accessories (blizzard intensifies)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, GLOB.body_markings_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, GLOB.tails_list_lizard)
@@ -46,7 +46,6 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_dorsal, GLOB.xeno_dorsal_list)
//genitals
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
-
for(var/K in GLOB.cock_shapes_list)
var/datum/sprite_accessory/penis/value = GLOB.cock_shapes_list[K]
GLOB.cock_shapes_icons[K] = value.icon_state
@@ -54,6 +53,14 @@
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, GLOB.breasts_shapes_list)
GLOB.breasts_size_list = list("a","b","c","d","e") //We need the list to choose from initialized, but it's no longer a sprite_accessory thing.
+ for(var/K in GLOB.breasts_shapes_list)
+ var/datum/sprite_accessory/breasts/value = GLOB.breasts_shapes_list[K]
+ GLOB.breasts_shapes_icons[K] = value.icon_state
+
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
+ for(var/K in GLOB.balls_shapes_list)
+ var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K]
+ GLOB.balls_shapes_icons[K] = value.icon_state
//END OF CIT CHANGES
//Species
diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm
index 8b77b170e0..d96ec76a7c 100644
--- a/code/__HELPERS/matrices.dm
+++ b/code/__HELPERS/matrices.dm
@@ -2,7 +2,7 @@
. = new_angle - old_angle
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
-/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3)
+/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3, parallel = TRUE)
if(!segments)
return
var/segment = 360/segments
@@ -18,7 +18,11 @@
speed /= segments
- animate(src, transform = matrices[1], time = speed, loops)
+ if(parallel)
+ animate(src, transform = matrices[1], time = speed, loops , flags = ANIMATION_PARALLEL)
+ else
+ animate(src, transform = matrices[1], time = speed, loops)
+
for(var/i in 2 to segments) //2 because 1 is covered above
animate(transform = matrices[i], time = speed)
//doesn't have an object argument because this is "Stacking" with the animate call above
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 74a1fbd785..5ec839130a 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -20,35 +20,34 @@
else
return "000"
-/proc/random_underwear(gender)//Cit change - makes random underwear always return nude
+#define UNDIE_COLORABLE(U) (U?.has_color)
+
+/proc/random_underwear(gender)
if(!GLOB.underwear_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
- return "Nude"
- /*switch(gender)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/bottom, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
+ switch(gender)
if(MALE)
return pick(GLOB.underwear_m)
if(FEMALE)
return pick(GLOB.underwear_f)
else
- return pick(GLOB.underwear_list)*/
+ return pick(GLOB.underwear_list)
-/proc/random_undershirt(gender)//Cit change - makes random undershirts always return nude
+/proc/random_undershirt(gender)
if(!GLOB.undershirt_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, GLOB.undershirt_list, GLOB.undershirt_m, GLOB.undershirt_f)
- return "Nude"
- /*switch(gender)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/top, GLOB.undershirt_list, GLOB.undershirt_m, GLOB.undershirt_f)
+ switch(gender)
if(MALE)
return pick(GLOB.undershirt_m)
if(FEMALE)
return pick(GLOB.undershirt_f)
else
- return pick(GLOB.undershirt_list)*/
+ return pick(GLOB.undershirt_list)
-/proc/random_socks()//Cit change - makes random socks always return nude
+/proc/random_socks()
if(!GLOB.socks_list.len)
- init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, GLOB.socks_list)
- return "Nude"
- //return pick(GLOB.socks_list)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/socks, GLOB.socks_list)
+ return pick(GLOB.socks_list)
/proc/random_features()
if(!GLOB.tails_list_human.len)
@@ -77,6 +76,8 @@
//CIT CHANGES - genitals and such
if(!GLOB.cock_shapes_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, GLOB.cock_shapes_list)
+ if(!GLOB.balls_shapes_list.len)
+ init_sprite_accessory_subtypes(/datum/sprite_accessory/testicles, GLOB.balls_shapes_list)
if(!GLOB.vagina_shapes_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/vagina, GLOB.vagina_shapes_list)
if(!GLOB.breasts_shapes_list.len)
@@ -168,6 +169,7 @@
"balls_amount" = 2,
"balls_sack_size" = BALLS_SACK_SIZE_DEF,
"balls_size" = BALLS_SIZE_DEF,
+ "balls_shape" = "Single",
"balls_cum_rate" = CUM_RATE,
"balls_cum_mult" = CUM_RATE_MULT,
"balls_efficiency" = CUM_EFFICIENCY,
@@ -185,7 +187,7 @@
"has_breasts" = FALSE,
"breasts_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"),
"breasts_size" = pick(GLOB.breasts_size_list),
- "breasts_shape" = pick(GLOB.breasts_shapes_list),
+ "breasts_shape" = "Pair",
"breasts_fluid" = "milk",
"has_vag" = FALSE,
"vag_shape" = pick(GLOB.vagina_shapes_list),
@@ -294,7 +296,7 @@ GLOBAL_LIST_EMPTY(species_list)
else
return "unknown"
-/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null)
+/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1, datum/callback/extra_checks = null, ignorehelditem = 0)
if(!user || !target)
return 0
var/user_loc = user.loc
@@ -327,7 +329,7 @@ GLOBAL_LIST_EMPTY(species_list)
drifting = 0
user_loc = user.loc
- if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_held_item() != holding || user.incapacitated() || user.lying || (extra_checks && !extra_checks.Invoke()))
+ 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)
diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm
index 09e0aa95b9..db2eba2422 100644
--- a/code/__HELPERS/names.dm
+++ b/code/__HELPERS/names.dm
@@ -151,6 +151,10 @@ GLOBAL_VAR(command_name)
GLOBAL_VAR(syndicate_code_phrase) //Code phrase for traitors.
GLOBAL_VAR(syndicate_code_response) //Code response for traitors.
+//Cached regex search - for checking if codewords are used.
+GLOBAL_DATUM(syndicate_code_phrase_regex, /regex)
+GLOBAL_DATUM(syndicate_code_response_regex, /regex)
+
/*
Should be expanded.
How this works:
diff --git a/code/__HELPERS/reagents.dm b/code/__HELPERS/reagents.dm
new file mode 100644
index 0000000000..f1208abdd3
--- /dev/null
+++ b/code/__HELPERS/reagents.dm
@@ -0,0 +1,74 @@
+/proc/chem_recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
+ //do the non-list tests first, because they are cheaper
+ if(r1.required_container != r2.required_container)
+ return FALSE
+ if(r1.is_cold_recipe == r2.is_cold_recipe)
+ if(r1.required_temp != r2.required_temp)
+ //one reaction requires a more extreme temperature than the other, so there is no conflict
+ return FALSE
+ else
+ var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2
+ var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1
+ if(cold_one.required_temp < warm_one.required_temp)
+ //the range of temperatures does not overlap, so there is no conflict
+ return FALSE
+
+ //find the reactions with the shorter and longer required_reagents list
+ var/datum/chemical_reaction/long_req
+ var/datum/chemical_reaction/short_req
+ if(r1.required_reagents.len > r2.required_reagents.len)
+ long_req = r1
+ short_req = r2
+ else if(r1.required_reagents.len < r2.required_reagents.len)
+ long_req = r2
+ short_req = r1
+ else
+ //if they are the same length, sort instead by the length of the catalyst list
+ //this is important if the required_reagents lists are the same
+ if(r1.required_catalysts.len > r2.required_catalysts.len)
+ long_req = r1
+ short_req = r2
+ else
+ long_req = r2
+ short_req = r1
+
+
+ //check if the shorter reaction list is a subset of the longer one
+ var/list/overlap = r1.required_reagents & r2.required_reagents
+ if(overlap.len != short_req.required_reagents.len)
+ //there is at least one reagent in the short list that is not in the long list, so there is no conflict
+ return FALSE
+
+ //check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list
+ //if the longer reaction's catalyst list is a subset of the shorter ones, that is fine
+ //if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict
+ var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts
+ if(short_minus_long_catalysts.len)
+ //there is at least one unique catalyst for the short reaction, so there is no conflict
+ return FALSE
+
+ //if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list, and will require the reagents to be added in a particular order otherwise
+ return TRUE
+
+/proc/get_chemical_reaction(id)
+ if(!GLOB.chemical_reactions_list)
+ return
+ for(var/reagent in GLOB.chemical_reactions_list)
+ for(var/datum/chemical_reaction/R in GLOB.chemical_reactions_list[reagent])
+ if(R.id == id)
+ return R
+
+/proc/remove_chemical_reaction(datum/chemical_reaction/R)
+ if(!GLOB.chemical_reactions_list || !R)
+ return
+ for(var/rid in R.required_reagents)
+ GLOB.chemical_reactions_list[rid] -= R
+
+//see build_chemical_reactions_list in holder.dm for explanations
+/proc/add_chemical_reaction(datum/chemical_reaction/R)
+ if(!GLOB.chemical_reactions_list || !R.id || !R.required_reagents || !R.required_reagents.len)
+ return
+ var/primary_reagent = R.required_reagents[1]
+ if(!GLOB.chemical_reactions_list[primary_reagent])
+ GLOB.chemical_reactions_list[primary_reagent] = list()
+ GLOB.chemical_reactions_list[primary_reagent] += R
diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm
index 7d6c017b77..1ee5ce986f 100644
--- a/code/__HELPERS/text.dm
+++ b/code/__HELPERS/text.dm
@@ -94,6 +94,8 @@
// Used to get a properly sanitized multiline input, of max_length
/proc/stripped_multiline_input(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(no_trim)
return copytext(html_encode(name), 1, max_length)
else
@@ -765,3 +767,27 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
return "twelfth"
else
return "[number]\th"
+
+/proc/unintelligize(message)
+ var/prefix=copytext(message,1,2)
+ if(prefix == ";")
+ message = copytext(message,2)
+ else if(prefix in list(":","#"))
+ prefix += copytext(message,2,3)
+ message = copytext(message,3)
+ else
+ prefix=""
+
+ var/list/words = splittext(message," ")
+ var/list/rearranged = list()
+ for(var/i=1;i<=words.len;i++)
+ var/cword = pick(words)
+ words.Remove(cword)
+ var/suffix = copytext(cword,length(cword)-1,length(cword))
+ while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
+ cword = copytext(cword,1 ,length(cword)-1)
+ suffix = copytext(cword,length(cword)-1,length(cword) )
+ if(length(cword))
+ rearranged += cword
+ message = "[prefix][jointext(rearranged," ")]"
+ . = message
diff --git a/code/__HELPERS/time.dm b/code/__HELPERS/time.dm
index 200e1f907f..b28e7b5807 100644
--- a/code/__HELPERS/time.dm
+++ b/code/__HELPERS/time.dm
@@ -70,3 +70,6 @@ GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
if(hour)
hourT = " and [hour] hour[(hour != 1)? "s":""]"
return "[day] day[(day != 1)? "s":""][hourT][minuteT][secondT]"
+
+/proc/daysSince(realtimev)
+ return round((world.realtime - realtimev) / (24 HOURS))
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 2f69b63ae9..7e078184b7 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1239,19 +1239,21 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
pixel_x = initialpixelx
pixel_y = initialpixely
-/atom/proc/do_jiggle(targetangle = 45)
+/atom/proc/do_jiggle(targetangle = 45, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
+ var/halftime = timer * 0.5
M.Turn(pick(-targetangle, targetangle))
- animate(src, transform = M, time = 10, easing = ELASTIC_EASING)
- animate(src, transform = OM, time = 10, easing = ELASTIC_EASING)
+ animate(src, transform = M, time = halftime, easing = ELASTIC_EASING)
+ animate(src, transform = OM, time = halftime, easing = ELASTIC_EASING)
-/atom/proc/do_squish(squishx = 1.2, squishy = 0.6)
+/atom/proc/do_squish(squishx = 1.2, squishy = 0.6, timer = 20)
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
+ var/halftime = timer * 0.5
M.Scale(squishx, squishy)
- animate(src, transform = M, time = 10, easing = BOUNCE_EASING)
- animate(src, transform = OM, time = 10, easing = BOUNCE_EASING)
+ animate(src, transform = M, time = halftime, easing = BOUNCE_EASING)
+ animate(src, transform = OM, time = halftime, easing = BOUNCE_EASING)
/proc/weightclass2text(var/w_class)
switch(w_class)
@@ -1483,7 +1485,9 @@ 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/deepfryholder,
+ /obj/item/reagent_containers/food/snacks/grown/shell,
+ /obj/item/reagent_containers/food/snacks/store/bread
)
blocked |= typesof(/obj/item/reagent_containers/food/snacks/customizable)
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index 835a733752..bb9fc98b8e 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -47,7 +47,6 @@ GLOBAL_LIST_INIT(bitfields, list(
"NO_MAT_REDEMPTION" = NO_MAT_REDEMPTION,
"DROPDEL" = DROPDEL,
"NOBLUDGEON" = NOBLUDGEON,
- "NODROP" = NODROP,
"ABSTRACT" = ABSTRACT,
),
"admin_flags" = list(
@@ -115,9 +114,6 @@ GLOBAL_LIST_INIT(bitfields, list(
"GOLIATH_RESISTANCE" = GOLIATH_RESISTANCE,
"GOLIATH_WEAKNESS" = GOLIATH_WEAKNESS
),
- "reagents_holder_flags" = list(
- "REAGENT_NOREACT" = REAGENT_NOREACT
- ),
"flags_1" = list(
"NOJAUNT_1" = NOJAUNT_1,
"UNUSED_RESERVATION_TURF_1" = UNUSED_RESERVATION_TURF_1,
@@ -143,6 +139,8 @@ GLOBAL_LIST_INIT(bitfields, list(
"MASKINTERNALS" = MASKINTERNALS,
"NOSLIP" = NOSLIP,
"THICKMATERIAL" = THICKMATERIAL,
+ "VOICEBOX_TOGGLABLE" = VOICEBOX_TOGGLABLE,
+ "VOICEBOX_DISABLED" = VOICEBOX_DISABLED,
),
"tesla_flags" = list(
"TESLA_MOB_DAMAGE" = TESLA_MOB_DAMAGE,
@@ -158,13 +156,14 @@ GLOBAL_LIST_INIT(bitfields, list(
"SMOOTH_BORDER" = SMOOTH_BORDER,
"SMOOTH_QUEUED" = SMOOTH_QUEUED,
),
- "container_type" = list(
+ "reagents_holder_flags" = list(
"INJECTABLE" = INJECTABLE,
"DRAWABLE" = DRAWABLE,
"REFILLABLE" = REFILLABLE,
"DRAINABLE" = DRAINABLE,
"TRANSPARENT" = TRANSPARENT,
"AMOUNT_VISIBLE" = AMOUNT_VISIBLE,
+ "NO_REACT" = NO_REACT,
),
"car_traits" = list(
"CAN_KIDNAP" = CAN_KIDNAP,
@@ -173,4 +172,9 @@ GLOBAL_LIST_INIT(bitfields, list(
"RAD_PROTECT_CONTENTS" = RAD_PROTECT_CONTENTS,
"RAD_NO_CONTAMINATE" = RAD_NO_CONTAMINATE,
),
- ))
+ "disease_flags" = list(
+ "CURABLE" = CURABLE,
+ "CAN_CARRY" = CAN_CARRY,
+ "CAN_RESIST" = CAN_RESIST
+ ),
+ ))
\ No newline at end of file
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 8b0ac278cd..82ccd439ee 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -7,15 +7,15 @@ GLOBAL_LIST_EMPTY(facial_hair_styles_list) //stores /datum/sprite_accessory/faci
GLOBAL_LIST_EMPTY(facial_hair_styles_male_list) //stores only hair names
GLOBAL_LIST_EMPTY(facial_hair_styles_female_list) //stores only hair names
//Underwear
-GLOBAL_LIST_EMPTY(underwear_list) //stores /datum/sprite_accessory/underwear indexed by name
+GLOBAL_LIST_EMPTY(underwear_list) //stores /datum/sprite_accessory/underwear/bottom indexed by name
GLOBAL_LIST_EMPTY(underwear_m) //stores only underwear name
GLOBAL_LIST_EMPTY(underwear_f) //stores only underwear name
//Undershirts
-GLOBAL_LIST_EMPTY(undershirt_list) //stores /datum/sprite_accessory/undershirt indexed by name
+GLOBAL_LIST_EMPTY(undershirt_list) //stores /datum/sprite_accessory/underwear/top indexed by name
GLOBAL_LIST_EMPTY(undershirt_m) //stores only undershirt name
GLOBAL_LIST_EMPTY(undershirt_f) //stores only undershirt name
//Socks
-GLOBAL_LIST_EMPTY(socks_list) //stores /datum/sprite_accessory/socks indexed by name
+GLOBAL_LIST_EMPTY(socks_list) //stores /datum/sprite_accessory/underwear/socks indexed by name
//Lizard Bits (all datum lists indexed by name)
GLOBAL_LIST_EMPTY(body_markings_list)
GLOBAL_LIST_EMPTY(tails_list_lizard)
@@ -40,6 +40,54 @@ GLOBAL_LIST_EMPTY(caps_list)
GLOBAL_LIST_INIT(ghost_forms_with_directions_list, list("ghost")) //stores the ghost forms that support directional sprites
GLOBAL_LIST_INIT(ghost_forms_with_accessories_list, list("ghost")) //stores the ghost forms that support hair and other such things
+GLOBAL_LIST_INIT(ai_core_display_screens, list(
+ ":thinking:",
+ "Alien",
+ "Angel",
+ "Banned",
+ "Bliss",
+ "Blue",
+ "Clown",
+ "Database",
+ "Dorf",
+ "Firewall",
+ "Fuzzy",
+ "Gentoo",
+ "Glitchman",
+ "Gondola",
+ "Goon",
+ "Hades",
+ "Heartline",
+ "Helios",
+ "House",
+ "Inverted",
+ "Matrix",
+ "Monochrome",
+ "Murica",
+ "Nanotrasen",
+ "Not Malf",
+ "President",
+ "Random",
+ "Rainbow",
+ "Red",
+ "Red October",
+ "Static",
+ "Syndicat Meow",
+ "TechDemon",
+ "Text",
+ "Too Deep",
+ "Triumvirate",
+ "Triumvirate-M",
+ "Weird"))
+
+/proc/resolve_ai_icon(input)
+ if(!input || !(input in GLOB.ai_core_display_screens))
+ return "ai"
+ else
+ if(input == "Random")
+ input = pick(GLOB.ai_core_display_screens - "Random")
+ return "ai-[lowertext(input)]"
+
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
@@ -117,7 +165,7 @@ GLOBAL_LIST_INIT(TAGGERLOCATIONS, list("Disposals",
"CMO Office", "Chemistry", "Research", "RD Office",
"Robotics", "HoP Office", "Library", "Chapel", "Theatre",
"Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics",
- "Circuitry", "Toxins", "Dormitories", "Virology",
+ "Circuitry", "Toxins", "Dormitories", "Virology",
"Xenobiology", "Law Office","Detective's Office"))
GLOBAL_LIST_INIT(station_prefixes, world.file2list("strings/station_prefixes.txt") + "")
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index 36049de77b..ef460cd54c 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -43,7 +43,8 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/assembly/timer = 3,
/obj/item/flashlight = 4,
/obj/item/flashlight/pen = 1,
- /obj/item/flashlight/glowstick/random = 4,
+ /obj/effect/spawner/lootdrop/glowstick = 4,
+ /obj/effect/spawner/lootdrop/mre = 3,
/obj/item/multitool = 2,
/obj/item/radio/off = 2,
/obj/item/t_scanner = 5,
@@ -68,7 +69,6 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/crowbar = 1,
/obj/item/crowbar/red = 1,
/obj/item/extinguisher = 11,
- //obj/item/gun/ballistic/revolver/russian = 1, //disabled until lootdrop is a proper world proc.
/obj/item/hand_labeler = 1,
/obj/item/paper/crumpled = 1,
/obj/item/pen = 1,
@@ -101,13 +101,18 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/assembly/signaler = 2,
/obj/item/assembly/mousetrap = 2,
/obj/item/reagent_containers/syringe = 2,
- /obj/item/clothing/gloves/color/random = 8,
+ /obj/effect/spawner/lootdrop/gloves = 8,
/obj/item/clothing/shoes/laceup = 1,
/obj/item/storage/secure/briefcase = 3,
/obj/item/storage/toolbox/artistic = 2,
/obj/item/toy/eightball = 1,
/obj/item/reagent_containers/pill/floorpill = 1,
+ /obj/item/reagent_containers/food/snacks/cannedpeaches/maint = 1,
/obj/item/storage/daki = 3, //VERY IMPORTANT CIT CHANGE - adds bodypillows to maint
/obj/item/storage/pill_bottle/penis_enlargement = 2,
+ /obj/item/clothing/shoes/wheelys = 1,
+ /obj/item/clothing/shoes/kindleKicks = 1,
+ /obj/item/autosurgeon/penis = 1,
+ /obj/item/autosurgeon/testicles = 1,
"" = 3
))
diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm
index fa0ecf117d..e7b2ae6cbe 100644
--- a/code/_globalvars/misc.dm
+++ b/code/_globalvars/misc.dm
@@ -18,3 +18,12 @@ GLOBAL_LIST_EMPTY(powernets)
GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes
GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details
+
+// All religion stuff
+GLOBAL_VAR(religion)
+GLOBAL_VAR(deity)
+GLOBAL_VAR(bible_name)
+GLOBAL_VAR(bible_icon_state)
+GLOBAL_VAR(bible_item_state)
+GLOBAL_VAR(holy_weapon_type)
+GLOBAL_VAR(holy_armor_type)
\ No newline at end of file
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 0c01468712..7a495b95e7 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -23,6 +23,9 @@
return
next_click = world.time + 1
+ if(!can_interact_with(A))
+ return
+
if(multicam_on)
var/turf/T = get_turf(A)
if(T)
@@ -60,7 +63,6 @@
controlled_mech.click_action(A, src, params) //Override AI normal click behavior.
return
- return
if(modifiers["shift"])
ShiftClickOn(A)
return
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 3d6de49a6a..22210bfd08 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -366,11 +366,15 @@
SEND_SIGNAL(src, COMSIG_CLICK_ALT, user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
- if(user.listed_turf == T)
- user.listed_turf = null
- else
- user.listed_turf = T
- user.client.statpanel = T.name
+ user.listed_turf = T
+ user.client.statpanel = T.name
+
+// Use this instead of /mob/proc/AltClickOn(atom/A) where you only want turf content listing without additional atom alt-click interaction
+/atom/proc/AltClickNoInteract(mob/user, atom/A)
+ var/turf/T = get_turf(A)
+ if(T && user.TurfAdjacent(T))
+ user.listed_turf = T
+ user.client.statpanel = T.name
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm
index 73a207a457..2b5af9ddb8 100644
--- a/code/_onclick/hud/action_button.dm
+++ b/code/_onclick/hud/action_button.dm
@@ -20,10 +20,23 @@
else
return TRUE
-/obj/screen/movable/action_button/MouseDrop()
- if (!can_use(usr))
+/obj/screen/movable/action_button/MouseDrop(over_object)
+ if(!can_use(usr))
return
- return ..()
+ if((istype(over_object, /obj/screen/movable/action_button) && !istype(over_object, /obj/screen/movable/action_button/hide_toggle)))
+ if(locked)
+ to_chat(usr, "Action button \"[name]\" is locked, unlock it first.")
+ return
+ var/obj/screen/movable/action_button/B = over_object
+ var/list/actions = usr.actions
+ actions.Swap(actions.Find(src.linked_action), actions.Find(B.linked_action))
+ moved = FALSE
+ ordered = TRUE
+ B.moved = FALSE
+ B.ordered = TRUE
+ usr.update_action_buttons()
+ else
+ return ..()
/obj/screen/movable/action_button/Click(location,control,params)
if (!can_use(usr))
diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm
index 03b951e6bb..df91223ed1 100644
--- a/code/_onclick/hud/radial.dm
+++ b/code/_onclick/hud/radial.dm
@@ -1,4 +1,7 @@
#define NEXT_PAGE_ID "__next__"
+#define DEFAULT_CHECK_DELAY 20
+
+GLOBAL_LIST_EMPTY(radial_menus)
/obj/screen/radial
icon = 'icons/mob/radial.dmi'
@@ -10,14 +13,19 @@
icon_state = "radial_slice"
var/choice
var/next_page = FALSE
+ var/tooltips = FALSE
/obj/screen/radial/slice/MouseEntered(location, control, params)
. = ..()
icon_state = "radial_slice_focus"
+ if(tooltips)
+ openToolTip(usr, src, params, title = name)
/obj/screen/radial/slice/MouseExited(location, control, params)
. = ..()
icon_state = "radial_slice"
+ if(tooltips)
+ closeToolTip(usr)
/obj/screen/radial/slice/Click(location, control, params)
if(usr.client == parent.current_user)
@@ -30,6 +38,14 @@
name = "Close Menu"
icon_state = "radial_center"
+/obj/screen/radial/center/MouseEntered(location, control, params)
+ . = ..()
+ icon_state = "radial_center_focus"
+
+/obj/screen/radial/center/MouseExited(location, control, params)
+ . = ..()
+ icon_state = "radial_center"
+
/obj/screen/radial/center/Click(location, control, params)
if(usr.client == parent.current_user)
parent.finished = TRUE
@@ -48,6 +64,9 @@
var/atom/anchor
var/image/menu_holder
var/finished = FALSE
+ var/datum/callback/custom_check_callback
+ var/next_check = 0
+ var/check_delay = DEFAULT_CHECK_DELAY
var/radius = 32
var/starting_angle = 0
@@ -57,7 +76,7 @@
var/max_elements
var/pages = 1
var/current_page = 1
-
+
var/hudfix_method = TRUE //TRUE to change anchor to user, FALSE to shift by py_shift
var/py_shift = 0
var/entry_animation = TRUE
@@ -75,7 +94,7 @@
restrict_to_dir(NORTH) //I was going to parse screen loc here but that's more effort than it's worth.
//Sets defaults
-//These assume 45 deg min_angle
+//These assume 45 deg min_angle
/datum/radial_menu/proc/restrict_to_dir(dir)
switch(dir)
if(NORTH)
@@ -91,18 +110,19 @@
starting_angle = 180
ending_angle = 45
-/datum/radial_menu/proc/setup_menu()
+/datum/radial_menu/proc/setup_menu(use_tooltips)
if(ending_angle > starting_angle)
zone = ending_angle - starting_angle
else
zone = 360 - starting_angle + ending_angle
-
+
max_elements = round(zone / min_angle)
var/paged = max_elements < choices.len
if(elements.len < max_elements)
var/elements_to_add = max_elements - elements.len
for(var/i in 1 to elements_to_add) //Create all elements
- var/obj/screen/radial/new_element = new /obj/screen/radial/slice
+ var/obj/screen/radial/slice/new_element = new /obj/screen/radial/slice
+ new_element.tooltips = use_tooltips
new_element.parent = src
elements += new_element
@@ -163,7 +183,7 @@
else
E.pixel_y = py
E.pixel_x = px
-
+
//Visuals
E.alpha = 255
E.mouse_opacity = MOUSE_OPACITY_ICON
@@ -183,7 +203,7 @@
E.next_page = FALSE
if(choices_icons[choice_id])
E.add_overlay(choices_icons[choice_id])
-
+
/datum/radial_menu/New()
close_button = new
close_button.parent = src
@@ -200,7 +220,7 @@
/datum/radial_menu/proc/get_next_id()
return "c_[choices.len]"
-/datum/radial_menu/proc/set_choices(list/new_choices)
+/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips)
if(choices.len)
Reset()
for(var/E in new_choices)
@@ -211,7 +231,7 @@
var/I = extract_image(new_choices[E])
if(I)
choices_icons[id] = I
- setup_menu()
+ setup_menu(use_tooltips)
/datum/radial_menu/proc/extract_image(E)
@@ -220,7 +240,7 @@
MA.layer = ABOVE_HUD_LAYER
MA.appearance_flags |= RESET_TRANSFORM
return MA
-
+
/datum/radial_menu/proc/next_page()
if(pages > 1)
@@ -243,28 +263,49 @@
if(current_user)
current_user.images -= menu_holder
-/datum/radial_menu/proc/wait()
+/datum/radial_menu/proc/wait(atom/user, atom/anchor, require_near = FALSE)
while (current_user && !finished && !selected_choice)
+ if(require_near && !in_range(anchor, user))
+ return
+ if(custom_check_callback && next_check < world.time)
+ if(!custom_check_callback.Invoke())
+ return
+ else
+ next_check = world.time + check_delay
stoplag(1)
/datum/radial_menu/Destroy()
Reset()
hide()
+ QDEL_NULL(custom_check_callback)
. = ..()
+
/*
- Presents radial menu to user anchored to anchor (or user if the anchor is currently in users screen)
+ Presents radial menu to user anchored to anchor (or user if the anchor is currently in users screen)
Choices should be a list where list keys are movables or text used for element names and return value
and list values are movables/icons/images used for element icons
*/
-/proc/show_radial_menu(mob/user,atom/anchor,list/choices)
+/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE)
+ if(!user || !anchor || !length(choices))
+ return
+ if(!uniqueid)
+ uniqueid = "defmenu_[REF(user)]_[REF(anchor)]"
+
+ if(GLOB.radial_menus[uniqueid])
+ return
+
var/datum/radial_menu/menu = new
- if(!user)
- user = usr
+ GLOB.radial_menus[uniqueid] = menu
+ if(radius)
+ menu.radius = radius
+ if(istype(custom_check))
+ menu.custom_check_callback = custom_check
menu.anchor = anchor
menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud
- menu.set_choices(choices)
+ menu.set_choices(choices, tooltips)
menu.show_to(user)
- menu.wait()
+ menu.wait(user, anchor, require_near)
var/answer = menu.selected_choice
qdel(menu)
+ GLOB.radial_menus -= uniqueid
return answer
\ No newline at end of file
diff --git a/code/_onclick/hud/radial_persistent.dm b/code/_onclick/hud/radial_persistent.dm
new file mode 100644
index 0000000000..0b5e8dc356
--- /dev/null
+++ b/code/_onclick/hud/radial_persistent.dm
@@ -0,0 +1,76 @@
+/*
+ A derivative of radial menu which persists onscreen until closed and invokes a callback each time an element is clicked
+*/
+
+/obj/screen/radial/persistent/center
+ name = "Close Menu"
+ icon_state = "radial_center"
+
+/obj/screen/radial/persistent/center/Click(location, control, params)
+ if(usr.client == parent.current_user)
+ parent.element_chosen(null,usr)
+
+/obj/screen/radial/persistent/center/MouseEntered(location, control, params)
+ . = ..()
+ icon_state = "radial_center_focus"
+
+/obj/screen/radial/persistent/center/MouseExited(location, control, params)
+ . = ..()
+ icon_state = "radial_center"
+
+
+
+/datum/radial_menu/persistent
+ var/uniqueid
+ var/datum/callback/select_proc_callback
+
+/datum/radial_menu/persistent/New()
+ close_button = new /obj/screen/radial/persistent/center
+ close_button.parent = src
+
+
+/datum/radial_menu/persistent/element_chosen(choice_id,mob/user)
+ select_proc_callback.Invoke(choices_values[choice_id])
+
+
+/datum/radial_menu/persistent/proc/change_choices(list/newchoices, tooltips)
+ if(!newchoices.len)
+ return
+ Reset()
+ set_choices(newchoices,tooltips)
+
+/datum/radial_menu/persistent/Destroy()
+ QDEL_NULL(select_proc_callback)
+ GLOB.radial_menus -= uniqueid
+ Reset()
+ hide()
+ . = ..()
+
+/*
+ Creates a persistent radial menu and shows it to the user, anchored to anchor (or user if the anchor is currently in users screen).
+ Choices should be a list where list keys are movables or text used for element names and return value
+ and list values are movables/icons/images used for element icons
+ Select_proc is the proc to be called each time an element on the menu is clicked, and should accept the chosen element as its final argument
+ Clicking the center button will return a choice of null
+*/
+/proc/show_radial_menu_persistent(mob/user, atom/anchor, list/choices, datum/callback/select_proc, uniqueid, radius, tooltips = FALSE)
+ if(!user || !anchor || !length(choices) || !select_proc)
+ return
+ if(!uniqueid)
+ uniqueid = "defmenu_[REF(user)]_[REF(anchor)]"
+
+ if(GLOB.radial_menus[uniqueid])
+ return
+
+ var/datum/radial_menu/persistent/menu = new
+ menu.uniqueid = uniqueid
+ GLOB.radial_menus[uniqueid] = menu
+ if(radius)
+ menu.radius = radius
+ menu.select_proc_callback = select_proc
+ menu.anchor = anchor
+ menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud
+ menu.set_choices(choices, tooltips)
+ menu.show_to(user)
+ return menu
+
diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index d23d0905e9..3896c3eac3 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -64,7 +64,7 @@
to_chat(user, "You're too exhausted.") // CIT CHANGE - ditto
return // CIT CHANGE - ditto
- if(force && user.has_trait(TRAIT_PACIFISM))
+ if(force && damtype != STAMINA && HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "You don't want to harm other living beings!")
return
diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm
index 6cacc90fcb..299d7f64f8 100644
--- a/code/_onclick/observer.dm
+++ b/code/_onclick/observer.dm
@@ -31,7 +31,7 @@
ShiftClickOn(A)
return
if(modifiers["alt"])
- AltClickOn(A)
+ AltClickNoInteract(src, A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
diff --git a/code/controllers/subsystem/augury.dm b/code/controllers/subsystem/augury.dm
index 875f1ee7d3..1b1c7bc3b7 100644
--- a/code/controllers/subsystem/augury.dm
+++ b/code/controllers/subsystem/augury.dm
@@ -50,7 +50,7 @@ SUBSYSTEM_DEF(augury)
watchers -= w
continue
var/mob/dead/observer/O = w
- if(biggest_doom && (!O.orbiting || O.orbiting.orbiting != biggest_doom))
+ if(biggest_doom && (!O.orbiting || O.orbiting.parent != biggest_doom))
O.ManualFollow(biggest_doom)
/datum/action/innate/augury
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index a2c60618ac..a365405ce6 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -256,10 +256,13 @@ GLOBAL_LIST_EMPTY(the_station_areas)
/datum/controller/subsystem/mapping/proc/generate_station_area_list()
var/list/station_areas_blacklist = typecacheof(list(/area/space, /area/mine, /area/ruin, /area/asteroid/nearstation))
for(var/area/A in world)
- var/turf/picked = safepick(get_area_turfs(A.type))
- if(picked && is_station_level(picked.z))
- if(!(A.type in GLOB.the_station_areas) && !is_type_in_typecache(A, station_areas_blacklist))
- GLOB.the_station_areas.Add(A.type)
+ if (is_type_in_typecache(A, station_areas_blacklist))
+ continue
+ if (!A.contents.len || !A.unique)
+ continue
+ var/turf/picked = A.contents[1]
+ if (is_station_level(picked.z))
+ GLOB.the_station_areas += A.type
if(!GLOB.the_station_areas.len)
log_world("ERROR: Station areas list failed to generate!")
@@ -495,4 +498,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
clearing |= used_turfs //used turfs is an associative list, BUT, reserve_turfs() can still handle it. If the code above works properly, this won't even be needed as the turfs would be freed already.
unused_turfs.Cut()
used_turfs.Cut()
- reserve_turfs(clearing)
\ No newline at end of file
+ reserve_turfs(clearing)
+
+/datum/controller/subsystem/mapping/proc/reg_in_areas_in_z(list/areas)
+ for(var/B in areas)
+ var/area/A = B
+ A.reg_in_areas_in_z()
diff --git a/code/controllers/subsystem/squeak.dm b/code/controllers/subsystem/minor_mapping.dm
similarity index 62%
rename from code/controllers/subsystem/squeak.dm
rename to code/controllers/subsystem/minor_mapping.dm
index 861bb0d8d5..2160cae6e3 100644
--- a/code/controllers/subsystem/squeak.dm
+++ b/code/controllers/subsystem/minor_mapping.dm
@@ -1,22 +1,14 @@
-// The Squeak
-// because this is about placement of mice mobs, and nothing to do with
-// mice - the computer peripheral
-
-SUBSYSTEM_DEF(squeak)
- name = "Squeak"
- init_order = INIT_ORDER_SQUEAK
+SUBSYSTEM_DEF(minor_mapping)
+ name = "Minor Mapping"
+ init_order = INIT_ORDER_MINOR_MAPPING
flags = SS_NO_FIRE
- var/list/exposed_wires = list()
-
-/datum/controller/subsystem/squeak/Initialize(timeofday)
+/datum/controller/subsystem/minor_mapping/Initialize(timeofday)
trigger_migration(CONFIG_GET(number/mice_roundstart))
return ..()
-/datum/controller/subsystem/squeak/proc/trigger_migration(num_mice=10)
- if(!num_mice)
- return
- find_exposed_wires()
+/datum/controller/subsystem/minor_mapping/proc/trigger_migration(num_mice=10)
+ var/list/exposed_wires = find_exposed_wires()
var/mob/living/simple_animal/mouse/M
var/turf/proposed_turf
@@ -31,7 +23,8 @@ SUBSYSTEM_DEF(squeak)
num_mice -= 1
M = null
-/datum/controller/subsystem/squeak/proc/find_exposed_wires()
+/proc/find_exposed_wires()
+ var/list/exposed_wires = list()
exposed_wires.Cut()
var/list/all_turfs
for (var/z in SSmapping.levels_by_trait(ZTRAIT_STATION))
@@ -41,3 +34,5 @@ SUBSYSTEM_DEF(squeak)
continue
if(locate(/obj/structure/cable) in T)
exposed_wires += T
+
+ return shuffle(exposed_wires)
\ No newline at end of file
diff --git a/code/controllers/subsystem/orbit.dm b/code/controllers/subsystem/orbit.dm
deleted file mode 100644
index 45d280b601..0000000000
--- a/code/controllers/subsystem/orbit.dm
+++ /dev/null
@@ -1,44 +0,0 @@
-SUBSYSTEM_DEF(orbit)
- name = "Orbits"
- priority = FIRE_PRIORITY_ORBIT
- wait = 2
- flags = SS_NO_INIT|SS_TICKER
-
- var/list/currentrun = list()
- var/list/processing = list()
-
-/datum/controller/subsystem/orbit/stat_entry()
- ..("P:[processing.len]")
-
-
-/datum/controller/subsystem/orbit/fire(resumed = 0)
- if (!resumed)
- src.currentrun = processing.Copy()
-
- //cache for sanic speed (lists are references anyways)
- var/list/currentrun = src.currentrun
-
- while (currentrun.len)
- var/datum/orbit/O = currentrun[currentrun.len]
- currentrun.len--
- if (!O)
- processing -= O
- if (MC_TICK_CHECK)
- return
- continue
- if (!O.orbiter)
- qdel(O)
- if (MC_TICK_CHECK)
- return
- continue
- if (O.lastprocess >= world.time) //we already checked recently
- if (MC_TICK_CHECK)
- return
- continue
- var/targetloc = get_turf(O.orbiting)
- if (targetloc != O.lastloc || O.orbiter.loc != targetloc)
- O.Check(targetloc)
- if (MC_TICK_CHECK)
- return
-
-
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index 978eedb62f..455b53b1df 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -28,6 +28,7 @@ SUBSYSTEM_DEF(persistence)
LoadPhotoPersistence()
if(CONFIG_GET(flag/use_antag_rep))
LoadAntagReputation()
+ LoadRandomizedRecipes()
return ..()
/datum/controller/subsystem/persistence/proc/LoadSatchels()
@@ -206,6 +207,7 @@ SUBSYSTEM_DEF(persistence)
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
if(CONFIG_GET(flag/use_antag_rep))
CollectAntagReputation()
+ SaveRandomizedRecipes()
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
var/album_path = file("data/photo_albums.json")
@@ -371,3 +373,43 @@ SUBSYSTEM_DEF(persistence)
fdel(FILE_ANTAG_REP)
text2file(json_encode(antag_rep), FILE_ANTAG_REP)
+/datum/controller/subsystem/persistence/proc/LoadRandomizedRecipes()
+ var/json_file = file("data/RandomizedChemRecipes.json")
+ var/json
+ if(fexists(json_file))
+ json = json_decode(file2text(json_file))
+
+ for(var/randomized_type in subtypesof(/datum/chemical_reaction/randomized))
+ var/datum/chemical_reaction/randomized/R = new randomized_type
+ var/loaded = FALSE
+ if(R.persistent && json)
+ var/list/recipe_data = json[R.id]
+ if(recipe_data && R.LoadOldRecipe(recipe_data) && (daysSince(R.created) <= R.persistence_period))
+ loaded = TRUE
+ if(!loaded) //We do not have information for whatever reason, just generate new one
+ R.GenerateRecipe()
+
+ if(!R.HasConflicts()) //Might want to try again if conflicts happened in the future.
+ add_chemical_reaction(R)
+
+/datum/controller/subsystem/persistence/proc/SaveRandomizedRecipes()
+ var/json_file = file("data/RandomizedChemRecipes.json")
+ var/list/file_data = list()
+
+ //asert globchems done
+ for(var/randomized_type in subtypesof(/datum/chemical_reaction/randomized))
+ var/datum/chemical_reaction/randomized/R = randomized_type
+ R = get_chemical_reaction(initial(R.id)) //ew, would be nice to add some simple tracking
+ if(R && R.persistent && R.id)
+ var/recipe_data = list()
+ recipe_data["timestamp"] = R.created
+ recipe_data["required_reagents"] = R.required_reagents
+ recipe_data["required_catalysts"] = R.required_catalysts
+ recipe_data["required_temp"] = R.required_temp
+ recipe_data["is_cold_recipe"] = R.is_cold_recipe
+ recipe_data["results"] = R.results
+ recipe_data["required_container"] = "[R.required_container]"
+ file_data["[R.id]"] = recipe_data
+
+ fdel(json_file)
+ WRITE_FILE(json_file, json_encode(file_data))
diff --git a/code/controllers/subsystem/religion.dm b/code/controllers/subsystem/religion.dm
deleted file mode 100644
index 1c3cd76da4..0000000000
--- a/code/controllers/subsystem/religion.dm
+++ /dev/null
@@ -1,11 +0,0 @@
-SUBSYSTEM_DEF(religion)
- name = "Religion"
- flags = SS_NO_FIRE|SS_NO_INIT
-
- var/religion
- var/deity
- var/bible_name
- var/bible_icon_state
- var/bible_item_state
- var/holy_weapon_type
- var/holy_armor_type
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index de58c1a0d7..77ad712b99 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -116,7 +116,7 @@ SUBSYSTEM_DEF(throwing)
return
dist_travelled++
-
+
if (dist_travelled > MAX_THROWING_DIST)
finalize()
return
@@ -154,7 +154,7 @@ SUBSYSTEM_DEF(throwing)
/datum/thrownthing/proc/hitcheck()
for (var/thing in get_turf(thrownthing))
var/atom/movable/AM = thing
- if (AM == thrownthing)
+ if (AM == thrownthing || (AM == thrower && !ismob(thrownthing)))
continue
if (AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags_1 & ON_BORDER_1))
finalize(hit=TRUE, target=AM)
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 4a3143da79..df96c44df7 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -126,9 +126,20 @@ SUBSYSTEM_DEF(ticker)
if(!GLOB.syndicate_code_phrase)
- GLOB.syndicate_code_phrase = generate_code_phrase()
+ GLOB.syndicate_code_phrase = generate_code_phrase(return_list=TRUE)
+
+ var/codewords = jointext(GLOB.syndicate_code_phrase, "|")
+ var/regex/codeword_match = new("([codewords])", "ig")
+
+ GLOB.syndicate_code_phrase_regex = codeword_match
+
if(!GLOB.syndicate_code_response)
- GLOB.syndicate_code_response = generate_code_phrase()
+ GLOB.syndicate_code_response = generate_code_phrase(return_list=TRUE)
+
+ var/codewords = jointext(GLOB.syndicate_code_response, "|")
+ var/regex/codeword_match = new("([codewords])", "ig")
+
+ GLOB.syndicate_code_response_regex = codeword_match
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
if(CONFIG_GET(flag/randomize_shift_time))
@@ -561,6 +572,15 @@ SUBSYSTEM_DEF(ticker)
news_message = "The burst of energy released near [station_name()] has been confirmed as merely a test of a new weapon. However, due to an unexpected mechanical error, their communications system has been knocked offline."
if(SHUTTLE_HIJACK)
news_message = "During routine evacuation procedures, the emergency shuttle of [station_name()] had its navigation protocols corrupted and went off course, but was recovered shortly after."
+ if(GANG_VICTORY)
+ news_message = "Company officials reaffirmed that sudden deployments of special forces are not in any way connected to rumors of [station_name()] being covered in graffiti."
+
+ if(SSblackbox.first_death)
+ var/list/ded = SSblackbox.first_death
+ if(ded.len)
+ news_message += " NT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""]"
+ else
+ news_message += " NT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
if(news_message)
send2otherserver(news_source, news_message,"News_Report")
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index c92db7cd01..d0eb0b9ce2 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -71,7 +71,6 @@ SUBSYSTEM_DEF(timer)
for(var/I in second_queue)
log_world(get_timer_debug_string(I))
- var/cut_start_index = 1
var/next_clienttime_timer_index = 0
var/len = length(clienttime_timers)
@@ -94,14 +93,14 @@ SUBSYSTEM_DEF(timer)
if(ctime_timer.flags & TIMER_LOOP)
ctime_timer.spent = 0
- clienttime_timers.Insert(ctime_timer, 1)
- cut_start_index++
+ ctime_timer.timeToRun = REALTIMEOFDAY + ctime_timer.wait
+ BINARY_INSERT(ctime_timer, clienttime_timers, datum/timedevent, timeToRun)
else
qdel(ctime_timer)
if (next_clienttime_timer_index)
- clienttime_timers.Cut(cut_start_index,next_clienttime_timer_index+1)
+ clienttime_timers.Cut(1, next_clienttime_timer_index+1)
if (MC_TICK_CHECK)
return
diff --git a/code/controllers/subsystem/traumas.dm b/code/controllers/subsystem/traumas.dm
index d70493dedf..ee1f5b8c3d 100644
--- a/code/controllers/subsystem/traumas.dm
+++ b/code/controllers/subsystem/traumas.dm
@@ -72,7 +72,7 @@ SUBSYSTEM_DEF(traumas)
"security" = typecacheof(list(/obj/item/clothing/under/rank/security, /obj/item/clothing/under/rank/warden,
/obj/item/clothing/under/rank/head_of_security, /obj/item/clothing/under/rank/det,
/obj/item/melee/baton, /obj/item/gun/energy/taser, /obj/item/restraints/handcuffs,
- /obj/machinery/door/airlock/security)),
+ /obj/machinery/door/airlock/security, /obj/effect/hallucination/simple/securitron)),
"clowns" = typecacheof(list(/obj/item/clothing/under/rank/clown, /obj/item/clothing/shoes/clown_shoes,
/obj/item/clothing/mask/gas/clown_hat, /obj/item/instrument/bikehorn,
@@ -160,22 +160,22 @@ SUBSYSTEM_DEF(traumas)
/obj/item/grown/bananapeel/mimanapeel, /obj/item/cartridge/virus/mime, /obj/item/clothing/shoes/sneakers/mime,
/obj/item/bedsheet/mime, /obj/item/reagent_containers/food/snacks/burger/mime, /obj/item/clothing/head/beret, /obj/item/clothing/mask/gas/sexymime,
/obj/item/clothing/under/sexymime, /obj/item/toy/figure/mime, /obj/item/toy/crayon/mime, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced, /obj/mecha/combat/reticence)),
-
+
"cats" = typecacheof(list(/obj/item/organ/ears/cat, /obj/item/organ/tail/cat, /obj/item/laser_pointer, /obj/item/toy/cattoy, /obj/item/clothing/head/kitty,
/obj/item/clothing/head/collectable/kitty, /obj/item/melee/chainofcommand/tailwhip/kitty, /obj/item/stack/sheet/animalhide/cat)),
-
+
"syndicate" = typecacheof(list(/obj/item/stack/tile/mineral/plastitanium, /obj/machinery/computer/shuttle/syndicate, /obj/machinery/computer/shuttle/syndicate/recall, /obj/machinery/computer/shuttle/syndicate/drop_pod, /obj/machinery/computer/camera_advanced/shuttle_docker/syndicate, /obj/machinery/recharge_station,
/obj/machinery/porta_turret/syndicate, /obj/structure/closet/syndicate, /obj/machinery/suit_storage_unit/syndicate, /obj/item/clothing/under/syndicate, /obj/item/folder/syndicate, /obj/item/documents/syndicate, /obj/item/clothing/glasses/phantomthief/syndicate, /obj/item/antag_spawner/nuke_ops, /obj/item/storage/box/syndicate,
/obj/structure/fluff/empty_sleeper/syndicate, /obj/item/implant/radio/syndicate, /obj/item/clothing/head/helmet/space/syndicate, /obj/machinery/nuclearbomb/syndicate, /obj/item/grenade/syndieminibomb, /obj/item/storage/backpack/duffelbag/syndie, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver/syndie,
/obj/item/gun/ballistic/automatic/shotgun/bulldog, /obj/item/gun/ballistic/automatic/c20r, /obj/item/gun/ballistic/automatic/m90, /obj/item/gun/ballistic/automatic/l6_saw, /obj/item/storage/belt/grenade/full, /obj/item/gun/ballistic/automatic/sniper_rifle/syndicate, /obj/item/gun/energy/kinetic_accelerator/crossbow,
- /obj/item/melee/transforming/energy/sword/saber, /obj/item/twohanded/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
+ /obj/item/melee/transforming/energy/sword/saber, /obj/item/twohanded/dualsaber, /obj/item/melee/powerfist, /obj/item/storage/box/syndie_kit, /obj/item/grenade/spawnergrenade/manhacks, /obj/item/grenade/chem_grenade/bioterrorfoam, /obj/item/reagent_containers/spray/chemsprayer/bioterror, /obj/item/ammo_box/magazine/m10mm,
/obj/item/ammo_box/magazine/pistolm9mm, /obj/item/ammo_box/a357, /obj/item/ammo_box/magazine/m12g, /obj/item/ammo_box/magazine/mm195x129, /obj/item/antag_spawner/nuke_ops, /obj/mecha/combat/gygax/dark, /obj/mecha/combat/marauder/mauler, /obj/item/soap/syndie, /obj/item/gun/syringe/syndicate, /obj/item/cartridge/virus/syndicate,
/obj/item/cartridge/virus/frame, /obj/item/chameleon, /obj/item/storage/box/syndie_kit/cutouts, /obj/item/clothing/suit/space/hardsuit/syndi, /obj/item/card/emag, /obj/item/storage/toolbox/syndicate, /obj/item/storage/book/bible/syndicate, /obj/item/encryptionkey/binary, /obj/item/encryptionkey/syndicate, /obj/item/aiModule/syndicate,
- /obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited,
- /obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate,
- /obj/machinery/computer/pod/old/syndicate, /obj/machinery/vending/medical/syndicate_access, /obj/item/mmi/syndie, /obj/item/target/syndicate, /obj/machinery/vending/cigarette/syndicate, /obj/item/robot_module/syndicate, /obj/item/clothing/mask/gas/syndicate, /obj/machinery/power/singularity_beacon/syndicate, /obj/item/clothing/head/syndicatefake,
- /obj/item/radio/headset/syndicate, /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate, /obj/item/pda/syndicate, /obj/item/clothing/suit/armor/vest/capcarapace/syndicate, /obj/item/gun/ballistic/automatic/flechette, /obj/item/ammo_box/magazine/flechette, /obj/item/clothing/suit/toggle/lawyer/black/syndie, /obj/item/melee/transforming/energy/sword/cx/traitor,
- /obj/structure/sign/poster/contraband/syndicate_pistol, /obj/structure/sign/poster/contraband/syndicate_recruitment, /obj/item/bedsheet/syndie, /obj/item/borg/upgrade/syndicate, /obj/item/tank/jetpack/oxygen/harness, /obj/item/firing_pin/implant/pindicate, /obj/item/reagent_containers/glass/bottle/traitor, /obj/item/storage/belt/military,
+ /obj/item/clothing/shoes/magboots/syndie, /obj/item/powersink, /obj/item/sbeacondrop, /obj/item/sbeacondrop/bomb, /obj/item/syndicatedetonator, /obj/item/shield/energy, /obj/item/assault_pod, /obj/item/slimepotion/slime/sentience/nuclear, /obj/item/stack/telecrystal, /obj/item/jammer, /obj/item/codespeak_manual/unlimited,
+ /obj/item/toy/cards/deck/syndicate, /obj/item/storage/secure/briefcase/syndie, /obj/item/storage/fancy/cigarettes/cigpack_syndicate, /obj/item/toy/syndicateballoon, /obj/item/clothing/gloves/rapid, /obj/item/paper/fluff/ruins/thederelict/syndie_mission, /obj/item/organ/cyberimp/eyes/hud/security/syndicate, /obj/item/clothing/head/HoS/syndicate,
+ /obj/machinery/computer/pod/old/syndicate, /obj/machinery/vending/medical/syndicate_access, /obj/item/mmi/syndie, /obj/item/target/syndicate, /obj/machinery/vending/cigarette/syndicate, /obj/item/robot_module/syndicate, /obj/item/clothing/mask/gas/syndicate, /obj/machinery/power/singularity_beacon/syndicate, /obj/item/clothing/head/syndicatefake,
+ /obj/item/radio/headset/syndicate, /obj/item/gun/ballistic/automatic/pistol/antitank/syndicate, /obj/item/pda/syndicate, /obj/item/clothing/suit/armor/vest/capcarapace/syndicate, /obj/item/gun/ballistic/automatic/flechette, /obj/item/ammo_box/magazine/flechette, /obj/item/clothing/suit/toggle/lawyer/black/syndie, /obj/item/melee/transforming/energy/sword/cx/traitor,
+ /obj/structure/sign/poster/contraband/syndicate_pistol, /obj/structure/sign/poster/contraband/syndicate_recruitment, /obj/item/bedsheet/syndie, /obj/item/borg/upgrade/syndicate, /obj/item/tank/jetpack/oxygen/harness, /obj/item/firing_pin/implant/pindicate, /obj/item/reagent_containers/glass/bottle/traitor, /obj/item/storage/belt/military,
/obj/item/twohanded/shockpaddles/syndicate, /obj/item/clothing/mask/cigarette/syndicate, /obj/item/toy/plush/nukeplushie)),
"eye" = typecacheof(list(/obj/item/organ/eyes, /obj/item/reagent_containers/syringe))
@@ -199,7 +199,7 @@ SUBSYSTEM_DEF(traumas)
"anime" = typecacheof(list(/datum/species/human/felinid)),
"cats" = typecacheof(list(/datum/species/human/felinid)),
"syndicate" = typecacheof(list(/datum/species/corporate, /datum/species/zombie/infectious))
- )
+ )
return ..()
diff --git a/code/datums/action.dm b/code/datums/action.dm
index b7089279cb..f64a549b29 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -195,11 +195,16 @@
/datum/action/item_action/toggle_firemode
name = "Toggle Firemode"
-/datum/action/item_action/rcl
+/datum/action/item_action/rcl_col
name = "Change Cable Color"
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "rcl_rainbow"
+/datum/action/item_action/rcl_gui
+ name = "Toggle Fast Wiring Gui"
+ icon_icon = 'icons/mob/actions/actions_items.dmi'
+ button_icon_state = "rcl_gui"
+
/datum/action/item_action/startchainsaw
name = "Pull The Starting Cord"
diff --git a/code/datums/brain_damage/brain_trauma.dm b/code/datums/brain_damage/brain_trauma.dm
index 941e7103c6..56a3f3969b 100644
--- a/code/datums/brain_damage/brain_trauma.dm
+++ b/code/datums/brain_damage/brain_trauma.dm
@@ -9,7 +9,8 @@
var/obj/item/organ/brain/brain //the poor bastard's brain
var/gain_text = "You feel traumatized."
var/lose_text = "You no longer feel traumatized."
- var/can_gain = TRUE //can this be gained through random traumas?
+ var/can_gain = TRUE
+ var/random_gain = TRUE //can this be gained through random traumas?
var/resilience = TRAUMA_RESILIENCE_BASIC //how hard is this to cure?
/datum/brain_trauma/Destroy()
@@ -23,7 +24,7 @@
//Called on life ticks
/datum/brain_trauma/proc/on_life()
return
-
+
//Called on death
/datum/brain_trauma/proc/on_death()
return
@@ -31,16 +32,18 @@
//Called when given to a mob
/datum/brain_trauma/proc/on_gain()
to_chat(owner, gain_text)
+ RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
//Called when removed from a mob
/datum/brain_trauma/proc/on_lose(silent)
if(!silent)
to_chat(owner, lose_text)
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
//Called when hearing a spoken message
/datum/brain_trauma/proc/on_hear(message, speaker, message_language, raw_message, radio_freq)
return message
//Called when speaking
-/datum/brain_trauma/proc/on_say(message)
- return message
+/datum/brain_trauma/proc/handle_speech(datum/source, list/speech_args)
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm
index afd53726db..c049a7db33 100644
--- a/code/datums/brain_damage/mild.dm
+++ b/code/datums/brain_damage/mild.dm
@@ -42,7 +42,7 @@
lose_text = "You feel smart again."
/datum/brain_trauma/mild/dumbness/on_gain()
- owner.add_trait(TRAIT_DUMB, TRAUMA_TRAIT)
+ ADD_TRAIT(owner, TRAIT_DUMB, TRAUMA_TRAIT)
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "dumb", /datum/mood_event/oblivious)
..()
@@ -55,7 +55,7 @@
..()
/datum/brain_trauma/mild/dumbness/on_lose()
- owner.remove_trait(TRAIT_DUMB, TRAUMA_TRAIT)
+ REMOVE_TRAIT(owner, TRAIT_DUMB, TRAUMA_TRAIT)
owner.derpspeech = 0
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "dumb")
..()
@@ -68,18 +68,12 @@
lose_text = ""
/datum/brain_trauma/mild/speech_impediment/on_gain()
- owner.dna.add_mutation(UNINTELLIGIBLE)
- ..()
-
-//no fiddling with genetics to get out of this one
-/datum/brain_trauma/mild/speech_impediment/on_life()
- if(!(GLOB.mutations_list[UNINTELLIGIBLE] in owner.dna.mutations))
- on_gain()
- ..()
+ ADD_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
+ . = ..()
/datum/brain_trauma/mild/speech_impediment/on_lose()
- owner.dna.remove_mutation(UNINTELLIGIBLE)
- ..()
+ REMOVE_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
+ . = ..()
/datum/brain_trauma/mild/concussion
name = "Concussion"
diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm
index c6ccbee38c..6723c89ba5 100644
--- a/code/datums/brain_damage/phobia.dm
+++ b/code/datums/brain_damage/phobia.dm
@@ -78,14 +78,13 @@
break
return message
-/datum/brain_trauma/mild/phobia/on_say(message)
+/datum/brain_trauma/mild/phobia/handle_speech(datum/source, list/speech_args)
for(var/word in trigger_words)
var/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
-
- if(findtext(message, reg))
+
+ if(findtext(speech_args[SPEECH_MESSAGE], reg))
to_chat(owner, "You can't bring yourself to say the word \"[word]\"!")
- return ""
- return message
+ speech_args[SPEECH_MESSAGE] = ""
/datum/brain_trauma/mild/phobia/proc/freak_out(atom/reason, trigger_word)
next_scare = world.time + 120
@@ -119,3 +118,7 @@
owner.confused += 10
owner.Jitter(10)
owner.stuttering += 10
+
+/datum/brain_trauma/mild/phobia/security
+ phobia_type = "security"
+ random_gain = FALSE
diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm
index a8adbfbce8..d094c162d7 100644
--- a/code/datums/brain_damage/severe.dm
+++ b/code/datums/brain_damage/severe.dm
@@ -13,11 +13,11 @@
lose_text = "You suddenly remember how to speak."
/datum/brain_trauma/severe/mute/on_gain()
- owner.add_trait(TRAIT_MUTE, TRAUMA_TRAIT)
+ ADD_TRAIT(owner, TRAIT_MUTE, TRAUMA_TRAIT)
..()
/datum/brain_trauma/severe/mute/on_lose()
- owner.remove_trait(TRAIT_MUTE, TRAUMA_TRAIT)
+ REMOVE_TRAIT(owner, TRAIT_MUTE, TRAUMA_TRAIT)
..()
/datum/brain_trauma/severe/aphasia
@@ -60,18 +60,68 @@
/datum/brain_trauma/severe/paralysis
name = "Paralysis"
- desc = "Patient's brain can no longer control its motor functions."
+ desc = "Patient's brain can no longer control part of its motor functions."
scan_desc = "cerebral paralysis"
- gain_text = "You can't feel your body anymore!"
- lose_text = "You can feel your limbs again!"
+ gain_text = ""
+ lose_text = ""
+ var/paralysis_type
+ var/list/paralysis_traits = list()
+ //for descriptions
-/datum/brain_trauma/severe/paralysis/on_life()
- owner.Knockdown(200, ignore_canknockdown = TRUE)
+/datum/brain_trauma/severe/paralysis/New(specific_type)
+ if(specific_type)
+ paralysis_type = specific_type
+ if(!paralysis_type)
+ paralysis_type = pick("full","left","right","arms","legs","r_arm","l_arm","r_leg","l_leg")
+ var/subject
+ switch(paralysis_type)
+ if("full")
+ subject = "your body"
+ paralysis_traits = list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG)
+ if("left")
+ subject = "the left side of your body"
+ paralysis_traits = list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_L_LEG)
+ if("right")
+ subject = "the right side of your body"
+ paralysis_traits = list(TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_R_LEG)
+ if("arms")
+ subject = "your arms"
+ paralysis_traits = list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM)
+ if("legs")
+ subject = "your legs"
+ paralysis_traits = list(TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG)
+ if("r_arm")
+ subject = "your right arm"
+ paralysis_traits = list(TRAIT_PARALYSIS_R_ARM)
+ if("l_arm")
+ subject = "your left arm"
+ paralysis_traits = list(TRAIT_PARALYSIS_L_ARM)
+ if("r_leg")
+ subject = "your right leg"
+ paralysis_traits = list(TRAIT_PARALYSIS_R_LEG)
+ if("l_leg")
+ subject = "your left leg"
+ paralysis_traits = list(TRAIT_PARALYSIS_L_LEG)
+
+ gain_text = "You can't feel [subject] anymore!"
+ lose_text = "You can feel [subject] again!"
+
+/datum/brain_trauma/severe/paralysis/on_gain()
..()
+ for(var/X in paralysis_traits)
+ ADD_TRAIT(owner, X, "trauma_paralysis")
+ owner.update_disabled_bodyparts()
/datum/brain_trauma/severe/paralysis/on_lose()
- owner.SetKnockdown(0)
..()
+ for(var/X in paralysis_traits)
+ REMOVE_TRAIT(owner, X, "trauma_paralysis")
+ owner.update_disabled_bodyparts()
+
+/datum/brain_trauma/severe/paralysis/paraplegic
+ //can_gain = FALSE maybe breaks.
+ paralysis_type = "legs"
+ resilience = TRAUMA_RESILIENCE_ABSOLUTE
/datum/brain_trauma/severe/narcolepsy
name = "Narcolepsy"
@@ -121,7 +171,7 @@
stress -= 4
/datum/brain_trauma/severe/monophobia/proc/check_alone()
- if(owner.has_trait(TRAIT_BLIND))
+ if(HAS_TRAIT(owner, TRAIT_BLIND))
return TRUE
for(var/mob/M in oview(owner, 7))
if(!isliving(M)) //ghosts ain't people
@@ -183,11 +233,11 @@
lose_text = "You feel in control of your hands again."
/datum/brain_trauma/severe/discoordination/on_gain()
- owner.add_trait(TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
+ ADD_TRAIT(owner, TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
..()
/datum/brain_trauma/severe/discoordination/on_lose()
- owner.remove_trait(TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
+ REMOVE_TRAIT(owner, TRAIT_MONKEYLIKE, TRAUMA_TRAIT)
..()
/datum/brain_trauma/severe/pacifism
@@ -198,9 +248,9 @@
lose_text = "You no longer feel compelled to not harm."
/datum/brain_trauma/severe/pacifism/on_gain()
- owner.add_trait(TRAIT_PACIFISM, TRAUMA_TRAIT)
+ ADD_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
..()
/datum/brain_trauma/severe/pacifism/on_lose()
- owner.remove_trait(TRAIT_PACIFISM, TRAUMA_TRAIT)
- ..()
\ No newline at end of file
+ REMOVE_TRAIT(owner, TRAIT_PACIFISM, TRAUMA_TRAIT)
+ ..()
diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm
index 0bbbf8de08..d9e6f00643 100644
--- a/code/datums/brain_damage/special.dm
+++ b/code/datums/brain_damage/special.dm
@@ -134,3 +134,71 @@
/datum/brain_trauma/special/psychotic_brawling/bath_salts
name = "Chemical Violent Psychosis"
+ random_gain = FALSE
+
+/datum/brain_trauma/special/beepsky
+ name = "Criminal"
+ desc = "Patient seems to be a criminal."
+ scan_desc = "criminal mind"
+ gain_text = "Justice is coming for you."
+ lose_text = "You were absolved for your crimes."
+ random_gain = FALSE
+ var/obj/effect/hallucination/simple/securitron/beepsky
+
+/datum/brain_trauma/special/beepsky/on_gain()
+ create_securitron()
+ ..()
+
+/datum/brain_trauma/special/beepsky/proc/create_securitron()
+ var/turf/where = locate(owner.x + pick(-12, 12), owner.y + pick(-12, 12), owner.z)
+ beepsky = new(where, owner)
+ beepsky.victim = owner
+
+/datum/brain_trauma/special/beepsky/on_lose()
+ QDEL_NULL(beepsky)
+ ..()
+
+/datum/brain_trauma/special/beepsky/on_life()
+ if(QDELETED(beepsky) || !beepsky.loc || beepsky.z != owner.z)
+ QDEL_NULL(beepsky)
+ if(prob(30))
+ create_securitron()
+ else
+ return
+ if(get_dist(owner, beepsky) >= 10 && prob(20))
+ QDEL_NULL(beepsky)
+ create_securitron()
+ if(owner.stat != CONSCIOUS)
+ if(prob(20))
+ owner.playsound_local(beepsky, 'sound/voice/beepsky/iamthelaw.ogg', 50)
+ return
+ if(get_dist(owner, beepsky) <= 1)
+ owner.playsound_local(owner, 'sound/weapons/egloves.ogg', 50)
+ owner.visible_message("[owner]'s body jerks as if it was shocked.", "You feel the fist of the LAW.")
+ owner.take_bodypart_damage(0,0,rand(40, 70))
+ QDEL_NULL(beepsky)
+ if(prob(20) && get_dist(owner, beepsky) <= 8)
+ owner.playsound_local(beepsky, 'sound/voice/beepsky/criminal.ogg', 40)
+ ..()
+
+/obj/effect/hallucination/simple/securitron
+ name = "Securitron"
+ desc = "The LAW is coming."
+ image_icon = 'icons/mob/aibots.dmi'
+ image_state = "secbot-c"
+ var/victim
+
+/obj/effect/hallucination/simple/securitron/New()
+ name = pick ( "officer Beepsky", "officer Johnson", "officer Pingsky")
+ START_PROCESSING(SSfastprocess,src)
+ ..()
+
+/obj/effect/hallucination/simple/securitron/process()
+ if(prob(60))
+ forceMove(get_step_towards(src, victim))
+ if(prob(5))
+ to_chat(victim, "[name] exclaims, \"Level 10 infraction alert!\"")
+
+/obj/effect/hallucination/simple/securitron/Destroy()
+ STOP_PROCESSING(SSfastprocess,src)
+ return ..()
\ No newline at end of file
diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm
index 9ce65717f1..653b8a98c0 100644
--- a/code/datums/brain_damage/split_personality.dm
+++ b/code/datums/brain_damage/split_personality.dm
@@ -192,17 +192,16 @@
return //no random switching
/datum/brain_trauma/severe/split_personality/brainwashing/on_hear(message, speaker, message_language, raw_message, radio_freq)
- if(owner.has_trait(TRAIT_DEAF) || owner == speaker)
+ if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == speaker)
return message
if(findtext(message, codeword))
message = replacetext(message, codeword, "[codeword]")
addtimer(CALLBACK(src, /datum/brain_trauma/severe/split_personality.proc/switch_personalities), 10)
return message
-/datum/brain_trauma/severe/split_personality/brainwashing/on_say(message)
- if(findtext(message, codeword))
- return "" //oh hey did you want to tell people about the secret word to bring you back?
- return message
+/datum/brain_trauma/severe/split_personality/brainwashing/handle_speech(datum/source, list/speech_args)
+ if(findtext(speech_args[SPEECH_MESSAGE], codeword))
+ speech_args[SPEECH_MESSAGE] = "" //oh hey did you want to tell people about the secret word to bring you back?
/mob/living/split_personality/traitor
name = "split personality"
diff --git a/code/datums/components/bouncy.dm b/code/datums/components/bouncy.dm
new file mode 100644
index 0000000000..f6a2a89195
--- /dev/null
+++ b/code/datums/components/bouncy.dm
@@ -0,0 +1,40 @@
+/datum/component/bouncy
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ var/bouncy_mod = 1
+ var/list/bounce_signals = list(COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_HIT_REACT, COMSIG_ITEM_ATTACK)
+
+/datum/component/bouncy/Initialize(_bouncy_mod, list/_bounce_signals)
+ if(!ismovableatom(parent))
+ return COMPONENT_INCOMPATIBLE
+ if(_bouncy_mod)
+ bouncy_mod = _bouncy_mod
+ if(_bounce_signals)
+ bounce_signals = _bounce_signals
+
+/datum/component/bouncy/InheritComponent(datum/component/bouncy/B, original, _bouncy_mod, list/_bounce_signals)
+ if(_bouncy_mod)
+ bouncy_mod = max(bouncy_mod, _bouncy_mod)
+ if(_bounce_signals)
+ var/list/diff_bounces = difflist(bounce_signals, _bounce_signals, TRUE)
+ for(var/bounce in diff_bounces)
+ bounce_signals += bounce
+ RegisterSignal(parent, bounce, .proc/bounce_up)
+
+/datum/component/bouncy/RegisterWithParent()
+ RegisterSignal(parent, bounce_signals, .proc/bounce_up)
+
+/datum/component/bouncy/UnregisterFromParent()
+ UnregisterSignal(parent, bounce_signals)
+
+/datum/component/bouncy/proc/bounce_up(datum/source)
+ var/atom/movable/A = parent
+ switch(rand(1, 3))
+ if(1)
+ A.do_jiggle(45 + rand(-10, 10) * bouncy_mod, 14)
+ if(2)
+ var/min_b = 0.6/bouncy_mod
+ var/max_b = 1.2 * bouncy_mod
+ A.do_squish(rand(min_b, max_b), rand(min_b, max_b), 14)
+ if(3)
+ var/pixelshift = 8 * bouncy_mod
+ A.Shake(pixelshift, pixelshift, duration = 15)
diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm
index 1e1b7a0a48..838a1b576a 100644
--- a/code/datums/components/caltrop.dm
+++ b/code/datums/components/caltrop.dm
@@ -24,7 +24,7 @@
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
- if(H.has_trait(TRAIT_PIERCEIMMUNE))
+ if(HAS_TRAIT(H, TRAIT_PIERCEIMMUNE))
return
if((flags & CALTROP_IGNORE_WALKERS) && H.m_intent == MOVE_INTENT_WALK)
@@ -46,7 +46,7 @@
return
var/damage = rand(min_damage, max_damage)
- if(H.has_trait(TRAIT_LIGHT_STEP))
+ if(HAS_TRAIT(H, TRAIT_LIGHT_STEP))
damage *= 0.75
H.apply_damage(damage, BRUTE, picked_def_zone)
diff --git a/code/datums/components/earhealing.dm b/code/datums/components/earhealing.dm
index 9396eab3a3..6eb71285e0 100644
--- a/code/datums/components/earhealing.dm
+++ b/code/datums/components/earhealing.dm
@@ -23,7 +23,7 @@
if (!wearer)
STOP_PROCESSING(SSobj, src)
return
- if(!wearer.has_trait(TRAIT_DEAF))
+ if(!HAS_TRAIT(wearer, TRAIT_DEAF))
var/obj/item/organ/ears/ears = wearer.getorganslot(ORGAN_SLOT_EARS)
if (ears)
ears.deaf = max(ears.deaf - 1, (ears.ear_damage < UNHEALING_EAR_DAMAGE ? 0 : 1)) // Do not clear deafness while above the unhealing ear damage threshold
diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm
index c93be4dae3..bfcc49f453 100644
--- a/code/datums/components/footstep.dm
+++ b/code/datums/components/footstep.dm
@@ -1,39 +1,105 @@
-/datum/component/footstep
- var/steps = 0
- var/volume
- var/e_range
-
-/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
- if(!isliving(parent))
- return COMPONENT_INCOMPATIBLE
- volume = volume_
- e_range = e_range_
- RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
-
-/datum/component/footstep/proc/play_footstep()
- var/turf/open/T = get_turf(parent)
- if(!istype(T))
- return
- var/mob/living/LM = parent
- var/v = volume
- var/e = e_range
- if(!T.footstep || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
- return
- if(iscarbon(LM))
- var/mob/living/carbon/C = LM
- if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
- return
- if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
- v /= 2
- e -= 5
- steps++
- if(steps >= 3)
- steps = 0
- else
- return
- if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
- return
- playsound(T, pick(GLOB.footstep[T.footstep][1]),
- GLOB.footstep[T.footstep][2] * v,
- TRUE,
- GLOB.footstep[T.footstep][3] + e)
+/datum/component/footstep
+ var/steps = 0
+ var/volume
+ var/e_range
+
+/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
+ if(!isliving(parent))
+ return COMPONENT_INCOMPATIBLE
+ volume = volume_
+ e_range = e_range_
+ RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
+
+/datum/component/footstep/proc/play_footstep()
+ var/turf/open/T = get_turf(parent)
+ if(!istype(T))
+ return
+
+ var/mob/living/LM = parent
+ var/v = volume
+ var/e = e_range
+ if(!T.footstep || LM.buckled || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing || LM.movement_type & (VENTCRAWLING | FLYING))
+ if (LM.lying && !(!T.footstep || LM.movement_type & (VENTCRAWLING | FLYING))) //play crawling sound if we're lying
+ playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
+ return
+
+ if(iscarbon(LM))
+ var/mob/living/carbon/C = LM
+ if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
+ return
+ if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
+ v /= 2
+ e -= 5
+ steps++
+
+ if(steps >= 3)
+ steps = 0
+
+ else
+ return
+
+ if(prob(80) && !LM.has_gravity(T)) // don't need to step as often when you hop around
+ return
+
+ //begin playsound shenanigans//
+
+ //for barefooted non-clawed mobs like monkeys
+ if(isbarefoot(LM))
+ playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
+ GLOB.barefootstep[T.barefootstep][2] * v,
+ TRUE,
+ GLOB.barefootstep[T.barefootstep][3] + e)
+ return
+
+ //for xenomorphs, dogs, and other clawed mobs
+ if(isclawfoot(LM))
+ if(isalienadult(LM)) //xenos are stealthy and get quieter footsteps
+ v /= 3
+ e -= 5
+
+ playsound(T, pick(GLOB.clawfootstep[T.clawfootstep][1]),
+ GLOB.clawfootstep[T.clawfootstep][2] * v,
+ TRUE,
+ GLOB.clawfootstep[T.clawfootstep][3] + e)
+ return
+
+ //for megafauna and other large and imtimidating mobs such as the bloodminer
+ if(isheavyfoot(LM))
+ playsound(T, pick(GLOB.heavyfootstep[T.heavyfootstep][1]),
+ GLOB.heavyfootstep[T.heavyfootstep][2] * v,
+ TRUE,
+ GLOB.heavyfootstep[T.heavyfootstep][3] + e)
+ return
+
+ //for slimes
+ if(isslime(LM))
+ playsound(T, 'sound/effects/footstep/slime1.ogg', 15 * v)
+ return
+
+ //for (simple) humanoid mobs (clowns, russians, pirates, etc.)
+ if(isshoefoot(LM))
+ if(!ishuman(LM))
+ playsound(T, pick(GLOB.footstep[T.footstep][1]),
+ GLOB.footstep[T.footstep][2] * v,
+ TRUE,
+ GLOB.footstep[T.footstep][3] + e)
+ return
+ if(ishuman(LM)) //for proper humans, they're special
+ var/mob/living/carbon/human/H = LM
+ var/feetCover = (H.wear_suit && (H.wear_suit.body_parts_covered & FEET)) || (H.w_uniform && (H.w_uniform.body_parts_covered & FEET))
+
+ if (H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle") //are we a naga or tentacle taur creature
+ playsound(T, 'sound/effects/footstep/crawl1.ogg', 15 * v)
+ return
+
+ if(H.shoes || feetCover) //are we wearing shoes
+ playsound(T, pick(GLOB.footstep[T.footstep][1]),
+ GLOB.footstep[T.footstep][2] * v,
+ TRUE,
+ GLOB.footstep[T.footstep][3] + e)
+
+ if((!H.shoes && !feetCover)) //are we NOT wearing shoes
+ playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
+ GLOB.barefootstep[T.barefootstep][2] * v,
+ TRUE,
+ GLOB.barefootstep[T.barefootstep][3] + e)
\ No newline at end of file
diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm
index 933c38505b..b32921a4ce 100644
--- a/code/datums/components/mood.dm
+++ b/code/datums/components/mood.dm
@@ -15,7 +15,7 @@
/datum/component/mood/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
-
+
START_PROCESSING(SSmood, src)
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
@@ -150,17 +150,17 @@
else
owner.crit_threshold -= (holdmyinsanityeffect - insanity_effect)
- if(owner.has_trait(TRAIT_DEPRESSION))
+ if(HAS_TRAIT(owner, TRAIT_DEPRESSION))
if(prob(0.05))
add_event(null, "depression", /datum/mood_event/depression)
clear_event(null, "jolly")
- if(owner.has_trait(TRAIT_JOLLY))
+ if(HAS_TRAIT(owner, TRAIT_JOLLY))
if(prob(0.05))
add_event(null, "jolly", /datum/mood_event/jolly)
clear_event(null, "depression")
holdmyinsanityeffect = insanity_effect
-
+
HandleNutrition(owner)
/datum/component/mood/proc/DecreaseSanity(amount, minimum = SANITY_INSANE)
diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm
index 426855f887..c7dd7123d2 100644
--- a/code/datums/components/nanites.dm
+++ b/code/datums/components/nanites.dm
@@ -2,10 +2,10 @@
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/mob/living/host_mob
- var/nanite_volume = 100 //amount of nanites in the system, used as fuel for nanite programs
- var/max_nanites = 500 //maximum amount of nanites in the system
+ var/nanite_volume = 50 //amount of nanites in the system, used as fuel for nanite programs
+ var/max_nanites = 250 //maximum amount of nanites in the system
var/regen_rate = 0.5 //nanites generated per second
- var/safety_threshold = 50 //how low nanites will get before they stop processing/triggering
+ var/safety_threshold = 25 //how low nanites will get before they stop processing/triggering
var/cloud_id = 0 //0 if not connected to the cloud, 1-100 to set a determined cloud backup to draw from
var/next_sync = 0
var/list/datum/nanite_program/programs = list()
@@ -311,4 +311,4 @@
mob_program["trigger_code"] = P.trigger_code
id++
mob_programs += list(mob_program)
- data["mob_programs"] = mob_programs
\ No newline at end of file
+ data["mob_programs"] = mob_programs
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
new file mode 100644
index 0000000000..301e50dc42
--- /dev/null
+++ b/code/datums/components/orbiter.dm
@@ -0,0 +1,156 @@
+/datum/component/orbiter
+ dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
+ var/list/orbiters
+ var/datum/callback/orbiter_spy
+ var/datum/callback/orbited_spy
+
+//radius: range to orbit at, radius of the circle formed by orbiting (in pixels)
+//clockwise: whether you orbit clockwise or anti clockwise
+//rotation_speed: how fast to rotate (how many ds should it take for a rotation to complete)
+//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
+//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
+/datum/component/orbiter/Initialize(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+ if(!istype(orbiter) || !isatom(parent) || isarea(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ orbiters = list()
+ orbiter_spy = CALLBACK(src, .proc/orbiter_move_react)
+ orbited_spy = CALLBACK(src, .proc/move_react)
+
+ var/atom/master = parent
+ master.orbiters = src
+
+ begin_orbit(orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+
+/datum/component/orbiter/RegisterWithParent()
+ var/atom/target = parent
+ while(ismovableatom(target))
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy)
+ target = target.loc
+
+/datum/component/orbiter/UnregisterFromParent()
+ var/atom/target = parent
+ while(ismovableatom(target))
+ UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
+ target = target.loc
+
+/datum/component/orbiter/Destroy()
+ var/atom/master = parent
+ master.orbiters = null
+ for(var/i in orbiters)
+ end_orbit(i)
+ orbiters = null
+ QDEL_NULL(orbiter_spy)
+ QDEL_NULL(orbited_spy)
+ return ..()
+
+/datum/component/orbiter/InheritComponent(datum/component/orbiter/newcomp, original, list/arguments)
+ if(arguments)
+ begin_orbit(arglist(arguments))
+ return
+ // The following only happens on component transfers
+ orbiters += newcomp.orbiters
+
+/datum/component/orbiter/PostTransfer()
+ if(!isatom(parent) || isarea(parent) || !get_turf(parent))
+ return COMPONENT_INCOMPATIBLE
+ move_react()
+
+/datum/component/orbiter/proc/begin_orbit(atom/movable/orbiter, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+ if(orbiter.orbiting)
+ if(orbiter.orbiting == src)
+ orbiter.orbiting.end_orbit(orbiter, TRUE)
+ else
+ orbiter.orbiting.end_orbit(orbiter)
+ orbiters[orbiter] = TRUE
+ orbiter.orbiting = src
+ RegisterSignal(orbiter, COMSIG_MOVABLE_MOVED, orbiter_spy)
+ var/matrix/initial_transform = matrix(orbiter.transform)
+
+ // Head first!
+ if(pre_rotation)
+ var/matrix/M = matrix(orbiter.transform)
+ var/pre_rot = 90
+ if(!clockwise)
+ pre_rot = -90
+ M.Turn(pre_rot)
+ orbiter.transform = M
+
+ var/matrix/shift = matrix(orbiter.transform)
+ shift.Translate(0, radius)
+ orbiter.transform = shift
+
+ orbiter.SpinAnimation(rotation_speed, -1, clockwise, rotation_segments, parallel = FALSE)
+
+ //we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
+ orbiter.transform = initial_transform
+ orbiter.forceMove(get_turf(parent))
+ to_chat(orbiter, "Now orbiting [parent].")
+
+/datum/component/orbiter/proc/end_orbit(atom/movable/orbiter, refreshing=FALSE)
+ if(!orbiters[orbiter])
+ return
+ UnregisterSignal(orbiter, COMSIG_MOVABLE_MOVED)
+ orbiter.SpinAnimation(0, 0)
+ orbiters -= orbiter
+ orbiter.stop_orbit(src)
+ orbiter.orbiting = null
+ if(!refreshing && !length(orbiters) && !QDELING(src))
+ qdel(src)
+
+// This proc can receive signals by either the thing being directly orbited or anything holding it
+/datum/component/orbiter/proc/move_react(atom/orbited, atom/oldloc, direction)
+ set waitfor = FALSE // Transfer calls this directly and it doesnt care if the ghosts arent done moving
+
+ var/atom/movable/master = parent
+ if(master.loc == oldloc)
+ return
+
+ var/turf/newturf = get_turf(master)
+ if(!newturf)
+ qdel(src)
+
+ // Handling the signals of stuff holding us (or not anymore)
+ // These are prety rarely activated, how often are you following something in a bag?
+ if(oldloc && !isturf(oldloc)) // We used to be registered to it, probably
+ var/atom/target = oldloc
+ while(ismovableatom(target))
+ UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
+ target = target.loc
+ if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too
+ var/atom/target = orbited.loc
+ while(ismovableatom(target))
+ RegisterSignal(target, COMSIG_MOVABLE_MOVED, orbited_spy, TRUE)
+ target = target.loc
+
+ var/atom/curloc = master.loc
+ for(var/i in orbiters)
+ var/atom/movable/thing = i
+ if(QDELETED(thing) || thing.loc == newturf)
+ continue
+ thing.forceMove(newturf)
+ if(CHECK_TICK && master.loc != curloc)
+ // We moved again during the checktick, cancel current operation
+ break
+
+
+/datum/component/orbiter/proc/orbiter_move_react(atom/movable/orbiter, atom/oldloc, direction)
+ if(orbiter.loc == get_turf(parent))
+ return
+ end_orbit(orbiter)
+
+/////////////////////
+
+/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE)
+ if(!istype(A) || !get_turf(A) || A == src)
+ return
+
+ return A.AddComponent(/datum/component/orbiter, src, radius, clockwise, rotation_speed, rotation_segments, pre_rotation)
+
+/atom/movable/proc/stop_orbit(datum/component/orbiter/orbits)
+ return // We're just a simple hook
+
+/atom/proc/transfer_observers_to(atom/target)
+ if(!orbiters || !istype(target) || !get_turf(target) || target == src)
+ return
+ target.TakeComponent(orbiters)
diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm
index 4d7e8bddc5..0b78605869 100644
--- a/code/datums/components/storage/concrete/_concrete.dm
+++ b/code/datums/components/storage/concrete/_concrete.dm
@@ -6,6 +6,8 @@
/datum/component/storage/concrete
var/drop_all_on_deconstruct = TRUE
var/drop_all_on_destroy = FALSE
+ var/drop_all_on_break = FALSE
+ var/unlock_on_break = FALSE
var/transfer_contents_on_component_transfer = FALSE
var/list/datum/component/storage/slaves = list()
@@ -16,6 +18,7 @@
. = ..()
RegisterSignal(parent, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
RegisterSignal(parent, COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct)
+ RegisterSignal(parent, COMSIG_OBJ_BREAK, .proc/on_break)
/datum/component/storage/concrete/Destroy()
var/atom/real_location = real_location()
@@ -100,6 +103,12 @@
if(drop_all_on_deconstruct)
do_quick_empty()
+/datum/component/storage/concrete/proc/on_break(datum/source, damage_flag)
+ if(drop_all_on_break)
+ do_quick_empty()
+ if(unlock_on_break)
+ set_locked(source, FALSE)
+
/datum/component/storage/concrete/can_see_contents()
. = ..()
for(var/i in slaves)
diff --git a/code/datums/components/storage/concrete/emergency.dm b/code/datums/components/storage/concrete/emergency.dm
new file mode 100644
index 0000000000..48880ff605
--- /dev/null
+++ b/code/datums/components/storage/concrete/emergency.dm
@@ -0,0 +1,38 @@
+/datum/component/storage/concrete/emergency
+ drop_all_on_break = TRUE
+ unlock_on_break = TRUE
+ locked = TRUE
+
+/datum/component/storage/concrete/emergency/Initialize()
+ . = ..()
+ RegisterSignal(parent, COMSIG_ATOM_EMAG_ACT, .proc/unlock_me)
+
+/datum/component/storage/concrete/emergency/on_attack_hand(datum/source, mob/user)
+ var/atom/A = parent
+ if(!attack_hand_interact)
+ return
+ if(user.active_storage == src && A.loc == user) //if you're already looking inside the storage item
+ user.active_storage.close(user)
+ close(user)
+ . = COMPONENT_NO_ATTACK_HAND
+ return
+ . = COMPONENT_NO_ATTACK_HAND
+ if(!check_locked(source, user, TRUE))
+ show_to(user)
+ A.do_jiggle()
+ if(rustle_sound)
+ playsound(A, "rustle", 50, 1, -5)
+
+/datum/component/storage/concrete/emergency/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE)
+ if(!silent && istype(I, /obj/item/card/emag))
+ silent = TRUE // suppresses the message
+ return ..()
+
+/datum/component/storage/concrete/emergency/check_locked(datum/source, mob/user, message = FALSE)
+ . = locked && GLOB.security_level < SEC_LEVEL_RED
+ if(message && . && user)
+ to_chat(user, "The storage unit will only unlock during a Red or Delta security alert.")
+
+/datum/component/storage/concrete/emergency/proc/unlock_me(datum/source)
+ if(locked)
+ set_locked(source, FALSE)
diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm
index dc25729e37..0c701cb943 100644
--- a/code/datums/components/storage/storage.dm
+++ b/code/datums/components/storage/storage.dm
@@ -156,8 +156,7 @@
next += slave.parent
/datum/component/storage/proc/attack_self(datum/source, mob/M)
- if(locked)
- to_chat(M, "[parent] seems to be locked!")
+ if(check_locked(source, M, TRUE))
return FALSE
if((M.get_active_held_item() == parent) && allow_quick_empty)
quick_empty(M)
@@ -166,8 +165,7 @@
if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE))
return FALSE
. = COMPONENT_NO_ATTACK
- if(locked)
- to_chat(M, "[parent] seems to be locked!")
+ if(check_locked(source, M, TRUE))
return FALSE
var/atom/A = parent
var/obj/item/I = O
@@ -238,8 +236,7 @@
var/atom/A = parent
if((!ishuman(M) && (A.loc != M)) || (M.stat != CONSCIOUS) || M.restrained() || !M.canmove)
return
- if(locked)
- to_chat(M, "[parent] seems to be locked!")
+ if(check_locked(null, M, TRUE))
return FALSE
A.add_fingerprint(M)
to_chat(M, "You start dumping out [parent].")
@@ -281,7 +278,7 @@
/datum/component/storage/proc/set_locked(datum/source, new_state)
locked = new_state
- if(locked)
+ if(check_locked())
close_all()
/datum/component/storage/proc/_process_numerical_display()
@@ -456,8 +453,7 @@
var/atom/A = parent
var/atom/dump_destination = dest_object.get_dumping_location()
if(A.Adjacent(M) && dump_destination && M.Adjacent(dump_destination))
- if(locked)
- to_chat(M, "[parent] seems to be locked!")
+ if(check_locked(null, M, TRUE))
return FALSE
if(dump_destination.storage_contents_dump_act(src, M))
playsound(A, "rustle", 50, 1, -5)
@@ -535,11 +531,9 @@
if(!istype(M))
return FALSE
A.add_fingerprint(M)
- if(locked && !force)
- to_chat(M, "[parent] seems to be locked!")
+ if(!force && (check_locked(null, M) || !M.CanReach(parent, view_only = TRUE)))
return FALSE
- if(force || M.CanReach(parent, view_only = TRUE))
- show_to(M)
+ show_to(M)
/datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M)
if(isitem(O))
@@ -563,10 +557,9 @@
var/atom/host = parent
if(real_location == I.loc)
return FALSE //Means the item is already in the storage item
- if(locked)
+ if(check_locked(null, M, !stop_messages))
if(M && !stop_messages)
host.add_fingerprint(M)
- to_chat(M, "[host] seems to be locked!")
return FALSE
if(real_location.contents.len >= max_items)
if(!stop_messages)
@@ -599,7 +592,7 @@
if(!stop_messages)
to_chat(M, "[IP] cannot hold [I] as it's a storage item of the same size!")
return FALSE //To prevent the stacking of same sized storage items.
- if(I.item_flags & NODROP) //SHOULD be handled in unEquip, but better safe than sorry.
+ if(HAS_TRAIT(I, TRAIT_NODROP)) //SHOULD be handled in unEquip, but better safe than sorry.
to_chat(M, "\the [I] is stuck to your hand, you can't put it in \the [host]!")
return FALSE
var/datum/component/storage/concrete/master = master()
@@ -659,8 +652,10 @@
/datum/component/storage/proc/on_check()
return TRUE
-/datum/component/storage/proc/check_locked()
- return locked
+/datum/component/storage/proc/check_locked(datum/source, mob/user, message = FALSE)
+ . = locked
+ if(message && . && user)
+ to_chat(user, "[parent] seems to be locked!")
/datum/component/storage/proc/signal_take_type(datum/source, type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted)
if(!force)
@@ -720,9 +715,7 @@
if(A.loc == user)
. = COMPONENT_NO_ATTACK_HAND
- if(locked)
- to_chat(user, "[parent] seems to be locked!")
- else
+ if(!check_locked(source, user, TRUE))
show_to(user)
A.do_jiggle()
@@ -747,15 +740,15 @@
/datum/component/storage/proc/on_alt_click(datum/source, mob/user)
if(!isliving(user) || !user.CanReach(parent))
return
- if(locked)
- to_chat(user, "[parent] seems to be locked!")
+ if(check_locked(source, user, TRUE))
return
var/atom/A = parent
if(!quickdraw)
A.add_fingerprint(user)
user_show_to_mob(user)
- playsound(A, "rustle", 50, 1, -5)
+ if(rustle_sound)
+ playsound(A, "rustle", 50, 1, -5)
return
if(!user.incapacitated())
diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm
index c5966452bb..8982530ab6 100644
--- a/code/datums/components/uplink.dm
+++ b/code/datums/components/uplink.dm
@@ -21,6 +21,9 @@ GLOBAL_LIST_EMPTY(uplinks)
var/datum/uplink_purchase_log/purchase_log
var/list/uplink_items
var/hidden_crystals = 0
+ var/unlock_note
+ var/unlock_code
+ var/failsafe_code
/datum/component/uplink/Initialize(_owner, _lockable = TRUE, _enabled = FALSE, datum/game_mode/_gamemode, starting_tc = 20)
if(!isitem(parent))
@@ -219,7 +222,10 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
var/obj/item/pda/master = parent
- if(trim(lowertext(new_ring_text)) != trim(lowertext(master.lock_code))) //why is the lock code stored on the pda?
+ if(trim(lowertext(new_ring_text)) != trim(lowertext(unlock_code)))
+ if(trim(lowertext(new_ring_text)) == trim(lowertext(failsafe_code)))
+ failsafe()
+ return COMPONENT_STOP_RINGTONE_CHANGE
return
locked = FALSE
interact(null, user)
@@ -233,7 +239,9 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/new_frequency(datum/source, list/arguments)
var/obj/item/radio/master = parent
var/frequency = arguments[1]
- if(frequency != master.traitor_frequency)
+ if(frequency != unlock_code)
+ if(frequency == failsafe_code)
+ failsafe()
return
locked = FALSE
if(ismob(master.loc))
@@ -243,9 +251,38 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/pen_rotation(datum/source, degrees, mob/living/carbon/user)
var/obj/item/pen/master = parent
- if(degrees != master.traitor_unlock_degrees)
+ if(degrees != unlock_code)
+ if(degrees == failsafe_code) //Getting failsafes on pens is risky business
+ failsafe()
return
locked = FALSE
master.degrees = 0
interact(null, user)
- to_chat(user, "Your pen makes a clicking noise, before quickly rotating back to 0 degrees!")
\ No newline at end of file
+ to_chat(user, "Your pen makes a clicking noise, before quickly rotating back to 0 degrees!")
+
+/datum/component/uplink/proc/setup_unlock_code()
+ unlock_code = generate_code()
+ var/obj/item/P = parent
+ if(istype(parent,/obj/item/pda))
+ unlock_note = "Uplink Passcode: [unlock_code] ([P.name])."
+ else if(istype(parent,/obj/item/radio))
+ unlock_note = "Radio Frequency: [format_frequency(unlock_code)] ([P.name])."
+ else if(istype(parent,/obj/item/pen))
+ unlock_note = "Uplink Degrees: [unlock_code] ([P.name])."
+
+/datum/component/uplink/proc/generate_code()
+ if(istype(parent,/obj/item/pda))
+ return "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
+ else if(istype(parent,/obj/item/radio))
+ return sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
+ else if(istype(parent,/obj/item/pen))
+ return rand(1, 360)
+
+/datum/component/uplink/proc/failsafe()
+ if(!parent)
+ return
+ var/turf/T = get_turf(parent)
+ if(!T)
+ return
+ explosion(T,1,2,3)
+ qdel(parent) //Alternatively could brick the uplink.
diff --git a/code/datums/datum.dm b/code/datums/datum.dm
index e74e30b536..cdb195dd82 100644
--- a/code/datums/datum.dm
+++ b/code/datums/datum.dm
@@ -2,6 +2,7 @@
var/gc_destroyed //Time when this object was destroyed.
var/list/active_timers //for SStimer
var/list/datum_components //for /datum/components
+ var/list/status_traits
var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register
var/list/signal_procs
var/signal_enabled = FALSE
diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm
index ba570eca06..e1432bf9a6 100644
--- a/code/datums/diseases/_MobProcs.dm
+++ b/code/datums/diseases/_MobProcs.dm
@@ -117,7 +117,7 @@
/mob/living/carbon/AirborneContractDisease(datum/disease/D, force_spread)
if(internal)
return
- if(has_trait(TRAIT_NOBREATH))
+ if(HAS_TRAIT(src, TRAIT_NOBREATH))
return
..()
@@ -137,7 +137,7 @@
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
if(dna)
- if(has_trait(TRAIT_VIRUSIMMUNE) && !D.bypasses_immunity)
+ if(HAS_TRAIT(src, TRAIT_VIRUSIMMUNE) && !D.bypasses_immunity)
return FALSE
for(var/thing in D.required_organs)
diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm
index 0ace2ca8fd..e666c7acd6 100644
--- a/code/datums/diseases/advance/symptoms/heal.dm
+++ b/code/datums/diseases/advance/symptoms/heal.dm
@@ -233,7 +233,7 @@
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
var/mob/living/M = A.affected_mob
- if(M.has_trait(TRAIT_DEATHCOMA))
+ if(HAS_TRAIT(M, TRAIT_DEATHCOMA))
return power
else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
return power * 0.9
@@ -364,15 +364,15 @@
/datum/symptom/heal/plasma/CanHeal(datum/disease/advance/A)
var/mob/living/M = A.affected_mob
var/datum/gas_mixture/environment
- var/list/gases
+ var/plasmamount
. = 0
if(M.loc)
environment = M.loc.return_air()
if(environment)
- gases = environment.gases
- if(gases["plasma"] && gases["plasma"][MOLES] > gases["plasma"][GAS_META][META_GAS_MOLES_VISIBLE]) //if there's enough plasma in the air to see
+ plasmamount = environment.gases[/datum/gas/plasma]
+ if(plasmamount && plasmamount > GLOB.meta_gas_visibility[/datum/gas/plasma]) //if there's enough plasma in the air to see
. += power * 0.5
if(M.reagents.has_reagent("plasma"))
. += power * 0.75
diff --git a/code/datums/diseases/advance/symptoms/sensory.dm b/code/datums/diseases/advance/symptoms/sensory.dm
index ffc145bd72..8d7cc5ed70 100644
--- a/code/datums/diseases/advance/symptoms/sensory.dm
+++ b/code/datums/diseases/advance/symptoms/sensory.dm
@@ -85,14 +85,14 @@
if(4, 5)
M.restoreEars()
- if(M.has_trait(TRAIT_BLIND, EYE_DAMAGE))
+ if(HAS_TRAIT_FROM(M, TRAIT_BLIND, EYE_DAMAGE))
if(prob(20))
to_chat(M, "Your vision slowly returns...")
M.cure_blind(EYE_DAMAGE)
M.cure_nearsighted(EYE_DAMAGE)
M.blur_eyes(35)
- else if(M.has_trait(TRAIT_NEARSIGHT, EYE_DAMAGE))
+ else if(HAS_TRAIT_FROM(M, TRAIT_NEARSIGHT, EYE_DAMAGE))
to_chat(M, "You can finally focus your eyes on distant objects.")
M.cure_nearsighted(EYE_DAMAGE)
M.blur_eyes(10)
diff --git a/code/datums/diseases/advance/symptoms/vision.dm b/code/datums/diseases/advance/symptoms/vision.dm
index 0b42012f76..d1cc6905a6 100644
--- a/code/datums/diseases/advance/symptoms/vision.dm
+++ b/code/datums/diseases/advance/symptoms/vision.dm
@@ -61,7 +61,7 @@ Bonus
M.become_nearsighted(EYE_DAMAGE)
if(prob(eyes.eye_damage - 10 + 1))
if(!remove_eyes)
- if(!M.has_trait(TRAIT_BLIND))
+ if(!HAS_TRAIT(M, TRAIT_BLIND))
to_chat(M, "You go blind!")
M.become_blind(EYE_DAMAGE)
else
diff --git a/code/datums/diseases/pierrot_throat.dm b/code/datums/diseases/pierrot_throat.dm
index 64f453cd48..b2241d59ba 100644
--- a/code/datums/diseases/pierrot_throat.dm
+++ b/code/datums/diseases/pierrot_throat.dm
@@ -26,3 +26,30 @@
if(4)
if(prob(5))
affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) , forced = "pierrot's throat")
+
+/datum/disease/pierrot_throat/after_add()
+ RegisterSignal(affected_mob, COMSIG_MOB_SAY, .proc/handle_speech)
+
+/datum/disease/pierrot_throat/proc/handle_speech(datum/source, list/speech_args)
+ var/message = speech_args[SPEECH_MESSAGE]
+ var/list/split_message = splittext(message, " ") //List each word in the message
+ var/applied = 0
+ for (var/i in 1 to length(split_message))
+ if(prob(3 * stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12%
+ if(findtext(split_message[i], "*") || findtext(split_message[i], ";") || findtext(split_message[i], ":"))
+ continue
+ split_message[i] = "HONK"
+ if (applied++ > stage)
+ break
+ if (applied)
+ speech_args[SPEECH_SPANS] |= SPAN_CLOWN // a little bonus
+ message = jointext(split_message, " ")
+ speech_args[SPEECH_MESSAGE] = message
+
+/datum/disease/pierrot_throat/Destroy()
+ UnregisterSignal(affected_mob, COMSIG_MOB_SAY)
+ return ..()
+
+/datum/disease/pierrot_throat/remove_disease()
+ UnregisterSignal(affected_mob, COMSIG_MOB_SAY)
+ return ..()
\ No newline at end of file
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 938515625d..33e92e4de5 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -185,25 +185,6 @@
if(DNA_TAUR_BLOCK)
construct_block(GLOB.taur_list.Find(features["taur"]), GLOB.taur_list.len)
-/datum/dna/proc/mutations_say_mods(message)
- if(message)
- for(var/datum/mutation/human/M in mutations)
- message = M.say_mod(message)
- return message
-
-/datum/dna/proc/mutations_get_spans()
- var/list/spans = list()
- for(var/datum/mutation/human/M in mutations)
- spans |= M.get_spans()
- return spans
-
-/datum/dna/proc/species_get_spans()
- var/list/spans = list()
- if(species)
- spans |= species.get_spans()
- return spans
-
-
/datum/dna/proc/is_same_as(datum/dna/D)
if(uni_identity == D.uni_identity && struc_enzymes == D.struc_enzymes && real_name == D.real_name && nameless == D.nameless && custom_species == D.custom_species)
if(species.type == D.species.type && features == D.features && blood_type == D.blood_type)
diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm
index 57cdb9bcf5..6c91cc3a7d 100644
--- a/code/datums/emotes.dm
+++ b/code/datums/emotes.dm
@@ -133,7 +133,7 @@
if(isliving(user))
var/mob/living/L = user
- if(L.has_trait(TRAIT_EMOTEMUTE))
+ if(HAS_TRAIT(L, TRAIT_EMOTEMUTE))
return FALSE
/datum/emote/sound
diff --git a/code/datums/ert.dm b/code/datums/ert.dm
index d3c256308d..d61c95c8f2 100644
--- a/code/datums/ert.dm
+++ b/code/datums/ert.dm
@@ -21,6 +21,8 @@
/datum/ert/amber
code = "Amber"
+ leader_role = /datum/antagonist/ert/commander/red
+ roles = list(/datum/antagonist/ert/security/red, /datum/antagonist/ert/medic/red, /datum/antagonist/ert/engineer/red)
/datum/ert/red
leader_role = /datum/antagonist/ert/commander/red
diff --git a/code/datums/explosion.dm b/code/datums/explosion.dm
index fe16b9459f..b3c57e4838 100644
--- a/code/datums/explosion.dm
+++ b/code/datums/explosion.dm
@@ -198,7 +198,8 @@ GLOBAL_LIST_EMPTY(explosions)
var/list/items = list()
for(var/I in T)
var/atom/A = I
- items += A.GetAllContents()
+ if (!A.prevent_content_explosion()) //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(!QDELETED(A))
diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm
index d673cdb16d..0623e2f5f9 100644
--- a/code/datums/helper_datums/teleport.dm
+++ b/code/datums/helper_datums/teleport.dm
@@ -103,11 +103,11 @@
// Can most things breathe?
if(trace_gases)
continue
- if(!(A_gases[/datum/gas/oxygen] && A_gases[/datum/gas/oxygen][MOLES] >= 16))
+ if(A_gases[/datum/gas/oxygen] >= 16)
continue
if(A_gases[/datum/gas/plasma])
continue
- if(A_gases[/datum/gas/carbon_dioxide] && A_gases[/datum/gas/carbon_dioxide][MOLES] >= 10)
+ if(A_gases[/datum/gas/carbon_dioxide] >= 10)
continue
// Aim for goldilocks temperatures and pressure
diff --git a/code/datums/looping_sounds/looping_sound.dm b/code/datums/looping_sounds/_looping_sound.dm
similarity index 91%
rename from code/datums/looping_sounds/looping_sound.dm
rename to code/datums/looping_sounds/_looping_sound.dm
index 2eba36dc90..1b7a304494 100644
--- a/code/datums/looping_sounds/looping_sound.dm
+++ b/code/datums/looping_sounds/_looping_sound.dm
@@ -11,7 +11,6 @@
chance (num) Chance per loop to play a mid_sound
volume (num) Sound output volume
- muted (bool) Private. Used to stop the sound loop.
max_loops (num) The max amount of loops to run for.
direct (bool) If true plays directly to provided atoms instead of from them
*/
@@ -68,7 +67,7 @@
if(!chance || prob(chance))
play(get_sound(starttime))
if(!timerid)
- timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_STOPPABLE | TIMER_LOOP)
+ timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_CLIENT_TIME | TIMER_STOPPABLE | TIMER_LOOP)
/datum/looping_sound/proc/play(soundfile)
var/list/atoms_cache = output_atoms
@@ -84,10 +83,7 @@
playsound(thing, S, volume)
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
- if(!_mid_sounds)
- . = mid_sounds
- else
- . = _mid_sounds
+ . = _mid_sounds || mid_sounds
while(!isfile(.) && !isnull(.))
. = pickweight(.)
@@ -96,7 +92,7 @@
if(start_sound)
play(start_sound)
start_wait = start_length
- addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
+ addtimer(CALLBACK(src, .proc/sound_loop), start_wait, TIMER_CLIENT_TIME)
/datum/looping_sound/proc/on_stop()
if(end_sound)
diff --git a/code/datums/martial.dm b/code/datums/martial.dm
index 2bc01e0bf6..ae8f92a342 100644
--- a/code/datums/martial.dm
+++ b/code/datums/martial.dm
@@ -5,6 +5,7 @@
var/current_target
var/datum/martial_art/base // The permanent style. This will be null unless the martial art is temporary
var/deflection_chance = 0 //Chance to deflect projectiles
+ var/reroute_deflection = FALSE //Delete the bullet, or actually deflect it in some direction?
var/block_chance = 0 //Chance to block melee attacks using items while on throw mode.
var/restraining = 0 //used in cqc's disarm_act to check if the disarmed is being restrained and so whether they should be put in a chokehold or not
var/help_verb
diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm
index 8a5f0f9439..4283d7f78f 100644
--- a/code/datums/martial/krav_maga.dm
+++ b/code/datums/martial/krav_maga.dm
@@ -86,13 +86,13 @@
return 0
/datum/martial_art/krav_maga/proc/leg_sweep(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
- if(D.stat || D.IsKnockdown())
+ if(D.lying || D.IsKnockdown())
return 0
D.visible_message("[A] leg sweeps [D]!", \
"[A] leg sweeps you!")
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE)
- D.Knockdown(40)
+ D.Knockdown(40, override_hardstun = 0.01, 25)
log_combat(A, D, "leg sweeped")
return 1
@@ -191,3 +191,18 @@
heat_protection = HANDS
max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
resistance_flags = NONE
+
+/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 = "blackglovesplus"
+ siemens_coefficient = 0
+ permeability_coefficient = 0.05
+ strip_delay = 80
+ cold_protection = HANDS
+ min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
+ heat_protection = HANDS
+ max_heat_protection_temperature = GLOVES_MAX_TEMP_PROTECT
+ resistance_flags = NONE
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 50)
diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm
index 4a15afd672..5f19c37b99 100644
--- a/code/datums/martial/sleeping_carp.dm
+++ b/code/datums/martial/sleeping_carp.dm
@@ -7,6 +7,7 @@
/datum/martial_art/the_sleeping_carp
name = "The Sleeping Carp"
deflection_chance = 100
+ reroute_deflection = TRUE
no_guns = TRUE
allow_temp_override = FALSE
help_verb = /mob/living/carbon/human/proc/sleeping_carp_help
@@ -179,7 +180,7 @@
/obj/item/twohanded/bostaff/attack(mob/target, mob/living/user)
add_fingerprint(user)
- if((user.has_trait(TRAIT_CLUMSY)) && prob(50))
+ if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
to_chat(user, "You club yourself over the head with [src].")
user.Knockdown(60)
if(ishuman(user))
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 90affe0228..7d150d890d 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -233,13 +233,10 @@
/datum/mind/proc/remove_antag_equip()
var/list/Mob_Contents = current.get_contents()
for(var/obj/item/I in Mob_Contents)
- if(istype(I, /obj/item/pda))
- var/obj/item/pda/P = I
- P.lock_code = ""
-
- else if(istype(I, /obj/item/radio))
- var/obj/item/radio/R = I
- R.traitor_frequency = 0
+ var/datum/component/uplink/O = I.GetComponent(/datum/component/uplink)
+//Todo make this reset signal
+ if(O)
+ O.unlock_code = null
/datum/mind/proc/remove_all_antag() //For the Lazy amongst us.
remove_changeling()
@@ -304,33 +301,22 @@
. = 0
else
. = uplink_loc
- uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
- var/unlock_note
-
- if(uplink_loc == R)
- R.traitor_frequency = sanitize_frequency(rand(MIN_FREQ, MAX_FREQ))
-
- if(!silent)
- to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(R.traitor_frequency)] to unlock its hidden features.")
- unlock_note = "Radio Frequency: [format_frequency(R.traitor_frequency)] ([R.name])."
- else if(uplink_loc == PDA)
- PDA.lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
-
- if(!silent)
- to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[PDA.lock_code]\" into the ringtone select to unlock its hidden features.")
- unlock_note = "Uplink Passcode: [PDA.lock_code] ([PDA.name])."
-
- else if(uplink_loc == P)
- P.traitor_unlock_degrees = rand(1, 360)
-
- if(!silent)
- to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [P.traitor_unlock_degrees] from its starting position to unlock its hidden features.")
- unlock_note = "Uplink Degrees: [P.traitor_unlock_degrees] ([P.name])."
+ var/datum/component/uplink/U = uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
+ if(!U)
+ CRASH("Uplink creation failed.")
+ U.setup_unlock_code()
+ if(!silent)
+ if(uplink_loc == R)
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [R.name]. Simply dial the frequency [format_frequency(U.unlock_code)] to unlock its hidden features.")
+ else if(uplink_loc == PDA)
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [PDA.name]. Simply enter the code \"[U.unlock_code]\" into the ringtone select to unlock its hidden features.")
+ else if(uplink_loc == P)
+ to_chat(traitor_mob, "[employer] has cunningly disguised a Syndicate Uplink as your [P.name]. Simply twist the top of the pen [U.unlock_code] from its starting position to unlock its hidden features.")
if(uplink_owner)
- uplink_owner.antag_memory += unlock_note + "
"
+ uplink_owner.antag_memory += U.unlock_note + "
"
else
- traitor_mob.mind.store_memory(unlock_note)
+ traitor_mob.mind.store_memory(U.unlock_note)
//Link a new mobs mind to the creator of said mob. They will join any team they are currently on, and will only switch teams when their creator does.
diff --git a/code/datums/mood_events/drink_events.dm b/code/datums/mood_events/drink_events.dm
index db5a91009e..5d0eb0e0cb 100644
--- a/code/datums/mood_events/drink_events.dm
+++ b/code/datums/mood_events/drink_events.dm
@@ -22,3 +22,8 @@
description = "That drink was amazing!\n"
mood_change = 4
timeout = 1200
+
+/datum/mood_event/amazingtaste
+ description = "Amazing taste!\n"
+ mood_change = 50
+ timeout = 10 MINUTES
diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm
index 4021d11128..b2b03fb56b 100644
--- a/code/datums/mood_events/generic_negative_events.dm
+++ b/code/datums/mood_events/generic_negative_events.dm
@@ -117,6 +117,16 @@
description = "I'm missing my family heirloom...\n"
mood_change = -4
+/datum/mood_event/loud_gong
+ description = "That loud gong noise really hurt my ears!\n"
+ mood_change = -3
+ timeout = 1200
+
+/datum/mood_event/spooked
+ description = "The rattling of those bones...It still haunts me.\n"
+ mood_change = -4
+ timeout = 2400
+
//These are unused so far but I want to remember them to use them later
/datum/mood_event/cloned_corpse
description = "I recently saw my own corpse...\n"
@@ -125,3 +135,11 @@
/datum/mood_event/surgery
description = "HE'S CUTTING ME OPEN!!\n"
mood_change = -8
+
+/datum/mood_event/sad_empath
+ description = "Someone seems upset...\n"
+ mood_change = -2
+ timeout = 600
+
+/datum/mood_event/sad_empath/add_effects(mob/sadtarget)
+ description = "[sadtarget.name] seems upset...\n"
diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm
index 6989744fe3..051a548d1d 100644
--- a/code/datums/mood_events/generic_positive_events.dm
+++ b/code/datums/mood_events/generic_positive_events.dm
@@ -75,3 +75,27 @@
description = "There is something soothing about this music.\n"
mood_change = 3
timeout = 600
+
+/datum/mood_event/betterhug
+ description = "Someone was very nice to me.\n"
+ mood_change = 3
+ timeout = 3000
+
+/datum/mood_event/betterhug/add_effects(mob/friend)
+ description = "[friend.name] was very nice to me.\n"
+
+/datum/mood_event/besthug
+ description = "Someone is great to be around, they make me feel so happy!\n"
+ mood_change = 5
+ timeout = 3000
+
+/datum/mood_event/besthug/add_effects(mob/friend)
+ description = "[friend.name] is great to be around, [friend.p_they()] makes me feel so happy!\n"
+
+/datum/mood_event/happy_empath
+ description = "Someone seems happy!\n"
+ mood_change = 2
+ timeout = 600
+
+/datum/mood_event/happy_empath/add_effects(var/mob/happytarget)
+ description = "[happytarget.name]'s happiness is infectious!\n"
diff --git a/code/datums/mutations.dm b/code/datums/mutations.dm
index 7de9ca8b4a..efa248b4f0 100644
--- a/code/datums/mutations.dm
+++ b/code/datums/mutations.dm
@@ -105,13 +105,6 @@ GLOBAL_LIST_EMPTY(mutations_list)
return 0
return 1
-/datum/mutation/human/proc/say_mod(message)
- if(message)
- return message
-
-/datum/mutation/human/proc/get_spans()
- return list()
-
/mob/living/carbon/proc/update_mutations_overlay()
return
diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm
index e114a43736..461c221ff8 100644
--- a/code/datums/mutations/body.dm
+++ b/code/datums/mutations/body.dm
@@ -86,12 +86,12 @@
/datum/mutation/human/clumsy/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- owner.add_trait(TRAIT_CLUMSY, GENETIC_MUTATION)
+ ADD_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
/datum/mutation/human/clumsy/on_losing(mob/living/carbon/human/owner)
if(..())
return
- owner.remove_trait(TRAIT_CLUMSY, GENETIC_MUTATION)
+ REMOVE_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
//Tourettes causes you to randomly stand in place and shout.
@@ -125,12 +125,12 @@
/datum/mutation/human/deaf/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- owner.add_trait(TRAIT_DEAF, GENETIC_MUTATION)
+ ADD_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
/datum/mutation/human/deaf/on_losing(mob/living/carbon/human/owner)
if(..())
return
- owner.remove_trait(TRAIT_DEAF, GENETIC_MUTATION)
+ REMOVE_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
//Monified turns you into a monkey.
diff --git a/code/datums/mutations/cold_resistance.dm b/code/datums/mutations/cold_resistance.dm
index 6c3ac2982d..3d8fbababa 100644
--- a/code/datums/mutations/cold_resistance.dm
+++ b/code/datums/mutations/cold_resistance.dm
@@ -17,14 +17,14 @@
/datum/mutation/human/cold_resistance/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- owner.add_trait(TRAIT_RESISTCOLD, "cold_resistance")
-// owner.add_trait(TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
+ ADD_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
+// ADD_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
/datum/mutation/human/cold_resistance/on_losing(mob/living/carbon/human/owner)
if(..())
return
- owner.remove_trait(TRAIT_RESISTCOLD, "cold_resistance")
-// owner.remove_trait(TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
+ REMOVE_TRAIT(owner, TRAIT_RESISTCOLD, "cold_resistance")
+// REMOVE_TRAIT(owner, TRAIT_RESISTLOWPRESSURE, "cold_resistance") CITADEL CHANGE
/datum/mutation/human/cold_resistance/on_life(mob/living/carbon/human/owner)
if(owner.getFireLoss())
diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm
index 7bcd056fab..85cecca489 100644
--- a/code/datums/mutations/hulk.dm
+++ b/code/datums/mutations/hulk.dm
@@ -11,10 +11,11 @@
/datum/mutation/human/hulk/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
- owner.add_trait(TRAIT_STUNIMMUNE, TRAIT_HULK)
- owner.add_trait(TRAIT_PUSHIMMUNE, TRAIT_HULK)
+ ADD_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
+ ADD_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
owner.update_body_parts()
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(mob/living/carbon/human/owner, atom/target, proximity)
if(proximity) //no telekinetic hulk attack
@@ -28,12 +29,15 @@
/datum/mutation/human/hulk/on_losing(mob/living/carbon/human/owner)
if(..())
return
- owner.remove_trait(TRAIT_STUNIMMUNE, TRAIT_HULK)
- owner.remove_trait(TRAIT_PUSHIMMUNE, TRAIT_HULK)
+ REMOVE_TRAIT(owner, TRAIT_STUNIMMUNE, TRAIT_HULK)
+ REMOVE_TRAIT(owner, TRAIT_PUSHIMMUNE, TRAIT_HULK)
owner.update_body_parts()
SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "hulk")
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
-/datum/mutation/human/hulk/say_mod(message)
+/datum/mutation/human/hulk/proc/handle_speech(original_message, wrapped_message)
+ var/message = wrapped_message[1]
if(message)
- message = "[uppertext(replacetext(message, ".", "!"))]!!"
- return message
+ message = "[replacetext(message, ".", "!")]!!"
+ wrapped_message[1] = message
+ return COMPONENT_UPPERCASE_SPEECH
diff --git a/code/datums/mutations/speech.dm b/code/datums/mutations/speech.dm
index 3f303535ce..21adc944f6 100644
--- a/code/datums/mutations/speech.dm
+++ b/code/datums/mutations/speech.dm
@@ -17,9 +17,20 @@
text_gain_indication = "You feel an off sensation in your voicebox."
text_lose_indication = "The off sensation passes."
-/datum/mutation/human/wacky/get_spans()
- return list(SPAN_SANS)
+/datum/mutation/human/wacky/on_acquiring(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
+/datum/mutation/human/wacky/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
+
+/datum/mutation/human/wacky/proc/handle_speech(datum/source, list/speech_args)
+ speech_args[SPEECH_SPANS] |= SPAN_SANS
/datum/mutation/human/mute
name = "Mute"
@@ -28,14 +39,16 @@
text_lose_indication = "You feel able to speak freely again."
/datum/mutation/human/mute/on_acquiring(mob/living/carbon/human/owner)
- if(..())
+ . = ..()
+ if(.)
return
- owner.add_trait(TRAIT_MUTE, GENETIC_MUTATION)
+ ADD_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
/datum/mutation/human/mute/on_losing(mob/living/carbon/human/owner)
- if(..())
+ . = ..()
+ if(.)
return
- owner.remove_trait(TRAIT_MUTE, GENETIC_MUTATION)
+ REMOVE_TRAIT(owner, TRAIT_MUTE, GENETIC_MUTATION)
/datum/mutation/human/smile
@@ -45,7 +58,20 @@
text_gain_indication = "You feel so happy. Nothing can be wrong with anything. :)"
text_lose_indication = "Everything is terrible again. :("
-/datum/mutation/human/smile/say_mod(message)
+/datum/mutation/human/smile/on_acquiring(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
+
+/datum/mutation/human/smile/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
+
+/datum/mutation/human/smile/proc/handle_speech(datum/source, list/speech_args)
+ var/message = speech_args[SPEECH_MESSAGE]
if(message)
message = " [message] "
//Time for a friendly game of SS13
@@ -92,7 +118,7 @@
message = replacetext(message," cunt "," privates ")
message = replacetext(message," dick "," jerk ")
message = replacetext(message," vagina "," privates ")
- return trim(message)
+ speech_args[SPEECH_MESSAGE] = trim(message)
/datum/mutation/human/unintelligible
@@ -102,30 +128,17 @@
text_gain_indication = "You can't seem to form any coherent thoughts!"
text_lose_indication = "Your mind feels more clear."
-/datum/mutation/human/unintelligible/say_mod(message)
- if(message)
- var/prefix=copytext(message,1,2)
- if(prefix == ";")
- message = copytext(message,2)
- else if(prefix in list(":","#"))
- prefix += copytext(message,2,3)
- message = copytext(message,3)
- else
- prefix=""
+/datum/mutation/human/unintelligible/on_acquiring(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ ADD_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, GENETIC_MUTATION)
- var/list/words = splittext(message," ")
- var/list/rearranged = list()
- for(var/i=1;i<=words.len;i++)
- var/cword = pick(words)
- words.Remove(cword)
- var/suffix = copytext(cword,length(cword)-1,length(cword))
- while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
- cword = copytext(cword,1 ,length(cword)-1)
- suffix = copytext(cword,length(cword)-1,length(cword) )
- if(length(cword))
- rearranged += cword
- message ="[prefix][jointext(rearranged," ")]"
- return message
+/datum/mutation/human/unintelligible/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ REMOVE_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, GENETIC_MUTATION)
/datum/mutation/human/swedish
@@ -135,7 +148,20 @@
text_gain_indication = "You feel Swedish, however that works."
text_lose_indication = "The feeling of Swedishness passes."
-/datum/mutation/human/swedish/say_mod(message)
+/datum/mutation/human/swedish/on_acquiring(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
+
+/datum/mutation/human/swedish/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
+
+/datum/mutation/human/swedish/proc/handle_speech(datum/source, list/speech_args)
+ var/message = speech_args[SPEECH_MESSAGE]
if(message)
message = replacetext(message,"w","v")
message = replacetext(message,"j","y")
@@ -144,7 +170,7 @@
message = replacetext(message,"o",pick("�","�","o"))
if(prob(30))
message += " Bork[pick("",", bork",", bork, bork")]!"
- return message
+ speech_args[SPEECH_MESSAGE] = trim(message)
/datum/mutation/human/chav
@@ -154,7 +180,20 @@
text_gain_indication = "Ye feel like a reet prat like, innit?"
text_lose_indication = "You no longer feel like being rude and sassy."
-/datum/mutation/human/chav/say_mod(message)
+/datum/mutation/human/chav/on_acquiring(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
+
+/datum/mutation/human/chav/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
+
+/datum/mutation/human/chav/proc/handle_speech(datum/source, list/speech_args)
+ var/message = speech_args[SPEECH_MESSAGE]
if(message)
message = " [message] "
message = replacetext(message," looking at "," gawpin' at ")
@@ -178,7 +217,7 @@
message = replacetext(message," break "," do ")
message = replacetext(message," your "," yer ")
message = replacetext(message," security "," coppers ")
- return trim(message)
+ speech_args[SPEECH_MESSAGE] = trim(message)
/datum/mutation/human/elvis
@@ -199,7 +238,20 @@
if(prob(15))
owner.visible_message("[owner] [pick("jiggles their hips", "rotates their hips", "gyrates their hips", "taps their foot", "dances to an imaginary song", "jiggles their legs", "snaps their fingers")]!")
-/datum/mutation/human/elvis/say_mod(message)
+/datum/mutation/human/elvis/on_acquiring(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
+
+/datum/mutation/human/elvis/on_losing(mob/living/carbon/human/owner)
+ . = ..()
+ if(.)
+ return
+ UnregisterSignal(owner, COMSIG_MOB_SAY)
+
+/datum/mutation/human/elvis/proc/handle_speech(datum/source, list/speech_args)
+ var/message = speech_args[SPEECH_MESSAGE]
if(message)
message = " [message] "
message = replacetext(message," i'm not "," I aint ")
@@ -211,7 +263,7 @@
message = replacetext(message," yes ",pick(" sure", "yea "))
message = replacetext(message," faggot "," square ")
message = replacetext(message," muh valids "," getting my kicks ")
- return trim(message)
+ speech_args[SPEECH_MESSAGE] = trim(message)
/datum/mutation/human/stoner
@@ -229,4 +281,4 @@
/datum/mutation/human/stoner/on_losing(mob/living/carbon/human/owner)
..()
owner.grant_language(/datum/language/common)
- owner.remove_language(/datum/language/beachbum)
+ owner.remove_language(/datum/language/beachbum)
\ No newline at end of file
diff --git a/code/datums/ruins/space.dm b/code/datums/ruins/space.dm
index 058c820f7a..22fca23902 100644
--- a/code/datums/ruins/space.dm
+++ b/code/datums/ruins/space.dm
@@ -281,3 +281,27 @@
suffix = "cloning_facility.dmm"
name = "Ancient Cloning Lab"
description = "An experimental cloning lab snapped off from an ancient ship. The cloner model inside lacks many modern functionalities and security measures."
+
+/datum/map_template/ruin/space/augmentation
+ id = "augmentationfacility"
+ suffix = "augmentationfacility.dmm"
+ name = "Roboticst Augmentation Facility"
+ description = "A mysterious lab in the depths of space containing robotics supplies and a one use autosurgeon."
+
+/datum/map_template/ruin/space/harambe
+ id = "bigape"
+ suffix = "bigape.dmm"
+ name = "Big Ape"
+ description = "A gorilla? Out here? But why."
+
+/datum/map_template/ruin/space/space_arcade
+ id = "arcade"
+ suffix = "arcade.dmm"
+ name = "Space Arcade"
+ description = "A lonely arcade in the depths of space."
+
+/datum/map_template/ruin/space/hermit
+ id = "spacehermit"
+ suffix = "spacehermit.dmm"
+ name = "Space Hermit"
+ description = "A late awakening cryo pod in a crashed escape pod wakes up to find what befell of his fellow survivors. Contains all the necessary resources to actually make it out alive. Good luck."
diff --git a/code/datums/saymode.dm b/code/datums/saymode.dm
index ed6edd11ab..c4f485653e 100644
--- a/code/datums/saymode.dm
+++ b/code/datums/saymode.dm
@@ -27,7 +27,7 @@
switch(M.lingcheck())
if (LINGHIVE_LING)
var/mob/living/L = M
- if (!L.has_trait(CHANGELING_HIVEMIND_MUTE))
+ if (!HAS_TRAIT(L, CHANGELING_HIVEMIND_MUTE))
to_chat(M, msg)
if(LINGHIVE_LINK)
to_chat(M, msg)
@@ -35,7 +35,7 @@
if(prob(40))
to_chat(M, "We can faintly sense an outsider trying to communicate through the hivemind...")
if(LINGHIVE_LING)
- if (user.has_trait(CHANGELING_HIVEMIND_MUTE))
+ if (HAS_TRAIT(user, CHANGELING_HIVEMIND_MUTE))
to_chat(user, "The poison in the air hinders our ability to interact with the hivemind.")
return FALSE
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
@@ -52,7 +52,7 @@
to_chat(M, msg)
if(LINGHIVE_LING)
var/mob/living/L = M
- if (!L.has_trait(CHANGELING_HIVEMIND_MUTE))
+ if (!HAS_TRAIT(L, CHANGELING_HIVEMIND_MUTE))
to_chat(M, msg)
if(LINGHIVE_OUTSIDER)
if(prob(40))
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index dd8ee1b166..0512977d1a 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -465,13 +465,13 @@
/datum/status_effect/hippocraticOath/on_apply()
//Makes the user passive, it's in their oath not to harm!
- owner.add_trait(TRAIT_PACIFISM, "hippocraticOath")
+ ADD_TRAIT(owner, TRAIT_PACIFISM, "hippocraticOath")
var/datum/atom_hud/H = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
H.add_hud_to(owner)
return ..()
/datum/status_effect/hippocraticOath/on_remove()
- owner.remove_trait(TRAIT_PACIFISM, "hippocraticOath")
+ REMOVE_TRAIT(owner, TRAIT_PACIFISM, "hippocraticOath")
var/datum/atom_hud/H = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
H.remove_hud_from(owner)
diff --git a/code/datums/traits/_quirk.dm b/code/datums/traits/_quirk.dm
index 963afacec3..cc6dd8db3f 100644
--- a/code/datums/traits/_quirk.dm
+++ b/code/datums/traits/_quirk.dm
@@ -21,7 +21,7 @@
to_chat(quirk_holder, gain_text)
quirk_holder.roundstart_quirks += src
if(mob_trait)
- quirk_holder.add_trait(mob_trait, ROUNDSTART_TRAIT)
+ ADD_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
START_PROCESSING(SSquirks, src)
add()
if(spawn_effects)
@@ -35,7 +35,7 @@
to_chat(quirk_holder, lose_text)
quirk_holder.roundstart_quirks -= src
if(mob_trait)
- quirk_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT, TRUE)
+ REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
SSquirks.quirk_objects -= src
return ..()
@@ -43,8 +43,8 @@
quirk_holder.roundstart_quirks -= src
to_mob.roundstart_quirks += src
if(mob_trait)
- quirk_holder.remove_trait(mob_trait, ROUNDSTART_TRAIT)
- to_mob.add_trait(mob_trait, ROUNDSTART_TRAIT)
+ REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
+ ADD_TRAIT(to_mob, mob_trait, ROUNDSTART_TRAIT)
quirk_holder = to_mob
on_transfer()
@@ -111,7 +111,7 @@ Use this as a guideline
mob_trait = TRAIT_NEARSIGHT
///This define is in __DEFINES/traits.dm and is the actual "trait" that the game tracks
- ///You'll need to use "has_trait(X, sources)" checks around the code to check this; for instance, the Ageusia trait is checked in taste code
+ ///You'll need to use "HAS_TRAIT_FROM(src, X, sources)" checks around the code to check this; for instance, the Ageusia trait is checked in taste code
///If you need help finding where to put it, the declaration finder on GitHub is the best way to locate it
gain_text = "Things far away from you start looking blurry."
diff --git a/code/datums/traits/good.dm b/code/datums/traits/good.dm
index 513115b194..300a1264eb 100644
--- a/code/datums/traits/good.dm
+++ b/code/datums/traits/good.dm
@@ -35,6 +35,14 @@
lose_text = "You no longer feel like drinking would ease your pain."
medical_record_text = "Patient has unusually efficient liver metabolism and can slowly regenerate wounds by drinking alcoholic beverages."
+/datum/quirk/empath
+ name = "Empath"
+ desc = "Whether it's a sixth sense or careful study of body language, it only takes you a quick glance at someone to understand how they feel."
+ value = 2
+ mob_trait = TRAIT_EMPATH
+ gain_text = "You feel in tune with those around you."
+ lose_text = "You feel isolated from others."
+
/datum/quirk/freerunning
name = "Freerunning"
desc = "You're great at quick moves! You can climb tables more quickly."
@@ -43,6 +51,15 @@
gain_text = "You feel lithe on your feet!"
lose_text = "You feel clumsy again."
+/datum/quirk/friendly
+ name = "Friendly"
+ desc = "You give the best hugs, especially when you're in the right mood."
+ value = 1
+ mob_trait = TRAIT_FRIENDLY
+ gain_text = "You want to hug someone."
+ lose_text = "You no longer feel compelled to hug others."
+ mood_quirk = TRUE
+
/datum/quirk/jolly
name = "Jolly"
desc = "You sometimes just feel happy, for no reason at all."
diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm
index 614cc65cbb..36c6733cf7 100644
--- a/code/datums/traits/negative.dm
+++ b/code/datums/traits/negative.dm
@@ -38,13 +38,13 @@
var/obj/item/heirloom_type
switch(quirk_holder.mind.assigned_role)
if("Clown")
- heirloom_type = /obj/item/paint/anycolor
- heirloom_type = /obj/item/bikehorn/golden
+ heirloom_type = pick(/obj/item/paint/anycolor, /obj/item/bikehorn/golden)
if("Mime")
- heirloom_type = /obj/item/paint/anycolor
- heirloom_type = /obj/item/toy/dummy
+ heirloom_type = pick(/obj/item/paint/anycolor, /obj/item/toy/dummy)
if("Cook")
heirloom_type = /obj/item/kitchen/knife/scimitar
+ 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
if("Station Engineer")
@@ -60,7 +60,7 @@
if("Scientist")
heirloom_type = /obj/item/toy/plush/slimeplushie
if("Assistant")
- heirloom_type = /obj/item/storage/toolbox/mechanical/old/heirloom
+ heirloom_type = /obj/item/clothing/gloves/cut/family
if("Chaplain")
heirloom_type = /obj/item/camera/spooky/family
if("Captain")
@@ -187,6 +187,41 @@
to_chat(quirk_holder, "Your antagonistic nature has caused you to renounce your pacifism.")
qdel(src)
+/datum/quirk/paraplegic
+ name = "Paraplegic"
+ desc = "Your legs do not function. Nothing will ever fix this. But hey, free wheelchair!"
+ value = -3
+ mob_trait = TRAIT_PARA
+ human_only = TRUE
+ gain_text = null // Handled by trauma.
+ lose_text = null
+ medical_record_text = "Patient has an untreatable impairment in motor function in the lower extremities."
+
+/datum/quirk/paraplegic/add()
+ var/datum/brain_trauma/severe/paralysis/paraplegic/T = new()
+ var/mob/living/carbon/human/H = quirk_holder
+ H.gain_trauma(T, TRAUMA_RESILIENCE_ABSOLUTE)
+
+/datum/quirk/paraplegic/on_spawn()
+ if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs.
+ quirk_holder.buckled.unbuckle_mob(quirk_holder)
+
+ var/turf/T = get_turf(quirk_holder)
+ var/obj/structure/chair/spawn_chair = locate() in T
+
+ var/obj/vehicle/ridden/wheelchair/wheels = new(T)
+ if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
+ wheels.setDir(spawn_chair.dir)
+
+ wheels.buckle_mob(quirk_holder)
+
+ // During the spawning process, they may have dropped what they were holding, due to the paralysis
+ // So put the things back in their hands.
+
+ for(var/obj/item/I in T)
+ if(I.fingerprintslast == quirk_holder.ckey)
+ quirk_holder.put_in_hands(I)
+
/datum/quirk/poor_aim
name = "Poor Aim"
desc = "You're terrible with guns and can't line up a straight shot to save your life. Dual-wielding is right out."
@@ -208,8 +243,12 @@
var/slot_string = "limb"
/datum/quirk/prosthetic_limb/on_spawn()
- var/limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/mob/living/carbon/human/H = quirk_holder
+ var/limb_slot
+ if(HAS_TRAIT(H, TRAIT_PARA))//Prevent paraplegic legs being replaced
+ limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
+ else
+ limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/old_part = H.get_bodypart(limb_slot)
var/obj/item/bodypart/prosthetic
switch(limb_slot)
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index f299e9904a..f70e3a3c68 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -93,3 +93,12 @@
gain_text = "You feel more prudish."
lose_text = "You don't feel as prudish as before."
medical_record_text = "Patient exhibits a special gene that makes them immune to Crocin and Hexacrocin."
+
+/datum/quirk/assblastusa
+ name = "Buns of Steel"
+ desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand."
+ mob_trait = TRAIT_ASSBLASTUSA
+ value = 0
+ medical_record_text = "Patient never skipped ass day."
+ gain_text = "Your ass rivals those of golems."
+ lose_text = "Your butt feels more squishy and slappable."
\ No newline at end of file
diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm
index 0906a7e053..f3b8118087 100644
--- a/code/datums/weather/weather_types/radiation_storm.dm
+++ b/code/datums/weather/weather_types/radiation_storm.dm
@@ -33,7 +33,7 @@
if(prob(40))
if(ishuman(L))
var/mob/living/carbon/human/H = L
- if(H.dna && !H.has_trait(TRAIT_RADIMMUNE))
+ if(H.dna && !HAS_TRAIT(H, TRAIT_RADIMMUNE))
if(prob(max(0,100-resist)))
H.randmuti()
if(prob(50))
diff --git a/code/datums/wires/microwave.dm b/code/datums/wires/microwave.dm
new file mode 100644
index 0000000000..8c74abfa46
--- /dev/null
+++ b/code/datums/wires/microwave.dm
@@ -0,0 +1,27 @@
+/datum/wires/microwave
+ holder_type = /obj/machinery/microwave
+ proper_name = "Microwave"
+
+/datum/wires/microwave/New(atom/holder)
+ wires = list(
+ WIRE_ACTIVATE
+ )
+ ..()
+
+/datum/wires/microwave/interactable(mob/user)
+ . = FALSE
+ var/obj/machinery/microwave/M = holder
+ if(M.panel_open)
+ . = TRUE
+
+/datum/wires/microwave/on_pulse(wire)
+ var/obj/machinery/microwave/M = holder
+ switch(wire)
+ if(WIRE_ACTIVATE)
+ M.cook()
+
+/datum/wires/microwave/on_cut(wire, mend)
+ var/obj/machinery/microwave/M = holder
+ switch(wire)
+ if(WIRE_ACTIVATE)
+ M.wire_disabled = !mend
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 10650153d6..dfbb59811b 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -76,7 +76,9 @@ GLOBAL_LIST_EMPTY(teleportlocs)
continue
if(GLOB.teleportlocs[AR.name])
continue
- var/turf/picked = safepick(get_area_turfs(AR.type))
+ if (!AR.contents.len)
+ continue
+ var/turf/picked = AR.contents[1]
if (picked && is_station_level(picked.z))
GLOB.teleportlocs[AR.name] = AR
@@ -120,6 +122,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(!IS_DYNAMIC_LIGHTING(src))
add_overlay(/obj/effect/fullbright)
+ reg_in_areas_in_z()
+
+ return INITIALIZE_HINT_LATELOAD
+
+/area/LateInitialize()
+ power_change() // all machines set to current power level, also updates icon
+
+/area/proc/reg_in_areas_in_z()
if(contents.len)
var/list/areas_in_z = SSmapping.areas_in_z
var/z
@@ -137,11 +147,6 @@ GLOBAL_LIST_EMPTY(teleportlocs)
areas_in_z["[z]"] = list()
areas_in_z["[z]"] += src
- return INITIALIZE_HINT_LATELOAD
-
-/area/LateInitialize()
- power_change() // all machines set to current power level, also updates icon
-
/area/Destroy()
if(GLOB.areas_by_type[type] == src)
GLOB.areas_by_type[type] = null
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 48596a0b6d..88fe2c8d13 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -6,7 +6,6 @@
var/flags_1 = NONE
var/interaction_flags_atom = NONE
- var/container_type = NONE
var/datum/reagents/reagents = null
//This atom's HUD (med/sec, etc) images. Associative list.
@@ -32,6 +31,8 @@
var/list/filter_data //For handling persistent filters
+ var/datum/component/orbiter/orbiters
+
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
var/rad_insulation = RAD_NO_INSULATION
@@ -203,16 +204,16 @@
return is_refillable() && is_drainable()
/atom/proc/is_injectable(allowmobs = TRUE)
- return reagents && (container_type & (INJECTABLE | REFILLABLE))
+ return reagents && (reagents.reagents_holder_flags & (INJECTABLE | REFILLABLE))
/atom/proc/is_drawable(allowmobs = TRUE)
- return reagents && (container_type & (DRAWABLE | DRAINABLE))
+ return reagents && (reagents.reagents_holder_flags & (DRAWABLE | DRAINABLE))
/atom/proc/is_refillable()
- return reagents && (container_type & REFILLABLE)
+ return reagents && (reagents.reagents_holder_flags & REFILLABLE)
/atom/proc/is_drainable()
- return reagents && (container_type & DRAINABLE)
+ return reagents && (reagents.reagents_holder_flags & DRAINABLE)
/atom/proc/AllowDrop()
@@ -261,7 +262,7 @@
to_chat(user, desc)
if(reagents)
- if(container_type & TRANSPARENT)
+ if(reagents.reagents_holder_flags & TRANSPARENT)
to_chat(user, "It contains:")
if(reagents.reagent_list.len)
if(user.can_see_reagents()) //Show each individual reagent
@@ -274,7 +275,7 @@
to_chat(user, "[total_volume] units of various reagents")
else
to_chat(user, "Nothing.")
- else if(container_type & AMOUNT_VISIBLE)
+ else if(reagents.reagents_holder_flags & AMOUNT_VISIBLE)
if(reagents.total_volume)
to_chat(user, "It has [reagents.total_volume] unit\s left.")
else
@@ -288,8 +289,11 @@
to_chat(user, "You can't move while buckled to [src]!")
return
+/atom/proc/prevent_content_explosion()
+ return FALSE
+
/atom/proc/contents_explosion(severity, target)
- return
+ return //For handling the effects of explosions on contents that would not normally be effected
/atom/proc/ex_act(severity, target)
set waitfor = FALSE
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index e56f6d366c..83762240bc 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -14,6 +14,7 @@
var/verb_exclaim = "exclaims"
var/verb_whisper = "whispers"
var/verb_yell = "yells"
+ var/speech_span
var/inertia_dir = 0
var/atom/inertia_last_loc
var/inertia_moving = 0
@@ -31,6 +32,8 @@
var/atom/movable/pulling
var/grab_state = 0
var/throwforce = 0
+ var/datum/component/orbiter/orbiting
+ var/can_be_z_moved = TRUE
/atom/movable/vv_edit_var(var_name, var_value)
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
@@ -295,14 +298,7 @@
if (length(client_mobs_in_contents))
update_parallax_contents()
- if (orbiters)
- for (var/thing in orbiters)
- var/datum/orbit/O = thing
- O.Check()
- if (orbiting)
- orbiting.Check()
-
- return 1
+ return TRUE
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
@@ -324,6 +320,10 @@
if(pulledby)
pulledby.stop_pulling()
+ if(orbiting)
+ orbiting.end_orbit(src)
+ orbiting = null
+
// Make sure you know what you're doing if you call this, this is intended to only be called by byond directly.
// You probably want CanPass()
/atom/movable/Cross(atom/movable/AM)
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 3af43ffb78..8506a4133a 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -100,7 +100,7 @@
//helper for getting the appropriate health status
/proc/RoundHealth(mob/living/M)
- if(M.stat == DEAD || (M.has_trait(TRAIT_FAKEDEATH)))
+ if(M.stat == DEAD || (HAS_TRAIT(M, TRAIT_FAKEDEATH)))
return "health-100" //what's our health? it doesn't matter, we're dead, or faking
var/maxi_health = M.maxHealth
if(iscarbon(M) && M.health < 0)
@@ -172,7 +172,7 @@
var/image/holder = hud_list[STATUS_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
- if(stat == DEAD || (has_trait(TRAIT_FAKEDEATH)))
+ if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
holder.icon_state = "huddead"
else
holder.icon_state = "hudhealthy"
@@ -182,9 +182,9 @@
var/icon/I = icon(icon, icon_state, dir)
var/virus_threat = check_virus()
holder.pixel_y = I.Height() - world.icon_size
- if(has_trait(TRAIT_XENO_HOST))
+ if(HAS_TRAIT(src, TRAIT_XENO_HOST))
holder.icon_state = "hudxeno"
- else if(stat == DEAD || (has_trait(TRAIT_FAKEDEATH)))
+ else if(stat == DEAD || (HAS_TRAIT(src, TRAIT_FAKEDEATH)))
if(tod)
var/tdelta = round(world.time - timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
@@ -242,7 +242,7 @@
var/icon/IC = icon(icon, icon_state, dir)
holder.pixel_y = IC.Height() - world.icon_size
holder.icon_state = "hud_imp_chem"
- if(has_trait(TRAIT_MINDSHIELD))
+ if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
holder = hud_list[IMPLOYAL_HUD]
var/icon/IC = icon(icon, icon_state, dir)
holder.pixel_y = IC.Height() - world.icon_size
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index feb81d44e0..d6131ce58e 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -86,8 +86,11 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
var/datum/dna/chosen_dna = chosen_prof.dna
user.real_name = chosen_prof.name
user.underwear = chosen_prof.underwear
+ user.undie_color = chosen_prof.undie_color
user.undershirt = chosen_prof.undershirt
+ user.shirt_color =chosen_prof.shirt_color
user.socks = chosen_prof.socks
+ user.socks_color =chosen_prof.socks_color
chosen_dna.transfer_identity(user, 1)
user.updateappearance(mutcolor_update=1)
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index d6513b5d40..94ca86e0dd 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -64,7 +64,7 @@ Credit where due:
return FALSE
if(isliving(M))
var/mob/living/L = M
- if(L.has_trait(TRAIT_MINDSHIELD))
+ if(HAS_TRAIT(L, TRAIT_MINDSHIELD))
return FALSE
if(ishuman(M) || isbrain(M) || isguardian(M) || issilicon(M) || isclockmob(M) || istype(M, /mob/living/simple_animal/drone/cogscarab) || istype(M, /mob/camera/eminence))
return TRUE
@@ -131,7 +131,7 @@ Credit where due:
config_tag = "clockwork_cult"
antag_flag = ROLE_SERVANT_OF_RATVAR
false_report_weight = 10
- required_players = 30
+ required_players = 35
required_enemies = 3
recommended_enemies = 5
enemy_minimum_age = 7
@@ -275,7 +275,7 @@ Credit where due:
gloves = /obj/item/clothing/gloves/color/yellow
belt = /obj/item/storage/belt/utility/servant
backpack_contents = list(/obj/item/storage/box/engineer = 1, \
- /obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1)
+ /obj/item/clockwork/replica_fabricator = 1, /obj/item/stack/tile/brass/fifty = 1, /obj/item/paper/servant_primer = 1, /obj/item/reagent_containers/food/drinks/holyoil = 1)
id = /obj/item/pda
var/plasmaman //We use this to determine if we should activate internals in post_equip()
@@ -338,6 +338,10 @@ Credit where due:
CLOCKCULTCHANGELOG\
\
\
+
"
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index d3b5e53a1b..ba9b6fc225 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -6,7 +6,7 @@
#define CLONE_INITIAL_DAMAGE 150 //Clones in clonepods start with 150 cloneloss damage and 150 brainloss damage, thats just logical
#define MINIMUM_HEAL_LEVEL 40
-#define SPEAK(message) radio.talk_into(src, message, radio_channel, get_spans(), get_default_language())
+#define SPEAK(message) radio.talk_into(src, message, radio_channel)
/obj/machinery/clonepod
name = "cloning pod"
@@ -182,11 +182,11 @@
//Get the clone body ready
maim_clone(H)
- H.add_trait(TRAIT_STABLEHEART, "cloning")
- H.add_trait(TRAIT_EMOTEMUTE, "cloning")
- H.add_trait(TRAIT_MUTE, "cloning")
- H.add_trait(TRAIT_NOBREATH, "cloning")
- H.add_trait(TRAIT_NOCRITDAMAGE, "cloning")
+ ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
+ ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
+ ADD_TRAIT(H, TRAIT_MUTE, "cloning")
+ ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
+ ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
H.Unconscious(80)
clonemind.transfer_to(H)
@@ -361,11 +361,11 @@
if(!mob_occupant)
return
- mob_occupant.remove_trait(TRAIT_STABLEHEART, "cloning")
- mob_occupant.remove_trait(TRAIT_EMOTEMUTE, "cloning")
- mob_occupant.remove_trait(TRAIT_MUTE, "cloning")
- mob_occupant.remove_trait(TRAIT_NOCRITDAMAGE, "cloning")
- mob_occupant.remove_trait(TRAIT_NOBREATH, "cloning")
+ REMOVE_TRAIT(mob_occupant, TRAIT_STABLEHEART, "cloning")
+ REMOVE_TRAIT(mob_occupant, TRAIT_EMOTEMUTE, "cloning")
+ REMOVE_TRAIT(mob_occupant, TRAIT_MUTE, "cloning")
+ REMOVE_TRAIT(mob_occupant, TRAIT_NOCRITDAMAGE, "cloning")
+ REMOVE_TRAIT(mob_occupant, TRAIT_NOBREATH, "cloning")
if(grab_ghost_when == CLONER_MATURE_CLONE)
mob_occupant.grab_ghost()
@@ -452,7 +452,7 @@
// brain function, they also have no limbs or internal organs.
- if(!H.has_trait(TRAIT_NODISMEMBER))
+ if(!HAS_TRAIT(H, TRAIT_NODISMEMBER))
var/static/list/zones = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)
for(var/zone in zones)
var/obj/item/bodypart/BP = H.get_bodypart(zone)
diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm
index 1f262c0979..8d0cfb95e8 100644
--- a/code/game/machinery/computer/arcade.dm
+++ b/code/game/machinery/computer/arcade.dm
@@ -1,3 +1,9 @@
+#define ARCADE_WEIGHT_TRICK 4
+#define ARCADE_WEIGHT_USELESS 2
+#define ARCADE_WEIGHT_RARE 1
+#define ARCADE_WEIGHT_PLUSH 65
+
+
/obj/machinery/computer/arcade
name = "random arcade"
desc = "random arcade machine"
@@ -6,55 +12,64 @@
icon_screen = "invaders"
clockwork = TRUE //it'd look weird
var/list/prizes = list(
- /obj/item/storage/box/snappops = 8,
- /obj/item/toy/talking/AI = 8,
- /obj/item/toy/talking/codex_gigas = 8,
- /obj/item/clothing/under/syndicate/tacticool = 8,
- /obj/item/toy/sword = 8,
- /obj/item/toy/gun = 8,
- /obj/item/gun/ballistic/shotgun/toy/crossbow = 8,
- /obj/item/storage/box/fakesyndiesuit = 8,
- /obj/item/storage/crayons = 8,
- /obj/item/toy/spinningtoy = 8,
- /obj/item/toy/prize/ripley = 4,
- /obj/item/toy/prize/fireripley = 4,
- /obj/item/toy/prize/deathripley = 4,
- /obj/item/toy/prize/gygax = 4,
- /obj/item/toy/prize/durand = 4,
- /obj/item/toy/prize/honk = 4,
- /obj/item/toy/prize/marauder = 4,
- /obj/item/toy/prize/seraph = 4,
- /obj/item/toy/prize/mauler = 4,
- /obj/item/toy/prize/odysseus = 4,
- /obj/item/toy/prize/phazon = 4,
- /obj/item/toy/prize/reticence = 4,
- /obj/item/toy/cards/deck = 8,
- /obj/item/toy/nuke = 8,
- /obj/item/toy/minimeteor = 8,
- /obj/item/toy/redbutton = 8,
- /obj/item/toy/talking/owl = 8,
- /obj/item/toy/talking/griffin = 8,
- /obj/item/coin/antagtoken = 8,
- /obj/item/stack/tile/fakespace/loaded = 8,
- /obj/item/stack/tile/fakepit/loaded = 8,
- /obj/item/toy/toy_xeno = 8,
- /obj/item/storage/box/actionfigure = 4,
- /obj/item/restraints/handcuffs/fake = 8,
- /obj/item/grenade/chem_grenade/glitter/pink = 4,
- /obj/item/grenade/chem_grenade/glitter/blue = 4,
- /obj/item/grenade/chem_grenade/glitter/white = 4,
- /obj/item/toy/eightball = 8,
- /obj/item/toy/windupToolbox = 8,
- /obj/item/toy/clockwork_watch = 8,
- /obj/item/toy/toy_dagger = 8,
- /obj/item/extendohand/acme = 4,
- /obj/item/hot_potato/harmless/toy = 4,
- /obj/item/card/emagfake = 4,
- /obj/item/clothing/shoes/wheelys = 8,
- /obj/item/clothing/shoes/kindleKicks = 8,
- /obj/item/storage/belt/military/snack = 8,
- /obj/item/toy/plush/random = 450
- )//plushies have a 0.6 chance
+ /obj/item/toy/balloon = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/beach_ball = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/cattoy = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/clockwork_watch = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/dummy = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/eightball = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/eightball/haunted = ARCADE_WEIGHT_RARE,
+ /obj/item/storage/box/actionfigure = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/foamblade = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/gun = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/gun/justicar = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/gun/m41 = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/katana = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/minimeteor = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/nuke = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/plush/random = ARCADE_WEIGHT_PLUSH,
+ /obj/item/toy/redbutton = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/spinningtoy = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/sword = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/sword/cx = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/talking/AI = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/talking/codex_gigas = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/talking/griffin = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/talking/owl = ARCADE_WEIGHT_USELESS,
+ /obj/item/toy/toy_dagger = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/toy_xeno = ARCADE_WEIGHT_TRICK,
+ /obj/item/toy/windupToolbox = ARCADE_WEIGHT_TRICK,
+
+ /mob/living/simple_animal/bot/secbot/grievous/toy = ARCADE_WEIGHT_RARE,
+ /obj/item/clothing/mask/facehugger/toy = ARCADE_WEIGHT_RARE,
+ /obj/item/gun/ballistic/automatic/toy/pistol/unrestricted = ARCADE_WEIGHT_TRICK,
+ /obj/item/hot_potato/harmless/toy = ARCADE_WEIGHT_RARE,
+ /obj/item/twohanded/dualsaber/toy = ARCADE_WEIGHT_RARE,
+ /obj/item/twohanded/hypereutactic/toy = ARCADE_WEIGHT_RARE,
+ /obj/item/twohanded/hypereutactic/toy/rainbow = ARCADE_WEIGHT_RARE,
+
+ /obj/item/storage/box/snappops = ARCADE_WEIGHT_TRICK,
+ /obj/item/clothing/under/syndicate/tacticool = ARCADE_WEIGHT_TRICK,
+ /obj/item/gun/ballistic/shotgun/toy/crossbow = ARCADE_WEIGHT_TRICK,
+ /obj/item/storage/box/fakesyndiesuit = ARCADE_WEIGHT_TRICK,
+ /obj/item/storage/crayons = ARCADE_WEIGHT_USELESS,
+ /obj/item/coin/antagtoken = ARCADE_WEIGHT_USELESS,
+ /obj/item/stack/tile/fakespace/loaded = ARCADE_WEIGHT_TRICK,
+ /obj/item/stack/tile/fakepit/loaded = ARCADE_WEIGHT_TRICK,
+ /obj/item/restraints/handcuffs/fake = ARCADE_WEIGHT_TRICK,
+
+ /obj/item/grenade/chem_grenade/glitter/pink = ARCADE_WEIGHT_TRICK,
+ /obj/item/grenade/chem_grenade/glitter/blue = ARCADE_WEIGHT_TRICK,
+ /obj/item/grenade/chem_grenade/glitter/white = ARCADE_WEIGHT_TRICK,
+
+ /obj/item/extendohand/acme = ARCADE_WEIGHT_TRICK,
+ /obj/item/card/emagfake = ARCADE_WEIGHT_TRICK,
+ /obj/item/clothing/shoes/wheelys = ARCADE_WEIGHT_RARE,
+ /obj/item/clothing/shoes/kindleKicks = ARCADE_WEIGHT_RARE,
+ /obj/item/storage/belt/military/snack = ARCADE_WEIGHT_RARE,
+
+ /obj/item/clothing/mask/fakemoustache/italian = ARCADE_WEIGHT_RARE
+ )
light_color = LIGHT_COLOR_GREEN
@@ -66,20 +81,32 @@
// If it's a generic arcade machine, pick a random arcade
// circuit board for it and make the new machine
if(!circuit)
- var/choice = pick(subtypesof(/obj/item/circuitboard/computer/arcade))
- var/obj/item/circuitboard/CB = new choice()
+ var/list/gameodds = list(/obj/item/circuitboard/computer/arcade/battle = 33,
+ /obj/item/circuitboard/computer/arcade/orion_trail = 33,
+ /obj/item/circuitboard/computer/arcade/minesweeper = 33,
+ /obj/item/circuitboard/computer/arcade/amputation = 2)
+ var/thegame = pickweight(gameodds)
+ var/obj/item/circuitboard/CB = new thegame()
new CB.build_path(loc, CB)
return INITIALIZE_HINT_QDEL
Reset()
-/obj/machinery/computer/arcade/proc/prizevend(mob/user)
+/obj/machinery/computer/arcade/proc/prizevend(mob/user, list/rarity_classes)
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "arcade", /datum/mood_event/arcade)
- if(prob(0.0001)) //1 in a million
+
+ if(prob(1) && prob(1) && prob(1)) //Proper 1 in a million
new /obj/item/gun/energy/pulse/prize(src)
SSmedals.UnlockMedal(MEDAL_PULSE, usr.client)
if(!contents.len)
- var/prizeselect = pickweight(prizes)
+ var/list/toy_raffle
+ if(rarity_classes)
+ for(var/A in prizes)
+ if(prizes[A] in rarity_classes)
+ LAZYSET(toy_raffle, A, prizes[A])
+ if(!toy_raffle)
+ toy_raffle = prizes
+ var/prizeselect = pickweight(toy_raffle)
new prizeselect(src)
var/atom/movable/prize = pick(contents)
@@ -104,1020 +131,3 @@
empprize = pickweight(prizes)
new empprize(loc)
explosion(loc, -1, 0, 1+num_of_prizes, flame_range = 1+num_of_prizes)
-
-
-// ** BATTLE ** //
-
-
-/obj/machinery/computer/arcade/battle
- name = "arcade machine"
- desc = "Does not support Pinball."
- icon_state = "arcade"
- circuit = /obj/item/circuitboard/computer/arcade/battle
- var/enemy_name = "Space Villain"
- var/temp = "Winners don't use space drugs" //Temporary message, for attack messages, etc
- var/player_hp = 30 //Player health/attack points
- var/player_mp = 10
- var/enemy_hp = 45 //Enemy health/attack points
- var/enemy_mp = 20
- var/gameover = FALSE
- var/blocked = FALSE //Player cannot attack/heal while set
- var/turtle = 0
-
-/obj/machinery/computer/arcade/battle/Reset()
- var/name_action
- var/name_part1
- var/name_part2
-
- name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "Ban ")
-
- name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ")
- name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn", "Bloopers")
-
- enemy_name = replacetext((name_part1 + name_part2), "the ", "")
- name = (name_action + name_part1 + name_part2)
-
-/obj/machinery/computer/arcade/battle/ui_interact(mob/user)
- . = ..()
- var/dat = "Close"
- dat += "[enemy_name]
[temp]
Game Over
Forever."
- if(!settlers.len)
- dat += "
Your entire crew died, and your ship joins the fleet of ghost-ships littering the galaxy."
- else
- if(food <= 0)
- dat += "
You ran out of food and starved."
- if(obj_flags & EMAGGED)
- user.nutrition = 0 //yeah you pretty hongry
- to_chat(user, "Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.")
- if(fuel <= 0)
- dat += "
You ran out of fuel, and drift, slowly, into a star."
- if(obj_flags & EMAGGED)
- var/mob/living/M = user
- M.adjust_fire_stacks(5)
- M.IgniteMob() //flew into a star, so you're on fire
- to_chat(user, "You feel an immense wave of heat emanate from the arcade machine. Your skin bursts into flames.")
-
- if(obj_flags & EMAGGED)
- to_chat(user, "You're never going to make it to Orion...")
- user.death()
- obj_flags &= ~EMAGGED //removes the emagged status after you lose
- gameStatus = ORION_STATUS_START
- name = "The Orion Trail"
- desc = "Learn how our ancestors got to Orion, and have fun in the process!"
-
- dat += ""
- else if(event)
- dat = eventdat
- else if(gameStatus == ORION_STATUS_NORMAL)
- var/title = stops[turns]
- var/subtext = stopblurbs[turns]
- dat = "[title]
Crew:
"
- dat += english_list(settlers)
- dat += "
Food: [food] | Fuel: [fuel]"
- dat += "
Engine Parts: [engine] | Hull Panels: [hull] | Electronics: [electronics]"
- if(turns == 7)
- dat += ""
- else
- dat += ""
- dat += ""
- dat += ""
- else
- dat = "The Orion Trail
Experience the journey of your ancestors!
"
- dat += "[event]
They have stolen [sfood] Food and [sfuel] Fuel."
- else if(prob(10))
- var/deadname = remove_crewmember()
- eventdat += "
[deadname] tried to fight back, but was killed."
- else
- eventdat += "
Fortunately, you fended them off without any trouble."
- eventdat += ""
- eventdat += ""
- canContinueEvent = 1
-
- if(ORION_TRAIL_FLUX)
- eventdat += "This region of space is highly turbulent.
If we go slowly we may avoid more damage, but if we keep our speed we won't waste supplies."
- eventdat += "
What will you do?"
- eventdat += ""
- eventdat += ""
-
- if(ORION_TRAIL_ILLNESS)
- eventdat += "A deadly illness has been contracted!"
- var/deadname = remove_crewmember()
- eventdat += "
[deadname] was killed by the disease."
- eventdat += ""
- eventdat += ""
- canContinueEvent = 1
-
- if(ORION_TRAIL_BREAKDOWN)
- eventdat += "Oh no! The engine has broken down!"
- eventdat += "
You can repair it with an engine part, or you can make repairs for 3 days."
- if(engine >= 1)
- eventdat += ""
- else
- eventdat += ""
- eventdat += ""
-
- if(ORION_TRAIL_MALFUNCTION)
- eventdat += "The ship's systems are malfunctioning!"
- eventdat += "
You can replace the broken electronics with spares, or you can spend 3 days troubleshooting the AI."
- if(electronics >= 1)
- eventdat += ""
- else
- eventdat += ""
- eventdat += ""
-
- if(ORION_TRAIL_COLLISION)
- eventdat += "Something hit us! Looks like there's some hull damage."
- if(prob(25))
- var/sfood = rand(5,15)
- var/sfuel = rand(5,15)
- food -= sfood
- fuel -= sfuel
- eventdat += "
[sfood] Food and [sfuel] Fuel was vented out into space."
- if(prob(10))
- var/deadname = remove_crewmember()
- eventdat += "
[deadname] was killed by rapid depressurization."
- eventdat += "
You can repair the damage with hull plates, or you can spend the next 3 days welding scrap together."
- if(hull >= 1)
- eventdat += ""
- else
- eventdat += ""
- eventdat += ""
-
- if(ORION_TRAIL_BLACKHOLE)
- eventdat += "You were swept away into the black hole."
- eventdat += ""
- eventdat += ""
- settlers = list()
-
- if(ORION_TRAIL_LING)
- eventdat += "Strange reports warn of changelings infiltrating crews on trips to Orion..."
- if(settlers.len <= 2)
- eventdat += "
Your crew's chance of reaching Orion is so slim the changelings likely avoided your ship..."
- eventdat += ""
- eventdat += ""
- if(prob(10)) // "likely", I didn't say it was guaranteed!
- lings_aboard = min(++lings_aboard,2)
- else
- if(lings_aboard) //less likely to stack lings
- if(prob(20))
- lings_aboard = min(++lings_aboard,2)
- else if(prob(70))
- lings_aboard = min(++lings_aboard,2)
-
- eventdat += ""
- eventdat += ""
- eventdat += ""
- canContinueEvent = 1
-
- if(ORION_TRAIL_LING_ATTACK)
- if(lings_aboard <= 0) //shouldn't trigger, but hey.
- eventdat += "Haha, fooled you, there are no changelings on board!"
- eventdat += "
(You should report this to a coder :S)"
- else
- var/ling1 = remove_crewmember()
- var/ling2 = ""
- if(lings_aboard >= 2)
- ling2 = remove_crewmember()
-
- eventdat += "Changelings among your crew suddenly burst from hiding and attack!"
- if(ling2)
- eventdat += "
[ling1] and [ling2]'s arms twist and contort into grotesque blades!"
- else
- eventdat += "
[ling1]'s arm twists and contorts into a grotesque blade!"
-
- var/chance2attack = alive*20
- if(prob(chance2attack))
- var/chancetokill = 30*lings_aboard-(5*alive) //eg: 30*2-(10) = 50%, 2 lings, 2 crew is 50% chance
- if(prob(chancetokill))
- var/deadguy = remove_crewmember()
- var/murder_text = pick("The changeling[ling2 ? "s" : ""] bring[ling2 ? "" : "s"] down [deadguy] and disembowel[ling2 ? "" : "s"] them in a spray of gore!", \
- "[ling2 ? pick(ling1, ling2) : ling1] corners [deadguy] and impales them through the stomach!", \
- "[ling2 ? pick(ling1, ling2) : ling1] decapitates [deadguy] in a single cleaving arc!")
- eventdat += "
[murder_text]"
- else
- eventdat += "
You valiantly fight off the changeling[ling2 ? "s":""]!"
- if(ling2)
- food += 30
- lings_aboard = max(0,lings_aboard-2)
- else
- food += 15
- lings_aboard = max(0,--lings_aboard)
- eventdat += "
Well, it's perfectly good food...\
-
You cut the changeling[ling2 ? "s" : ""] into meat, gaining [ling2 ? "30" : "15"] Food!"
- else
- eventdat += "
[pick("Sensing unfavorable odds", "After a failed attack", "Suddenly breaking nerve")], \
- the changeling[ling2 ? "s":""] vanish[ling2 ? "" : "es"] into space through the airlocks! You're safe... for now."
- if(ling2)
- lings_aboard = max(0,lings_aboard-2)
- else
- lings_aboard = max(0,--lings_aboard)
-
- eventdat += ""
- eventdat += ""
- canContinueEvent = 1
-
-
- if(ORION_TRAIL_SPACEPORT)
- gameStatus = ORION_STATUS_MARKET
- if(spaceport_raided)
- eventdat += "The spaceport is on high alert! You've been barred from docking by the local authorities after your failed raid."
- if(last_spaceport_action)
- eventdat += "
Last Spaceport Action: [last_spaceport_action]"
- eventdat += ""
- eventdat += ""
- else
- eventdat += "Your jump into the sector yields a spaceport - a lucky find!"
- eventdat += "
This spaceport is home to travellers who failed to reach Orion, but managed to find a different home..."
- eventdat += "
Trading terms: FU = Fuel, FO = Food"
- if(last_spaceport_action)
- eventdat += "
Last action: [last_spaceport_action]"
- eventdat += "Crew:
"
- eventdat += english_list(settlers)
- eventdat += "
Food: [food] | Fuel: [fuel]"
- eventdat += "
Engine Parts: [engine] | Hull Panels: [hull] | Electronics: [electronics]"
-
-
- //If your crew is pathetic you can get freebies (provided you haven't already gotten one from this port)
- if(!spaceport_freebie && (fuel < 20 || food < 20))
- spaceport_freebie++
- var/FU = 10
- var/FO = 10
- var/freecrew = 0
- if(prob(30))
- FU = 25
- FO = 25
-
- if(prob(10))
- add_crewmember()
- freecrew++
-
- eventdat += "
The traders of the spaceport take pity on you, and generously give you some free supplies! (+[FU]FU, +[FO]FO)"
- if(freecrew)
- eventdat += "
You also gain a new crewmember!"
-
- fuel += FU
- food += FO
-
- //CREW INTERACTIONS
- eventdat += "
| [MINESWEEPERIMG(flag)] | " + if(0) + if(game_status != MINESWEEPER_GAME_PLAYING) + web += "[MINESWEEPERIMG(mine)] | " + else + web += "[MINESWEEPERIMG(hidden)] | " //Make unique hrefs for every square + if(1 to 9) + if(game_status != MINESWEEPER_GAME_PLAYING) + web += "[MINESWEEPERIMG(hidden)] | " + else + web += "[MINESWEEPERIMG(hidden)] | " //Make unique hrefs for every square + if(10) + web += "[MINESWEEPERIMG(minehit)] | " + if(11) + web += "[MINESWEEPERIMG(empty)] | " + if(12) + web += "[MINESWEEPERIMG(1)] | " + if(13) + web += "[MINESWEEPERIMG(2)] | " + if(14) + web += "[MINESWEEPERIMG(3)] | " + if(15) + web += "[MINESWEEPERIMG(4)] | " + if(16) + web += "[MINESWEEPERIMG(5)] | " + if(17) + web += "[MINESWEEPERIMG(6)] | " + if(18) + web += "[MINESWEEPERIMG(7)] | " + if(19) + web += "[MINESWEEPERIMG(8)] | " + web += "" + web += "
Crew Management:
" + + //Buy crew + if(food >= 10 && fuel >= 10) + eventdat += "Hire a New Crewmember (-10FU, -10FO)
" + else + eventdat += "You cannot afford a new crewmember.
" + + //Sell crew + if(settlers.len > 1) + eventdat += "Sell Crew for Fuel and Food (+7FU, +7FO)
" + else + eventdat += "You have no other crew to sell.
" + + //BUY/SELL STUFF + eventdat += "Spare Parts:
" + + //Engine parts + if(fuel > 5) + eventdat += "" + else + eventdat += "You cannot afford engine parts." + + //Hull plates + if(fuel > 5) + eventdat += "
" + else + eventdat += "You cannot afford hull plates." + + //Electronics + if(fuel > 5) + eventdat += "
" + else + eventdat += "You cannot afford spare electronics." + + //Trade + if(fuel > 5) + eventdat += "
Trade Fuel for Food (-5FU,+5FO)
" + else + eventdat += "You don't have 5FU to trade.
5) + eventdat += "Trade Food for Fuel (+5FU,-5FO)
" + else + eventdat += "You don't have 5FO to trade.
!! Raid Spaceport !!" + + eventdat += "" + + +//Add Random/Specific crewmember +/obj/machinery/computer/arcade/orion_trail/proc/add_crewmember(var/specific = "") + var/newcrew = "" + if(specific) + newcrew = specific + else + if(prob(50)) + newcrew = pick(GLOB.first_names_male) + else + newcrew = pick(GLOB.first_names_female) + if(newcrew) + settlers += newcrew + alive++ + return newcrew + + +//Remove Random/Specific crewmember +/obj/machinery/computer/arcade/orion_trail/proc/remove_crewmember(var/specific = "", var/dont_remove = "") + var/list/safe2remove = settlers + var/removed = "" + if(dont_remove) + safe2remove -= dont_remove + if(specific && specific != dont_remove) + safe2remove = list(specific) + else + removed = pick(safe2remove) + + if(removed) + if(lings_aboard && prob(40*lings_aboard)) //if there are 2 lings you're twice as likely to get one, obviously + lings_aboard = max(0,--lings_aboard) + settlers -= removed + alive-- + return removed + + +/obj/machinery/computer/arcade/orion_trail/proc/win(mob/user) + gameStatus = ORION_STATUS_START + say("Congratulations, you made it to Orion!") + if(obj_flags & EMAGGED) + new /obj/item/orion_ship(loc) + message_admins("[ADMIN_LOOKUPFLW(usr)] made it to Orion on an emagged machine and got an explosive toy ship.") + log_game("[key_name(usr)] made it to Orion on an emagged machine and got an explosive toy ship.") + else + prizevend(user) + obj_flags &= ~EMAGGED + name = "The Orion Trail" + desc = "Learn how our ancestors got to Orion, and have fun in the process!" + +/obj/machinery/computer/arcade/orion_trail/emag_act(mob/user) + if(obj_flags & EMAGGED) + return + to_chat(user, "You override the cheat code menu and skip to Cheat #[rand(1, 50)]: Realism Mode.") + name = "The Orion Trail: Realism Edition" + desc = "Learn how our ancestors got to Orion, and try not to die in the process!" + newgame() + obj_flags |= EMAGGED + +/mob/living/simple_animal/hostile/syndicate/ranged/smg/orion + name = "spaceport security" + desc = "Premier corporate security forces for all spaceports found along the Orion Trail." + faction = list("orion") + loot = list() + del_on_death = TRUE + +/obj/item/orion_ship + name = "model settler ship" + desc = "A model spaceship, it looks like those used back in the day when travelling to Orion! It even has a miniature FX-293 reactor, which was renowned for its instability and tendency to explode..." + icon = 'icons/obj/toy.dmi' + icon_state = "ship" + w_class = WEIGHT_CLASS_SMALL + var/active = 0 //if the ship is on + +/obj/item/orion_ship/examine(mob/user) + ..() + if(!(in_range(user, src))) + return + if(!active) + to_chat(user, "There's a little switch on the bottom. It's flipped down.") + else + to_chat(user, "There's a little switch on the bottom. It's flipped up.") + +/obj/item/orion_ship/attack_self(mob/user) //Minibomb-level explosion. Should probably be more because of how hard it is to survive the machine! Also, just over a 5-second fuse + if(active) + return + + message_admins("[ADMIN_LOOKUPFLW(usr)] primed an explosive Orion ship for detonation at [AREACOORD(usr)].") + log_game("[key_name(usr)] primed an explosive Orion ship for detonation at [AREACOORD(usr)].") + + to_chat(user, "You flip the switch on the underside of [src].") + active = 1 + visible_message("[src] softly beeps and whirs to life!") + playsound(loc, 'sound/machines/defib_SaftyOn.ogg', 25, 1) + say("This is ship ID #[rand(1,1000)] to Orion Port Authority. We're coming in for landing, over.") + sleep(20) + visible_message("[src] begins to vibrate...") + say("Uh, Port? Having some issues with our reactor, could you check it out? Over.") + sleep(30) + say("Oh, God! Code Eight! CODE EIGHT! IT'S GONNA BL-") + playsound(loc, 'sound/machines/buzz-sigh.ogg', 25, 1) + sleep(3.6) + visible_message("[src] explodes!") + explosion(loc, 2,4,8, flame_range = 16) + qdel(src) + +#undef ORION_TRAIL_WINTURN +#undef ORION_TRAIL_RAIDERS +#undef ORION_TRAIL_FLUX +#undef ORION_TRAIL_ILLNESS +#undef ORION_TRAIL_BREAKDOWN +#undef ORION_TRAIL_LING +#undef ORION_TRAIL_LING_ATTACK +#undef ORION_TRAIL_MALFUNCTION +#undef ORION_TRAIL_COLLISION +#undef ORION_TRAIL_SPACEPORT +#undef ORION_TRAIL_BLACKHOLE + +#undef ORION_STATUS_START +#undef ORION_STATUS_NORMAL +#undef ORION_STATUS_GAMEOVER +#undef ORION_STATUS_MARKET diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index 94f5e63afb..cb3cbf2aa6 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -80,9 +80,21 @@ /obj/machinery/computer/atmos_alert/update_icon() ..() + cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + var/overlay_state = icon_screen if(stat & (NOPOWER|BROKEN)) + add_overlay("[icon_keyboard]_off") return + add_overlay(icon_keyboard) if(priority_alarms.len) + overlay_state = "alert:2" add_overlay("alert:2") else if(minor_alarms.len) + overlay_state = "alert:1" add_overlay("alert:1") + else + overlay_state = "alert:0" + add_overlay("alert:0") + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm index baa6fa577e..6576f51e46 100644 --- a/code/game/machinery/computer/atmos_control.dm +++ b/code/game/machinery/computer/atmos_control.dm @@ -59,8 +59,8 @@ var/total_moles = air_sample.total_moles() if(total_moles) for(var/gas_id in air_sample.gases) - var/gas_name = air_sample.gases[gas_id][GAS_META][META_GAS_NAME] - signal.data["gases"][gas_name] = air_sample.gases[gas_id][MOLES] / total_moles * 100 + var/gas_name = GLOB.meta_gas_names[gas_id] + signal.data["gases"][gas_name] = air_sample.gases[gas_id] / total_moles * 100 radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 00a5c8941d..39d5c3d56f 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -450,7 +450,7 @@ scantemp = "Subject's brain is not responding to scanning stimuli." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) return - if((mob_occupant.has_trait(TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) + if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) scantemp = "Subject no longer contains the fundamental materials required to create a living clone." playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) return diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm index 43f5b96fbd..752765baa1 100755 --- a/code/game/machinery/computer/communications.dm +++ b/code/game/machinery/computer/communications.dm @@ -173,14 +173,15 @@ var/obj/machinery/shuttle_manipulator/M = locate() in GLOB.machines if(M) SSshuttle.shuttle_purchased = TRUE - M.unload_preview() - M.load_template(S) - M.existing_shuttle = SSshuttle.emergency - M.action_load(S) SSshuttle.points -= 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.") else diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm index 09cbb68083..c11f7d9edc 100644 --- a/code/game/machinery/computer/crew.dm +++ b/code/game/machinery/computer/crew.dm @@ -31,7 +31,6 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) var/list/jobs = new/list() jobs["Captain"] = 00 - jobs["Head of Personnel"] = 50 jobs["Head of Security"] = 10 jobs["Warden"] = 11 jobs["Security Officer"] = 12 @@ -47,9 +46,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) jobs["Chief Engineer"] = 40 jobs["Station Engineer"] = 41 jobs["Atmospheric Technician"] = 42 - jobs["Quartermaster"] = 51 - jobs["Shaft Miner"] = 52 - jobs["Cargo Technician"] = 53 + jobs["Quartermaster"] = 50 + jobs["Shaft Miner"] = 51 + jobs["Cargo Technician"] = 52 + jobs["Head of Personnel"] = 60 jobs["Bartender"] = 61 jobs["Cook"] = 62 jobs["Botanist"] = 63 @@ -103,7 +103,9 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) if(data_by_z["[z]"] && last_update["[z]"] && world.time <= last_update["[z]"] + SENSORS_UPDATE_PERIOD) return data_by_z["[z]"] - var/list/results = list() + var/list/results_damaged = list() + var/list/results_undamaged = list() + var/obj/item/clothing/under/U var/obj/item/card/id/I var/turf/pos @@ -114,6 +116,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) var/toxdam var/burndam var/brutedam + var/totaldam var/area var/pos_x var/pos_y @@ -157,11 +160,13 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) toxdam = round(H.getToxLoss(),1) burndam = round(H.getFireLoss(),1) brutedam = round(H.getBruteLoss(),1) + totaldam = oxydam + toxdam + burndam + brutedam else oxydam = null toxdam = null burndam = null brutedam = null + totaldam = 0 if (nanite_sensors || U.sensor_mode >= SENSOR_COORDS) if (!pos) @@ -174,16 +179,26 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new) pos_x = null pos_y = null - results[++results.len] = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null)) + var/total_list = list("name" = name, "assignment" = assignment, "ijob" = ijob, "life_status" = life_status, "oxydam" = oxydam, "toxdam" = toxdam, "burndam" = burndam, "brutedam" = brutedam, "totaldam" = totaldam, "area" = area, "pos_x" = pos_x, "pos_y" = pos_y, "can_track" = H.can_track(null)) - data_by_z["[z]"] = sortTim(results,/proc/sensor_compare) + if(totaldam) + results_damaged[++results_damaged.len] = total_list + else + results_undamaged[++results_undamaged.len] = total_list + + var/list/returning = sortTim(results_damaged,/proc/damage_compare) + sortTim(results_undamaged,/proc/ijob_compare) + + data_by_z["[z]"] = returning last_update["[z]"] = world.time - return results + return returning -/proc/sensor_compare(list/a,list/b) +/proc/ijob_compare(list/a,list/b) return a["ijob"] - b["ijob"] +/proc/damage_compare(list/a,list/b) + return b["totaldam"] - a["totaldam"] + /datum/crewmonitor/ui_act(action,params) var/mob/living/silicon/ai/AI = usr if(!istype(AI)) diff --git a/code/game/machinery/computer/dna_console.dm b/code/game/machinery/computer/dna_console.dm index 2980c741be..9d49574317 100644 --- a/code/game/machinery/computer/dna_console.dm +++ b/code/game/machinery/computer/dna_console.dm @@ -76,7 +76,7 @@ if(connected && connected.is_operational()) if(connected.occupant) //set occupant_status message viable_occupant = connected.occupant - if(viable_occupant.has_dna() && !viable_occupant.has_trait(TRAIT_RADIMMUNE) && !viable_occupant.has_trait(TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification + if(viable_occupant.has_dna() && !HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification occupant_status += "[viable_occupant.name] => " switch(viable_occupant.stat) if(CONSCIOUS) @@ -523,7 +523,7 @@ var/mob/living/carbon/viable_occupant = null if(connected) viable_occupant = connected.occupant - if(!istype(viable_occupant) || !viable_occupant.dna || viable_occupant.has_trait(TRAIT_RADIMMUNE) || viable_occupant.has_trait(TRAIT_NOCLONE)) + if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE)) viable_occupant = null return viable_occupant diff --git a/code/game/machinery/computer/station_alert.dm b/code/game/machinery/computer/station_alert.dm index 6769244335..36ba4b0c94 100644 --- a/code/game/machinery/computer/station_alert.dm +++ b/code/game/machinery/computer/station_alert.dm @@ -76,12 +76,23 @@ /obj/machinery/computer/station_alert/update_icon() ..() + cut_overlays() + SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays) + var/overlay_state = icon_screen if(stat & (NOPOWER|BROKEN)) + add_overlay("[icon_keyboard]_off") return + add_overlay(icon_keyboard) var/active_alarms = FALSE for(var/cat in alarms) var/list/L = alarms[cat] if(L.len) active_alarms = TRUE if(active_alarms) + overlay_state = "alert:2" add_overlay("alert:2") + else + overlay_state = "alert:0" + add_overlay("alert:0") + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir) + SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128) diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm index 7beb32eebb..1c6d713437 100644 --- a/code/game/machinery/dance_machine.dm +++ b/code/game/machinery/dance_machine.dm @@ -214,11 +214,11 @@ sparkles += S switch(i) if(1 to 8) - S.orbit(src, 30, TRUE, 60, 36, TRUE, FALSE) + S.orbit(src, 30, TRUE, 60, 36, TRUE) if(9 to 16) - S.orbit(src, 62, TRUE, 60, 36, TRUE, FALSE) + S.orbit(src, 62, TRUE, 60, 36, TRUE) if(17 to 24) - S.orbit(src, 95, TRUE, 60, 36, TRUE, FALSE) + S.orbit(src, 95, TRUE, 60, 36, TRUE) if(25) S.pixel_y = 7 S.forceMove(get_turf(src)) diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm index 7b7c8a3411..4210435f33 100644 --- a/code/game/machinery/defibrillator_mount.dm +++ b/code/game/machinery/defibrillator_mount.dm @@ -69,7 +69,7 @@ if(defib) to_chat(user, "There's already a defibrillator in [src]!") return - if(I.item_flags & NODROP || !user.transferItemToLoc(I, src)) + if(HAS_TRAIT(I, TRAIT_NODROP) || !user.transferItemToLoc(I, src)) to_chat(user, "[I] is stuck to your hand!") return user.visible_message("[user] hooks up [I] to [src]!", \ diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index 90a6b07733..7895fb8c9f 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -99,7 +99,7 @@ var/mob/living/mob_occupant = get_mob_or_brainmob(occupant) if(istype(mob_occupant)) if(locate_computer(/obj/machinery/computer/cloning)) - if(!mob_occupant.suiciding && !(mob_occupant.has_trait(TRAIT_NOCLONE)) && !mob_occupant.hellbound) + if(!mob_occupant.suiciding && !(HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && !mob_occupant.hellbound) mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src) // DNA manipulators cannot operate on severed heads or brains diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 0183fcecd4..1081cb5fa7 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -763,7 +763,7 @@ if(ishuman(user) && prob(40) && src.density) var/mob/living/carbon/human/H = user - if((H.has_trait(TRAIT_DUMB)) && Adjacent(user)) + if((HAS_TRAIT(H, TRAIT_DUMB)) && Adjacent(user)) playsound(src.loc, 'sound/effects/bang.ogg', 25, 1) if(!istype(H.head, /obj/item/clothing/head/helmet)) H.visible_message("[user] headbutts the airlock.", \ diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm index 45ac999a6a..e8364d2271 100644 --- a/code/game/machinery/exp_cloner.dm +++ b/code/game/machinery/exp_cloner.dm @@ -42,11 +42,11 @@ icon_state = "pod_1" //Get the clone body ready maim_clone(H) - H.add_trait(TRAIT_STABLEHEART, "cloning") - H.add_trait(TRAIT_EMOTEMUTE, "cloning") - H.add_trait(TRAIT_MUTE, "cloning") - H.add_trait(TRAIT_NOBREATH, "cloning") - H.add_trait(TRAIT_NOCRITDAMAGE, "cloning") + ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning") + ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning") + ADD_TRAIT(H, TRAIT_MUTE, "cloning") + ADD_TRAIT(H, TRAIT_NOBREATH, "cloning") + ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning") H.Unconscious(80) var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H) @@ -268,7 +268,7 @@ scantemp = "Unable to locate valid genetic data." playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0) return - if((mob_occupant.has_trait(TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) + if((HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && (src.scanner.scan_level < 2)) scantemp = "Subject no longer contains the fundamental materials required to create a living clone." playsound(src, 'sound/machines/terminal_alert.ogg', 50, 0) return diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index 1f40672e05..8be7becfdd 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -65,7 +65,7 @@ if(!isitem(A)) continue var/obj/item/I = A - if(!(I.item_flags & NODROP)) + if(!HAS_TRAIT(I, TRAIT_NODROP)) say("Subject may not have abiotic items on.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) return @@ -73,7 +73,7 @@ say("Subject is not organic.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) return - if(!allow_living && !(C.stat == DEAD || C.has_trait(TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive + if(!allow_living && !(C.stat == DEAD || HAS_TRAIT(C, TRAIT_FAKEDEATH))) //I mean, the machines scanners arent advanced enough to tell you're alive say("Subject is still alive.") playsound(src, 'sound/machines/buzz-sigh.ogg', 30, 1) return diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 7284b3c738..03c60be91c 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -81,12 +81,6 @@ to_chat(usr, "The drip beeps: Warning, incompatible creature!") return - var/mob/living/L - if(isliving(target)) - L = target - if(!L.can_inject(usr, 1)) - return - if(Adjacent(target) && usr.Adjacent(target)) if(beaker) usr.visible_message("[usr] attaches [src] to [target].", "You attach [src] to [target].") diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm index 8a0658fd0f..a3250fe1b0 100644 --- a/code/game/machinery/limbgrower.dm +++ b/code/game/machinery/limbgrower.dm @@ -10,7 +10,6 @@ icon = 'icons/obj/machines/limbgrower.dmi' icon_state = "limbgrower_idleoff" density = TRUE - container_type = OPENCONTAINER use_power = IDLE_POWER_USE idle_power_usage = 10 active_power_usage = 100 @@ -34,7 +33,7 @@ ) /obj/machinery/limbgrower/Initialize() - create_reagents(100) + create_reagents(100, OPENCONTAINER) stored_research = new /datum/techweb/specialized/autounlocking/limbgrower . = ..() diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 911bb76bda..b0204ddeb8 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -485,7 +485,7 @@ threatcount += 4 if(shoot_unloyal) - if (!perp.has_trait(TRAIT_MINDSHIELD)) + if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)) threatcount += 4 return threatcount diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index f2c216ca98..ad9a846bdc 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -323,7 +323,7 @@ GLOBAL_LIST_EMPTY(allConsoles) emergency = "Medical" if(radio_freq) Radio.set_frequency(radio_freq) - Radio.talk_into(src,"[emergency] emergency in [department]!!",radio_freq,get_spans(),get_default_language()) + Radio.talk_into(src,"[emergency] emergency in [department]!!",radio_freq) update_icon() addtimer(CALLBACK(src, .proc/clear_emergency), 3000) @@ -382,7 +382,7 @@ GLOBAL_LIST_EMPTY(allConsoles) screen = 6 if(radio_freq) - Radio.talk_into(src,"[alert]: [message]",radio_freq,get_spans(),get_default_language()) + Radio.talk_into(src, "[alert]: [message]", radio_freq) switch(priority) if(2) diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index b84db2ca8d..90166dacf0 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -51,6 +51,7 @@ /obj/machinery/suit_storage_unit/security suit_type = /obj/item/clothing/suit/space/hardsuit/security mask_type = /obj/item/clothing/mask/gas/sechailer + storage_type = /obj/item/tank/jetpack/oxygen/security /obj/machinery/suit_storage_unit/hos suit_type = /obj/item/clothing/suit/space/hardsuit/security/hos diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index 99baad11ae..ba08109427 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -257,8 +257,7 @@ /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Initialize() . = ..() - create_reagents(max_volume) - reagents.set_reacting(FALSE) + create_reagents(max_volume, NO_REACT) syringes = new known_reagents = list("epinephrine"="Epinephrine","charcoal"="Charcoal") processed_reagents = new @@ -274,7 +273,7 @@ /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/critfail() ..() if(reagents) - reagents.set_reacting(TRUE) + DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT) /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/can_attach(obj/mecha/medical/M) if(..()) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index 1a3886c3df..80c92c7922 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -421,14 +421,13 @@ if(!istype(T)) return var/datum/gas_mixture/GM = new - GM.add_gas(/datum/gas/plasma) if(prob(10)) - GM.gases[/datum/gas/plasma][MOLES] += 100 + GM.gases[/datum/gas/plasma] += 100 GM.temperature = 1500+T0C //should be enough to start a fire T.visible_message("[src] suddenly disgorges a cloud of heated plasma.") qdel(src) else - GM.gases[/datum/gas/plasma][MOLES] += 5 + GM.gases[/datum/gas/plasma] += 5 GM.temperature = istype(T) ? T.air.return_temperature() : T20C T.visible_message("[src] suddenly disgorges a cloud of plasma.") T.assume_air(GM) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index d8c0fbeeb3..2e5a13beb2 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -305,7 +305,7 @@ name = "\improper SRM-8 missile rack" desc = "A weapon for combat exosuits. Shoots light explosive missiles." icon_state = "mecha_missilerack" - projectile = /obj/item/projectile/bullet/srmrocket + projectile = /obj/item/projectile/bullet/a84mm_he fire_sound = 'sound/weapons/grenadelaunch.ogg' projectiles = 8 projectile_energy_cost = 1000 diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index d5de4a4898..fc0665f51e 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -237,9 +237,8 @@ cabin_air = new cabin_air.temperature = T20C cabin_air.volume = 200 - cabin_air.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen) - cabin_air.gases[/datum/gas/oxygen][MOLES] = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) - cabin_air.gases[/datum/gas/nitrogen][MOLES] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) + cabin_air.gases[/datum/gas/oxygen] = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) + cabin_air.gases[/datum/gas/nitrogen] = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature) return cabin_air /obj/mecha/proc/add_radio() @@ -446,13 +445,13 @@ var/mob/living/L = user if(!Adjacent(target)) if(selected && selected.is_ranged()) - if(L.has_trait(TRAIT_PACIFISM) && selected.harmful) + if(HAS_TRAIT(L, TRAIT_PACIFISM) && selected.harmful) to_chat(user, "You don't want to harm other living beings!") return if(selected.action(target,params)) selected.start_cooldown() else if(selected && selected.is_melee()) - if(isliving(target) && selected.harmful && L.has_trait(TRAIT_PACIFISM)) + if(isliving(target) && selected.harmful && HAS_TRAIT(L, TRAIT_PACIFISM)) to_chat(user, "You don't want to harm other living beings!") return if(selected.action(target,params)) @@ -538,7 +537,7 @@ var/oldloc = loc if(internal_damage & MECHA_INT_CONTROL_LOST) move_result = mechsteprand() - else if(dir != direction && !strafe) + else if(dir != direction && (!strafe || occupant.client.keys_held["Alt"])) move_result = mechturn(direction) else move_result = mechstep(direction) diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index 6d42c302e1..7b00e208cc 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -128,7 +128,7 @@ /datum/action/innate/mecha/strafe - name = "Toggle Strafing" + name = "Toggle Strafing. Disabled when Alt is held." button_icon_state = "strafe" /datum/action/innate/mecha/strafe/Activate() diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 07152b0310..d5aff99f32 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -72,7 +72,7 @@ ..() if(ishuman(O)) var/mob/living/carbon/human/H = O - if(H.shoes && blood_state && bloodiness && !H.has_trait(TRAIT_LIGHT_STEP)) + if(H.shoes && blood_state && bloodiness && !HAS_TRAIT(H, TRAIT_LIGHT_STEP)) var/obj/item/clothing/shoes/S = H.shoes var/add_blood = 0 if(bloodiness >= BLOOD_GAIN_PER_STEP) diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index f1a1655fb4..35f06c2768 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -60,7 +60,7 @@ /obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L) if(istype(L) && has_gravity(loc)) - playsound(loc, 'sound/effects/gib_step.ogg', L.has_trait(TRAIT_LIGHT_STEP) ? 20 : 50, 1) + playsound(loc, 'sound/effects/gib_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 20 : 50, 1) . = ..() /obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions) diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 55a162ad38..cc69b88cc4 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -219,7 +219,7 @@ name = "stabilized plasma" desc = "A puddle of stabilized plasma." icon_state = "flour" - color = "#C8A5DC" + color = "#9e0089" /obj/effect/decal/cleanable/insectguts name = "insect guts" diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 34263ef9a4..0a0348ae39 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -3,6 +3,7 @@ desc = "Graffiti. Damn kids." icon = 'icons/effects/crayondecal.dmi' icon_state = "rune1" + plane = GAME_PLANE //makes the graffiti visible over a wall. gender = NEUTER mergeable_decal = FALSE var/do_icon_rotate = TRUE diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm index 264715e2ac..10ee73915c 100644 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ b/code/game/objects/effects/effect_system/effects_foam.dm @@ -1,347 +1,347 @@ -// Foam -// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin. -#define ALUMINUM_FOAM 1 -#define IRON_FOAM 2 -#define RESIN_FOAM 3 - - -/obj/effect/particle_effect/foam - name = "foam" - icon_state = "foam" - opacity = 0 - anchored = TRUE - density = FALSE - layer = EDGED_TURF_LAYER - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - var/amount = 3 - animate_movement = 0 - var/metal = 0 - var/lifetime = 40 - var/reagent_divisor = 7 - var/static/list/blacklisted_turfs = typecacheof(list( - /turf/open/space/transit, - /turf/open/chasm, - /turf/open/lava)) - -/obj/effect/particle_effect/foam/firefighting - name = "firefighting foam" - lifetime = 20 //doesn't last as long as normal foam - amount = 0 //no spread - var/absorbed_plasma = 0 - -/obj/effect/particle_effect/foam/firefighting/MakeSlippery() - return - -/obj/effect/particle_effect/foam/firefighting/process() - ..() - - var/turf/open/T = get_turf(src) - var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) - if(hotspot && istype(T) && T.air) - qdel(hotspot) - var/datum/gas_mixture/G = T.air - var/plas_amt = min(30,G.gases[/datum/gas/plasma][MOLES]) //Absorb some plasma - G.gases[/datum/gas/plasma][MOLES] -= plas_amt - absorbed_plasma += plas_amt - if(G.temperature > T20C) - G.temperature = max(G.temperature/2,T20C) - G.garbage_collect() - T.air_update_turf() - -/obj/effect/particle_effect/foam/firefighting/kill_foam() - STOP_PROCESSING(SSfastprocess, src) - - if(absorbed_plasma) - var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src)) - if(!P) - P = new(loc) - P.reagents.add_reagent("stable_plasma", absorbed_plasma) - - flick("[icon_state]-disolve", src) - QDEL_IN(src, 5) - -/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L) - if(!istype(L)) - return - L.adjust_fire_stacks(-2) - L.ExtinguishMob() - -/obj/effect/particle_effect/foam/firefighting/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - -/obj/effect/particle_effect/foam/metal - name = "aluminium foam" - metal = ALUMINUM_FOAM - icon_state = "mfoam" - -/obj/effect/particle_effect/foam/metal/MakeSlippery() - return - -/obj/effect/particle_effect/foam/metal/smart - name = "smart foam" - -/obj/effect/particle_effect/foam/metal/iron - name = "iron foam" - metal = IRON_FOAM - -/obj/effect/particle_effect/foam/metal/resin - name = "resin foam" - metal = RESIN_FOAM - -/obj/effect/particle_effect/foam/long_life - lifetime = 150 - -/obj/effect/particle_effect/foam/Initialize() - . = ..() - MakeSlippery() - create_reagents(1000) //limited by the size of the reagent holder anyway. - START_PROCESSING(SSfastprocess, src) - playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) - -/obj/effect/particle_effect/foam/proc/MakeSlippery() - AddComponent(/datum/component/slippery, 100) - -/obj/effect/particle_effect/foam/Destroy() - STOP_PROCESSING(SSfastprocess, src) - return ..() - - -/obj/effect/particle_effect/foam/proc/kill_foam() - STOP_PROCESSING(SSfastprocess, src) - switch(metal) - if(ALUMINUM_FOAM) - new /obj/structure/foamedmetal(get_turf(src)) - if(IRON_FOAM) - new /obj/structure/foamedmetal/iron(get_turf(src)) - if(RESIN_FOAM) - new /obj/structure/foamedmetal/resin(get_turf(src)) - flick("[icon_state]-disolve", src) - QDEL_IN(src, 5) - -/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls - STOP_PROCESSING(SSfastprocess, src) - if(metal) - var/turf/T = get_turf(src) - if(isspaceturf(T)) //Block up any exposed space - T.PlaceOnTop(/turf/open/floor/plating/foam) - for(var/direction in GLOB.cardinals) - var/turf/cardinal_turf = get_step(T, direction) - if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! - new/obj/structure/foamedmetal(T) - break - flick("[icon_state]-disolve", src) - QDEL_IN(src, 5) - -/obj/effect/particle_effect/foam/process() - lifetime-- - if(lifetime < 1) - kill_foam() - return - - var/fraction = 1/initial(reagent_divisor) - for(var/obj/O in range(0,src)) - if(O.type == src.type) - continue - if(isturf(O.loc)) - var/turf/T = O.loc - if(T.intact && O.level == 1) //hidden under the floor - continue - if(lifetime % reagent_divisor) - reagents.reaction(O, VAPOR, fraction) - var/hit = 0 - for(var/mob/living/L in range(0,src)) - hit += foam_mob(L) - if(hit) - lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate. - var/T = get_turf(src) - if(lifetime % reagent_divisor) - reagents.reaction(T, VAPOR, fraction) - - if(--amount < 0) - return - spread_foam() - -/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L) - if(lifetime<1) - return 0 - if(!istype(L)) - return 0 - var/fraction = 1/initial(reagent_divisor) - if(lifetime % reagent_divisor) - reagents.reaction(L, VAPOR, fraction) - lifetime-- - return 1 - -/obj/effect/particle_effect/foam/proc/spread_foam() - var/turf/t_loc = get_turf(src) - for(var/turf/T in t_loc.GetAtmosAdjacentTurfs()) - var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam! - if(foundfoam) - continue - - if(is_type_in_typecache(T, blacklisted_turfs)) - continue - - for(var/mob/living/L in T) - foam_mob(L) - var/obj/effect/particle_effect/foam/F = new src.type(T) - F.amount = amount - reagents.copy_to(F, (reagents.total_volume)) - F.add_atom_colour(color, FIXED_COLOUR_PRIORITY) - F.metal = metal - - -/obj/effect/particle_effect/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated - kill_foam() - - -/obj/effect/particle_effect/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - return - - -/////////////////////////////////////////////// -//FOAM EFFECT DATUM -/datum/effect_system/foam_spread - var/amount = 10 // the size of the foam spread. - var/obj/chemholder - effect_type = /obj/effect/particle_effect/foam - var/metal = 0 - - -/datum/effect_system/foam_spread/metal - effect_type = /obj/effect/particle_effect/foam/metal - - -/datum/effect_system/foam_spread/metal/smart - effect_type = /obj/effect/particle_effect/foam/smart - - -/datum/effect_system/foam_spread/long - effect_type = /obj/effect/particle_effect/foam/long_life - -/datum/effect_system/foam_spread/New() - ..() - chemholder = new /obj() - var/datum/reagents/R = new/datum/reagents(1000) - chemholder.reagents = R - R.my_atom = chemholder - -/datum/effect_system/foam_spread/Destroy() - qdel(chemholder) - chemholder = null - return ..() - -/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null) - if(isturf(loca)) - location = loca - else - location = get_turf(loca) - - amount = round(sqrt(amt / 2), 1) - carry.copy_to(chemholder, carry.total_volume) - -/datum/effect_system/foam_spread/metal/set_up(amt=5, loca, datum/reagents/carry = null, metaltype) - ..() - metal = metaltype - -/datum/effect_system/foam_spread/start() - var/obj/effect/particle_effect/foam/F = new effect_type(location) - var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list) - chemholder.reagents.copy_to(F, chemholder.reagents.total_volume/amount) - F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY) - F.amount = amount - F.metal = metal - - -////////////////////////////////////////////////////////// -// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break -/obj/structure/foamedmetal - icon = 'icons/effects/effects.dmi' - icon_state = "metalfoam" - density = TRUE - opacity = 1 // changed in New() - anchored = TRUE - layer = EDGED_TURF_LAYER - resistance_flags = FIRE_PROOF | ACID_PROOF - name = "foamed metal" - desc = "A lightweight foamed metal wall." - gender = PLURAL - max_integrity = 20 - CanAtmosPass = ATMOS_PASS_DENSITY - -/obj/structure/foamedmetal/Initialize() - . = ..() - air_update_turf(1) - -/obj/structure/foamedmetal/Move() - var/turf/T = loc - . = ..() - move_update_air(T) - -/obj/structure/foamedmetal/attack_paw(mob/user) - return attack_hand(user) - -/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) - playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) - -/obj/structure/foamedmetal/attack_hand(mob/user) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - to_chat(user, "You hit [src] but bounce off it!") - playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) - -/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target) - return !density - -/obj/structure/foamedmetal/iron - max_integrity = 50 - icon_state = "ironfoam" - -//Atmos Backpack Resin, transparent, prevents atmos and filters the air -/obj/structure/foamedmetal/resin - name = "\improper ATMOS Resin" - desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature." - opacity = FALSE - icon_state = "atmos_resin" - alpha = 120 - max_integrity = 10 - -/obj/structure/foamedmetal/resin/Initialize() - . = ..() - if(isopenturf(loc)) - var/turf/open/O = loc - O.ClearWet() - if(O.air) - var/datum/gas_mixture/G = O.air - G.temperature = 293.15 - for(var/obj/effect/hotspot/H in O) - qdel(H) - var/list/G_gases = G.gases - for(var/I in G_gases) - if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen) - continue - G_gases[I][MOLES] = 0 - G.garbage_collect() - O.air_update_turf() - for(var/obj/machinery/atmospherics/components/unary/U in O) - if(!U.welded) - U.welded = TRUE - U.update_icon() - U.visible_message("[U] sealed shut!") - for(var/mob/living/L in O) - L.ExtinguishMob() - for(var/obj/item/Item in O) - Item.extinguish() - -/obj/structure/foamedmetal/resin/CanPass(atom/movable/mover, turf/target) - if(istype(mover) && (mover.pass_flags & PASSGLASS)) - return TRUE - . = ..() - -#undef ALUMINUM_FOAM -#undef IRON_FOAM -#undef RESIN_FOAM +// Foam +// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin. +#define ALUMINUM_FOAM 1 +#define IRON_FOAM 2 +#define RESIN_FOAM 3 + + +/obj/effect/particle_effect/foam + name = "foam" + icon_state = "foam" + opacity = 0 + anchored = TRUE + density = FALSE + layer = EDGED_TURF_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + var/amount = 3 + animate_movement = 0 + var/metal = 0 + var/lifetime = 40 + var/reagent_divisor = 7 + var/static/list/blacklisted_turfs = typecacheof(list( + /turf/open/space/transit, + /turf/open/chasm, + /turf/open/lava)) + +/obj/effect/particle_effect/foam/firefighting + name = "firefighting foam" + lifetime = 20 //doesn't last as long as normal foam + amount = 0 //no spread + var/absorbed_plasma = 0 + +/obj/effect/particle_effect/foam/firefighting/MakeSlippery() + return + +/obj/effect/particle_effect/foam/firefighting/process() + ..() + + var/turf/open/T = get_turf(src) + var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) + if(hotspot && istype(T) && T.air) + qdel(hotspot) + var/datum/gas_mixture/G = T.air + var/plas_amt = min(30,G.gases[/datum/gas/plasma]) //Absorb some plasma + G.gases[/datum/gas/plasma] -= plas_amt + absorbed_plasma += plas_amt + if(G.temperature > T20C) + G.temperature = max(G.temperature/2,T20C) + GAS_GARBAGE_COLLECT(G.gases) + T.air_update_turf() + +/obj/effect/particle_effect/foam/firefighting/kill_foam() + STOP_PROCESSING(SSfastprocess, src) + + if(absorbed_plasma) + var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src)) + if(!P) + P = new(loc) + P.reagents.add_reagent("stable_plasma", absorbed_plasma) + + flick("[icon_state]-disolve", src) + QDEL_IN(src, 5) + +/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L) + if(!istype(L)) + return + L.adjust_fire_stacks(-2) + L.ExtinguishMob() + +/obj/effect/particle_effect/foam/firefighting/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + +/obj/effect/particle_effect/foam/metal + name = "aluminium foam" + metal = ALUMINUM_FOAM + icon_state = "mfoam" + +/obj/effect/particle_effect/foam/metal/MakeSlippery() + return + +/obj/effect/particle_effect/foam/metal/smart + name = "smart foam" + +/obj/effect/particle_effect/foam/metal/iron + name = "iron foam" + metal = IRON_FOAM + +/obj/effect/particle_effect/foam/metal/resin + name = "resin foam" + metal = RESIN_FOAM + +/obj/effect/particle_effect/foam/long_life + lifetime = 150 + +/obj/effect/particle_effect/foam/Initialize() + . = ..() + MakeSlippery() + create_reagents(1000) //limited by the size of the reagent holder anyway. + START_PROCESSING(SSfastprocess, src) + playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3) + +/obj/effect/particle_effect/foam/proc/MakeSlippery() + AddComponent(/datum/component/slippery, 100) + +/obj/effect/particle_effect/foam/Destroy() + STOP_PROCESSING(SSfastprocess, src) + return ..() + + +/obj/effect/particle_effect/foam/proc/kill_foam() + STOP_PROCESSING(SSfastprocess, src) + switch(metal) + if(ALUMINUM_FOAM) + new /obj/structure/foamedmetal(get_turf(src)) + if(IRON_FOAM) + new /obj/structure/foamedmetal/iron(get_turf(src)) + if(RESIN_FOAM) + new /obj/structure/foamedmetal/resin(get_turf(src)) + flick("[icon_state]-disolve", src) + QDEL_IN(src, 5) + +/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls + STOP_PROCESSING(SSfastprocess, src) + if(metal) + var/turf/T = get_turf(src) + if(isspaceturf(T)) //Block up any exposed space + T.PlaceOnTop(/turf/open/floor/plating/foam) + for(var/direction in GLOB.cardinals) + var/turf/cardinal_turf = get_step(T, direction) + if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! + new/obj/structure/foamedmetal(T) + break + flick("[icon_state]-disolve", src) + QDEL_IN(src, 5) + +/obj/effect/particle_effect/foam/process() + lifetime-- + if(lifetime < 1) + kill_foam() + return + + var/fraction = 1/initial(reagent_divisor) + for(var/obj/O in range(0,src)) + if(O.type == src.type) + continue + if(isturf(O.loc)) + var/turf/T = O.loc + if(T.intact && O.level == 1) //hidden under the floor + continue + if(lifetime % reagent_divisor) + reagents.reaction(O, VAPOR, fraction) + var/hit = 0 + for(var/mob/living/L in range(0,src)) + hit += foam_mob(L) + if(hit) + lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate. + var/T = get_turf(src) + if(lifetime % reagent_divisor) + reagents.reaction(T, VAPOR, fraction) + + if(--amount < 0) + return + spread_foam() + +/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L) + if(lifetime<1) + return 0 + if(!istype(L)) + return 0 + var/fraction = 1/initial(reagent_divisor) + if(lifetime % reagent_divisor) + reagents.reaction(L, VAPOR, fraction) + lifetime-- + return 1 + +/obj/effect/particle_effect/foam/proc/spread_foam() + var/turf/t_loc = get_turf(src) + for(var/turf/T in t_loc.GetAtmosAdjacentTurfs()) + var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam! + if(foundfoam) + continue + + if(is_type_in_typecache(T, blacklisted_turfs)) + continue + + for(var/mob/living/L in T) + foam_mob(L) + var/obj/effect/particle_effect/foam/F = new src.type(T) + F.amount = amount + reagents.copy_to(F, (reagents.total_volume)) + F.add_atom_colour(color, FIXED_COLOUR_PRIORITY) + F.metal = metal + + +/obj/effect/particle_effect/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated + kill_foam() + + +/obj/effect/particle_effect/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) + return + + +/////////////////////////////////////////////// +//FOAM EFFECT DATUM +/datum/effect_system/foam_spread + var/amount = 10 // the size of the foam spread. + var/obj/chemholder + effect_type = /obj/effect/particle_effect/foam + var/metal = 0 + + +/datum/effect_system/foam_spread/metal + effect_type = /obj/effect/particle_effect/foam/metal + + +/datum/effect_system/foam_spread/metal/smart + effect_type = /obj/effect/particle_effect/foam/smart + + +/datum/effect_system/foam_spread/long + effect_type = /obj/effect/particle_effect/foam/long_life + +/datum/effect_system/foam_spread/New() + ..() + chemholder = new /obj() + var/datum/reagents/R = new/datum/reagents(1000) + chemholder.reagents = R + R.my_atom = chemholder + +/datum/effect_system/foam_spread/Destroy() + qdel(chemholder) + chemholder = null + return ..() + +/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null) + if(isturf(loca)) + location = loca + else + location = get_turf(loca) + + amount = round(sqrt(amt / 2), 1) + carry.copy_to(chemholder, carry.total_volume) + +/datum/effect_system/foam_spread/metal/set_up(amt=5, loca, datum/reagents/carry = null, metaltype) + ..() + metal = metaltype + +/datum/effect_system/foam_spread/start() + var/obj/effect/particle_effect/foam/F = new effect_type(location) + var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list) + chemholder.reagents.copy_to(F, chemholder.reagents.total_volume/amount) + F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY) + F.amount = amount + F.metal = metal + + +////////////////////////////////////////////////////////// +// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break +/obj/structure/foamedmetal + icon = 'icons/effects/effects.dmi' + icon_state = "metalfoam" + density = TRUE + opacity = 1 // changed in New() + anchored = TRUE + layer = EDGED_TURF_LAYER + resistance_flags = FIRE_PROOF | ACID_PROOF + name = "foamed metal" + desc = "A lightweight foamed metal wall." + gender = PLURAL + max_integrity = 20 + CanAtmosPass = ATMOS_PASS_DENSITY + +/obj/structure/foamedmetal/Initialize() + . = ..() + air_update_turf(1) + +/obj/structure/foamedmetal/Move() + var/turf/T = loc + . = ..() + move_update_air(T) + +/obj/structure/foamedmetal/attack_paw(mob/user) + return attack_hand(user) + +/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) + playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) + +/obj/structure/foamedmetal/attack_hand(mob/user) + . = ..() + if(.) + return + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) + to_chat(user, "You hit [src] but bounce off it!") + playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1) + +/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target) + return !density + +/obj/structure/foamedmetal/iron + max_integrity = 50 + icon_state = "ironfoam" + +//Atmos Backpack Resin, transparent, prevents atmos and filters the air +/obj/structure/foamedmetal/resin + name = "\improper ATMOS Resin" + desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature." + opacity = FALSE + icon_state = "atmos_resin" + alpha = 120 + max_integrity = 10 + +/obj/structure/foamedmetal/resin/Initialize() + . = ..() + if(isopenturf(loc)) + var/turf/open/O = loc + O.ClearWet() + if(O.air) + var/datum/gas_mixture/G = O.air + G.temperature = 293.15 + for(var/obj/effect/hotspot/H in O) + qdel(H) + var/list/G_gases = G.gases + for(var/I in G_gases) + if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen) + continue + G_gases[I] = 0 + GAS_GARBAGE_COLLECT(G.gases) + O.air_update_turf() + for(var/obj/machinery/atmospherics/components/unary/U in O) + if(!U.welded) + U.welded = TRUE + U.update_icon() + U.visible_message("[U] sealed shut!") + for(var/mob/living/L in O) + L.ExtinguishMob() + for(var/obj/item/Item in O) + Item.extinguish() + +/obj/structure/foamedmetal/resin/CanPass(atom/movable/mover, turf/target) + if(istype(mover) && (mover.pass_flags & PASSGLASS)) + return TRUE + . = ..() + +#undef ALUMINUM_FOAM +#undef IRON_FOAM +#undef RESIN_FOAM diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm index e8e833890b..79deac475b 100644 --- a/code/game/objects/effects/effect_system/effects_smoke.dm +++ b/code/game/objects/effects/effect_system/effects_smoke.dm @@ -1,329 +1,328 @@ -///////////////////////////////////////////// -//// SMOKE SYSTEMS -///////////////////////////////////////////// - -/obj/effect/particle_effect/smoke - name = "smoke" - icon = 'icons/effects/96x96.dmi' - icon_state = "smoke" - pixel_x = -32 - pixel_y = -32 - opacity = 0 - layer = FLY_LAYER - anchored = TRUE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - animate_movement = 0 - var/amount = 4 - var/lifetime = 5 - var/opaque = 1 //whether the smoke can block the view when in enough amount - - -/obj/effect/particle_effect/smoke/proc/fade_out(frames = 16) - if(alpha == 0) //Handle already transparent case - return - if(frames == 0) - frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame". - var/step = alpha / frames - for(var/i = 0, i < frames, i++) - alpha -= step - if(alpha < 160) - set_opacity(0) //if we were blocking view, we aren't now because we're fading out - stoplag() - -/obj/effect/particle_effect/smoke/Initialize() - . = ..() - create_reagents(500) - START_PROCESSING(SSobj, src) - - -/obj/effect/particle_effect/smoke/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/particle_effect/smoke/proc/kill_smoke() - STOP_PROCESSING(SSobj, src) - INVOKE_ASYNC(src, .proc/fade_out) - QDEL_IN(src, 10) - -/obj/effect/particle_effect/smoke/process() - lifetime-- - if(lifetime < 1) - kill_smoke() - return 0 - for(var/mob/living/L in range(0,src)) - smoke_mob(L) - return 1 - -/obj/effect/particle_effect/smoke/proc/smoke_mob(mob/living/carbon/C) - if(!istype(C)) - return 0 - if(lifetime<1) - return 0 - if(C.internal != null || C.has_smoke_protection()) - return 0 - if(C.smoke_delay) - return 0 - C.smoke_delay++ - addtimer(CALLBACK(src, .proc/remove_smoke_delay, C), 10) - return 1 - -/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C) - if(C) - C.smoke_delay = 0 - -/obj/effect/particle_effect/smoke/proc/spread_smoke() - var/turf/t_loc = get_turf(src) - if(!t_loc) - return - var/list/newsmokes = list() - for(var/turf/T in t_loc.GetAtmosAdjacentTurfs()) - var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke! - if(foundsmoke) - continue - for(var/mob/living/L in T) - smoke_mob(L) - var/obj/effect/particle_effect/smoke/S = new type(T) - reagents.copy_to(S, reagents.total_volume) - S.setDir(pick(GLOB.cardinals)) - S.amount = amount-1 - S.add_atom_colour(color, FIXED_COLOUR_PRIORITY) - S.lifetime = lifetime - if(S.amount>0) - if(opaque) - S.set_opacity(TRUE) - newsmokes.Add(S) - - if(newsmokes.len) - spawn(1) //the smoke spreads rapidly but not instantly - for(var/obj/effect/particle_effect/smoke/SM in newsmokes) - SM.spread_smoke() - - -/datum/effect_system/smoke_spread - var/amount = 10 - effect_type = /obj/effect/particle_effect/smoke - -/datum/effect_system/smoke_spread/set_up(radius = 5, loca) - if(isturf(loca)) - location = loca - else - location = get_turf(loca) - amount = radius - -/datum/effect_system/smoke_spread/start() - if(holder) - location = get_turf(holder) - var/obj/effect/particle_effect/smoke/S = new effect_type(location) - S.amount = amount - if(S.amount) - S.spread_smoke() - - -///////////////////////////////////////////// -// Bad smoke -///////////////////////////////////////////// - -/obj/effect/particle_effect/smoke/bad - lifetime = 8 - -/obj/effect/particle_effect/smoke/bad/smoke_mob(mob/living/carbon/M) - if(..()) - M.drop_all_held_items() - M.adjustOxyLoss(1) - M.emote("cough") - return 1 - -/obj/effect/particle_effect/smoke/bad/CanPass(atom/movable/mover, turf/target) - if(istype(mover, /obj/item/projectile/beam)) - var/obj/item/projectile/beam/B = mover - B.damage = (B.damage/2) - return 1 - - - -/datum/effect_system/smoke_spread/bad - effect_type = /obj/effect/particle_effect/smoke/bad - -///////////////////////////////////////////// -// Nanofrost smoke -///////////////////////////////////////////// - -/obj/effect/particle_effect/smoke/freezing - name = "nanofrost smoke" - color = "#B2FFFF" - opaque = 0 - -/datum/effect_system/smoke_spread/freezing - effect_type = /obj/effect/particle_effect/smoke/freezing - var/blast = 0 - var/temperature = 2 - var/weldvents = TRUE - var/distcheck = TRUE - -/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A) - if(isopenturf(A)) - var/turf/open/T = A - if(T.air) - var/datum/gas_mixture/G = T.air - if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air - G.temperature = temperature - T.air_update_turf() - for(var/obj/effect/hotspot/H in T) - qdel(H) - var/list/G_gases = G.gases - if(G_gases[/datum/gas/plasma]) - G.assert_gas(/datum/gas/nitrogen) - G_gases[/datum/gas/nitrogen][MOLES] += (G_gases[/datum/gas/plasma][MOLES]) - G_gases[/datum/gas/plasma][MOLES] = 0 - G.garbage_collect() - if (weldvents) - for(var/obj/machinery/atmospherics/components/unary/U in T) - if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber. - U.welded = TRUE - U.update_icon() - U.visible_message("[U] was frozen shut!") - for(var/mob/living/L in T) - L.ExtinguishMob() - for(var/obj/item/Item in T) - Item.extinguish() - -/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blast_radius = 0) - ..() - blast = blast_radius - -/datum/effect_system/smoke_spread/freezing/start() - if(blast) - for(var/turf/T in RANGE_TURFS(blast, location)) - Chilled(T) - ..() - -/datum/effect_system/smoke_spread/freezing/decon - temperature = 293.15 - distcheck = FALSE - weldvents = FALSE - - -///////////////////////////////////////////// -// Sleep smoke -///////////////////////////////////////////// - -/obj/effect/particle_effect/smoke/sleeping - color = "#9C3636" - lifetime = 10 - -/obj/effect/particle_effect/smoke/sleeping/smoke_mob(mob/living/carbon/M) - if(..()) - M.Sleeping(200) - M.emote("cough") - return 1 - -/datum/effect_system/smoke_spread/sleeping - effect_type = /obj/effect/particle_effect/smoke/sleeping - -///////////////////////////////////////////// -// Chem smoke -///////////////////////////////////////////// - -/obj/effect/particle_effect/smoke/chem - lifetime = 10 - - -/obj/effect/particle_effect/smoke/chem/process() - if(..()) - var/turf/T = get_turf(src) - var/fraction = 1/initial(lifetime) - for(var/atom/movable/AM in T) - if(AM.type == src.type) - continue - if(T.intact && AM.level == 1) //hidden under the floor - continue - reagents.reaction(AM, TOUCH, fraction) - - reagents.reaction(T, TOUCH, fraction) - return 1 - -/obj/effect/particle_effect/smoke/chem/smoke_mob(mob/living/carbon/M) - if(lifetime<1) - return 0 - if(!istype(M)) - return 0 - var/mob/living/carbon/C = M - if(C.internal != null || C.has_smoke_protection()) - return 0 - var/fraction = 1/initial(lifetime) - reagents.copy_to(C, fraction*reagents.total_volume) - reagents.reaction(M, INGEST, fraction) - return 1 - - - -/datum/effect_system/smoke_spread/chem - var/obj/chemholder - effect_type = /obj/effect/particle_effect/smoke/chem - -/datum/effect_system/smoke_spread/chem/New() - ..() - chemholder = new /obj() - var/datum/reagents/R = new/datum/reagents(500) - chemholder.reagents = R - R.my_atom = chemholder - -/datum/effect_system/smoke_spread/chem/Destroy() - qdel(chemholder) - chemholder = null - return ..() - -/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = FALSE) - if(isturf(loca)) - location = loca - else - location = get_turf(loca) - amount = radius - carry.copy_to(chemholder, carry.total_volume) - - if(!silent) - var/contained = "" - for(var/reagent in carry.reagent_list) - contained += " [reagent] " - if(contained) - contained = "\[[contained]\]" - - var/where = "[AREACOORD(location)]" - if(carry.my_atom.fingerprintslast) - var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) - var/more = "" - if(M) - more = "[ADMIN_LOOKUPFLW(M)] " - message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].") - log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].") - else - message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.") - log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") - - -/datum/effect_system/smoke_spread/chem/start() - var/mixcolor = mix_color_from_reagents(chemholder.reagents.reagent_list) - if(holder) - location = get_turf(holder) - var/obj/effect/particle_effect/smoke/chem/S = new effect_type(location) - - if(chemholder.reagents.total_volume > 1) // can't split 1 very well - chemholder.reagents.copy_to(S, chemholder.reagents.total_volume) - - if(mixcolor) - S.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with - S.amount = amount - if(S.amount) - S.spread_smoke() //calling process right now so the smoke immediately attacks mobs. - - -///////////////////////////////////////////// -// Transparent smoke -///////////////////////////////////////////// - -//Same as the base type, but the smoke produced is not opaque -/datum/effect_system/smoke_spread/transparent - effect_type = /obj/effect/particle_effect/smoke/transparent - -/obj/effect/particle_effect/smoke/transparent - opaque = FALSE +///////////////////////////////////////////// +//// SMOKE SYSTEMS +///////////////////////////////////////////// + +/obj/effect/particle_effect/smoke + name = "smoke" + icon = 'icons/effects/96x96.dmi' + icon_state = "smoke" + pixel_x = -32 + pixel_y = -32 + opacity = 0 + layer = FLY_LAYER + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + animate_movement = 0 + var/amount = 4 + var/lifetime = 5 + var/opaque = 1 //whether the smoke can block the view when in enough amount + + +/obj/effect/particle_effect/smoke/proc/fade_out(frames = 16) + if(alpha == 0) //Handle already transparent case + return + if(frames == 0) + frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame". + var/step = alpha / frames + for(var/i = 0, i < frames, i++) + alpha -= step + if(alpha < 160) + set_opacity(0) //if we were blocking view, we aren't now because we're fading out + stoplag() + +/obj/effect/particle_effect/smoke/Initialize() + . = ..() + create_reagents(500) + START_PROCESSING(SSobj, src) + + +/obj/effect/particle_effect/smoke/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/effect/particle_effect/smoke/proc/kill_smoke() + STOP_PROCESSING(SSobj, src) + INVOKE_ASYNC(src, .proc/fade_out) + QDEL_IN(src, 10) + +/obj/effect/particle_effect/smoke/process() + lifetime-- + if(lifetime < 1) + kill_smoke() + return 0 + for(var/mob/living/L in range(0,src)) + smoke_mob(L) + return 1 + +/obj/effect/particle_effect/smoke/proc/smoke_mob(mob/living/carbon/C) + if(!istype(C)) + return 0 + if(lifetime<1) + return 0 + if(C.internal != null || C.has_smoke_protection()) + return 0 + if(C.smoke_delay) + return 0 + C.smoke_delay++ + addtimer(CALLBACK(src, .proc/remove_smoke_delay, C), 10) + return 1 + +/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C) + if(C) + C.smoke_delay = 0 + +/obj/effect/particle_effect/smoke/proc/spread_smoke() + var/turf/t_loc = get_turf(src) + if(!t_loc) + return + var/list/newsmokes = list() + for(var/turf/T in t_loc.GetAtmosAdjacentTurfs()) + var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke! + if(foundsmoke) + continue + for(var/mob/living/L in T) + smoke_mob(L) + var/obj/effect/particle_effect/smoke/S = new type(T) + reagents.copy_to(S, reagents.total_volume) + S.setDir(pick(GLOB.cardinals)) + S.amount = amount-1 + S.add_atom_colour(color, FIXED_COLOUR_PRIORITY) + S.lifetime = lifetime + if(S.amount>0) + if(opaque) + S.set_opacity(TRUE) + newsmokes.Add(S) + + if(newsmokes.len) + spawn(1) //the smoke spreads rapidly but not instantly + for(var/obj/effect/particle_effect/smoke/SM in newsmokes) + SM.spread_smoke() + + +/datum/effect_system/smoke_spread + var/amount = 10 + effect_type = /obj/effect/particle_effect/smoke + +/datum/effect_system/smoke_spread/set_up(radius = 5, loca) + if(isturf(loca)) + location = loca + else + location = get_turf(loca) + amount = radius + +/datum/effect_system/smoke_spread/start() + if(holder) + location = get_turf(holder) + var/obj/effect/particle_effect/smoke/S = new effect_type(location) + S.amount = amount + if(S.amount) + S.spread_smoke() + + +///////////////////////////////////////////// +// Bad smoke +///////////////////////////////////////////// + +/obj/effect/particle_effect/smoke/bad + lifetime = 8 + +/obj/effect/particle_effect/smoke/bad/smoke_mob(mob/living/carbon/M) + if(..()) + M.drop_all_held_items() + M.adjustOxyLoss(1) + M.emote("cough") + return 1 + +/obj/effect/particle_effect/smoke/bad/CanPass(atom/movable/mover, turf/target) + if(istype(mover, /obj/item/projectile/beam)) + var/obj/item/projectile/beam/B = mover + B.damage = (B.damage/2) + return 1 + + + +/datum/effect_system/smoke_spread/bad + effect_type = /obj/effect/particle_effect/smoke/bad + +///////////////////////////////////////////// +// Nanofrost smoke +///////////////////////////////////////////// + +/obj/effect/particle_effect/smoke/freezing + name = "nanofrost smoke" + color = "#B2FFFF" + opaque = 0 + +/datum/effect_system/smoke_spread/freezing + effect_type = /obj/effect/particle_effect/smoke/freezing + var/blast = 0 + var/temperature = 2 + var/weldvents = TRUE + var/distcheck = TRUE + +/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A) + if(isopenturf(A)) + var/turf/open/T = A + if(T.air) + var/datum/gas_mixture/G = T.air + if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air + G.temperature = temperature + T.air_update_turf() + for(var/obj/effect/hotspot/H in T) + qdel(H) + var/list/G_gases = G.gases + if(G_gases[/datum/gas/plasma]) + G_gases[/datum/gas/nitrogen] += (G_gases[/datum/gas/plasma]) + G_gases[/datum/gas/plasma] = 0 + GAS_GARBAGE_COLLECT(G.gases) + if (weldvents) + for(var/obj/machinery/atmospherics/components/unary/U in T) + if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber. + U.welded = TRUE + U.update_icon() + U.visible_message("[U] was frozen shut!") + for(var/mob/living/L in T) + L.ExtinguishMob() + for(var/obj/item/Item in T) + Item.extinguish() + +/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blast_radius = 0) + ..() + blast = blast_radius + +/datum/effect_system/smoke_spread/freezing/start() + if(blast) + for(var/turf/T in RANGE_TURFS(blast, location)) + Chilled(T) + ..() + +/datum/effect_system/smoke_spread/freezing/decon + temperature = 293.15 + distcheck = FALSE + weldvents = FALSE + + +///////////////////////////////////////////// +// Sleep smoke +///////////////////////////////////////////// + +/obj/effect/particle_effect/smoke/sleeping + color = "#9C3636" + lifetime = 10 + +/obj/effect/particle_effect/smoke/sleeping/smoke_mob(mob/living/carbon/M) + if(..()) + M.Sleeping(200) + M.emote("cough") + return 1 + +/datum/effect_system/smoke_spread/sleeping + effect_type = /obj/effect/particle_effect/smoke/sleeping + +///////////////////////////////////////////// +// Chem smoke +///////////////////////////////////////////// + +/obj/effect/particle_effect/smoke/chem + lifetime = 10 + + +/obj/effect/particle_effect/smoke/chem/process() + if(..()) + var/turf/T = get_turf(src) + var/fraction = 1/initial(lifetime) + for(var/atom/movable/AM in T) + if(AM.type == src.type) + continue + if(T.intact && AM.level == 1) //hidden under the floor + continue + reagents.reaction(AM, TOUCH, fraction) + + reagents.reaction(T, TOUCH, fraction) + return 1 + +/obj/effect/particle_effect/smoke/chem/smoke_mob(mob/living/carbon/M) + if(lifetime<1) + return 0 + if(!istype(M)) + return 0 + var/mob/living/carbon/C = M + if(C.internal != null || C.has_smoke_protection()) + return 0 + var/fraction = 1/initial(lifetime) + reagents.copy_to(C, fraction*reagents.total_volume) + reagents.reaction(M, INGEST, fraction) + return 1 + + + +/datum/effect_system/smoke_spread/chem + var/obj/chemholder + effect_type = /obj/effect/particle_effect/smoke/chem + +/datum/effect_system/smoke_spread/chem/New() + ..() + chemholder = new /obj() + var/datum/reagents/R = new/datum/reagents(500) + chemholder.reagents = R + R.my_atom = chemholder + +/datum/effect_system/smoke_spread/chem/Destroy() + qdel(chemholder) + chemholder = null + return ..() + +/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = FALSE) + if(isturf(loca)) + location = loca + else + location = get_turf(loca) + amount = radius + carry.copy_to(chemholder, carry.total_volume) + + if(!silent) + var/contained = "" + for(var/reagent in carry.reagent_list) + contained += " [reagent] " + if(contained) + contained = "\[[contained]\]" + + var/where = "[AREACOORD(location)]" + if(carry.my_atom.fingerprintslast) + var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast) + var/more = "" + if(M) + more = "[ADMIN_LOOKUPFLW(M)] " + message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].") + log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].") + else + message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.") + log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.") + + +/datum/effect_system/smoke_spread/chem/start() + var/mixcolor = mix_color_from_reagents(chemholder.reagents.reagent_list) + if(holder) + location = get_turf(holder) + var/obj/effect/particle_effect/smoke/chem/S = new effect_type(location) + + if(chemholder.reagents.total_volume > 1) // can't split 1 very well + chemholder.reagents.copy_to(S, chemholder.reagents.total_volume) + + if(mixcolor) + S.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with + S.amount = amount + if(S.amount) + S.spread_smoke() //calling process right now so the smoke immediately attacks mobs. + + +///////////////////////////////////////////// +// Transparent smoke +///////////////////////////////////////////// + +//Same as the base type, but the smoke produced is not opaque +/datum/effect_system/smoke_spread/transparent + effect_type = /obj/effect/particle_effect/smoke/transparent + +/obj/effect/particle_effect/smoke/transparent + opaque = FALSE diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index 12a72685bb..32d91ee76a 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -131,7 +131,7 @@ var/obj/item/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc) victim.log_message("entered a blood frenzy", LOG_ATTACK) - chainsaw.item_flags |= NODROP + ADD_TRAIT(chainsaw, TRAIT_NODROP, CHAINSAW_FRENZY_TRAIT) victim.drop_all_held_items() victim.put_in_hands(chainsaw, forced = TRUE) chainsaw.attack_self(victim) @@ -170,7 +170,7 @@ if(!victim.client || !istype(victim)) return to_chat(victim, "You feel fast!") - victim.add_trait(TRAIT_GOTTAGOREALLYFAST, "yellow_orb") + ADD_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb") sleep(duration) - victim.remove_trait(TRAIT_GOTTAGOREALLYFAST, "yellow_orb") + REMOVE_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb") to_chat(victim, "You slow down.") diff --git a/code/game/objects/effects/spawners/bombspawner.dm b/code/game/objects/effects/spawners/bombspawner.dm index b1bb3e6b4d..65395d534a 100644 --- a/code/game/objects/effects/spawners/bombspawner.dm +++ b/code/game/objects/effects/spawners/bombspawner.dm @@ -1,6 +1,6 @@ #define CELSIUS_TO_KELVIN(T_K) ((T_K) + T0C) -#define OPTIMAL_TEMP_K_PLA_BURN_SCALE(PRESSURE_P,PRESSURE_O,TEMP_O) (((PRESSURE_P) * GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_SPECIFIC_HEAT]) / (((PRESSURE_P) * GLOB.meta_gas_info[/datum/gas/plasma][META_GAS_SPECIFIC_HEAT] + (PRESSURE_O) * GLOB.meta_gas_info[/datum/gas/oxygen][META_GAS_SPECIFIC_HEAT]) / PLASMA_UPPER_TEMPERATURE - (PRESSURE_O) * GLOB.meta_gas_info[/datum/gas/oxygen][META_GAS_SPECIFIC_HEAT] / CELSIUS_TO_KELVIN(TEMP_O))) +#define OPTIMAL_TEMP_K_PLA_BURN_SCALE(PRESSURE_P,PRESSURE_O,TEMP_O) (((PRESSURE_P) * GLOB.meta_gas_specific_heats[/datum/gas/plasma]) / (((PRESSURE_P) * GLOB.meta_gas_specific_heats[/datum/gas/plasma] + (PRESSURE_O) * GLOB.meta_gas_specific_heats[/datum/gas/oxygen]) / PLASMA_UPPER_TEMPERATURE - (PRESSURE_O) * GLOB.meta_gas_specific_heats[/datum/gas/oxygen] / CELSIUS_TO_KELVIN(TEMP_O))) #define OPTIMAL_TEMP_K_PLA_BURN_RATIO(PRESSURE_P,PRESSURE_O,TEMP_O) (CELSIUS_TO_KELVIN(TEMP_O) * PLASMA_OXYGEN_FULLBURN * (PRESSURE_P) / (PRESSURE_O)) /obj/effect/spawner/newbomb @@ -19,12 +19,10 @@ var/obj/item/tank/internals/plasma/PT = new(V) var/obj/item/tank/internals/oxygen/OT = new(V) - PT.air_contents.assert_gas(/datum/gas/plasma) - PT.air_contents.gases[/datum/gas/plasma][MOLES] = pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p)) + PT.air_contents.gases[/datum/gas/plasma] = pressure_p*PT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_p)) PT.air_contents.temperature = CELSIUS_TO_KELVIN(temp_p) - OT.air_contents.assert_gas(/datum/gas/oxygen) - OT.air_contents.gases[/datum/gas/oxygen][MOLES] = pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o)) + OT.air_contents.gases[/datum/gas/oxygen] = pressure_o*OT.volume/(R_IDEAL_GAS_EQUATION*CELSIUS_TO_KELVIN(temp_o)) OT.air_contents.temperature = CELSIUS_TO_KELVIN(temp_o) V.tank_one = PT diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 4a77274d23..bdb949a570 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -30,6 +30,18 @@ loot_spawned++ return INITIALIZE_HINT_QDEL +/obj/effect/spawner/lootdrop/bedsheet + icon = 'icons/obj/bedsheets.dmi' + icon_state = "random_bedsheet" + name = "random dorms bedsheet" + loot = list(/obj/item/bedsheet = 8, /obj/item/bedsheet/blue = 8, /obj/item/bedsheet/green = 8, + /obj/item/bedsheet/grey = 8, /obj/item/bedsheet/orange = 8, /obj/item/bedsheet/purple = 8, + /obj/item/bedsheet/red = 8, /obj/item/bedsheet/yellow = 8, /obj/item/bedsheet/brown = 8, + /obj/item/bedsheet/black = 8, /obj/item/bedsheet/patriot = 3, /obj/item/bedsheet/rainbow = 3, + /obj/item/bedsheet/ian = 3, /obj/item/bedsheet/runtime = 3, /obj/item/bedsheet/nanotrasen = 3, + /obj/item/bedsheet/pirate = 1, /obj/item/bedsheet/cosmos = 1, /obj/item/bedsheet/gondola = 1 + ) + /obj/effect/spawner/lootdrop/armory_contraband name = "armory contraband gun spawner" lootdoubles = FALSE @@ -108,6 +120,33 @@ loot = GLOB.maintenance_loot . = ..() +/obj/effect/spawner/lootdrop/glowstick + name = "random colored glowstick" + icon = 'icons/obj/lighting.dmi' + icon_state = "random_glowstick" + +/obj/effect/spawner/lootdrop/glowstick/Initialize() + loot = typesof(/obj/item/flashlight/glowstick) + . = ..() + + +/obj/effect/spawner/lootdrop/gloves + name = "random gloves" + desc = "These gloves are supposed to be a random color..." + icon = 'icons/obj/clothing/gloves.dmi' + icon_state = "random_gloves" + loot = list( + /obj/item/clothing/gloves/color/orange = 1, + /obj/item/clothing/gloves/color/red = 1, + /obj/item/clothing/gloves/color/blue = 1, + /obj/item/clothing/gloves/color/purple = 1, + /obj/item/clothing/gloves/color/green = 1, + /obj/item/clothing/gloves/color/grey = 1, + /obj/item/clothing/gloves/color/light_brown = 1, + /obj/item/clothing/gloves/color/brown = 1, + /obj/item/clothing/gloves/color/white = 1, + /obj/item/clothing/gloves/color/rainbow = 1) + /obj/effect/spawner/lootdrop/crate_spawner name = "lootcrate spawner" //USE PROMO CODE "SELLOUT" FOR 20% OFF! lootdoubles = FALSE @@ -214,6 +253,20 @@ /obj/item/aiModule/core/full/damaged ) +/obj/effect/spawner/lootdrop/mre + name = "random MRE" + icon = 'icons/obj/storage.dmi' + icon_state = "mre" + +/obj/effect/spawner/lootdrop/mre/Initialize() + for(var/A in subtypesof(/obj/item/storage/box/mre)) + var/obj/item/storage/box/mre/M = A + var/our_chance = initial(M.spawner_chance) + if(our_chance) + LAZYSET(loot, M, our_chance) + return ..() + + // Tech storage circuit board spawners // For these, make sure that lootcount equals the number of list items diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 9ff1b5cf01..384a1e4ee4 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -109,6 +109,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder! + /obj/item/Initialize() materials = typelist("materials", materials) @@ -229,9 +230,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) research_msg += "." to_chat(user, research_msg.Join()) -/obj/item/proc/speechModification(message) //for message modding by mask slot. - return message - /obj/item/interact(mob/user) add_fingerprint(user) ui_interact(user) @@ -256,7 +254,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) can_handle_hot = TRUE else if(C.gloves && (C.gloves.max_heat_protection_temperature > 360)) can_handle_hot = TRUE - else if(C.has_trait(TRAIT_RESISTHEAT) || C.has_trait(TRAIT_RESISTHEATHANDS)) + else if(HAS_TRAIT(C, TRAIT_RESISTHEAT) || HAS_TRAIT(C, TRAIT_RESISTHEATHANDS)) can_handle_hot = TRUE if(can_handle_hot) @@ -449,7 +447,11 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return 0 /obj/item/proc/eyestab(mob/living/carbon/M, mob/living/carbon/user) - + if(HAS_TRAIT(user, TRAIT_PACIFISM)) + to_chat(user, "You don't want to harm [M]!") + return + if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) + M = user var/is_human_victim = 0 var/obj/item/bodypart/affecting = M.get_bodypart(BODY_ZONE_HEAD) if(ishuman(M)) @@ -519,7 +521,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) M.adjust_blurriness(15) if(M.stat != DEAD) to_chat(M, "Your eyes start to bleed profusely!") - if(!(M.has_trait(TRAIT_BLIND) || M.has_trait(TRAIT_NEARSIGHT))) + if(!(HAS_TRAIT(M, TRAIT_BLIND) || HAS_TRAIT(M, TRAIT_NEARSIGHT))) to_chat(M, "You become nearsighted!") M.become_nearsighted(EYE_DAMAGE) if(prob(50)) @@ -642,11 +644,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) else . = "" - -//when an item modify our speech spans when in our active hand. Override this to modify speech spans. -/obj/item/proc/get_held_item_speechspans(mob/living/carbon/user) - return - /obj/item/hitby(atom/movable/AM) return @@ -681,7 +678,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) ..() /obj/item/proc/microwave_act(obj/machinery/microwave/M) - if(M && M.dirty < 100) + if(istype(M) && M.dirty < 100) M.dirty++ /obj/item/proc/on_mob_death(mob/living/L, gibbed) @@ -820,6 +817,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return ..() /obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) - if (item_flags & NODROP) + if (HAS_TRAIT(src, TRAIT_NODROP)) return return ..() diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm index 7881c277ff..8895bffd70 100644 --- a/code/game/objects/items/RCD.dm +++ b/code/game/objects/items/RCD.dm @@ -161,13 +161,18 @@ RLD user.visible_message("[user] sets the RCD to 'Wall' and points it down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide..") return (BRUTELOSS) -/obj/item/construction/rcd/verb/toggle_window_type() - set name = "Toggle Window Type" +/obj/item/construction/rcd/verb/toggle_window_type_verb() + set name = "RCD : Toggle Window Type" set category = "Object" - set src in usr // What does this do? + set src in view(1) + if(!usr.canUseTopic(src, BE_CLOSE)) + return + + toggle_window_type(usr) + +/obj/item/construction/rcd/proc/toggle_window_type(mob/user) var/window_type_name - if (window_type == /obj/structure/window/fulltile) window_type = /obj/structure/window/reinforced/fulltile window_type_name = "reinforced glass" @@ -175,17 +180,14 @@ RLD window_type = /obj/structure/window/fulltile window_type_name = "glass" - to_chat(usr, "You change \the [src]'s window mode to [window_type_name].") + to_chat(user, "You change \the [src]'s window mode to [window_type_name].") -/obj/item/construction/rcd/verb/change_airlock_access() - set name = "Change Airlock Access" - set category = "Object" - set src in usr +/obj/item/construction/rcd/verb/change_airlock_access(mob/user) - if (!ishuman(usr) && !usr.has_unlimited_silicon_privilege) - return ..(usr) + if (!ishuman(user) && !user.has_unlimited_silicon_privilege) + return - var/t1 = text("") + var/t1 = "" if(use_one_access) @@ -216,24 +218,23 @@ RLD t1 += "\n" - var/datum/browser/popup = new(usr, "airlock_electronics", "Access Control", 900, 500) + var/datum/browser/popup = new(user, "rcd_access", "Access Control", 900, 500) popup.set_content(t1) - popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state)) + popup.set_title_image(user.browse_rsc_icon(icon, icon_state)) popup.open() - onclose(usr, "airlock") + onclose(user, "rcd_access") /obj/item/construction/rcd/Topic(href, href_list) ..() if (usr.stat || usr.restrained()) return if (href_list["close"]) - usr << browse(null, "window=airlock") + usr << browse(null, "window=rcd_access") return if (href_list["access"]) toggle_access(href_list["access"]) - - change_airlock_access() + change_airlock_access(usr) /obj/item/construction/rcd/proc/toggle_access(acc) if (acc == "all") @@ -253,16 +254,77 @@ RLD if (!conf_access.len) conf_access = null -/obj/item/construction/rcd/verb/change_airlock_setting() - set name = "Change Airlock Setting" - set category = "Object" - set src in usr +/obj/item/construction/rcd/proc/get_airlock_image(airlock_type) + var/obj/machinery/door/airlock/proto = airlock_type + var/ic = initial(proto.icon) + var/mutable_appearance/MA = mutable_appearance(ic, "closed") + if(!initial(proto.glass)) + MA.overlays += "fill_closed" + //Not scaling these down to button size because they look horrible then, instead just bumping up radius. + return MA - var/airlockcat = input(usr, "Select whether the airlock is solid or glass.") in list("Solid", "Glass") +/obj/item/construction/rcd/proc/check_menu(mob/living/user) + if(!istype(user)) + return FALSE + if(user.incapacitated() || !user.Adjacent(src)) + return FALSE + return TRUE + +/obj/item/construction/rcd/proc/change_airlock_setting(mob/user) + if(!user) + return + + var/list/solid_or_glass_choices = list( + "Solid" = get_airlock_image(/obj/machinery/door/airlock), + "Glass" = get_airlock_image(/obj/machinery/door/airlock/glass) + ) + + var/list/solid_choices = list( + "Standard" = get_airlock_image(/obj/machinery/door/airlock), + "Public" = get_airlock_image(/obj/machinery/door/airlock/public), + "Engineering" = get_airlock_image(/obj/machinery/door/airlock/engineering), + "Atmospherics" = get_airlock_image(/obj/machinery/door/airlock/atmos), + "Security" = get_airlock_image(/obj/machinery/door/airlock/security), + "Command" = get_airlock_image(/obj/machinery/door/airlock/command), + "Medical" = get_airlock_image(/obj/machinery/door/airlock/medical), + "Research" = get_airlock_image(/obj/machinery/door/airlock/research), + "Freezer" = get_airlock_image(/obj/machinery/door/airlock/freezer), + "Science" = get_airlock_image(/obj/machinery/door/airlock/science), + "Virology" = get_airlock_image(/obj/machinery/door/airlock/virology), + "Mining" = get_airlock_image(/obj/machinery/door/airlock/mining), + "Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance), + "External" = get_airlock_image(/obj/machinery/door/airlock/external), + "External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external), + "Airtight Hatch" = get_airlock_image(/obj/machinery/door/airlock/hatch), + "Maintenance Hatch" = get_airlock_image(/obj/machinery/door/airlock/maintenance_hatch) + ) + + var/list/glass_choices = list( + "Standard" = get_airlock_image(/obj/machinery/door/airlock/glass), + "Public" = get_airlock_image(/obj/machinery/door/airlock/public/glass), + "Engineering" = get_airlock_image(/obj/machinery/door/airlock/engineering/glass), + "Atmospherics" = get_airlock_image(/obj/machinery/door/airlock/atmos/glass), + "Security" = get_airlock_image(/obj/machinery/door/airlock/security/glass), + "Command" = get_airlock_image(/obj/machinery/door/airlock/command/glass), + "Medical" = get_airlock_image(/obj/machinery/door/airlock/medical/glass), + "Research" = get_airlock_image(/obj/machinery/door/airlock/research/glass), + "Science" = get_airlock_image(/obj/machinery/door/airlock/science/glass), + "Virology" = get_airlock_image(/obj/machinery/door/airlock/virology/glass), + "Mining" = get_airlock_image(/obj/machinery/door/airlock/mining/glass), + "Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/glass), + "External" = get_airlock_image(/obj/machinery/door/airlock/external/glass), + "External Maintenance" = get_airlock_image(/obj/machinery/door/airlock/maintenance/external/glass) + ) + + var/airlockcat = show_radial_menu(user, src, solid_or_glass_choices, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE) + if(!check_menu(user)) + return switch(airlockcat) if("Solid") if(advanced_airlock_setting == 1) - var/airlockpaint = input(usr, "Select the type of the airlock.") in list("Standard", "Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Freezer", "Science", "Virology", "Mining", "Maintenance", "External", "External Maintenance", "Airtight Hatch", "Maintenance Hatch") + var/airlockpaint = show_radial_menu(user, src, solid_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE) + if(!check_menu(user)) + return switch(airlockpaint) if("Standard") airlock_type = /obj/machinery/door/airlock @@ -305,7 +367,9 @@ RLD if("Glass") if(advanced_airlock_setting == 1) - var/airlockpaint = input(usr, "Select the type of the airlock.") in list("Standard", "Public", "Engineering", "Atmospherics", "Security", "Command", "Medical", "Research", "Science", "Virology", "Mining", "Maintenance", "External", "External Maintenance") + var/airlockpaint = show_radial_menu(user, src , glass_choices, radius = 42, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE) + if(!check_menu(user)) + return switch(airlockpaint) if("Standard") airlock_type = /obj/machinery/door/airlock/glass @@ -350,14 +414,16 @@ RLD return FALSE if(do_after(user, rcd_results["delay"] * delay_mod, target = A)) if(checkResource(rcd_results["cost"], user)) + var/atom/cached = A if(A.rcd_act(user, src, rcd_results["mode"])) useResource(rcd_results["cost"], user) activate() - playsound(src.loc, 'sound/machines/click.ogg', 50, 1) + investigate_log("[user] used [src] on [cached] (now [A]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD) + playsound(src, 'sound/machines/click.ogg', 50, 1) return TRUE -/obj/item/construction/rcd/New() - ..() +/obj/item/construction/rcd/Initialize() + . = ..() GLOB.rcd_list += src /obj/item/construction/rcd/Destroy() @@ -366,19 +432,46 @@ RLD /obj/item/construction/rcd/attack_self(mob/user) ..() - switch(mode) - if(1) - mode = 2 - to_chat(user, "You change RCD's mode to 'Airlock'.") - if(2) - mode = 3 - to_chat(user, "You change RCD's mode to 'Deconstruct'.") - if(3) - mode = 4 - to_chat(user, "You change RCD's mode to 'Grilles & Windows'.") - if(4) - mode = 1 - to_chat(user, "You change RCD's mode to 'Floor & Walls'.") + var/list/choices = list( + "Airlock" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock"), + "Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"), + "Grilles & Windows" = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"), + "Floors & Walls" = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor") + ) + if(mode == RCD_AIRLOCK) + choices += list( + "Change Access" = image(icon = 'icons/mob/radial.dmi', icon_state = "access"), + "Change Airlock Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlocktype") + ) + else if(mode == RCD_WINDOWGRILLE) + choices += list( + "Change Window Type" = image(icon = 'icons/mob/radial.dmi', icon_state = "windowtype") + ) + var/choice = show_radial_menu(user,src,choices, custom_check = CALLBACK(src,.proc/check_menu,user)) + if(!check_menu(user)) + return + switch(choice) + if("Floors & Walls") + mode = RCD_FLOORWALL + if("Airlock") + mode = RCD_AIRLOCK + if("Deconstruct") + mode = RCD_DECONSTRUCT + if("Grilles & Windows") + mode = RCD_WINDOWGRILLE + if("Change Access") + change_airlock_access(user) + return + if("Change Airlock Type") + change_airlock_setting(user) + return + if("Change Window Type") + toggle_window_type(user) + return + else + return + playsound(src, 'sound/effects/pop.ogg', 50, 0) + to_chat(user, "You change RCD's mode to '[choice]'.") /obj/item/construction/rcd/proc/target_check(atom/A, mob/user) // only returns true for stuff the device can actually work with if((isturf(A) && A.density && mode==RCD_DECONSTRUCT) || (isturf(A) && !A.density) || (istype(A, /obj/machinery/door/airlock) && mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/grille) || (istype(A, /obj/structure/window) && mode==RCD_DECONSTRUCT) || istype(A, /obj/structure/girder)) @@ -531,6 +624,7 @@ RLD sheetmultiplier = 16 var/mode = LIGHT_MODE actions_types = list(/datum/action/item_action/pick_color) + ammo_sections = 5 var/wallcost = 10 var/floorcost = 15 @@ -551,7 +645,7 @@ RLD ..() /obj/item/construction/rld/update_icon() - icon_state = "rld-[round(matter/35)]" + icon_state = "rld-[round((matter/max_matter) * 5, 1)]" ..() diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm index bc1b128c69..cea8165e02 100644 --- a/code/game/objects/items/RCL.dm +++ b/code/game/objects/items/RCL.dm @@ -14,13 +14,14 @@ w_class = WEIGHT_CLASS_NORMAL var/max_amount = 90 var/active = FALSE - actions_types = list(/datum/action/item_action/rcl) + actions_types = list(/datum/action/item_action/rcl_col,/datum/action/item_action/rcl_gui) var/list/colors = list("red", "yellow", "green", "blue", "pink", "orange", "cyan", "white") var/current_color_index = 1 var/ghetto = FALSE lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' var/datum/component/mobhook + var/datum/radial_menu/persistent/wiring_gui_menu /obj/item/twohanded/rcl/attackby(obj/item/W, mob/user) if(istype(W, /obj/item/stack/cable_coil)) @@ -85,7 +86,8 @@ /obj/item/twohanded/rcl/Destroy() QDEL_NULL(loaded) last = null - setActive(FALSE, null) // setactive(FALSE) removes mobhook + QDEL_NULL(mobhook) + QDEL_NULL(wiring_gui_menu) return ..() /obj/item/twohanded/rcl/update_icon() @@ -115,20 +117,28 @@ if(loaded) QDEL_NULL(loaded) loaded = null + QDEL_NULL(wiring_gui_menu) unwield(user) - setActive(wielded, user) + active = wielded return TRUE return FALSE +/obj/item/twohanded/rcl/pickup(mob/user) + ..() + getMobhook(user) + + + /obj/item/twohanded/rcl/dropped(mob/wearer) ..() if(mobhook) - setActive(FALSE, mobhook.parent) + active = FALSE + QDEL_NULL(mobhook) last = null /obj/item/twohanded/rcl/attack_self(mob/user) ..() - setActive(wielded, user) + active = wielded if(!active) last = null else if(!last) @@ -137,17 +147,24 @@ last = C break -/obj/item/twohanded/rcl/proc/setActive(toggle, mob/user) - active = toggle - if (active && user) - if (mobhook && mobhook.parent != user) +obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook) + if(to_hook) + if(mobhook && mobhook.parent != to_hook) QDEL_NULL(mobhook) if (!mobhook) - mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger))) + mobhook = to_hook.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger))) else QDEL_NULL(mobhook) /obj/item/twohanded/rcl/proc/trigger(mob/user) + if(active) + layCable(user) + if(wiring_gui_menu) //update the wire options as you move + wiringGuiUpdate(user) + + +//previous contents of trigger(), lays cable each time the player moves +/obj/item/twohanded/rcl/proc/layCable(mob/user) if(!isturf(user.loc)) return if(is_empty(user, 0)) @@ -156,7 +173,7 @@ if(prob(2) && ghetto) //Give ghetto RCLs a 2% chance to jam, requiring it to be reactviated manually. to_chat(user, "[src]'s wires jam!") - setActive(FALSE, user) + active = FALSE return else if(last) @@ -179,6 +196,91 @@ is_empty(user) //If we've run out, display message update_icon() +//searches the current tile for a stub cable of the same colour +/obj/item/twohanded/rcl/proc/findLinkingCable(mob/user) + var/turf/T + if(!isturf(user.loc)) + return + + T = get_turf(user) + if(T.intact || !T.can_have_cabling()) + return + + for(var/obj/structure/cable/C in T) + if(!C) + continue + if(C.cable_color != GLOB.cable_colors[colors[current_color_index]]) + continue + if(C.d1 == 0) + return C + break + return + + +/obj/item/twohanded/rcl/proc/wiringGuiGenerateChoices(mob/user) + var/fromdir = 0 + var/obj/structure/cable/linkingCable = findLinkingCable(user) + if(linkingCable) + fromdir = linkingCable.d2 + + var/list/wiredirs = list("1","5","4","6","2","10","8","9") + for(var/icondir in wiredirs) + var/dirnum = text2num(icondir) + var/cablesuffix = "[min(fromdir,dirnum)]-[max(fromdir,dirnum)]" + if(fromdir == dirnum) //cables can't loop back on themselves + cablesuffix = "invalid" + var/image/img = image(icon = 'icons/mob/radial.dmi', icon_state = "cable_[cablesuffix]") + img.color = GLOB.cable_colors[colors[current_color_index]] + wiredirs[icondir] = img + return wiredirs + +/obj/item/twohanded/rcl/proc/showWiringGui(mob/user) + var/list/choices = wiringGuiGenerateChoices(user) + + wiring_gui_menu = show_radial_menu_persistent(user, src , choices, select_proc = CALLBACK(src, .proc/wiringGuiReact, user), radius = 42) + +/obj/item/twohanded/rcl/proc/wiringGuiUpdate(mob/user) + if(!wiring_gui_menu) + return + + wiring_gui_menu.entry_animation = FALSE //stop the open anim from playing each time we update + var/list/choices = wiringGuiGenerateChoices(user) + + wiring_gui_menu.change_choices(choices,FALSE) + + +//Callback used to respond to interactions with the wiring menu +/obj/item/twohanded/rcl/proc/wiringGuiReact(mob/living/user,choice) + if(!choice) //close on a null choice (the center button) + QDEL_NULL(wiring_gui_menu) + return + + choice = text2num(choice) + + if(!isturf(user.loc)) + return + if(is_empty(user, 0)) + to_chat(user, "\The [src] is empty!") + return + + var/turf/T = get_turf(user) + if(T.intact || !T.can_have_cabling()) + return + + loaded.item_color = colors[current_color_index] + + var/obj/structure/cable/linkingCable = findLinkingCable(user) + if(linkingCable) + if(choice != linkingCable.d2) + loaded.cable_join(linkingCable, user, FALSE, choice) + last = null + else + last = loaded.place_turf(get_turf(src), user, choice) + + is_empty(user) //If we've run out, display message + + wiringGuiUpdate(user) + /obj/item/twohanded/rcl/pre_loaded/Initialize() //Comes preloaded with cable, for testing stuff . = ..() @@ -192,12 +294,21 @@ update_icon() /obj/item/twohanded/rcl/ui_action_click(mob/user, action) - if(istype(action, /datum/action/item_action/rcl)) + if(istype(action, /datum/action/item_action/rcl_col)) current_color_index++; if (current_color_index > colors.len) current_color_index = 1 var/cwname = colors[current_color_index] to_chat(user, "Color changed to [cwname]!") + if(loaded) + loaded.item_color= colors[current_color_index] + if(wiring_gui_menu) + wiringGuiUpdate(user) + else if(istype(action, /datum/action/item_action/rcl_gui)) + if(wiring_gui_menu) //The menu is already open, close it + QDEL_NULL(wiring_gui_menu) + else //open the menu + showWiringGui(user) /obj/item/twohanded/rcl/ghetto actions_types = list() diff --git a/code/game/objects/items/RPD.dm b/code/game/objects/items/RPD.dm index 41ddc22106..6dbf0c2ad3 100644 --- a/code/game/objects/items/RPD.dm +++ b/code/game/objects/items/RPD.dm @@ -233,6 +233,10 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1) return(BRUTELOSS) +/obj/item/pipe_dispenser/ui_base_html(html) + var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes) + . = replacetext(html, "", assets.css_tag()) + /obj/item/pipe_dispenser/ui_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) @@ -331,7 +335,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list( //make sure what we're clicking is valid for the current category var/static/list/make_pipe_whitelist if(!make_pipe_whitelist) - make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe)) + make_pipe_whitelist = typecacheof(list(/obj/structure/lattice, /obj/structure/girder, /obj/item/pipe, /obj/structure/window, /obj/structure/grille)) var/can_make_pipe = (isturf(A) || is_type_in_typecache(A, make_pipe_whitelist)) . = FALSE diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm index ab877ff97a..699efaac2e 100644 --- a/code/game/objects/items/blueprints.dm +++ b/code/game/objects/items/blueprints.dm @@ -59,7 +59,7 @@ /obj/item/areaeditor/blueprints/attack_self(mob/user) . = ..() if(!legend) - var/area/A = get_area() + var/area/A = get_area(user) if(get_area_type() == AREA_STATION) . += "According to \the [src], you are now in \"[html_encode(A.name)]\".
" . += "" @@ -140,12 +140,10 @@ legend = FALSE -/obj/item/areaeditor/proc/get_area() - var/turf/T = get_turf(usr) - var/area/A = T.loc - return A -/obj/item/areaeditor/proc/get_area_type(area/A = get_area()) +/obj/item/areaeditor/proc/get_area_type(area/A) + if(!A) + A = get_area(usr) if(A.outdoors) return AREA_SPACE var/list/SPECIALS = list( @@ -183,7 +181,7 @@ return "" /obj/item/areaeditor/proc/edit_area() - var/area/A = get_area() + var/area/A = get_area(usr) var/prevname = "[A.name]" var/str = stripped_input(usr,"New area name:", "Area Creation", "", MAX_NAME_LEN) if(!str || !length(str) || str==prevname) //cancel diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm index a8f5894b7c..80fc0f43fd 100644 --- a/code/game/objects/items/body_egg.dm +++ b/code/game/objects/items/body_egg.dm @@ -16,7 +16,7 @@ /obj/item/organ/body_egg/Insert(var/mob/living/carbon/M, special = 0) ..() - owner.add_trait(TRAIT_XENO_HOST, TRAIT_GENERIC) + ADD_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC) START_PROCESSING(SSobj, src) owner.med_hud_set_status() INVOKE_ASYNC(src, .proc/AddInfectionImages, owner) @@ -24,7 +24,7 @@ /obj/item/organ/body_egg/Remove(var/mob/living/carbon/M, special = 0) STOP_PROCESSING(SSobj, src) if(owner) - owner.remove_trait(TRAIT_XENO_HOST, TRAIT_GENERIC) + REMOVE_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC) owner.med_hud_set_status() INVOKE_ASYNC(src, .proc/RemoveInfectionImages, owner) ..() diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index 30b1ca3399..96bbe759ca 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -105,7 +105,7 @@ if(isturf(A)) return - if(istype(A,/obj/item/storage/lockbox)) + if(istype(A,/obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod)) A.emag_act(user) uses = max(uses - 1, 0) if(!uses) diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm index f7c37715aa..5db5aa416e 100644 --- a/code/game/objects/items/chrono_eraser.dm +++ b/code/game/objects/items/chrono_eraser.dm @@ -48,7 +48,7 @@ icon_state = "chronogun" item_state = "chronogun" w_class = WEIGHT_CLASS_NORMAL - item_flags = NODROP | DROPDEL + item_flags = DROPDEL ammo_type = list(/obj/item/ammo_casing/energy/chrono_beam) can_charge = 0 fire_delay = 50 @@ -58,6 +58,7 @@ /obj/item/gun/energy/chrono_gun/Initialize() . = ..() + ADD_TRAIT(src, TRAIT_NODROP, CHRONO_GUN_TRAIT) if(istype(loc, /obj/item/chrono_eraser)) TED = loc else //admin must have spawned it @@ -150,8 +151,8 @@ gun = loc . = ..() - - + + /obj/effect/chrono_field @@ -248,9 +249,8 @@ /obj/effect/chrono_field/return_air() //we always have nominal air and temperature var/datum/gas_mixture/GM = new - GM.add_gases(/datum/gas/oxygen, /datum/gas/nitrogen) - GM.gases[/datum/gas/oxygen][MOLES] = MOLES_O2STANDARD - GM.gases[/datum/gas/nitrogen][MOLES] = MOLES_N2STANDARD + GM.gases[/datum/gas/oxygen] = MOLES_O2STANDARD + GM.gases[/datum/gas/nitrogen] = MOLES_N2STANDARD GM.temperature = T20C return GM diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 1ad7974fc1..000c52ae43 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -102,7 +102,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM icon_state = "cigoff" throw_speed = 0.5 item_state = "cigoff" - container_type = INJECTABLE w_class = WEIGHT_CLASS_TINY body_parts_covered = null grind_results = list() @@ -123,8 +122,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/cigarette/Initialize() . = ..() - create_reagents(chem_volume) - reagents.set_reacting(FALSE) // so it doesn't react until you light it + create_reagents(chem_volume, INJECTABLE | NO_REACT) // so it doesn't react until you light it if(list_reagents) reagents.add_reagent_list(list_reagents) if(starts_lit) @@ -184,7 +182,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM qdel(src) return // allowing reagents to react after being lit - reagents.set_reacting(TRUE) + DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT) reagents.handle_reactions() icon_state = icon_on item_state = icon_on @@ -325,7 +323,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM list_reagents = list("space_drugs" = 15, "lipolicide" = 35) /obj/item/clothing/mask/cigarette/rollie/mindbreaker - list_reagents = list("mindbreaker" = 35, "lipolicide" = 15) + list_reagents = list("mindbreaker" = 35, "lipolicide" = 15) /obj/item/cigbutt/roach name = "roach" @@ -709,9 +707,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = null w_class = WEIGHT_CLASS_TINY var/chem_volume = 100 - var/vapetime = 0 //this so it won't puff out clouds every tick - var/screw = 0 // kinky - var/super = 0 //for the fattest vapes dude. + var/vapetime = FALSE //this so it won't puff out clouds every tick + var/screw = FALSE // kinky + var/super = FALSE //for the fattest vapes dude. /obj/item/clothing/mask/vape/suicide_act(mob/user) user.visible_message("[user] is puffin hard on dat vape, [user.p_they()] trying to join the vape life on a whole notha plane!")//it doesn't give you cancer, it is cancer @@ -720,8 +718,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/vape/Initialize(mapload, param_color) . = ..() - create_reagents(chem_volume) - reagents.set_reacting(FALSE) // so it doesn't react until you light it + create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it reagents.add_reagent("nicotine", 50) if(!icon_state) if(!param_color) @@ -730,52 +727,48 @@ CIGARETTE PACKETS ARE IN FANCY.DM item_state = "[param_color]_vape" /obj/item/clothing/mask/vape/attackby(obj/item/O, mob/user, params) - if(O.is_drainable()) - if(reagents.total_volume < chem_volume) - if(O.reagents.total_volume > 0) - O.reagents.trans_to(src,25) - to_chat(user, "You add the contents of [O] to [src].") - else - to_chat(user, "[O] is empty!") - else - to_chat(user, "[src] can't hold anymore reagents!") - - if(istype(O, /obj/item/screwdriver)) + if(O.tool_behaviour == TOOL_SCREWDRIVER) if(!screw) - screw = 1 + screw = TRUE to_chat(user, "You open the cap on [src].") - if(super) + ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER) + if(obj_flags & EMAGGED) + add_overlay("vapeopen_high") + else if(super) add_overlay("vapeopen_med") else add_overlay("vapeopen_low") else - screw = 0 + screw = FALSE to_chat(user, "You close the cap on [src].") + DISABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER) cut_overlays() - if(istype(O, /obj/item/multitool)) + if(O.tool_behaviour == TOOL_MULTITOOL) if(screw && !(obj_flags & EMAGGED))//also kinky if(!super) cut_overlays() - super = 1 + super = TRUE to_chat(user, "You increase the voltage of [src].") add_overlay("vapeopen_med") else cut_overlays() - super = 0 + super = FALSE to_chat(user, "You decrease the voltage of [src].") add_overlay("vapeopen_low") if(screw && (obj_flags & EMAGGED)) to_chat(user, "[src] can't be modified!") + else + ..() /obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY. if(screw) if(!(obj_flags & EMAGGED)) cut_overlays() obj_flags |= EMAGGED - super = 0 + super = FALSE to_chat(user, "You maximize the voltage of [src].") add_overlay("vapeopen_high") var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect @@ -790,13 +783,12 @@ CIGARETTE PACKETS ARE IN FANCY.DM if(reagents.total_volume > 0) to_chat(user, "You empty [src] of all reagents.") reagents.clear_reagents() - return /obj/item/clothing/mask/vape/equipped(mob/user, slot) if(slot == SLOT_WEAR_MASK) if(!screw) to_chat(user, "You start puffing on the vape.") - reagents.set_reacting(TRUE) + DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT) START_PROCESSING(SSobj, src) else //it will not start if the vape is opened. to_chat(user, "You need to close the cap first!") @@ -804,7 +796,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/clothing/mask/vape/dropped(mob/user) var/mob/living/carbon/C = user if(C.get_item_by_slot(SLOT_WEAR_MASK) == src) - reagents.set_reacting(FALSE) + ENABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT) STOP_PROCESSING(SSobj, src) /obj/item/clothing/mask/vape/proc/hand_reagents()//had to rename to avoid duplicate error diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm index 26f00c730e..a1ee62e2eb 100644 --- a/code/game/objects/items/circuitboards/computer_circuitboards.dm +++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm @@ -123,6 +123,14 @@ name = "Orion Trail (Computer Board)" build_path = /obj/machinery/computer/arcade/orion_trail +/obj/item/circuitboard/computer/arcade/minesweeper + name = "Minesweeper (Computer Board)" + build_path = /obj/machinery/computer/arcade/minesweeper + +/obj/item/circuitboard/computer/arcade/amputation + name = "Mediborg's Amputation Adventure (Computer Board)" + build_path = /obj/machinery/computer/arcade/amputation + /obj/item/circuitboard/computer/turbine_control name = "Turbine control (Computer Board)" build_path = /obj/machinery/computer/turbine_computer diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 26f8a73cb3..99d6c874e8 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -68,6 +68,8 @@ var/pre_noise = FALSE var/post_noise = FALSE + var/datum/team/gang/gang //For marking territory. + var/gang_tag_delay = 30 //this is the delay for gang mode tag applications on anything that gang = true on. /obj/item/toy/crayon/suicide_act(mob/user) user.visible_message("[user] is jamming [src] up [user.p_their()] nose and into [user.p_their()] brain. It looks like [user.p_theyre()] trying to commit suicide!") @@ -252,7 +254,7 @@ cost = 0 if(ishuman(user)) var/mob/living/carbon/human/H = user - if (H.has_trait(TRAIT_TAGGER)) + if (HAS_TRAIT(H, TRAIT_TAGGER)) cost *= 0.5 var/charges_used = use_charges(user, cost) if(!charges_used) @@ -288,6 +290,13 @@ else if(drawing in numerals) temp = "number" + // If a gang member is using a gang spraycan, it'll behave differently + var/gang_mode = FALSE + if(gang && user.mind && user.mind.has_antag_datum(/datum/antagonist/gang)) //Heres a check. + gang_mode = TRUE // No more runtimes if a non-gang member sprays a gang can, it just works like normal cans. + // discontinue if the area isn't valid for tagging because gang "honour" + if(gang_mode && (!can_claim_for_gang(user, target))) + return var/graf_rot if(drawing in oriented) @@ -310,20 +319,22 @@ clicky = CLAMP(text2num(click_params["icon-y"]) - 16, -(world.icon_size/2), world.icon_size/2) if(!instant) - to_chat(user, "You start drawing a [temp] on the [target.name]...") + to_chat(user, "You start drawing a [temp] on the [target.name]...") if(pre_noise) audible_message("You hear spraying.") playsound(user.loc, 'sound/effects/spray.ogg', 5, 1, 5) - var/takes_time = !instant + var/takes_time = !instant //For order purposes, since I'm maximum bad. + if(gang_mode) + takes_time = TRUE var/wait_time = 50 if(paint_mode == PAINT_LARGE_HORIZONTAL) wait_time *= 3 - if(takes_time) - if(!do_after(user, 50, target = target)) + if(takes_time) //This is what deteremines the time it takes to spray a tag in gang mode. 50 is Default. + if(!do_after(user, gang_tag_delay, target = target)) //25 is a good number, but we have gang_tag_delay var now. return if(length(text_buffer)) @@ -332,26 +343,34 @@ var/list/turf/affected_turfs = list() + if(actually_paints) - switch(paint_mode) - if(PAINT_NORMAL) - var/obj/effect/decal/cleanable/crayon/C = new(target, paint_color, drawing, temp, graf_rot) - C.add_hiddenprint(user) - C.pixel_x = clickx - C.pixel_y = clicky - affected_turfs += target - if(PAINT_LARGE_HORIZONTAL) - var/turf/left = locate(target.x-1,target.y,target.z) - var/turf/right = locate(target.x+1,target.y,target.z) - if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces)) - var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON) + if(gang_mode) + // Double check it wasn't tagged in the meanwhile. + if(!can_claim_for_gang(user, target)) + return + tag_for_gang(user, target) + affected_turfs += target + else + switch(paint_mode) + if(PAINT_NORMAL) + var/obj/effect/decal/cleanable/crayon/C = new(target, paint_color, drawing, temp, graf_rot) C.add_hiddenprint(user) - affected_turfs += left - affected_turfs += right + C.pixel_x = clickx + C.pixel_y = clicky affected_turfs += target - else - to_chat(user, "There isn't enough space to paint!") - return + if(PAINT_LARGE_HORIZONTAL) + var/turf/left = locate(target.x-1,target.y,target.z) + var/turf/right = locate(target.x+1,target.y,target.z) + if(is_type_in_list(left, validSurfaces) && is_type_in_list(right, validSurfaces)) + var/obj/effect/decal/cleanable/crayon/C = new(left, paint_color, drawing, temp, graf_rot, PAINT_LARGE_HORIZONTAL_ICON) + C.add_hiddenprint(user) + affected_turfs += left + affected_turfs += right + affected_turfs += target + else + to_chat(user, "There isn't enough space to paint!") + return if(!instant) to_chat(user, "You finish drawing \the [temp].") @@ -373,6 +392,52 @@ reagents.trans_to(t, ., volume_multiplier) check_empty(user) + +//////////////Gang mode stuff///////////////// +/obj/item/toy/crayon/proc/can_claim_for_gang(mob/user, atom/target) + // Check area validity. + // Reject space, player-created areas, and non-station z-levels. + var/area/A = get_area(target) + if(!A || (!is_station_level(A.z)) || !A.valid_territory) + to_chat(user, "[A] is unsuitable for tagging.") + return FALSE + + var/spraying_over = FALSE + for(var/G in target) + var/obj/effect/decal/cleanable/crayon/gang/gangtag = G + if(istype(gangtag)) + var/datum/antagonist/gang/GA = user.mind.has_antag_datum(/datum/antagonist/gang) + if(gangtag.gang != GA.gang) + spraying_over = TRUE + break + + var/occupying_gang = territory_claimed(A, user) + if(occupying_gang && !spraying_over) + to_chat(user, "[A] has already been tagged by the [occupying_gang] gang! You must get rid of or spray over the old tag first!") + return FALSE + + // If you pass the gauntlet of checks, you're good to proceed + return TRUE + +/obj/item/toy/crayon/proc/territory_claimed(area/territory, mob/user) + for(var/datum/team/gang/G in GLOB.gangs) + if(territory.type in (G.territories|G.new_territories)) + . = G.name + break + +/obj/item/toy/crayon/proc/tag_for_gang(mob/user, atom/target) + //Delete any old markings on this tile, including other gang tags + for(var/obj/effect/decal/cleanable/crayon/old_marking in target) + qdel(old_marking) + + var/datum/antagonist/gang/G = user.mind.has_antag_datum(/datum/antagonist/gang) + var/area/territory = get_area(target) + + new /obj/effect/decal/cleanable/crayon/gang(target,G.gang,"graffiti",0,user) // Heres the gang tag. + to_chat(user, "You tagged [territory] for your gang!") +/////////////////Gang end//////////////////// + + /obj/item/toy/crayon/attack(mob/M, mob/user) if(edible && (M == user)) to_chat(user, "You take a bite of the [src.name]. Delicious!") @@ -524,6 +589,7 @@ is_capped = TRUE self_contained = FALSE // Don't disappear when they're empty can_change_colour = TRUE + gang = TRUE //Gang check is true for all things upon the honored hierarchy of spraycans, except those that are FALSE. validSurfaces = list(/turf/open/floor, /turf/closed/wall) reagent_contents = list("welding_fuel" = 1, "ethanol" = 1) @@ -669,6 +735,7 @@ icon_capped = "deathcan2_cap" icon_uncapped = "deathcan2" use_overlays = FALSE + gang = FALSE volume_multiplier = 25 charges = 100 @@ -683,6 +750,7 @@ icon_capped = "clowncan2_cap" icon_uncapped = "clowncan2" use_overlays = FALSE + gang = FALSE reagent_contents = list("lube" = 1, "banana" = 1) volume_multiplier = 5 @@ -695,6 +763,7 @@ icon_capped = "mimecan_cap" icon_uncapped = "mimecan" use_overlays = FALSE + gang = FALSE can_change_colour = FALSE paint_color = "#FFFFFF" //RGB @@ -703,6 +772,26 @@ post_noise = FALSE reagent_contents = list("nothing" = 1, "mutetoxin" = 1) +/obj/item/toy/crayon/spraycan/gang + charges = 20 // Charges back to 20, which is the default value for them. + gang = TRUE + gang_tag_delay = 15 //Its 50% faster than a regular spraycan, for tagging. After-all they did spend points/meet the boss. + + pre_noise = FALSE + post_noise = TRUE // Its even more stealthy just a tad. + +/obj/item/toy/crayon/spraycan/gang/Initialize(loc, datum/team/gang/G) + ..() + if(G) + gang = G + paint_color = G.color + update_icon() + +/obj/item/toy/crayon/spraycan/gang/examine(mob/user) + . = ..() + if(user.mind && user.mind.has_antag_datum(/datum/antagonist/gang) || isobserver(user)) + to_chat(user, "This spraycan has been specially modified with a stage 2 nozzle kit, making it faster.") + #undef RANDOM_GRAFFITI #undef RANDOM_LETTER #undef RANDOM_NUMBER diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index 5868ef4b1d..55e75b3992 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -444,7 +444,7 @@ /obj/item/twohanded/shockpaddles/proc/can_defib(mob/living/carbon/H) var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain) - return (!H.suiciding && !(H.has_trait(TRAIT_NOCLONE)) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain) + return (!H.suiciding && !(HAS_TRAIT(H, TRAIT_NOCLONE)) && !H.hellbound && ((world.time - H.timeofdeath) < tlimit) && (H.getBruteLoss() < 180) && (H.getFireLoss() < 180) && H.getorgan(/obj/item/organ/heart) && BR && !BR.damaged_brain) /obj/item/twohanded/shockpaddles/proc/shock_touching(dmg, mob/H) if(req_defib) @@ -585,7 +585,7 @@ shock_touching(30, H) var/failed - if (H.suiciding || (H.has_trait(TRAIT_NOCLONE))) + if (H.suiciding || (HAS_TRAIT(H, TRAIT_NOCLONE))) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Recovery of patient impossible. Further attempts futile." else if (H.hellbound) failed = "[req_defib ? "[defib]" : "[src]"] buzzes: Resuscitation failed - Patient's soul appears to be on another plane of existence. Further attempts futile." @@ -713,12 +713,12 @@ req_defib = FALSE /////////////////////////////////////////// -/////////Dedibrillators Disks////////////// +/////////Defibrillator Disks////////////// /////////////////////////////////////////// /obj/item/disk/medical name = "Defibrillator Upgrade Disk" - desc = "A blank defibrillator disk..." + desc = "A blank upgrade disk, made for a defibrillator" icon = 'modular_citadel/icons/obj/defib_disks.dmi' icon_state = "upgrade_disk" item_state = "heal_disk" @@ -726,25 +726,25 @@ /obj/item/disk/medical/defib_heal name = "Defibrillator Healing Disk" - desc = "A disk alowing for grater amounts of healing" + desc = "An upgrade which increases the healing power of the defibrillator" icon_state = "heal_disk" materials = list(MAT_METAL=16000, MAT_GLASS = 18000, MAT_GOLD = 6000, MAT_SILVER = 6000) /obj/item/disk/medical/defib_shock name = "Defibrillator Anti-Shock Disk" - desc = "A disk that helps agains shocking anyone, other then the intented target" + desc = "A safety upgrade that guarantees only the patient will get shocked" icon_state = "zap_disk" materials = list(MAT_METAL=16000, MAT_GLASS = 18000, MAT_GOLD = 6000, MAT_SILVER = 6000) /obj/item/disk/medical/defib_decay name = "Defibrillator Body-Decay Extender Disk" - desc = "A disk that helps defibrillators revive the longer decayed" + desc = "An upgrade allowing the defibrillator to work on more decayed bodies" icon_state = "body_disk" materials = list(MAT_METAL=16000, MAT_GLASS = 18000, MAT_GOLD = 16000, MAT_SILVER = 6000, MAT_TITANIUM = 2000) /obj/item/disk/medical/defib_speed - name = "Defibrllator Pre-Primer Disk" - desc = "A disk that cuts the time charg time in half for defibrillator use" + name = "Defibrillator Fast Charge Disk" + desc = "An upgrade to the defibrillator capacitors, which let it charge faster" icon_state = "fast_disk" materials = list(MAT_METAL=16000, MAT_GLASS = 8000, MAT_GOLD = 26000, MAT_SILVER = 26000) diff --git a/code/game/objects/items/dehy_carp.dm b/code/game/objects/items/dehy_carp.dm index 29f0cf27f9..55d1a2c78a 100644 --- a/code/game/objects/items/dehy_carp.dm +++ b/code/game/objects/items/dehy_carp.dm @@ -19,6 +19,9 @@ else return ..() +/obj/item/toy/plush/carpplushie/dehy_carp/plop(obj/item/toy/plush/Daddy) + return FALSE + /obj/item/toy/plush/carpplushie/dehy_carp/proc/Swell() desc = "It's growing!" visible_message("[src] swells up!") diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 7d3d36c5b2..45baa542d4 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -10,11 +10,20 @@ GLOBAL_LIST_EMPTY(PDAs) #define PDA_SCANNER_HALOGEN 4 #define PDA_SCANNER_GAS 5 #define PDA_SPAM_DELAY 2 MINUTES +#define PDA_STANDARD_OVERLAYS list("pda-r", "blank", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay") + +//pda icon overlays list defines +#define PDA_OVERLAY_ALERT 1 +#define PDA_OVERLAY_SCREEN 2 +#define PDA_OVERLAY_ID 3 +#define PDA_OVERLAY_ITEM 4 +#define PDA_OVERLAY_LIGHT 5 +#define PDA_OVERLAY_PAI 6 /obj/item/pda name = "\improper PDA" desc = "A portable microcomputer by Thinktronic Systems, LTD. Functionality determined by a preprogrammed ROM cartridge." - icon = 'icons/obj/pda.dmi' + icon = 'icons/obj/pda_alt.dmi' icon_state = "pda" item_state = "electronic" lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' @@ -31,7 +40,8 @@ GLOBAL_LIST_EMPTY(PDAs) var/default_cartridge = 0 // Access level defined by cartridge var/obj/item/cartridge/cartridge = null //current cartridge var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge. - var/icon_alert = "pda-r" //Icon to be overlayed for message alerts. Taken from the pda icon file. + var/list/overlays_icons = list('icons/obj/pda_alt.dmi' = list("pda-r", "screen_default", "id_overlay", "insert_overlay", "light_overlay", "pai_overlay")) + var/current_overlays = PDA_STANDARD_OVERLAYS var/font_index = 0 //This int tells DM which font is currently selected and lets DM know when the last font has been selected so that it can cycle back to the first font when "toggle font" is pressed again. var/font_mode = "font-family:monospace;" //The currently selected font. var/background_color = "#808000" //The currently selected background color. @@ -58,7 +68,6 @@ GLOBAL_LIST_EMPTY(PDAs) var/last_everyone //No text for everyone spamming var/last_noise //Also no honk spamming that's bad too var/ttone = "beep" //The ringtone! - var/lock_code = "" // Lockcode to unlock uplink var/honkamt = 0 //How many honks left when infected with honk.exe var/mimeamt = 0 //How many silence left when infected with mime.exe var/note = "Congratulations, your station has chosen the Thinktronic 5230 Personal Data Assistant! To help with navigation, we have provided the following definitions. North: Fore. South: Aft. West: Port. East: Starboard. Quarter is either side of aft." //Current note in the notepad function @@ -78,7 +87,9 @@ GLOBAL_LIST_EMPTY(PDAs) var/list/contained_item = list(/obj/item/pen, /obj/item/toy/crayon, /obj/item/lipstick, /obj/item/flashlight/pen, /obj/item/clothing/mask/cigarette) var/obj/item/inserted_item //Used for pen, crayon, and lipstick insertion or removal. Same as above. - var/overlays_x_offset = 0 //x offset to use for certain overlays + var/list/overlays_offsets // offsets to use for certain overlays + var/overlays_x_offset = 0 + var/overlays_y_offset = 0 var/underline_flag = TRUE //flag for underline @@ -91,15 +102,13 @@ GLOBAL_LIST_EMPTY(PDAs) return BRUTELOSS /obj/item/pda/examine(mob/user) - ..() - if(!id && !inserted_item) - return - - if(id) - to_chat(user, "Alt-click to remove the id.") - + . = ..() + var/dat = id ? "Alt-click to remove the id." : "" if(inserted_item && (!isturf(loc))) - to_chat(user, "Ctrl-click to remove [inserted_item].") + dat += "\nCtrl-click to remove [inserted_item]." + if(LAZYLEN(GLOB.pda_reskins)) + dat += "\nCtrl-shift-click it to reskin it." + to_chat(user, dat) /obj/item/pda/Initialize() . = ..() @@ -113,30 +122,71 @@ GLOBAL_LIST_EMPTY(PDAs) inserted_item = new inserted_item(src) else inserted_item = new /obj/item/pen(src) - update_icon() + update_icon(FALSE, TRUE) + +/obj/item/pda/CtrlShiftClick(mob/living/user) + . = ..() + if(GLOB.pda_reskins && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY)) + reskin_obj(user) + +/obj/item/pda/reskin_obj(mob/M) + if(!LAZYLEN(GLOB.pda_reskins)) + return + var/dat = "Reskin options for [name]:" + for(var/V in GLOB.pda_reskins) + var/output = icon2html(GLOB.pda_reskins[V], M, icon_state) + dat += "\n[V]: [output]" + to_chat(M, dat) + + var/choice = input(M, "Choose the a reskin for [src]","Reskin Object") as null|anything in GLOB.pda_reskins + var/new_icon = GLOB.pda_reskins[choice] + if(QDELETED(src) || isnull(new_icon) || new_icon == icon || M.incapacitated() || !in_range(M,src)) + return + icon = new_icon + update_icon(FALSE, TRUE) + to_chat(M, "[src] is now skinned as '[choice]'.") + +/obj/item/pda/proc/set_new_overlays() + if(!overlays_offsets || !(icon in overlays_offsets)) + overlays_x_offset = 0 + overlays_y_offset = 0 + else + var/list/new_offsets = overlays_offsets[icon] + if(new_offsets) + overlays_x_offset = new_offsets[1] + overlays_y_offset = new_offsets[2] + if(!(icon in overlays_icons)) + current_overlays = PDA_STANDARD_OVERLAYS + return + current_overlays = overlays_icons[icon] /obj/item/pda/equipped(mob/user, slot) . = ..() - if(!equipped) - if(user.client) - background_color = user.client.prefs.pda_color - switch(user.client.prefs.pda_style) - if(MONO) - font_index = MODE_MONO - font_mode = FONT_MONO - if(SHARE) - font_index = MODE_SHARE - font_mode = FONT_SHARE - if(ORBITRON) - font_index = MODE_ORBITRON - font_mode = FONT_ORBITRON - if(VT) - font_index = MODE_VT - font_mode = FONT_VT - else - font_index = MODE_MONO - font_mode = FONT_MONO - equipped = TRUE + if(equipped) + return + if(user.client) + background_color = user.client.prefs.pda_color + switch(user.client.prefs.pda_style) + if(MONO) + font_index = MODE_MONO + font_mode = FONT_MONO + if(SHARE) + font_index = MODE_SHARE + font_mode = FONT_SHARE + if(ORBITRON) + font_index = MODE_ORBITRON + font_mode = FONT_ORBITRON + if(VT) + font_index = MODE_VT + font_mode = FONT_VT + else + font_index = MODE_MONO + font_mode = FONT_MONO + var/pref_skin = GLOB.pda_reskins[user.client.prefs.pda_skin] + if(icon != pref_skin) + icon = pref_skin + update_icon(FALSE, TRUE) + equipped = TRUE /obj/item/pda/proc/update_label() name = "PDA-[owner] ([ownjob])" //Name generalisation @@ -150,33 +200,36 @@ GLOBAL_LIST_EMPTY(PDAs) /obj/item/pda/GetID() return id -/obj/item/pda/update_icon() +/obj/item/pda/update_icon(alert = FALSE, new_overlays = FALSE) + if(new_overlays) + set_new_overlays() cut_overlays() + add_overlay(alert ? current_overlays[PDA_OVERLAY_ALERT] : current_overlays[PDA_OVERLAY_SCREEN]) var/mutable_appearance/overlay = new() overlay.pixel_x = overlays_x_offset if(id) - overlay.icon_state = "id_overlay" + overlay.icon_state = current_overlays[PDA_OVERLAY_ID] add_overlay(new /mutable_appearance(overlay)) if(inserted_item) - overlay.icon_state = "insert_overlay" + overlay.icon_state = current_overlays[PDA_OVERLAY_ITEM] add_overlay(new /mutable_appearance(overlay)) if(fon) - overlay.icon_state = "light_overlay" + overlay.icon_state = current_overlays[PDA_OVERLAY_LIGHT] add_overlay(new /mutable_appearance(overlay)) if(pai) - if(pai.pai) - overlay.icon_state = "pai_overlay" - add_overlay(new /mutable_appearance(overlay)) - else - overlay.icon_state = "pai_off_overlay" - add_overlay(new /mutable_appearance(overlay)) + overlay.icon_state = "[current_overlays[PDA_OVERLAY_PAI]][pai.pai ? "" : "_off"]" + add_overlay(new /mutable_appearance(overlay)) -/obj/item/pda/MouseDrop(obj/over_object, src_location, over_location) +/obj/item/pda/MouseDrop(mob/over, src_location, over_location) var/mob/M = usr - if((!istype(over_object, /obj/screen)) && usr.canUseTopic(src)) + if((M == over) && usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) return attack_self(M) return ..() +/obj/item/pda/attack_self_tk(mob/user) + to_chat(user, "The PDA's capacitive touch screen doesn't seem to respond!") + return + /obj/item/pda/interact(mob/user) if(!user.IsAdvancedToolUser()) to_chat(user, "You don't have the dexterity to do this!") @@ -358,9 +411,9 @@ GLOBAL_LIST_EMPTY(PDAs) if (total_moles) for(var/id in env_gases) - var/gas_level = env_gases[id][MOLES]/total_moles + var/gas_level = env_gases[id]/total_moles if(gas_level > 0) - dat += "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_level*100, 0.01)]%It really is that easy! Good luck! - +